diff --git a/.gitignore b/.gitignore index af08f086b..525c048bd 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ obj *.pidb *.suo *.vsp +*.ipch /Setup/Accord.Setup.dll /Setup/Accord.Setup.pdb @@ -20,6 +21,8 @@ obj /Docs /Unit Tests/Accord.Tests.Math.Cpp/Debug /Unit Tests/Accord.Tests.Math.Cpp/Release +/Unit Tests/packages + /Sources/Debug /Sources/Release diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..996755e0b --- /dev/null +++ b/.travis.yml @@ -0,0 +1,8 @@ +language: csharp +solution: Sources/Accord.NET.Mono.sln +install: + - nuget restore Sources/Accord.NET.Mono.sln +script: + - ./Build.sh framework + - ./Build.sh samples + - ./Tests.sh \ No newline at end of file diff --git a/Setup/Compile.cmd b/Build.cmd similarity index 59% rename from Setup/Compile.cmd rename to Build.cmd index 4e5f9972d..9d0ee874b 100644 --- a/Setup/Compile.cmd +++ b/Build.cmd @@ -14,20 +14,20 @@ set DEVENV="C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\deve del /q "bin\*.log" echo. - +echo. echo - Building Debug configuration... -%DEVENV% ..\Sources\Accord.NET.sln /Rebuild Debug /out "bin\Build.Debug.log" - +%DEVENV% Sources\Accord.NET.sln /Rebuild Debug /out "bin\Build.Debug.log" +echo. echo - Building NET35 configuration... -%DEVENV% ..\Sources\Accord.NET.sln /Rebuild NET35 /out "bin\Build.NET35.log" - +%DEVENV% Sources\Accord.NET.sln /Rebuild NET35 /out "bin\Build.NET35.log" +echo. echo - Building NET40 configuration... -%DEVENV% ..\Sources\Accord.NET.sln /Rebuild NET40 /out "bin\Build.NET40.log" - +%DEVENV% Sources\Accord.NET.sln /Rebuild NET40 /out "bin\Build.NET40.log" +echo. echo - Building NET45 configuration... -%DEVENV% ..\Sources\Accord.NET.sln /Rebuild NET45 /out "bin\Build.NET45.log" - +%DEVENV% Sources\Accord.NET.sln /Rebuild NET45 /out "bin\Build.NET45.log" +echo. echo - Building samples... -%DEVENV% ..\Samples\Samples.sln /Rebuild Release /out "bin\Build.Samples.log" - +%DEVENV% Samples\Samples.sln /Rebuild Release /out "bin\Build.Samples.log" +echo. timeout /T 5 \ No newline at end of file diff --git a/Build.sh b/Build.sh new file mode 100755 index 0000000000..353cf9b1a --- /dev/null +++ b/Build.sh @@ -0,0 +1,26 @@ +#!/bin/bash +########### + +echo " " +echo "Accord.NET Framework all projects configurations builder " +echo "=========================================================" +echo " " +echo "This Linux bash script will use Mono's xbuild tool to " +echo "compile the Debug and Release versions of the framework. " +echo " " + + + +if [ $# -eq 0 ] || [ "$1" == "framework" ]; then + echo "" + echo " - Building NET40 configuration..." + echo "" + xbuild /p:Configuration=NET40 Sources/Accord.NET.Mono.sln +fi + +if [ $# -eq 0 ] || [ "$1" == "samples" ]; then + echo "" + echo " - Building samples..." + echo "" + xbuild /p:Configuration=Mono /p:Platform=x86 Samples/Samples.sln +fi diff --git a/Contributors.txt b/Contributors.txt index f613d41e1..3e360ef83 100644 --- a/Contributors.txt +++ b/Contributors.txt @@ -7,7 +7,7 @@ decided to share their work and contribute to its development. The space below enlists a few of those people who either agreed to help or actively participated on its development: - + - Anders Gustafsson - Antonino Porcino @@ -25,3 +25,27 @@ - Mikkel Porse Rasmussen - Peter Sergio Larsen - Remy Disp + + +In May 2015, the project has been merged with the AForge.NET codebase, +incorporating the work of even more contributors. In a true spirit of +community, notorious previous contributors are also listed below: + + + - Andrew Kirillov (the project creator, with the best ideas) + - Fbio Caversan + - Alejandro Pirola + - Cezary Wagner + - Dale McCoy + - Fabio Caversan + - Frank Nagl + - Israel Lot + - Jeremy Noring + - Joan Charmant + - Joris Geurts + - Krzysztof Blacha + - Kyle Parrigan + - Markus Falkensteiner + - Mladen Prajdic + - Volodymyr Goncharov + - Yves Vander Haeghen \ No newline at end of file diff --git a/Copyright.txt b/Copyright.txt index 65575f447..1cb5e110d 100644 --- a/Copyright.txt +++ b/Copyright.txt @@ -1,6 +1,6 @@ The Accord.NET Framework -Copyright (c) 2009-2015, César Roberto de Souza +Copyright (c) 2009-2015, Accord.NET Authors 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 @@ -31,9 +31,10 @@ Creative Commons Attribution/Share-Alike License. All referenced sections includ original article page. If you think you have found something which has not been properly linked, please let me know so it can be corrected. -Overall framework architecture and style was greatly inspired by AForge.NET. The AForge.NET -Framework is a copyrighted work by Andrew Kirillov. This framework (Accord.NET) is in no way -affiliated with AForge.NET, its authors or contributors. +Overall framework architecture and style was greatly inspired by AForge.NET. In May 2015, this project +has been merged with the AForge.NET framework since public support for AForge.NET has ended. The original +AForge.NET Framework is a copyrighted work by Andrew Kirillov, altough developed and shared under the same +LGPL license. diff --git a/Externals/AForge.NET/AForge.Controls.dll b/Externals/AForge.NET/AForge.Controls.dll deleted file mode 100644 index 93310dd2d..0000000000 Binary files a/Externals/AForge.NET/AForge.Controls.dll and /dev/null differ diff --git a/Externals/AForge.NET/AForge.Controls.xml b/Externals/AForge.NET/AForge.Controls.xml deleted file mode 100644 index b2b53693f..0000000000 --- a/Externals/AForge.NET/AForge.Controls.xml +++ /dev/null @@ -1,1447 +0,0 @@ - - - - AForge.Controls - - - - - Picture box control for displaying an image. - - - This control is inherited from System.Windows.Forms.PictureBox and is - aimed to resolve one of its issues - inability to display images with high color depth, - like 16 bpp grayscale, 48 bpp and 64 bpp color images. .NET framework does not handle - 16 bpp grayscale images at all, throwing exception when user tries to display them. Color - images with 48 bpp and 64 bpp are "kind of" supported, but only maximum of 13 bits for each - color plane are allowed. Therefore this control is created, which allows to display as - 16 bpp grayscale images, as 48 bpp and 64 bpp color images. - - To display high color depth images, the control does internal conversion of them - to lower color depth images - 8 bpp grayscale, 24 bpp and 32 bpp color images respectively. In - the case source image already has low color depth, it is displayed without any conversions. - - - - - - - Gets or sets the image that the PictureBox displays. - - - The property is used to set image to be displayed or to get currently - displayed image. - - In the case if source image has high color depth, like 16 bpp grayscale image, - 48 bpp or 64 bpp color image, it is converted to lower color depth before displaying - - to 8 bpp grayscale, 24 bpp or 32 bpp color image respectively. - - During color conversion the original source image is kept unmodified, but internal - converted copy is created. The property always returns original source image. - - - - - - Color slider control. - - - The control represent a color slider, which allows selecting - one or two values in the [0, 255] range. The application of this control - includes mostly areas of image processing and computer vision, where it is required - to select color threshold or ranges for different type of color filtering. - - Depending on the control's , it has different look and may suite - different tasks. See documentation to for information - about available type and possible control's looks. - - - - - - Initializes a new instance of the class. - - - - - - Dispose the object. - - - Specifies if disposing was invoked by user's code. - - - - - An event, to notify about changes of or properties. - - - The event is fired after changes of or property, - which is caused by user dragging the corresponding control’s arrow (slider). - - - - - - Start color for gradient filling. - - - See documentation to enumeration for information about - the usage of this property. - - - - - End color for gradient filling. - - - See documentation to enumeration for information about - the usage of this property. - - - - - Color to fill control's background in filtered zones. - - - See documentation to enumeration for information about - the usage of this property. - - - - - Specifies control's type. - - - See documentation to enumeration for information about - the usage of this property. - - - - - Minimum selected value, [0, 255]. - - - - - - Maximum selected value, [0, 255]. - - - - - - Single or Double arrow slider control. - - - The property specifies if the slider has one or two selection arrows (sliders). - - The single arrow allows only to specify one value, which is set by - property. The single arrow slider is useful for applications, where it is required to select - color threshold, for example. - - The double arrow allows to specify two values, which are set by - and properties. The double arrow slider is useful for applications, where it is - required to select filtering color range, for example. - - - - - - Enumeration of color slider types. - - - - The slider's type supposes the control's - background filled with gradient startting from color and ending - with color. The color does not have - impact on control's look. - - This type allows as one-arrow, as two-arrows control. - - Sample control's look: - - - The slider's type supposes the control's - background filled with gradient startting from color and ending - with color. In addition the areas, which are outside of - [, ] range, are filled with color. - - This type allows only two-arrows control. - - Sample control's look: - - - The slider's type supposes the - control's background filled with gradient startting from color - and ending with color. In addition the area, which is inside of - [, ] range, is filled with color. - - This type allows only two-arrows control. - - Sample control's look: - - - The slider's type supposes filling areas - outside of [, ] range with and - inside the range with . The color does not - have impact on control's look. - - This type allows as one-arrow, as two-arrows control. - - Sample control's look: - - - - - - - Gradient color slider type. - - - - - Inner gradient color slider type. - - - - - Outer gradient color slider type. - - - - - Threshold color slider type. - - - - - Video source player control. - - - The control is aimed to play video sources, which implement - interface. To start playing a video - the property should be initialized first and then - method should be called. In the case if user needs to - perform some sort of image processing with video frames before they are displayed, - the event may be used. - - Sample usage: - - // set new frame event handler if we need processing of new frames - playerControl.NewFrame += new VideoSourcePlayer.NewFrameHandler( this.playerControl_NewFrame ); - - // create video source - IVideoSource videoSource = new ... - // start playing it - playerControl.VideoSource = videoSource; - playerControl.Start( ); - ... - - // new frame event handler - private void playerControl_NewFrame( object sender, ref Bitmap image ) - { - // process new frame somehow ... - - // Note: it may be even changed, so the control will display the result - // of image processing done here - } - - - - - - - Initializes a new instance of the class. - - - - - Start video source and displaying its frames. - - - - - Stop video source. - - - The method stops video source by calling its - method, which abourts internal video source's thread. Use and - for more polite video source stopping, which gives a chance for - video source to perform proper shut down and clean up. - - - - - - Signal video source to stop. - - - Use method to wait until video source - stops. - - - - - Wait for video source has stopped. - - - Waits for video source stopping after it was signaled to stop using - method. If was not called, then - it will be called automatically. - - - - - Get clone of current video frame displayed by the control. - - - Returns copy of the video frame, which is currently displayed - by the control - the last video frame received from video source. If the - control did not receive any video frames yet, then the method returns - . - - - - - Required designer variable. - - - - - Clean up any resources being used. - - true if managed resources should be disposed; otherwise, false. - - - - Required method for Designer support - do not modify - the contents of this method with the code editor. - - - - - Auto size control or not. - - - The property specifies if the control should be autosized or not. - If the property is set to , then the control will change its size according to - video size and control will change its position automatically to be in the center - of parent's control. - - Setting the property to has no effect if - property is set to . - - - - - - Control's border color. - - - Specifies color of the border drawn around video frame. - - - - - Video source to play. - - - The property sets the video source to play. After setting the property the - method should be used to start playing the video source. - - Trying to change video source while currently set video source is still playing - will generate an exception. Use property to check if current video - source is still playing or or and - methods to stop current video source. - - - Video source can not be changed while current video source is still running. - - - - - State of the current video source. - - - Current state of the current video source object - running or not. - - - - - New frame event. - - - The event is fired on each new frame received from video source. The - event is fired right after receiving and before displaying, what gives user a chance to - perform some image processing on the new frame and/or update it. - - Users should not keep references of the passed to the event handler image. - If user needs to keep the image, it should be cloned, since the original image will be disposed - by the control when it is required. - - - - - - Playing finished event. - - - The event is fired when/if video playing finishes. The reason of video - stopping is provided as an argument to the event handler. - - - - - Delegate to notify about new frame. - - - Event sender. - New frame. - - - - - Slider control. - - - - The control represents a slider, which can be dragged in the [-1, 1] range. - Default position of the slider is set 0, which corresponds to center of the control.
- -
-
- -
- - - Initializes a new instance of the class. - - - - - Required designer variable. - - - - - Clean up any resources being used. - - true if managed resources should be disposed; otherwise, false. - - - - Required method for Designer support - do not modify - the contents of this method with the code editor. - - - - - Determines behaviour of manipulator, when mouse button is released. - - - - The property controls behaviour of manipulator on releasing mouse button. If - the property is set to , then position of manipulator is reset - to 0, when mouse button is released. Otherwise manipulator stays on the place, - where it was left. - - Default value is set to . - - - - - - Color used for drawing borders. - - - - Default value is set to . - - - - - - Background color used for filling area corresponding to positive values. - - - - Default value is set to . - - - - - - Background color used for filling area corresponding to negative values. - - - - Default value is set to . - - - - - - Color used for filling manipulator. - - - - Default value is set to . - - - - - - Defines if control has horizontal or vertical look. - - - - Default value is set to . - - - - - - Current manipulator's position, [-1, 1]. - - - The property equals to current manipulator's position. - - - - - - Event used for notification about manipulator's position changes. - - - - - Delegate used for notification about manipulator's position changes. - - - Event sender - object sending the event. - Current position of manipulator. - - - - - The class provides simple API for enumerating available joysticks and checking their - current status. - - - The class provides simple access to joysticks (game controllers) through using - Win32 API, which allows to enumerate available devices and query their status (state of all buttons, - axes, etc). - - Sample usage: - - // enumerate available devices - List<Joystick.DeviceInfo> devices = Joystick.GetAvailableDevices( ); - - foreach ( Joystick.DeviceInfo di in devices ) - { - System.Diagnostics.Debug.WriteLine( - string.Format( "{0} : {1} ({2} axes, {3} buttons)", - di.ID, di.Name, di.Axes, di.Buttons ) ); - } - - - // create new joystick and initialize it - Joystick joystick = new Joystick( 0 ); - // get its current status - Joystick.Status status = joystick.GetCurrentStatus( ); - // check if 1st button is pressed - if ( status.IsButtonPressed( Joystick.Buttons.Button1 ) ) - { - // 1st button is pressed - } - - - - - - - Get list of available joysticks connected to the system. - - - Returns list containing information about available joysticks connected to - the system. - - - - - Initializes a new instance of the class. - - - This constructor does not make initialization of any joystick - device, so method should be used before querying joystick - status or properties. - - - - - Initializes a new instance of the class. - - - Joystick ID to initialize, [0, 15]. - - This constructor initializes joystick with specified ID using - method, so the object becomes ready for querying joystick's - status. - - - - - Initialize joystick with the specified ID. - - - Joystick's ID to initialize, [0, 15]. - - - - Invalid joystick ID was specified. It must be in [0, 15] range. - The requested joystick is not connected to the system. - - - - - Get joystick's status. - - - Returns current status of initialized joystick, which provides information - about current state of all axes, buttons and point of view. - - Before using this method the joystick object needs to be initialized - using method or constructor. - - The requested joystick is not connected to the system. - Joystick was not initialized. - - - - - Information about initialized joystick. - - - The property keeps information about joystick, which was - initialized using method. If no joystick was initialized, - then accessing this property will generate - exception. - - Joystick was not initialized. - - - - - Information about joystick connected to the system. - - - - - - Joystick ID, [0..15]. - - - - - Joystick name. - - - - - Number of joystick axes. - - - - - Number of joystick buttons. - - - - - Class describing current joystick's status. - - - All joystick axes' positions are measured in [-1, 1] range, where - 0 corresponds to center position - axis is not deflected (directed) to any side. - - - - - Check if certain button (or combination of buttons) is pressed. - - - Button to check state of. - - Returns if the specified button is pressed or - otherwise. - - - - - Position of X axis, [-1, 1]. - - - - - Position of Y axis, [-1, 1]. - - - - - Position of Z axis, [-1, 1]. - - - - - Position of R axis - 4th joystick's axes, [-1, 1]. - - - - - Position of U axis - 5th joystick's axes, [-1, 1]. - - - - - Position of V axis - 6th joystick's axes, [-1, 1]. - - - - - Joystick buttons' state. - - - - - Current point of view state, [0, 359]. - - - - - - Flags enumeration of joystick buttons. - - - - - 1st button. - - - - - 2nd button. - - - - - 3rd button. - - - - - 4th button. - - - - - 5th button. - - - - - 6th button. - - - - - 7th button. - - - - - 8th button. - - - - - 9th button. - - - - - 10th button. - - - - - 11th button. - - - - - 12th button. - - - - - 13th button. - - - - - 14th button. - - - - - 15th button. - - - - - 16th button. - - - - - Hue picker control. - - - The control allows selecting hue value (or range) from HSL color space. Hue values - are integer values in the [0, 359] range. - - If control's type is set to , then it allows selecting single - hue value and looks like this:
- -
- - If control's type is set to , then it allows selecting range - of hue values and looks like this:
- -
-
- -
- - - Initializes a new instance of the class. - - - - - - Dispose the object. - - - Specifies if disposing was invoked by user's code. - - - - - Paint the controls. - - - Paint event arguments. - - - - - An event, to notify about changes of or properties. - - - The event is fired after changes of its , or - properties, which is caused by user dragging the corresponding hue picker's bullets. - - - - - - Selected value of the hue picker control in mode. - - - - - Minimum selected value of the hue picker control in mode. - - - - - Maximum selected value of the hue picker control in mode. - - - - - Current type of the hue picker control. - - - See enumeration for description of the available types. - - - - - Enumeration of hue picker types. - - - - The type provides single bullet to drag, which allows - selecting single hue value. The value is accessible through property. - - The type provides two bullets to drag, which correspond - to minimum and maximum values of the hue range. These values are accessible through - and properties. - - - - - - Selecting single hue value. - - - - - Selecting hue values range. - - - - - Manipulator control. - - - - The manipulator control can be used to mimic behaviour of analogue joystick using - regular mouse. By dragging manipulator away from control's centre, it fires - event notifying about its X/Y coordinates (or about R/Theta coordinates in Polar coordinates system). - - - For example, in robotics applications the control can be used to drive robots. If user drags manipulator - further from centre (increasing distance between centre and manipulator), then higher power (speed) should be - set for robot's motors. But dragging it in different directions away from centre should result in changing - robot's direction: straight forward, backward, turning right or left, etc.
- -
- - Another possible application of the control is to control position of some device, etc. - For example, the control could be used with pan-tilt camera - by dragging control away from centre, - the camera may rotate in one of the directions.
- -
-
- -
- - - Clean up any resources being used. - - - true if managed resources should be disposed; otherwise, false. - - - - Required method for Designer support - do not modify - the contents of this method with the code editor. - - - - - Initializes a new instance of the class. - - - - - Determines if the control has square or round look. - - - - The control has a square look if the property is set to , - otherwise it has round look. - - Default value is set to . - - - - - - Determines if horizontal axis should be drawn or not. - - - - Default value is set to . - - - - - - Determines if vertical axis should be drawn or not. - - - - Default value is set to . - - - - - - Determines behaviour of manipulator, when mouse button is released. - - - - The property controls behaviour of manipulator on releasing mouse button. If - the property is set to , then position of manipulator is reset - to (0, 0), when mouse button is released. Otherwise manipulator stays on the place, - where it was left. - - Default value is set to . - - - - - - Color used for drawing borders and axis's. - - - - Default value is set to . - - - - - - Background color used for filling top left quarter of the control. - - - - Default value is set to . - - - - - - Background color used for filling top right quarter of the control. - - - - Default value is set to . - - - - - - Background color used for filling bottom left quarter of the control. - - - - Default value is set to . - - - - - - Background color used for filling bottom right quarter of the control. - - - - Default value is set to . - - - - - - Color used for filling manipulator. - - - - Default value is set to . - - - - - - Current manipulator's position. - - - The property equals to current manipulator's position. Both X and Y values - are in the [-1, 1] range and represented in - Cartesian coordinate system. - - - - - - Event used for notification about manipulator's position changes. - - - - - Class, which summarizes arguments of manipulator's position change event. - - - Properties of this class allow to get: - - X/Y coordinates of manipulator in - Cartesian coordinate system, - where X axis is directed from center of the control to the right and Y axis is directed from - center to the top. Both coordinates are measured in [-1, 1] range. - Theta and R coordinates of manipulator in - Polar coordinate system. - - - - - - - Initializes a new instance of the class. - - - X coordinate of manipulator, [-1, 1]. - Y coordinate of manipulator, [-1, 1]. - - - - - X coordinate of manipulator, [-1, 1]. - - - - - Y coordinate of manipulator, [-1, 1]. - - - - - Theta coordinate of manipulator in Polar coordinate system, [0, 359]. - - - - - R (radius) coordinate of manipulator in Polar coordinate system, [0, 1]. - - - - - Delegate used for notification about manipulator's position changes. - - - Event sender - object sending the event. - Event arguments - current manipulator's position. - - - - - Arguments of histogram events. - - - - - Initializes a new instance of the class. - - - Histogram's index under mouse pointer. - - - - - Initializes a new instance of the class. - - - Min histogram's index in selection. - Max histogram's index in selection. - - - - - Min histogram's index in selection. - - - - - Max histogram's index in selection. - - - - - Histogram's index under mouse pointer. - - - - - Delegate for histogram events handlers. - - - Sender object. - Event arguments. - - - - - Histogram control. - - - The control displays histograms represented with integer arrays, - where each array's element keeps occurrence number of the corresponding element. - - - Sample usage: - - // create array with histogram values - int[] histogramValues = new int[] { 3, 8, 53, 57, 79, 69, ... }; - // set values to histogram control - histogram.Values = histogramValues; - - - Sample control's look: - - - - - - - Initializes a new instance of the class. - - - - - - Dispose the object. - - - Indicates if disposing was initiated manually. - - - - - Paint the control. - - - Data for Paint event. - - - - - Histogram's color. - - - - - - Allow mouse selection or not. - - - In the case if mouse selection is allowed, the control will - fire and events - and provide information about the selection. - - - - - Logarithmic view or not. - - - In the case if logarihmic view is selected, then the control - will display base 10 logarithm of values. - - By default the property is set to false - none logarithmic view. - - - - - Vertical view or not. - - - The property determines if histogram should be displayed vertically or - not (horizontally). - - By default the property is set to false - horizontal view. - - - - - Histogram values. - - - Non-negative histogram values. - - Histogram values should be non-negative. - - - - - Mouse position changed event. - - - The event is fired only if the property is set - to true. The passed to event handler class is initialized - with property only, which is histogram value's - index pointed by mouse. - - - - - Mouse selection changed event. - - - The event is fired only if the property is set - to true. The passed to event handler class is initialized - with and properties - only, which represent selection range - min and max indexes. - - - - - Chart control. - - - The chart control allows to display multiple charts at time - of different types: dots, lines, connected dots. - - Sample usage: - - // create data series array - double[,] testValues = new double[10, 2]; - // fill data series - for ( int i = 0; i < 10; i++ ) - { - testValues[i, 0] = i; // X values - testValues[i, 1] = Math.Sin( i / 18.0 * Math.PI ); // Y values - } - // add new data series to the chart - chart.AddDataSeries( "Test", Color.DarkGreen, Chart.SeriesType.ConnectedDots, 3 ); - // set X range to display - chart.RangeX = new AForge.Range( 0, 9 ); - // update the chart - chart.UpdateDataSeries( "Test", testValues ); - - - - - - - Required designer variable. - - - - - Initializes a new instance of the class. - - - - - - Dispose the object. - - - - - Required method for Designer support - do not modify - the contents of this method with the code editor. - - - - - Add data series to the chart. - - - Data series name. - Data series color. - Data series type. - Width (depends on the data series type, see remarks). - - Adds new empty data series to the collection of data series. To update this - series the method should be used. - - The meaning of the width parameter depends on the data series type: - - Line - width of the line; - Dots - size of dots (rectangular dots with specified width and the same height); - Connected dots - size of dots (dots are connected with one pixel width line). - - - - - - - - Add data series to the chart. - - - Data series name. - Data series color. - Data series type. - Width (depends on the data series type, see remarks). - Specifies if should be updated. - - Adds new empty data series to the collection of data series. - - The updateYRange parameter specifies if the data series may affect displayable - Y range. If the value is set to false, then displayable Y range is not updated, but used the - range, which was specified by user (see property). In the case if the - value is set to true, the displayable Y range is recalculated to fully fit the new data - series. - - - - - - Update data series on the chart. - - - Data series name to update. - Data series values. - - - - - Remove data series from the chart. - - - Data series name to remove. - - - - - Remove all data series from the chart. - - - - - Update Y range. - - - - - Chart's X range. - - - The value sets the X range of data to be displayed on the chart. - - - - - Chart's Y range. - - - The value sets the Y range of data to be displayed on the chart. - - - - - Chart series type enumeration. - - - - - Line style. - - - - - Dots style. - - - - - Connected dots style. - - -
-
diff --git a/Externals/AForge.NET/AForge.DebuggerVisualizers (2010).dll b/Externals/AForge.NET/AForge.DebuggerVisualizers (2010).dll deleted file mode 100644 index 430116ac2..0000000000 Binary files a/Externals/AForge.NET/AForge.DebuggerVisualizers (2010).dll and /dev/null differ diff --git a/Externals/AForge.NET/AForge.Fuzzy.dll b/Externals/AForge.NET/AForge.Fuzzy.dll deleted file mode 100644 index 21d37dc0d..0000000000 Binary files a/Externals/AForge.NET/AForge.Fuzzy.dll and /dev/null differ diff --git a/Externals/AForge.NET/AForge.Fuzzy.xml b/Externals/AForge.NET/AForge.Fuzzy.xml deleted file mode 100644 index 6c62a53e0..0000000000 --- a/Externals/AForge.NET/AForge.Fuzzy.xml +++ /dev/null @@ -1,1559 +0,0 @@ - - - - AForge.Fuzzy - - - - - The class represents a fuzzy rulebase, a set of fuzzy rules used in a Fuzzy Inference System. - - - - - - Initializes a new instance of the class. - - - - - - Adds a fuzzy rule to the database. - - - A fuzzy to add to the database. - - The fuzzy rule was not initialized. - The fuzzy rule name already exists in the rulebase. - - - - - Removes all the fuzzy rules of the database. - - - - - - Returns an existing fuzzy rule from the rulebase. - - - Name of the fuzzy to retrieve. - - Reference to named . - - The rule indicated in ruleName was not found in the rulebase. - - - - - Gets all the rules of the rulebase. - - - An array with all the rulebase rules. - - - - - Interface which specifies set of methods required to be implemented by all defuzzification methods - that can be used in Fuzzy Inference Systems. - - - In many applications, a Fuzzy Inference System is used to perform linguistic computation, - but at the end of the inference process, a numerical value is needed. It does not mean that the system - needs precision, but simply that a numerical value is required, most of the times because it will be used to - control another system that needs the number. To obtain this numer, a defuzzification method is performed. - - Several deffuzification methods were proposed, and they can be created as classes that - implements this interface. - - - - - Defuzzification method to obtain the numerical representation of a fuzzy output. - - - A containing the output of - several rules of a Fuzzy Inference System. - A operator to be used when constraining - the label to the firing strength. - - The numerical representation of the fuzzy output. - - - - - NOT operator, used to calculate the complement of a fuzzy set. - - - The NOT operator definition is (1 - m) for all the values of membership m of the fuzzy set. - - Sample usage: - - // creating a fuzzy sets to represent Cool (Temperature) - TrapezoidalFunction function1 = new TrapezoidalFunction( 13, 18, 23, 28 ); - FuzzySet fsCool = new FuzzySet( "Cool", function1 ); - - // getting membership - float m1 = fsCool.GetMembership( 15 ); - - // computing the membership of "NOT Cool" - NotOperator NOT = new NotOperator( ); - float result = NOT.Evaluate( m1 ); - - // show result - Console.WriteLine( result ); - - - - - - - - - Interface with the common methods of Fuzzy Unary Operator. - - - All fuzzy operators that act as a Unary Operator (NOT, VERY, LITTLE) must implement this interface. - - - - - - Calculates the numerical result of a Unary operation applied to one - fuzzy membership value. - - - A fuzzy membership value, [0..1]. - - The numerical result of the operation applied to . - - - - - Calculates the numerical result of the NOT operation applied to - a fuzzy membership value. - - - A fuzzy membership value, [0..1]. - - The numerical result of the unary operation NOT applied to . - - - - - Maximum CoNorm, used to calculate the linguistic value of a OR operation. - - - The maximum CoNorm uses a maximum operator to compute the OR - among two fuzzy memberships. - - Sample usage: - - // creating 2 fuzzy sets to represent Cool (Temperature) and Near (Distance) - TrapezoidalFunction function1 = new TrapezoidalFunction( 13, 18, 23, 28 ); - FuzzySet fsCool = new FuzzySet( "Cool", function1 ); - TrapezoidalFunction function2 = new TrapezoidalFunction( 23, 28, 33, 38 ); - FuzzySet fsNear = new FuzzySet( "Near", function2 ); - - // getting memberships - float m1 = fsCool.GetMembership( 15 ); - float m2 = fsNear.GetMembership( 35 ); - - // computing the membership of "Cool OR Near" - MaximumCoNorm OR = new MaximumCoNorm( ); - float result = OR.Evaluate( m1, m2 ); - - // show result - Console.WriteLine( result ); - - - - - - - - - Interface with the common methods of a Fuzzy CoNorm. - - - All fuzzy operators that act as a CoNorm must implement this interface. - - - - - - Calculates the numerical result of a CoNorm (OR) operation applied to - two fuzzy membership values. - - - A fuzzy membership value, [0..1]. - A fuzzy membership value, [0..1]. - - The numerical result the operation OR applied to - and . - - - - - Calculates the numerical result of the OR operation applied to - two fuzzy membership values. - - - A fuzzy membership value, [0..1]. - A fuzzy membership value, [0..1]. - - The numerical result of the binary operation OR applied to - and . - - - - - Membership function used in fuzzy singletons: fuzzy sets that have just one point with membership value 1. - - - Sometimes it is needed to represent crisp (classical) number in the fuzzy domain. Several approaches - can be used, like adding some uncertain (fuzziness) in the original number (the number one, for instance, can be seen as a - with -0.5, 1.0 and 0.5 parameters). Another approach is to declare fuzzy singletons: fuzzy sets with only one point returning a none zero membership. - - While trapezoidal and half trapezoidal are classic functions used in fuzzy functions, this class supports any function - or approximation that can be represented as a sequence of lines. - - Sample usage: - - // creating the instance - SingletonFunction membershipFunction = new SingletonFunction( 10 ); - // getting membership for several points - for ( int i = 0; i < 20; i++ ) - Console.WriteLine( membershipFunction.GetMembership( i ) ); - - - - - - - Interface which specifies set of methods required to be implemented by all membership - functions. - - - All membership functions must implement this interface, which is used by - class to calculate value's membership to a particular fuzzy set. - - - - - - Calculate membership of a given value to the fuzzy set. - - - Value which membership will to be calculated. - - Degree of membership [0..1] of the value to the fuzzy set. - - - - - The leftmost x value of the membership function. - - - - - The rightmost x value of the membership function. - - - - - The unique point where the membership value is 1. - - - - - Initializes a new instance of the class. - - - Support is the only value of x where the membership function is 1. - - - - - Calculate membership of a given value to the singleton function. - - - Value which membership will to be calculated. - - Degree of membership {0,1} since singletons do not admit memberships different from 0 and 1. - - - - - The leftmost x value of the membership function, the same value of the support. - - - - - - The rightmost x value of the membership function, the same value of the support. - - - - - - This class represents a Fuzzy Inference System. - - - A Fuzzy Inference System is a model capable of executing fuzzy computing. - It is mainly composed by a with the linguistic variables - (see ) and a - with the fuzzy rules (see ) that represent the behavior of the system. - The typical operation of a Fuzzy Inference System is: - - Get the numeric inputs; - Use the with the linguistic variables - (see ) to obtain linguistic meaning for each - numerical input; - Verify which rules (see ) of the are - activated by the input; - Combine the consequent of the activated rules to obtain a ; - Use some defuzzifier (see ) to obtain a numerical output. - - - - The following sample usage is a Fuzzy Inference System that controls an - auto guided vehicle avoing frontal collisions: - - // linguistic labels (fuzzy sets) that compose the distances - FuzzySet fsNear = new FuzzySet( "Near", - new TrapezoidalFunction( 15, 50, TrapezoidalFunction.EdgeType.Right ) ); - FuzzySet fsMedium = new FuzzySet( "Medium", - new TrapezoidalFunction( 15, 50, 60, 100 ) ); - FuzzySet fsFar = new FuzzySet( "Far", - new TrapezoidalFunction( 60, 100, TrapezoidalFunction.EdgeType.Left ) ); - - // front distance (input) - LinguisticVariable lvFront = new LinguisticVariable( "FrontalDistance", 0, 120 ); - lvFront.AddLabel( fsNear ); - lvFront.AddLabel( fsMedium ); - lvFront.AddLabel( fsFar ); - - // linguistic labels (fuzzy sets) that compose the angle - FuzzySet fsZero = new FuzzySet( "Zero", - new TrapezoidalFunction( -10, 5, 5, 10 ) ); - FuzzySet fsLP = new FuzzySet( "LittlePositive", - new TrapezoidalFunction( 5, 10, 20, 25 ) ); - FuzzySet fsP = new FuzzySet( "Positive", - new TrapezoidalFunction( 20, 25, 35, 40 ) ); - FuzzySet fsVP = new FuzzySet( "VeryPositive", - new TrapezoidalFunction( 35, 40, TrapezoidalFunction.EdgeType.Left ) ); - - // angle - LinguisticVariable lvAngle = new LinguisticVariable( "Angle", -10, 50 ); - lvAngle.AddLabel( fsZero ); - lvAngle.AddLabel( fsLP ); - lvAngle.AddLabel( fsP ); - lvAngle.AddLabel( fsVP ); - - // the database - Database fuzzyDB = new Database( ); - fuzzyDB.AddVariable( lvFront ); - fuzzyDB.AddVariable( lvAngle ); - - // creating the inference system - InferenceSystem IS = new InferenceSystem( fuzzyDB, new CentroidDefuzzifier( 1000 ) ); - - // going Straight - IS.NewRule( "Rule 1", "IF FrontalDistance IS Far THEN Angle IS Zero" ); - // Turning Left - IS.NewRule( "Rule 2", "IF FrontalDistance IS Near THEN Angle IS Positive" ); - - ... - // inference section - - // setting inputs - IS.SetInput( "FrontalDistance", 20 ); - - // getting outputs - try - { - float newAngle = IS.Evaluate( "Angle" ); - } - catch ( Exception ) - { - ... - } - - - - - - - Initializes a new Fuzzy . - - - A fuzzy containing the system linguistic variables. - A defuzzyfier method used to evaluate the numeric uotput of the system. - - - - - Initializes a new Fuzzy . - - - A fuzzy containing the system linguistic - variables. - A defuzzyfier method used to evaluate the numeric otput - of the system. - A operator used to evaluate the norms - in the . For more information of the norm evaluation see . - A operator used to evaluate the - conorms in the . For more information of the conorm evaluation see . - - - - - Creates a new and add it to the of the - . - - - Name of the to create. - A string representing the fuzzy rule. - - The new reference. - - - - - Sets a numerical input for one of the linguistic variables of the . - - - Name of the . - Numeric value to be used as input. - - The variable indicated in - was not found in the database. - - - - - Gets one of the of the . - - - Name of the to get. - - The variable indicated in - was not found in the database. - - - - - Gets one of the Rules of the . - - - Name of the to get. - - The rule indicated in - was not found in the rulebase. - - - - - Executes the fuzzy inference, obtaining a numerical output for a choosen output - linguistic variable. - - - Name of the to evaluate. - - The numerical output of the Fuzzy Inference System for the choosen variable. - - The variable indicated was not found in the database. - - - - - Executes the fuzzy inference, obtaining the of the system for the required - . - - - Name of the to evaluate. - - A containing the fuzzy output of the system for the - specified in . - - The variable indicated was not found in the database. - - - - - This class implements the centroid defuzzification method. - - - In many applications, a Fuzzy Inference System is used to perform linguistic - computation, but at the end of the inference process, a numerical value is needed. It does - not mean that the system needs precision, but simply that a numerical value is required, - most of the times because it will be used to control another system that needs the number. - To obtain this numer, a defuzzification method is performed. - - This class implements the centroid defuzzification method. The output of a Fuzzy - Inference System is a set of rules (see ) with firing strength greater - than zero. Those firing strength apply a constraint to the consequent fuzzy sets - (see ) of the rules. Putting all those fuzzy sets togheter results - in a a shape that is the linguistic output meaning. - - - The centroid method calculates the center of the area of this shape to obtain the - numerical representation of the output. It uses a numerical approximation, so a number - of intervals must be choosen. As the number of intervals grow, the precision of the - numerical ouput grows. - - - For a sample usage of the see - class. - - - - - - Initializes a new instance of the class. - - - Number of segments that the speech universe will be splited - to perform the numerical approximation of the center of area. - - - - - Centroid method to obtain the numerical representation of a fuzzy output. The numerical - value will be the center of the shape formed by the several fuzzy labels with their - constraints. - - - A containing the output of several - rules of a Fuzzy Inference System. - A operator to be used when constraining - the label to the firing strength. - - The numerical representation of the fuzzy output. - - The numerical output is unavaliable. All memberships are zero. - - - - - Product Norm, used to calculate the linguistic value of a AND operation. - - - The product Norm uses a multiplication operator to compute the - AND among two fuzzy memberships. - - Sample usage: - - // creating 2 fuzzy sets to represent Cool (Temperature) and Near (Distance) - TrapezoidalFunction function1 = new TrapezoidalFunction( 13, 18, 23, 28 ); - FuzzySet fsCool = new FuzzySet( "Cool", function1 ); - TrapezoidalFunction function2 = new TrapezoidalFunction( 23, 28, 33, 38 ); - FuzzySet fsNear = new FuzzySet( "Near", function2 ); - - // getting memberships - float m1 = fsCool.GetMembership( 15 ); - float m2 = fsNear.GetMembership( 35 ); - - // computing the membership of "Cool AND Near" - ProductNorm AND = new ProductNorm( ); - float result = AND.Evaluate( m1, m2 ); - - // show result - Console.WriteLine( result ); - - - - - - - - - Interface with the common methods of a Fuzzy Norm. - - - All fuzzy operators that act as a Norm must implement this interface. - - - - - - Calculates the numerical result of a Norm (AND) operation applied to - two fuzzy membership values. - - - A fuzzy membership value, [0..1]. - A fuzzy membership value, [0..1]. - - The numerical result the operation AND applied to - and . - - - - - Calculates the numerical result of the AND operation applied to - two fuzzy membership values using the product rule. - - - A fuzzy membership value, [0..1]. - A fuzzy membership value, [0..1]. - - The numerical result of the AND operation applied to - and . - - - - - Membership function in the shape of a trapezoid. Can be a half trapzoid if the left or the right side is missing. - - - Since the can represent any piece wise linear - function, it can represent trapezoids too. But as trapezoids are largely used in the creation of - Linguistic Variables, this class simplifies the creation of them. - - Sample usage: - - // creating a typical triangular fuzzy set /\ - TrapezoidalFunction function1 = new TrapezoidalFunction( 10, 20, 30 ); - // creating a right fuzzy set, the rigth side of the set is fuzzy but the left is opened - TrapezoidalFunction function2 = new TrapezoidalFunction( 10, 20, 30, TrapezoidalFunction.EdgeType.Right ); - - - - - - - Membership function composed by several connected linear functions. - - - The piecewise linear is a generic function used by many specific fuzzy membership - functions, like the trappezoidal function. This class must - be instantiated with a sequence of points representing the edges of each one of the lines composing the - piecewise function. - - The x-axis points must be ordered (crescent), so the function will use each X value - as an ending point for one line and starting point of the next. - - While trapezoidal and half trapezoidal are classic functions used in fuzzy functions, this class supports any function - or approximation that can be represented as a sequence of lines. - - Sample usage: - - // creating an array of points representing a typical trapezoidal function /-\ - Point [] points = new Point[4]; - // point where membership starts to rise - points[0] = new Point( 10, 0 ); - // maximum membership (1) reached at the second point - points[1] = new Point( 20, 1 ); - // membership starts to fall at the third point - points[2] = new Point( 30, 1 ); - // membership gets to zero at the last point - points[3] = new Point( 40, 0 ); - // creating the instance - PiecewiseLinearFunction membershipFunction = new PiecewiseLinearFunction( points ); - // getting membership for several points - for ( int i = 5; i < 45; i++ ) - Console.WriteLine( membershipFunction.GetMembership( i ) ); - - - - - - - Vector of (X,Y) coordinates for end/start of each line. - - - - - Initializes a new instance of the class. - - - This constructor must be used only by inherited classes to create the - points vector after the instantiation. - - - - - Initializes a new instance of the class. - - - Array of (X,Y) coordinates of each start/end of the lines. - - Specified point must be in crescent order on X axis and their Y value - must be in the range of [0, 1]. - - Points must be in crescent order on X axis. - Y value of points must be in the range of [0, 1]. - - - - - Calculate membership of a given value to the piecewise function. - - - Value which membership will to be calculated. - - Degree of membership [0..1] of the value to the fuzzy set. - - Points of the membership function are not initialized. - - - - - The leftmost x value of the membership function, given by the first (X,Y) coordinate. - - - Points of the membership function are not initialized. - - - - - The rightmost x value of the membership function, given by the last (X,Y) coordinate. - - - Points of the membership function are not initialized. - - - - - A private constructor used only to reuse code inside of this default constructor. - - - Size of points vector to create. This size depends of the shape of the - trapezoid. - - - - - Initializes a new instance of the class. - - With four points the shape is known as flat fuzzy number or fuzzy interval (/--\). - - - X value where the degree of membership starts to raise. - X value where the degree of membership reaches the maximum value. - X value where the degree of membership starts to fall. - X value where the degree of membership reaches the minimum value. - The maximum value that the membership will reach, [0, 1]. - The minimum value that the membership will reach, [0, 1]. - - - - - Initializes a new instance of the class. - - With four points the shape is known as flat fuzzy number or fuzzy interval (/--\). - - - X value where the degree of membership starts to raise. - X value where the degree of membership reaches the maximum value. - X value where the degree of membership starts to fall. - X value where the degree of membership reaches the minimum value. - - - Maximum membership value is set to 1.0 and the minimum is set to 0.0. - - - - - - Initializes a new instance of the class. - - With three points the shape is known as triangular fuzzy number or just fuzzy number (/\). - - - X value where the degree of membership starts to raise. - X value where the degree of membership reaches the maximum value and starts to fall. - X value where the degree of membership reaches the minimum value. - The maximum value that the membership will reach, [0, 1]. - The minimum value that the membership will reach, [0, 1]. - - - - - Initializes a new instance of the class. - - With three points the shape is known as triangular fuzzy number or just fuzzy number (/\). - - - X value where the degree of membership starts to raise. - X value where the degree of membership reaches the maximum value and starts to fall. - X value where the degree of membership reaches the minimum value. - - - Maximum membership value is set to 1.0 and the minimum is set to 0.0. - - - - - - Initializes a new instance of the class. - - With two points and an edge this shape can be a left fuzzy number (/) or a right fuzzy number (\). - - - Edge = Left: X value where the degree of membership starts to raise. - Edge = Right: X value where the function starts, with maximum degree of membership. - Edge = Left: X value where the degree of membership reaches the maximum. - Edge = Right: X value where the degree of membership reaches minimum value. - The maximum value that the membership will reach, [0, 1]. - The minimum value that the membership will reach, [0, 1]. - Trapezoid's . - - - - - Initializes a new instance of the class. - - With three points and an edge this shape can be a left fuzzy number (/--) or a right fuzzy number (--\). - - - Edge = Left: X value where the degree of membership starts to raise. - Edge = Right: X value where the function starts, with maximum degree of membership. - Edge = Left: X value where the degree of membership reaches the maximum. - Edge = Right: X value where the degree of membership reaches minimum value. - Trapezoid's . - - - Maximum membership value is set to 1.0 and the minimum is set to 0.0. - - - - - - Enumeration used to create trapezoidal membership functions with half trapezoids. - - - If the value is Left, the trapezoid has the left edge, but right - is open (/--). If the value is Right, the trapezoid has the right edge, but left - is open (--\). - - - - - The fuzzy side of the trapezoid is at the left side. - - - - - The fuzzy side of the trapezoid is at the right side. - - - - - The class represents a fuzzy database, a set of linguistic variables used in a Fuzzy - Inference System. - - - - - - Initializes a new instance of the class. - - - - - - Adds a linguistic variable to the database. - - - A linguistic variable to add. - - The linguistic variable was not initialized. - The linguistic variable name already exists in the database. - - - - - Removes all the linguistic variables of the database. - - - - - - Returns an existing linguistic variable from the database. - - - Name of the linguistic variable to retrieve. - - Reference to named . - - The variable indicated was not found in the database. - - - - - The class represents a linguistic variable. - - - Linguistic variables are variables that store linguistic values (labels). Fuzzy Inference Systems (FIS) - use a set of linguistic variables, called the FIS database, to execute fuzzy computation (computing with words). A linguistic - variable has a name and is composed by a set of called its linguistic labels. When declaring fuzzy - statements in a FIS, a linguistic variable can be only assigned or compared to one of its labels. - - Let us consider, for example, a linguistic variable temperature. In a given application, temperature can be - cold, cool, warm or hot. Those will be the variable's linguistic labels, each one a fuzzy set with its own membership - function. Ideally, the labels will represent concepts related to the variable's meaning. Futhermore, fuzzy statements like - "temperature is warm" or "temperature is not cold" can be used to build a Fuzzy Inference Systems. - - - Sample usage: - - // create a linguistic variable to represent temperature - LinguisticVariable lvTemperature = new LinguisticVariable( "Temperature", 0, 80 ); - - // create the linguistic labels (fuzzy sets) that compose the temperature - TrapezoidalFunction function1 = new TrapezoidalFunction( 10, 15, TrapezoidalFunction.EdgeType.Right ); - FuzzySet fsCold = new FuzzySet( "Cold", function1 ); - TrapezoidalFunction function2 = new TrapezoidalFunction( 10, 15, 20, 25 ); - FuzzySet fsCool = new FuzzySet( "Cool", function2 ); - TrapezoidalFunction function3 = new TrapezoidalFunction( 20, 25, 30, 35 ); - FuzzySet fsWarm = new FuzzySet( "Warm", function3 ); - TrapezoidalFunction function4 = new TrapezoidalFunction( 30, 35, TrapezoidalFunction.EdgeType.Left ); - FuzzySet fsHot = new FuzzySet( "Hot" , function4 ); - - // adding labels to the variable - lvTemperature.AddLabel( fsCold ); - lvTemperature.AddLabel( fsCool ); - lvTemperature.AddLabel( fsWarm ); - lvTemperature.AddLabel( fsHot ); - - // showing the shape of the linguistic variable - the shape of its labels memberships from start to end - Console.WriteLine( "Cold; Cool; Warm; Hot" ); - for ( float x = 0; x < 80; x += 0.2 ) - { - float y1 = lvTemperature.GetLabelMembership( "Cold", x ); - float y2 = lvTemperature.GetLabelMembership( "Cool", x ); - float y3 = lvTemperature.GetLabelMembership( "Warm", x ); - float y4 = lvTemperature.GetLabelMembership( "Hot" , x ); - - Console.WriteLine( String.Format( "{0:N}; {1:N}; {2:N}; {3:N}", y1, y2, y3, y4 ) ); - } - - - - - - - Initializes a new instance of the class. - - - Name of the linguistic variable. - - Left limit of the valid variable range. - - Right limit of the valid variable range. - - - - - Adds a linguistic label to the variable. - - - A that will be a linguistic label of the linguistic variable. - - Linguistic labels are fuzzy sets (). Each - label of the variable must have a unique name. The range of the label - (left and right limits) cannot be greater than - the linguistic variable range (start/end). - - The fuzzy set was not initialized. - The linguistic label name already exists in the linguistic variable. - The left limit of the fuzzy set can not be lower than the linguistic variable's starting point. - "The right limit of the fuzzy set can not be greater than the linguistic variable's ending point." - - - - - Removes all the linguistic labels of the linguistic variable. - - - - - - Returns an existing label from the linguistic variable. - - - Name of the label to retrieve. - - Reference to named label (). - - The label indicated was not found in the linguistic variable. - - - - - Calculate the membership of a given value to a given label. Used to evaluate linguistics clauses like - "X IS A", where X is a value and A is a linguistic label. - - - Label (fuzzy set) to evaluate value's membership. - Value which label's membership will to be calculated. - - Degree of membership [0..1] of the value to the label (fuzzy set). - - The label indicated in labelName was not found in the linguistic variable. - - - - - Numerical value of the input of this linguistic variable. - - - - - Name of the linguistic variable. - - - - - Left limit of the valid variable range. - - - - - Right limit of the valid variable range. - - - - - This class represents a Fuzzy Rule, a linguistic expression representing some behavioral - aspect of a Fuzzy Inference System. - - - - A Fuzzy Rule is a fuzzy linguistic instruction that can be executed by a fuzzy system. - The format of the Fuzzy Rule is: - - - IF antecedent THEN consequent - - The antecedent is composed by a set of fuzzy clauses (see ) connected - by fuzzy operations, like AND or OR. The operator NOT can be used to negate expressions: - - ...Clause1 AND (Clause2 OR Clause3) AND NOT Clause4 ... - - Fuzzy clauses are written in form Variable IS Value. The NOT operator can be used to negate linguistic values as well:
- ...Variable1 IS Value1 AND Variable2 IS NOT Value2 ...
- - The consequent is a single of fuzzy clauses (). To perform the - linguistic computing, the evaluates the clauses and then applies the fuzzy - operators. Once this is done a value representing the confidence in the antecedent being - true is obtained, and this is called firing strength of the . - - The firing strength is used to discover with how much confidence the consequent - of a rule is true. - - Sample usage: - - // create the linguistic labels (fuzzy sets) that compose the temperature - TrapezoidalFunction function1 = new TrapezoidalFunction( - 10, 15, TrapezoidalFunction.EdgeType.Right ); - FuzzySet fsCold = new FuzzySet( "Cold", function1 ); - TrapezoidalFunction function2 = new TrapezoidalFunction( 10, 15, 20, 25 ); - FuzzySet fsCool = new FuzzySet( "Cool", function2 ); - TrapezoidalFunction function3 = new TrapezoidalFunction( 20, 25, 30, 35 ); - FuzzySet fsWarm = new FuzzySet( "Warm", function3 ); - TrapezoidalFunction function4 = new TrapezoidalFunction( - 30, 35, TrapezoidalFunction.EdgeType.Left ); - FuzzySet fsHot = new FuzzySet( "Hot", function4 ); - - // create a linguistic variable to represent steel temperature - LinguisticVariable lvSteel = new LinguisticVariable( "Steel", 0, 80 ); - // adding labels to the variable - lvSteel.AddLabel( fsCold ); - lvSteel.AddLabel( fsCool ); - lvSteel.AddLabel( fsWarm ); - lvSteel.AddLabel( fsHot ); - - // create a linguistic variable to represent stove temperature - LinguisticVariable lvStove = new LinguisticVariable( "Stove", 0, 80 ); - // adding labels to the variable - lvStove.AddLabel( fsCold ); - lvStove.AddLabel( fsCool ); - lvStove.AddLabel( fsWarm ); - lvStove.AddLabel( fsHot ); - - // create the linguistic labels (fuzzy sets) that compose the pressure - TrapezoidalFunction function5 = new TrapezoidalFunction( - 20, 40, TrapezoidalFunction.EdgeType.Right ); - FuzzySet fsLow = new FuzzySet( "Low", function5 ); - TrapezoidalFunction function6 = new TrapezoidalFunction( 20, 40, 60, 80 ); - FuzzySet fsMedium = new FuzzySet( "Medium", function6 ); - TrapezoidalFunction function7 = new TrapezoidalFunction( - 60, 80, TrapezoidalFunction.EdgeType.Left ); - FuzzySet fsHigh = new FuzzySet( "High", function7 ); - // create a linguistic variable to represent pressure - LinguisticVariable lvPressure = new LinguisticVariable( "Pressure", 0, 100 ); - // adding labels to the variable - lvPressure.AddLabel( fsLow ); - lvPressure.AddLabel( fsMedium ); - lvPressure.AddLabel( fsHigh ); - - // create a linguistic variable database - Database db = new Database( ); - db.AddVariable( lvSteel ); - db.AddVariable( lvStove ); - db.AddVariable( lvPressure ); - - // sample rules just to test the expression parsing - Rule r1 = new Rule( db, "Test1", "IF Steel is not Cold and Stove is Hot then Pressure is Low" ); - Rule r2 = new Rule( db, "Test2", "IF Steel is Cold and not (Stove is Warm or Stove is Hot) then Pressure is Medium" ); - Rule r3 = new Rule( db, "Test3", "IF Steel is Cold and Stove is Warm or Stove is Hot then Pressure is High" ); - - // testing the firing strength - lvSteel.NumericInput = 12; - lvStove.NumericInput = 35; - float result = r1.EvaluateFiringStrength( ); - Console.WriteLine( result.ToString( ) ); - -
- -
- - - Initializes a new instance of the class. - - - A fuzzy containig the linguistic variables - (see ) that will be used in the Rule. - - Name of this . - - A string representing the . It must be a "IF..THEN" statement. - For a more detailed description see class. - - A class that implements a interface to - evaluate the AND operations of the Rule. - - A class that implements a interface - to evaluate the OR operations of the Rule. - - - - - Initializes a new instance of the class using as - CoNorm the and as Norm the . - - - A fuzzy containig the linguistic variables - (see ) that will be used in the . - - Name of this . - - A string representing the . It must be a "IF..THEN" - statement. For a more detailed description see class. - - - - - Converts the RPN fuzzy expression into a string representation. - - - String representation of the RPN fuzzy expression. - - - - - Defines the priority of the fuzzy operators. - - - A fuzzy operator or openning parenthesis. - - A number indicating the priority of the operator, and zero for openning - parenthesis. - - - - - Converts the Fuzzy Rule to RPN (Reverse Polish Notation). For debug proposes, the string representation of the - RPN expression can be acessed by calling method. - - - - - - Performs a preprocessing on the rule, placing unary operators in proper position and breaking the string - space separated tokens. - - - Rule in string format. - - An array of strings with tokens of the rule. - - - - - Evaluates the firing strength of the Rule, the degree of confidence that the consequent of this Rule - must be executed. - - - The firing strength [0..1] of the Rule. - - - - - The name of the fuzzy rule. - - - - - - The fuzzy that represents the consequent of the . - - - - - - The class represents a fuzzy set. - - - The fuzzy sets are the base for all fuzzy applications. In a classical set, the membership of - a given value to the set can always be defined as true (1) or false (0). In fuzzy sets, this membership can be - a value in the range [0..1], representing the imprecision existent in many real world applications. - - Let us consider, for example, fuzzy sets representing some temperature. In a given application, there is the - need to represent a cool and warm temperature. Like in real life, the precise point when the temperature changes from - cool to warm is not easy to find, and does not makes sense. If we consider the cool around 20 degrees and warm around - 30 degrees, it is not simple to find a break point. If we take the mean, we can consider values greater than or equal - 25 to be warm. But we can still consider 25 a bit cool. And a bit warm at the same time. This is where fuzzy sets can - help. - - Fuzzy sets are often used to compose Linguistic Variables, used in Fuzzy Inference Systems. - - Sample usage: - - // creating 2 fuzzy sets to represent Cool and Warm - TrapezoidalFunction function1 = new TrapezoidalFunction( 13, 18, 23, 28 ); - FuzzySet fsCool = new FuzzySet( "Cool", function1 ); - TrapezoidalFunction function2 = new TrapezoidalFunction( 23, 28, 33, 38 ); - FuzzySet fsWarm = new FuzzySet( "Warm", function2 ); - - // show membership to the Cool set for some values - Console.WriteLine( "COOL" ); - for ( int i = 13; i <= 28; i++ ) - Console.WriteLine( fsCool.GetMembership( i ) ); - - // show membership to the Warm set for some values - Console.WriteLine( "WARM" ); - for ( int i = 23; i <= 38; i++ ) - Console.WriteLine( fsWarm.GetMembership( i ) ); - - - - - - - Initializes a new instance of the class. - - - Name of the fuzzy set. - Membership function that will define the shape of the fuzzy set. - - - - - Calculate membership of a given value to the fuzzy set. - - - Value which membership needs to be calculated. - - Degree of membership [0..1] of the value to the fuzzy set. - - - - - Name of the fuzzy set. - - - - - The leftmost x value of the fuzzy set's membership function. - - - - - - The rightmost x value of the fuzzy set's membership function. - - - - - - The class represents the output of a Fuzzy Inference System. - - - The class keeps set of rule's output - pairs with the output fuzzy label - and the rule's firing strength. - - - - Sample usage: - - // linguistic labels (fuzzy sets) that compose the distances - FuzzySet fsNear = new FuzzySet( "Near", - new TrapezoidalFunction( 15, 50, TrapezoidalFunction.EdgeType.Right ) ); - FuzzySet fsMedium = new FuzzySet( "Medium", - new TrapezoidalFunction( 15, 50, 60, 100 ) ); - FuzzySet fsFar = new FuzzySet( "Far", - new TrapezoidalFunction( 60, 100, TrapezoidalFunction.EdgeType.Left ) ); - - // front distance (input) - LinguisticVariable lvFront = new LinguisticVariable( "FrontalDistance", 0, 120 ); - lvFront.AddLabel( fsNear ); - lvFront.AddLabel( fsMedium ); - lvFront.AddLabel( fsFar ); - - // linguistic labels (fuzzy sets) that compose the angle - FuzzySet fsZero = new FuzzySet( "Zero", - new TrapezoidalFunction( -10, 5, 5, 10 ) ); - FuzzySet fsLP = new FuzzySet( "LittlePositive", - new TrapezoidalFunction( 5, 10, 20, 25 ) ); - FuzzySet fsP = new FuzzySet( "Positive", - new TrapezoidalFunction( 20, 25, 35, 40 ) ); - FuzzySet fsVP = new FuzzySet( "VeryPositive", - new TrapezoidalFunction( 35, 40, TrapezoidalFunction.EdgeType.Left ) ); - - // angle - LinguisticVariable lvAngle = new LinguisticVariable( "Angle", -10, 50 ); - lvAngle.AddLabel( fsZero ); - lvAngle.AddLabel( fsLP ); - lvAngle.AddLabel( fsP ); - lvAngle.AddLabel( fsVP ); - - // the database - Database fuzzyDB = new Database( ); - fuzzyDB.AddVariable( lvFront ); - fuzzyDB.AddVariable( lvAngle ); - - // creating the inference system - InferenceSystem IS = new InferenceSystem( fuzzyDB, new CentroidDefuzzifier( 1000 ) ); - - // going straight - IS.NewRule( "Rule 1", "IF FrontalDistance IS Far THEN Angle IS Zero" ); - // turning left - IS.NewRule( "Rule 2", "IF FrontalDistance IS Near THEN Angle IS Positive" ); - - ... - // inference section - - // setting inputs - IS.SetInput( "FrontalDistance", 20 ); - - // getting outputs - try - { - FuzzyOutput fuzzyOutput = IS.ExecuteInference ( "Angle" ); - - // showing the fuzzy output - foreach ( FuzzyOutput.OutputConstraint oc in fuzzyOutput.OutputList ) - { - Console.WriteLine( oc.Label + " - " + oc.FiringStrength.ToString( ) ); - } - } - catch ( Exception ) - { - ... - } - - - - - - - Initializes a new instance of the class. - - - A representing a Fuzzy Inference System's output. - - - - - Adds an output to the Fuzzy Output. - - - The name of a label representing a fuzzy rule's output. - The firing strength [0..1] of a fuzzy rule. - - The label indicated was not found in the linguistic variable. - - - - - Removes all the linguistic variables of the database. - - - - - - A list with of a Fuzzy Inference System's output. - - - - - - Gets the acting as a Fuzzy Inference System Output. - - - - - - Inner class to store the pair fuzzy label / firing strength of - a fuzzy output. - - - - - Initializes a new instance of the class. - - - A string representing the output label of a . - The firing strength of a , to be applied to its output label. - - - - - The representing the output label of a . - - - - - - The firing strength of a , to be applied to its output label. - - - - - - This class represents a fuzzy clause, a linguistic expression of the type "Variable IS Value". - - - A Fuzzy Clause is used to verify if a linguistic variable can be considered - as a specific value at a specific moment. Linguistic variables can only assume value of - their linugistic labels. Because of the nature of the Fuzzy Logic, a Variable can be - several of its labels at the same time, with different membership values. - - For example, a linguistic variable "temperature" can be "hot" with a membership 0.3 - and "warm" with a membership 0.7 at the same time. To obtain those memberships, Fuzzy Clauses - "temperature is hot" and "temperature is war" can be built. - - Typically Fuzzy Clauses are used to build Fuzzy Rules (). - - Sample usage: - - // create a linguistic variable to represent temperature - LinguisticVariable lvTemperature = new LinguisticVariable( "Temperature", 0, 80 ); - - // create the linguistic labels (fuzzy sets) that compose the temperature - TrapezoidalFunction function1 = new TrapezoidalFunction( 10, 15, TrapezoidalFunction.EdgeType.Right ); - FuzzySet fsCold = new FuzzySet( "Cold", function1 ); - TrapezoidalFunction function2 = new TrapezoidalFunction( 10, 15, 20, 25 ); - FuzzySet fsCool = new FuzzySet( "Cool", function2 ); - TrapezoidalFunction function3 = new TrapezoidalFunction( 20, 25, 30, 35 ); - FuzzySet fsWarm = new FuzzySet( "Warm", function3 ); - TrapezoidalFunction function4 = new TrapezoidalFunction( 30, 35, TrapezoidalFunction.EdgeType.Left ); - FuzzySet fsHot = new FuzzySet( "Hot" , function4 ); - - // adding labels to the variable - lvTemperature.AddLabel( fsCold ); - lvTemperature.AddLabel( fsCool ); - lvTemperature.AddLabel( fsWarm ); - lvTemperature.AddLabel( fsHot ); - - // creating the Clause - Clause fuzzyClause = new Clause( lvTemperature, fsHot ); - // setting the numerical input of the variable to evaluate the Clause - lvTemperature.NumericInput = 35; - float result = fuzzyClause.Evaluate( ); - Console.WriteLine ( result.ToString( ) ); - - - - - - - Initializes a new instance of the class. - - - Linguistic variable of the clause. - - Label of the linguistic variable, a fuzzy set used as label into the linguistic variable. - - The label indicated was not found in the linguistic variable. - - - - - Evaluates the fuzzy clause. - - - Degree of membership [0..1] of the clause. - - - - - Returns the fuzzy clause in its linguistic representation. - - - A string representing the fuzzy clause. - - - - - Gets the of the . - - - - - Gets the of the . - - - - - Minimum Norm, used to calculate the linguistic value of a AND operation. - - - The minimum Norm uses a minimum operator to compute the AND - among two fuzzy memberships. - - Sample usage: - - // creating 2 fuzzy sets to represent Cool (Temperature) and Near (Distance) - TrapezoidalFunction function1 = new TrapezoidalFunction( 13, 18, 23, 28 ); - FuzzySet fsCool = new FuzzySet( "Cool", function1 ); - TrapezoidalFunction function2 = new TrapezoidalFunction( 23, 28, 33, 38 ); - FuzzySet fsNear = new FuzzySet( "Near", function2 ); - - // getting memberships - float m1 = fsCool.GetMembership( 15 ); - float m2 = fsNear.GetMembership( 35 ); - - // computing the membership of "Cool AND Near" - MinimumNorm AND = new MinimumNorm( ); - float result = AND.Evaluate( m1, m2 ); - - // show result - Console.WriteLine( result ); - - - - - - - - - Calculates the numerical result of the AND operation applied to - two fuzzy membership values using the minimum rule. - - - A fuzzy membership value, [0..1]. - - A fuzzy membership value, [0..1]. - - The numerical result of the AND operation applied to - and . - - -
-
diff --git a/Externals/AForge.NET/AForge.Genetic.dll b/Externals/AForge.NET/AForge.Genetic.dll deleted file mode 100644 index e97771639..0000000000 Binary files a/Externals/AForge.NET/AForge.Genetic.dll and /dev/null differ diff --git a/Externals/AForge.NET/AForge.Genetic.xml b/Externals/AForge.NET/AForge.Genetic.xml deleted file mode 100644 index 18e74200e..0000000000 --- a/Externals/AForge.NET/AForge.Genetic.xml +++ /dev/null @@ -1,2563 +0,0 @@ - - - - AForge.Genetic - - - - - Fitness function for symbolic regression (function approximation) problem - - - The fitness function calculates fitness value of - GP and GEP - chromosomes with the aim of solving symbolic regression problem. The fitness function's - value is computed as: - 100.0 / ( error + 1 ) - where error equals to the sum of absolute differences between function values (computed using - the function encoded by chromosome) and input values (function to be approximated). - - Sample usage: - - // constants - double[] constants = new double[5] { 1, 2, 3, 5, 7 }; - // function to be approximated - double[,] data = new double[5, 2] { - {1, 1}, {2, 3}, {3, 6}, {4, 10}, {5, 15} }; - // create population - Population population = new Population( 100, - new GPTreeChromosome( new SimpleGeneFunction( 1 + constants.Length ) ), - new SymbolicRegressionFitness( data, constants ), - new EliteSelection( ) ); - // run one epoch of the population - population.RunEpoch( ); - - - - - - - Fitness function interface. - - - The interface should be implemented by all fitness function - classes, which are supposed to be used for calculation of chromosomes - fitness values. All fitness functions should return positive (greater - then zero) value, which indicates how good is the evaluated chromosome - - the greater the value, the better the chromosome. - - - - - Evaluates chromosome. - - - Chromosome to evaluate. - - Returns chromosome's fitness value. - - The method calculates fitness value of the specified - chromosome. - - - - - Initializes a new instance of the class. - - - Function to be approximated. - Array of constants to be used as additional - paramters for genetic expression. - - The parameter defines the function to be approximated and - represents a two dimensional array of (x, y) points. - - The parameter is an array of constants, which can be used as - additional variables for a genetic expression. The actual amount of variables for - genetic expression equals to the amount of constants plus one - the x variable. - - - - - - Evaluates chromosome. - - - Chromosome to evaluate. - - Returns chromosome's fitness value. - - The method calculates fitness value of the specified - chromosome. - - - - - Translates genotype to phenotype . - - - Chromosome, which genoteype should be - translated to phenotype. - - Returns chromosome's fenotype - the actual solution - encoded by the chromosome. - - The method returns string value, which represents approximation - expression written in polish postfix notation. - - - - - Chromosome interface. - - - The interfase should be implemented by all classes, which implement - particular chromosome type. - - - - - Generate random chromosome value. - - - Regenerates chromosome's value using random number generator. - - - - - - Create new random chromosome with same parameters (factory method). - - - The method creates new chromosome of the same type, but randomly - initialized. The method is useful as factory method for those classes, which work - with chromosome's interface, but not with particular chromosome class. - - - - - Clone the chromosome. - - - The method clones the chromosome returning the exact copy of it. - - - - - - Mutation operator. - - - The method performs chromosome's mutation, changing its part randomly. - - - - - Crossover operator. - - - Pair chromosome to crossover with. - - The method performs crossover between two chromosomes – interchanging some parts of chromosomes. - - - - - Evaluate chromosome with specified fitness function. - - - Fitness function to use for evaluation of the chromosome. - - Calculates chromosome's fitness using the specifed fitness function. - - - - - Chromosome's fintess value. - - - The fitness value represents chromosome's usefulness - the greater the - value, the more useful it. - - - - - Genetic programming gene, which represents simple arithmetic functions and arguments. - - - Simple gene function may represent an arithmetic function (+, -, *, /) or - an argument to function. This class is used by Genetic Programming (or Gene Expression Programming) - chromosomes to build arbitrary expressions with help of genetic operators. - - - - - - Genetic Programming's gene interface. - - - This is a gene interface, which is used for building chromosomes - in Genetic Programming (GP) and Gene Expression Programming (GEP). - - - - - - Clone gene. - - - The method clones gene returning the exact copy of it. - - - - - Randomize gene with random type and value. - - - The method randomizes a gene, setting its type and value randomly. - - - - - Randomize gene with random value. - - - Gene type to set. - - The method randomizes a gene, setting its value randomly, but type - is set to the specified one. - - - - - Creates new gene with random type and value. - - - The method creates new randomly initialized gene . - The method is useful as factory method for those classes, which work with gene's interface, - but not with particular gene class. - - - - - - Creates new gene with certain type and random value. - - - Gene type to create. - - The method creates new gene with specified type, but random value. - The method is useful as factory method for those classes, which work with gene's interface, - but not with particular gene class. - - - - - - Gene type. - - - The property represents type of a gene - function, argument, etc. - - - - - - Arguments count. - - - Arguments count of a particular function gene. - - - - - Maximum arguments count. - - - Maximum arguments count of a function gene. The property may be used - by chromosomes' classes to allocate correctly memory for functions' arguments, - for example. - - - - - Number of different functions supported by the class. - - - - - Random number generator for chromosoms generation. - - - - - Initializes a new instance of the class. - - - Total amount of variables in the task which is supposed - to be solved. - - The constructor creates randomly initialized gene with random type - and value by calling method. - - - - - Initializes a new instance of the class. - - - Total amount of variables in the task which is supposed - to be solved. - Gene type to set. - - The constructor creates randomly initialized gene with random - value and preset gene type. - - - - - Get string representation of the gene. - - - Returns string representation of the gene. - - - - - Clone the gene. - - - The method clones the chromosome returning the exact copy of it. - - - - - Randomize gene with random type and value. - - - The method randomizes the gene, setting its type and value randomly. - - - - - Randomize gene with random value. - - - Gene type to set. - - The method randomizes a gene, setting its value randomly, but type - is set to the specified one. - - - - - Creates new gene with random type and value. - - - The method creates new randomly initialized gene . - The method is useful as factory method for those classes, which work with gene's interface, - but not with particular gene class. - - - - - - Creates new gene with certain type and random value. - - - Gene type to create. - - The method creates new gene with specified type, but random value. - The method is useful as factory method for those classes, which work with gene's interface, - but not with particular gene class. - - - - - - Gene type. - - - The property represents type of a gene - function, argument, etc. - - - - - - Arguments count. - - - Arguments count of a particular function gene. - - - - - Maximum arguments count. - - - Maximum arguments count of a function gene supported by the class. - The property may be used by chromosomes' classes to allocate correctly memory for - functions' arguments, for example. - - - - - Enumeration of supported functions. - - - - - Addition operator. - - - - - Suntraction operator. - - - - - Multiplication operator. - - - - - Division operator. - - - - - Population of chromosomes. - - - The class represents population - collection of individuals (chromosomes) - and provides functionality for common population's life cycle - population growing - with help of genetic operators and selection of chromosomes to new generation - with help of selection algorithm. The class may work with any type of chromosomes - implementing interface, use any type of fitness functions - implementing interface and use any type of selection - algorithms implementing interface. - - - - - - Initializes a new instance of the class. - - - Initial size of population. - Ancestor chromosome to use for population creatioin. - Fitness function to use for calculating - chromosome's fitness values. - Selection algorithm to use for selection - chromosome's to new generation. - - Creates new population of specified size. The specified ancestor - becomes first member of the population and is used to create other members - with same parameters, which were used for ancestor's creation. - - Too small population's size was specified. The - exception is thrown in the case if is smaller than 2. - - - - - Regenerate population. - - - The method regenerates population filling it with random chromosomes. - - - - - Do crossover in the population. - - - The method walks through the population and performs crossover operator - taking each two chromosomes in the order of their presence in the population. - The total amount of paired chromosomes is determined by - crossover rate. - - - - - Do mutation in the population. - - - The method walks through the population and performs mutation operator - taking each chromosome one by one. The total amount of mutated chromosomes is - determined by mutation rate. - - - - - Do selection. - - - The method applies selection operator to the current population. Using - specified selection algorithm it selects members to the new generation from current - generates and adds certain amount of random members, if is required - (see ). - - - - - Run one epoch of the population. - - - The method runs one epoch of the population, doing crossover, mutation - and selection by calling , and - . - - - - - Shuffle randomly current population. - - - Population shuffling may be useful in cases when selection - operator results in not random order of chromosomes (for example, after elite - selection population may be ordered in ascending/descending order). - - - - - Add chromosome to the population. - - - Chromosome to add to the population. - - The method adds specified chromosome to the current population. - Manual adding of chromosome maybe useful, when it is required to add some initialized - chromosomes instead of random. - - Adding chromosome manually should be done very carefully, since it - may break the population. The manually added chromosome must have the same type - and initialization parameters as the ancestor passed to constructor. - - - - - - Perform migration between two populations. - - - Population to do migration with. - Number of chromosomes from each population to migrate. - Selection algorithm used to select chromosomes to migrate. - - The method performs migration between two populations - current and the - specified one. During migration - specified number of chromosomes is choosen from - each population using specified selection algorithms - and put into another population replacing worst members there. - - - - - Resize population to the new specified size. - - - New size of population. - - The method does resizing of population. In the case if population - should grow, it just adds missing number of random members. In the case if - population should get smaller, the population's - selection method is used to reduce the population. - - Too small population's size was specified. The - exception is thrown in the case if is smaller than 2. - - - - - Resize population to the new specified size. - - - New size of population. - Selection algorithm to use in the case - if population should get smaller. - - The method does resizing of population. In the case if population - should grow, it just adds missing number of random members. In the case if - population should get smaller, the specified selection method is used to - reduce the population. - - Too small population's size was specified. The - exception is thrown in the case if is smaller than 2. - - - - - Crossover rate, [0.1, 1]. - - - The value determines the amount of chromosomes which participate - in crossover. - - Default value is set to 0.75. - - - - - - Mutation rate, [0.1, 1]. - - - The value determines the amount of chromosomes which participate - in mutation. - - Defaul value is set to 0.1. - - - - - Random selection portion, [0, 0.9]. - - - The value determines the amount of chromosomes which will be - randomly generated for the new population. The property controls the amount - of chromosomes, which are selected to a new population using - selection operator, and amount of random - chromosomes added to the new population. - - Default value is set to 0. - - - - - Determines of auto shuffling is on or off. - - - The property specifies if automatic shuffling needs to be done - on each epoch by calling - method. - - Default value is set to . - - - - - Selection method to use with the population. - - - The property sets selection method which is used to select - population members for a new population - filter population after reproduction - was done with operators like crossover and mutations. - - - - - Fitness function to apply to the population. - - - The property sets fitness function, which is used to evaluate - usefulness of population's chromosomes. Setting new fitness function causes recalculation - of fitness values for all population's members and new best member will be found. - - - - - - Maximum fitness of the population. - - - The property keeps maximum fitness of chromosomes currently existing - in the population. - - The property is recalculate only after selection - or migration was done. - - - - - - Summary fitness of the population. - - - The property keeps summary fitness of all chromosome existing in the - population. - - The property is recalculate only after selection - or migration was done. - - - - - - Average fitness of the population. - - - The property keeps average fitness of all chromosome existing in the - population. - - The property is recalculate only after selection - or migration was done. - - - - - - Best chromosome of the population. - - - The property keeps the best chromosome existing in the population - or if all chromosomes have 0 fitness. - - The property is recalculate only after selection - or migration was done. - - - - - - Size of the population. - - - The property keeps initial (minimal) size of population. - Population always returns to this size after selection operator was applied, - which happens after or methods - call. - - - - - Get chromosome with specified index. - - - Chromosome's index to retrieve. - - Allows to access individuals of the population. - - - - - Permutation chromosome. - - - Permutation chromosome is based on short array chromosome, - but has two features: - - all genes are unique within chromosome, i.e. there are no two genes - with the same value; - maximum value of each gene is equal to chromosome length minus 1. - - - - - - - Short array chromosome. - - - Short array chromosome represents array of unsigned short values. - Array length is in the range of [2, 65536]. - - - - - Chromosomes' base class. - - - The base class provides implementation of some - methods and properties, which are identical to all types of chromosomes. - - - - - Chromosome's fintess value. - - - - - Generate random chromosome value. - - - Regenerates chromosome's value using random number generator. - - - - - - Create new random chromosome with same parameters (factory method). - - - The method creates new chromosome of the same type, but randomly - initialized. The method is useful as factory method for those classes, which work - with chromosome's interface, but not with particular chromosome class. - - - - - Clone the chromosome. - - - The method clones the chromosome returning the exact copy of it. - - - - - - Mutation operator. - - - The method performs chromosome's mutation, changing its part randomly. - - - - - Crossover operator. - - - Pair chromosome to crossover with. - - The method performs crossover between two chromosomes – interchanging some parts of chromosomes. - - - - - Evaluate chromosome with specified fitness function. - - - Fitness function to use for evaluation of the chromosome. - - Calculates chromosome's fitness using the specifed fitness function. - - - - - Compare two chromosomes. - - - Binary chromosome to compare to. - - Returns comparison result, which equals to 0 if fitness values - of both chromosomes are equal, 1 if fitness value of this chromosome - is less than fitness value of the specified chromosome, -1 otherwise. - - - - - Chromosome's fintess value. - - - Fitness value (usefulness) of the chromosome calculate by calling - method. The greater the value, the more useful the chromosome. - - - - - - Chromosome's maximum length. - - - Maxim chromosome's length in array elements. - - - - - Chromosome's length in number of elements. - - - - - Maximum value of chromosome's gene (element). - - - - - Chromosome's value. - - - - - Random number generator for chromosoms generation, crossover, mutation, etc. - - - - - Initializes a new instance of the class. - - - Chromosome's length in array elements, [2, ]. - - This constructor initializes chromosome setting genes' maximum value to - maximum posible value of type. - - - - - Initializes a new instance of the class. - - - Chromosome's length in array elements, [2, ]. - Maximum value of chromosome's gene (array element). - - - - - Initializes a new instance of the class. - - - Source chromosome to copy. - - This is a copy constructor, which creates the exact copy - of specified chromosome. - - - - - Get string representation of the chromosome. - - - Returns string representation of the chromosome. - - - - - Generate random chromosome value. - - - Regenerates chromosome's value using random number generator. - - - - - - Create new random chromosome with same parameters (factory method). - - - The method creates new chromosome of the same type, but randomly - initialized. The method is useful as factory method for those classes, which work - with chromosome's interface, but not with particular chromosome type. - - - - - Clone the chromosome. - - - Return's clone of the chromosome. - - The method clones the chromosome returning the exact copy of it. - - - - - - Mutation operator. - - - The method performs chromosome's mutation, changing randomly - one of its genes (array elements). - - - - - Crossover operator. - - - Pair chromosome to crossover with. - - The method performs crossover between two chromosomes – interchanging - range of genes (array elements) between these chromosomes. - - - - - Chromosome's length. - - - Length of the chromosome in array elements. - - - - - Chromosome's value. - - - Current value of the chromosome. - - - - - Max possible value of single chromosomes element - gene. - - - Maximum possible numerical value, which may be represented - by single chromosome's gene (array element). - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Source chromosome to copy. - - This is a copy constructor, which creates the exact copy - of specified chromosome. - - - - - Generate random chromosome value. - - - Regenerates chromosome's value using random number generator. - - - - - - Create new random chromosome with same parameters (factory method). - - - The method creates new chromosome of the same type, but randomly - initialized. The method is useful as factory method for those classes, which work - with chromosome's interface, but not with particular chromosome type. - - - - - Clone the chromosome. - - - Return's clone of the chromosome. - - The method clones the chromosome returning the exact copy of it. - - - - - - Mutation operator. - - - The method performs chromosome's mutation, swapping two randomly - chosen genes (array elements). - - - - - Crossover operator. - - - Pair chromosome to crossover with. - - The method performs crossover between two chromosomes – interchanging - some parts between these chromosomes. - - - - - Tree chromosome represents a tree of genes, which is is used for - different tasks of Genetic Programming (GP). - - - This type of chromosome represents a tree, where each node - is represented by containing . - Depending on type of genes used to build the tree, it may represent different - types of expressions aimed to solve different type of tasks. For example, a - particular implementation of interface may represent - simple algebraic operations and their arguments. - - - See documentation to implementations for additional - information about possible Genetic Programming trees. - - - - - - Random generator used for chromosoms' generation. - - - - - Initializes a new instance of the class. - - - A gene, which is used as generator for the genetic tree. - - This constructor creates a randomly generated genetic tree, - which has all genes of the same type and properties as the specified . - - - - - - Initializes a new instance of the class. - - - Source genetic tree to clone from. - - This constructor creates new genetic tree as a copy of the - specified tree. - - - - - Get string representation of the chromosome by providing its expression in - reverse polish notation (postfix notation). - - - Returns string representation of the genetic tree. - - The method returns string representation of the tree's root node - (see ). - - - - - Generate random chromosome value. - - - Regenerates chromosome's value using random number generator. - - - - - - Generate chromosome's subtree of specified level. - - - Sub tree's node to generate. - Sub tree's level to generate. - - - - - Create new random chromosome with same parameters (factory method). - - - The method creates new chromosome of the same type, but randomly - initialized. The method is useful as factory method for those classes, which work - with chromosome's interface, but not with particular chromosome type. - - - - - Clone the chromosome. - - - Return's clone of the chromosome. - - The method clones the chromosome returning the exact copy of it. - - - - - - Mutation operator. - - - The method performs chromosome's mutation by regenerating tree's - randomly selected node. - - - - - Crossover operator. - - - Pair chromosome to crossover with. - - The method performs crossover between two chromosomes – interchanging - randomly selected sub trees. - - - - - Crossover helper routine - selects random node of chromosomes tree and - swaps it with specified node. - - - - - Trim tree node, so its depth does not exceed specified level. - - - - - Maximum initial level of genetic trees, [1, 25]. - - - The property sets maximum possible initial depth of new - genetic programming tree. For example, if it is set to 1, then largest initial - tree may have a root and one level of children. - - Default value is set to 3. - - - - - - Maximum level of genetic trees, [1, 50]. - - - The property sets maximum possible depth of - genetic programming tree, which may be created with mutation and crossover operators. - This property guarantees that genetic programmin tree will never have - higher depth, than the specified value. - - Default value is set to 5. - - - - - - Double array chromosome. - - - Double array chromosome represents array of double values. - Array length is in the range of [2, 65536]. - - - See documentation to and methods - for information regarding implemented mutation and crossover operators. - - - - - - Chromosome's maximum length. - - - Maxim chromosome's length in array elements. - - - - - Chromosome generator. - - - This random number generator is used to initialize chromosome's genes, - which is done by calling method. - - - - - Mutation multiplier generator. - - - This random number generator is used to generate random multiplier values, - which are used to multiply chromosome's genes during mutation. - - - - - Mutation addition generator. - - - This random number generator is used to generate random addition values, - which are used to add to chromosome's genes during mutation. - - - - - Random number generator for crossover and mutation points selection. - - - This random number generator is used to select crossover - and mutation points. - - - - - Chromosome's length in number of elements. - - - - - Chromosome's value. - - - - - Initializes a new instance of the class. - - - Chromosome generator - random number generator, which is - used to initialize chromosome's genes, which is done by calling method - or in class constructor. - Mutation multiplier generator - random number - generator, which is used to generate random multiplier values, which are used to - multiply chromosome's genes during mutation. - Mutation addition generator - random number - generator, which is used to generate random addition values, which are used to - add to chromosome's genes during mutation. - Chromosome's length in array elements, [2, ]. - - The constructor initializes the new chromosome randomly by calling - method. - - - - - Initializes a new instance of the class. - - - Chromosome generator - random number generator, which is - used to initialize chromosome's genes, which is done by calling method - or in class constructor. - Mutation multiplier generator - random number - generator, which is used to generate random multiplier values, which are used to - multiply chromosome's genes during mutation. - Mutation addition generator - random number - generator, which is used to generate random addition values, which are used to - add to chromosome's genes during mutation. - Values used to initialize the chromosome. - - The constructor initializes the new chromosome with specified values. - - - Invalid length of values array. - - - - - Initializes a new instance of the class. - - - Source chromosome to copy. - - This is a copy constructor, which creates the exact copy - of specified chromosome. - - - - - Get string representation of the chromosome. - - - Returns string representation of the chromosome. - - - - - Generate random chromosome value. - - - Regenerates chromosome's value using random number generator. - - - - - - Create new random chromosome with same parameters (factory method). - - - The method creates new chromosome of the same type, but randomly - initialized. The method is useful as factory method for those classes, which work - with chromosome's interface, but not with particular chromosome type. - - - - - Clone the chromosome. - - - Return's clone of the chromosome. - - The method clones the chromosome returning the exact copy of it. - - - - - - Mutation operator. - - - The method performs chromosome's mutation, adding random number - to chromosome's gene or multiplying the gene by random number. These random - numbers are generated with help of mutation - multiplier and mutation - addition generators. - - The exact type of mutation applied to the particular gene - is selected randomly each time and depends on . - Before mutation is done a random number is generated in [0, 1] range - if the - random number is smaller than , then multiplication - mutation is done, otherwise addition mutation. - - - - - - Crossover operator. - - - Pair chromosome to crossover with. - - The method performs crossover between two chromosomes, selecting - randomly the exact type of crossover to perform, which depends on . - Before crossover is done a random number is generated in [0, 1] range - if the - random number is smaller than , then the first crossover - type is used, otherwise second type is used. - - The first crossover type is based on interchanging - range of genes (array elements) between these chromosomes and is known - as one point crossover. A crossover point is selected randomly and chromosomes - interchange genes, which start from the selected point. - - The second crossover type is aimed to produce one child, which genes' - values are between corresponding genes of parents, and another child, which genes' - values are outside of the range formed by corresponding genes of parents. - Let take, for example, two genes with 1.0 and 3.0 valueы (of course chromosomes have - more genes, but for simplicity lets think about one). First of all we randomly choose - a factor in the [0, 1] range, let's take 0.4. Then, for each pair of genes (we have - one pair) we calculate difference value, which is 2.0 in our case. In the result we’ll - have two children – one between and one outside of the range formed by parents genes' values. - We may have 1.8 and 3.8 children, or we may have 0.2 and 2.2 children. As we can see - we add/subtract (chosen randomly) difference * factor. So, this gives us exploration - in between and in near outside. The randomly chosen factor is applied to all genes - of the chromosomes participating in crossover. - - - - - - Chromosome's length. - - - Length of the chromosome in array elements. - - - - - Chromosome's value. - - - Current value of the chromosome. - - - - - Mutation balancer to control mutation type, [0, 1]. - - - The property controls type of mutation, which is used more - frequently. A radnom number is generated each time before doing mutation - - if the random number is smaller than the specified balance value, then one - mutation type is used, otherwse another. See method - for more information. - - Default value is set to 0.5. - - - - - - Crossover balancer to control crossover type, [0, 1]. - - - The property controls type of crossover, which is used more - frequently. A radnom number is generated each time before doing crossover - - if the random number is smaller than the specified balance value, then one - crossover type is used, otherwse another. See method - for more information. - - Default value is set to 0.5. - - - - - - Genetic selection method interface. - - - The interface should be implemented by all classes, which - implement genetic selection algorithm. These algorithms select members of - current generation, which should be kept in the new generation. Basically, - these algorithms filter provided population keeping only specified amount of - members. - - - - - Apply selection to the specified population. - - - Population, which should be filtered. - The amount of chromosomes to keep. - - Filters specified population according to the implemented - selection algorithm. - - - - - Rank selection method. - - - The algorithm selects chromosomes to the new generation depending on - their fitness values - the better fitness value chromosome has, the more chances - it has to become member of the new generation. Each chromosome can be selected - several times to the new generation. - - This algorithm is similar to Roulette Wheel - Selection algorithm, but the difference is in "wheel" and its sectors' size - calculation method. The size of the wheel equals to size * ( size + 1 ) / 2, - where size is the current size of population. The worst chromosome has its sector's - size equal to 1, the next chromosome has its sector's size equal to 2, etc. - - - - - - Initializes a new instance of the class. - - - - - Apply selection to the specified population. - - - Population, which should be filtered. - The amount of chromosomes to keep. - - Filters specified population keeping only those chromosomes, which - won "roulette" game. - - - - - Roulette wheel selection method. - - - The algorithm selects chromosomes to the new generation according to - their fitness values - the more fitness value chromosome has, the more chances - it has to become member of new generation. Each chromosome can be selected - several times to the new generation. - - The "roulette's wheel" is divided into sectors, which size is proportional to - the fitness values of chromosomes - the size of the wheel is the sum of all fitness - values, size of each sector equals to fitness value of chromosome. - - - - - - Initializes a new instance of the class. - - - - - Apply selection to the specified population. - - - Population, which should be filtered. - The amount of chromosomes to keep. - - Filters specified population keeping only those chromosomes, which - won "roulette" game. - - - - - Binary chromosome, which supports length from 2 till 64. - - - The binary chromosome is the simplest type of chromosomes, - which is represented by a set of bits. Maximum number of bits comprising - the chromosome is 64. - - - - - Chromosome's maximum length. - - - Maxim chromosome's length in bits, which is supported - by the class - - - - - Chromosome's length in bits. - - - - - Numerical chromosome's value. - - - - - Random number generator for chromosoms generation, crossover, mutation, etc. - - - - - Initializes a new instance of the class. - - - Chromosome's length in bits, [2, ]. - - - - - Initializes a new instance of the class. - - - Source chromosome to copy. - - This is a copy constructor, which creates the exact copy - of specified chromosome. - - - - - Get string representation of the chromosome. - - - Returns string representation of the chromosome. - - - - - Generate random chromosome value. - - - Regenerates chromosome's value using random number generator. - - - - - - Create new random chromosome with same parameters (factory method). - - - The method creates new chromosome of the same type, but randomly - initialized. The method is useful as factory method for those classes, which work - with chromosome's interface, but not with particular chromosome type. - - - - - Clone the chromosome. - - - Return's clone of the chromosome. - - The method clones the chromosome returning the exact copy of it. - - - - - - Mutation operator. - - - The method performs chromosome's mutation, changing randomly - one of its bits. - - - - - Crossover operator. - - - Pair chromosome to crossover with. - - The method performs crossover between two chromosomes – interchanging - range of bits between these chromosomes. - - - - - Chromosome's length. - - - Length of the chromosome in bits. - - - - - Chromosome's value. - - - Current numerical value of the chromosome. - - - - - Max possible chromosome's value. - - - Maximum possible numerical value, which may be represented - by the chromosome of current length. - - - - Base class for one dimensional function optimizations. - - The class is aimed to be used for one dimensional function - optimization problems. It implements all methods of - interface and requires overriding only one method - - , which represents the - function to optimize. - - The optimization function should be greater - than 0 on the specified optimization range. - - The class works only with binary chromosomes (). - - Sample usage: - - // define optimization function - public class UserFunction : OptimizationFunction1D - { - public UserFunction( ) : - base( new Range( 0, 255 ) ) { } - - public override double OptimizationFunction( double x ) - { - return Math.Cos( x / 23 ) * Math.Sin( x / 50 ) + 2; - } - } - ... - // create genetic population - Population population = new Population( 40, - new BinaryChromosome( 32 ), - new UserFunction( ), - new EliteSelection( ) ); - - while ( true ) - { - // run one epoch of the population - population.RunEpoch( ); - // ... - } - - - - - - - Initializes a new instance of the class. - - - Specifies range for optimization. - - - - - Evaluates chromosome. - - - Chromosome to evaluate. - - Returns chromosome's fitness value. - - The method calculates fitness value of the specified - chromosome. - - - - - Translates genotype to phenotype. - - - Chromosome, which genoteype should be - translated to phenotype. - - Returns chromosome's fenotype - the actual solution - encoded by the chromosome. - - The method returns double value, which represents function's - input point encoded by the specified chromosome. - - - - - Function to optimize. - - - Function's input value. - - Returns function output value. - - The method should be overloaded by inherited class to - specify the optimization function. - - - - - Optimization range. - - - Defines function's input range. The function's extreme point will - be searched in this range only. - - - - - - Optimization mode. - - - Defines optimization mode - what kind of extreme point to search. - - - - - Optimization modes. - - - The enumeration defines optimization modes for - the one dimensional function optimization. - - - - - Search for function's maximum value. - - - - - Search for function's minimum value. - - - - Base class for two dimenstional function optimization. - - The class is aimed to be used for two dimensional function - optimization problems. It implements all methods of - interface and requires overriding only one method - - , which represents the - function to optimize. - - The optimization function should be greater - than 0 on the specified optimization range. - - The class works only with binary chromosomes (). - - Sample usage: - - // define optimization function - public class UserFunction : OptimizationFunction2D - { - public UserFunction( ) : - base( new Range( -4, 4 ), new Range( -4, 4 ) ) { } - - public override double OptimizationFunction( double x, double y ) - { - return ( Math.Cos( y ) * x * y ) / ( 2 - Math.Sin( x ) ); - } - } - ... - // create genetic population - Population population = new Population( 40, - new BinaryChromosome( 32 ), - new UserFunction( ), - new EliteSelection( ) ); - // run one epoch of the population - population.RunEpoch( ); - - - - - - - Initializes a new instance of the class. - - - Specifies X variable's range. - Specifies Y variable's range. - - - - - Evaluates chromosome. - - - Chromosome to evaluate. - - Returns chromosome's fitness value. - - The method calculates fitness value of the specified - chromosome. - - - - - Translates genotype to phenotype - - - Chromosome, which genoteype should be - translated to phenotype - - Returns chromosome's fenotype - the actual solution - encoded by the chromosome - - The method returns array of two double values, which - represent function's input point (X and Y) encoded by the specified - chromosome. - - - - - Function to optimize. - - - Function X input value. - Function Y input value. - - Returns function output value. - - The method should be overloaded by inherited class to - specify the optimization function. - - - - - X variable's optimization range. - - - Defines function's X range. The function's extreme will - be searched in this range only. - - - - - - Y variable's optimization range. - - - Defines function's Y range. The function's extreme will - be searched in this range only. - - - - - - Optimization mode. - - - Defines optimization mode - what kind of extreme to search. - - - - - Optimization modes. - - - The enumeration defines optimization modes for - the two dimensional function optimization. - - - - - Search for function's maximum value. - - - - - Search for function's minimum value. - - - - - Genetic programming gene, which represents arithmetic functions, common mathematical functions - and arguments. - - - Extended gene function may represent arithmetic functions (+, -, *, /), - some common mathematical functions (sin, cos, ln, exp, sqrt) or an argument to functions. - This class is used by Genetic Programming (or Gene Expression Programming) - chromosomes to build arbitrary expressions with help of genetic operators. - - - - - - Number of different functions supported by the class. - - - - - Random number generator for chromosoms generation. - - - - - Initializes a new instance of the class. - - - Total amount of variables in the task which is supposed - to be solved. - - The constructor creates randomly initialized gene with random type - and value by calling method. - - - - - Initializes a new instance of the class. - - - Total amount of variables in the task which is supposed - to be solved. - Gene type to set. - - The constructor creates randomly initialized gene with random - value and preset gene type. - - - - - Get string representation of the gene. - - - Returns string representation of the gene. - - - - - Clone the gene. - - - The method clones the chromosome returning the exact copy of it. - - - - - Randomize gene with random type and value. - - - The method randomizes the gene, setting its type and value randomly. - - - - - Randomize gene with random value. - - - Gene type to set. - - The method randomizes a gene, setting its value randomly, but type - is set to the specified one. - - - - - Creates new gene with random type and value. - - - The method creates new randomly initialized gene . - The method is useful as factory method for those classes, which work with gene's interface, - but not with particular gene class. - - - - - - Creates new gene with certain type and random value. - - - Gene type to create. - - The method creates new gene with specified type, but random value. - The method is useful as factory method for those classes, which work with gene's interface, - but not with particular gene class. - - - - - - Gene type. - - - The property represents type of a gene - function, argument, etc. - - - - - - Arguments count. - - - Arguments count of a particular function gene. - - - - - Maximum arguments count. - - - Maximum arguments count of a function gene supported by the class. - The property may be used by chromosomes' classes to allocate correctly memory for - functions' arguments, for example. - - - - - Enumeration of supported functions. - - - - - Addition operator. - - - - - Suntraction operator. - - - - - Multiplication operator. - - - - - Division operator. - - - - - Sine function. - - - - - Cosine function. - - - - - Natural logarithm function. - - - - - Exponent function. - - - - - Square root function. - - - - - Fitness function for times series prediction problem - - - The fitness function calculates fitness value of - GP and GEP - chromosomes with the aim of solving times series prediction problem using - sliding window method. The fitness function's value is computed as: - 100.0 / ( error + 1 ) - where error equals to the sum of absolute differences between predicted value - and actual future value. - - Sample usage: - - // number of points from the past used to predict new one - int windowSize = 5; - // time series to predict - double[] data = new double[13] { 1, 2, 4, 7, 11, 16, 22, 29, 37, 46, 56, 67, 79 }; - // constants - double[] constants = new double[10] { 1, 2, 3, 5, 7, 11, 13, 17, 19, 23 }; - // create population - Population population = new Population( 100, - new GPTreeChromosome( new SimpleGeneFunction( windowSize + constants.Length ) ), - new TimeSeriesPredictionFitness( data, windowSize, 1, constants ), - new EliteSelection( ) ); - // run one epoch of the population - population.RunEpoch( ); - - - - - - - Initializes a new instance of the class. - - - Time series to be predicted. - Window size - number of past samples used - to predict future value. - Prediction size - number of values to be predicted. These - values are excluded from training set. - Array of constants to be used as additional - paramters for genetic expression. - - The parameter is a one dimensional array, which defines times - series to predict. The amount of learning samples is equal to the number of samples - in the provided time series, minus window size, minus prediction size. - - The parameter specifies the amount of samples, which should - be excluded from training set. This set of samples may be used for future verification - of the prediction model. - - The parameter is an array of constants, which can be used as - additional variables for a genetic expression. The actual amount of variables for - genetic expression equals to the amount of constants plus the window size. - - - - - - Evaluates chromosome. - - - Chromosome to evaluate. - - Returns chromosome's fitness value. - - The method calculates fitness value of the specified - chromosome. - - - - - Translates genotype to phenotype. - - - Chromosome, which genoteype should be - translated to phenotype. - - Returns chromosome's fenotype - the actual solution - encoded by the chromosome. - - The method returns string value, which represents prediction - expression written in polish postfix notation. - - The interpretation of the prediction expression is very simple. For example, let's - take a look at sample expression, which was received with window size equal to 5: - $0 $1 - $5 / $2 * - The above expression in postfix polish notation should be interpreted as a next expression: - ( ( x[t - 1] - x[t - 2] ) / const1 ) * x[t - 3] - - - - - - - Represents tree node of genetic programming tree. - - - In genetic programming a chromosome is represented by a tree, which - is represented by class. The - class represents single node of such genetic programming tree. - - Each node may or may not have children. This means that particular node of a genetic - programming tree may represent its sub tree or even entire tree. - - - - - - Gene represented by the chromosome. - - - - - List of node's children. - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - - - - Get string representation of the node. - - - Returns string representation of the node. - - String representation of the node lists all node's children and - then the node itself. Such node's string representations equals to - its reverse polish notation. - - For example, if nodes value is '+' and its children are '3' and '5', then - nodes string representation is "3 5 +". - - - - - - Clone the tree node. - - - Returns exact clone of the node. - - - - - Elite selection method. - - - Elite selection method selects specified amount of - best chromosomes to the next generation. - - - - - Initializes a new instance of the class. - - - - - Apply selection to the specified population. - - - Population, which should be filtered. - The amount of chromosomes to keep. - - Filters specified population keeping only specified amount of best - chromosomes. - - - - - Types of genes in Genetic Programming. - - - - - Function gene - represents function to be executed. - - - - - Argument gene - represents argument of function. - - - - - The chromosome represents a Gene Expression, which is used for - different tasks of Genetic Expression Programming (GEP). - - - This type of chromosome represents combination of ideas taken from - Genetic Algorithms (GA), where chromosomes are linear structures of fixed length, and - Genetic Programming (GP), where chromosomes are expression trees. The GEP chromosome - is also a fixed length linear structure, but with some additional features which - make it possible to generate valid expression tree from any GEP chromosome. - - The theory of Gene Expression Programming is well described in the next paper: - Ferreira, C., 2001. Gene Expression Programming: A New Adaptive Algorithm for Solving - Problems. Complex Systems, Vol. 13, issue 2: 87-129. A copy of the paper may be - obtained on the - gene expression programming web site. - - - - - - Length of GEP chromosome's head. - - - GEP chromosome's head is a part of chromosome, which may contain both - functions' and arguments' nodes. The rest of chromosome (tail) may contain only arguments' nodes. - - - - - - GEP chromosome's length. - - - The variable keeps chromosome's length, but not expression length represented by the - chromosome. - - - - - Array of chromosome's genes. - - - - - Random generator used for chromosoms' generation. - - - - - Initializes a new instance of the class. - - - A gene, which is used as generator for the genetic tree. - Length of GEP chromosome's head (see ). - - This constructor creates a randomly generated GEP chromosome, - which has all genes of the same type and properties as the specified . - - - - - - Initializes a new instance of the class. - - - Source GEP chromosome to clone from. - - - - - Get string representation of the chromosome by providing its expression in - reverse polish notation (postfix notation). - - - Returns string representation of the expression represented by the GEP - chromosome. - - - - - Get string representation of the chromosome. - - - Returns the chromosome in native linear representation. - - The method is used for debugging mostly. - - - - - Generate random chromosome value. - - - Regenerates chromosome's value using random number generator. - - - - - - Get tree representation of the chromosome. - - - Returns expression's tree represented by the chromosome. - - The method builds expression's tree for the native linear representation - of the GEP chromosome. - - - - - Create new random chromosome with same parameters (factory method). - - - The method creates new chromosome of the same type, but randomly - initialized. The method is useful as factory method for those classes, which work - with chromosome's interface, but not with particular chromosome type. - - - - - Clone the chromosome. - - - Return's clone of the chromosome. - - The method clones the chromosome returning the exact copy of it. - - - - - - Mutation operator. - - - The method performs chromosome's mutation by calling on of the methods - randomly: , , . - - - - - - Usual gene mutation. - - - The method performs usual gene mutation by randomly changing randomly selected - gene. - - - - - Transposition of IS elements (insertion sequence). - - - The method performs transposition of IS elements by copying randomly selected region - of genes into chromosome's head (into randomly selected position). First gene of the chromosome's head - is not affected - can not be selected as target point. - - - - - Root transposition. - - - The method performs root transposition of the GEP chromosome - inserting - new root of the chromosome and shifting existing one. The method first of all randomly selects - a function gene in chromosome's head - starting point of the sequence to put into chromosome's - head. Then it randomly selects the length of the sequence making sure that the entire sequence is - located within head. Once the starting point and the length of the sequence are known, it is copied - into chromosome's head shifting existing elements in the head. - - - - - - Crossover operator. - - - Pair chromosome to crossover with. - - The method performs one-point or two-point crossover selecting - them randomly with equal probability. - - - - - One-point recombination (crossover). - - - Pair chromosome to crossover with. - - - - - Two point recombination (crossover). - - - Pair chromosome to crossover with. - - - - - Swap parts of two chromosomes. - - - First chromosome participating in genes' interchange. - Second chromosome participating in genes' interchange. - Index of the first gene in the interchange sequence. - Length of the interchange sequence - number of genes - to interchange. - - The method performs interchanging of genes between two chromosomes - starting from the position. - - - - diff --git a/Externals/AForge.NET/AForge.Imaging.Formats.dll b/Externals/AForge.NET/AForge.Imaging.Formats.dll deleted file mode 100644 index 9269562fe..0000000000 Binary files a/Externals/AForge.NET/AForge.Imaging.Formats.dll and /dev/null differ diff --git a/Externals/AForge.NET/AForge.Imaging.Formats.xml b/Externals/AForge.NET/AForge.Imaging.Formats.xml deleted file mode 100644 index 7c98a77d7..0000000000 --- a/Externals/AForge.NET/AForge.Imaging.Formats.xml +++ /dev/null @@ -1,576 +0,0 @@ - - - - AForge.Imaging.Formats - - - - - Image decoder to decode different custom image file formats. - - - The class represent a help class, which simplifies decoding of image - files finding appropriate image decoder automatically (using list of registered - image decoders). Instead of using required image decoder directly, users may use this - class, which will find required decoder by file's extension. - - By default the class registers on its own all decoders, which are available in - AForge.Imaging.Formats library. If user has implementation of his own image decoders, he - needs to register them using method to be able to use them through - the class. - - If the class can not find appropriate decode in the list of registered - decoders, it passes file to .NET's image decoder for decoding. - - Sample usage: - - // sample file name - string fileName = "myFile.pnm"; - // decode image file - Bitmap = ImageDecoder.DecodeFromFile( fileName ); - - - - - - - - - - Register image decoder for a specified file extension. - - - File extension to register decoder for ("bmp", for example). - Image decoder to use for the specified file extension. - - The method allows to register image decoder object, which should be used - to decode images from files with the specified extension. - - - - - Decode first frame for the specified file. - - - File name to read image from. - - Return decoded image. In the case if file format support multiple - frames, the method return the first frame. - - The method uses table of registered image decoders to find the one, - which should be used for the specified file. If there is not appropriate decoder - found, the method uses default .NET's image decoding routine (see - ). - - - - - Decode first frame for the specified file. - - - File name to read image from. - Information about the decoded image. - - Return decoded image. In the case if file format support multiple - frames, the method return the first frame. - - The method uses table of registered image decoders to find the one, - which should be used for the specified file. If there is not appropriate decoder - found, the method uses default .NET's image decoding routine (see - ). - - - - - Information about PNM image's frame. - - - - - Information about image's frame. - - - This is a base class, which keeps basic information about image, like its width, - height, etc. Classes, which inherit from this, may define more properties describing certain - image formats. - - - - - Image's width. - - - - - Image's height. - - - - - Number of bits per image's pixel. - - - - - Frame's index. - - - - - Total frames in the image. - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Image's width. - Image's height. - Number of bits per image's pixel. - Frame's index. - Total frames in the image. - - - - - Creates a new object that is a copy of the current instance. - - - A new object that is a copy of this instance. - - - - - Image's width. - - - - - Image's height. - - - - - Number of bits per image's pixel. - - - - - Frame's index. - - - Some image formats support storing multiple frames in one image file. - The property specifies index of a particular frame. - - - - - Total frames in the image. - - - Some image formats support storing multiple frames in one image file. - The property specifies total number of frames in image file. - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Image's width. - Image's height. - Number of bits per image's pixel. - Frame's index. - Total frames in the image. - - - - - Creates a new object that is a copy of the current instance. - - - A new object that is a copy of this instance. - - - - - PNM file version (format), [1, 6]. - - - - - Maximum pixel's value in source PNM image. - - - The value is used to scale image's data converting them - from original data range to the range of - supported bits per pixel format. - - - - - PNM image format decoder. - - - The PNM (an acronym derived from "Portable Any Map") format is an - abstraction of the PBM, PGM and PPM formats. I.e. the name "PNM" refers collectively - to PBM (binary images), PGM (grayscale images) and PPM (color image) image formats. - - Image in PNM format can be found in different scientific databases and laboratories, - for example Yale Face Database and AT&T Face Database. - - Only PNM images of P5 (binary encoded PGM) and P6 (binary encoded PPM) formats - are supported at this point. - - The maximum supported pixel value is 255 at this point. - - The class supports only one-frame PNM images. As it is specified in format - specification, the multi-frame PNM images has appeared starting from 2000. - - - - - - - Image decoder interface, which specifies set of methods, which should be - implemented by image decoders for different file formats. - - - The interface specifies set of methods, which are suitable not - only for simple one-frame image formats. The interface also defines methods - to work with image formats designed to store multiple frames and image formats - which provide different type of image description (like acquisition - parameters, etc). - - - - - - Decode first frame of image from the specified stream. - - - Source stream, which contains encoded image. - - Returns decoded image frame. - - - For one-frame image formats the method is supposed to decode single - available frame. For multi-frame image formats the first frame should be - decoded. - - Implementations of this method may throw - exception to report about unrecognized image - format, exception to report about incorrectly - formatted image or exception to report if - certain formats are not supported. - - - - - - Open specified stream. - - - Stream to open. - - Returns number of images found in the specified stream. - - Implementation of this method is supposed to read image's header, - checking for correct image format and reading its atributes. - - Implementations of this method may throw - exception to report about unrecognized image - format, exception to report about incorrectly - formatted image or exception to report if - certain formats are not supported. - - - - - - Decode specified frame. - - - Image frame to decode. - Receives information about decoded frame. - - Returns decoded frame. - - Implementations of this method may throw - exception in the case if no image - stream was opened previously, in the - case if stream does not contain frame with specified index or - exception to report about incorrectly formatted image. - - - - - - Close decoding of previously opened stream. - - - Implementations of this method don't close stream itself, but just close - decoding cleaning all associated data with it. - - - - - Decode first frame of PNM image. - - - Source stream, which contains encoded image. - - Returns decoded image frame. - - Not a PNM image format. - Format of the PNM image is not supported. - The stream contains invalid (broken) PNM image. - - - - - Open specified stream. - - - Stream to open. - - Returns number of images found in the specified stream. - - Not a PNM image format. - Format of the PNM image is not supported. - The stream contains invalid (broken) PNM image. - - - - - Decode specified frame. - - - Image frame to decode. - Receives information about decoded frame. - - Returns decoded frame. - - No image stream was opened previously. - Stream does not contain frame with specified index. - The stream contains invalid (broken) PNM image. - - - - - Close decoding of previously opened stream. - - - The method does not close stream itself, but just closes - decoding cleaning all associated data with it. - - - - - Information about FITS image's frame. - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Image's width. - Image's height. - Number of bits per image's pixel. - Frame's index. - Total frames in the image. - - - - - Creates a new object that is a copy of the current instance. - - - A new object that is a copy of this instance. - - - - - Original bits per pixel. - - - The property specifies original number of bits per image's pixel. For - FITS images the value may be equal to 8, 16, 32, -32 (32 bit image with float data - type for pixel encoding), -64 (64 bit image with double data type for pixel encoding). - - - - - - Minimum data value found during parsing FITS image. - - - Minimum and maximum data values are used to scale image's data converting - them from original bits per pixel format to - supported bits per pixel format. - - - - - Maximum data value found during parsing FITS image. - - - Minimum and maximum data values are used to scale image's data converting - them from original bits per pixel format to - supported bits per pixel format. - - - - - Telescope used for object's observation. - - - - - Object acquired during observation. - - - - - Observer doing object's acquiring. - - - - - Instrument used for observation. - - - - - FITS image format decoder. - - - The FITS (an acronym derived from "Flexible Image Transport System") format - is an astronomical image and table format created and supported by NASA. FITS is the most - commonly used in astronomy and is designed specifically for scientific data. Different astronomical - organizations keep their images acquired using telescopes and other equipment in FITS format. - - The class extracts image frames only from the main data section of FITS file. - 2D (single frame) and 3D (series of frames) data structures are supported. - - During image reading/parsing, its data are scaled using minimum and maximum values of - the source image data. FITS tags are not used for this purpose - data are scaled from the - [min, max] range found to the range of supported image format ([0, 255] for 8 bpp grayscale - or [0, 65535] for 16 bpp grayscale image). - - - - - - Decode first frame of FITS image. - - - Source stream, which contains encoded image. - - Returns decoded image frame. - - Not a FITS image format. - Format of the FITS image is not supported. - The stream contains invalid (broken) FITS image. - - - - - Open specified stream. - - - Stream to open. - - Returns number of images found in the specified stream. - - Not a FITS image format. - Format of the FITS image is not supported. - The stream contains invalid (broken) FITS image. - - - - - Decode specified frame. - - - Image frame to decode. - Receives information about decoded frame. - - Returns decoded frame. - - No image stream was opened previously. - Stream does not contain frame with specified index. - The stream contains invalid (broken) FITS image. - - - - - Close decoding of previously opened stream. - - - The method does not close stream itself, but just closes - decoding cleaning all associated data with it. - - - - - Set of tools used internally in AForge.Imaging.Formats library. - - - - - Create and initialize new grayscale image. - - - Image width. - Image height. - - Returns new created grayscale image. - - AForge.Imaging.Image.CreateGrayscaleImage() function - could be used instead, which does the some. But it was not used to get - rid of dependency on AForge.Imaing library. - - - - - Read specified amount of bytes from the specified stream. - - - Source sream to read data from. - Buffer to read data into. - Offset in buffer to put data into. - Number of bytes to read. - - Returns total number of bytes read. It may be smaller than requested amount only - in the case if end of stream was reached. - - This tool function guarantees that requested number of bytes - was read from the source stream (.NET streams don't guarantee this and may return less bytes - than it was requested). Only in the case if end of stream was reached, the function - may return with less bytes read. - - - - - diff --git a/Externals/AForge.NET/AForge.Imaging.IPPrototyper.dll b/Externals/AForge.NET/AForge.Imaging.IPPrototyper.dll deleted file mode 100644 index ad062415b..0000000000 Binary files a/Externals/AForge.NET/AForge.Imaging.IPPrototyper.dll and /dev/null differ diff --git a/Externals/AForge.NET/AForge.Imaging.dll b/Externals/AForge.NET/AForge.Imaging.dll deleted file mode 100644 index 150e87d42..0000000000 Binary files a/Externals/AForge.NET/AForge.Imaging.dll and /dev/null differ diff --git a/Externals/AForge.NET/AForge.Imaging.xml b/Externals/AForge.NET/AForge.Imaging.xml deleted file mode 100644 index bd85baf1c..0000000000 --- a/Externals/AForge.NET/AForge.Imaging.xml +++ /dev/null @@ -1,19015 +0,0 @@ - - - - AForge.Imaging - - - - - Corners detector's interface. - - - The interface specifies set of methods, which should be implemented by different - corners detection algorithms. - - - - - Process image looking for corners. - - - Source image to process. - - Returns list of found corners (X-Y coordinates). - - - - - Process image looking for corners. - - - Source image data to process. - - Returns list of found corners (X-Y coordinates). - - - - - Process image looking for corners. - - - Unmanaged source image to process. - - Returns list of found corners (X-Y coordinates). - - - - - Shrink an image by removing specified color from its boundaries. - - - Removes pixels with specified color from image boundaries making - the image smaller in size. - - The filter accepts 8 bpp grayscale and 24 bpp color images for processing. - - Sample usage: - - // create filter - Shrink filter = new Shrink( Color.Black ); - // apply the filter - Bitmap newImage = filter.Apply( image ); - - - Initial image: - - Result image: - - - - - - - Base class for filters, which may produce new image of different size as a - result of image processing. - - - The abstract class is the base class for all filters, which - do image processing creating new image of the size, which may differ from the - size of source image. Filters based on this class cannot be applied directly - to the source image, which is kept unchanged. - - The base class itself does not define supported pixel formats of source - image and resulting pixel formats of destination image. Filters inheriting from - this base class, should specify supported pixel formats and their transformations - overriding abstract property. - - - - - - Image processing filter interface. - - - The interface defines the set of methods, which should be - provided by all image processing filters. Methods of this interface - keep the source image unchanged and returt the result of image processing - filter as new image. - - - - - - - - Apply filter to an image. - - - Source image to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The method keeps the source image unchanged and returns - the result of image processing filter as new image. - - - - - Apply filter to an image. - - - Source image to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The filter accepts bitmap data as input and returns the result - of image processing filter as new image. The source image data are kept - unchanged. - - - - - Apply filter to an image. - - - Image in unmanaged memory. - - Returns filter's result obtained by applying the filter to - the source image. - - The method keeps the source image unchanged and returns - the result of image processing filter as new image. - - - - - Apply filter to an image. - - - Source image to be processed. - Destination image to store filter's result. - - The method keeps the source image unchanged and puts the - the result of image processing filter into destination image. - - The destination image must have the size, which is expected by - the filter. - - - In the case if destination image has incorrect - size. - - - - - Interface which provides information about image processing filter. - - - The interface defines set of properties, which provide different type - of information about image processing filters implementing interface - or another filter's interface. - - - - - Format translations dictionary. - - - The dictionary defines, which pixel formats are supported for - source images and which pixel format will be used for resulting image. - - - Keys of this dictionary defines all pixel formats which are supported for source - images, but corresponding values define what will be resulting pixel format. For - example, if value Format16bppGrayScale - is put into the dictionary with the - Format48bppRgb key, then it means - that the filter accepts color 48 bpp image and produces 16 bpp grayscale image as a result - of image processing. - - The information provided by this property is mostly actual for filters, which can not - be applied directly to the source image, but provide new image a result. Since usually all - filters implement interface, the information provided by this property - (if filter also implements interface) may be useful to - user to resolve filter's capabilities. - - Sample usage: - - // get filter's IFilterInformation interface - IFilterInformation info = (IFilterInformation) filter; - // check if the filter supports our image's format - if ( info.FormatTranslations.ContainsKey( image.PixelFormat ) - { - // format is supported, check what will be result of image processing - PixelFormat resultingFormat = info.FormatTranslations[image.PixelFormat]; - } - /// - - - - - - Apply filter to an image. - - - Source image to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The method keeps the source image unchanged and returns - the result of image processing filter as new image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image. - - - Source image to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The filter accepts bitmap data as input and returns the result - of image processing filter as new image. The source image data are kept - unchanged. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image in unmanaged memory. - - - Source image in unmanaged memory to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The method keeps the source image unchanged and returns - the result of image processing filter as new image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image in unmanaged memory. - - - Source image in unmanaged memory to apply filter to. - Destination image in unmanaged memory to put result into. - - The method keeps the source image unchanged and puts result of image processing - into destination image. - - The destination image must have the same width and height as source image. Also - destination image must have pixel format, which is expected by particular filter (see - property for information about pixel format conversions). - - - Unsupported pixel format of the source image. - Incorrect destination pixel format. - Destination image has wrong width and/or height. - - - - - Calculates new image size. - - - Source image data. - - New image size - size of the destination image. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - - - - Format translations dictionary. - - - The dictionary defines, which pixel formats are supported for - source images and which pixel format will be used for resulting image. - - - See for more information. - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Color to remove from boundaries. - - - - - Calculates new image size. - - - Source image data. - - New image size - size of the destination image. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - - - - Format translations dictionary. - - - - - Color to remove from boundaries. - - - - - - Rotate image using nearest neighbor algorithm. - - - The class implements image rotation filter using nearest - neighbor algorithm, which does not assume any interpolation. - - Rotation is performed in counterclockwise direction. - - The filter accepts 8/16 bpp grayscale images and 24/48 bpp color image - for processing. - - Sample usage: - - // create filter - rotate for 30 degrees keeping original image size - RotateNearestNeighbor filter = new RotateNearestNeighbor( 30, true ); - // apply the filter - Bitmap newImage = filter.Apply( image ); - - - Initial image: - - Result image: - - - - - - - - - - Base class for image rotation filters. - - - The abstract class is the base class for all filters, - which implement rotating algorithms. - - - - - Rotation angle. - - - - - Keep image size or not. - - - - - Fill color. - - - - - Initializes a new instance of the class. - - - Rotation angle. - - This constructor sets property to false. - - - - - - Initializes a new instance of the class. - - - Rotation angle. - Keep image size or not. - - - - - Calculates new image size. - - - Source image data. - - New image size - size of the destination image. - - - - - Rotation angle, [0, 360]. - - - - - Keep image size or not. - - - The property determines if source image's size will be kept - as it is or not. If the value is set to false, then the new image will have - new dimension according to rotation angle. If the valus is set to - true, then the new image will have the same size, which means that some parts - of the image may be clipped because of rotation. - - - - - - Fill color. - - - The fill color is used to fill areas of destination image, - which don't have corresponsing pixels in source image. - - - - - Initializes a new instance of the class. - - - Rotation angle. - - This constructor sets property to - . - - - - - - Initializes a new instance of the class. - - - Rotation angle. - Keep image size or not. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - - - - Format translations dictionary. - - - - - Conservative smoothing. - - - The filter implements conservative smoothing, which is a noise reduction - technique that derives its name from the fact that it employs a simple, fast filtering - algorithm that sacrifices noise suppression power in order to preserve the high spatial - frequency detail (e.g. sharp edges) in an image. It is explicitly designed to remove noise - spikes - isolated pixels of exceptionally low or high pixel intensity - (salt and pepper noise). - - If the filter finds a pixel which has minimum/maximum value compared to its surrounding - pixel, then its value is replaced by minimum/maximum value of those surrounding pixel. - For example, lets suppose the filter uses kernel size of 3x3, - which means each pixel has 8 surrounding pixel. If pixel's value is smaller than any value - of surrounding pixels, then the value of the pixel is replaced by minimum value of those surrounding - pixels. - - The filter accepts 8 bpp grayscale images and 24/32 bpp - color images for processing. - - Sample usage: - - // create filter - ConservativeSmoothing filter = new ConservativeSmoothing( ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - Base class for filters, which require source image backup to make them applicable to - source image (or its part) directly. - - - The base class is used for filters, which can not do - direct manipulations with source image. To make effect of in-place filtering, - these filters create a background copy of the original image (done by this - base class) and then do manipulations with it putting result back to the original - source image. - - The background copy of the source image is created only in the case of in-place - filtering. Otherwise background copy is not created - source image is processed and result is - put to destination image. - - The base class is for those filters, which support as filtering entire image, as - partial filtering of specified rectangle only. - - - - - - In-place filter interface. - - - The interface defines the set of methods, which should be - implemented by filters, which are capable to do image processing - directly on the source image. Not all image processing filters - can be applied directly to the source image - only filters, which do not - change image's dimension and pixel format, can be applied directly to the - source image. - - - - - - - - Apply filter to an image. - - - Image to apply filter to. - - The method applies filter directly to the provided image data. - - - - - Apply filter to an image. - - - Image to apply filter to. - - The method applies filter directly to the provided image data. - - - - - Apply filter to an image in unmanaged memory. - - - Image in unmanaged memory. - - The method applies filter directly to the provided image data. - - - - - In-place partial filter interface. - - - The interface defines the set of methods, which should be - implemented by filters, which are capable to do image processing - directly on the source image. Not all image processing filters - can be applied directly to the source image - only filters, which do not - change image dimension and pixel format, can be applied directly to the - source image. - - The interface also supports partial image filtering, allowing to specify - image rectangle, which should be filtered. - - - - - - - - - Apply filter to an image or its part. - - - Image to apply filter to. - Image rectangle for processing by filter. - - The method applies filter directly to the provided image data. - - - - - Apply filter to an image or its part. - - - Image to apply filter to. - Image rectangle for processing by filter. - - The method applies filter directly to the provided image data. - - - - - Apply filter to an image in unmanaged memory. - - - Image in unmanaged memory. - Image rectangle for processing by filter. - - The method applies filter directly to the provided image. - - - - - Apply filter to an image. - - - Source image to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The method keeps the source image unchanged and returns - the result of image processing filter as new image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image. - - - Source image to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The filter accepts bitmap data as input and returns the result - of image processing filter as new image. The source image data are kept - unchanged. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image in unmanaged memory. - - - Source image in unmanaged memory to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The method keeps the source image unchanged and returns - the result of image processing filter as new image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image in unmanaged memory. - - - Source image in unmanaged memory to apply filter to. - Destination image in unmanaged memory to put result into. - - The method keeps the source image unchanged and puts result of image processing - into destination image. - - The destination image must have the same width and height as source image. Also - destination image must have pixel format, which is expected by particular filter (see - property for information about pixel format conversions). - - - Unsupported pixel format of the source image. - Incorrect destination pixel format. - Destination image has wrong width and/or height. - - - - - Apply filter to an image. - - - Image to apply filter to. - - The method applies the filter directly to the provided source image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image. - - - Image data to apply filter to. - - The method applies the filter directly to the provided source image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an unmanaged image. - - - Unmanaged image to apply filter to. - - The method applies the filter directly to the provided source unmanaged image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image or its part. - - - Image to apply filter to. - Image rectangle for processing by the filter. - - The method applies the filter directly to the provided source image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image or its part. - - - Image data to apply filter to. - Image rectangle for processing by the filter. - - The method applies the filter directly to the provided source image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an unmanaged image or its part. - - - Unmanaged image to apply filter to. - Image rectangle for processing by the filter. - - The method applies the filter directly to the provided source image. - - Unsupported pixel format of the source image. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - The dictionary defines, which pixel formats are supported for - source images and which pixel format will be used for resulting image. - - - See for more information. - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Kernel size. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Kernel size, [3, 25]. - - - Determines the size of pixel's square used for smoothing. - - Default value is set to 3. - - The value should be odd. - - - - - - Rotate RGB channels. - - - The filter rotates RGB channels: red channel is replaced with green, - green channel is replaced with blue, blue channel is replaced with red. - - The filter accepts 24/32 bpp color images for processing. - - Sample usage: - - // create filter - RotateChannels filter = new RotateChannels( ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - Base class for filters, which may be applied directly to the source image or its part. - - - The abstract class is the base class for all filters, which can - be applied to an image producing new image as a result of image processing or - applied directly to the source image (or its part) without changing its size and - pixel format. - - - - - - Apply filter to an image. - - - Source image to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The method keeps the source image unchanged and returns - the result of image processing filter as new image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image. - - - Source image to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The filter accepts bitmap data as input and returns the result - of image processing filter as new image. The source image data are kept - unchanged. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image in unmanaged memory. - - - Source image in unmanaged memory to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The method keeps the source image unchanged and returns - the result of image processing filter as new image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image in unmanaged memory. - - - Source image in unmanaged memory to apply filter to. - Destination image in unmanaged memory to put result into. - - The method keeps the source image unchanged and puts result of image processing - into destination image. - - The destination image must have the same width and height as source image. Also - destination image must have pixel format, which is expected by particular filter (see - property for information about pixel format conversions). - - - Unsupported pixel format of the source image. - Incorrect destination pixel format. - Destination image has wrong width and/or height. - - - - - Apply filter to an image. - - - Image to apply filter to. - - The method applies the filter directly to the provided source image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image. - - - Image data to apply filter to. - - The method applies the filter directly to the provided source image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an unmanaged image. - - - Unmanaged image to apply filter to. - - The method applies the filter directly to the provided source unmanaged image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image or its part. - - - Image to apply filter to. - Image rectangle for processing by the filter. - - The method applies the filter directly to the provided source image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image or its part. - - - Image data to apply filter to. - Image rectangle for processing by the filter. - - The method applies the filter directly to the provided source image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an unmanaged image or its part. - - - Unmanaged image to apply filter to. - Image rectangle for processing by the filter. - - The method applies the filter directly to the provided source image. - - Unsupported pixel format of the source image. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - The dictionary defines, which pixel formats are supported for - source images and which pixel format will be used for resulting image. - - - See for more information. - - - - - - Initializes a new instance of the class. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Gamma correction filter. - - - The filter performs gamma correction - of specified image in RGB color space. Each pixels' value is converted using the Vout=Ving - equation, where g is gamma value. - - The filter accepts 8 bpp grayscale and 24 bpp color images for processing. - - Sample usage: - - // create filter - GammaCorrection filter = new GammaCorrection( 0.5 ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Gamma value. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Gamma value, [0.1, 5.0]. - - - Default value is set to 2.2. - - - - - Brightness adjusting in RGB color space. - - - The filter operates in RGB color space and adjusts - pixels' brightness by increasing every pixel's RGB values by the specified - adjust value. The filter is based on - filter and simply sets all input ranges to (0, 255-) and - all output range to (, 255) in the case if the adjust value is positive. - If the adjust value is negative, then all input ranges are set to - (-, 255 ) and all output ranges are set to - ( 0, 255+). - - See documentation for more information about the base filter. - - The filter accepts 8 bpp grayscale and 24/32 bpp color images for processing. - - Sample usage: - - // create filter - BrightnessCorrection filter = new BrightnessCorrection( -50 ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Brightness adjust value. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Brightness adjust value, [-255, 255]. - - - Default value is set to 10, which corresponds to increasing - RGB values of each pixel by 10. - - - - - Format translations dictionary. - - - See - documentation for additional information. - - - - - Dithering using Stucki error diffusion. - - - The filter represents binarization filter, which is based on - error diffusion dithering with Stucki coefficients. Error is diffused - on 12 neighbor pixels with next coefficients: - - | * | 8 | 4 | - | 2 | 4 | 8 | 4 | 2 | - | 1 | 2 | 4 | 2 | 1 | - - / 42 - - - The filter accepts 8 bpp grayscale images for processing. - - Sample usage: - - // create filter - StuckiDithering filter = new StuckiDithering( ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - - - - Base class for error diffusion dithering, where error is diffused to - adjacent neighbor pixels. - - - The class does error diffusion to adjacent neighbor pixels - using specified set of coefficients. These coefficients are represented by - 2 dimensional jugged array, where first array of coefficients is for - right-standing pixels, but the rest of arrays are for bottom-standing pixels. - All arrays except the first one should have odd number of coefficients. - - Suppose that error diffusion coefficients are represented by the next - jugged array: - - - int[][] coefficients = new int[2][] { - new int[1] { 7 }, - new int[3] { 3, 5, 1 } - }; - - - The above coefficients are used to diffuse error over the next neighbor - pixels (* marks current pixel, coefficients are placed to corresponding - neighbor pixels): - - | * | 7 | - | 3 | 5 | 1 | - - / 16 - - - The filter accepts 8 bpp grayscale images for processing. - - Sample usage: - - // create filter - ErrorDiffusionToAdjacentNeighbors filter = new ErrorDiffusionToAdjacentNeighbors( - new int[3][] { - new int[2] { 5, 3 }, - new int[5] { 2, 4, 5, 4, 2 }, - new int[3] { 2, 3, 2 } - } ); - // apply the filter - filter.ApplyInPlace( image ); - - - - - - - Base class for error diffusion dithering. - - - The class is the base class for binarization algorithms based on - error diffusion. - - Binarization with error diffusion in its idea is similar to binarization based on thresholding - of pixels' cumulative value (see ). Each pixel is binarized based not only - on its own value, but on values of some surrounding pixels. During pixel's binarization, its binarization - error is distributed (diffused) to some neighbor pixels with some coefficients. This error diffusion - updates neighbor pixels changing their values, what affects their upcoming binarization. Error diffuses - only on unprocessed yet neighbor pixels, which are right and bottom pixels usually (in the case if image - processing is done from upper left corner to bottom right corner). Binarization error equals - to processing pixel value, if it is below threshold value, or pixel value minus 255 otherwise. - - The filter accepts 8 bpp grayscale images for processing. - - - - - - Current processing X coordinate. - - - - - Current processing Y coordinate. - - - - - Processing X start position. - - - - - Processing Y start position. - - - - - Processing X stop position. - - - - - Processing Y stop position. - - - - - Processing image's stride (line size). - - - - - Initializes a new instance of the class. - - - - - - Do error diffusion. - - - Current error value. - Pointer to current processing pixel. - - All parameters of the image and current processing pixel's coordinates - are initialized in protected members. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Threshold value. - - - Default value is 128. - - - - - Format translations dictionary. - - - - - Initializes a new instance of the class. - - - Diffusion coefficients. - - - - - Do error diffusion. - - - Current error value. - Pointer to current processing pixel. - - All parameters of the image and current processing pixel's coordinates - are initialized by base class. - - - - - Diffusion coefficients. - - - Set of coefficients, which are used for error diffusion to - pixel's neighbors. - - - - - Initializes a new instance of the class. - - - - - - Interpolation routines. - - - - - - Bicubic kernel. - - - X value. - - Bicubic cooefficient. - - The function implements bicubic kernel W(x) as described on - Wikipedia - (coefficient a is set to -0.5). - - - - - Binary erosion operator from Mathematical Morphology with 3x3 structuring element. - - - The filter represents an optimized version of - filter, which is aimed for binary images (containing black and white pixels) processed - with 3x3 structuring element. This makes this filter ideal for removing noise in binary - images – it removes all white pixels, which are neighbouring with at least one blank pixel. - - - See filter, which represents generic version of - erosion filter supporting custom structuring elements and wider range of image formats. - - The filter accepts 8 bpp grayscale (binary) images for processing. - - - - - - - - Initializes a new instance of the class. - - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - Image rectangle for processing by the filter. - - Processing rectangle mast be at least 3x3 in size. - - - - - Format translations dictionary. - - - - - Filter iterator. - - - Filter iterator performs specified amount of filter's iterations. - The filter take the specified base filter and applies it - to source image specified amount of times. - - The filter itself does not have any restrictions to pixel format of source - image. This is set by base filter. - - The filter does image processing using only - interface of the specified base filter. This means - that this filter may not utilize all potential features of the base filter, like - in-place processing (see ) and region based processing - (see ). To utilize those features, it is required to - do filter's iteration manually. - - Sample usage (morphological thinning): - - // create filter sequence - FiltersSequence filterSequence = new FiltersSequence( ); - // add 8 thinning filters with different structuring elements - filterSequence.Add( new HitAndMiss( - new short [,] { { 0, 0, 0 }, { -1, 1, -1 }, { 1, 1, 1 } }, - HitAndMiss.Modes.Thinning ) ); - filterSequence.Add( new HitAndMiss( - new short [,] { { -1, 0, 0 }, { 1, 1, 0 }, { -1, 1, -1 } }, - HitAndMiss.Modes.Thinning ) ); - filterSequence.Add( new HitAndMiss( - new short [,] { { 1, -1, 0 }, { 1, 1, 0 }, { 1, -1, 0 } }, - HitAndMiss.Modes.Thinning ) ); - filterSequence.Add( new HitAndMiss( - new short [,] { { -1, 1, -1 }, { 1, 1, 0 }, { -1, 0, 0 } }, - HitAndMiss.Modes.Thinning ) ); - filterSequence.Add( new HitAndMiss( - new short [,] { { 1, 1, 1 }, { -1, 1, -1 }, { 0, 0, 0 } }, - HitAndMiss.Modes.Thinning ) ); - filterSequence.Add( new HitAndMiss( - new short [,] { { -1, 1, -1 }, { 0, 1, 1 }, { 0, 0, -1 } }, - HitAndMiss.Modes.Thinning ) ); - filterSequence.Add( new HitAndMiss( - new short [,] { { 0, -1, 1 }, { 0, 1, 1 }, { 0, -1, 1 } }, - HitAndMiss.Modes.Thinning ) ); - filterSequence.Add( new HitAndMiss( - new short [,] { { 0, 0, -1 }, { 0, 1, 1 }, { -1, 1, -1 } }, - HitAndMiss.Modes.Thinning ) ); - // create filter iterator for 10 iterations - FilterIterator filter = new FilterIterator( filterSequence, 10 ); - // apply the filter - Bitmap newImage = filter.Apply( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - Filter to iterate. - - - - - Initializes a new instance of the class. - - - Filter to iterate. - Iterations amount. - - - - - Apply filter to an image. - - - Source image to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The method keeps the source image unchanged and returns - the result of image processing filter as new image. - - - - - Apply filter to an image. - - - Source image to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The filter accepts bitmap data as input and returns the result - of image processing filter as new image. The source image data are kept - unchanged. - - - - - Apply filter to an image in unmanaged memory. - - - Source image in unmanaged memory to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The method keeps the source image unchanged and returns - the result of image processing filter as new image. - - - - - Apply filter to an image in unmanaged memory. - - - Source image in unmanaged memory to apply filter to. - Destination image in unmanaged memory to put result into. - - The method keeps the source image unchanged and puts result of image processing - into destination image. - - The destination image must have the same width and height as source image. Also - destination image must have pixel format, which is expected by particular filter (see - property for information about pixel format conversions). - - - - - - Format translations dictionary. - - - See - documentation for additional information. - - The filter provides format translation dictionary taken from - filter. - - - - - - Base filter. - - - The base filter is the filter to be applied specified amount of iterations to - a specified image. - - - - - Iterations amount, [1, 255]. - - - The amount of times to apply specified filter to a specified image. - - Default value is set to 1. - - - - - - Threshold binarization. - - - The filter does image binarization using specified threshold value. All pixels - with intensities equal or higher than threshold value are converted to white pixels. All other - pixels with intensities below threshold value are converted to black pixels. - - The filter accepts 8 and 16 bpp grayscale images for processing. - - Since the filter can be applied as to 8 bpp and to 16 bpp images, - the value should be set appropriately to the pixel format. - In the case of 8 bpp images the threshold value is in the [0, 255] range, but in the case - of 16 bpp images the threshold value is in the [0, 65535] range. - - Sample usage: - - // create filter - Threshold filter = new Threshold( 100 ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - Threshold value. - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Threshold value. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Threshold value. - - - Default value is set to 128. - - - - - Base class for filters, which may be applied directly to the source image. - - - The abstract class is the base class for all filters, which can - be applied to an image producing new image as a result of image processing or - applied directly to the source image without changing its size and pixel format. - - - - - - Apply filter to an image. - - - Source image to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The method keeps the source image unchanged and returns - the result of image processing filter as new image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image. - - - Source image to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The filter accepts bitmap data as input and returns the result - of image processing filter as new image. The source image data are kept - unchanged. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image in unmanaged memory. - - - Source image in unmanaged memory to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The method keeps the source image unchanged and returns - the result of image processing filter as new image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image in unmanaged memory. - - - Source image in unmanaged memory to apply filter to. - Destination image in unmanaged memory to put result into. - - The method keeps the source image unchanged and puts result of image processing - into destination image. - - The destination image must have the same width and height as source image. Also - destination image must have pixel format, which is expected by particular filter (see - property for information about pixel format conversions). - - - Unsupported pixel format of the source image. - Incorrect destination pixel format. - Destination image has wrong width and/or height. - - - - - Apply filter to an image. - - - Image to apply filter to. - - The method applies the filter directly to the provided source image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image. - - - Image data to apply filter to. - - The method applies the filter directly to the provided source image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an unmanaged image. - - - Unmanaged image to apply filter to. - - The method applies the filter directly to the provided source unmanaged image. - - Unsupported pixel format of the source image. - - - - - Process the filter on the specified image. - - - Source image data. - - - - - Format translations dictionary. - - - The dictionary defines, which pixel formats are supported for - source images and which pixel format will be used for resulting image. - - - See for more information. - - - - - - Add fillter - add pixel values of two images. - - - The add filter takes two images (source and overlay images) - of the same size and pixel format and produces an image, where each pixel equals - to the sum value of corresponding pixels from provided images (if sum is greater - than maximum allowed value, 255 or 65535, then it is truncated to that maximum). - - The filter accepts 8 and 16 bpp grayscale images and 24, 32, 48 and 64 bpp - color images for processing. - - Sample usage: - - // create filter - Add filter = new Add( overlayImage ); - // apply the filter - Bitmap resultImage = filter.Apply( sourceImage ); - - - Source image: - - Overlay image: - - Result image: - - - - - - - - - - - - Base class for filters, which operate with two images of the same size and format and - may be applied directly to the source image. - - - The abstract class is the base class for all filters, which can - be applied to an image producing new image as a result of image processing or - applied directly to the source image without changing its size and pixel format. - - The base class is aimed for such type of filters, which require additional image - to process the source image. The additional image is set by - or property and must have the same size and pixel format - as source image. See documentation of particular inherited class for information - about overlay image purpose. - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Overlay image. - - - - - Initializes a new instance of the class. - - - Unmanaged overlay image. - - - - - Process the filter on the specified image. - - - Source image data. - - Source and overlay images have different pixel formats and/or size. - Overlay image is not set. - - - - - Process the filter on the specified image. - - - Source image data. - Overlay image data. - - Overlay image size and pixel format is checked by this base class, before - passing execution to inherited class. - - - - - Overlay image. - - - - The property sets an overlay image, which will be used as the second image required - to process source image. See documentation of particular inherited class for information - about overlay image purpose. - - - Overlay image must have the same size and pixel format as source image. - Otherwise exception will be generated when filter is applied to source image. - - Setting this property will clear the property - - only one overlay image is allowed: managed or unmanaged. - - - - - - Unmanaged overlay image. - - - - The property sets an overlay image, which will be used as the second image required - to process source image. See documentation of particular inherited class for information - about overlay image purpose. - - - Overlay image must have the same size and pixel format as source image. - Otherwise exception will be generated when filter is applied to source image. - - Setting this property will clear the property - - only one overlay image is allowed: managed or unmanaged. - - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Overlay image. - - - - - Initializes a new instance of the class. - - - Unmanaged overlay image. - - - - - Process the filter on the specified image. - - - Source image data. - Overlay image data. - - - - - Format translations dictionary. - - - - - Color dithering using Stucki error diffusion. - - - The image processing routine represents color dithering algorithm, which is based on - error diffusion dithering with Stucki coefficients. Error is diffused - on 12 neighbor pixels with next coefficients: - - | * | 8 | 4 | - | 2 | 4 | 8 | 4 | 2 | - | 1 | 2 | 4 | 2 | 1 | - - / 42 - - - The image processing routine accepts 24/32 bpp color images for processing. As a result this routine - produces 4 bpp or 8 bpp indexed image, which depends on size of the specified - color table - 4 bpp result for - color tables with 16 colors or less; 8 bpp result for larger color tables. - - Sample usage: - - // create color image quantization routine - ColorImageQuantizer ciq = new ColorImageQuantizer( new MedianCutQuantizer( ) ); - // create 64 colors table - Color[] colorTable = ciq.CalculatePalette( image, 64 ); - // create dithering routine - StuckiColorDithering dithering = new StuckiColorDithering( ); - dithering.ColorTable = colorTable; - // apply the dithering routine - Bitmap newImage = dithering.Apply( image ); - - - Initial image: - - Result image: - - - - - - - - - - - - Base class for error diffusion color dithering, where error is diffused to - adjacent neighbor pixels. - - - The class does error diffusion to adjacent neighbor pixels - using specified set of coefficients. These coefficients are represented by - 2 dimensional jugged array, where first array of coefficients is for - right-standing pixels, but the rest of arrays are for bottom-standing pixels. - All arrays except the first one should have odd number of coefficients. - - Suppose that error diffusion coefficients are represented by the next - jugged array: - - - int[][] coefficients = new int[2][] { - new int[1] { 7 }, - new int[3] { 3, 5, 1 } - }; - - - The above coefficients are used to diffuse error over the next neighbor - pixels (* marks current pixel, coefficients are placed to corresponding - neighbor pixels): - - | * | 7 | - | 3 | 5 | 1 | - - / 16 - - - The image processing routine accepts 24/32 bpp color images for processing. - - Sample usage: - - // create dithering routine - ColorErrorDiffusionToAdjacentNeighbors dithering = new ColorErrorDiffusionToAdjacentNeighbors( - new int[3][] { - new int[2] { 5, 3 }, - new int[5] { 2, 4, 5, 4, 2 }, - new int[3] { 2, 3, 2 } - } ); - // apply the dithering routine - Bitmap newImage = dithering.Apply( image ); - - - - - - - Base class for error diffusion color dithering. - - - The class is the base class for color dithering algorithms based on - error diffusion. - - Color dithering with error diffusion is based on the idea that each pixel from the specified source - image is substituted with a best matching color (or better say with color's index) from the specified color - table. However, the error (difference between color value in the source image and the best matching color) - is diffused to neighbor pixels of the source image, which affects the way those pixels are substituted by colors - from the specified table. - - The image processing routine accepts 24/32 bpp color images for processing. As a result this routine - produces 4 bpp or 8 bpp indexed image, which depends on size of the specified color table - 4 bpp result for - color tables with 16 colors or less; 8 bpp result for larger color tables. - - - - - - Current processing X coordinate. - - - - - Current processing Y coordinate. - - - - - Processing image's width. - - - - - Processing image's height. - - - - - Processing image's stride (line size). - - - - - Processing image's pixel size in bytes. - - - - - Initializes a new instance of the class. - - - - - - Do error diffusion. - - - Error value of red component. - Error value of green component. - Error value of blue component. - Pointer to current processing pixel. - - All parameters of the image and current processing pixel's coordinates - are initialized in protected members. - - - - - Perform color dithering for the specified image. - - - Source image to do color dithering for. - - Returns color dithered image. See for information about format of - the result image. - - Unsupported pixel format of the source image. It must 24 or 32 bpp color image. - - - - - Perform color dithering for the specified image. - - - Source image to do color dithering for. - - Returns color dithered image. See for information about format of - the result image. - - Unsupported pixel format of the source image. It must 24 or 32 bpp color image. - - - - - Color table to use for image dithering. Must contain 2-256 colors. - - - Color table size determines format of the resulting image produced by this - image processing routine. If color table contains 16 color or less, then result image will have - 4 bpp indexed pixel format. If color table contains more than 16 colors, then result image will - have 8 bpp indexed pixel format. - - By default the property is initialized with default 16 colors, which are: - Black, Dark Blue, Dark Green, Dark Cyan, Dark Red, Dark Magenta, Dark Khaki, Light Gray, - Gray, Blue, Green, Cyan, Red, Magenta, Yellow and White. - - - Color table length must be in the [2, 256] range. - - - - - Use color caching during color dithering or not. - - - The property specifies if internal cache of already processed colors should be used or not. - For each pixel in the original image the color dithering routine does search in target color palette to find - the best matching color. To avoid doing the search again and again for already processed colors, the class may - use internal dictionary which maps colors of original image to indexes in target color palette. - - - The property provides a trade off. On one hand it may speedup color dithering routine, but on another - hand it increases memory usage. Also cache usage may not be efficient for very small target color tables. - - Default value is set to . - - - - - - Initializes a new instance of the class. - - - Diffusion coefficients (see - for more information). - - - - - Do error diffusion. - - - Error value of red component. - Error value of green component. - Error value of blue component. - Pointer to current processing pixel. - - All parameters of the image and current processing pixel's coordinates - are initialized by base class. - - - - - Diffusion coefficients. - - - Set of coefficients, which are used for error diffusion to - pixel's neighbors. - - - - - Initializes a new instance of the class. - - - - - - Interface which is implemented by different color quantization algorithms. - - - The interface defines set of methods, which are to be implemented by different - color quantization algorithms - algorithms which are aimed to provide reduced color table/palette - for a color image. - - See documentation to particular implementation of the interface for additional information - about the algorithm. - - - - - - Process color by a color quantization algorithm. - - - Color to process. - - Depending on particular implementation of interface, - this method may simply process the specified color or store it in internal list for - later color palette calculation. - - - - - Get palette of the specified size. - - - Palette size to return. - - Returns reduced color palette for the accumulated/processed colors. - - The method must be called after continuously calling method and - returns reduced color palette for colors accumulated/processed so far. - - - - - Clear internals of the algorithm, like accumulated color table, etc. - - - The methods resets internal state of a color quantization algorithm returning - it to initial state. - - - - - Color dithering using Floyd-Steinberg error diffusion. - - - The image processing routine represents color dithering algorithm, which is based on - error diffusion dithering with Floyd-Steinberg - coefficients. Error is diffused on 4 neighbor pixels with the next coefficients: - - - | * | 7 | - | 3 | 5 | 1 | - - / 16 - - - The image processing routine accepts 24/32 bpp color images for processing. As a result this routine - produces 4 bpp or 8 bpp indexed image, which depends on size of the specified - color table - 4 bpp result for - color tables with 16 colors or less; 8 bpp result for larger color tables. - - Sample usage: - - // create color image quantization routine - ColorImageQuantizer ciq = new ColorImageQuantizer( new MedianCutQuantizer( ) ); - // create 16 colors table - Color[] colorTable = ciq.CalculatePalette( image, 16 ); - // create dithering routine - FloydSteinbergColorDithering dithering = new FloydSteinbergColorDithering( ); - dithering.ColorTable = colorTable; - // apply the dithering routine - Bitmap newImage = dithering.Apply( image ); - - - Initial image: - - Result image: - - - - - - - - - - - - Initializes a new instance of the class. - - - - - - Template match class keeps information about found template match. The class is - used with template matching algorithms implementing - interface. - - - - - Initializes a new instance of the class. - - - Rectangle of the matching area. - Similarity between template and found matching, [0..1]. - - - - - Rectangle of the matching area. - - - - - Similarity between template and found matching, [0..1]. - - - - - Susan corners detector. - - - The class implements Susan corners detector, which is described by - S.M. Smith in: S.M. Smith, "SUSAN - a new approach to low level image processing", - Internal Technical Report TR95SMS1, Defense Research Agency, Chobham Lane, Chertsey, - Surrey, UK, 1995. - - Some implementation notes: - - Analyzing each pixel and searching for its USAN area, the 7x7 mask is used, - which is comprised of 37 pixels. The mask has circle shape: - - xxx - xxxxx - xxxxxxx - xxxxxxx - xxxxxxx - xxxxx - xxx - - - In the case if USAN's center of mass has the same coordinates as nucleus - (central point), the pixel is not a corner. - For noise suppression the 5x5 square window is used. - - The class processes only grayscale 8 bpp and color 24/32 bpp images. - In the case of color image, it is converted to grayscale internally using - filter. - - Sample usage: - - // create corners detector's instance - SusanCornersDetector scd = new SusanCornersDetector( ); - // process image searching for corners - List<IntPoint> corners = scd.ProcessImage( image ); - // process points - foreach ( IntPoint corner in corners ) - { - // ... - } - - - - - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Brightness difference threshold. - Geometrical threshold. - - - - - Process image looking for corners. - - - Source image to process. - - Returns list of found corners (X-Y coordinates). - - The source image has incorrect pixel format. - - - - - Process image looking for corners. - - - Source image data to process. - - Returns list of found corners (X-Y coordinates). - - The source image has incorrect pixel format. - - - - - Process image looking for corners. - - - Unmanaged source image to process. - - Returns array of found corners (X-Y coordinates). - - The source image has incorrect pixel format. - - - - - Brightness difference threshold. - - - The brightness difference threshold controls the amount - of pixels, which become part of USAN area. If difference between central - pixel (nucleus) and surrounding pixel is not higher than difference threshold, - then that pixel becomes part of USAN. - - Increasing this value decreases the amount of detected corners. - - Default value is set to 25. - - - - - - Geometrical threshold. - - - The geometrical threshold sets the maximum number of pixels - in USAN area around corner. If potential corner has USAN with more pixels, than - it is not a corner. - - Decreasing this value decreases the amount of detected corners - only sharp corners - are detected. Increasing this value increases the amount of detected corners, but - also increases amount of flat corners, which may be not corners at all. - - Default value is set to 18, which is half of maximum amount of pixels in USAN. - - - - - - Rotate image using bilinear interpolation. - - - Rotation is performed in counterclockwise direction. - - The class implements image rotation filter using bilinear - interpolation algorithm. - - The filter accepts 8 bpp grayscale images and 24 bpp - color images for processing. - - Sample usage: - - // create filter - rotate for 30 degrees keeping original image size - RotateBilinear filter = new RotateBilinear( 30, true ); - // apply the filter - Bitmap newImage = filter.Apply( image ); - - - Initial image: - - Result image: - - - - - - - - - - Initializes a new instance of the class. - - - Rotation angle. - - This constructor sets property - to . - - - - - - Initializes a new instance of the class. - - - Rotation angle. - Keep image size or not. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - - - - Format translations dictionary. - - - - - Simple water wave effect filter. - - - The image processing filter implements simple water wave effect. Using - properties of the class, it is possible to set number of vertical/horizontal waves, - as well as their amplitude. - - Bilinear interpolation is used to create smooth effect. - - The filter accepts 8 bpp grayscale images and 24/32 - color images for processing. - - Sample usage: - - // create filter - WaterWave filter = new WaterWave( ); - filter.HorizontalWavesCount = 10; - filter.HorizontalWavesAmplitude = 5; - filter.VerticalWavesCount = 3; - filter.VerticalWavesAmplitude = 15; - // apply the filter - Bitmap newImage = filter.Apply( image ); - - - Initial image: - - Result image: - - - - - - - Base class for filters, which produce new image of the same size as a - result of image processing. - - - The abstract class is the base class for all filters, which - do image processing creating new image with the same size as source. - Filters based on this class cannot be applied directly to the source - image, which is kept unchanged. - - The base class itself does not define supported pixel formats of source - image and resulting pixel formats of destination image. Filters inheriting from - this base class, should specify supported pixel formats and their transformations - overriding abstract property. - - - - - - Apply filter to an image. - - - Source image to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The method keeps the source image unchanged and returns - the result of image processing filter as new image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image. - - - Source image to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The filter accepts bitmap data as input and returns the result - of image processing filter as new image. The source image data are kept - unchanged. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image in unmanaged memory. - - - Source image in unmanaged memory to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The method keeps the source image unchanged and returns - the result of image processing filter as new image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image in unmanaged memory. - - - Source image in unmanaged memory to apply filter to. - Destination image in unmanaged memory to put result into. - - The method keeps the source image unchanged and puts result of image processing - into destination image. - - The destination image must have the same width and height as source image. Also - destination image must have pixel format, which is expected by particular filter (see - property for information about pixel format conversions). - - - Unsupported pixel format of the source image. - Incorrect destination pixel format. - Destination image has wrong width and/or height. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - - - - Format translations dictionary. - - - The dictionary defines, which pixel formats are supported for - source images and which pixel format will be used for resulting image. - - - See for more information. - - - - - - Initializes a new instance of the class. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - - - - Number of horizontal waves, [1, 10000]. - - - Default value is set to 5. - - - - - Number of vertical waves, [1, 10000]. - - - Default value is set to 5. - - - - - Amplitude of horizontal waves measured in pixels, [0, 10000]. - - - Default value is set to 10. - - - - - Amplitude of vertical waves measured in pixels, [0, 10000]. - - - Default value is set to 10. - - - - - Format translations dictionary. - - - See - documentation for additional information. - - - - - Filter to mark (highlight) corners of objects. - - - - The filter highlights corners of objects on the image using provided corners - detection algorithm. - - The filter accepts 8 bpp grayscale and 24/32 color images for processing. - - Sample usage: - - // create corner detector's instance - SusanCornersDetector scd = new SusanCornersDetector( ); - // create corner maker filter - CornersMarker filter = new CornersMarker( scd, Color.Red ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - Interface of corners' detection algorithm. - - - - - Initializes a new instance of the class. - - - Interface of corners' detection algorithm. - Marker's color used to mark corner. - - - - - Process the filter on the specified image. - - - Source image data. - - - - - Format translations dictionary. - - - - - Color used to mark corners. - - - - - Interface of corners' detection algorithm used to detect corners. - - - - - Flood filling with mean color starting from specified point. - - - The filter performs image's area filling (4 directional) starting - from the specified point. It fills - the area of the pointed color, but also fills other colors, which - are similar to the pointed within specified tolerance. - The area is filled using its mean color. - - - The filter is similar to filter, but instead - of filling the are with specified color, it fills the area with its mean color. This means - that this is a two pass filter - first pass is to calculate the mean value and the second pass is to - fill the area. Unlike to filter, this filter has nothing - to do in the case if zero tolerance is specified. - - The filter accepts 8 bpp grayscale images and 24 bpp - color images for processing. - - Sample usage: - - // create filter - PointedMeanFloodFill filter = new PointedMeanFloodFill( ); - // configre the filter - filter.Tolerance = Color.FromArgb( 150, 92, 92 ); - filter.StartingPoint = new IntPoint( 150, 100 ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - Initializes a new instance of the class. - - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - See - documentation for additional information. - - - - - Flood fill tolerance. - - - The tolerance value determines the level of similarity between - colors to fill and the pointed color. If the value is set to zero, then the - filter does nothing, since the filling area contains only one color and its - filling with mean is meaningless. - - The tolerance value is specified as , - where each component (R, G and B) represents tolerance for the corresponding - component of color. This allows to set different tolerances for red, green - and blue components. - - Default value is set to (16, 16, 16). - - - - - - Point to start filling from. - - - The property allows to set the starting point, where filling is - started from. - - Default value is set to (0, 0). - - - - - - Color filtering. - - - The filter filters pixels inside/outside of specified RGB color range - - it keeps pixels with colors inside/outside of specified range and fills the rest with - specified color. - - The filter accepts 24 and 32 bpp color images for processing. - - Sample usage: - - // create filter - ColorFiltering filter = new ColorFiltering( ); - // set color ranges to keep - filter.Red = new IntRange( 100, 255 ); - filter.Green = new IntRange( 0, 75 ); - filter.Blue = new IntRange( 0, 75 ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Red components filtering range. - Green components filtering range. - Blue components filtering range. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Range of red color component. - - - - - Range of green color component. - - - - - Range of blue color component. - - - - - Fill color used to fill filtered pixels. - - - - - Determines, if pixels should be filled inside or outside of specified - color ranges. - - - Default value is set to , which means - the filter removes colors outside of the specified range. - - - - - Color dithering using Jarvis, Judice and Ninke error diffusion. - - - The image processing routine represents color dithering algorithm, which is based on - error diffusion dithering with Jarvis-Judice-Ninke coefficients. Error is diffused - on 12 neighbor pixels with next coefficients: - - | * | 7 | 5 | - | 3 | 5 | 7 | 5 | 3 | - | 1 | 3 | 5 | 3 | 1 | - - / 48 - - - The image processing routine accepts 24/32 bpp color images for processing. As a result this routine - produces 4 bpp or 8 bpp indexed image, which depends on size of the specified - color table - 4 bpp result for - color tables with 16 colors or less; 8 bpp result for larger color tables. - - Sample usage: - - // create color image quantization routine - ColorImageQuantizer ciq = new ColorImageQuantizer( new MedianCutQuantizer( ) ); - // create 32 colors table - Color[] colorTable = ciq.CalculatePalette( image, 32 ); - // create dithering routine - JarvisJudiceNinkeColorDithering dithering = new JarvisJudiceNinkeColorDithering( ); - dithering.ColorTable = colorTable; - // apply the dithering routine - Bitmap newImage = dithering.Apply( image ); - - - Initial image: - - Result image: - - - - - - - - - - - - Initializes a new instance of the class. - - - - - - Simple skeletonization filter. - - - The filter build simple objects' skeletons by thinning them until - they have one pixel wide "bones" horizontally and vertically. The filter uses - and colors to distinguish - between object and background. - - The filter accepts 8 bpp grayscale images for processing. - - Sample usage: - - // create filter - SimpleSkeletonization filter = new SimpleSkeletonization( ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Background pixel color. - Foreground pixel color. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - See - documentation for additional information. - - - - - Background pixel color. - - - The property sets background (none object) color to look for. - - Default value is set to 0 - black. - - - - - Foreground pixel color. - - - The property sets objects' (none background) color to look for. - - Default value is set to 255 - white. - - - - - Connected components labeling. - - - The filter performs labeling of objects in the source image. It colors - each separate object using different color. The image processing filter treats all none - black pixels as objects' pixels and all black pixel as background. - - The filter accepts 8 bpp grayscale images and 24/32 bpp color images and produces - 24 bpp RGB image. - - Sample usage: - - // create filter - ConnectedComponentsLabeling filter = new ConnectedComponentsLabeling( ); - // apply the filter - Bitmap newImage = filter.Apply( image ); - // check objects count - int objectCount = filter.ObjectCount; - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - - - - Format translations dictionary. - - - - - Blob counter used to locate separate blobs. - - - The property allows to set blob counter to use for blobs' localization. - - Default value is set to . - - - - - - Colors used to color the binary image. - - - - - Specifies if blobs should be filtered. - - - See documentation for property - of class for more information. - - - - - Specifies if size filetering should be coupled or not. - - - See documentation for property - of class for more information. - - - - - Minimum allowed width of blob. - - - - - - Minimum allowed height of blob. - - - - - - Maximum allowed width of blob. - - - - - - Maximum allowed height of blob. - - - - - - Objects count. - - - The amount of objects found in the last processed image. - - - - - Morph filter. - - - The filter combines two images by taking - specified percent of pixels' intensities from source - image and the rest from overlay image. For example, if the - source percent value is set to 0.8, then each pixel - of the result image equals to 0.8 * source + 0.2 * overlay, where source - and overlay are corresponding pixels' values in source and overlay images. - - The filter accepts 8 bpp grayscale and 24 bpp color images for processing. - - Sample usage: - - // create filter - Morph filter = new Morph( overlayImage ); - filter.SourcePercent = 0.75; - // apply the filter - Bitmap resultImage = filter.Apply( sourceImage ); - - - Source image: - - Overlay image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Overlay image. - - - - - Initializes a new instance of the class. - - - Unmanaged overlay image. - - - - - Process the filter on the specified image. - - - Source image data. - Overlay image data. - - - - - Format translations dictionary. - - - - - Percent of source image to keep, [0, 1]. - - - The property specifies the percentage of source pixels' to take. The - rest is taken from an overlay image. - - - - - Filtering of frequencies outside of specified range in complex Fourier - transformed image. - - - The filer keeps only specified range of frequencies in complex - Fourier transformed image. The rest of frequencies are zeroed. - - Sample usage: - - // create complex image - ComplexImage complexImage = ComplexImage.FromBitmap( image ); - // do forward Fourier transformation - complexImage.ForwardFourierTransform( ); - // create filter - FrequencyFilter filter = new FrequencyFilter( new IntRange( 20, 128 ) ); - // apply filter - filter.Apply( complexImage ); - // do backward Fourier transformation - complexImage.BackwardFourierTransform( ); - // get complex image as bitmat - Bitmap fourierImage = complexImage.ToBitmap( ); - - - Initial image: - - Fourier image: - - - - - - - Image processing filter, which operates with Fourier transformed - complex image. - - - The interface defines the set of methods, which should be - provided by all image processing filter, which operate with Fourier - transformed complex image. - - - - - Apply filter to complex image. - - - Complex image to apply filter to. - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Range of frequencies to keep. - - - - - Apply filter to complex image. - - - Complex image to apply filter to. - - The source complex image should be Fourier transformed. - - - - - Range of frequencies to keep. - - - The range specifies the range of frequencies to keep. Values is frequencies - outside of this range are zeroed. - - Default value is set to [0, 1024]. - - - - - Resize image using bicubic interpolation algorithm. - - - The class implements image resizing filter using bicubic - interpolation algorithm. It uses bicubic kernel W(x) as described on - Wikipedia - (coefficient a is set to -0.5). - - The filter accepts 8 grayscale images and 24 bpp - color images for processing. - - Sample usage: - - // create filter - ResizeBicubic filter = new ResizeBicubic( 400, 300 ); - // apply the filter - Bitmap newImage = filter.Apply( image ); - - - Initial image: - - Result image: - - - - - - - - - - Base class for image resizing filters. - - - The abstract class is the base class for all filters, - which implement image rotation algorithms. - - - - - - New image width. - - - - - New image height. - - - - - Initializes a new instance of the class. - - - Width of the new resized image. - Height of the new resize image. - - - - - Calculates new image size. - - - Source image data. - - New image size - size of the destination image. - - - - - Width of the new resized image. - - - - - - Height of the new resized image. - - - - - - Initializes a new instance of the class. - - - Width of new image. - Height of new image. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - - - - Format translations dictionary. - - - - - Performs quadrilateral transformation of an area in a given source image. - - - The class implements quadrilateral transformation algorithm, - which allows to transform any quadrilateral from a given source image - to a rectangular image. The idea of the algorithm is based on homogeneous - transformation and its math is described by Paul Heckbert in his - "Projective Mappings for Image Warping" paper. - - - The image processing filter accepts 8 grayscale images and 24/32 bpp - color images for processing. - - Sample usage: - - // define quadrilateral's corners - List<IntPoint> corners = new List<IntPoint>( ); - corners.Add( new IntPoint( 99, 99 ) ); - corners.Add( new IntPoint( 156, 79 ) ); - corners.Add( new IntPoint( 184, 126 ) ); - corners.Add( new IntPoint( 122, 150 ) ); - // create filter - QuadrilateralTransformation filter = - new QuadrilateralTransformation( corners, 200, 200 ); - // apply the filter - Bitmap newImage = filter.Apply( image ); - - - Initial image: - - Result image: - - - - - - - - - - New image width. - - - - - New image height. - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Corners of the source quadrilateral area. - Width of the new transformed image. - Height of the new transformed image. - - This constructor sets to - , which means that destination image will have width and - height as specified by user. - - - - - Initializes a new instance of the class. - - - Corners of the source quadrilateral area. - - This constructor sets to - , which means that destination image will have width and - height automatically calculated based on property. - - - - - Calculates new image size. - - - Source image data. - - New image size - size of the destination image. - - Source quadrilateral was not set. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - - - - Format translations dictionary. - - - See - documentation for additional information. - - - - - Automatic calculation of destination image or not. - - - The property specifies how to calculate size of destination (transformed) - image. If the property is set to , then - and properties have effect and destination image's size is - specified by user. If the property is set to , then setting the above - mentioned properties does not have any effect, but destionation image's size is - automatically calculated from property - width and height - come from length of longest edges. - - - Default value is set to . - - - - - - Quadrilateral's corners in source image. - - - The property specifies four corners of the quadrilateral area - in the source image to be transformed. - - - - - - Width of the new transformed image. - - - The property defines width of the destination image, which gets - transformed quadrilateral image. - - Setting the property does not have any effect, if - property is set to . In this case destination image's width - is calculated automatically based on property. - - - - - - Height of the new transformed image. - - - The property defines height of the destination image, which gets - transformed quadrilateral image. - - Setting the property does not have any effect, if - property is set to . In this case destination image's height - is calculated automatically based on property. - - - - - - Specifies if bilinear interpolation should be used or not. - - - Default value is set to - interpolation - is used. - - - - - - Saturation adjusting in HSL color space. - - - The filter operates in HSL color space and adjusts - pixels' saturation value, increasing it or decreasing by specified percentage. - The filters is based on filter, passing work to it after - recalculating saturation adjust value to input/output - ranges of the filter. - - The filter accepts 24 and 32 bpp color images for processing. - - Sample usage: - - // create filter - SaturationCorrection filter = new SaturationCorrection( -0.5f ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Saturation adjust value. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Saturation adjust value, [-1, 1]. - - - Default value is set to 0.1, which corresponds to increasing - saturation by 10%. - - - - - Format translations dictionary. - - - - - Convolution filter. - - - The filter implements convolution operator, which calculates each pixel - of the result image as weighted sum of the correspond pixel and its neighbors in the source - image. The weights are set by convolution kernel. The weighted - sum is divided by before putting it into result image and also - may be thresholded using value. - - Convolution is a simple mathematical operation which is fundamental to many common - image processing filters. Depending on the type of provided kernel, the filter may produce - different results, like blur image, sharpen it, find edges, etc. - - The filter accepts 8 and 16 bpp grayscale images and 24, 32, 48 and 64 bpp - color images for processing. Note: depending on the value of - property, the alpha channel is either copied as is or processed with the kernel. - - Sample usage: - - // define emboss kernel - int[,] kernel = { - { -2, -1, 0 }, - { -1, 1, 1 }, - { 0, 1, 2 } }; - // create filter - Convolution filter = new Convolution( kernel ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Convolution kernel. - - Using this constructor (specifying only convolution kernel), - division factor will be calculated automatically - summing all kernel values. In the case if kernel's sum equals to zero, - division factor will be assigned to 1. - - Invalid kernel size is specified. Kernel must be - square, its width/height should be odd and should be in the [3, 25] range. - - - - - Initializes a new instance of the class. - - - Convolution kernel. - Divisor, used used to divide weighted sum. - - Invalid kernel size is specified. Kernel must be - square, its width/height should be odd and should be in the [3, 25] range. - Divisor can not be equal to zero. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Convolution kernel. - - - - Convolution kernel must be square and its width/height - should be odd and should be in the [3, 99] range. - - Setting convolution kernel through this property does not - affect - it is not recalculated automatically. - - - Invalid kernel size is specified. - - - - - Division factor. - - - The value is used to divide convolution - weighted sum - of pixels is divided by this value. - - The value may be calculated automatically in the case if constructor - with one parameter is used (). - - - Divisor can not be equal to zero. - - - - - Threshold to add to weighted sum. - - - The property specifies threshold value, which is added to each weighted - sum of pixels. The value is added right after division was done by - value. - - Default value is set to 0. - - - - - - Use dynamic divisor for edges or not. - - - The property specifies how to handle edges. If it is set to - , then the same divisor (which is specified by - property or calculated automatically) will be applied both for non-edge regions - and for edge regions. If the value is set to , then dynamically - calculated divisor will be used for edge regions, which is sum of those kernel - elements, which are taken into account for particular processed pixel - (elements, which are not outside image). - - Default value is set to . - - - - - - Specifies if alpha channel must be processed or just copied. - - - The property specifies the way how alpha channel is handled for 32 bpp - and 64 bpp images. If the property is set to , then alpha - channel's values are just copied as is. If the property is set to - then alpha channel is convolved using the specified kernel same way as RGB channels. - - Default value is set to . - - - - - - Convert grayscale image to RGB. - - - The filter creates color image from specified grayscale image - initializing all RGB channels to the same value - pixel's intensity of grayscale image. - - The filter accepts 8 bpp grayscale images and produces - 24 bpp RGB image. - - Sample usage: - - // create filter - GrayscaleToRGB filter = new GrayscaleToRGB( ); - // apply the filter - Bitmap rgbImage = filter.Apply( image ); - - - - - - - - Initializes a new instance of the class. - - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - - - - Format translations dictionary. - - - - - Adaptive thresholding using the internal image. - - - The image processing routine implements local thresholding technique described - by Derek Bradley and Gerhard Roth in the "Adaptive Thresholding Using the Integral Image" paper. - - - The brief idea of the algorithm is that every image's pixel is set to black if its brightness - is t percent lower (see ) than the average brightness - of surrounding pixels in the window of the specified size (see ), othwerwise it is set - to white. - - Sample usage: - - // create the filter - BradleyLocalThresholding filter = new BradleyLocalThresholding( ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - - Process the filter on the specified image. - - - Source image data. - - - - - Window size to calculate average value of pixels for. - - - The property specifies window size around processing pixel, which determines number of - neighbor pixels to use for calculating their average brightness. - - Default value is set to 41. - - The value should be odd. - - - - - - Brightness difference limit between processing pixel and average value across neighbors. - - - The property specifies what is the allowed difference percent between processing pixel - and average brightness of neighbor pixels in order to be set white. If the value of the - current pixel is t percent (this property value) lower than the average then it is set - to black, otherwise it is set to white. - - Default value is set to 0.15. - - - - - - Format translations dictionary. - - - See for more information. - - - - - Integral image. - - - The class implements integral image concept, which is described by - Viola and Jones in: P. Viola and M. J. Jones, "Robust real-time face detection", - Int. Journal of Computer Vision 57(2), pp. 137–154, 2004. - - "An integral image I of an input image G 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." - - The intensity at position (x, y) can be written as: - - x y - I(x,y) = SUM( SUM( G(i,j) ) ) - i=0 j=0 - - - The class uses 32-bit integers to represent integral image. - - The class processes only grayscale (8 bpp indexed) images. - - 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. - - Sample usage: - - // create integral image - IntegralImage im = IntegralImage.FromBitmap( image ); - // get pixels' mean value in the specified rectangle - float mean = im.GetRectangleMean( 10, 10, 20, 30 ) - - - - - - - Intergral image's array. - - - See remarks to property. - - - - - Initializes a new instance of the class. - - - Image width. - Image height. - - The constractor is protected, what makes it imposible to instantiate this - class directly. To create an instance of this class or - method should be used. - - - - - Construct integral image from source grayscale image. - - - Source grayscale image. - - Returns integral image. - - The source image has incorrect pixel format. - - - - - Construct integral image from source grayscale image. - - - Source image data. - - Returns integral image. - - The source image has incorrect pixel format. - - - - - Construct integral image from source grayscale image. - - - Source unmanaged image. - - Returns integral image. - - The source image has incorrect pixel format. - - - - - Calculate sum of pixels in the specified rectangle. - - - X coordinate of left-top rectangle's corner. - Y coordinate of left-top rectangle's corner. - X coordinate of right-bottom rectangle's corner. - Y coordinate of right-bottom rectangle's corner. - - Returns sum of pixels in the specified rectangle. - - Both specified points are included into the calculation rectangle. - - - - - Calculate horizontal (X) haar wavelet at the specified point. - - - X coordinate of the point to calculate wavelet at. - Y coordinate of the point to calculate wavelet at. - Wavelet size to calculate. - - Returns value of the horizontal wavelet at the specified point. - - The method calculates horizontal wavelet, which is a difference - of two horizontally adjacent boxes' sums, i.e. A-B. A is the sum of rectangle with coordinates - (x, y-radius, x+radius-1, y+radius-1). B is the sum of rectangle with coordinates - (x-radius, y-radius, x-1, y+radiys-1). - - - - - Calculate vertical (Y) haar wavelet at the specified point. - - - X coordinate of the point to calculate wavelet at. - Y coordinate of the point to calculate wavelet at. - Wavelet size to calculate. - - Returns value of the vertical wavelet at the specified point. - - The method calculates vertical wavelet, which is a difference - of two vertical adjacent boxes' sums, i.e. A-B. A is the sum of rectangle with coordinates - (x-radius, y, x+radius-1, y+radius-1). B is the sum of rectangle with coordinates - (x-radius, y-radius, x+radius-1, y-1). - - - - - Calculate sum of pixels in the specified rectangle without checking it's coordinates. - - - X coordinate of left-top rectangle's corner. - Y coordinate of left-top rectangle's corner. - X coordinate of right-bottom rectangle's corner. - Y coordinate of right-bottom rectangle's corner. - - Returns sum of pixels in the specified rectangle. - - Both specified points are included into the calculation rectangle. - - - - - Calculate sum of pixels in the specified rectangle. - - - X coordinate of central point of the rectangle. - Y coordinate of central point of the rectangle. - Radius of the rectangle. - - Returns sum of pixels in the specified rectangle. - - The method calculates sum of pixels in square rectangle with - odd width and height. In the case if it is required to calculate sum of - 3x3 rectangle, then it is required to specify its center and radius equal to 1. - - - - - - Calculate sum of pixels in the specified rectangle without checking it's coordinates. - - - X coordinate of central point of the rectangle. - Y coordinate of central point of the rectangle. - Radius of the rectangle. - - Returns sum of pixels in the specified rectangle. - - The method calculates sum of pixels in square rectangle with - odd width and height. In the case if it is required to calculate sum of - 3x3 rectangle, then it is required to specify its center and radius equal to 1. - - - - - - Calculate mean value of pixels in the specified rectangle. - - - X coordinate of left-top rectangle's corner. - Y coordinate of left-top rectangle's corner. - X coordinate of right-bottom rectangle's corner. - Y coordinate of right-bottom rectangle's corner. - - Returns mean value of pixels in the specified rectangle. - - Both specified points are included into the calculation rectangle. - - - - - Calculate mean value of pixels in the specified rectangle without checking it's coordinates. - - - X coordinate of left-top rectangle's corner. - Y coordinate of left-top rectangle's corner. - X coordinate of right-bottom rectangle's corner. - Y coordinate of right-bottom rectangle's corner. - - Returns mean value of pixels in the specified rectangle. - - Both specified points are included into the calculation rectangle. - - - - - Calculate mean value of pixels in the specified rectangle. - - - X coordinate of central point of the rectangle. - Y coordinate of central point of the rectangle. - Radius of the rectangle. - - Returns mean value of pixels in the specified rectangle. - - The method calculates mean value of pixels in square rectangle with - odd width and height. In the case if it is required to calculate mean value of - 3x3 rectangle, then it is required to specify its center and radius equal to 1. - - - - - - Calculate mean value of pixels in the specified rectangle without checking it's coordinates. - - - X coordinate of central point of the rectangle. - Y coordinate of central point of the rectangle. - Radius of the rectangle. - - Returns mean value of pixels in the specified rectangle. - - The method calculates mean value of pixels in square rectangle with - odd width and height. In the case if it is required to calculate mean value of - 3x3 rectangle, then it is required to specify its center and radius equal to 1. - - - - - - Width of the source image the integral image was constructed for. - - - - - Height of the source image the integral image was constructed for. - - - - - Provides access to internal array keeping integral image data. - - - - The array should be accessed by [y, x] indexing. - - The array's size is [+1, +1]. The first - row and column are filled with zeros, what is done for more efficient calculation of - rectangles' sums. - - - - - - Gather statistics about image in RGB color space. - - - The class is used to accumulate statistical values about images, - like histogram, mean, standard deviation, etc. for each color channel in RGB color - space. - - The class accepts 8 bpp grayscale and 24/32 bpp color images for processing. - - Sample usage: - - // gather statistics - ImageStatistics stat = new ImageStatistics( image ); - // get red channel's histogram - Histogram red = stat.Red; - // check mean value of red channel - if ( red.Mean > 128 ) - { - // do further processing - } - - - - - - - - - Initializes a new instance of the class. - - - Image to gather statistics about. - - Source pixel format is not supported. - - - - - Initializes a new instance of the class. - - - Image to gather statistics about. - Mask image which specifies areas to collect statistics for. - - The mask image must be a grayscale/binary (8bpp) image of the same size as the - specified source image, where black pixels (value 0) correspond to areas which should be excluded - from processing. So statistics is calculated only for pixels, which are none black in the mask image. - - - Source pixel format is not supported. - Mask image must be 8 bpp grayscale image. - Mask must have the same size as the source image to get statistics for. - - - - - Initializes a new instance of the class. - - - Image to gather statistics about. - Mask array which specifies areas to collect statistics for. - - The mask array must be of the same size as the specified source image, where 0 values - correspond to areas which should be excluded from processing. So statistics is calculated only for pixels, - which have none zero corresponding value in the mask. - - - Source pixel format is not supported. - Mask must have the same size as the source image to get statistics for. - - - - - Initializes a new instance of the class. - - - Unmanaged image to gather statistics about. - - Source pixel format is not supported. - - - - - Initializes a new instance of the class. - - - Image to gather statistics about. - Mask image which specifies areas to collect statistics for. - - The mask image must be a grayscale/binary (8bpp) image of the same size as the - specified source image, where black pixels (value 0) correspond to areas which should be excluded - from processing. So statistics is calculated only for pixels, which are none black in the mask image. - - - Source pixel format is not supported. - Mask image must be 8 bpp grayscale image. - Mask must have the same size as the source image to get statistics for. - - - - - Initializes a new instance of the class. - - - Image to gather statistics about. - Mask array which specifies areas to collect statistics for. - - The mask array must be of the same size as the specified source image, where 0 values - correspond to areas which should be excluded from processing. So statistics is calculated only for pixels, - which have none zero corresponding value in the mask. - - - Source pixel format is not supported. - Mask must have the same size as the source image to get statistics for. - - - - - Histogram of red channel. - - - The property is valid only for color images - (see property). - - - - - Histogram of green channel. - - - The property is valid only for color images - (see property). - - - - - Histogram of blue channel. - - - The property is valid only for color images - (see property). - - - - - Histogram of gray channel. - - - The property is valid only for grayscale images - (see property). - - - - - Histogram of red channel excluding black pixels. - - - The property keeps statistics about red channel, which - excludes all black pixels, what affects mean, standard deviation, etc. - - The property is valid only for color images - (see property). - - - - - Histogram of green channel excluding black pixels. - - - The property keeps statistics about green channel, which - excludes all black pixels, what affects mean, standard deviation, etc. - - The property is valid only for color images - (see property). - - - - - Histogram of blue channel excluding black pixels - - - The property keeps statistics about blue channel, which - excludes all black pixels, what affects mean, standard deviation, etc. - - The property is valid only for color images - (see property). - - - - - Histogram of gray channel channel excluding black pixels. - - - The property keeps statistics about gray channel, which - excludes all black pixels, what affects mean, standard deviation, etc. - - The property is valid only for grayscale images - (see property). - - - - - Total pixels count in the processed image. - - - - - - Total pixels count in the processed image excluding black pixels. - - - - - - Value wich specifies if the processed image was color or grayscale. - - - If the value is set to then - property should be used to get statistics information about image. Otherwise - , and properties should be used - for color images. - - - - - Horizontal intensity statistics. - - - The class provides information about horizontal distribution - of pixel intensities, which may be used to locate objects, their centers, etc. - - - The class accepts grayscale (8 bpp indexed and 16 bpp) and color (24, 32, 48 and 64 bpp) images. - In the case of 32 and 64 bpp color images, the alpha channel is not processed - statistics is not - gathered for this channel. - - Sample usage: - - // collect statistics - HorizontalIntensityStatistics his = new HorizontalIntensityStatistics( sourceImage ); - // get gray histogram (for grayscale image) - Histogram histogram = his.Gray; - // output some histogram's information - System.Diagnostics.Debug.WriteLine( "Mean = " + histogram.Mean ); - System.Diagnostics.Debug.WriteLine( "Min = " + histogram.Min ); - System.Diagnostics.Debug.WriteLine( "Max = " + histogram.Max ); - - - Sample grayscale image with its horizontal intensity histogram: - - - - - - - - - Initializes a new instance of the class. - - - Source image. - - Unsupported pixel format of the source image. - - - - - Initializes a new instance of the class. - - - Source image data. - - Unsupported pixel format of the source image. - - - - - Initializes a new instance of the class. - - - Source unmanaged image. - - Unsupported pixel format of the source image. - - - - - Gather horizontal intensity statistics for specified image. - - - Source image. - - - - - Histogram for red channel. - - - - - - Histogram for green channel. - - - - - - Histogram for blue channel. - - - - - - Histogram for gray channel (intensities). - - - - - - Value wich specifies if the processed image was color or grayscale. - - - If the property equals to true, then the - property should be used to retrieve histogram for the processed grayscale image. - Otherwise , and property - should be used to retrieve histogram for particular RGB channel of the processed - color image. - - - - - Performs quadrilateral transformation using nearest neighbor algorithm for interpolation. - - - The class is deprecated and should be used instead. - - - - - - - - Initializes a new instance of the class. - - - Corners of the source quadrilateral area. - Width of the new transformed image. - Height of the new transformed image. - - This constructor sets to - , which means that destination image will have width and - height as specified by user. - - - - - Initializes a new instance of the class. - - - Corners of the source quadrilateral area. - - This constructor sets to - , which means that destination image will have width and - height automatically calculated based on property. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - - - - Calculates new image size. - - - Source image data. - - New image size - size of the destination image. - - The specified quadrilateral's corners are outside of the given image. - - - - - Format translations dictionary. - - - - - Automatic calculation of destination image or not. - - - The property specifies how to calculate size of destination (transformed) - image. If the property is set to , then - and properties have effect and destination image's size is - specified by user. If the property is set to , then setting the above - mentioned properties does not have any effect, but destionation image's size is - automatically calculated from property - width and height - come from length of longest edges. - - - - - - Quadrilateral's corners in source image. - - - The property specifies four corners of the quadrilateral area - in the source image to be transformed. - - - - - - Width of the new transformed image. - - - The property defines width of the destination image, which gets - transformed quadrilateral image. - - Setting the property does not have any effect, if - property is set to . In this case destination image's width - is calculated automatically based on property. - - - - - - Height of the new transformed image. - - - The property defines height of the destination image, which gets - transformed quadrilateral image. - - Setting the property does not have any effect, if - property is set to . In this case destination image's height - is calculated automatically based on property. - - - - - - Median filter. - - - The median filter is normally used to reduce noise in an image, somewhat like - the mean filter. However, it often does a better job than the mean - filter of preserving useful detail in the image. - - Each pixel of the original source image is replaced with the median of neighboring pixel - values. The median is calculated by first sorting all the pixel values from the surrounding - neighborhood into numerical order and then replacing the pixel being considered with the - middle pixel value. - - The filter accepts 8 bpp grayscale images and 24/32 bpp - color images for processing. - - Sample usage: - - // create filter - Median filter = new Median( ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Processing square size. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Processing square size for the median filter, [3, 25]. - - - Default value is set to 3. - - The value should be odd. - - - - - - Textured filter - filter an image using texture. - - - The filter is similar to filter in its - nature, but instead of working with source image and overly, it uses provided - filters to create images to merge (see and - properties). In addition, it uses a bit more complex formula for calculation - of destination pixel's value, which gives greater amount of flexibility:
- dst = * ( src1 * textureValue + src2 * ( 1.0 - textureValue ) ) + * src2, - where src1 is value of pixel from the image produced by , - src2 is value of pixel from the image produced by , - dst is value of pixel in a destination image and textureValue is corresponding value - from provided texture (see or ).
- - It is possible to set to . In this case - original source image will be used instead of result produced by the second filter. - - The filter 24 bpp color images for processing. - - Sample usage #1: - - // create filter - TexturedFilter filter = new TexturedFilter( new CloudsTexture( ), - new HueModifier( 50 ) ); - // apply the filter - Bitmap newImage = filter.Apply( image ); - - - Sample usage #2: - - // create filter - TexturedFilter filter = new TexturedFilter( new CloudsTexture( ), - new GrayscaleBT709( ), new Sepia( ) ); - // apply the filter - Bitmap newImage = filter.Apply( image ); - - - Initial image: - - Result image #1: - - Result image #2: - -
- -
- - - Initializes a new instance of the class. - - - Generated texture. - First filter. - - - - - Initializes a new instance of the class. - - - Generated texture. - First filter. - Second filter. - - - - - Initializes a new instance of the class. - - - Texture generator. - First filter. - - - - - Initializes a new instance of the class. - - - Texture generator. - First filter. - Second filter. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - Texture size does not match image size. - Filters should not change image dimension. - - - - - Format translations dictionary. - - - See for more information. - - - - - Filter level value, [0, 1]. - - - Filtering factor determines portion of the destionation image, which is formed - as a result of merging source images using specified texture. - - Default value is set to 1.0. - - See class description for more details. - - - - - - Preserve level value - - - Preserving factor determines portion taken from the image produced - by (or from original source) without applying textured - merge to it. - - Default value is set to 0.0. - - See class description for more details. - - - - - - Generated texture. - - - Two dimensional array of texture intensities. - - Size of the provided texture should be the same as size of images, which will - be passed to the filter. - - The property has priority over this property - if - generator is specified than the static generated texture is not used. - - - - - - Texture generator. - - - Generator used to generate texture. - - The property has priority over the property. - - - - - - First filter. - - - Filter, which is used to produce first image for the merge. The filter - needs to implement interface, so it could be possible - to get information about the filter. The filter must be able to process color 24 bpp - images and produce color 24 bpp or grayscale 8 bppp images as result. - - - The specified filter does not support 24 bpp color images. - The specified filter does not produce image of supported format. - The specified filter does not implement IFilterInformation interface. - - - - - Second filter - - - Filter, which is used to produce second image for the merge. The filter - needs to implement interface, so it could be possible - to get information about the filter. The filter must be able to process color 24 bpp - images and produce color 24 bpp or grayscale 8 bppp images as result. - - The filter may be set to . In this case original source image - is used as a second image for the merge. - - - The specified filter does not support 24 bpp color images. - The specified filter does not produce image of supported format. - The specified filter does not implement IFilterInformation interface. - - - - - Top-hat operator from Mathematical Morphology. - - - Top-hat morphological operator subtracts - result of morphological opening on the input image - from the input image itself. - - Applied to binary image, the filter allows to get all those object (their parts) - which were removed by opening filter, but never restored. - - The filter accepts 8 and 16 bpp grayscale images and 24 and 48 bpp - color images for processing. - - Sample usage: - - // create filter - TopHat filter = new TopHat( ); - // apply the filter - filter.Apply( image ); - - - Initial image: - - Result image: - - - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Structuring element to pass to operator. - - - - - Process the filter on the specified image. - - - Source image data. - - - - - Format translations dictionary. - - - - - Difference edge detector. - - - The filter finds objects' edges by calculating maximum difference - between pixels in 4 directions around the processing pixel. - - Suppose 3x3 square element of the source image (x - is currently processed - pixel): - - P1 P2 P3 - P8 x P4 - P7 P6 P5 - - The corresponding pixel of the result image equals to: - - max( |P1-P5|, |P2-P6|, |P3-P7|, |P4-P8| ) - - - - The filter accepts 8 bpp grayscale images for processing. - - Sample usage: - - // create filter - DifferenceEdgeDetector filter = new DifferenceEdgeDetector( ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - - Initializes a new instance of the class. - - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Mean filter. - - - The filter performs each pixel value's averaging with its 8 neighbors, which is - convolution filter using the mean kernel: - - - 1 1 1 - 1 1 1 - 1 1 1 - - - For the list of supported pixel formats, see the documentation to - filter. - - With the above kernel the convolution filter is just calculates each pixel's value - in result image as average of 9 corresponding pixels in the source image. - - By default this filter sets property to - , so the alpha channel of 32 bpp and 64 bpp images is blurred as well. - - - Sample usage: - - // create filter - Mean filter = new Mean( ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - Initializes a new instance of the class. - - - - - Linear correction of RGB channels. - - - The filter performs linear correction of RGB channels by mapping specified - channels' input ranges to output ranges. It is similar to the - , but the remapping is linear. - - The filter accepts 8 bpp grayscale and 24/32 bpp color images for processing. - - Sample usage: - - // create filter - LevelsLinear filter = new LevelsLinear( ); - // set ranges - filter.InRed = new IntRange( 30, 230 ); - filter.InGreen = new IntRange( 50, 240 ); - filter.InBlue = new IntRange( 10, 210 ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - - Initializes a new instance of the class. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Calculate conversion map. - - - Input range. - Output range. - Conversion map. - - - - - Format translations dictionary. - - - - - Red component's input range. - - - - - Green component's input range. - - - - - Blue component's input range. - - - - - Gray component's input range. - - - - - Input range for RGB components. - - - The property allows to set red, green and blue input ranges to the same value. - - - - - Red component's output range. - - - - - Green component's output range. - - - - - Blue component's output range. - - - - - Gray component's output range. - - - - - Output range for RGB components. - - - The property allows to set red, green and blue output ranges to the same value. - - - - - Threshold using Simple Image Statistics (SIS). - - - The filter performs image thresholding calculating threshold automatically - using simple image statistics method. For each pixel: - - two gradients are calculated - ex = |I(x + 1, y) - I(x - 1, y)| and - |I(x, y + 1) - I(x, y - 1)|; - weight is calculated as maximum of two gradients; - sum of weights is updated (weightTotal += weight); - sum of weighted pixel values is updated (total += weight * I(x, y)). - - The result threshold is calculated as sum of weighted pixel values divided by sum of weight. - - The filter accepts 8 bpp grayscale images for processing. - - Sample usage: - - // create filter - SISThreshold filter = new SISThreshold( ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image (calculated threshold is 127): - - - - - - - - - - Initializes a new instance of the class. - - - - - - Calculate binarization threshold for the given image. - - - Image to calculate binarization threshold for. - Rectangle to calculate binarization threshold for. - - Returns binarization threshold. - - The method is used to calculate binarization threshold only. The threshold - later may be applied to the image using image processing filter. - - Source pixel format is not supported by the routine. It should be - 8 bpp grayscale (indexed) image. - - - - - Calculate binarization threshold for the given image. - - - Image to calculate binarization threshold for. - Rectangle to calculate binarization threshold for. - - Returns binarization threshold. - - The method is used to calculate binarization threshold only. The threshold - later may be applied to the image using image processing filter. - - Source pixel format is not supported by the routine. It should be - 8 bpp grayscale (indexed) image. - - - - - Calculate binarization threshold for the given image. - - - Image to calculate binarization threshold for. - Rectangle to calculate binarization threshold for. - - Returns binarization threshold. - - The method is used to calculate binarization threshold only. The threshold - later may be applied to the image using image processing filter. - - Source pixel format is not supported by the routine. It should be - 8 bpp grayscale (indexed) image. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Threshold value. - - - The property is read only and represents the value, which - was automaticaly calculated using image statistics. - - - - - Difference filter - get the difference between overlay and source images. - - - The difference filter takes two images (source and - overlay images) - of the same size and pixel format and produces an image, where each pixel equals - to absolute difference between corresponding pixels from provided images. - - The filter accepts 8 and 16 bpp grayscale images and 24, 32, 48 and 64 bpp - color images for processing. - - In the case if images with alpha channel are used (32 or 64 bpp), visualization - of the result image may seem a bit unexpected - most probably nothing will be seen - (in the case if image is displayed according to its alpha channel). This may be - caused by the fact that after differencing the entire alpha channel will be zeroed - (zero difference between alpha channels), what means that the resulting image will be - 100% transparent. - - Sample usage: - - // create filter - Difference filter = new Difference( overlayImage ); - // apply the filter - Bitmap resultImage = filter.Apply( sourceImage ); - - - Source image: - - Overlay image: - - Result image: - - - - - - - - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Overlay image. - - - - - Initializes a new instance of the class. - - - Unmanaged overlay image. - - - - - Process the filter on the specified image. - - - Source image data. - Overlay image data. - - - - - Format translations dictionary. - - - - - Image in unmanaged memory. - - - - The class represents wrapper of an image in unmanaged memory. Using this class - it is possible as to allocate new image in unmanaged memory, as to just wrap provided - pointer to unmanaged memory, where an image is stored. - - Usage of unmanaged images is mostly beneficial when it is required to apply multiple - image processing routines to a single image. In such scenario usage of .NET managed images - usually leads to worse performance, because each routine needs to lock managed image - before image processing is done and then unlock it after image processing is done. Without - these lock/unlock there is no way to get direct access to managed image's data, which means - there is no way to do fast image processing. So, usage of managed images lead to overhead, which - is caused by locks/unlock. Unmanaged images are represented internally using unmanaged memory - buffer. This means that it is not required to do any locks/unlocks in order to get access to image - data (no overhead). - - Sample usage: - - // sample 1 - wrapping .NET image into unmanaged without - // making extra copy of image in memory - BitmapData imageData = image.LockBits( - new Rectangle( 0, 0, image.Width, image.Height ), - ImageLockMode.ReadWrite, image.PixelFormat ); - - try - { - UnmanagedImage unmanagedImage = new UnmanagedImage( imageData ) ); - // apply several routines to the unmanaged image - } - finally - { - image.UnlockBits( imageData ); - } - - - // sample 2 - converting .NET image into unmanaged - UnmanagedImage unmanagedImage = UnmanagedImage.FromManagedImage( image ); - // apply several routines to the unmanaged image - ... - // conver to managed image if it is required to display it at some point of time - Bitmap managedImage = unmanagedImage.ToManagedImage( ); - - - - - - - Initializes a new instance of the class. - - - Pointer to image data in unmanaged memory. - Image width in pixels. - Image height in pixels. - Image stride (line size in bytes). - Image pixel format. - - Using this constructor, make sure all specified image attributes are correct - and correspond to unmanaged memory buffer. If some attributes are specified incorrectly, - this may lead to exceptions working with the unmanaged memory. - - - - - Initializes a new instance of the class. - - - Locked bitmap data. - - Unlike method, this constructor does not make - copy of managed image. This means that managed image must stay locked for the time of using the instance - of unamanged image. - - - - - Destroys the instance of the class. - - - - - - Dispose the object. - - - Frees unmanaged resources used by the object. The object becomes unusable - after that. - - The method needs to be called only in the case if unmanaged image was allocated - using method. In the case if the class instance was created using constructor, - this method does not free unmanaged memory. - - - - - - Dispose the object. - - - Indicates if disposing was initiated manually. - - - - - Clone the unmanaged images. - - - Returns clone of the unmanaged image. - - The method does complete cloning of the object. - - - - - Copy unmanaged image. - - - Destination image to copy this image to. - - The method copies current unmanaged image to the specified image. - Size and pixel format of the destination image must be exactly the same. - - Destination image has different size or pixel format. - - - - - Allocate new image in unmanaged memory. - - - Image width. - Image height. - Image pixel format. - - Return image allocated in unmanaged memory. - - Allocate new image with specified attributes in unmanaged memory. - - The method supports only - Format8bppIndexed, - Format16bppGrayScale, - Format24bppRgb, - Format32bppRgb, - Format32bppArgb, - Format32bppPArgb, - Format48bppRgb, - Format64bppArgb and - Format64bppPArgb pixel formats. - In the case if Format8bppIndexed - format is specified, pallete is not not created for the image (supposed that it is - 8 bpp grayscale image). - - - - Unsupported pixel format was specified. - Invalid image size was specified. - - - - - Create managed image from the unmanaged. - - - Returns managed copy of the unmanaged image. - - The method creates a managed copy of the unmanaged image with the - same size and pixel format (it calls specifying - for the makeCopy parameter). - - - - - Create managed image from the unmanaged. - - - Make a copy of the unmanaged image or not. - - Returns managed copy of the unmanaged image. - - If the is set to , then the method - creates a managed copy of the unmanaged image, so the managed image stays valid even when the unmanaged - image gets disposed. However, setting this parameter to creates a managed image which is - just a wrapper around the unmanaged image. So if unmanaged image is disposed, the - managed image becomes no longer valid and accessing it will generate an exception. - - The unmanaged image has some invalid properties, which results - in failure of converting it to managed image. This may happen if user used the - constructor specifying some - invalid parameters. - - - - - Create unmanaged image from the specified managed image. - - - Source managed image. - - Returns new unmanaged image, which is a copy of source managed image. - - The method creates an exact copy of specified managed image, but allocated - in unmanaged memory. - - Unsupported pixel format of source image. - - - - - Create unmanaged image from the specified managed image. - - - Source locked image data. - - Returns new unmanaged image, which is a copy of source managed image. - - The method creates an exact copy of specified managed image, but allocated - in unmanaged memory. This means that managed image may be unlocked right after call to this - method. - - Unsupported pixel format of source image. - - - - - Collect pixel values from the specified list of coordinates. - - - List of coordinates to collect pixels' value from. - - Returns array of pixels' values from the specified coordinates. - - The method goes through the specified list of points and for each point retrievs - corresponding pixel's value from the unmanaged image. - - For grayscale image the output array has the same length as number of points in the - specified list of points. For color image the output array has triple length, containing pixels' - values in RGB order. - - The method does not make any checks for valid coordinates and leaves this up to user. - If specified coordinates are out of image's bounds, the result is not predictable (crash in most cases). - - - This method is supposed for images with 8 bpp channels only (8 bpp grayscale image and - 24/32 bpp color images). - - - Unsupported pixel format of the source image. Use Collect16bppPixelValues() method for - images with 16 bpp channels. - - - - - Collect coordinates of none black pixels in the image. - - - Returns list of points, which have other than black color. - - - - - Collect coordinates of none black pixels within specified rectangle of the image. - - - Image's rectangle to process. - - Returns list of points, which have other than black color. - - - - - Set pixels with the specified coordinates to the specified color. - - - List of points to set color for. - Color to set for the specified points. - - For images having 16 bpp per color plane, the method extends the specified color - value to 16 bit by multiplying it by 256. - - - - - Set pixel with the specified coordinates to the specified color. - - - Point's coordiates to set color for. - Color to set for the pixel. - - See for more information. - - - - - Set pixel with the specified coordinates to the specified color. - - - X coordinate of the pixel to set. - Y coordinate of the pixel to set. - Color to set for the pixel. - - For images having 16 bpp per color plane, the method extends the specified color - value to 16 bit by multiplying it by 256. - - For grayscale images this method will calculate intensity value based on the below formula: - - 0.2125 * Red + 0.7154 * Green + 0.0721 * Blue - - - - - - - - Set pixel with the specified coordinates to the specified value. - - - X coordinate of the pixel to set. - Y coordinate of the pixel to set. - Pixel value to set. - - The method sets all color components of the pixel to the specified value. - If it is a grayscale image, then pixel's intensity is set to the specified value. - If it is a color image, then pixel's R/G/B components are set to the same specified value - (if an image has alpha channel, then it is set to maximum value - 255 or 65535). - - For images having 16 bpp per color plane, the method extends the specified color - value to 16 bit by multiplying it by 256. - - - - - - Get color of the pixel with the specified coordinates. - - - Point's coordiates to get color of. - - Return pixel's color at the specified coordinates. - - See for more information. - - - - - Get color of the pixel with the specified coordinates. - - - X coordinate of the pixel to get. - Y coordinate of the pixel to get. - - Return pixel's color at the specified coordinates. - - - In the case if the image has 8 bpp grayscale format, the method will return a color with - all R/G/B components set to same value, which is grayscale intensity. - - The method supports only 8 bpp grayscale images and 24/32 bpp color images so far. - - - The specified pixel coordinate is out of image's bounds. - Pixel format of this image is not supported by the method. - - - - - Collect pixel values from the specified list of coordinates. - - - List of coordinates to collect pixels' value from. - - Returns array of pixels' values from the specified coordinates. - - The method goes through the specified list of points and for each point retrievs - corresponding pixel's value from the unmanaged image. - - For grayscale image the output array has the same length as number of points in the - specified list of points. For color image the output array has triple length, containing pixels' - values in RGB order. - - The method does not make any checks for valid coordinates and leaves this up to user. - If specified coordinates are out of image's bounds, the result is not predictable (crash in most cases). - - - This method is supposed for images with 16 bpp channels only (16 bpp grayscale image and - 48/64 bpp color images). - - - Unsupported pixel format of the source image. Use Collect8bppPixelValues() method for - images with 8 bpp channels. - - - - - Pointer to image data in unmanaged memory. - - - - - Image width in pixels. - - - - - Image height in pixels. - - - - - Image stride (line size in bytes). - - - - - Image pixel format. - - - - - Clouds texture. - - - The texture generator creates textures with effect of clouds. - - The generator is based on the Perlin noise function. - - Sample usage: - - // create texture generator - CloudsTexture textureGenerator = new CloudsTexture( ); - // generate new texture - float[,] texture = textureGenerator.Generate( 320, 240 ); - // convert it to image to visualize - Bitmap textureImage = TextureTools.ToBitmap( texture ); - - - Result image: - - - - - - - Texture generator interface. - - - Each texture generator generates a 2-D texture of the specified size and returns - it as two dimensional array of intensities in the range of [0, 1] - texture's values. - - - - - - Generate texture. - - - Texture's width. - Texture's height. - - Two dimensional array of texture's intensities. - - Generates new texture of the specified size. - - - - - Reset generator. - - - Resets the generator - resets all internal variables, regenerates - internal random numbers, etc. - - - - - Initializes a new instance of the class. - - - - - - Generate texture. - - - Texture's width. - Texture's height. - - Two dimensional array of intensities. - - Generates new texture of the specified size. - - - - - Reset generator. - - - Regenerates internal random numbers. - - - - - Searching of quadrilateral/triangle corners. - - - The class searches for quadrilateral's/triangle's corners on the specified image. - It first collects edge points of the object and then uses - to find corners - the quadrilateral/triangle. - - The class treats all black pixels as background (none-object) and - all none-black pixels as object. - - The class processes grayscale 8 bpp and color 24/32 bpp images. - - Sample usage: - - // get corners of the quadrilateral - QuadrilateralFinder qf = new QuadrilateralFinder( ); - List<IntPoint> corners = qf.ProcessImage( image ); - - // lock image to draw on it with AForge.NET's methods - // (or draw directly on image without locking if it is unmanaged image) - BitmapData data = image.LockBits( new Rectangle( 0, 0, image.Width, image.Height ), - ImageLockMode.ReadWrite, image.PixelFormat ); - - Drawing.Polygon( data, corners, Color.Red ); - for ( int i = 0; i < corners.Count; i++ ) - { - Drawing.FillRectangle( data, - new Rectangle( corners[i].X - 2, corners[i].Y - 2, 5, 5 ), - Color.FromArgb( i * 32 + 127 + 32, i * 64, i * 64 ) ); - } - - image.UnlockBits( data ); - - - Source image: - - Result image: - - - - - - - Find corners of quadrilateral/triangular area in the specified image. - - - Source image to search quadrilateral for. - - Returns a list of points, which are corners of the quadrilateral/triangular area found - in the specified image. The first point in the list is the point with lowest - X coordinate (and with lowest Y if there are several points with the same X value). - Points are in clockwise order (screen coordinates system). - - Unsupported pixel format of the source image. - - - - - Find corners of quadrilateral/triangular area in the specified image. - - - Source image data to search quadrilateral for. - - Returns a list of points, which are corners of the quadrilateral/triangular area found - in the specified image. The first point in the list is the point with lowest - X coordinate (and with lowest Y if there are several points with the same X value). - Points are in clockwise order (screen coordinates system). - - Unsupported pixel format of the source image. - - - - - Find corners of quadrilateral/triangular area in the specified image. - - - Source image to search quadrilateral for. - - Returns a list of points, which are corners of the quadrilateral/triangular area found - in the specified image. The first point in the list is the point with lowest - X coordinate (and with lowest Y if there are several points with the same X value). - Points are in clockwise order (screen coordinates system). - - Unsupported pixel format of the source image. - - - - - Interface for custom blobs' filters used for filtering blobs after - blob counting. - - - The interface should be implemented by classes, which perform - custom blobs' filtering different from default filtering implemented in - . See - for additional information. - - - - - - Check specified blob and decide if should be kept or not. - - - Blob to check. - - Return if the blob should be kept or - if it should be removed. - - - - - Hough line. - - - Represents line of Hough Line transformation using - polar coordinates. - See Wikipedia - for information on how to convert polar coordinates to Cartesian coordinates. - - - Hough Line transformation does not provide - information about lines start and end points, only slope and distance from image's center. Using - only provided information it is not possible to draw the detected line as it exactly appears on - the source image. But it is possible to draw a line through the entire image, which contains the - source line (see sample code below). - - - Sample code to draw detected Hough lines: - - HoughLineTransformation lineTransform = new HoughLineTransformation( ); - // apply Hough line transofrm - lineTransform.ProcessImage( sourceImage ); - Bitmap houghLineImage = lineTransform.ToBitmap( ); - // get lines using relative intensity - HoughLine[] lines = lineTransform.GetLinesByRelativeIntensity( 0.5 ); - - foreach ( HoughLine line in lines ) - { - // get line's radius and theta values - int r = line.Radius; - double t = line.Theta; - - // check if line is in lower part of the image - if ( r < 0 ) - { - t += 180; - r = -r; - } - - // convert degrees to radians - t = ( t / 180 ) * Math.PI; - - // get image centers (all coordinate are measured relative - // to center) - int w2 = image.Width /2; - int h2 = image.Height / 2; - - double x0 = 0, x1 = 0, y0 = 0, y1 = 0; - - if ( line.Theta != 0 ) - { - // none-vertical line - x0 = -w2; // most left point - x1 = w2; // most right point - - // calculate corresponding y values - y0 = ( -Math.Cos( t ) * x0 + r ) / Math.Sin( t ); - y1 = ( -Math.Cos( t ) * x1 + r ) / Math.Sin( t ); - } - else - { - // vertical line - x0 = line.Radius; - x1 = line.Radius; - - y0 = h2; - y1 = -h2; - } - - // draw line on the image - Drawing.Line( sourceData, - new IntPoint( (int) x0 + w2, h2 - (int) y0 ), - new IntPoint( (int) x1 + w2, h2 - (int) y1 ), - Color.Red ); - } - - - To clarify meaning of and values - of detected Hough lines, let's take a look at the below sample image and - corresponding values of radius and theta for the lines on the image: - - - - - Detected radius and theta values (color in corresponding colors): - - Theta = 90, R = 125, I = 249; - Theta = 0, R = -170, I = 187 (converts to Theta = 180, R = 170); - Theta = 90, R = -58, I = 163 (converts to Theta = 270, R = 58); - Theta = 101, R = -101, I = 130 (converts to Theta = 281, R = 101); - Theta = 0, R = 43, I = 112; - Theta = 45, R = 127, I = 82. - - - - - - - - - - - Line's slope - angle between polar axis and line's radius (normal going - from pole to the line). Measured in degrees, [0, 180). - - - - - Line's distance from image center, (−∞, +∞). - - - Negative line's radius means, that the line resides in lower - part of the polar coordinates system. This means that value - should be increased by 180 degrees and radius should be made positive. - - - - - - Line's absolute intensity, (0, +∞). - - - Line's absolute intensity is a measure, which equals - to number of pixels detected on the line. This value is bigger for longer - lines. - - The value may not be 100% reliable to measure exact number of pixels - on the line. Although these value correlate a lot (which means they are very close - in most cases), the intensity value may slightly vary. - - - - - - Line's relative intensity, (0, 1]. - - - Line's relative intensity is relation of line's - value to maximum found intensity. For the longest line (line with highest intesity) the - relative intensity is set to 1. If line's relative is set 0.5, for example, this means - its intensity is half of maximum found intensity. - - - - - - Initializes a new instance of the class. - - - Line's slope. - Line's distance from image center. - Line's absolute intensity. - Line's relative intensity. - - - - - Compare the object with another instance of this class. - - - Object to compare with. - - A signed number indicating the relative values of this instance and value: 1) greater than zero - - this instance is greater than value; 2) zero - this instance is equal to value; - 3) greater than zero - this instance is less than value. - - The sort order is descending. - - - Object are compared using their intensity value. - - - - - - Hough line transformation. - - - The class implements Hough line transformation, which allows to detect - straight lines in an image. Lines, which are found by the class, are provided in - polar coordinates system - - lines' distances from image's center and lines' slopes are provided. - The pole of polar coordinates system is put into processing image's center and the polar - axis is directed to the right from the pole. Lines' slope is measured in degrees and - is actually represented by angle between polar axis and line's radius (normal going - from pole to the line), which is measured in counter-clockwise direction. - - - Found lines may have negative radius. - This means, that the line resides in lower part of the polar coordinates system - and its value should be increased by 180 degrees and - radius should be made positive. - - - The class accepts binary images for processing, which are represented by 8 bpp grayscale images. - All black pixels (0 pixel's value) are treated as background, but pixels with different value are - treated as lines' pixels. - - See also documentation to class for additional information - about Hough Lines. - - Sample usage: - - HoughLineTransformation lineTransform = new HoughLineTransformation( ); - // apply Hough line transofrm - lineTransform.ProcessImage( sourceImage ); - Bitmap houghLineImage = lineTransform.ToBitmap( ); - // get lines using relative intensity - HoughLine[] lines = lineTransform.GetLinesByRelativeIntensity( 0.5 ); - - foreach ( HoughLine line in lines ) - { - // ... - } - - - Initial image: - - Hough line transformation image: - - - - - - - - - Initializes a new instance of the class. - - - - - - Process an image building Hough map. - - - Source image to process. - - Unsupported pixel format of the source image. - - - - - Process an image building Hough map. - - - Source image to process. - Image's rectangle to process. - - Unsupported pixel format of the source image. - - - - - Process an image building Hough map. - - - Source image data to process. - - Unsupported pixel format of the source image. - - - - - Process an image building Hough map. - - - Source image data to process. - Image's rectangle to process. - - Unsupported pixel format of the source image. - - - - - Process an image building Hough map. - - - Source unmanaged image to process. - - Unsupported pixel format of the source image. - - - - - Process an image building Hough map. - - - Source unmanaged image to process. - Image's rectangle to process. - - Unsupported pixel format of the source image. - - - - - Convert Hough map to bitmap. - - - Returns 8 bppp grayscale bitmap, which shows Hough map. - - Hough transformation was not yet done by calling - ProcessImage() method. - - - - - Get specified amount of lines with highest intensity. - - - Amount of lines to get. - - Returns array of most intesive lines. If there are no lines detected, - the returned array has zero length. - - - - - Get lines with relative intensity higher then specified value. - - - Minimum relative intesity of lines. - - Returns array of lines. If there are no lines detected, - the returned array has zero length. - - - - - Steps per degree. - - - The value defines quality of Hough line transformation and its ability to detect - lines' slope precisely. - - Default value is set to 1. Minimum value is 1. Maximum value is 10. - - - - - Minimum line's intensity in Hough map to recognize a line. - - - The value sets minimum intensity level for a line. If a value in Hough - map has lower intensity, then it is not treated as a line. - - Default value is set to 10. - - - - - Radius for searching local peak value. - - - The value determines radius around a map's value, which is analyzed to determine - if the map's value is a local maximum in specified area. - - Default value is set to 4. Minimum value is 1. Maximum value is 10. - - - - - Maximum found intensity in Hough map. - - - The property provides maximum found line's intensity. - - - - - Found lines count. - - - The property provides total number of found lines, which intensity is higher (or equal to), - than the requested minimum intensity. - - - - - Performs quadrilateral transformation of an area in the source image. - - - The class implements simple algorithm described by - Olivier Thill - for transforming quadrilateral area from a source image into rectangular image. - The idea of the algorithm is based on finding for each line of destination - rectangular image a corresponding line connecting "left" and "right" sides of - quadrilateral in a source image. Then the line is linearly transformed into the - line in destination image. - - Due to simplicity of the algorithm it does not do any correction for perspective. - - - To make sure the algorithm works correctly, it is preferred if the - "left-top" corner of the quadrilateral (screen coordinates system) is - specified first in the list of quadrilateral's corners. At least - user need to make sure that the "left" side (side connecting first and the last - corner) and the "right" side (side connecting second and third corners) are - not horizontal. - - Use to avoid the above mentioned limitations, - which is a more advanced quadrilateral transformation algorithms (although a bit more - computationally expensive). - - The image processing filter accepts 8 grayscale images and 24/32 bpp - color images for processing. - - Sample usage: - - // define quadrilateral's corners - List<IntPoint> corners = new List<IntPoint>( ); - corners.Add( new IntPoint( 99, 99 ) ); - corners.Add( new IntPoint( 156, 79 ) ); - corners.Add( new IntPoint( 184, 126 ) ); - corners.Add( new IntPoint( 122, 150 ) ); - // create filter - SimpleQuadrilateralTransformation filter = - new SimpleQuadrilateralTransformation( corners, 200, 200 ); - // apply the filter - Bitmap newImage = filter.Apply( image ); - - - Initial image: - - Result image: - - - - - - - - - New image width. - - - - - New image height. - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Corners of the source quadrilateral area. - Width of the new transformed image. - Height of the new transformed image. - - This constructor sets to - , which means that destination image will have width and - height as specified by user. - - - - - Initializes a new instance of the class. - - - Corners of the source quadrilateral area. - - This constructor sets to - , which means that destination image will have width and - height automatically calculated based on property. - - - - - Calculates new image size. - - - Source image data. - - New image size - size of the destination image. - - Source quadrilateral was not set. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - - - - Format translations dictionary. - - - See - documentation for additional information. - - - - - Automatic calculation of destination image or not. - - - The property specifies how to calculate size of destination (transformed) - image. If the property is set to , then - and properties have effect and destination image's size is - specified by user. If the property is set to , then setting the above - mentioned properties does not have any effect, but destionation image's size is - automatically calculated from property - width and height - come from length of longest edges. - - - Default value is set to . - - - - - - Quadrilateral's corners in source image. - - - The property specifies four corners of the quadrilateral area - in the source image to be transformed. - - See documentation to the - class itself for additional information. - - - - - - Width of the new transformed image. - - - The property defines width of the destination image, which gets - transformed quadrilateral image. - - Setting the property does not have any effect, if - property is set to . In this case destination image's width - is calculated automatically based on property. - - - - - - Height of the new transformed image. - - - The property defines height of the destination image, which gets - transformed quadrilateral image. - - Setting the property does not have any effect, if - property is set to . In this case destination image's height - is calculated automatically based on property. - - - - - - Specifies if bilinear interpolation should be used or not. - - - Default value is set to - interpolation - is used. - - - - - - Texturer filter. - - - Adjust pixels’ color values using factors from the given texture. In conjunction with different type - of texture generators, the filter may produce different type of interesting effects. - - The filter uses specified texture to adjust values using the next formula:
- dst = src * + src * * textureValue,
- where src is value of pixel in a source image, dst is value of pixel in a destination image and - textureValue is corresponding value from provided texture (see or - ). Using and values it is possible - to control the portion of source data affected by texture. -
- - In most cases the and properties are set in such - way, that + = 1. But there is no limitations actually - for those values, so their sum may be as greater, as lower than 1 in order create different type of - effects. - - The filter accepts 8 bpp grayscale and 24 bpp color images for processing. - - Sample usage: - - // create filter - Texturer filter = new Texturer( new TextileTexture( ), 0.3, 0.7 ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - -
- -
- - - Initializes a new instance of the class. - - - Generated texture. - - - - - Initializes a new instance of the class. - - - Generated texture. - Filter level value (see property). - Preserve level value (see property). - - - - - Initializes a new instance of the class. - - - Texture generator. - - - - - Initializes a new instance of the class. - - - Texture generator. - Filter level value (see property). - Preserve level value (see property). - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - See for more information. - - - - - Filter level value. - - - Filtering factor determines image fraction to filter - to multiply - by values from the provided texture. - - Default value is set to 0.5. - - See class description for more details. - - - - - - Preserve level value. - - - Preserving factor determines image fraction to keep from filtering. - - Default value is set to 0.5. - - See class description for more details. - - - - - - Generated texture. - - - Two dimensional array of texture intensities. - - In the case if image passed to the filter is smaller or - larger than the specified texture, than image's region is processed, which equals to the - minimum overlapping area. - - The property has priority over this property - if - generator is specified than the static generated texture is not used. - - - - - - Texture generator. - - - Generator used to generate texture. - - The property has priority over the property. - - - - - - Luminance and saturation linear correction. - - - The filter operates in HSL color space and provides - with the facility of luminance and saturation linear correction - mapping specified channels' - input ranges to specified output ranges. - - The filter accepts 24 and 32 bpp color images for processing. - - Sample usage: - - // create filter - HSLLinear filter = new HSLLinear( ); - // configure the filter - filter.InLuminance = new Range( 0, 0.85f ); - filter.OutSaturation = new Range( 0.25f, 1 ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - - Initializes a new instance of the class. - - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Luminance input range. - - - Luminance component is measured in the range of [0, 1]. - - - - - Luminance output range. - - - Luminance component is measured in the range of [0, 1]. - - - - - Saturation input range. - - - Saturation component is measured in the range of [0, 1]. - - - - - Saturation output range. - - - Saturation component is measured in the range of [0, 1]. - - - - - Format translations dictionary. - - - - - Blur filter. - - - The filter performs convolution filter using - the blur kernel: - - - 1 2 3 2 1 - 2 4 5 4 2 - 3 5 6 5 3 - 2 4 5 4 2 - 1 2 3 2 1 - - - For the list of supported pixel formats, see the documentation to - filter. - - By default this filter sets property to - , so the alpha channel of 32 bpp and 64 bpp images is blurred as well. - - - Sample usage: - - // create filter - Blur filter = new Blur( ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - Initializes a new instance of the class. - - - - - Simple posterization of an image. - - - The class implements simple posterization of an image by splitting - each color plane into adjacent areas of the specified size. After the process - is done, each color plane will contain maximum of 256/PosterizationInterval levels. - For example, if grayscale image is posterized with posterization interval equal to 64, - then result image will contain maximum of 4 tones. If color image is posterized with the - same posterization interval, then it will contain maximum of 43=64 colors. - See property to get information about the way how to control - color used to fill posterization areas. - - Posterization is a process in photograph development which converts normal photographs - into an image consisting of distinct, but flat, areas of different tones or colors. - - The filter accepts 8 bpp grayscale and 24/32 bpp color images. - - Sample usage: - - // create filter - SimplePosterization filter = new SimplePosterization( ); - // process image - filter.ApplyInPlace( sourceImage ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Specifies filling type of posterization areas. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Posterization interval, which specifies size of posterization areas. - - - The property specifies size of adjacent posterization areas - for each color plane. The value has direct effect on the amount of colors - in the result image. For example, if grayscale image is posterized with posterization - interval equal to 64, then result image will contain maximum of 4 tones. If color - image is posterized with same posterization interval, then it will contain maximum - of 43=64 colors. - - Default value is set to 64. - - - - - - Posterization filling type. - - - The property controls the color, which is used to substitute - colors within the same posterization interval - minimum, maximum or average value. - - - Default value is set to . - - - - - - Format translations dictionary. - - - - - Enumeration of possible types of filling posterized areas. - - - - - Fill area with minimum color's value. - - - - - Fill area with maximum color's value. - - - - - Fill area with average color's value. - - - - - Dithering using Jarvis, Judice and Ninke error diffusion. - - - The filter represents binarization filter, which is based on - error diffusion dithering with Jarvis-Judice-Ninke coefficients. Error is diffused - on 12 neighbor pixels with next coefficients: - - | * | 7 | 5 | - | 3 | 5 | 7 | 5 | 3 | - | 1 | 3 | 5 | 3 | 1 | - - / 48 - - - The filter accepts 8 bpp grayscale images for processing. - - Sample usage: - - // create filter - JarvisJudiceNinkeDithering filter = new JarvisJudiceNinkeDithering( ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - - - - Initializes a new instance of the class. - - - - - - Median cut color quantization algorithm. - - - The class implements median cut - color quantization algorithm. - - See also class, which may simplify processing of images. - - Sample usage: - - // create the color quantization algorithm - IColorQuantizer quantizer = new MedianCutQuantizer( ); - // process colors (taken from image for example) - for ( int i = 0; i < pixelsToProcess; i++ ) - { - quantizer.AddColor( /* pixel color */ ); - } - // get palette reduced to 16 colors - Color[] palette = quantizer.GetPalette( 16 ); - - - - - - - - - Add color to the list of processed colors. - - - Color to add to the internal list. - - The method adds the specified color into internal list of processed colors. The list - is used later by method to build reduced color table of the specified size. - - - - - - Get paletter of the specified size. - - - Palette size to get. - - Returns reduced palette of the specified size, which covers colors processed so far. - - The method must be called after continuously calling method and - returns reduced color palette for colors accumulated/processed so far. - - - - - Clear internal state of the color quantization algorithm by clearing the list of colors - so far processed. - - - - - - Labirinth texture. - - - The texture generator creates textures with effect of labyrinth. - - The generator is based on the Perlin noise function. - - Sample usage: - - // create texture generator - LabyrinthTexture textureGenerator = new LabyrinthTexture( ); - // generate new texture - float[,] texture = textureGenerator.Generate( 320, 240 ); - // convert it to image to visualize - Bitmap textureImage = TextureTools.ToBitmap( texture ); - - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - - Generate texture. - - - Texture's width. - Texture's height. - - Two dimensional array of intensities. - - Generates new texture of the specified size. - - - - - Reset generator. - - - Regenerates internal random numbers. - - - - - Template matching algorithm's interface. - - - The interface specifies set of methods, which should be implemented by different - template matching algorithms - algorithms, which search for the given template in specified - image. - - - - - Process image looking for matchings with specified template. - - - Source image to process. - Template image to search for. - Rectangle in source image to search template for. - - Returns array of found matchings. - - - - - Process image looking for matchings with specified template. - - - Source image data to process. - Template image to search for. - Rectangle in source image to search template for. - - Returns array of found matchings. - - - - - Process image looking for matchings with specified template. - - - Unmanaged source image to process. - Unmanaged template image to search for. - Rectangle in source image to search template for. - - Returns array of found matchings. - - - - - Replace channel of YCbCr color space. - - - Replaces specified YCbCr channel of color image with - specified grayscale imge. - - The filter is quite useful in conjunction with filter - (however may be used alone in some cases). Using the filter - it is possible to extract one of YCbCr channel, perform some image processing with it and then - put it back into the original color image. - - The filter accepts 24 and 32 bpp color images for processing. - - Sample usage: - - // create YCbCrExtractChannel filter for channel extracting - YCbCrExtractChannel extractFilter = new YCbCrExtractChannel( - YCbCr.CbIndex ); - // extract Cb channel - Bitmap cbChannel = extractFilter.Apply( image ); - // invert the channel - Invert invertFilter = new Invert( ); - invertFilter.ApplyInPlace( cbChannel ); - // put the channel back into the source image - YCbCrReplaceChannel replaceFilter = new YCbCrReplaceChannel( - YCbCr.CbIndex, cbChannel ); - replaceFilter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - Initializes a new instance of the class. - - - YCbCr channel to replace. - Channel image to use for replacement. - - - - - Initializes a new instance of the class. - - - YCbCr channel to replace. - Unmanaged channel image to use for replacement. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - Channel image size does not match source - image size. - - - - - Format translations dictionary. - - - - - YCbCr channel to replace. - - - Default value is set to (Y channel). - - Invalid channel was specified. - - - - - Grayscale image to use for channel replacement. - - - - Setting this property will clear the property - - only one channel image is allowed: managed or unmanaged. - - - Channel image should be 8bpp indexed image (grayscale). - - - - - Unmanaged grayscale image to use for channel replacement. - - - - Setting this property will clear the property - - only one channel image is allowed: managed or unmanaged. - - - Channel image should be 8bpp indexed image (grayscale). - - - - - Adaptive Smoothing - noise removal with edges preserving. - - - The filter is aimed to perform image smoothing, but keeping sharp edges. - This makes it applicable to additive noise removal and smoothing objects' interiors, but - not applicable for spikes (salt and pepper noise) removal. - - The next calculations are done for each pixel: - - weights are calculate for 9 pixels - pixel itself and 8 neighbors: - - w(x, y) = exp( -1 * (Gx^2 + Gy^2) / (2 * factor^2) ) - Gx(x, y) = (I(x + 1, y) - I(x - 1, y)) / 2 - Gy(x, y) = (I(x, y + 1) - I(x, y - 1)) / 2 - , - where factor is a configurable value determining smoothing's quality. - sum of 9 weights is calclated (weightTotal); - sum of 9 weighted pixel values is calculatd (total); - destination pixel is calculated as total / weightTotal. - - - Description of the filter was found in "An Edge Detection Technique Using - the Facet Model and Parameterized Relaxation Labeling" by Ioannis Matalas, Student Member, - IEEE, Ralph Benjamin, and Richard Kitney. - - The filter accepts 8 bpp grayscale images and 24 bpp - color images for processing. - - Sample usage: - - // create filter - AdaptiveSmoothing filter = new AdaptiveSmoothing( ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Factor value. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Factor value. - - - Factor determining smoothing quality (see - documentation). - - Default value is set to 3. - - - - - - Blobs filtering by size. - - - The filter performs filtering of blobs by their size in the specified - source image - all blobs, which are smaller or bigger then specified limits, are - removed from the image. - - The image processing filter treats all none black pixels as objects' - pixels and all black pixel as background. - - The filter accepts 8 bpp grayscale images and 24/32 - color images for processing. - - Sample usage: - - // create filter - BlobsFiltering filter = new BlobsFiltering( ); - // configure filter - filter.CoupledSizeFiltering = true; - filter.MinWidth = 70; - filter.MinHeight = 70; - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Minimum allowed width of blob. - Minimum allowed height of blob. - Maximum allowed width of blob. - Maximum allowed height of blob. - - This constructor creates an instance of class - with property set to false. - - - - - Initializes a new instance of the class. - - - Minimum allowed width of blob. - Minimum allowed height of blob. - Maximum allowed width of blob. - Maximum allowed height of blob. - Specifies if size filetering should be coupled or not. - - For information about coupled filtering mode see documentation for - property of - class. - - - - - Initializes a new instance of the class. - - - Custom blobs' filtering routine to use - (see ). - - - - - Process the filter on the specified image. - - - Source image data. - - - - - Format translations dictionary. - - - - - Specifies if size filetering should be coupled or not. - - - See documentation for property - of class for more information. - - - - - Minimum allowed width of blob. - - - - - - Minimum allowed height of blob. - - - - - - Maximum allowed width of blob. - - - - - - Maximum allowed height of blob. - - - - - - Custom blobs' filter to use. - - - See for information - about custom blobs' filtering routine. - - - - - Hit-And-Miss operator from Mathematical Morphology. - - - The hit-and-miss filter represents generalization of - and filters by extending flexibility of structuring element and - providing different modes of its work. Structuring element may contain: - - 1 - foreground; - 0 - background; - -1 - don't care. - - - - Filter's mode is set by property. The list of modes and its - documentation may be found in enumeration. - - The filter accepts 8 bpp grayscale images for processing. Note: grayscale images are treated - as binary with 0 value equals to black and 255 value equals to white. - - Sample usage: - - // define kernel to remove pixels on the right side of objects - // (pixel is removed, if there is white pixel on the left and - // black pixel on the right) - short[,] se = new short[,] { - { -1, -1, -1 }, - { 1, 1, 0 }, - { -1, -1, -1 } - }; - // create filter - HitAndMiss filter = new HitAndMiss( se, HitAndMiss.Modes.Thinning ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - Structuring element. - - Structuring elemement for the hit-and-miss morphological operator - must be square matrix with odd size in the range of [3, 99]. - - Invalid size of structuring element. - - - - - Initializes a new instance of the class. - - - Structuring element. - Operation mode. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Operation mode. - - - Mode to use for the filter. See enumeration - for the list of available modes and their documentation. - - Default mode is set to . - - - - - Hit and Miss modes. - - - Bellow is a list of modes meaning depending on pixel's correspondence - to specified structuring element: - - - on match pixel is set to white, otherwise to black; - - on match pixel is set to black, otherwise not changed. - - on match pixel is set to white, otherwise not changed. - - - - - - - Hit and miss mode. - - - - - Thinning mode. - - - - - Thickening mode. - - - - - Homogenity edge detector. - - - The filter finds objects' edges by calculating maximum difference - of processing pixel with neighboring pixels in 8 direction. - - Suppose 3x3 square element of the source image (x - is currently processed - pixel): - - P1 P2 P3 - P8 x P4 - P7 P6 P5 - - The corresponding pixel of the result image equals to: - - max( |x-P1|, |x-P2|, |x-P3|, |x-P4|, - |x-P5|, |x-P6|, |x-P7|, |x-P8| ) - - - - The filter accepts 8 bpp grayscale images for processing. - - Sample usage: - - // create filter - HomogenityEdgeDetector filter = new HomogenityEdgeDetector( ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - - Initializes a new instance of the class. - - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Gaussian sharpen filter. - - - The filter performs convolution filter using - the kernel, which is calculate with the help of - method and then converted to integer sharpening kernel. First of all the integer kernel - is calculated from by dividing all elements by - the element with the smallest value. Then the integer kernel is converted to sharpen kernel by - negating all kernel's elements (multiplying with -1), but the central kernel's element - is calculated as 2 * sum - centralElement, where sum is the sum off elements - in the integer kernel before negating. - - For the list of supported pixel formats, see the documentation to - filter. - - Sample usage: - - // create filter with kernel size equal to 11 - // and Gaussia sigma value equal to 4.0 - GaussianSharpen filter = new GaussianSharpen( 4, 11 ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Gaussian sigma value. - - - - - Initializes a new instance of the class. - - - Gaussian sigma value. - Kernel size. - - - - - Gaussian sigma value, [0.5, 5.0]. - - - Sigma value for Gaussian function used to calculate - the kernel. - - Default value is set to 1.4. - - - - - - Kernel size, [3, 5]. - - - Size of Gaussian kernel. - - Default value is set to 5. - - - - - - Merge filter - get MAX of pixels in two images. - - - The merge filter takes two images (source and overlay images) - of the same size and pixel format and produces an image, where each pixel equals - to the maximum value of corresponding pixels from provided images. - - The filter accepts 8 and 16 bpp grayscale images and 24, 32, 48 and 64 bpp - color images for processing. - - Sample usage: - - // create filter - Merge filter = new Merge( overlayImage ); - // apply the filter - Bitmap resultImage = filter.Apply( sourceImage ); - - - Source image: - - Overlay image: - - Result image: - - - - - - - - - - - - Initializes a new instance of the class - - - - - Initializes a new instance of the class. - - - Overlay image. - - - - - Initializes a new instance of the class. - - - Unmanaged overlay image. - - - - - Process the filter on the specified image. - - - Source image data. - Overlay image data. - - - - - Format translations dictionary. - - - - - Skew angle checker for scanned documents. - - - The class implements document's skew checking algorithm, which is based - on Hough line transformation. The algorithm - is based on searching for text base lines - black line of text bottoms' followed - by white line below. - - The routine supposes that a white-background document is provided - with black letters. The algorithm is not supposed for any type of objects, but for - document images with text. - - The range of angles to detect is controlled by property. - - The filter accepts 8 bpp grayscale images for processing. - - Sample usage: - - // create instance of skew checker - DocumentSkewChecker skewChecker = new DocumentSkewChecker( ); - // get documents skew angle - double angle = skewChecker.GetSkewAngle( documentImage ); - // create rotation filter - RotateBilinear rotationFilter = new RotateBilinear( -angle ); - rotationFilter.FillColor = Color.White; - // rotate image applying the filter - Bitmap rotatedImage = rotationFilter.Apply( documentImage ); - - - Initial image: - - Deskewed image: - - - - - - - - - Initializes a new instance of the class. - - - - - Get skew angle of the provided document image. - - - Document's image to get skew angle of. - - Returns document's skew angle. If the returned angle equals to -90, - then document skew detection has failed. - - Unsupported pixel format of the source image. - - - - - Get skew angle of the provided document image. - - - Document's image to get skew angle of. - Image's rectangle to process (used to exclude processing of - regions, which are not relevant to skew detection). - - Returns document's skew angle. If the returned angle equals to -90, - then document skew detection has failed. - - Unsupported pixel format of the source image. - - - - - Get skew angle of the provided document image. - - - Document's image data to get skew angle of. - - Returns document's skew angle. If the returned angle equals to -90, - then document skew detection has failed. - - Unsupported pixel format of the source image. - - - - - Get skew angle of the provided document image. - - - Document's image data to get skew angle of. - Image's rectangle to process (used to exclude processing of - regions, which are not relevant to skew detection). - - Returns document's skew angle. If the returned angle equals to -90, - then document skew detection has failed. - - Unsupported pixel format of the source image. - - - - - Get skew angle of the provided document image. - - - Document's unmanaged image to get skew angle of. - - Returns document's skew angle. If the returned angle equals to -90, - then document skew detection has failed. - - Unsupported pixel format of the source image. - - - - - Get skew angle of the provided document image. - - - Document's unmanaged image to get skew angle of. - Image's rectangle to process (used to exclude processing of - regions, which are not relevant to skew detection). - - Returns document's skew angle. If the returned angle equals to -90, - then document skew detection has failed. - - Unsupported pixel format of the source image. - - - - - Steps per degree, [1, 10]. - - - The value defines quality of Hough transform and its ability to detect - line slope precisely. - - Default value is set to 1. - - - - - - Maximum skew angle to detect, [0, 45] degrees. - - - The value sets maximum document's skew angle to detect. - Document's skew angle can be as positive (rotated counter clockwise), as negative - (rotated clockwise). So setting this value to 25, for example, will lead to - [-25, 25] degrees detection range. - - Scanned documents usually have skew in the [-20, 20] degrees range. - - Default value is set to 30. - - - - - - Minimum angle to detect skew in degrees. - - - The property is deprecated and setting it has not any effect. - Use property instead. - - - - - Maximum angle to detect skew in degrees. - - - The property is deprecated and setting it has not any effect. - Use property instead. - - - - - Radius for searching local peak value, [1, 10]. - - - The value determines radius around a map's value, which is analyzed to determine - if the map's value is a local maximum in specified area. - - Default value is set to 4. - - - - - Wood texture. - - - The texture generator creates textures with effect of - rings on trunk's shear. The property allows to specify the - desired amount of wood rings. - - The generator is based on the Perlin noise function. - - Sample usage: - - // create texture generator - WoodTexture textureGenerator = new WoodTexture( ); - // generate new texture - float[,] texture = textureGenerator.Generate( 320, 240 ); - // convert it to image to visualize - Bitmap textureImage = TextureTools.ToBitmap( texture ); - - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Wood rings amount. - - - - - Generate texture. - - - Texture's width. - Texture's height. - - Two dimensional array of intensities. - - Generates new texture of the specified size. - - - - - Reset generator. - - - Regenerates internal random numbers. - - - - - Wood rings amount, ≥ 3. - - - The property sets the amount of wood rings, which make effect of - rings on trunk's shear. - - Default value is set to 12. - - - - - Internal memory manager used by image processing routines. - - - The memory manager supports memory allocation/deallocation - caching. Caching means that memory blocks may be not freed on request, but - kept for later reuse. - - - - - Allocate unmanaged memory. - - - Memory size to allocate. - - Return's pointer to the allocated memory buffer. - - The method allocates requested amount of memory and returns pointer to it. It may avoid allocation - in the case some caching scheme is uses and there is already enough allocated memory available. - - There is insufficient memory to satisfy the request. - - - - - Free unmanaged memory. - - - Pointer to memory buffer to free. - - This method may skip actual deallocation of memory and keep it for future requests, - if some caching scheme is used. - - - - - Force freeing unused memory. - - - Frees and removes from cache memory blocks, which are not used by users. - - Returns number of freed memory blocks. - - - - - Maximum amount of memory blocks to keep in cache. - - - The value specifies the amount of memory blocks, which could be - cached by the memory manager. - - Default value is set to 3. Maximum value is 10. - - - - - - Current amount of memory blocks in cache. - - - - - - Amount of busy memory blocks in cache (which were not freed yet by user). - - - - - - Amount of free memory blocks in cache (which are not busy by users). - - - - - - Amount of cached memory in bytes. - - - - - - Maximum memory block's size in bytes, which could be cached. - - - Memory blocks, which size is greater than this value, are not cached. - - - - - Minimum memory block's size in bytes, which could be cached. - - - Memory blocks, which size is less than this value, are not cached. - - - - - Extract YCbCr channel from image. - - - The filter extracts specified YCbCr channel of color image and returns - it in the form of grayscale image. - - The filter accepts 24 and 32 bpp color images and produces - 8 bpp grayscale images. - - Sample usage: - - // create filter - YCbCrExtractChannel filter = new YCbCrExtractChannel( YCbCr.CrIndex ); - // apply the filter - Bitmap crChannel = filter.Apply( image ); - - - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - YCbCr channel to extract. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - - - - Format translations dictionary. - - - - - YCbCr channel to extract. - - - Default value is set to (Y channel). - - Invalid channel was specified. - - - - - Resize image using nearest neighbor algorithm. - - - The class implements image resizing filter using nearest - neighbor algorithm, which does not assume any interpolation. - - The filter accepts 8 and 16 bpp grayscale images and 24, 32, 48 and 64 bpp - color images for processing. - - Sample usage: - - // create filter - ResizeNearestNeighbor filter = new ResizeNearestNeighbor( 400, 300 ); - // apply the filter - Bitmap newImage = filter.Apply( image ); - - - Initial image: - - Result image: - - - - - - - - - - Initializes a new instance of the class. - - - Width of the new image. - Height of the new image. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - - - - Format translations dictionary. - - - - - Crop an image. - - - - The filter crops an image providing a new image, which contains only the specified - rectangle of the original image. - - The filter accepts 8 and 16 bpp grayscale images and 24, 32, 48 and 64 bpp - color images for processing. - - Sample usage: - - // create filter - Crop filter = new Crop( new Rectangle( 75, 75, 320, 240 ) ); - // apply the filter - Bitmap newImage = filter.Apply( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - Rectangle to crop. - - - - - Calculates new image size. - - - Source image data. - - New image size - size of the destination image. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - - - - Format translations dictionary. - - - - - Rectangle to crop. - - - - - Flood filling with specified color starting from specified point. - - - The filter performs image's area filling (4 directional) starting - from the specified point. It fills - the area of the pointed color, but also fills other colors, which - are similar to the pointed within specified tolerance. - The area is filled using specified fill color. - - - The filter accepts 8 bpp grayscale images and 24 bpp - color images for processing. - - Sample usage: - - // create filter - PointedColorFloodFill filter = new PointedColorFloodFill( ); - // configure the filter - filter.Tolerance = Color.FromArgb( 150, 92, 92 ); - filter.FillColor = Color.FromArgb( 255, 255, 255 ); - filter.StartingPoint = new IntPoint( 150, 100 ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Fill color. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Flood fill tolerance. - - - The tolerance value determines which colors to fill. If the - value is set to 0, then only color of the pointed pixel - is filled. If the value is not 0, then other colors may be filled as well, - which are similar to the color of the pointed pixel within the specified - tolerance. - - The tolerance value is specified as , - where each component (R, G and B) represents tolerance for the corresponding - component of color. This allows to set different tolerances for red, green - and blue components. - - - - - - Fill color. - - - The fill color is used to fill image's area starting from the - specified point. - - For grayscale images the color needs to be specified with all three - RGB values set to the same value, (128, 128, 128) for example. - - Default value is set to black. - - - - - - Point to start filling from. - - - The property allows to set the starting point, where filling is - started from. - - Default value is set to (0, 0). - - - - - - Erosion operator from Mathematical Morphology with 3x3 structuring element. - - - The filter represents an optimized version of - filter, which is aimed for grayscale image processing with 3x3 structuring element. - - See filter, which represents generic version of - erosion filter supporting custom structuring elements and wider range of image formats. - - The filter accepts 8 bpp grayscale images for processing. - - - - - - - - - Initializes a new instance of the class. - - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - Image rectangle for processing by the filter. - - Processing rectangle mast be at least 3x3 in size. - - - - - Format translations dictionary. - - - - - Flat field correction filter. - - - The goal of flat-field correction is to remove artifacts from 2-D images that - are caused by variations in the pixel-to-pixel sensitivity of the detector and/or by distortions - in the optical path. The filter requires two images for the input - source image, which represents - acquisition of some objects (using microscope, for example), and background image, which is taken - without any objects presented. The source image is corrected using the formula: src = bgMean * src / bg, - where src - source image's pixel value, bg - background image's pixel value, bgMean - mean - value of background image. - - If background image is not provided, then it will be automatically generated on each filter run - from source image. The automatically generated background image is produced running Gaussian Blur on the - original image with (sigma value is set to 5, kernel size is set to 21). Before blurring the original image - is resized to 1/3 of its original size and then the result of blurring is resized back to the original size. - - - The class processes only grayscale (8 bpp indexed) and color (24 bpp) images. - - Sample usage: - - // create filter - FlatFieldCorrection filter = new FlatFieldCorrection( bgImage ); - // process image - filter.ApplyInPlace( sourceImage ); - - - Source image: - - Background image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - This constructor does not set background image, which means that background - image will be generated on the fly on each filter run. The automatically generated background - image is produced running Gaussian Blur on the original image with (sigma value is set to 5, - kernel size is set to 21). Before blurring the original image is resized to 1/3 of its original size - and then the result of blurring is resized back to the original size. - - - - - Initializes a new instance of the class. - - - Background image used for flat field correction. - - - - - Process the filter on the specified image. - - - Source image data. - - - - - Background image used for flat field correction. - - - The property sets the background image (without any objects), which will be used - for illumination correction of an image passed to the filter. - - The background image must have the same size and pixel format as source image. - Otherwise exception will be generated when filter is applied to source image. - - Setting this property will clear the property - - only one background image is allowed: managed or unmanaged. - - - - - - Background image used for flat field correction. - - - The property sets the background image (without any objects), which will be used - for illumination correction of an image passed to the filter. - - The background image must have the same size and pixel format as source image. - Otherwise exception will be generated when filter is applied to source image. - - Setting this property will clear the property - - only one background image is allowed: managed or unmanaged. - - - - - - Format translations dictionary. - - - See for more information. - - - - - Color filtering in HSL color space. - - - The filter operates in HSL color space and filters - pixels, which color is inside/outside of the specified HSL range - - it keeps pixels with colors inside/outside of the specified range and fills the - rest with specified color. - - The filter accepts 24 and 32 bpp color images for processing. - - Sample usage: - - // create filter - HSLFiltering filter = new HSLFiltering( ); - // set color ranges to keep - filter.Hue = new IntRange( 335, 0 ); - filter.Saturation = new Range( 0.6f, 1 ); - filter.Luminance = new Range( 0.1f, 1 ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - Sample usage with saturation update only: - - // create filter - HSLFiltering filter = new HSLFiltering( ); - // configure the filter - filter.Hue = new IntRange( 340, 20 ); - filter.UpdateLuminance = false; - filter.UpdateHue = false; - // apply the filter - filter.ApplyInPlace( image ); - - - Result image: - - - - - - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Range of hue component. - Range of saturation component. - Range of luminance component. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Range of hue component, [0, 359]. - - - Because of hue values are cycled, the minimum value of the hue - range may have bigger integer value than the maximum value, for example [330, 30]. - - - - - Range of saturation component, [0, 1]. - - - - - Range of luminance component, [0, 1]. - - - - - Fill color used to fill filtered pixels. - - - - - Determines, if pixels should be filled inside or outside specified - color range. - - - Default value is set to , which means - the filter removes colors outside of the specified range. - - - - - Determines, if hue value of filtered pixels should be updated. - - - The property specifies if hue of filtered pixels should be - updated with value from fill color or not. - - Default value is set to . - - - - - Determines, if saturation value of filtered pixels should be updated. - - - The property specifies if saturation of filtered pixels should be - updated with value from fill color or not. - - Default value is set to . - - - - - Determines, if luminance value of filtered pixels should be updated. - - - The property specifies if luminance of filtered pixels should be - updated with value from fill color or not. - - Default value is set to . - - - - - Gaussian blur filter. - - - The filter performs convolution filter using - the kernel, which is calculate with the help of - method and then converted to integer kernel by dividing all elements by the element with the - smallest value. Using the kernel the convolution filter is known as Gaussian blur. - - Using property it is possible to configure - sigma value of Gaussian function. - - For the list of supported pixel formats, see the documentation to - filter. - - By default this filter sets property to - , so the alpha channel of 32 bpp and 64 bpp images is blurred as well. - - - Sample usage: - - // create filter with kernel size equal to 11 - // and Gaussia sigma value equal to 4.0 - GaussianBlur filter = new GaussianBlur( 4, 11 ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Gaussian sigma value. - - - - - Initializes a new instance of the class. - - - Gaussian sigma value. - Kernel size. - - - - - Gaussian sigma value, [0.5, 5.0]. - - - Sigma value for Gaussian function used to calculate - the kernel. - - Default value is set to 1.4. - - - - - - Kernel size, [3, 21]. - - - Size of Gaussian kernel. - - Default value is set to 5. - - - - - - Simple edge detector. - - - The filter performs convolution filter using - the edges kernel: - - - 0 -1 0 - -1 4 -1 - 0 -1 0 - - - For the list of supported pixel formats, see the documentation to - filter. - - Sample usage: - - // create filter - Edges filter = new Edges( ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - Initializes a new instance of the class. - - - - - Base class for filters, which operate with two images of the same size and format and - produce new image as a result. - - - The abstract class is the base class for all filters, which can - be applied to an image producing new image as a result of image processing. - - The base class is aimed for such type of filters, which require additional image - to process the source image. The additional image is set by - or property and must have the same size and pixel format - as source image. See documentation of particular inherited class for information - about overlay image purpose. - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Overlay image. - - - - - Initializes a new instance of the class. - - - Unmanaged overlay image. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - - - - Process the filter on the specified image. - - - Source image data. - Overlay image data. - Destination image data - - Overlay image size and pixel format is checked by this base class, before - passing execution to inherited class. - - - - - Overlay image. - - - - The property sets an overlay image, which will be used as the second image required - to process source image. See documentation of particular inherited class for information - about overlay image purpose. - - - Overlay image must have the same size and pixel format as source image. - Otherwise exception will be generated when filter is applied to source image. - - Setting this property will clear the property - - only one overlay image is allowed: managed or unmanaged. - - - - - - Unmanaged overlay image. - - - - The property sets an overlay image, which will be used as the second image required - to process source image. See documentation of particular inherited class for information - about overlay image purpose. - - - Overlay image must have the same size and pixel format as source image. - Otherwise exception will be generated when filter is applied to source image. - - Setting this property will clear the property - - only one overlay image is allowed: managed or unmanaged. - - - - - - Otsu thresholding. - - - The class implements Otsu thresholding, which is described in - N. Otsu, "A threshold selection method from gray-level histograms", IEEE Trans. Systems, - Man and Cybernetics 9(1), pp. 62–66, 1979. - - This implementation instead of minimizing the weighted within-class variance - does maximization of between-class variance, what gives the same result. The approach is - described in this presentation. - - The filter accepts 8 bpp grayscale images for processing. - - Sample usage: - - // create filter - OtsuThreshold filter = new OtsuThreshold( ); - // apply the filter - filter.ApplyInPlace( image ); - // check threshold value - byte t = filter.ThresholdValue; - // ... - - - Initial image: - - Result image (calculated threshold is 97): - - - - - - - - - - Initializes a new instance of the class. - - - - - - Calculate binarization threshold for the given image. - - - Image to calculate binarization threshold for. - Rectangle to calculate binarization threshold for. - - Returns binarization threshold. - - The method is used to calculate binarization threshold only. The threshold - later may be applied to the image using image processing filter. - - Source pixel format is not supported by the routine. It should be - 8 bpp grayscale (indexed) image. - - - - - Calculate binarization threshold for the given image. - - - Image to calculate binarization threshold for. - Rectangle to calculate binarization threshold for. - - Returns binarization threshold. - - The method is used to calculate binarization threshold only. The threshold - later may be applied to the image using image processing filter. - - Source pixel format is not supported by the routine. It should be - 8 bpp grayscale (indexed) image. - - - - - Calculate binarization threshold for the given image. - - - Image to calculate binarization threshold for. - Rectangle to calculate binarization threshold for. - - Returns binarization threshold. - - The method is used to calculate binarization threshold only. The threshold - later may be applied to the image using image processing filter. - - Source pixel format is not supported by the routine. It should be - 8 bpp grayscale (indexed) image. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Threshold value. - - - The property is read only and represents the value, which - was automaticaly calculated using Otsu algorithm. - - - - - Iterative threshold search and binarization. - - - - The algorithm works in the following way: - - select any start threshold; - compute average value of Background (µB) and Object (µO) values: - 1) all pixels with a value that is below threshold, belong to the Background values; - 2) all pixels greater or equal threshold, belong to the Object values. - - calculate new thresghold: (µB + µO) / 2; - if |oldThreshold - newThreshold| is less than a given manimum allowed error, then stop iteration process - and create the binary image with the new threshold. - - - - For additional information see Digital Image Processing, Gonzalez/Woods. Ch.10 page:599. - - The filter accepts 8 and 16 bpp grayscale images for processing. - - Since the filter can be applied as to 8 bpp and to 16 bpp images, - the initial value of property should be set appropriately to the - pixel format. In the case of 8 bpp images the threshold value is in the [0, 255] range, but - in the case of 16 bpp images the threshold value is in the [0, 65535] range. - - Sample usage: - - // create filter - IterativeThreshold filter = new IterativeThreshold( 2, 128 ); - // apply the filter - Bitmap newImage = filter.Apply( image ); - - - Initial image: - - Result image (calculated threshold is 102): - - - - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Minimum allowed error, that ends the iteration process. - - - - - Initializes a new instance of the class. - - - Minimum allowed error, that ends the iteration process. - Initial threshold value. - - - - - Calculate binarization threshold for the given image. - - - Image to calculate binarization threshold for. - Rectangle to calculate binarization threshold for. - - Returns binarization threshold. - - The method is used to calculate binarization threshold only. The threshold - later may be applied to the image using image processing filter. - - Source pixel format is not supported by the routine. It should - 8 bpp grayscale (indexed) or 16 bpp grayscale image. - - - - - Calculate binarization threshold for the given image. - - - Image to calculate binarization threshold for. - Rectangle to calculate binarization threshold for. - - Returns binarization threshold. - - The method is used to calculate binarization threshold only. The threshold - later may be applied to the image using image processing filter. - - Source pixel format is not supported by the routine. It should - 8 bpp grayscale (indexed) or 16 bpp grayscale image. - - - - - Calculate binarization threshold for the given image. - - - Image to calculate binarization threshold for. - Rectangle to calculate binarization threshold for. - - Returns binarization threshold. - - The method is used to calculate binarization threshold only. The threshold - later may be applied to the image using image processing filter. - - Source pixel format is not supported by the routine. It should - 8 bpp grayscale (indexed) or 16 bpp grayscale image. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Minimum error, value when iterative threshold search is stopped. - - - Default value is set to 0. - - - - - Calculate Euclidean difference between two images and threshold it. - - - The filter produces similar to , however it uses - Euclidean distance for finding difference between pixel values instead of Manhattan distance. Result of this - image processing routine may be useful in motion detection applications or finding areas of significant - difference. - - The filter accepts 8 and 24/32color images for processing. - - Sample usage: - - // create filter - ThresholdedEuclideanDifference filter = new ThresholdedEuclideanDifference( 60 ); - // apply the filter - filter.OverlayImage = backgroundImage; - Bitmap resultImage = filter.Apply( sourceImage ); - - - Source image: - - Background image: - - Result image: - - - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Difference threshold (see ). - - - - - Process the filter on the specified image. - - - Source image data. - Overlay image data. - Destination image data - - - - - Difference threshold. - - - The property specifies difference threshold. If difference between pixels of processing image - and overlay image is greater than this value, then corresponding pixel of result image is set to white; otherwise - black. - - - Default value is set to 15. - - - - - Number of pixels which were set to white in destination image during last image processing call. - - - The property may be useful to determine amount of difference between two images which, - for example, may be treated as amount of motion in motion detection applications, etc. - - - - - Format translations dictionary. - - - See for more information. - - - - - Intersect filter - get MIN of pixels in two images. - - - The intersect filter takes two images (source and overlay images) - of the same size and pixel format and produces an image, where each pixel equals - to the minimum value of corresponding pixels from provided images. - - The filter accepts 8 and 16 bpp grayscale images and 24, 32, 48 and 64 bpp - color images for processing. - - Sample usage: - - // create filter - Intersect filter = new Intersect( overlayImage ); - // apply the filter - Bitmap resultImage = filter.Apply( sourceImage ); - - - Source image: - - Overlay image: - - Result image: - - - - - - - - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Overlay image. - - - - - Initializes a new instance of the class. - - - Unmanaged overlay image. - - - - - Process the filter on the specified image. - - - Source image data. - Overlay image data. - - - - - Format translations dictionary. - - - - - Color dithering using Sierra error diffusion. - - - The image processing routine represents color dithering algorithm, which is based on - error diffusion dithering with Sierra coefficients. Error is diffused - on 10 neighbor pixels with next coefficients: - - | * | 5 | 3 | - | 2 | 4 | 5 | 4 | 2 | - | 2 | 3 | 2 | - - / 32 - - - The image processing routine accepts 24/32 bpp color images for processing. As a result this routine - produces 4 bpp or 8 bpp indexed image, which depends on size of the specified - color table - 4 bpp result for - color tables with 16 colors or less; 8 bpp result for larger color tables. - - Sample usage: - - // create dithering routine (use default color table) - SierraColorDithering dithering = new SierraColorDithering( ); - // apply the dithering routine - Bitmap newImage = dithering.Apply( image ); - - - Initial image: - - Result image: - - - - - - - - - - - - Initializes a new instance of the class. - - - - - - Texture tools. - - - The class represents collection of different texture tools, like - converting a texture to/from grayscale image. - - Sample usage: - - // create texture generator - WoodTexture textureGenerator = new WoodTexture( ); - // generate new texture - float[,] texture = textureGenerator.Generate( 320, 240 ); - // convert it to image to visualize - Bitmap textureImage = TextureTools.ToBitmap( texture ); - - - - - - - Convert texture to grayscale bitmap. - - - Texture to convert to bitmap. - - Returns bitmap of the texture. - - - - - Convert grayscale bitmap to texture. - - - Image to convert to texture. - - Returns texture as 2D float array. - - Only grayscale (8 bpp indexed images) are supported. - - - - - Convert grayscale bitmap to texture - - - Image data to convert to texture - - Returns texture as 2D float array. - - Only grayscale (8 bpp indexed images) are supported. - - - - - Convert grayscale bitmap to texture. - - - Image data to convert to texture. - - Returns texture as 2D float array. - - Only grayscale (8 bpp indexed images) are supported. - - - - - Textile texture. - - - The texture generator creates textures with effect of textile. - - The generator is based on the Perlin noise function. - - Sample usage: - - // create texture generator - TextileTexture textureGenerator = new TextileTexture( ); - // generate new texture - float[,] texture = textureGenerator.Generate( 320, 240 ); - // convert it to image to visualize - Bitmap textureImage = TextureTools.ToBitmap( texture ); - - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - - Generate texture. - - - Texture's width. - Texture's height. - - Two dimensional array of intensities. - - Generates new texture of the specified size. - - - - - Reset generator. - - - Regenerates internal random numbers. - - - - - Blob counter based on recursion. - - - The class counts and extracts stand alone objects in - images using recursive version of connected components labeling - algorithm. - - The algorithm treats all pixels with values less or equal to - as background, but pixels with higher values are treated as objects' pixels. - - Since this algorithm is based on recursion, it is - required to be careful with its application to big images with big blobs, - because in this case recursion will require big stack size and may lead - to stack overflow. The recursive version may be applied (and may be even - faster than ) to an image with small blobs - - "star sky" image (or small cells, for example, etc). - - For blobs' searching the class supports 8 bpp indexed grayscale images and - 24/32 bpp color images. - See documentation about for information about which - pixel formats are supported for extraction of blobs. - - Sample usage: - - // create an instance of blob counter algorithm - RecursiveBlobCounter bc = new RecursiveBlobCounter( ); - // process binary image - bc.ProcessImage( image ); - Rectangle[] rects = bc.GetObjectsRectangles( ); - // process blobs - foreach ( Rectangle rect in rects ) - { - // ... - } - - - - - - - Base class for different blob counting algorithms. - - - The class is abstract and serves as a base for different blob counting algorithms. - Classes, which inherit from this base class, require to implement - method, which does actual building of object's label's map. - - For blobs' searcing usually all inherited classes accept binary images, which are actually - grayscale thresholded images. But the exact supported format should be checked in particular class, - inheriting from the base class. For blobs' extraction the class supports grayscale (8 bpp indexed) - and color images (24 and 32 bpp). - - Sample usage: - - // create an instance of blob counter algorithm - BlobCounterBase bc = new ... - // set filtering options - bc.FilterBlobs = true; - bc.MinWidth = 5; - bc.MinHeight = 5; - // process binary image - bc.ProcessImage( image ); - Blob[] blobs = bc.GetObjects( image, false ); - // process blobs - foreach ( Blob blob in blobs ) - { - // ... - // blob.Rectangle - blob's rectangle - // blob.Image - blob's image - } - - - - - - - Objects count. - - - - - Objects' labels. - - - - - Width of processed image. - - - - - Height of processed image. - - - - - Initializes a new instance of the class. - - - Creates new instance of the class with - an empty objects map. Before using methods, which provide information about blobs - or extract them, the , - or - method should be called to collect objects map. - - - - - Initializes a new instance of the class. - - - Binary image to look for objects in. - - Creates new instance of the class with - initialized objects map built by calling method. - - - - - Initializes a new instance of the class. - - - Binary image data to look for objects in. - - Creates new instance of the class with - initialized objects map built by calling method. - - - - - Initializes a new instance of the class. - - - Unmanaged binary image to look for objects in. - - Creates new instance of the class with - initialized objects map built by calling method. - - - - - Build objects map. - - - Source binary image. - - Processes the image and builds objects map, which is used later to extracts blobs. - - Unsupported pixel format of the source image. - - - - - Build objects map. - - - Source binary image data. - - Processes the image and builds objects map, which is used later to extracts blobs. - - Unsupported pixel format of the source image. - - - - - Build object map from raw image data. - - - Source unmanaged binary image data. - - Processes the image and builds objects map, which is used later to extracts blobs. - - Unsupported pixel format of the source image. - Thrown by some inherited classes if some image property other - than the pixel format is not supported. See that class's documentation or the exception message for details. - - - - - Get objects' rectangles. - - - Returns array of objects' rectangles. - - The method returns array of objects rectangles. Before calling the - method, the , - or method should be called, which will - build objects map. - - No image was processed before, so objects' rectangles - can not be collected. - - - - - Get objects' information. - - - Returns array of partially initialized blobs (without property initialized). - - By the amount of provided information, the method is between and - methods. The method provides array of blobs without initialized their image. - Blob's image may be extracted later using - or method. - - - - - // create blob counter and process image - BlobCounter bc = new BlobCounter( sourceImage ); - // specify sort order - bc.ObjectsOrder = ObjectsOrder.Size; - // get objects' information (blobs without image) - Blob[] blobs = bc.GetObjectInformation( ); - // process blobs - foreach ( Blob blob in blobs ) - { - // check blob's properties - if ( blob.Rectangle.Width > 50 ) - { - // the blob looks interesting, let's extract it - bc.ExtractBlobsImage( sourceImage, blob ); - } - } - - - - No image was processed before, so objects' information - can not be collected. - - - - - Get blobs. - - - Source image to extract objects from. - - Returns array of blobs. - Specifies size of blobs' image to extract. - If set to each blobs' image will have the same size as - the specified image. If set to each blobs' image will - have the size of its blob. - - The method returns array of blobs. Before calling the - method, the , - or method should be called, which will build - objects map. - - The method supports 24/32 bpp color and 8 bpp indexed grayscale images. - - - Unsupported pixel format of the provided image. - No image was processed before, so objects - can not be collected. - - - - - Get blobs. - - - Source unmanaged image to extract objects from. - Specifies size of blobs' image to extract. - If set to each blobs' image will have the same size as - the specified image. If set to each blobs' image will - have the size of its blob. - - Returns array of blobs. - - The method returns array of blobs. Before calling the - method, the , - or method should be called, which will build - objects map. - - The method supports 24/32 bpp color and 8 bpp indexed grayscale images. - - - Unsupported pixel format of the provided image. - No image was processed before, so objects - can not be collected. - - - - - Extract blob's image. - - - Source image to extract blob's image from. - Blob which is required to be extracted. - Specifies size of blobs' image to extract. - If set to each blobs' image will have the same size as - the specified image. If set to each blobs' image will - have the size of its blob. - - The method is used to extract image of partially initialized blob, which - was provided by method. Before calling the - method, the , - or method should be called, which will build - objects map. - - The method supports 24/32 bpp color and 8 bpp indexed grayscale images. - - - Unsupported pixel format of the provided image. - No image was processed before, so blob - can not be extracted. - - - - - Extract blob's image. - - - Source unmanaged image to extract blob's image from. - Blob which is required to be extracted. - Specifies size of blobs' image to extract. - If set to each blobs' image will have the same size as - the specified image. If set to each blobs' image will - have the size of its blob. - - The method is used to extract image of partially initialized blob, which - was provided by method. Before calling the - method, the , - or method should be called, which will build - objects map. - - The method supports 24/32 bpp color and 8 bpp indexed grayscale images. - - - Unsupported pixel format of the provided image. - No image was processed before, so blob - can not be extracted. - - - - - Get list of points on the left and right edges of the blob. - - - Blob to collect edge points for. - List of points on the left edge of the blob. - List of points on the right edge of the blob. - - The method scans each line of the blob and finds the most left and the - most right points for it adding them to appropriate lists. The method may be very - useful in conjunction with different routines from , - which allow finding convex hull or quadrilateral's corners. - - Both lists of points are sorted by Y coordinate - points with smaller Y - value go first. - - - No image was processed before, so blob - can not be extracted. - - - - - Get list of points on the top and bottom edges of the blob. - - - Blob to collect edge points for. - List of points on the top edge of the blob. - List of points on the bottom edge of the blob. - - The method scans each column of the blob and finds the most top and the - most bottom points for it adding them to appropriate lists. The method may be very - useful in conjunction with different routines from , - which allow finding convex hull or quadrilateral's corners. - - Both lists of points are sorted by X coordinate - points with smaller X - value go first. - - - No image was processed before, so blob - can not be extracted. - - - - - Get list of object's edge points. - - - Blob to collect edge points for. - - Returns unsorted list of blob's edge points. - - The method scans each row and column of the blob and finds the - most top/bottom/left/right points. The method returns similar result as if results of - both and - methods were combined, but each edge point occurs only once in the list. - - Edge points in the returned list are not ordered. This makes the list unusable - for visualization with methods, which draw polygon or poly-line. But the returned list - can be used with such algorithms, like convex hull search, shape analyzer, etc. - - - No image was processed before, so blob - can not be extracted. - - - - - Actual objects map building. - - - Unmanaged image to process. - - By the time this method is called bitmap's pixel format is not - yet checked, so this should be done by the class inheriting from the base class. - and members are initialized - before the method is called, so these members may be used safely. - - - - - Objects count. - - - Number of objects (blobs) found by method. - - - - - - Objects' labels. - - - The array of width * height size, which holds - labels for all objects. Background is represented with 0 value, - but objects are represented with labels starting from 1. - - - - - Objects sort order. - - - The property specifies objects' sort order, which are provided - by , , etc. - - - - - - Specifies if blobs should be filtered. - - - If the property is equal to false, then there is no any additional - post processing after image was processed. If the property is set to true, then - blobs filtering is done right after image processing routine. If - is set, then custom blobs' filtering is done, which is implemented by user. Otherwise - blobs are filtered according to dimensions specified in , - , and properties. - - Default value is set to . - - - - - Specifies if size filetering should be coupled or not. - - - In uncoupled filtering mode, objects are filtered out in the case if - their width is smaller than or height is smaller than - . But in coupled filtering mode, objects are filtered out in - the case if their width is smaller than and height is - smaller than . In both modes the idea with filtering by objects' - maximum size is the same as filtering by objects' minimum size. - - Default value is set to , what means uncoupled filtering by size. - - - - - - Minimum allowed width of blob. - - - The property specifies minimum object's width acceptable by blob counting - routine and has power only when property is set to - and custom blobs' filter is - set to . - - See documentation to for additional information. - - - - - - Minimum allowed height of blob. - - - The property specifies minimum object's height acceptable by blob counting - routine and has power only when property is set to - and custom blobs' filter is - set to . - - See documentation to for additional information. - - - - - - Maximum allowed width of blob. - - - The property specifies maximum object's width acceptable by blob counting - routine and has power only when property is set to - and custom blobs' filter is - set to . - - See documentation to for additional information. - - - - - - Maximum allowed height of blob. - - - The property specifies maximum object's height acceptable by blob counting - routine and has power only when property is set to - and custom blobs' filter is - set to . - - See documentation to for additional information. - - - - - - Custom blobs' filter to use. - - - The property specifies custom blobs' filtering routine to use. It has - effect only in the case if property is set to . - - When custom blobs' filtering routine is set, it has priority over default filtering done - with , , and . - - - - - - Initializes a new instance of the class. - - - Creates new instance of the class with - an empty objects map. Before using methods, which provide information about blobs - or extract them, the , - or - method should be called to collect objects map. - - - - - Initializes a new instance of the class. - - - Image to look for objects in. - - - - - Initializes a new instance of the class. - - - Image data to look for objects in. - - - - - Initializes a new instance of the class. - - - Unmanaged image to look for objects in. - - - - - Actual objects map building. - - - Unmanaged image to process. - - The method supports 8 bpp indexed grayscale images and 24/32 bpp color images. - - Unsupported pixel format of the source image. - - - - - Background threshold's value. - - - The property sets threshold value for distinguishing between background - pixel and objects' pixels. All pixel with values less or equal to this property are - treated as background, but pixels with higher values are treated as objects' pixels. - - In the case of colour images a pixel is treated as objects' pixel if any of its - RGB values are higher than corresponding values of this threshold. - - For processing grayscale image, set the property with all RGB components eqaul. - - Default value is set to (0, 0, 0) - black colour. - - - - - Gather statistics about image in HSL color space. - - - The class is used to accumulate statistical values about images, - like histogram, mean, standard deviation, etc. for each HSL color channel. - - The class accepts 24 and 32 bpp color images for processing. - - Sample usage: - - // gather statistics - ImageStatisticsHSL stat = new ImageStatisticsHSL( image ); - // get saturation channel's histogram - ContinuousHistogram saturation = stat.Saturation; - // check mean value of saturation channel - if ( saturation.Mean > 0.5 ) - { - // do further processing - } - - - - - - - - - Initializes a new instance of the class. - - - Image to gather statistics about. - - Source pixel format is not supported. - - - - - Initializes a new instance of the class. - - - Image to gather statistics about. - Mask image which specifies areas to collect statistics for. - - The mask image must be a grayscale/binary (8bpp) image of the same size as the - specified source image, where black pixels (value 0) correspond to areas which should be excluded - from processing. So statistics is calculated only for pixels, which are none black in the mask image. - - - Source pixel format is not supported. - Mask image must be 8 bpp grayscale image. - Mask must have the same size as the source image to get statistics for. - - - - - Initializes a new instance of the class. - - - Image to gather statistics about. - Mask array which specifies areas to collect statistics for. - - The mask array must be of the same size as the specified source image, where 0 values - correspond to areas which should be excluded from processing. So statistics is calculated only for pixels, - which have none zero corresponding value in the mask. - - - Source pixel format is not supported. - Mask must have the same size as the source image to get statistics for. - - - - - Initializes a new instance of the class. - - - Unmanaged image to gather statistics about. - - Source pixel format is not supported. - - - - - Initializes a new instance of the class. - - - Image to gather statistics about. - Mask image which specifies areas to collect statistics for. - - The mask image must be a grayscale/binary (8bpp) image of the same size as the - specified source image, where black pixels (value 0) correspond to areas which should be excluded - from processing. So statistics is calculated only for pixels, which are none black in the mask image. - - - Source pixel format is not supported. - Mask image must be 8 bpp grayscale image. - Mask must have the same size as the source image to get statistics for. - - - - - Initializes a new instance of the class. - - - Image to gather statistics about. - Mask array which specifies areas to collect statistics for. - - The mask array must be of the same size as the specified source image, where 0 values - correspond to areas which should be excluded from processing. So statistics is calculated only for pixels, - which have none zero corresponding value in the mask. - - - Source pixel format is not supported. - Mask must have the same size as the source image to get statistics for. - - - - - Histogram of saturation channel. - - - - - - Histogram of luminance channel. - - - - - - Histogram of saturation channel excluding black pixels. - - - The property keeps statistics about saturation channel, which - excludes all black pixels, what affects mean, standard deviation, etc. - - - - - - Histogram of luminance channel excluding black pixels. - - - The property keeps statistics about luminance channel, which - excludes all black pixels, what affects mean, standard deviation, etc. - - - - - - Total pixels count in the processed image. - - - - - - Total pixels count in the processed image excluding black pixels. - - - - - - Fill holes in objects in binary image. - - - The filter allows to fill black holes in white object in a binary image. - It is possible to specify maximum holes' size to fill using - and properties. - - The filter accepts binary image only, which are represented as 8 bpp images. - - Sample usage: - - // create and configure the filter - FillHoles filter = new FillHoles( ); - filter.MaxHoleHeight = 20; - filter.MaxHoleWidth = 20; - filter.CoupledSizeFiltering = false; - // apply the filter - Bitmap result = filter.Apply( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - Process the filter on the specified image. - - - Source image data. - - - - - Specifies if size filetering should be coupled or not. - - - In uncoupled filtering mode, holes are filled in the case if - their width is smaller than or equal to or height is smaller than - or equal to . But in coupled filtering mode, holes are filled only in - the case if both width and height are smaller or equal to the corresponding value. - - Default value is set to , what means coupled filtering by size. - - - - - - Maximum width of a hole to fill. - - - All holes, which have width greater than this value, are kept unfilled. - See for additional information. - - Default value is set to . - - - - - Maximum height of a hole to fill. - - - All holes, which have height greater than this value, are kept unfilled. - See for additional information. - - Default value is set to . - - - - - Format translations dictionary. - - - - - Move canvas to the specified point. - - - - The filter moves canvas to the specified area filling unused empty areas with specified color. - - The filter accepts 8/16 bpp grayscale images and 24/32/48/64 bpp color image - for processing. - - Sample usage: - - // create filter - CanvasMove filter = new CanvasMove( new IntPoint( -50, -50 ), Color.Green ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - Point to move the canvas to. - - - - - Initializes a new instance of the class. - - - Point to move the canvas. - RGB color to use for filling areas empty areas in color images. - - - - - Initializes a new instance of the class. - - - Point to move the canvas. - Gray color to use for filling empty areas in grayscale images. - - - - - Initializes a new instance of the class. - - - Point to move the canvas. - RGB color to use for filling areas empty areas in color images. - Gray color to use for filling empty areas in grayscale images. - - - - - Process the filter on the specified image. - - - Source image data. - - - - - Format translations dictionary. - - - See - documentation for additional information. - - - - - RGB fill color. - - - The color is used to fill empty areas in color images. - - Default value is set to white - ARGB(255, 255, 255, 255). - - - - - Gray fill color. - - - The color is used to fill empty areas in grayscale images. - - Default value is set to white - 255. - - - - - Point to move the canvas to. - - - - - - Replace RGB channel of color imgae. - - - Replaces specified RGB channel of color image with - specified grayscale image. - - The filter is quite useful in conjunction with filter - (however may be used alone in some cases). Using the filter - it is possible to extract one of RGB channel, perform some image processing with it and then - put it back into the original color image. - - The filter accepts 24, 32, 48 and 64 bpp color images for processing. - - Sample usage: - - // extract red channel - ExtractChannel extractFilter = new ExtractChannel( RGB.R ); - Bitmap channel = extractFilter.Apply( image ); - // threshold channel - Threshold thresholdFilter = new Threshold( 230 ); - thresholdFilter.ApplyInPlace( channel ); - // put the channel back - ReplaceChannel replaceFilter = new ReplaceChannel( RGB.R, channel ); - replaceFilter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - - Initializes a new instance of the class. - - - ARGB channel to replace. - Channel image to use for replacement. - - - - - Initializes a new instance of the class. - - - RGB channel to replace. - Unmanaged channel image to use for replacement. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - Channel image size does not match source - image size. - Channel image's format does not correspond to format of the source image. - - Can not replace alpha channel of none ARGB image. The - exception is throw, when alpha channel is requested to be replaced in RGB image. - - - - - Format translations dictionary. - - - - - ARGB channel to replace. - - - Default value is set to . - - Invalid channel is specified. - - - - - Grayscale image to use for channel replacement. - - - - Setting this property will clear the property - - only one channel image is allowed: managed or unmanaged. - - - Channel image should be 8 bpp indexed or 16 bpp grayscale image. - - - - - Unmanaged grayscale image to use for channel replacement. - - - - Setting this property will clear the property - - only one channel image is allowed: managed or unmanaged. - - - Channel image should be 8 bpp indexed or 16 bpp grayscale image. - - - - - Grayscale image using R-Y algorithm. - - - The class uses R-Y algorithm to convert color image - to grayscale. The conversion coefficients are: - - Red: 0.5; - Green: 0.419; - Blue: 0.081. - - - - - - - - - - - Base class for image grayscaling. - - - This class is the base class for image grayscaling. Other - classes should inherit from this class and specify RGB - coefficients used for color image conversion to grayscale. - - The filter accepts 24, 32, 48 and 64 bpp color images and produces - 8 (if source is 24 or 32 bpp image) or 16 (if source is 48 or 64 bpp image) - bpp grayscale image. - - Sample usage: - - // create grayscale filter (BT709) - Grayscale filter = new Grayscale( 0.2125, 0.7154, 0.0721 ); - // apply the filter - Bitmap grayImage = filter.Apply( image ); - - - Initial image: - - Result image: - - - - - - - - - - - Portion of red channel's value to use during conversion from RGB to grayscale. - - - - - Portion of green channel's value to use during conversion from RGB to grayscale. - - - - - Portion of blue channel's value to use during conversion from RGB to grayscale. - - - - - Initializes a new instance of the class. - - - Red coefficient. - Green coefficient. - Blue coefficient. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - - - - Format translations dictionary. - - - - - Set of predefined common grayscaling algorithms, which have aldready initialized - grayscaling coefficients. - - - - - Grayscale image using BT709 algorithm. - - - The instance uses BT709 algorithm to convert color image - to grayscale. The conversion coefficients are: - - Red: 0.2125; - Green: 0.7154; - Blue: 0.0721. - - - Sample usage: - - // apply the filter - Bitmap grayImage = Grayscale.CommonAlgorithms.BT709.Apply( image ); - - - - - - - Grayscale image using R-Y algorithm. - - - The instance uses R-Y algorithm to convert color image - to grayscale. The conversion coefficients are: - - Red: 0.5; - Green: 0.419; - Blue: 0.081. - - - Sample usage: - - // apply the filter - Bitmap grayImage = Grayscale.CommonAlgorithms.RMY.Apply( image ); - - - - - - - Grayscale image using Y algorithm. - - - The instance uses Y algorithm to convert color image - to grayscale. The conversion coefficients are: - - Red: 0.299; - Green: 0.587; - Blue: 0.114. - - - Sample usage: - - // apply the filter - Bitmap grayImage = Grayscale.CommonAlgorithms.Y.Apply( image ); - - - - - - - Initializes a new instance of the class. - - - - - Threshold binarization with error carry. - - - The filter is similar to filter in the way, - that it also uses threshold value for image binarization. Unlike regular threshold - filter, this filter uses cumulative pixel value in comparing with threshold value. - If cumulative pixel value is below threshold value, then image pixel becomes black. - If cumulative pixel value is equal or higher than threshold value, then image pixel - becomes white and cumulative pixel value is decreased by 255. In the beginning of each - image line the cumulative value is reset to 0. - - - The filter accepts 8 bpp grayscale images for processing. - - Sample usage: - - // create filter - Threshold filter = new Threshold( 100 ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Threshold value. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Threshold value. - - - Default value is 128. - - - - - Color dithering using Burkes error diffusion. - - - The image processing routine represents color dithering algorithm, which is based on - error diffusion dithering with Burkes coefficients. Error is diffused - on 7 neighbor pixels with next coefficients: - - | * | 8 | 4 | - | 2 | 4 | 8 | 4 | 2 | - - / 32 - - - The image processing routine accepts 24/32 bpp color images for processing. As a result this routine - produces 4 bpp or 8 bpp indexed image, which depends on size of the specified - color table - 4 bpp result for - color tables with 16 colors or less; 8 bpp result for larger color tables. - - Sample usage: - - // create color image quantization routine - ColorImageQuantizer ciq = new ColorImageQuantizer( new MedianCutQuantizer( ) ); - // create 8 colors table - Color[] colorTable = ciq.CalculatePalette( image, 8 ); - // create dithering routine - BurkesColorDithering dithering = new BurkesColorDithering( ); - dithering.ColorTable = colorTable; - // apply the dithering routine - Bitmap newImage = dithering.Apply( image ); - - - Initial image: - - Result image: - - - - - - - - - - - - Initializes a new instance of the class. - - - - - - Moravec corners detector. - - - The class implements Moravec corners detector. For information about algorithm's - details its description - should be studied. - - Due to limitations of Moravec corners detector (anisotropic response, etc.) its usage is limited - to certain cases only. - - The class processes only grayscale 8 bpp and color 24/32 bpp images. - - Sample usage: - - // create corner detector's instance - MoravecCornersDetector mcd = new MoravecCornersDetector( ); - // process image searching for corners - List<IntPoint> corners = scd.ProcessImage( image ); - // process points - foreach ( IntPoint corner in corners ) - { - // ... - } - - - - - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Threshold value, which is used to filter out uninteresting points. - - - - - Initializes a new instance of the class. - - - Threshold value, which is used to filter out uninteresting points. - Window size used to determine if point is interesting. - - - - - Process image looking for corners. - - - Source image to process. - - Returns array of found corners (X-Y coordinates). - - The source image has incorrect pixel format. - - - - - Process image looking for corners. - - - Source image data to process. - - Returns array of found corners (X-Y coordinates). - - The source image has incorrect pixel format. - - - - - Process image looking for corners. - - - Unmanaged source image to process. - - Returns array of found corners (X-Y coordinates). - - The source image has incorrect pixel format. - - - - - Window size used to determine if point is interesting, [3, 15]. - - - The value specifies window size, which is used for initial searching of - corners candidates and then for searching local maximums. - - Default value is set to 3. - - - Setting value is not odd. - - - - - Threshold value, which is used to filter out uninteresting points. - - - The value is used to filter uninteresting points - points which have value below - specified threshold value are treated as not corners candidates. Increasing this value decreases - the amount of detected point. - - Default value is set to 500. - - - - - - Mirroring filter. - - - The filter mirrors image around X and/or Y axis (horizontal and vertical - mirroring). - - The filter accepts 8 bpp grayscale images and 24 bpp - color images for processing. - - Sample usage: - - // create filter - Mirror filter = new Mirror( false, true ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - Specifies if mirroring should be done for X axis. - Specifies if mirroring should be done for Y axis - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Specifies if mirroring should be done for X axis (horizontal mirroring). - - - - - - Specifies if mirroring should be done for Y axis (vertical mirroring). - - - - - - Apply filter according to the specified mask. - - - The image processing routine applies the specified to - a source image according to the specified mask - if a pixel/value in the specified mask image/array - is set to 0, then the original pixel's value is kept; otherwise the pixel is filtered using the - specified base filter. - - Mask can be specified as .NET's managed Bitmap, as - UnmanagedImage or as byte array. - In the case if mask is specified as image, it must be 8 bpp grayscale image. In all case - mask size must be the same as size of the image to process. - - Pixel formats accepted by this filter are specified by the . - - Sample usage: - - // create the filter - MaskedFilter maskedFilter = new MaskedFilter( new Sepia( ), maskImage ); - // apply the filter - maskedFilter.ApplyInPlace( image ); - - - Initial image: - - Mask image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - Base filter to apply to the specified source image. - Mask image to use. - - - - - Initializes a new instance of the class. - - - Base filter to apply to the specified source image. - Unmanaged mask image to use. - - - - - Initializes a new instance of the class. - - - Base filter to apply to the specified source image. - to use. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - None of the possible mask properties were set. Need to provide mask before applying the filter. - Invalid size of provided mask. Its size must be the same as the size of the image to mask. - - - - - Base filter to apply to the source image. - - - The property specifies base filter which is applied to the specified source - image (to all pixels which have corresponding none 0 value in mask image/array). - - The base filter must implement interface. - - The base filter must never change image's pixel format. For example, if source - image's pixel format is 24 bpp color image, then it must stay the same after the base - filter is applied. - - The base filter must never change size of the source image. - - - Base filter can not be set to null. - The specified base filter must implement IFilterInformation interface. - The specified filter must never change pixel format. - - - - - Mask image to apply. - - - The property specifies mask image to use. The image must be grayscale - (8 bpp format) and have the same size as the source image to process. - - When the property is set, both and - properties are set to . - - - The mask image must be 8 bpp grayscale image. - - - - - Unmanaged mask image to apply. - - - The property specifies unmanaged mask image to use. The image must be grayscale - (8 bpp format) and have the same size as the source image to process. - - When the property is set, both and - properties are set to . - - - The mask image must be 8 bpp grayscale image. - - - - - Mask to apply. - - - The property specifies mask array to use. Size of the array must - be the same size as the size of the source image to process - its 0th dimension - must be equal to image's height and its 1st dimension must be equal to width. For - example, for 640x480 image, the mask array must be defined as: - - byte[,] mask = new byte[480, 640]; - - - - - - - Format translations dictionary. - - - See - documentation for additional information. - - The property returns format translation table from the - . - - - - - - Jitter filter. - - - The filter moves each pixel of a source image in - random direction within a window of specified radius. - - The filter accepts 8 bpp grayscale images and 24/32 - color images for processing. - - Sample usage: - - // create filter - Jitter filter = new Jitter( 4 ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Jittering radius. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - See - documentation for additional information. - - - - - Jittering radius, [1, 10] - - - Determines radius in which pixels can move. - - Default value is set to 2. - - - - - - Fill areas iniside of the specified region. - - - - The filter fills areas inside of specified region using the specified color. - - The filter accepts 8bpp grayscale and 24/32 bpp color images for processing. - - Sample usage: - - // create filter - CanvasFill filter = new CanvasFill( new Rectangle( - 5, 5, image.Width - 10, image.Height - 10 ), Color.Red ); - // apply the filter - filter.ApplyInPlace( image ); - - - - - - - - - Initializes a new instance of the class. - - - Region to fill. - - - - - Initializes a new instance of the class. - - - Region to fill. - RGB color to use for filling areas inside of specified region in color images. - - - - - Initializes a new instance of the class. - - - Region to fill. - Gray color to use for filling areas inside of specified region in grayscale images. - - - - - Initializes a new instance of the class. - - - Region to fill. - RGB color to use for filling areas inside of specified region in color images. - Gray color to use for filling areas inside of specified region in grayscale images. - - - - - Process the filter on the specified image. - - - Source image data. - - - - - Format translations dictionary. - - - See - documentation for additional information. - - - - - RGB fill color. - - - The color is used to fill areas out of specified region in color images. - - Default value is set to white - RGB(255, 255, 255). - - - - - Gray fill color. - - - The color is used to fill areas out of specified region in grayscale images. - - Default value is set to white - 255. - - - - - Region to fill. - - - Pixels inside of the specified region will be filled with specified color. - - - - - Histogram equalization filter. - - - The filter does histogram equalization increasing local contrast in images. The effect - of histogram equalization can be better seen on images, where pixel values have close contrast values. - Through this adjustment, pixels intensities can be better distributed on the histogram. This allows for - areas of lower local contrast to gain a higher contrast without affecting the global contrast. - - - The filter accepts 8 bpp grayscale images and 24/32 bpp - color images for processing. - - For color images the histogram equalization is applied to each color plane separately. - - Sample usage: - - // create filter - HistogramEqualization filter = new HistogramEqualization( ); - // process image - filter.ApplyInPlace( sourceImage ); - - - Source image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Extract RGB channel from image. - - - Extracts specified channel of color image and returns - it as grayscale image. - - The filter accepts 24, 32, 48 and 64 bpp color images and produces - 8 (if source is 24 or 32 bpp image) or 16 (if source is 48 or 64 bpp image) - bpp grayscale image. - - Sample usage: - - // create filter - ExtractChannel filter = new ExtractChannel( RGB.G ); - // apply the filter - Bitmap channelImage = filter.Apply( image ); - - - Initial image: - - Result image: - - - - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - ARGB channel to extract. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - Can not extract alpha channel from none ARGB image. The - exception is throw, when alpha channel is requested from RGB image. - - - - - Format translations dictionary. - - - - - ARGB channel to extract. - - - Default value is set to . - - Invalid channel is specified. - - - - - Dithering using Floyd-Steinberg error diffusion. - - - The filter represents binarization filter, which is based on - error diffusion dithering with Floyd-Steinberg - coefficients. Error is diffused on 4 neighbor pixels with next coefficients: - - - | * | 7 | - | 3 | 5 | 1 | - - / 16 - - - The filter accepts 8 bpp grayscale images for processing. - - Sample usage: - - // create filter - FloydSteinbergDithering filter = new FloydSteinbergDithering( ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - - - - Initializes a new instance of the class. - - - - - - Core image relatad methods. - - - All methods of this class are static and represent general routines - used by different image processing classes. - - - - - Check if specified 8 bpp image is grayscale. - - - Image to check. - - Returns true if the image is grayscale or false otherwise. - - The methods checks if the image is a grayscale image of 256 gradients. - The method first examines if the image's pixel format is - Format8bppIndexed - and then it examines its palette to check if the image is grayscale or not. - - - - - Create and initialize new 8 bpp grayscale image. - - - Image width. - Image height. - - Returns the created grayscale image. - - The method creates new 8 bpp grayscale image and initializes its palette. - Grayscale image is represented as - Format8bppIndexed - image with palette initialized to 256 gradients of gray color. - - - - - Set pallete of the 8 bpp indexed image to grayscale. - - - Image to initialize. - - The method initializes palette of - Format8bppIndexed - image with 256 gradients of gray color. - - Provided image is not 8 bpp indexed image. - - - - - Clone image. - - - Source image. - Pixel format of result image. - - Returns clone of the source image with specified pixel format. - - The original Bitmap.Clone() - does not produce the desired result - it does not create a clone with specified pixel format. - More of it, the original method does not create an actual clone - it does not create a copy - of the image. That is why this method was implemented to provide the functionality. - - - - - Clone image. - - - Source image. - - Return clone of the source image. - - The original Bitmap.Clone() - does not produce the desired result - it does not create an actual clone (it does not create a copy - of the image). That is why this method was implemented to provide the functionality. - - - - - Clone image. - - - Source image data. - - Clones image from source image data. The message does not clone pallete in the - case if the source image has indexed pixel format. - - - - - Format an image. - - - Source image to format. - - Formats the image to one of the formats, which are supported - by the AForge.Imaging library. The image is left untouched in the - case if it is already of - Format24bppRgb or - Format32bppRgb or - Format32bppArgb or - Format48bppRgb or - Format64bppArgb - format or it is grayscale, otherwise the image - is converted to Format24bppRgb - format. - - The method is deprecated and method should - be used instead with specifying desired pixel format. - - - - - - Load bitmap from file. - - - File name to load bitmap from. - - Returns loaded bitmap. - - The method is provided as an alternative of - method to solve the issues of locked file. The standard .NET's method locks the source file until - image's object is disposed, so the file can not be deleted or overwritten. This method workarounds the issue and - does not lock the source file. - - Sample usage: - - Bitmap image = AForge.Imaging.Image.FromFile( "test.jpg" ); - - - - - - - Convert bitmap with 16 bits per plane to a bitmap with 8 bits per plane. - - - Source image to convert. - - Returns new image which is a copy of the source image but with 8 bits per plane. - - The routine does the next pixel format conversions: - - Format16bppGrayScale to - Format8bppIndexed with grayscale palette; - Format48bppRgb to - Format24bppRgb; - Format64bppArgb to - Format32bppArgb; - Format64bppPArgb to - Format32bppPArgb. - - - - Invalid pixel format of the source image. - - - - - Convert bitmap with 8 bits per plane to a bitmap with 16 bits per plane. - - - Source image to convert. - - Returns new image which is a copy of the source image but with 16 bits per plane. - - The routine does the next pixel format conversions: - - Format8bppIndexed (grayscale palette assumed) to - Format16bppGrayScale; - Format24bppRgb to - Format48bppRgb; - Format32bppArgb to - Format64bppArgb; - Format32bppPArgb to - Format64bppPArgb. - - - - Invalid pixel format of the source image. - - - - - Linear correction of YCbCr channels. - - - The filter operates in YCbCr color space and provides - with the facility of linear correction of its channels - mapping specified channels' - input ranges to specified output ranges. - - The filter accepts 24 and 32 bpp color images for processing. - - Sample usage: - - // create filter - YCbCrLinear filter = new YCbCrLinear( ); - // configure the filter - filter.InCb = new Range( -0.276f, 0.163f ); - filter.InCr = new Range( -0.202f, 0.500f ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - - Initializes a new instance of the class. - - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Y component's input range. - - - Y component is measured in the range of [0, 1]. - - - - - Cb component's input range. - - - Cb component is measured in the range of [-0.5, 0.5]. - - - - - Cr component's input range. - - - Cr component is measured in the range of [-0.5, 0.5]. - - - - - Y component's output range. - - - Y component is measured in the range of [0, 1]. - - - - - Cb component's output range. - - - Cb component is measured in the range of [-0.5, 0.5]. - - - - - Cr component's output range. - - - Cr component is measured in the range of [-0.5, 0.5]. - - - - - Format translations dictionary. - - - - - Resize image using bilinear interpolation algorithm. - - - The class implements image resizing filter using bilinear - interpolation algorithm. - - The filter accepts 8 grayscale images and 24/32 bpp - color images for processing. - - Sample usage: - - // create filter - ResizeBilinear filter = new ResizeBilinear( 400, 300 ); - // apply the filter - Bitmap newImage = filter.Apply( image ); - - - Initial image: - - Result image: - - - - - - - - - - Initializes a new instance of the class. - - - Width of the new image. - Height of the new image. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - - - - Format translations dictionary. - - - - - Oil painting filter. - - - Processing source image the filter changes each pixels' value - to the value of pixel with the most frequent intensity within window of the - specified size. Going through the window the filters - finds which intensity of pixels is the most frequent. Then it updates value - of the pixel in the center of the window to the value with the most frequent - intensity. The update procedure creates the effect of oil painting. - - The filter accepts 8 bpp grayscale images and 24/32 - color images for processing. - - Sample usage: - - // create filter - OilPainting filter = new OilPainting( 15 ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Brush size. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - See - documentation for additional information. - - - - - Brush size, [3, 21]. - - - Window size to search for most frequent pixels' intensity. - - Default value is set to 5. - - - - - Extract normalized RGB channel from color image. - - - Extracts specified normalized RGB channel of color image and returns - it as grayscale image. - - Normalized RGB color space is defined as: - - r = R / (R + G + B ), - g = G / (R + G + B ), - b = B / (R + G + B ), - - where R, G and B are components of RGB color space and - r, g and b are components of normalized RGB color space. - - - The filter accepts 24, 32, 48 and 64 bpp color images and produces - 8 (if source is 24 or 32 bpp image) or 16 (if source is 48 or 64 bpp image) - bpp grayscale image. - - Sample usage: - - // create filter - ExtractNormalizedRGBChannel filter = new ExtractNormalizedRGBChannel( RGB.G ); - // apply the filter - Bitmap channelImage = filter.Apply( image ); - - - - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Normalized RGB channel to extract. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - - - - Format translations dictionary. - - - - - Normalized RGB channel to extract. - - - Default value is set to . - - Invalid channel is specified. - - - - - Binary dilatation operator from Mathematical Morphology with 3x3 structuring element. - - - The filter represents an optimized version of - filter, which is aimed for binary images (containing black and white pixels) processed - with 3x3 structuring element. This makes this filter ideal for growing objects in binary - images – it puts white pixel to the destination image in the case if there is at least - one white neighbouring pixel in the source image. - - See filter, which represents generic version of - dilatation filter supporting custom structuring elements and wider range of image formats. - - The filter accepts 8 bpp grayscale (binary) images for processing. - - - - - - - - - Initializes a new instance of the class. - - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - Image rectangle for processing by the filter. - - Processing rectangle mast be at least 3x3 in size. - - - - - Format translations dictionary. - - - - - Sobel edge detector. - - - The filter searches for objects' edges by applying Sobel operator. - - Each pixel of the result image is calculated as approximated absolute gradient - magnitude for corresponding pixel of the source image: - - |G| = |Gx| + |Gy] , - - where Gx and Gy are calculate utilizing Sobel convolution kernels: - - Gx Gy - -1 0 +1 +1 +2 +1 - -2 0 +2 0 0 0 - -1 0 +1 -1 -2 -1 - - Using the above kernel the approximated magnitude for pixel x is calculate using - the next equation: - - P1 P2 P3 - P8 x P4 - P7 P6 P5 - - |G| = |P1 + 2P2 + P3 - P7 - 2P6 - P5| + - |P3 + 2P4 + P5 - P1 - 2P8 - P7| - - - - The filter accepts 8 bpp grayscale images for processing. - - Sample usage: - - // create filter - SobelEdgeDetector filter = new SobelEdgeDetector( ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - - Initializes a new instance of the class. - - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Scale intensity or not. - - - The property determines if edges' pixels intensities of the result image - should be scaled in the range of the lowest and the highest possible intensity - values. - - Default value is set to . - - - - - - Sharpen filter - - - The filter performs convolution filter using - the sharpen kernel: - - - 0 -1 0 - -1 5 -1 - 0 -1 0 - - - For the list of supported pixel formats, see the documentation to - filter. - - Sample usage: - - // create filter - Sharpen filter = new Sharpen( ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - Initializes a new instance of the class. - - - - - Sepia filter - old brown photo. - - - The filter makes an image look like an old brown photo. The main - idea of the algorithm: - - transform to YIQ color space; - modify it; - transform back to RGB. - - - - 1) RGB -> YIQ: - - Y = 0.299 * R + 0.587 * G + 0.114 * B - I = 0.596 * R - 0.274 * G - 0.322 * B - Q = 0.212 * R - 0.523 * G + 0.311 * B - - - - - 2) update: - - I = 51 - Q = 0 - - - - - 3) YIQ -> RGB: - - R = 1.0 * Y + 0.956 * I + 0.621 * Q - G = 1.0 * Y - 0.272 * I - 0.647 * Q - B = 1.0 * Y - 1.105 * I + 1.702 * Q - - - - The filter accepts 24/32 bpp color images for processing. - - Sample usage: - - // create filter - Sepia filter = new Sepia( ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Invert image. - - - The filter inverts colored and grayscale images. - - The filter accepts 8, 16 bpp grayscale and 24, 48 bpp color images for processing. - - Sample usage: - - // create filter - Invert filter = new Invert( ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Euclidean color filtering. - - - The filter filters pixels, which color is inside/outside - of RGB sphere with specified center and radius - it keeps pixels with - colors inside/outside of the specified sphere and fills the rest with - specified color. - - The filter accepts 24 and 32 bpp color images for processing. - - Sample usage: - - // create filter - EuclideanColorFiltering filter = new EuclideanColorFiltering( ); - // set center colol and radius - filter.CenterColor = new RGB( 215, 30, 30 ); - filter.Radius = 100; - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - RGB sphere's center. - RGB sphere's radius. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - RGB sphere's radius, [0, 450]. - - - Default value is 100. - - - - - RGB sphere's center. - - - Default value is (255, 255, 255) - white color. - - - - - Fill color used to fill filtered pixels. - - - - - Determines, if pixels should be filled inside or outside specified - RGB sphere. - - - Default value is set to , which means - the filter removes colors outside of the specified range. - - - - - Exhaustive template matching. - - - The class implements exhaustive template matching algorithm, - which performs complete scan of source image, comparing each pixel with corresponding - pixel of template. - - The class processes only grayscale 8 bpp and color 24 bpp images. - - Sample usage: - - // create template matching algorithm's instance - ExhaustiveTemplateMatching tm = new ExhaustiveTemplateMatching( 0.9f ); - // find all matchings with specified above similarity - TemplateMatch[] matchings = tm.ProcessImage( sourceImage, templateImage ); - // highlight found matchings - BitmapData data = sourceImage.LockBits( - new Rectangle( 0, 0, sourceImage.Width, sourceImage.Height ), - ImageLockMode.ReadWrite, sourceImage.PixelFormat ); - foreach ( TemplateMatch m in matchings ) - { - Drawing.Rectangle( data, m.Rectangle, Color.White ); - // do something else with matching - } - sourceImage.UnlockBits( data ); - - - The class also can be used to get similarity level between two image of the same - size, which can be useful to get information about how different/similar are images: - - // create template matching algorithm's instance - // use zero similarity to make sure algorithm will provide anything - ExhaustiveTemplateMatching tm = new ExhaustiveTemplateMatching( 0 ); - // compare two images - TemplateMatch[] matchings = tm.ProcessImage( image1, image2 ); - // check similarity level - if ( matchings[0].Similarity > 0.95f ) - { - // do something with quite similar images - } - - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Similarity threshold. - - - - - Process image looking for matchings with specified template. - - - Source image to process. - Template image to search for. - - Returns array of found template matches. The array is sorted by similarity - of found matches in descending order. - - The source image has incorrect pixel format. - Template image is bigger than source image. - - - - - Process image looking for matchings with specified template. - - - Source image to process. - Template image to search for. - Rectangle in source image to search template for. - - Returns array of found template matches. The array is sorted by similarity - of found matches in descending order. - - The source image has incorrect pixel format. - Template image is bigger than source image. - - - - - Process image looking for matchings with specified template. - - - Source image data to process. - Template image to search for. - - Returns array of found template matches. The array is sorted by similarity - of found matches in descending order. - - The source image has incorrect pixel format. - Template image is bigger than source image. - - - - - Process image looking for matchings with specified template. - - - Source image data to process. - Template image to search for. - Rectangle in source image to search template for. - - Returns array of found template matches. The array is sorted by similarity - of found matches in descending order. - - The source image has incorrect pixel format. - Template image is bigger than source image. - - - - - Process image looking for matchings with specified template. - - - Unmanaged source image to process. - Unmanaged template image to search for. - - Returns array of found template matches. The array is sorted by similarity - of found matches in descending order. - - The source image has incorrect pixel format. - Template image is bigger than source image. - - - - - Process image looking for matchings with specified template. - - - Unmanaged source image to process. - Unmanaged template image to search for. - Rectangle in source image to search template for. - - Returns array of found template matches. The array is sorted by similarity - of found matches in descending order. - - The source image has incorrect pixel format. - Template image is bigger than search zone. - - - - - Similarity threshold, [0..1]. - - - The property sets the minimal acceptable similarity between template - and potential found candidate. If similarity is lower than this value, - then object is not treated as matching with template. - - - Default value is set to 0.9. - - - - - - Block matching implementation with the exhaustive search algorithm. - - - The class implements exhaustive search block matching algorithm - (see documentation for for information about - block matching algorithms). Exhaustive search algorithm tests each possible - location of block within search window trying to find a match with minimal - difference. - - Because of the exhaustive nature of the algorithm, high performance - should not be expected in the case if big number of reference points is provided - or big block size and search radius are specified. Minimizing theses values increases - performance. But too small block size and search radius may affect quality. - - The class processes only grayscale (8 bpp indexed) and color (24 bpp) images. - - Sample usage: - - // collect reference points using corners detector (for example) - SusanCornersDetector scd = new SusanCornersDetector( 30, 18 ); - List<IntPoint> points = scd.ProcessImage( sourceImage ); - - // create block matching algorithm's instance - ExhaustiveBlockMatching bm = new ExhaustiveBlockMatching( 8, 12 ); - // process images searching for block matchings - List<BlockMatch> matches = bm.ProcessImage( sourceImage, points, searchImage ); - - // draw displacement vectors - BitmapData data = sourceImage.LockBits( - new Rectangle( 0, 0, sourceImage.Width, sourceImage.Height ), - ImageLockMode.ReadWrite, sourceImage.PixelFormat ); - - foreach ( BlockMatch match in matches ) - { - // highlight the original point in source image - Drawing.FillRectangle( data, - new Rectangle( match.SourcePoint.X - 1, match.SourcePoint.Y - 1, 3, 3 ), - Color.Yellow ); - // draw line to the point in search image - Drawing.Line( data, match.SourcePoint, match.MatchPoint, Color.Red ); - - // check similarity - if ( match.Similarity > 0.98f ) - { - // process block with high similarity somehow special - } - } - - sourceImage.UnlockBits( data ); - - - Test image 1 (source): - - Test image 2 (search): - - Result image: - - - - - - - Block matching interface. - - - The interface specifies set of methods, which should be implemented by different - block matching algorithms. - - Block matching algorithms work with two images - source and search image - and - a set of reference points. For each provided reference point, the algorithm takes - a block from source image (reference point is a coordinate of block's center) and finds - the best match for it in search image providing its coordinate (search is done within - search window of specified size). In other words, block matching algorithm tries to - find new coordinates in search image of specified reference points in source image. - - - - - - - Process images matching blocks between them. - - - Source image with reference points. - List of reference points to be matched. - Image in which the reference points will be looked for. - - Returns list of found block matches. - - - - - Process images matching blocks between them. - - - Source image with reference points. - List of reference points to be matched. - Image in which the reference points will be looked for. - - Returns list of found block matches. - - - - - Process images matching blocks between them. - - - Source unmanaged image with reference points. - List of reference points to be matched. - Unmanaged image in which the reference points will be looked for. - - Returns list of found block matches. - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Block size to search for. - Search radius. - - - - - Process images matching blocks between hem. - - - Source image with reference points. - List of reference points to be matched. - Image in which the reference points will be looked for. - - Returns list of found block matches. The list is sorted by similarity - of found matches in descending order. - - Source and search images sizes must match. - Source images can be grayscale (8 bpp indexed) or color (24 bpp) image only. - Source and search images must have same pixel format. - - - - - Process images matching blocks between them. - - - Source image with reference points. - List of reference points to be matched. - Image in which the reference points will be looked for. - - Returns list of found block matches. The list is sorted by similarity - of found matches in descending order. - - Source and search images sizes must match. - Source images can be grayscale (8 bpp indexed) or color (24 bpp) image only. - Source and search images must have same pixel format. - - - - - Process images matching blocks between them. - - - Source unmanaged image with reference points. - List of reference points to be matched. - Unmanaged image in which the reference points will be looked for. - - Returns list of found block matches. The list is sorted by similarity - of found matches in descending order. - - Source and search images sizes must match. - Source images can be grayscale (8 bpp indexed) or color (24 bpp) image only. - Source and search images must have same pixel format. - - - - - Search radius. - - - The value specifies the shift from reference point in all - four directions, used to search for the best matching block. - - Default value is set to 12. - - - - - - Block size to search for. - - - The value specifies block size to search for. For each provided - reference pointer, a square block of this size is taken from the source image - (reference point becomes the coordinate of block's center) and the best match - is searched in second image within specified search - radius. - - Default value is set to 16. - - - - - - Similarity threshold, [0..1]. - - - The property sets the minimal acceptable similarity between blocks - in source and search images. If similarity is lower than this value, - then the candidate block in search image is not treated as a match for the block - in source image. - - - Default value is set to 0.9. - - - - - - Unsupported image format exception. - - - The unsupported image format exception is thrown in the case when - user passes an image of certain format to an image processing routine, which does - not support the format. Check documentation of the image processing routine - to discover which formats are supported by the routine. - - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Message providing some additional information. - - - - - Initializes a new instance of the class. - - - Message providing some additional information. - Name of the invalid parameter. - - - - - Invalid image properties exception. - - - The invalid image properties exception is thrown in the case when - user provides an image with certain properties, which are treated as invalid by - particular image processing routine. Another case when this exception is - thrown is the case when user tries to access some properties of an image (or - of a recently processed image by some routine), which are not valid for that image. - - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Message providing some additional information. - - - - - Initializes a new instance of the class. - - - Message providing some additional information. - Name of the invalid parameter. - - - - - Complex image. - - - The class is used to keep image represented in complex numbers sutable for Fourier - transformations. - - Sample usage: - - // create complex image - ComplexImage complexImage = ComplexImage.FromBitmap( image ); - // do forward Fourier transformation - complexImage.ForwardFourierTransform( ); - // get complex image as bitmat - Bitmap fourierImage = complexImage.ToBitmap( ); - - - Initial image: - - Fourier image: - - - - - - - Initializes a new instance of the class. - - - Image width. - Image height. - - The constractor is protected, what makes it imposible to instantiate this - class directly. To create an instance of this class or - method should be used. - - - - - Clone the complex image. - - - Returns copy of the complex image. - - - - - Create complex image from grayscale bitmap. - - - Source grayscale bitmap (8 bpp indexed). - - Returns an instance of complex image. - - The source image has incorrect pixel format. - Image width and height should be power of 2. - - - - - Create complex image from grayscale bitmap. - - - Source image data (8 bpp indexed). - - Returns an instance of complex image. - - The source image has incorrect pixel format. - Image width and height should be power of 2. - - - - - Convert complex image to bitmap. - - - Returns grayscale bitmap. - - - - - Applies forward fast Fourier transformation to the complex image. - - - - - - Applies backward fast Fourier transformation to the complex image. - - - - - - Image width. - - - - - - Image height. - - - - - - Status of the image - Fourier transformed or not. - - - - - - Complex image's data. - - - Return's 2D array of [height, width] size, which keeps image's - complex data. - - - - - RGB components. - - - The class encapsulates RGB color components. - PixelFormat.Format24bppRgb - actually means BGR format. - - - - - - Index of red component. - - - - - Index of green component. - - - - - Index of blue component. - - - - - Index of alpha component for ARGB images. - - - - - Red component. - - - - - Green component. - - - - - Blue component. - - - - - Alpha component. - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Red component. - Green component. - Blue component. - - - - - Initializes a new instance of the class. - - - Red component. - Green component. - Blue component. - Alpha component. - - - - - Initializes a new instance of the class. - - - Initialize from specified color. - - - - - Color value of the class. - - - - - HSL components. - - - The class encapsulates HSL color components. - - - - - Hue component. - - - Hue is measured in the range of [0, 359]. - - - - - Saturation component. - - - Saturation is measured in the range of [0, 1]. - - - - - Luminance value. - - - Luminance is measured in the range of [0, 1]. - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Hue component. - Saturation component. - Luminance component. - - - - - Convert from RGB to HSL color space. - - - Source color in RGB color space. - Destination color in HSL color space. - - See HSL and HSV Wiki - for information about the algorithm to convert from RGB to HSL. - - - - - Convert from RGB to HSL color space. - - - Source color in RGB color space. - - Returns instance, which represents converted color value. - - - - - Convert from HSL to RGB color space. - - - Source color in HSL color space. - Destination color in RGB color space. - - - - - Convert the color to RGB color space. - - - Returns instance, which represents converted color value. - - - - - YCbCr components. - - - The class encapsulates YCbCr color components. - - - - - Index of Y component. - - - - - Index of Cb component. - - - - - Index of Cr component. - - - - - Y component. - - - - - Cb component. - - - - - Cr component. - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Y component. - Cb component. - Cr component. - - - - - Convert from RGB to YCbCr color space (Rec 601-1 specification). - - - Source color in RGB color space. - Destination color in YCbCr color space. - - - - - Convert from RGB to YCbCr color space (Rec 601-1 specification). - - - Source color in RGB color space. - - Returns instance, which represents converted color value. - - - - - Convert from YCbCr to RGB color space. - - - Source color in YCbCr color space. - Destination color in RGB color spacs. - - - - - Convert the color to RGB color space. - - - Returns instance, which represents converted color value. - - - - - Color dithering with a thresold matrix (ordered dithering). - - - The class implements ordered color dithering as described on - Wikipedia. - The algorithm achieves dithering by applying a threshold map on - the pixels displayed, causing some of the pixels to be rendered at a different color, depending on - how far in between the color is of available color entries. - - The image processing routine accepts 24/32 bpp color images for processing. As a result this routine - produces 4 bpp or 8 bpp indexed image, which depends on size of the specified - color table - 4 bpp result for - color tables with 16 colors or less; 8 bpp result for larger color tables. - - Sample usage: - - // create color image quantization routine - ColorImageQuantizer ciq = new ColorImageQuantizer( new MedianCutQuantizer( ) ); - // create 256 colors table - Color[] colorTable = ciq.CalculatePalette( image, 256 ); - // create dithering routine - OrderedColorDithering dithering = new OrderedColorDithering( ); - dithering.ColorTable = colorTable; - // apply the dithering routine - Bitmap newImage = dithering.Apply( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Threshold matrix (see property). - - - - - Perform color dithering for the specified image. - - - Source image to do color dithering for. - - Returns color dithered image. See for information about format of - the result image. - - Unsupported pixel format of the source image. It must 24 or 32 bpp color image. - - - - - Perform color dithering for the specified image. - - - Source image to do color dithering for. - - Returns color dithered image. See for information about format of - the result image. - - Unsupported pixel format of the source image. It must 24 or 32 bpp color image. - - - - - Threshold matrix - values to add source image's values. - - - The property keeps a threshold matrix, which is applied to values of a source image - to dither. By adding these values to the source image the algorithm produces the effect when pixels - of the same color in source image may have different color in the result image (which depends on pixel's - position). This threshold map is also known as an index matrix or Bayer matrix. - - By default the property is inialized with the below matrix: - - 2 18 6 22 - 26 10 30 14 - 8 24 4 20 - 32 16 28 12 - - - - - - - - Color table to use for image dithering. Must contain 2-256 colors. - - - Color table size determines format of the resulting image produced by this - image processing routine. If color table contains 16 color or less, then result image will have - 4 bpp indexed pixel format. If color table contains more than 16 colors, then result image will - have 8 bpp indexed pixel format. - - By default the property is initialized with default 16 colors, which are: - Black, Dark Blue, Dark Green, Dark Cyan, Dark Red, Dark Magenta, Dark Khaki, Light Gray, - Gray, Blue, Green, Cyan, Red, Magenta, Yellow and White. - - - Color table length must be in the [2, 256] range. - - - - - Use color caching during color dithering or not. - - - The property specifies if internal cache of already processed colors should be used or not. - For each pixel in the original image the color dithering routine does search in target color palette to find - the best matching color. To avoid doing the search again and again for already processed colors, the class may - use internal dictionary which maps colors of original image to indexes in target color palette. - - - The property provides a trade off. On one hand it may speedup color dithering routine, but on another - hand it increases memory usage. Also cache usage may not be efficient for very small target color tables. - - Default value is set to . - - - - - - Block match class keeps information about found block match. The class is - used with block matching algorithms implementing - interface. - - - - - - Initializes a new instance of the class. - - - Reference point in source image. - Match point in search image (point of a found match). - Similarity between blocks in source and search images, [0..1]. - - - - - Reference point in source image. - - - - - Match point in search image (point of a found match). - - - - - Similarity between blocks in source and search images, [0..1]. - - - - - Image's blob. - - - The class represents a blob - part of another images. The - class encapsulates the blob itself and information about its position - in parent image. - - The class is not responsible for blob's image disposing, so it should be - done manually when it is required. - - - - - - Initializes a new instance of the class. - - - Blob's ID in the original image. - Blob's rectangle in the original image. - - This constructor leaves property not initialized. The blob's - image may be extracted later using - or method. - - - - - Initializes a new instance of the class. - - - Source blob to copy. - - This copy constructor leaves property not initialized. The blob's - image may be extracted later using - or method. - - - - - Blob's image. - - - The property keeps blob's image. In the case if it equals to null, - the image may be extracted using - or method. - - - - - Blob's image size. - - - The property specifies size of the blob's image. - If the property is set to , the blob's image size equals to the - size of original image. If the property is set to , the blob's - image size equals to size of actual blob. - - - - - Blob's rectangle in the original image. - - - The property specifies position of the blob in the original image - and its size. - - - - - Blob's ID in the original image. - - - - - Blob's area. - - - The property equals to blob's area measured in number of pixels - contained by the blob. - - - - - Blob's fullness, [0, 1]. - - - The property equals to blob's fullness, which is calculated - as Area / ( Width * Height ). If it equals to 1, then - it means that entire blob's rectangle is filled by blob's pixel (no - blank areas), which is true only for rectangles. If it equals to 0.5, - for example, then it means that only half of the bounding rectangle is filled - by blob's pixels. - - - - - Blob's center of gravity point. - - - The property keeps center of gravity point, which is calculated as - mean value of X and Y coordinates of blob's points. - - - - - Blob's mean color. - - - The property keeps mean color of pixels comprising the blob. - - - - - Blob color's standard deviation. - - - The property keeps standard deviation of pixels' colors comprising the blob. - - - - - Hough circle. - - - Represents circle of Hough transform. - - - - - - - Circle center's X coordinate. - - - - - Circle center's Y coordinate. - - - - - Circle's radius. - - - - - Line's absolute intensity. - - - - - Line's relative intensity. - - - - - Initializes a new instance of the class. - - - Circle's X coordinate. - Circle's Y coordinate. - Circle's radius. - Circle's absolute intensity. - Circle's relative intensity. - - - - - Compare the object with another instance of this class. - - - Object to compare with. - - A signed number indicating the relative values of this instance and value: 1) greater than zero - - this instance is greater than value; 2) zero - this instance is equal to value; - 3) greater than zero - this instance is less than value. - - The sort order is descending. - - - Object are compared using their intensity value. - - - - - - Hough circle transformation. - - - The class implements Hough circle transformation, which allows to detect - circles of specified radius in an image. - - The class accepts binary images for processing, which are represented by 8 bpp grayscale images. - All black pixels (0 pixel's value) are treated as background, but pixels with different value are - treated as circles' pixels. - - Sample usage: - - HoughCircleTransformation circleTransform = new HoughCircleTransformation( 35 ); - // apply Hough circle transform - circleTransform.ProcessImage( sourceImage ); - Bitmap houghCirlceImage = circleTransform.ToBitmap( ); - // get circles using relative intensity - HoughCircle[] circles = circleTransform.GetCirclesByRelativeIntensity( 0.5 ); - - foreach ( HoughCircle circle in circles ) - { - // ... - } - - - Initial image: - - Hough circle transformation image: - - - - - - - - - Initializes a new instance of the class. - - - Circles' radius to detect. - - - - - Process an image building Hough map. - - - Source image to process. - - Unsupported pixel format of the source image. - - - - - Process an image building Hough map. - - - Source image data to process. - - Unsupported pixel format of the source image. - - - - - Process an image building Hough map. - - - Source unmanaged image to process. - - Unsupported pixel format of the source image. - - - - - Сonvert Hough map to bitmap. - - - Returns 8 bppp grayscale bitmap, which shows Hough map. - - Hough transformation was not yet done by calling - ProcessImage() method. - - - - - Get specified amount of circles with highest intensity. - - - Amount of circles to get. - - Returns arrary of most intesive circles. If there are no circles detected, - the returned array has zero length. - - - - - Get circles with relative intensity higher then specified value. - - - Minimum relative intesity of circles. - - Returns arrary of most intesive circles. If there are no circles detected, - the returned array has zero length. - - - - - Minimum circle's intensity in Hough map to recognize a circle. - - - The value sets minimum intensity level for a circle. If a value in Hough - map has lower intensity, then it is not treated as a circle. - - Default value is set to 10. - - - - - Radius for searching local peak value. - - - The value determines radius around a map's value, which is analyzed to determine - if the map's value is a local maximum in specified area. - - Default value is set to 4. Minimum value is 1. Maximum value is 10. - - - - - Maximum found intensity in Hough map. - - - The property provides maximum found circle's intensity. - - - - - Found circles count. - - - The property provides total number of found circles, which intensity is higher (or equal to), - than the requested minimum intensity. - - - - - Performs quadrilateral transformation using bilinear algorithm for interpolation. - - - The class is deprecated and should be used instead. - - - - - - - - Initializes a new instance of the class. - - - Corners of the source quadrilateral area. - Width of the new transformed image. - Height of the new transformed image. - - This constructor sets to - , which means that destination image will have width and - height as specified by user. - - - - - Initializes a new instance of the class. - - - Corners of the source quadrilateral area. - - This constructor sets to - , which means that destination image will have width and - height automatically calculated based on property. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - - - - Calculates new image size. - - - Source image data. - - New image size - size of the destination image. - - The specified quadrilateral's corners are outside of the given image. - - - - - Format translations dictionary. - - - - - Automatic calculation of destination image or not. - - - The property specifies how to calculate size of destination (transformed) - image. If the property is set to , then - and properties have effect and destination image's size is - specified by user. If the property is set to , then setting the above - mentioned properties does not have any effect, but destionation image's size is - automatically calculated from property - width and height - come from length of longest edges. - - - - - - Quadrilateral's corners in source image. - - - The property specifies four corners of the quadrilateral area - in the source image to be transformed. - - - - - - Width of the new transformed image. - - - The property defines width of the destination image, which gets - transformed quadrilateral image. - - Setting the property does not have any effect, if - property is set to . In this case destination image's width - is calculated automatically based on property. - - - - - - Height of the new transformed image. - - - The property defines height of the destination image, which gets - transformed quadrilateral image. - - Setting the property does not have any effect, if - property is set to . In this case destination image's height - is calculated automatically based on property. - - - - - - Performs backward quadrilateral transformation into an area in destination image. - - - The class implements backward quadrilateral transformation algorithm, - which allows to transform any rectangular image into any quadrilateral area - in a given destination image. The idea of the algorithm is based on homogeneous - transformation and its math is described by Paul Heckbert in his - "Projective Mappings for Image Warping" paper. - - - The image processing routines implements similar math to , - but performs it in backward direction. - - The image processing filter accepts 8 grayscale images and 24/32 bpp - color images for processing. - - Sample usage: - - // define quadrilateral's corners - List<IntPoint> corners = new List<IntPoint>( ); - corners.Add( new IntPoint( 99, 99 ) ); - corners.Add( new IntPoint( 156, 79 ) ); - corners.Add( new IntPoint( 184, 126 ) ); - corners.Add( new IntPoint( 122, 150 ) ); - // create filter - BackwardQuadrilateralTransformation filter = - new BackwardQuadrilateralTransformation( sourceImage, corners ); - // apply the filter - Bitmap newImage = filter.Apply( image ); - - - Source image: - - Destination image: - - Result image: - - - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Source image to be transformed into specified quadrilateral - (see ). - - - - - Initializes a new instance of the class. - - - Source unmanaged image to be transformed into specified quadrilateral - (see ). - - - - - Initializes a new instance of the class. - - - Source image to be transformed into specified quadrilateral - (see ). - Quadrilateral in destination image to transform into. - - - - - Initializes a new instance of the class. - - - Source unmanaged image to be transformed into specified quadrilateral - (see ). - Quadrilateral in destination image to transform into. - - - - - Process the filter on the specified image. - - - Image data to process by the filter. - - Destination quadrilateral was not set. - - - - - Format translations dictionary. - - - See - documentation for additional information. - - - - - Source image to be transformed into specified quadrilateral. - - - The property sets the source image, which will be transformed - to the specified quadrilateral and put into destination image the filter is applied to. - - The source image must have the same pixel format as a destination image the filter - is applied to. Otherwise exception will be generated when filter is applied. - - Setting this property will clear the property - - only one source image is allowed: managed or unmanaged. - - - - - - Source unmanaged image to be transformed into specified quadrilateral. - - - The property sets the source image, which will be transformed - to the specified quadrilateral and put into destination image the filter is applied to. - - The source image must have the same pixel format as a destination image the filter - is applied to. Otherwise exception will be generated when filter is applied. - - Setting this property will clear the property - - only one source image is allowed: managed or unmanaged. - - - - - - Quadrilateral in destination image to transform into. - - - The property specifies 4 corners of a quadrilateral area - in destination image where the source image will be transformed into. - - - - - - Specifies if bilinear interpolation should be used or not. - - - Default value is set to - interpolation - is used. - - - - - - Image warp effect filter. - - - The image processing filter implements a warping filter, which - sets pixels in destination image to values from source image taken with specified offset - (see ). - - - The filter accepts 8 bpp grayscale images and 24/32 - color images for processing. - - Sample usage: - - // build warp map - int width = image.Width; - int height = image.Height; - - IntPoint[,] warpMap = new IntPoint[height, width]; - - int size = 8; - int maxOffset = -size + 1; - - for ( int y = 0; y < height; y++ ) - { - for ( int x = 0; x < width; x++ ) - { - int dx = ( x / size ) * size - x; - int dy = ( y / size ) * size - y; - - if ( dx + dy <= maxOffset ) - { - dx = ( x / size + 1 ) * size - 1 - x; - } - - warpMap[y, x] = new IntPoint( dx, dy ); - } - } - // create filter - ImageWarp filter = new ImageWarp( warpMap ); - // apply the filter - Bitmap newImage = filter.Apply( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - Map used for warping images (see ). - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - - - - Map used for warping images. - - - The property sets displacement map used for warping images. - The map sets offsets of pixels in source image, which are used to set values in destination - image. In other words, each pixel in destination image is set to the same value - as pixel in source image with corresponding offset (coordinates of pixel in source image - are calculated as sum of destination coordinate and corresponding value from warp map). - - - The map array is accessed using [y, x] indexing, i.e. - first dimension in the map array corresponds to Y axis of image. - - If the map is smaller or bigger than the image to process, then only minimum - overlapping area of the image is processed. This allows to prepare single big map and reuse - it for a set of images for creating similar effects. - - - - - - Format translations dictionary. - - - See - documentation for additional information. - - - - - Horizontal run length smoothing algorithm. - - - The class implements horizontal run length smoothing algorithm, which - is described in: K.Y. Wong, R.G. Casey and F.M. Wahl, "Document analysis system," - IBM J. Res. Devel., Vol. 26, NO. 6,111). 647-656, 1982. - - Unlike the original description of this algorithm, this implementation must be applied - to inverted binary images containing document, i.e. white text on black background. So this - implementation fills horizontal black gaps between white pixels. - - This algorithm is usually used together with , - and then further analysis of white blobs. - - The filter accepts 8 bpp grayscale images, which are supposed to be binary inverted documents. - - Sample usage: - - // create filter - HorizontalRunLengthSmoothing hrls = new HorizontalRunLengthSmoothing( 32 ); - // apply the filter - hrls.ApplyInPlace( image ); - - - Source image: - - Result image: - - - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Maximum gap size to fill (see ). - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Maximum gap size to fill (in pixels). - - - The property specifies maximum horizontal gap between white pixels to fill. - If number of black pixels between some white pixels is bigger than this value, then those - black pixels are left as is; otherwise the gap is filled with white pixels. - - - Default value is set to 10. Minimum value is 1. Maximum value is 1000. - - - - - Process gaps between objects and image borders or not. - - - The property sets if gaps between image borders and objects must be treated as - gaps between objects and also filled. - - Default value is set to . - - - - - - Format translations dictionary. - - - See - documentation for additional information. - - - - - Extract the biggest blob from image. - - - The filter locates the biggest blob in the source image and extracts it. - The filter also can use the source image for the biggest blob's location only, but extract it from - another image, which is set using property. The original image - usually is the source of the processed image. - - The filter accepts 8 bpp grayscale images and 24/32 color images for processing as source image passed to - method and also for the . - - Sample usage: - - // create filter - ExtractBiggestBlob filter = new ExtractBiggestBlob( ); - // apply the filter - Bitmap biggestBlobsImage = filter.Apply( image ); - - - Initial image: - - Result image: - - - - - - - Apply filter to an image. - - - Source image to get biggest blob from. - - Returns image of the biggest blob. - - Unsupported pixel format of the source image. - Unsupported pixel format of the original image. - Source and original images must have the same size. - The source image does not contain any blobs. - - - - - Apply filter to an image. - - - Source image to get biggest blob from. - - Returns image of the biggest blob. - - Unsupported pixel format of the source image. - Unsupported pixel format of the original image. - Source and original images must have the same size. - The source image does not contain any blobs. - - - - - Apply filter to an image (not implemented). - - - Image in unmanaged memory. - - Returns filter's result obtained by applying the filter to - the source image. - - The method is not implemented. - - - - - Apply filter to an image (not implemented). - - - Source image to be processed. - Destination image to store filter's result. - - The method is not implemented. - - - - - Position of the extracted blob. - - - After applying the filter this property keeps position of the extracted - blob in the source image. - - - - - Format translations dictionary. - - - The dictionary defines, which pixel formats are supported for - source images and which pixel format will be used for resulting image. - - - See for more information. - - - - - - Original image, which is the source of the processed image where the biggest blob is searched for. - - - The property may be set to . In this case the biggest blob - is extracted from the image, which is passed to image. - - - - - - Dilatation operator from Mathematical Morphology with 3x3 structuring element. - - - The filter represents an optimized version of - filter, which is aimed for grayscale image processing with 3x3 structuring element. - - See filter, which represents generic version of - dilatation filter supporting custom structuring elements and wider range of image formats. - - The filter accepts 8 bpp grayscale images for processing. - - - - - - - - - Initializes a new instance of the class. - - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - Image rectangle for processing by the filter. - - Processing rectangle mast be at least 3x3 in size. - - - - - Format translations dictionary. - - - - - Grayscale image using BT709 algorithm. - - - The class uses BT709 algorithm to convert color image - to grayscale. The conversion coefficients are: - - Red: 0.2125; - Green: 0.7154; - Blue: 0.0721. - - - - - - - - - - - Initializes a new instance of the class. - - - - - Possible object orders. - - - The enumeration defines possible sorting orders of objects, found by blob - counting classes. - - - - - Unsorted order (as it is collected by algorithm). - - - - - Objects are sorted by size in descending order (bigger objects go first). - Size is calculated as Width * Height. - - - - - Objects are sorted by area in descending order (bigger objects go first). - - - - - Objects are sorted by Y coordinate, then by X coordinate in ascending order - (smaller coordinates go first). - - - - - Objects are sorted by X coordinate, then by Y coordinate in ascending order - (smaller coordinates go first). - - - - - Blob counter - counts objects in image, which are separated by black background. - - - The class counts and extracts stand alone objects in - images using connected components labeling algorithm. - - The algorithm treats all pixels with values less or equal to - as background, but pixels with higher values are treated as objects' pixels. - - For blobs' searching the class supports 8 bpp indexed grayscale images and - 24/32 bpp color images that are at least two pixels wide. Images that are one - pixel wide can be processed if they are rotated first, or they can be processed - with . - See documentation about for information about which - pixel formats are supported for extraction of blobs. - - Sample usage: - - // create an instance of blob counter algorithm - BlobCounter bc = new BlobCounter( ); - // process binary image - bc.ProcessImage( image ); - Rectangle[] rects = bc.GetObjectsRectangles( ); - // process blobs - foreach ( Rectangle rect in rects ) - { - // ... - } - - - - - - - Initializes a new instance of the class. - - - Creates new instance of the class with - an empty objects map. Before using methods, which provide information about blobs - or extract them, the , - or - method should be called to collect objects map. - - - - - Initializes a new instance of the class. - - - Image to look for objects in. - - - - - Initializes a new instance of the class. - - - Image data to look for objects in. - - - - - Initializes a new instance of the class. - - - Unmanaged image to look for objects in. - - - - - Actual objects map building. - - - Unmanaged image to process. - - The method supports 8 bpp indexed grayscale images and 24/32 bpp color images. - - Unsupported pixel format of the source image. - Cannot process images that are one pixel wide. Rotate the image - or use . - - - - - Background threshold's value. - - - The property sets threshold value for distinguishing between background - pixel and objects' pixels. All pixel with values less or equal to this property are - treated as background, but pixels with higher values are treated as objects' pixels. - - In the case of colour images a pixel is treated as objects' pixel if any of its - RGB values are higher than corresponding values of this threshold. - - For processing grayscale image, set the property with all RGB components eqaul. - - Default value is set to (0, 0, 0) - black colour. - - - - - Gather statistics about image in YCbCr color space. - - - The class is used to accumulate statistical values about images, - like histogram, mean, standard deviation, etc. for each YCbCr color channel. - - The class accepts 24 and 32 bpp color images for processing. - - Sample usage: - - // gather statistics - ImageStatisticsYCbCr stat = new ImageStatisticsYCbCr( image ); - // get Y channel's histogram - ContinuousHistogram y = stat.Y; - // check mean value of Y channel - if ( y.Mean > 0.5 ) - { - // do further processing - } - - - - - - - - - Initializes a new instance of the class. - - - Image to gather statistics about. - - Source pixel format is not supported. - - - - - Initializes a new instance of the class. - - - Image to gather statistics about. - Mask image which specifies areas to collect statistics for. - - The mask image must be a grayscale/binary (8bpp) image of the same size as the - specified source image, where black pixels (value 0) correspond to areas which should be excluded - from processing. So statistics is calculated only for pixels, which are none black in the mask image. - - - Source pixel format is not supported. - Mask image must be 8 bpp grayscale image. - Mask must have the same size as the source image to get statistics for. - - - - - Initializes a new instance of the class. - - - Image to gather statistics about. - Mask array which specifies areas to collect statistics for. - - The mask array must be of the same size as the specified source image, where 0 values - correspond to areas which should be excluded from processing. So statistics is calculated only for pixels, - which have none zero corresponding value in the mask. - - - Source pixel format is not supported. - Mask must have the same size as the source image to get statistics for. - - - - - Initializes a new instance of the class. - - - Unmanaged image to gather statistics about. - - Source pixel format is not supported. - - - - - Initializes a new instance of the class. - - - Image to gather statistics about. - Mask image which specifies areas to collect statistics for. - - The mask image must be a grayscale/binary (8bpp) image of the same size as the - specified source image, where black pixels (value 0) correspond to areas which should be excluded - from processing. So statistics is calculated only for pixels, which are none black in the mask image. - - - Source pixel format is not supported. - Mask image must be 8 bpp grayscale image. - Mask must have the same size as the source image to get statistics for. - - - - - Initializes a new instance of the class. - - - Image to gather statistics about. - Mask array which specifies areas to collect statistics for. - - The mask array must be of the same size as the specified source image, where 0 values - correspond to areas which should be excluded from processing. So statistics is calculated only for pixels, - which have none zero corresponding value in the mask. - - - Source pixel format is not supported. - Mask must have the same size as the source image to get statistics for. - - - - - Histogram of Y channel. - - - - - - Histogram of Cb channel. - - - - - - Histogram of Cr channel. - - - - - - Histogram of Y channel excluding black pixels. - - - The property keeps statistics about Y channel, which - excludes all black pixels, what affects mean, standard deviation, etc. - - - - - - Histogram of Cb channel excluding black pixels - - - The property keeps statistics about Cb channel, which - excludes all black pixels, what affects mean, standard deviation, etc. - - - - - - Histogram of Cr channel excluding black pixels - - - The property keeps statistics about Cr channel, which - excludes all black pixels, what affects mean, standard deviation, etc. - - - - - - Total pixels count in the processed image. - - - - - - Total pixels count in the processed image excluding black pixels. - - - - - - Color filtering in YCbCr color space. - - - The filter operates in YCbCr color space and filters - pixels, which color is inside/outside of the specified YCbCr range - - it keeps pixels with colors inside/outside of the specified range and fills the - rest with specified color. - - The filter accepts 24 and 32 bpp color images for processing. - - Sample usage: - - // create filter - YCbCrFiltering filter = new YCbCrFiltering( ); - // set color ranges to keep - filter.Cb = new Range( -0.2f, 0.0f ); - filter.Cr = new Range( 0.26f, 0.5f ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Range of Y component. - Range of Cb component. - Range of Cr component. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Range of Y component, [0, 1]. - - - - - - Range of Cb component, [-0.5, 0.5]. - - - - - - Range of Cr component, [-0.5, 0.5]. - - - - - - Fill color used to fill filtered pixels. - - - - - Determines, if pixels should be filled inside or outside specified - color range. - - - Default value is set to , which means - the filter removes colors outside of the specified range. - - - - - Determines, if Y value of filtered pixels should be updated. - - - The property specifies if Y channel of filtered pixels should be - updated with value from fill color or not. - - Default value is set to . - - - - - Determines, if Cb value of filtered pixels should be updated. - - - The property specifies if Cb channel of filtered pixels should be - updated with value from fill color or not. - - Default value is set to . - - - - - Determines, if Cr value of filtered pixels should be updated. - - - The property specifies if Cr channel of filtered pixels should be - updated with value from fill color or not. - - Default value is set to . - - - - - Bilateral filter implementation - edge preserving smoothing and noise reduction that uses chromatic and spatial factors. - - - - Bilateral filter conducts "selective" Gaussian smoothing of areas of same color (domains) which removes noise and contrast artifacts - while preserving sharp edges. - - Two major parameters and define the result of the filter. - By changing these parameters you may achieve either only noise reduction with little change to the - image or get nice looking effect to the entire image. - - Although the filter can use parallel processing large values - (greater than 25) on high resolution images may decrease speed of processing. Also on high - resolution images small values (less than 9) may not provide noticeable - results. - - More details on the algorithm can be found by following this - link. - - The filter accepts 8 bpp grayscale images and 24/32 bpp color images for processing. - - Sample usage: - - // create filter - BilateralSmoothing filter = new BilateralSmoothing( ); - filter.KernelSize = 7; - filter.SpatialFactor = 10; - filter.ColorFactor = 60; - filter.ColorPower = 0.5; - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - Image rectangle for processing by the filter. - - - - - Specifies if exception must be thrown in the case a large - kernel size is used which may lead - to significant performance issues. - - - - Default value is set to . - - - - - - Enable or not parallel processing on multi-core CPUs. - - - If the property is set to , then this image processing - routine will run in parallel on the systems with multiple core/CPUs. The - is used to make it parallel. - - Default value is set to . - - - - - - Size of a square for limiting surrounding pixels that take part in calculations, [3, 255]. - - - The greater the value the more is the general power of the filter. Small values - (less than 9) on high resolution images (3000 pixels wide) do not give significant results. - Large values increase the number of calculations and degrade performance. - - The value of this property must be an odd integer in the [3, 255] range if - is set to or in the [3, 25] range - otherwise. - - Default value is set to 9. - - - The specified value is out of range (see - eception message for details). - The value of this must be an odd integer. - - - - - Determines smoothing power within a color domain (neighbor pixels of similar color), >= 1. - - - - Default value is set to 10. - - - - - - Exponent power, used in Spatial function calculation, >= 1. - - - - Default value is set to 2. - - - - - - Determines the variance of color for a color domain, >= 1. - - - - Default value is set to 50. - - - - - - Exponent power, used in Color function calculation, >= 1. - - - - Default value is set to 2. - - - - - - Format translations dictionary. - - - See - documentation for additional information. - - - - - Opening operator from Mathematical Morphology. - - - Opening morphology operator equals to erosion followed - by dilatation. - - Applied to binary image, the filter may be used for removing small object keeping big objects - unchanged. Since erosion is used first, it removes all small objects. Then dilatation restores big - objects, which were not removed by erosion. - - See documentation to and classes for more - information and list of supported pixel formats. - - Sample usage: - - // create filter - Opening filter = new Opening( ); - // apply the filter - filter.Apply( image ); - - - Initial image: - - Result image: - - - - - - - - - - - Initializes a new instance of the class. - - - Initializes new instance of the class using - default structuring element for both and - classes - 3x3 structuring element with all elements equal to 1. - - - - - - Initializes a new instance of the class. - - - Structuring element. - - See documentation to and - classes for information about structuring element constraints. - - - - - Apply filter to an image. - - - Source image to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The method keeps the source image unchanged and returns - the result of image processing filter as new image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image. - - - Source image to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The filter accepts bitmap data as input and returns the result - of image processing filter as new image. The source image data are kept - unchanged. - - - - - Apply filter to an image in unmanaged memory. - - - Source image in unmanaged memory to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The method keeps the source image unchanged and returns - the result of image processing filter as new image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image in unmanaged memory. - - - Source image in unmanaged memory to apply filter to. - Destination image in unmanaged memory to put result into. - - The method keeps the source image unchanged and puts result of image processing - into destination image. - - The destination image must have the same width and height as source image. Also - destination image must have pixel format, which is expected by particular filter (see - property for information about pixel format conversions). - - - Unsupported pixel format of the source image. - Incorrect destination pixel format. - Destination image has wrong width and/or height. - - - - - Apply filter to an image. - - - Image to apply filter to. - - The method applies the filter directly to the provided source image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image. - - - Image data to apply filter to. - - The method applies the filter directly to the provided source image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an unmanaged image. - - - Unmanaged image to apply filter to. - - The method applies the filter directly to the provided source unmanaged image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image or its part. - - - Image to apply filter to. - Image rectangle for processing by the filter. - - The method applies the filter directly to the provided source image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image or its part. - - - Image data to apply filter to. - Image rectangle for processing by the filter. - - The method applies the filter directly to the provided source image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an unmanaged image or its part. - - - Unmanaged image to apply filter to. - Image rectangle for processing by the filter. - - The method applies the filter directly to the provided source image. - - Unsupported pixel format of the source image. - - - - - Format translations dictionary. - - - - - Dilatation operator from Mathematical Morphology. - - - The filter assigns maximum value of surrounding pixels to each pixel of - the result image. Surrounding pixels, which should be processed, are specified by - structuring element: 1 - to process the neighbor, -1 - to skip it. - - The filter especially useful for binary image processing, where it allows to grow - separate objects or join objects. - - For processing image with 3x3 structuring element, there are different optimizations - available, like and . - - The filter accepts 8 and 16 bpp grayscale images and 24 and 48 bpp - color images for processing. - - Sample usage: - - // create filter - Dilatation filter = new Dilatation( ); - // apply the filter - filter.Apply( image ); - - - Initial image: - - Result image: - - - - - - - - - - - - - Initializes a new instance of the class. - - - Initializes new instance of the class using - default structuring element - 3x3 structuring element with all elements equal to 1. - - - - - - Initializes a new instance of the class. - - - Structuring element. - - Structuring elemement for the dilatation morphological operator - must be square matrix with odd size in the range of [3, 99]. - - Invalid size of structuring element. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Filters' collection to apply to an image in sequence. - - - The class represents collection of filters, which need to be applied - to an image in sequence. Using the class user may specify set of filters, which will - be applied to source image one by one in the order user defines them. - - The class itself does not define which pixel formats are accepted for the source - image and which pixel formats may be produced by the filter. Format of acceptable source - and possible output is defined by filters, which added to the sequence. - - Sample usage: - - // create filter, which is binarization sequence - FiltersSequence filter = new FiltersSequence( - new GrayscaleBT709( ), - new Threshold( ) - ); - // apply the filter - Bitmap newImage = filter.Apply( image ); - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Sequence of filters to apply. - - - - - Add new filter to the sequence. - - - Filter to add to the sequence. - - - - - Apply filter to an image. - - - Source image to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The method keeps the source image unchanged and returns - the result of image processing filter as new image. - - No filters were added into the filters' sequence. - - - - - Apply filter to an image. - - - Source image to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The filter accepts bitmap data as input and returns the result - of image processing filter as new image. The source image data are kept - unchanged. - - No filters were added into the filters' sequence. - - - - - Apply filter to an image in unmanaged memory. - - - Source image in unmanaged memory to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The method keeps the source image unchanged and returns - the result of image processing filter as new image. - - No filters were added into the filters' sequence. - - - - - Apply filter to an image in unmanaged memory. - - - Source image in unmanaged memory to apply filter to. - Destination image in unmanaged memory to put result into. - - The method keeps the source image unchanged and puts result of image processing - into destination image. - - The destination image must have width, height and pixel format as it is expected by - the final filter in the sequence. - - - No filters were added into the filters' sequence. - - - - - Get filter at the specified index. - - - Index of filter to get. - - Returns filter at specified index. - - - - - Contrast adjusting in RGB color space. - - - The filter operates in RGB color space and adjusts - pixels' contrast value by increasing RGB values of bright pixel and decreasing - RGB values of dark pixels (or vise versa if contrast needs to be decreased). - The filter is based on - filter and simply sets all input ranges to (, 255-) and - all output range to (0, 255) in the case if the factor value is positive. - If the factor value is negative, then all input ranges are set to - (0, 255 ) and all output ranges are set to - (-, 255_). - - See documentation forr more information about the base filter. - - The filter accepts 8 bpp grayscale and 24/32 bpp color images for processing. - - Sample usage: - - // create filter - ContrastCorrection filter = new ContrastCorrection( 15 ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Contrast adjusting factor. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Contrast adjusting factor, [-127, 127]. - - - Factor which is used to adjust contrast. Factor values greater than - 0 increase contrast making light areas lighter and dark areas darker. Factor values - less than 0 decrease contrast - decreasing variety of contrast. - - Default value is set to 10. - - - - - Format translations dictionary. - - - See - documentation for additional information. - - - - - Marble texture. - - - The texture generator creates textures with effect of marble. - The and properties allow to control the look - of marble texture in X/Y directions. - - The generator is based on the Perlin noise function. - - Sample usage: - - // create texture generator - MarbleTexture textureGenerator = new MarbleTexture( ); - // generate new texture - float[,] texture = textureGenerator.Generate( 320, 240 ); - // convert it to image to visualize - Bitmap textureImage = TextureTools.ToBitmap( texture ); - - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - X period value. - Y period value. - - - - - Generate texture. - - - Texture's width. - Texture's height. - - Two dimensional array of intensities. - - Generates new texture of the specified size. - - - - - Reset generator. - - - Regenerates internal random numbers. - - - - - X period value, ≥ 2. - - - Default value is set to 5. - - - - - Y period value, ≥ 2. - - - Default value is set to 10. - - - - - Transform rectangle image into circle (to polar coordinates). - - - The image processing routine does transformation of the source image into - circle (polar transformation). The produced effect is similar to GIMP's "Polar Coordinates" - distortion filter (or its equivalent in Photoshop). - - - The filter accepts 8 bpp grayscale and 24/32 bpp color images for processing. - - Sample usage: - - // create filter - TransformToPolar filter = new TransformToPolar( ); - filter.OffsetAngle = 0; - filter.CirlceDepth = 1; - filter.UseOriginalImageSize = false; - filter.NewSize = new Size( 200, 200 ); - // apply the filter - Bitmap newImage = filter.Apply( image ); - - - Initial image: - - Result image: - - - - - - - - - Initializes a new instance of the class. - - - - - - Calculates new image size. - - - Source image data. - - New image size - size of the destination image. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - - - - Circularity coefficient of the mapping, [0, 1]. - - - The property specifies circularity coefficient of the mapping to be done. - If the coefficient is set to 1, then the mapping will produce ideal circle. If the coefficient - is set to 0, then the mapping will occupy entire area of the destination image (circle will - be extended into direction of edges). Changing the property from 0 to 1 user may balance - circularity of the produced output. - - - Default value is set to 1. - - - - - - Offset angle used to shift mapping, [-360, 360] degrees. - - - The property specifies offset angle, which can be used to shift - mapping in counter clockwise direction. For example, if user sets this property to 30, then - start of polar mapping is shifted by 30 degrees in counter clockwise direction. - - Default value is set to 0. - - - - - - Specifies direction of mapping. - - - The property specifies direction of mapping source image's X axis. If the - property is set to , the image is mapped in clockwise direction; - otherwise in counter clockwise direction. - - Default value is set to . - - - - - - Specifies if top of the source image should go to center or edge of the result image. - - - The property specifies position of the source image's top line in the destination - image. If the property is set to , then it goes to the center of the result image; - otherwise it goes to the edge. - - Default value is set to . - - - - - - Fill color to use for unprocessed areas. - - - The property specifies fill color, which is used to fill unprocessed areas. - In the case if is greater than 0, then there will be some areas on - the image's edge, which are not filled by the produced "circular" image, but are filled by - the specified color. - - - Default value is set to . - - - - - - Size of destination image. - - - The property specifies size of result image produced by this image - processing routine in the case if property - is set to . - - Both width and height must be in the [1, 10000] range. - - Default value is set to 200 x 200. - - - - - - Use source image size for destination or not. - - - The property specifies if the image processing routine should create destination - image of the same size as original image or of the size specified by - property. - - Default value is set to . - - - - - - Format translations dictionary. - - - See - documentation for additional information. - - - - - Transform polar image into rectangle. - - - The image processing routine is oposite transformation to the one done by - routine, i.e. transformation from polar image into rectangle. The produced effect is similar to GIMP's - "Polar Coordinates" distortion filter (or its equivalent in Photoshop). - - The filter accepts 8 bpp grayscale and 24/32 bpp color images for processing. - - Sample usage: - - // create filter - TransformFromPolar filter = new TransformFromPolar( ); - filter.OffsetAngle = 0; - filter.CirlceDepth = 1; - filter.UseOriginalImageSize = false; - filter.NewSize = new Size( 360, 120 ); - // apply the filter - Bitmap newImage = filter.Apply( image ); - - - Initial image: - - Result image: - - - - - - - - - Initializes a new instance of the class. - - - - - - Calculates new image size. - - - Source image data. - - New image size - size of the destination image. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - - - - Circularity coefficient of the mapping, [0, 1]. - - - The property specifies circularity coefficient of the mapping to be done. - If the coefficient is set to 1, then destination image will be produced by mapping - ideal circle from the source image, which is placed in source image's centre and its - radius equals to the minimum distance from centre to the image’s edge. If the coefficient - is set to 0, then the mapping will use entire area of the source image (circle will - be extended into direction of edges). Changing the property from 0 to 1 user may balance - circularity of the produced output. - - Default value is set to 1. - - - - - - Offset angle used to shift mapping, [-360, 360] degrees. - - - The property specifies offset angle, which can be used to shift - mapping in clockwise direction. For example, if user sets this property to 30, then - start of polar mapping is shifted by 30 degrees in clockwise direction. - - Default value is set to 0. - - - - - - Specifies direction of mapping. - - - The property specifies direction of mapping source image. If the - property is set to , the image is mapped in clockwise direction; - otherwise in counter clockwise direction. - - Default value is set to . - - - - - - Specifies if centre of the source image should to top or bottom of the result image. - - - The property specifies position of the source image's centre in the destination image. - If the property is set to , then it goes to the top of the result image; - otherwise it goes to the bottom. - - Default value is set to . - - - - - - Size of destination image. - - - The property specifies size of result image produced by this image - processing routine in the case if property - is set to . - - Both width and height must be in the [1, 10000] range. - - Default value is set to 200 x 200. - - - - - - Use source image size for destination or not. - - - The property specifies if the image processing routine should create destination - image of the same size as original image or of the size specified by - property. - - Default value is set to . - - - - - - Format translations dictionary. - - - See - documentation for additional information. - - - - - Rotate image using bicubic interpolation. - - - The class implements image rotation filter using bicubic - interpolation algorithm. It uses bicubic kernel W(x) as described on - Wikipedia - (coefficient a is set to -0.5). - - Rotation is performed in counterclockwise direction. - - The filter accepts 8 bpp grayscale images and 24 bpp - color images for processing. - - Sample usage: - - // create filter - rotate for 30 degrees keeping original image size - RotateBicubic filter = new RotateBicubic( 30, true ); - // apply the filter - Bitmap newImage = filter.Apply( image ); - - - Initial image: - - Result image: - - - - - - - - - - Initializes a new instance of the class. - - - Rotation angle. - - This constructor sets property - to . - - - - - - Initializes a new instance of the class. - - - Rotation angle. - Keep image size or not. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - - - - Format translations dictionary. - - - - - Vertical run length smoothing algorithm. - - - The class implements vertical run length smoothing algorithm, which - is described in: K.Y. Wong, R.G. Casey and F.M. Wahl, "Document analysis system," - IBM J. Res. Devel., Vol. 26, NO. 6,111). 647-656, 1982. - - Unlike the original description of this algorithm, this implementation must be applied - to inverted binary images containing document, i.e. white text on black background. So this - implementation fills vertical black gaps between white pixels. - - This algorithm is usually used together with , - and then further analysis of white blobs. - - The filter accepts 8 bpp grayscale images, which are supposed to be binary inverted documents. - - Sample usage: - - // create filter - VerticalRunLengthSmoothing vrls = new VerticalRunLengthSmoothing( 32 ); - // apply the filter - vrls.ApplyInPlace( image ); - - - Source image: - - Result image: - - - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Maximum gap size to fill (see ). - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Maximum gap size to fill (in pixels). - - - The property specifies maximum vertical gap between white pixels to fill. - If number of black pixels between some white pixels is bigger than this value, then those - black pixels are left as is; otherwise the gap is filled with white pixels. - - - Default value is set to 10. Minimum value is 1. Maximum value is 1000. - - - - - Process gaps between objects and image borders or not. - - - The property sets if gaps between image borders and objects must be treated as - gaps between objects and also filled. - - Default value is set to . - - - - - - Format translations dictionary. - - - See - documentation for additional information. - - - - - Salt and pepper noise. - - - The filter adds random salt and pepper noise - sets - maximum or minimum values to randomly selected pixels. - - The filter accepts 8 bpp grayscale images and 24/32 bpp - color images for processing. - - Sample usage: - - // create filter - SaltAndPepperNoise filter = new SaltAndPepperNoise( 10 ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Amount of noise to generate in percents, [0, 100]. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Amount of noise to generate in percents, [0, 100]. - - - - - - Additive noise filter. - - - The filter adds random value to each pixel of the source image. - The distribution of random values can be specified by random generator. - - - The filter accepts 8 bpp grayscale images and 24 bpp - color images for processing. - - Sample usage: - - // create random generator - IRandomNumberGenerator generator = new UniformGenerator( new Range( -50, 50 ) ); - // create filter - AdditiveNoise filter = new AdditiveNoise( generator ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Random number genertor used to add noise. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Random number genertor used to add noise. - - - Default generator is uniform generator in the range of (-10, 10). - - - - - Closing operator from Mathematical Morphology. - - - Closing morphology operator equals to dilatation followed - by erosion. - - Applied to binary image, the filter may be used connect or fill objects. Since dilatation is used - first, it may connect/fill object areas. Then erosion restores objects. But since dilatation may connect - something before, erosion may not remove after that because of the formed connection. - - See documentation to and classes for more - information and list of supported pixel formats. - - Sample usage: - - // create filter - Closing filter = new Closing( ); - // apply the filter - filter.Apply( image ); - - - Initial image: - - Result image: - - - - - - - - - - - Initializes a new instance of the class. - - - Initializes new instance of the class using - default structuring element for both and - classes - 3x3 structuring element with all elements equal to 1. - - - - - - Initializes a new instance of the class. - - - Structuring element. - - See documentation to and - classes for information about structuring element constraints. - - - - - Apply filter to an image. - - - Source image to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The method keeps the source image unchanged and returns - the result of image processing filter as new image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image. - - - Source image to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The filter accepts bitmap data as input and returns the result - of image processing filter as new image. The source image data are kept - unchanged. - - - - - Apply filter to an image in unmanaged memory. - - - Source image in unmanaged memory to apply filter to. - - Returns filter's result obtained by applying the filter to - the source image. - - The method keeps the source image unchanged and returns - the result of image processing filter as new image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image in unmanaged memory. - - - Source image in unmanaged memory to apply filter to. - Destination image in unmanaged memory to put result into. - - The method keeps the source image unchanged and puts result of image processing - into destination image. - - The destination image must have the same width and height as source image. Also - destination image must have pixel format, which is expected by particular filter (see - property for information about pixel format conversions). - - - Unsupported pixel format of the source image. - Incorrect destination pixel format. - Destination image has wrong width and/or height. - - - - - Apply filter to an image. - - - Image to apply filter to. - - The method applies the filter directly to the provided source image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image. - - - Image data to apply filter to. - - The method applies the filter directly to the provided source image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an unmanaged image. - - - Unmanaged image to apply filter to. - - The method applies the filter directly to the provided source unmanaged image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image or its part. - - - Image to apply filter to. - Image rectangle for processing by the filter. - - The method applies the filter directly to the provided source image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an image or its part. - - - Image data to apply filter to. - Image rectangle for processing by the filter. - - The method applies the filter directly to the provided source image. - - Unsupported pixel format of the source image. - - - - - Apply filter to an unmanaged image or its part. - - - Unmanaged image to apply filter to. - Image rectangle for processing by the filter. - - The method applies the filter directly to the provided source image. - - Unsupported pixel format of the source image. - - - - - Format translations dictionary. - - - - - Hue modifier. - - - The filter operates in HSL color space and updates - pixels' hue values setting it to the specified value (luminance and - saturation are kept unchanged). The result of the filter looks like the image - is observed through a glass of the given color. - - The filter accepts 24 and 32 bpp color images for processing. - Sample usage: - - // create filter - HueModifier filter = new HueModifier( 180 ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Hue value to set. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Hue value to set, [0, 359]. - - - Default value is set to 0. - - - - - Set of Bayer patterns supported by . - - - - - Pattern:

- G R
- B G -
-
- - - Pattern:

- B G
- G R -
-
- - - Optimized Bayer fileter image processing routine. - - - The class implements Bayer filter - routine, which creates color image out of grayscale image produced by image sensor built with - Bayer color matrix. - - This class does all the same as class. However this version is - optimized for some well known patterns defined in enumeration. - Also this class processes images with even width and height only. Image size must be at least 2x2 pixels. - - - The filter accepts 8 bpp grayscale images and produces 24 bpp RGB image. - - Sample usage: - - // create filter - BayerFilter filter = new BayerFilter( ); - // apply the filter - Bitmap rgbImage = filter.Apply( image ); - - - - - - - - - Initializes a new instance of the class. - - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - - - - Bayer pattern of source images to decode. - - - The property specifies Bayer pattern of source images to be - decoded into color images. - - Default value is set to . - - - - - - Format translations dictionary. - - - See - documentation for additional information. - - - - - Color remapping. - - - The filter allows to remap colors of the image. Unlike filter - the filter allow to do non-linear remapping. For each pixel of specified image the filter changes - its values (value of each color plane) to values, which are stored in remapping arrays by corresponding - indexes. For example, if pixel's RGB value equals to (32, 96, 128), the filter will change it to - ([32], [96], [128]). - - The filter accepts 8 bpp grayscale and 24/32 bpp color images for processing. - - Sample usage: - - // create map - byte[] map = new byte[256]; - for ( int i = 0; i < 256; i++ ) - { - map[i] = (byte) Math.Min( 255, Math.Pow( 2, (double) i / 32 ) ); - } - // create filter - ColorRemapping filter = new ColorRemapping( map, map, map ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - Initializes the filter without any remapping. All - pixel values are mapped to the same values. - - - - - Initializes a new instance of the class. - - - Red map. - Green map. - Blue map. - - - - - Initializes a new instance of the class. - - - Gray map. - - This constructor is supposed for grayscale images. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Remapping array for red color plane. - - - The remapping array should contain 256 remapping values. The remapping occurs - by changing pixel's red value r to [r]. - - A map should be array with 256 value. - - - - - Remapping array for green color plane. - - - The remapping array should contain 256 remapping values. The remapping occurs - by changing pixel's green value g to [g]. - - A map should be array with 256 value. - - - - - Remapping array for blue color plane. - - - The remapping array should contain 256 remapping values. The remapping occurs - by changing pixel's blue value b to [b]. - - A map should be array with 256 value. - - - - - Remapping array for gray color. - - - The remapping array should contain 256 remapping values. The remapping occurs - by changing pixel's value g to [g]. - - The gray map is for grayscale images only. - - A map should be array with 256 value. - - - - - Binarization with thresholds matrix. - - - Idea of the filter is the same as idea of filter - - change pixel value to white, if its intensity is equal or higher than threshold value, or - to black otherwise. But instead of using single threshold value for all pixel, the filter - uses matrix of threshold values. Processing image is divided to adjacent windows of matrix - size each. For pixels binarization inside of each window, corresponding threshold values are - used from specified threshold matrix. - - The filter accepts 8 bpp grayscale images for processing. - - Sample usage: - - // create binarization matrix - byte[,] matrix = new byte[4, 4] - { - { 95, 233, 127, 255 }, - { 159, 31, 191, 63 }, - { 111, 239, 79, 207 }, - { 175, 47, 143, 15 } - }; - // create filter - OrderedDithering filter = new OrderedDithering( matrix ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Thresholds matrix. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Ordered dithering using Bayer matrix. - - - The filter represents filter initialized - with the next threshold matrix: - - byte[,] matrix = new byte[4, 4] - { - { 0, 192, 48, 240 }, - { 128, 64, 176, 112 }, - { 32, 224, 16, 208 }, - { 160, 96, 144, 80 } - }; - - - The filter accepts 8 bpp grayscale images for processing. - - Sample usage: - - // create filter - BayerDithering filter = new BayerDithering( ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - - Vertical intensity statistics. - - - The class provides information about vertical distribution - of pixel intensities, which may be used to locate objects, their centers, etc. - - - The class accepts grayscale (8 bpp indexed and 16 bpp) and color (24, 32, 48 and 64 bpp) images. - In the case of 32 and 64 bpp color images, the alpha channel is not processed - statistics is not - gathered for this channel. - - Sample usage: - - // collect statistics - VerticalIntensityStatistics vis = new VerticalIntensityStatistics( sourceImage ); - // get gray histogram (for grayscale image) - Histogram histogram = vis.Gray; - // output some histogram's information - System.Diagnostics.Debug.WriteLine( "Mean = " + histogram.Mean ); - System.Diagnostics.Debug.WriteLine( "Min = " + histogram.Min ); - System.Diagnostics.Debug.WriteLine( "Max = " + histogram.Max ); - - - Sample grayscale image with its vertical intensity histogram: - - - - - - - - - Initializes a new instance of the class. - - - Source image. - - Unsupported pixel format of the source image. - - - - - Initializes a new instance of the class. - - - Source image data. - - Unsupported pixel format of the source image. - - - - - Initializes a new instance of the class. - - - Source unmanaged image. - - Unsupported pixel format of the source image. - - - - - Gather vertical intensity statistics for specified image. - - - Source image. - - - - - Histogram for red channel. - - - - - - Histogram for green channel. - - - - - - Histogram for blue channel. - - - - - - Histogram for gray channel (intensities). - - - - - - Value wich specifies if the processed image was color or grayscale. - - - If the property equals to true, then the - property should be used to retrieve histogram for the processed grayscale image. - Otherwise , and property - should be used to retrieve histogram for particular RGB channel of the processed - color image. - - - - - Merge two images using factors from texture. - - - The filter is similar to filter in its idea, but - instead of using single value for balancing amount of source's and overlay's image - values (see ), the filter uses texture, which determines - the amount to take from source image and overlay image. - - The filter uses specified texture to adjust values using the next formula:
- dst = src * textureValue + ovr * ( 1.0 - textureValue ),
- where src is value of pixel in a source image, ovr is value of pixel in - overlay image, dst is value of pixel in a destination image and - textureValue is corresponding value from provided texture (see or - ).
- - The filter accepts 8 bpp grayscale and 24 bpp color images for processing. - - Sample usage #1: - - // create filter - TexturedMerge filter = new TexturedMerge( new TextileTexture( ) ); - // create an overlay image to merge with - filter.OverlayImage = new Bitmap( image.Width, image.Height, - PixelFormat.Format24bppRgb ); - // fill the overlay image with solid color - PointedColorFloodFill fillFilter = new PointedColorFloodFill( Color.DarkKhaki ); - fillFilter.ApplyInPlace( filter.OverlayImage ); - // apply the merge filter - filter.ApplyInPlace( image ); - - - Sample usage #2: - - // create filter - TexturedMerge filter = new TexturedMerge( new CloudsTexture( ) ); - // create 2 images with modified Hue - HueModifier hm1 = new HueModifier( 50 ); - HueModifier hm2 = new HueModifier( 200 ); - filter.OverlayImage = hm2.Apply( image ); - hm1.ApplyInPlace( image ); - // apply the merge filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image #1: - - Result image #2: - -
- -
- - - Initializes a new instance of the class. - - - Generated texture. - - - - - Initializes a new instance of the class. - - - Texture generator. - - - - - Process the filter on the specified image. - - - Source image data. - Overlay image data. - - - - - Format translations dictionary. - - - See for more information. - - - - - Generated texture. - - - Two dimensional array of texture intensities. - - In the case if image passed to the filter is smaller or - larger than the specified texture, than image's region is processed, which equals to the - minimum overlapping area. - - The property has priority over this property - if - generator is specified than the static generated texture is not used. - - - - - - Texture generator. - - - Generator used to generate texture. - - The property has priority over the property. - - - - - - Fill areas outiside of specified region. - - - - The filter fills areas outside of specified region using the specified color. - - The filter accepts 8bpp grayscale and 24/32 bpp color images for processing. - - Sample usage: - - // create filter - CanvasCrop filter = new CanvasCrop( new Rectangle( - 5, 5, image.Width - 10, image.Height - 10 ), Color.Red ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - Initializes a new instance of the class. - - - Region to keep. - - - - - Initializes a new instance of the class. - - - Region to keep. - RGB color to use for filling areas outside of specified region in color images. - - - - - Initializes a new instance of the class. - - - Region to keep. - Gray color to use for filling areas outside of specified region in grayscale images. - - - - - Initializes a new instance of the class. - - - Region to keep. - RGB color to use for filling areas outside of specified region in color images. - Gray color to use for filling areas outside of specified region in grayscale images. - - - - - Process the filter on the specified image. - - - Source image data. - - - - - Format translations dictionary. - - - See - documentation for additional information. - - - - - RGB fill color. - - - The color is used to fill areas out of specified region in color images. - - Default value is set to white - RGB(255, 255, 255). - - - - - Gray fill color. - - - The color is used to fill areas out of specified region in grayscale images. - - Default value is set to white - 255. - - - - - Region to keep. - - - Pixels inside of the specified region will keep their values, but - pixels outside of the region will be filled with specified color. - - - - - Erosion operator from Mathematical Morphology. - - - The filter assigns minimum value of surrounding pixels to each pixel of - the result image. Surrounding pixels, which should be processed, are specified by - structuring element: 1 - to process the neighbor, -1 - to skip it. - - The filter especially useful for binary image processing, where it removes pixels, which - are not surrounded by specified amount of neighbors. It gives ability to remove noisy pixels - (stand-alone pixels) or shrink objects. - - For processing image with 3x3 structuring element, there are different optimizations - available, like and . - - The filter accepts 8 and 16 bpp grayscale images and 24 and 48 bpp - color images for processing. - - Sample usage: - - // create filter - Erosion filter = new Erosion( ); - // apply the filter - filter.Apply( image ); - - - Initial image: - - Result image: - - - - - - - - - - - - - Initializes a new instance of the class. - - - Initializes new instance of the class using - default structuring element - 3x3 structuring element with all elements equal to 1. - - - - - - Initializes a new instance of the class. - - - Structuring element. - - Structuring elemement for the erosion morphological operator - must be square matrix with odd size in the range of [3, 99]. - - Invalid size of structuring element. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Bottop-hat operator from Mathematical Morphology. - - - Bottom-hat morphological operator subtracts - input image from the result of morphological closing on the - the input image. - - Applied to binary image, the filter allows to get all object parts, which were - added by closing filter, but were not removed after that due - to formed connections/fillings. - - The filter accepts 8 and 16 bpp grayscale images and 24 and 48 bpp - color images for processing. - - Sample usage: - - // create filter - BottomHat filter = new BottomHat( ); - // apply the filter - filter.Apply( image ); - - - Initial image: - - Result image: - - - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Structuring element to pass to operator. - - - - - Process the filter on the specified image. - - - Source image data. - - - - - Format translations dictionary. - - - - - Grayscale image using Y algorithm. - - - The class uses Y algorithm to convert color image - to grayscale. The conversion coefficients are: - - Red: 0.299; - Green: 0.587; - Blue: 0.114. - - - - - - - - - - - Initializes a new instance of the class. - - - - - Contrast stretching filter. - - - Contrast stretching (or as it is often called normalization) is a simple image enhancement - technique that attempts to improve the contrast in an image by 'stretching' the range of intensity values - it contains to span a desired range of values, e.g. the full range of pixel values that the image type - concerned allows. It differs from the more sophisticated histogram equalization - in that it can only apply a linear scaling function to the image pixel values. - - The result of this filter may be achieved by using class, which allows to - get pixels' intensities histogram, and filter, which does linear correction - of pixel's intensities. - - The filter accepts 8 bpp grayscale and 24 bpp color images. - - Sample usage: - - // create filter - ContrastStretch filter = new ContrastStretch( ); - // process image - filter.ApplyInPlace( sourceImage ); - - - Source image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Channels filters. - - - The filter does color channels' filtering by clearing (filling with - specified values) values, which are inside/outside of the specified value's - range. The filter allows to fill certain ranges of RGB color channels with specified - value. - - The filter is similar to , but operates with not - entire pixels, but with their RGB values individually. This means that pixel itself may - not be filtered (will be kept), but one of its RGB values may be filtered if they are - inside/outside of specified range. - - The filter accepts 24 and 32 bpp color images for processing. - - Sample usage: - - // create filter - ChannelFiltering filter = new ChannelFiltering( ); - // set channels' ranges to keep - filter.Red = new IntRange( 0, 255 ); - filter.Green = new IntRange( 100, 255 ); - filter.Blue = new IntRange( 100, 255 ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Red channel's filtering range. - Green channel's filtering range. - Blue channel's filtering range. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Calculate filtering map. - - - Filtering range. - Fillter value. - Fill outside or inside the range. - Filtering map. - - - - - Format translations dictionary. - - - - - Red channel's range. - - - - - Red fill value. - - - - - Green channel's range. - - - - - Green fill value. - - - - - Blue channel's range. - - - - - Blue fill value. - - - - - Determines, if red channel should be filled inside or outside filtering range. - - - Default value is set to . - - - - - Determines, if green channel should be filled inside or outside filtering range. - - - Default value is set to . - - - - - Determines, if blue channel should be filled inside or outside filtering range. - - - Default value is set to . - - - - - Generic Bayer fileter image processing routine. - - - The class implements Bayer filter - routine, which creates color image out of grayscale image produced by image sensor built with - Bayer color matrix. - - This Bayer filter implementation is made generic by allowing user to specify used - Bayer pattern. This makes it slower. For optimized version - of the Bayer filter see class, which implements Bayer filter - specifically optimized for some well known patterns. - - The filter accepts 8 bpp grayscale images and produces 24 bpp RGB image. - - Sample usage: - - // create filter - BayerFilter filter = new BayerFilter( ); - // apply the filter - Bitmap rgbImage = filter.Apply( image ); - - - Source image: - - Result image: - - - - - - - - - Initializes a new instance of the class. - - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - - - - - Specifies if demosaicing must be done or not. - - - The property specifies if color demosaicing must be done or not. - If the property is set to , then pixels of the result color image - are colored according to the Bayer pattern used, i.e. every pixel - of the source grayscale image is copied to corresponding color plane of the result image. - If the property is set to , then pixels of the result image - are set to color, which is obtained by averaging color components from the 3x3 window - pixel - itself plus 8 surrounding neighbors. - - Default value is set to . - - - - - - Specifies Bayer pattern used for decoding color image. - - - The property specifies 2x2 array of RGB color indexes, which set the - Bayer patter used for decoding color image. - - By default the property is set to: - - new int[2, 2] { { RGB.G, RGB.R }, { RGB.B, RGB.G } } - , - which corresponds to - - G R - B G - - pattern. - - - - - - - Format translations dictionary. - - - See - documentation for additional information. - - - - - Move towards filter. - - - The result of this filter is an image, which is based on source image, - but updated in the way to decrease diffirence with overlay image - source image is - moved towards overlay image. The update equation is defined in the next way: - res = src + Min( Abs( ovr - src ), step ) * Sign( ovr - src ). - - The bigger is step size value the more resulting - image will look like overlay image. For example, in the case if step size is equal - to 255 (or 65535 for images with 16 bits per channel), the resulting image will be - equal to overlay image regardless of source image's pixel values. In the case if step - size is set to 1, the resulting image will very little differ from the source image. - But, in the case if the filter is applied repeatedly to the resulting image again and - again, it will become equal to overlay image in maximum 255 (65535 for images with 16 - bits per channel) iterations. - - The filter accepts 8 and 16 bpp grayscale images and 24, 32, 48 and 64 bpp - color images for processing. - - Sample usage: - - // create filter - MoveTowards filter = new MoveTowards( overlayImage, 20 ); - // apply the filter - Bitmap resultImage = filter.Apply( sourceImage ); - - - Source image: - - Overlay image: - - Result image: - - - - - - - Initializes a new instance of the class - - - - - Initializes a new instance of the class. - - - Overlay image. - - - - - Initializes a new instance of the class. - - - Overlay image. - Step size. - - - - - Initializes a new instance of the class. - - - Unmanaged overlay image. - - - - - Initializes a new instance of the class. - - - Unmanaged overlay image. - Step size. - - - - - Process the filter on the specified image. - - - Source image data. - Overlay image data. - - - - - Format translations dictionary. - - - - - Step size, [0, 65535]. - - - - The property defines the maximum amount of changes per pixel in the source image. - - Default value is set to 1. - - - - - - Drawing primitives. - - - The class allows to do drawing of some primitives directly on - locked image data or unmanaged image. - - All methods of this class support drawing only on color 24/32 bpp images and - on grayscale 8 bpp indexed images. - - When it comes to alpha blending for 24/32 bpp images, all calculations are done - as described on Wikipeadia - (see "over" operator). - - - - - - Fill rectangle on the specified image. - - - Source image data to draw on. - Rectangle's coordinates to fill. - Rectangle's color. - - The source image has incorrect pixel format. - - - - - Fill rectangle on the specified image. - - - Source image to draw on. - Rectangle's coordinates to fill. - Rectangle's color. - - The source image has incorrect pixel format. - - - - - Draw rectangle on the specified image. - - - Source image data to draw on. - Rectangle's coordinates to draw. - Rectangle's color. - - The source image has incorrect pixel format. - - - - - Draw rectangle on the specified image. - - - Source image to draw on. - Rectangle's coordinates to draw. - Rectangle's color. - - The source image has incorrect pixel format. - - - - - Draw a line on the specified image. - - - Source image data to draw on. - The first point to connect. - The second point to connect. - Line's color. - - The source image has incorrect pixel format. - - - - - Draw a line on the specified image. - - - Source image to draw on. - The first point to connect. - The second point to connect. - Line's color. - - The source image has incorrect pixel format. - - - - - Draw a polygon on the specified image. - - - Source image data to draw on. - Points of the polygon to draw. - Polygon's color. - - The method draws a polygon by connecting all points from the - first one to the last one and then connecting the last point with the first one. - - - - - - Draw a polygon on the specified image. - - - Source image to draw on. - Points of the polygon to draw. - Polygon's color. - - The method draws a polygon by connecting all points from the - first one to the last one and then connecting the last point with the first one. - - - - - - Draw a polyline on the specified image. - - - Source image data to draw on. - Points of the polyline to draw. - polyline's color. - - The method draws a polyline by connecting all points from the - first one to the last one. Unlike - method, this method does not connect the last point with the first one. - - - - - - Draw a polyline on the specified image. - - - Source image to draw on. - Points of the polyline to draw. - polyline's color. - - The method draws a polyline by connecting all points from the - first one to the last one. Unlike - method, this method does not connect the last point with the first one. - - - - - - Color quantization tools. - - - The class contains methods aimed to simplify work with color quantization - algorithms implementing interface. Using its methods it is possible - to calculate reduced color palette for the specified image or reduce colors to the specified number. - - Sample usage: - - // instantiate the images' color quantization class - ColorImageQuantizer ciq = new ColorImageQuantizer( new MedianCutQuantizer( ) ); - // get 16 color palette for a given image - Color[] colorTable = ciq.CalculatePalette( image, 16 ); - - // ... or just reduce colors in the specified image - Bitmap newImage = ciq.ReduceColors( image, 16 ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - Color quantization algorithm to use for processing images. - - - - - Calculate reduced color palette for the specified image. - - - Image to calculate palette for. - Palette size to calculate. - - Return reduced color palette for the specified image. - - See for details. - - - - - Calculate reduced color palette for the specified image. - - - Image to calculate palette for. - Palette size to calculate. - - Return reduced color palette for the specified image. - - The method processes the specified image and feeds color value of each pixel - to the specified color quantization algorithm. Finally it returns color palette built by - that algorithm. - - Unsupported format of the source image - it must 24 or 32 bpp color image. - - - - - Create an image with reduced number of colors. - - - Source image to process. - Number of colors to get in the output image, [2, 256]. - - Returns image with reduced number of colors. - - See for details. - - - - - Create an image with reduced number of colors. - - - Source image to process. - Number of colors to get in the output image, [2, 256]. - - Returns image with reduced number of colors. - - The method creates an image, which looks similar to the specified image, but contains - reduced number of colors. First, target color palette is calculated using - method and then a new image is created, where pixels from the given source image are substituted by - best matching colors from calculated color table. - - The output image has 4 bpp or 8 bpp indexed pixel format depending on the target palette size - - 4 bpp for palette size 16 or less; 8 bpp otherwise. - - - Unsupported format of the source image - it must 24 or 32 bpp color image. - Invalid size of the target color palette. - - - - - Create an image with reduced number of colors using the specified palette. - - - Source image to process. - Target color palette. Must contatin 2-256 colors. - - Returns image with reduced number of colors. - - See for details. - - - - - Create an image with reduced number of colors using the specified palette. - - - Source image to process. - Target color palette. Must contatin 2-256 colors. - - Returns image with reduced number of colors. - - The method creates an image, which looks similar to the specified image, but contains - reduced number of colors. Is substitutes every pixel of the source image with the closest matching color - in the specified paletter. - - The output image has 4 bpp or 8 bpp indexed pixel format depending on the target palette size - - 4 bpp for palette size 16 or less; 8 bpp otherwise. - - - Unsupported format of the source image - it must 24 or 32 bpp color image. - Invalid size of the target color palette. - - - - - Color quantization algorithm used by this class to build color palettes for the specified images. - - - - - - Use color caching during color reduction or not. - - - The property has effect only for methods like and - specifies if internal cache of already processed colors should be used or not. For each pixel in the original - image the color reduction routine does search in target color palette to find the best matching color. - To avoid doing the search again and again for already processed colors, the class may use internal dictionary - which maps colors of original image to indexes in target color palette. - - - The property provides a trade off. On one hand it may speedup color reduction routine, but on another - hand it increases memory usage. Also cache usage may not be efficient for very small target color tables. - - Default value is set to . - - - - - - Pixellate filter. - - - The filter processes an image creating the effect of an image with larger - pixels - pixellated image. The effect is achieved by filling image's rectangles of the - specified size by the color, which is mean color value for the corresponding rectangle. - The size of rectangles to process is set by and - properties. - - The filter accepts 8 bpp grayscale images and 24 bpp - color images for processing. - - Sample usage: - - // create filter - Pixellate filter = new Pixellate( ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Pixel size. - - - - - Initializes a new instance of the class. - - - Pixel width. - Pixel height. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Pixel width, [2, 32]. - - - Default value is set to 8. - - - - - - - - Pixel height, [2, 32]. - - - Default value is set to 8. - - - - - - - - Pixel size, [2, 32]. - - - The property is used to set both and - simultaneously. - - - - - Apply mask to the specified image. - - - The filter applies mask to the specified image - keeps all pixels - in the image if corresponding pixels/values of the mask are not equal to 0. For all - 0 pixels/values in mask, corresponding pixels in the source image are set to 0. - - Mask can be specified as .NET's managed Bitmap, as - UnmanagedImage or as byte array. - In the case if mask is specified as image, it must be 8 bpp grayscale image. In all case - mask size must be the same as size of the image to process. - - The filter accepts 8/16 bpp grayscale and 24/32/48/64 bpp color images for processing. - - - - - - Initializes a new instance of the class. - - - Mask image to use. - - - - - Initializes a new instance of the class. - - - Unmanaged mask image to use. - - - - - Initializes a new instance of the class. - - - to use. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - None of the possible mask properties were set. Need to provide mask before applying the filter. - Invalid size of provided mask. Its size must be the same as the size of the image to mask. - - - - - Mask image to apply. - - - The property specifies mask image to use. The image must be grayscale - (8 bpp format) and have the same size as the source image to process. - - When the property is set, both and - properties are set to . - - - The mask image must be 8 bpp grayscale image. - - - - - Unmanaged mask image to apply. - - - The property specifies unmanaged mask image to use. The image must be grayscale - (8 bpp format) and have the same size as the source image to process. - - When the property is set, both and - properties are set to . - - - The mask image must be 8 bpp grayscale image. - - - - - Mask to apply. - - - The property specifies mask array to use. Size of the array must - be the same size as the size of the source image to process - its 0th dimension - must be equal to image's height and its 1st dimension must be equal to width. For - example, for 640x480 image, the mask array must be defined as: - - byte[,] mask = new byte[480, 640]; - - - - - - - Format translations dictionary. - - - See - documentation for additional information. - - - - - Canny edge detector. - - - The filter searches for objects' edges by applying Canny edge detector. - The implementation follows - Bill Green's Canny edge detection tutorial. - - The implemented canny edge detector has one difference with the above linked algorithm. - The difference is in hysteresis step, which is a bit simplified (getting faster as a result). On the - hysteresis step each pixel is compared with two threshold values: and - . If pixel's value is greater or equal to , then - it is kept as edge pixel. If pixel's value is greater or equal to , then - it is kept as edge pixel only if there is at least one neighbouring pixel (8 neighbours are checked) which - has value greater or equal to ; otherwise it is none edge pixel. In the case - if pixel's value is less than , then it is marked as none edge immediately. - - - The filter accepts 8 bpp grayscale images for processing. - - Sample usage: - - // create filter - CannyEdgeDetector filter = new CannyEdgeDetector( ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Low threshold. - High threshold. - - - - - Initializes a new instance of the class. - - - Low threshold. - High threshold. - Gaussian sigma. - - - - - Process the filter on the specified image. - - - Source image data. - Destination image data. - Image rectangle for processing by the filter. - - - - - Format translations dictionary. - - - - - Low threshold. - - - Low threshold value used for hysteresis - (see tutorial - for more information). - - Default value is set to 20. - - - - - - High threshold. - - - High threshold value used for hysteresis - (see tutorial - for more information). - - Default value is set to 100. - - - - - - Gaussian sigma. - - - Sigma value for Gaussian bluring. - - - - - Gaussian size. - - - Size of Gaussian kernel. - - - - - Linear correction of RGB channels for images, which have 16 bpp planes (16 bit gray images or 48/64 bit colour images). - - - The filter performs linear correction of RGB channels by mapping specified - channels' input ranges to output ranges. This version of the filter processes only images - with 16 bpp colour planes. See for 8 bpp version. - - The filter accepts 16 bpp grayscale and 48/64 bpp colour images for processing. - - Sample usage: - - // create filter - LevelsLinear16bpp filter = new LevelsLinear16bpp( ); - // set ranges - filter.InRed = new IntRange( 3000, 42000 ); - filter.InGreen = new IntRange( 5000, 37500 ); - filter.InBlue = new IntRange( 1000, 60000 ); - // apply the filter - filter.ApplyInPlace( image ); - - - - - - - - - Initializes a new instance of the class. - - - - - Process the filter on the specified image. - - - Source image data. - Image rectangle for processing by the filter. - - - - - Calculate conversion map. - - - Input range. - Output range. - Conversion map. - - - - - Format translations dictionary. - - - - - Red component's input range. - - - - - Green component's input range. - - - - - Blue component's input range. - - - - - Gray component's input range. - - - - - Input range for RGB components. - - - The property allows to set red, green and blue input ranges to the same value. - - - - - Red component's output range. - - - - - Green component's output range. - - - - - Blue component's output range. - - - - - Gray component's output range. - - - - - Output range for RGB components. - - - The property allows to set red, green and blue output ranges to the same value. - - - - - Dithering using Sierra error diffusion. - - - The filter represents binarization filter, which is based on - error diffusion dithering with Sierra coefficients. Error is diffused - on 10 neighbor pixels with next coefficients: - - | * | 5 | 3 | - | 2 | 4 | 5 | 4 | 2 | - | 2 | 3 | 2 | - - / 32 - - - The filter accepts 8 bpp grayscale images for processing. - - Sample usage: - - // create filter - SierraDithering filter = new SierraDithering( ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - - - - Initializes a new instance of the class. - - - - - - Dithering using Burkes error diffusion. - - - The filter represents binarization filter, which is based on - error diffusion dithering with Burkes coefficients. Error is diffused - on 7 neighbor pixels with next coefficients: - - | * | 8 | 4 | - | 2 | 4 | 8 | 4 | 2 | - - / 32 - - - The filter accepts 8 bpp grayscale images for processing. - - Sample usage: - - // create filter - BurkesDithering filter = new BurkesDithering( ); - // apply the filter - filter.ApplyInPlace( image ); - - - Initial image: - - Result image: - - - - - - - - - - - - Initializes a new instance of the class. - - - - - - Calculate difference between two images and threshold it. - - - The filter produces similar result as applying filter and - then filter - thresholded difference between two images. Result of this - image processing routine may be useful in motion detection applications or finding areas of significant - difference. - - The filter accepts 8 and 24/32color images for processing. - In the case of color images, the image processing routine differences sum over 3 RGB channels (Manhattan distance), i.e. - |diffR| + |diffG| + |diffB|. - - - Sample usage: - - // create filter - ThresholdedDifference filter = new ThresholdedDifference( 60 ); - // apply the filter - filter.OverlayImage = backgroundImage; - Bitmap resultImage = filter.Apply( sourceImage ); - - - Source image: - - Background image: - - Result image: - - - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Difference threshold (see ). - - - - - Process the filter on the specified image. - - - Source image data. - Overlay image data. - Destination image data - - - - - Difference threshold. - - - The property specifies difference threshold. If difference between pixels of processing image - and overlay image is greater than this value, then corresponding pixel of result image is set to white; otherwise - black. - - - Default value is set to 15. - - - - - Number of pixels which were set to white in destination image during last image processing call. - - - The property may be useful to determine amount of difference between two images which, - for example, may be treated as amount of motion in motion detection applications, etc. - - - - - Format translations dictionary. - - - See for more information. - - - - - Subtract filter - subtract pixel values of two images. - - - The subtract filter takes two images (source and overlay images) - of the same size and pixel format and produces an image, where each pixel equals - to the difference value of corresponding pixels from provided images (if difference is less - than minimum allowed value, 0, then it is truncated to that minimum value). - - The filter accepts 8 and 16 bpp grayscale images and 24, 32, 48 and 64 bpp - color images for processing. - - Sample usage: - - // create filter - Subtract filter = new Subtract( overlayImage ); - // apply the filter - Bitmap resultImage = filter.Apply( sourceImage ); - - - Source image: - - Overlay image: - - Result image: - - - - - - - - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Overlay image - - - - - Initializes a new instance of the class. - - - Unmanaged overlay image. - - - - - Process the filter on the specified image. - - - Source image data. - Overlay image data. - - - - - Format translations dictionary. - - - - - Stereo anaglyph filter. - - - The image processing filter produces stereo anaglyph images which are - aimed to be viewed through anaglyph glasses with red filter over the left eye and - cyan over the right. - - - - The stereo image is produced by combining two images of the same scene taken - from a bit different points. The right image must be provided to the filter using - property, but the left image must be provided to - method, which creates the anaglyph image. - - The filter accepts 24 bpp color images for processing. - - See enumeration for the list of supported anaglyph algorithms. - - Sample usage: - - // create filter - StereoAnaglyph filter = new StereoAnaglyph( ); - // set right image as overlay - filter.Overlay = rightImage - // apply the filter (providing left image) - Bitmap resultImage = filter.Apply( leftImage ); - - - Source image (left): - - Overlay image (right): - - Result image: - - - - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Algorithm to use for creating anaglyph images. - - - - - Process the filter on the specified image. - - - Source image data (left image). - Overlay image data (right image). - - - - - Algorithm to use for creating anaglyph images. - - - Default value is set to . - - - - - Format translations dictionary. - - - - - Enumeration of algorithms for creating anaglyph images. - - - See anaglyph methods comparison for - descipton of different algorithms. - - - - - - Creates anaglyph image using the below calculations: - - Ra=0.299*Rl+0.587*Gl+0.114*Bl; - Ga=0; - Ba=0.299*Rr+0.587*Gr+0.114*Br. - - - - - - Creates anaglyph image using the below calculations: - - Ra=0.299*Rl+0.587*Gl+0.114*Bl; - Ga=0.299*Rr+0.587*Gr+0.114*Br; - Ba=0.299*Rr+0.587*Gr+0.114*Br. - - - - - - Creates anaglyph image using the below calculations: - - Ra=Rl; - Ga=Gr; - Ba=Br. - - - - - - Creates anaglyph image using the below calculations: - - Ra=0.299*Rl+0.587*Gl+0.114*Bl; - Ga=Gr; - Ba=Br. - - - - - - Creates anaglyph image using the below calculations: - - Ra=0.7*Gl+0.3*Bl; - Ga=Gr; - Ba=Br. - - - -
-
diff --git a/Externals/AForge.NET/AForge.MachineLearning.dll b/Externals/AForge.NET/AForge.MachineLearning.dll deleted file mode 100644 index 17e2b0c89..0000000000 Binary files a/Externals/AForge.NET/AForge.MachineLearning.dll and /dev/null differ diff --git a/Externals/AForge.NET/AForge.MachineLearning.xml b/Externals/AForge.NET/AForge.MachineLearning.xml deleted file mode 100644 index c13b5ccac..0000000000 --- a/Externals/AForge.NET/AForge.MachineLearning.xml +++ /dev/null @@ -1,472 +0,0 @@ - - - - AForge.MachineLearning - - - - - Sarsa learning algorithm. - - - The class provides implementation of Sarse algorithm, known as - on-policy Temporal Difference control. - - - - - - - Initializes a new instance of the class. - - - Amount of possible states. - Amount of possible actions. - Exploration policy. - - Action estimates are randomized in the case of this constructor - is used. - - - - - Initializes a new instance of the class. - - - Amount of possible states. - Amount of possible actions. - Exploration policy. - Randomize action estimates or not. - - The randomize parameter specifies if initial action estimates should be randomized - with small values or not. Randomization of action values may be useful, when greedy exploration - policies are used. In this case randomization ensures that actions of the same type are not chosen always. - - - - - Get next action from the specified state. - - - Current state to get an action for. - - Returns the action for the state. - - The method returns an action according to current - exploration policy. - - - - - Update Q-function's value for the previous state-action pair. - - - Curren state. - Action, which lead from previous to the next state. - Reward value, received by taking specified action from previous state. - Next state. - Next action. - - Updates Q-function's value for the previous state-action pair in - the case if the next state is non terminal. - - - - - Update Q-function's value for the previous state-action pair. - - - Curren state. - Action, which lead from previous to the next state. - Reward value, received by taking specified action from previous state. - - Updates Q-function's value for the previous state-action pair in - the case if the next state is terminal. - - - - - Amount of possible states. - - - - - - Amount of possible actions. - - - - - - Exploration policy. - - - Policy, which is used to select actions. - - - - - Learning rate, [0, 1]. - - - The value determines the amount of updates Q-function receives - during learning. The greater the value, the more updates the function receives. - The lower the value, the less updates it receives. - - - - - Discount factor, [0, 1]. - - - Discount factor for the expected summary reward. The value serves as - multiplier for the expected reward. So if the value is set to 1, - then the expected summary reward is not discounted. If the value is getting - smaller, then smaller amount of the expected reward is used for actions' - estimates update. - - - - - Roulette wheel exploration policy. - - - The class implements roulette whell exploration policy. Acording to the policy, - action a at state s is selected with the next probability: - - Q( s, a ) - p( s, a ) = ------------------ - SUM( Q( s, b ) ) - b - - where Q(s, a) is action's a estimation (usefulness) at state s. - - The exploration policy may be applied only in cases, when action estimates (usefulness) - are represented with positive value greater then 0. - - - - - - - - - - Exploration policy interface. - - - The interface describes exploration policies, which are used in Reinforcement - Learning to explore state space. - - - - - Choose an action. - - - Action estimates. - - Returns selected action. - - The method chooses an action depending on the provided estimates. The - estimates can be any sort of estimate, which values usefulness of the action - (expected summary reward, discounted reward, etc). - - - - - Initializes a new instance of the class. - - - - - - Choose an action. - - - Action estimates. - - Returns selected action. - - The method chooses an action depending on the provided estimates. The - estimates can be any sort of estimate, which values usefulness of the action - (expected summary reward, discounted reward, etc). - - - - - Epsilon greedy exploration policy. - - - The class implements epsilon greedy exploration policy. Acording to the policy, - the best action is chosen with probability 1-epsilon. Otherwise, - with probability epsilon, any other action, except the best one, is - chosen randomly. - - According to the policy, the epsilon value is known also as exploration rate. - - - - - - - - - - Initializes a new instance of the class. - - - Epsilon value (exploration rate). - - - - - Choose an action. - - - Action estimates. - - Returns selected action. - - The method chooses an action depending on the provided estimates. The - estimates can be any sort of estimate, which values usefulness of the action - (expected summary reward, discounted reward, etc). - - - - - Epsilon value (exploration rate), [0, 1]. - - - The value determines the amount of exploration driven by the policy. - If the value is high, then the policy drives more to exploration - choosing random - action, which excludes the best one. If the value is low, then the policy is more - greedy - choosing the beat so far action. - - - - - - Tabu search exploration policy. - - - The class implements simple tabu search exploration policy, - allowing to set certain actions as tabu for a specified amount of - iterations. The actual exploration and choosing from non-tabu actions - is done by base exploration policy. - - - - - - - - - Initializes a new instance of the class. - - - Total actions count. - Base exploration policy. - - - - - Choose an action. - - - Action estimates. - - Returns selected action. - - The method chooses an action depending on the provided estimates. The - estimates can be any sort of estimate, which values usefulness of the action - (expected summary reward, discounted reward, etc). The action is choosed from - non-tabu actions only. - - - - - Reset tabu list. - - - Clears tabu list making all actions allowed. - - - - - Set tabu action. - - - Action to set tabu for. - Tabu time in iterations. - - - - - Base exploration policy. - - - Base exploration policy is the policy, which is used - to choose from non-tabu actions. - - - - - Boltzmann distribution exploration policy. - - - The class implements exploration policy base on Boltzmann distribution. - Acording to the policy, action a at state s is selected with the next probability: - - exp( Q( s, a ) / t ) - p( s, a ) = ----------------------------- - SUM( exp( Q( s, b ) / t ) ) - b - - where Q(s, a) is action's a estimation (usefulness) at state s and - t is . - - - - - - - - - - Initializes a new instance of the class. - - - Termperature parameter of Boltzmann distribution. - - - - - Choose an action. - - - Action estimates. - - Returns selected action. - - The method chooses an action depending on the provided estimates. The - estimates can be any sort of estimate, which values usefulness of the action - (expected summary reward, discounted reward, etc). - - - - - Termperature parameter of Boltzmann distribution, >0. - - - The property sets the balance between exploration and greedy actions. - If temperature is low, then the policy tends to be more greedy. - - - - - QLearning learning algorithm. - - - The class provides implementation of Q-Learning algorithm, known as - off-policy Temporal Difference control. - - - - - - - Initializes a new instance of the class. - - - Amount of possible states. - Amount of possible actions. - Exploration policy. - - Action estimates are randomized in the case of this constructor - is used. - - - - - Initializes a new instance of the class. - - - Amount of possible states. - Amount of possible actions. - Exploration policy. - Randomize action estimates or not. - - The randomize parameter specifies if initial action estimates should be randomized - with small values or not. Randomization of action values may be useful, when greedy exploration - policies are used. In this case randomization ensures that actions of the same type are not chosen always. - - - - - Get next action from the specified state. - - - Current state to get an action for. - - Returns the action for the state. - - The method returns an action according to current - exploration policy. - - - - - Update Q-function's value for the previous state-action pair. - - - Previous state. - Action, which leads from previous to the next state. - Reward value, received by taking specified action from previous state. - Next state. - - - - - Amount of possible states. - - - - - - Amount of possible actions. - - - - - - Exploration policy. - - - Policy, which is used to select actions. - - - - - Learning rate, [0, 1]. - - - The value determines the amount of updates Q-function receives - during learning. The greater the value, the more updates the function receives. - The lower the value, the less updates it receives. - - - - - Discount factor, [0, 1]. - - - Discount factor for the expected summary reward. The value serves as - multiplier for the expected reward. So if the value is set to 1, - then the expected summary reward is not discounted. If the value is getting - smaller, then smaller amount of the expected reward is used for actions' - estimates update. - - - - diff --git a/Externals/AForge.NET/AForge.Math.dll b/Externals/AForge.NET/AForge.Math.dll deleted file mode 100644 index bdc5e5ba6..0000000000 Binary files a/Externals/AForge.NET/AForge.Math.dll and /dev/null differ diff --git a/Externals/AForge.NET/AForge.Math.xml b/Externals/AForge.NET/AForge.Math.xml deleted file mode 100644 index 2d86543e0..0000000000 --- a/Externals/AForge.NET/AForge.Math.xml +++ /dev/null @@ -1,5676 +0,0 @@ - - - - AForge.Math - - - - - Set of tool functions. - - - The class contains different utility functions. - - - - - Calculates power of 2. - - - Power to raise in. - - Returns specified power of 2 in the case if power is in the range of - [0, 30]. Otherwise returns 0. - - - - - Checks if the specified integer is power of 2. - - - Integer number to check. - - Returns true if the specified number is power of 2. - Otherwise returns false. - - - - - Get base of binary logarithm. - - - Source integer number. - - Power of the number (base of binary logarithm). - - - - - Interface for distance metric algorithms. - - - The interface defines a set of methods implemented - by distance metric algorithms. These algorithms typically take a set of points and return a - distance measure of the x and y coordinates. In this case, the points are represented by two vectors. - - Distance metric algorithms are used in many machine learning algorithms e.g K-nearest neighbor - and K-means clustering. - - For additional details about distance metrics, documentation of the - particular algorithms should be studied. - - - - - - Returns distance between two N-dimensional double vectors. - - - 1st point vector. - 2nd point vector. - - Returns distance measurement determined by the given algorithm. - - - - - Histogram for discrete random values. - - - The class wraps histogram for discrete stochastic function, which is represented - by integer array, where indexes of the array are treated as values of the stochastic function, - but array values are treated as "probabilities" (total amount of hits). - - - Sample usage: - - // create histogram - Histogram histogram = new Histogram( new int[10] { 0, 0, 1, 3, 6, 8, 11, 0, 0, 0 } ); - // get mean and standard deviation values - Console.WriteLine( "mean = " + histogram.Mean + ", std.dev = " + histogram.StdDev ); - - - - - - - Initializes a new instance of the class. - - - Values of the histogram. - - Indexes of the input array are treated as values of stochastic function, - but array values are treated as "probabilities" (total amount of hits). - - - - - - Get range around median containing specified percentage of values. - - - Values percentage around median. - - Returns the range which containes specifies percentage of values. - - The method calculates range of stochastic variable, which summary probability - comprises the specified percentage of histogram's hits. - - Sample usage: - - // create histogram - Histogram histogram = new Histogram( new int[10] { 0, 0, 1, 3, 6, 8, 11, 0, 0, 0 } ); - // get 50% range - IntRange range = histogram.GetRange( 0.5 ); - // show the range ([4, 6]) - Console.WriteLine( "50% range = [" + range.Min + ", " + range.Max + "]" ); - - - - - - - Update statistical value of the histogram. - - - The method recalculates statistical values of the histogram, like mean, - standard deviation, etc., in the case if histogram's values were changed directly. - The method should be called only in the case if histogram's values were retrieved - through property and updated after that. - - - - - - Values of the histogram. - - - Indexes of this array are treated as values of stochastic function, - but array values are treated as "probabilities" (total amount of hits). - - - - - - Mean value. - - - The property allows to retrieve mean value of the histogram. - - Sample usage: - - // create histogram - Histogram histogram = new Histogram( new int[10] { 0, 0, 1, 3, 6, 8, 11, 0, 0, 0 } ); - // get mean value (= 4.862) - Console.WriteLine( "mean = " + histogram.Mean.ToString( "F3" ) ); - - - - - - - Standard deviation. - - - The property allows to retrieve standard deviation value of the histogram. - - Sample usage: - - // create histogram - Histogram histogram = new Histogram( new int[10] { 0, 0, 1, 3, 6, 8, 11, 0, 0, 0 } ); - // get std.dev. value (= 1.136) - Console.WriteLine( "std.dev. = " + histogram.StdDev.ToString( "F3" ) ); - - - - - - - Median value. - - - The property allows to retrieve median value of the histogram. - - Sample usage: - - // create histogram - Histogram histogram = new Histogram( new int[10] { 0, 0, 1, 3, 6, 8, 11, 0, 0, 0 } ); - // get median value (= 5) - Console.WriteLine( "median = " + histogram.Median ); - - - - - - - Minimum value. - - - The property allows to retrieve minimum value of the histogram with non zero - hits count. - - Sample usage: - - // create histogram - Histogram histogram = new Histogram( new int[10] { 0, 0, 1, 3, 6, 8, 11, 0, 0, 0 } ); - // get min value (= 2) - Console.WriteLine( "min = " + histogram.Min ); - - - - - - - Maximum value. - - - The property allows to retrieve maximum value of the histogram with non zero - hits count. - - Sample usage: - - // create histogram - Histogram histogram = new Histogram( new int[10] { 0, 0, 1, 3, 6, 8, 11, 0, 0, 0 } ); - // get max value (= 6) - Console.WriteLine( "max = " + histogram.Max ); - - - - - - - Total count of values. - - - The property represents total count of values contributed to the histogram, which is - essentially sum of the array. - - Sample usage: - - // create histogram - Histogram histogram = new Histogram( new int[10] { 0, 0, 1, 3, 6, 8, 11, 0, 0, 0 } ); - // get total value (= 29) - Console.WriteLine( "total = " + histogram.TotalCount ); - - - - - - - Set of statistics functions. - - - The class represents collection of simple functions used - in statistics. - - - - - Calculate mean value. - - - Histogram array. - - Returns mean value. - - The input array is treated as histogram, i.e. its - indexes are treated as values of stochastic function, but - array values are treated as "probabilities" (total amount of - hits). - - Sample usage: - - // create histogram array - int[] histogram = new int[] { 1, 1, 2, 3, 6, 8, 11, 12, 7, 3 }; - // calculate mean value - double mean = Statistics.Mean( histogram ); - // output it (5.759) - Console.WriteLine( "mean = " + mean.ToString( "F3" ) ); - - - - - - - Calculate standard deviation. - - - Histogram array. - - Returns value of standard deviation. - - The input array is treated as histogram, i.e. its - indexes are treated as values of stochastic function, but - array values are treated as "probabilities" (total amount of - hits). - - Sample usage: - - // create histogram array - int[] histogram = new int[] { 1, 1, 2, 3, 6, 8, 11, 12, 7, 3 }; - // calculate standard deviation value - double stdDev = Statistics.StdDev( histogram ); - // output it (1.999) - Console.WriteLine( "std.dev. = " + stdDev.ToString( "F3" ) ); - - - - - - - Calculate standard deviation. - - - Histogram array. - Mean value of the histogram. - - Returns value of standard deviation. - - The input array is treated as histogram, i.e. its - indexes are treated as values of stochastic function, but - array values are treated as "probabilities" (total amount of - hits). - - The method is an equevalent to the method, - but it relieas on the passed mean value, which is previously calculated - using method. - - - - - - Calculate median value. - - - Histogram array. - - Returns value of median. - - - The input array is treated as histogram, i.e. its - indexes are treated as values of stochastic function, but - array values are treated as "probabilities" (total amount of - hits). - - The median value is calculated accumulating histogram's - values starting from the left point until the sum reaches 50% of - histogram's sum. - - Sample usage: - - // create histogram array - int[] histogram = new int[] { 1, 1, 2, 3, 6, 8, 11, 12, 7, 3 }; - // calculate median value - int median = Statistics.Median( histogram ); - // output it (6) - Console.WriteLine( "median = " + median ); - - - - - - - Get range around median containing specified percentage of values. - - - Histogram array. - Values percentage around median. - - Returns the range which containes specifies percentage - of values. - - - The input array is treated as histogram, i.e. its - indexes are treated as values of stochastic function, but - array values are treated as "probabilities" (total amount of - hits). - - The method calculates range of stochastic variable, which summary probability - comprises the specified percentage of histogram's hits. - - Sample usage: - - // create histogram array - int[] histogram = new int[] { 1, 1, 2, 3, 6, 8, 11, 12, 7, 3 }; - // get 75% range around median - IntRange range = Statistics.GetRange( histogram, 0.75 ); - // output it ([4, 8]) - Console.WriteLine( "range = [" + range.Min + ", " + range.Max + "]" ); - - - - - - - Calculate entropy value. - - - Histogram array. - - Returns entropy value of the specified histagram array. - - The input array is treated as histogram, i.e. its - indexes are treated as values of stochastic function, but - array values are treated as "probabilities" (total amount of - hits). - - Sample usage: - - // create histogram array with 2 values of equal probabilities - int[] histogram1 = new int[2] { 3, 3 }; - // calculate entropy - double entropy1 = Statistics.Entropy( histogram1 ); - // output it (1.000) - Console.WriteLine( "entropy1 = " + entropy1.ToString( "F3" ) ); - - // create histogram array with 4 values of equal probabilities - int[] histogram2 = new int[4] { 1, 1, 1, 1 }; - // calculate entropy - double entropy2 = Statistics.Entropy( histogram2 ); - // output it (2.000) - Console.WriteLine( "entropy2 = " + entropy2.ToString( "F3" ) ); - - // create histogram array with 4 values of different probabilities - int[] histogram3 = new int[4] { 1, 2, 3, 4 }; - // calculate entropy - double entropy3 = Statistics.Entropy( histogram3 ); - // output it (1.846) - Console.WriteLine( "entropy3 = " + entropy3.ToString( "F3" ) ); - - - - - - - Calculate mode value. - - - Histogram array. - - Returns mode value of the histogram array. - - - The input array is treated as histogram, i.e. its - indexes are treated as values of stochastic function, but - array values are treated as "probabilities" (total amount of - hits). - - Returns the minimum mode value if the specified histogram is multimodal. - - Sample usage: - - // create array - int[] values = new int[] { 1, 1, 2, 3, 6, 8, 11, 12, 7, 3 }; - // calculate mode value - int mode = Statistics.Mode( values ); - // output it (7) - Console.WriteLine( "mode = " + mode ); - - - - - - - Gaussian random numbers generator. - - - The random number generator generates gaussian - random numbers with specified mean and standard deviation values. - - The generator uses generator as base - to generate random numbers. - - Sample usage: - - // create instance of random generator - IRandomNumberGenerator generator = new GaussianGenerator( 5.0, 1.5 ); - // generate random number - float randomNumber = generator.Next( ); - - - - - - - Interface for random numbers generators. - - - The interface defines set of methods and properties, which should - be implemented by different algorithms for random numbers generatation. - - - - - - Generate next random number. - - - Returns next random number. - - - - - Set seed of the random numbers generator. - - - Seed value. - - - - - Mean value of generator. - - - - - - Variance value of generator. - - - - - - Initializes a new instance of the class. - - - Mean value. - Standard deviation value. - - - - - Initializes a new instance of the class. - - - Mean value. - Standard deviation value. - Seed value to initialize random numbers generator. - - - - - Generate next random number. - - - Returns next random number. - - - - - Set seed of the random numbers generator. - - - Seed value. - - Resets random numbers generator initializing it with - specified seed value. - - - - - Mean value of the generator. - - - - - - Variance value of the generator. - - - - - - Standard deviation value. - - - - - - The class encapsulates 2D line segment and provides some tool methods related to lines. - - - The class provides some methods which are related to line segments: - distance to point, finding intersection point, etc. - - - A line segment may be converted to a . - - Sample usage: - - // create a segment - LineSegment segment = new LineSegment( new Point( 0, 0 ), new Point( 3, 4 ) ); - // get segment's length - float length = segment.Length; - - // get intersection point with a line - Point? intersection = segment.GetIntersectionWith( - new Line( new Point( -3, 8 ), new Point( 0, 4 ) ) ); - - - - - - - Initializes a new instance of the class. - - - Segment's start point. - Segment's end point. - - Thrown if the two points are the same. - - - - - Converts this to a by discarding - its endpoints and extending it infinitely in both directions. - - - The segment to convert to a . - - Returns a that contains this . - - - - - Calculate Euclidean distance between a point and a finite line segment. - - - The point to calculate the distance to. - - Returns the Euclidean distance between this line segment and the specified point. Unlike - , this returns the distance from the finite segment. (0,0) is 5 units - from the segment (0,5)-(0,8), but is 0 units from the line through those points. - - - - - Finds, provided it exists, the intersection point with the specified . - - - to find intersection with. - - Returns intersection point with the specified , or , if - the two segments do not intersect. - - If the two segments do not intersect, the method returns . If the two - segments share multiple points, this throws an . - - - Thrown if the segments overlap - if they have - multiple points in common. - - - - - Finds, provided it exists, the intersection point with the specified . - - - to find intersection with. - - Returns intersection point with the specified , or , if - the line does not intersect with this segment. - - If the line and the segment do not intersect, the method returns . If the line - and the segment share multiple points, the method throws an . - - - Thrown if this segment is a portion of - line. - - - - - Equality operator - checks if two line segments have equal parameters. - - - First line segment to check. - Second line segment to check. - - Returns if parameters of specified - line segments are equal. - - - - - Inequality operator - checks if two lines have different parameters. - - - First line segment to check. - Second line segment to check. - - Returns if parameters of specified - line segments are not equal. - - - - - Check if this instance of equals to the specified one. - - - Another line segment to check equalty to. - - Return if objects are equal. - - - - - Get hash code for this instance. - - - Returns the hash code for this instance. - - - - - Get string representation of the class. - - - Returns string, which contains values of the like in readable form. - - - - - Start point of the line segment. - - - - - End point of the line segment. - - - - - Get segment's length - Euclidean distance between its and points. - - - - - Gaussian function. - - - The class is used to calculate 1D and 2D Gaussian functions for - specified (s) value: - - - 1-D: f(x) = exp( x * x / ( -2 * s * s ) ) / ( s * sqrt( 2 * PI ) ) - - 2-D: f(x, y) = exp( x * x + y * y / ( -2 * s * s ) ) / ( s * s * 2 * PI ) - - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Sigma value. - - - - - 1-D Gaussian function. - - - x value. - - Returns function's value at point . - - The function calculates 1-D Gaussian function: - - - f(x) = exp( x * x / ( -2 * s * s ) ) / ( s * sqrt( 2 * PI ) ) - - - - - - - 2-D Gaussian function. - - - x value. - y value. - - Returns function's value at point (, ). - - The function calculates 2-D Gaussian function: - - - f(x, y) = exp( x * x + y * y / ( -2 * s * s ) ) / ( s * s * 2 * PI ) - - - - - - - 1-D Gaussian kernel. - - - Kernel size (should be odd), [3, 101]. - - Returns 1-D Gaussian kernel of the specified size. - - The function calculates 1-D Gaussian kernel, which is array - of Gaussian function's values in the [-r, r] range of x value, where - r=floor(/2). - - - Wrong kernel size. - - - - - 2-D Gaussian kernel. - - - Kernel size (should be odd), [3, 101]. - - Returns 2-D Gaussian kernel of specified size. - - The function calculates 2-D Gaussian kernel, which is array - of Gaussian function's values in the [-r, r] range of x,y values, where - r=floor(/2). - - - Wrong kernel size. - - - - - Sigma value. - - - Sigma property of Gaussian function. - - Default value is set to 1. Minimum allowed value is 0.00000001. - - - - - - Fourier transformation. - - - The class implements one dimensional and two dimensional - Discrete and Fast Fourier Transformation. - - - - - One dimensional Discrete Fourier Transform. - - - Data to transform. - Transformation direction. - - - - - Two dimensional Discrete Fourier Transform. - - - Data to transform. - Transformation direction. - - - - - One dimensional Fast Fourier Transform. - - - Data to transform. - Transformation direction. - - The method accepts array of 2n size - only, where n may vary in the [1, 14] range. - - Incorrect data length. - - - - - Two dimensional Fast Fourier Transform. - - - Data to transform. - Transformation direction. - - The method accepts array of 2n size - only in each dimension, where n may vary in the [1, 14] range. For example, 16x16 array - is valid, but 15x15 is not. - - Incorrect data length. - - - - - Fourier transformation direction. - - - - - Forward direction of Fourier transformation. - - - - - Backward direction of Fourier transformation. - - - - - The class encapsulates 2D line and provides some tool methods related to lines. - - - The class provides some methods which are related to lines: - angle between lines, distance to point, finding intersection point, etc. - - - Generally, the equation of the line is y = * x + - . However, when is an Infinity, - would normally be meaningless, and it would be - impossible to distinguish the line x = 5 from the line x = -5. Therefore, - if is or - , the line's equation is instead - x = . - - Sample usage: - - // create a line - Line line = Line.FromPoints( new Point( 0, 0 ), new Point( 3, 4 ) ); - // check if it is vertical or horizontal - if ( line.IsVertical || line.IsHorizontal ) - { - // ... - } - - // get intersection point with another line - Point intersection = line.GetIntersectionWith( - Line.FromPoints( new Point( 3, 0 ), new Point( 0, 4 ) ) ); - - - - - - - Creates a that goes through the two specified points. - - - One point on the line. - Another point on the line. - - Returns a representing the line between - and . - - Thrown if the two points are the same. - - - - - Creates a with the specified slope and intercept. - - - The slope of the line - The Y-intercept of the line, unless the slope is an - infinity, in which case the line's equation is "x = intercept" instead. - - Returns a representing the specified line. - - The construction here follows the same rules as for the rest of this class. - Most lines are expressed as y = slope * x + intercept. Vertical lines, however, are - x = intercept. This is indicated by being true or by - returning or - . - - - - - Constructs a from a radius and an angle (in degrees). - - - The minimum distance from the line to the origin. - The angle of the vector from the origin to the line. - - Returns a representing the specified line. - - is the minimum distance from the origin - to the line, and is the counterclockwise rotation from - the positive X axis to the vector through the origin and normal to the line. - This means that if is in [0,180), the point on the line - closest to the origin is on the positive X or Y axes, or in quadrants I or II. Likewise, - if is in [180,360), the point on the line closest to the - origin is on the negative X or Y axes, or in quadrants III or IV. - - Thrown if radius is negative. - - - - - Constructs a from a point and an angle (in degrees). - - - The minimum distance from the line to the origin. - The angle of the normal vector from the origin to the line. - - is the counterclockwise rotation from - the positive X axis to the vector through the origin and normal to the line. - This means that if is in [0,180), the point on the line - closest to the origin is on the positive X or Y axes, or in quadrants I or II. Likewise, - if is in [180,360), the point on the line closest to the - origin is on the negative X or Y axes, or in quadrants III or IV. - - Returns a representing the specified line. - - - - - Calculate minimum angle between this line and the specified line measured in [0, 90] degrees range. - - - The line to find angle between. - - Returns minimum angle between lines. - - - - - Finds intersection point with the specified line. - - - Line to find intersection with. - - Returns intersection point with the specified line, or - if the lines are parallel and distinct. - - Thrown if the specified line is the same line as this line. - - - - - Finds, provided it exists, the intersection point with the specified . - - - to find intersection with. - - Returns intersection point with the specified , or , - if this line does not intersect with the segment. - - If the line and segment do not intersect, the method returns . - If the line and segment share multiple points, the method throws an . - - - Thrown if is a portion - of this line. - - - - - Calculate Euclidean distance between a point and a line. - - - The point to calculate distance to. - - Returns the Euclidean distance between this line and the specified point. Unlike - , this returns the distance from the infinite line. (0,0) is 0 units - from the line defined by (0,5) and (0,8), but is 5 units from the segment with those endpoints. - - - - - Equality operator - checks if two lines have equal parameters. - - - First line to check. - Second line to check. - - Returns if parameters of specified - lines are equal. - - - - - Inequality operator - checks if two lines have different parameters. - - - First line to check. - Second line to check. - - Returns if parameters of specified - lines are not equal. - - - - - Check if this instance of equals to the specified one. - - - Another line to check equalty to. - - Return if objects are equal. - - - - - Get hash code for this instance. - - - Returns the hash code for this instance. - - - - - Get string representation of the class. - - - Returns string, which contains values of the like in readable form. - - - - - Checks if the line vertical or not. - - - - - - Checks if the line horizontal or not. - - - - - Gets the slope of the line. - - - - - If not , gets the Line's Y-intercept. - If gets the line's X-intercept. - - - - - Jaccard distance metric. - - - This class represents the - Jaccard distance metric. - - Sample usage: - - // instantiate new distance class - JaccardDistance dist = new JaccardDistance( ); - // create two vectors for inputs - double[] p = new double[] { 2.5, 3.5, 3.0, 3.5, 2.5, 3.0 }; - double[] q = new double[] { 3.0, 3.5, 1.5, 5.0, 3.5, 3.0 }; - // get distance between the two vectors - double distance = dist.GetDistance( p, q ); - - - - - - - Returns distance between two N-dimensional double vectors. - - - 1st point vector. - 2nd point vector. - - Returns Jaccard distance between two supplied vectors. - - Thrown if the two vectors are of different dimensions (if specified - array have different length). - - - - - Collection of some gemetry tool methods. - - - - - - Calculate angle between to vectors measured in [0, 180] degrees range. - - - Starting point of both vectors. - Ending point of the first vector. - Ending point of the second vector. - - Returns angle between specified vectors measured in degrees. - - - - - Calculate minimum angle between two lines measured in [0, 90] degrees range. - - - A point on the first line. - Another point on the first line. - A point on the second line. - Another point on the second line. - - Returns minimum angle between two lines. - - It is preferred to use if it is required to calculate angle - multiple times for one of the lines. - - and are the same, - -OR- and are the same. - - - - - Shape optimizer, which merges points within close distance to each other. - - - This shape optimizing algorithm checks all points of a shape - and merges any two points which are within specified distance - to each other. Two close points are replaced by a single point, which has - mean coordinates of the removed points. - - Because of the fact that the algorithm performs points merging - while it goes through a shape, it may merge several points (more than 2) into a - single point, where distance between extreme points may be bigger - than the specified limit. For example, suppose - a case with 3 points, where 1st and 2nd points are close enough to be merged, but the - 3rd point is a little bit further. During merging of 1st and 2nd points, it may - happen that the new point with mean coordinates will get closer to the 3rd point, - so they will be merged also on next iteration of the algorithm. - - - For example, the below circle shape comprised of 65 points, can be optimized to 8 points - by setting to 28.
- -
-
- -
- - - Interface for shape optimizing algorithms. - - - The interface defines set of methods, which should be implemented - by shape optimizing algorithms. These algorithms take input shape, which is defined - by a set of points (corners of convex hull, etc.), and remove some insignificant points from it, - which has little influence on the final shape's look. - - The shape optimizing algorithms can be useful in conjunction with such algorithms - like convex hull searching, which usually may provide many hull points, where some - of them are insignificant and could be removed. - - For additional details about shape optimizing algorithms, documentation of - particular algorithm should be studied. - - - - - - Optimize specified shape. - - - Shape to be optimized. - - Returns final optimized shape, which may have reduced amount of points. - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Maximum allowed distance between points, which are - merged during optimization (see ). - - - - - Optimize specified shape. - - - Shape to be optimized. - - Returns final optimized shape, which may have reduced amount of points. - - - - - Maximum allowed distance between points, which are merged during optimization, [0, ∞). - - - The property sets maximum allowed distance between two points of - a shape, which are replaced by single point with mean coordinates. - - Default value is set to 10. - - - - - Standard random numbers generator. - - - The random number generator generates gaussian - random numbers with zero mean and standard deviation of one. The generator - implements polar form of the Box-Muller transformation. - - The generator uses generator as a base - to generate random numbers. - - Sample usage: - - // create instance of random generator - IRandomNumberGenerator generator = new StandardGenerator( ); - // generate random number - float randomNumber = generator.Next( ); - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Seed value to initialize random numbers generator. - - - - - Generate next random number. - - - Returns next random number. - - - - - Set seed of the random numbers generator. - - - Seed value. - - Resets random numbers generator initializing it with - specified seed value. - - - - - Mean value of the generator. - - - - - - Variance value of the generator. - - - - - - 3D pose estimation algorithm (coplanar case). - - - The class implements an algorithm for 3D object's pose estimation from it's - 2D coordinates obtained by perspective projection, when the object is described coplanar points. - The idea of the implemented math and algorithm is described in "Iterative Pose Estimation using - Coplanar Feature Points" paper written by Oberkampf, Daniel DeMenthon and Larry Davis - (the implementation of the algorithm is very close translation of the pseudo code given by the - paper, so should be easy to follow). - - At this point the implementation works only with models described by 4 points, which is - the minimum number of points enough for 3D pose estimation. - - The 4 model's point are supposed to be coplanar, i.e. supposed to reside all within - same planer. See for none coplanar case. - - Read 3D Pose Estimation article for - additional information and samples. - - Sample usage: - - // points of real object - model - Vector3[] copositObject = new Vector3[4] - { - new Vector3( -56.5f, 0, 56.5f ), - new Vector3( 56.5f, 0, 56.5f ), - new Vector3( 56.5f, 0, -56.5f ), - new Vector3( -56.5f, 0, -56.5f ), - }; - // focal length of camera used to capture the object - float focalLength = 640; // depends on your camera or projection system - // initialize CoPOSIT object - CoplanarPosit coposit = new CoplanarPosit( copositObject, focalLength ); - - // 2D points of te object - projection - AForge.Point[] projectedPoints = new AForge.Point[4] - { - new AForge.Point( -77, 48 ), - new AForge.Point( 44, 66 ), - new AForge.Point( 75, -36 ), - new AForge.Point( -61, -58 ), - }; - // estimate pose - Matrix3x3 rotationMatrix; - Vector3 translationVector; - coposit.EstimatePose( projectedPoints, - out rotationMatrix, out translationVector ); - - - - - - - - - Initializes a new instance of the class. - - - Array of vectors containing coordinates of four real model's point. - Effective focal length of the camera used to capture the model. - - The model must have 4 points. - - - - - Estimate pose of a model from it's projected 2D coordinates. - - - 4 2D points of the model's projection. - Gets best estimation of object's rotation. - Gets best estimation of object's translation. - - 4 points must be be given for pose estimation. - - Because of the Coplanar POSIT algorithm's nature, it provides two pose estimations, - which are valid from the algorithm's math point of view. For each pose an error is calculated, - which specifies how good estimation fits to the specified real 2D coordinated. The method - provides the best estimation through its output parameters and - . This may be enough for many of the pose estimation application. - For those, who require checking the alternate pose estimation, it can be obtained using - and properties. - The calculated error is provided for both estimations through and - properties. - - - - - - Best estimated pose recently found. - - - The property keeps best estimated pose found by the latest call to . - The same estimated pose is provided by that method also and can be accessed through this property - for convenience. - - See also and . - - - - - - Best estimated translation recently found. - - - The property keeps best estimated translation found by the latest call to . - The same estimated translation is provided by that method also and can be accessed through this property - for convenience. - - See also and . - - - - - - Error of the best pose estimation. - - - The property keeps error of the best pose estimation, which is calculated as average - error between real angles of the specified quadrilateral and angles of the quadrilateral which - is a projection of the best pose estimation. The error is measured degrees in (angle). - - - - - - Alternate estimated pose recently found. - - - The property keeps alternate estimated pose found by the latest call to . - - See also and . - - - - - - Alternated estimated translation recently found. - - - The property keeps alternate estimated translation found by the latest call to . - - See also and . - - - - - - Error of the alternate pose estimation. - - - The property keeps error of the alternate pose estimation, which is calculated as average - error between real angles of the specified quadrilateral and angles of the quadrilateral which - is a projection of the alternate pose estimation. The error is measured in degrees (angle). - - - - - - Coordinates of the model points which pose should be estimated. - - - - - Effective focal length of the camera used to capture the model. - - - - - Pearson correlation metric. - - - This class represents the - Pearson correlation metric. - - Sample usage: - - // instantiate new pearson correlation class - PearsonCorrelation cor = new PearsonCorrelation( ); - // create two vectors for inputs - double[] p = new double[] { 2.5, 3.5, 3.0, 3.5, 2.5, 3.0 }; - double[] q = new double[] { 3.0, 3.5, 1.5, 5.0, 3.5, 3.0 }; - // get correlation between the two vectors - double correlation = cor.GetSimilarityScore( p, q ); - - - - - - - Interface for similarity algorithms. - - - The interface defines a set of methods implemented - by similarity and correlation algorithms. These algorithms typically take a set of points and return a - similarity score for the two vectors. - - Similarity and correlation algorithms are used in many machine learning and collaborative - filtering algorithms. - - For additional details about similarity metrics, documentation of the - particular algorithms should be studied. - - - - - - Returns similarity score for two N-dimensional double vectors. - - - 1st point vector. - 2nd point vector. - - Returns similarity score determined by the given algorithm. - - - - - Returns the pearson correlation for two N-dimensional double vectors. - - - 1st point vector. - 2nd point vector. - - Returns Pearson correlation between two supplied vectors. - - Thrown if the two vectors are of different dimensions (if specified - array have different length). - - - - - A class for checking simple geometrical shapes. - - - The class performs checking/detection of some simple geometrical - shapes for provided set of points (shape's edge points). During the check - the class goes through the list of all provided points and checks how accurately - they fit into assumed shape. - - All the shape checks allow some deviation of - points from the shape with assumed parameters. In other words it is allowed - that specified set of points may form a little bit distorted shape, which may be - still recognized. The allowed amount of distortion is controlled by two - properties ( and ), - which allow higher distortion level for bigger shapes and smaller amount of - distortion for smaller shapes. Checking specified set of points, the class - calculates mean distance between specified set of points and edge of the assumed - shape. If the mean distance is equal to or less than maximum allowed distance, - then a shape is recognized. The maximum allowed distance is calculated as: - - maxDistance = max( minAcceptableDistortion, relativeDistortionLimit * ( width + height ) / 2 ) - - , where width and height is the size of bounding rectangle for the - specified points. - - - See also and properties, - which set acceptable errors for polygon sub type checking done by - method. - - See the next article for details about the implemented algorithms: - Detecting some simple shapes in images. - - - Sample usage: - - private List<IntPoint> idealCicle = new List<IntPoint>( ); - private List<IntPoint> distorredCircle = new List<IntPoint>( ); - System.Random rand = new System.Random( ); - - // generate sample circles - float radius = 100; - - for ( int i = 0; i < 360; i += 10 ) - { - float angle = (float) ( (float) i / 180 * System.Math.PI ); - - // add point to ideal circle - idealCicle.Add( new IntPoint( - (int) ( radius * System.Math.Cos( angle ) ), - (int) ( radius * System.Math.Sin( angle ) ) ) ); - - // add a bit distortion for distorred cirlce - float distorredRadius = radius + rand.Next( 7 ) - 3; - - distorredCircle.Add( new IntPoint( - (int) ( distorredRadius * System.Math.Cos( angle ) ), - (int) ( distorredRadius * System.Math.Sin( angle ) ) ) ); - } - - // check shape - SimpleShapeChecker shapeChecker = new SimpleShapeChecker( ); - - if ( shapeChecker.IsCircle( idealCicle ) ) - { - // ... - } - - if ( shapeChecker.CheckShapeType( distorredCircle ) == ShapeType.Circle ) - { - // ... - } - - - - - - - Check type of the shape formed by specified points. - - - Shape's points to check. - - Returns type of the detected shape. - - - - - Check if the specified set of points form a circle shape. - - - Shape's points to check. - - Returns if the specified set of points form a - circle shape or otherwise. - - Circle shape must contain at least 8 points to be recognized. - The method returns always, of number of points in the specified - shape is less than 8. - - - - - Check if the specified set of points form a circle shape. - - - Shape's points to check. - Receives circle's center on successful return. - Receives circle's radius on successful return. - - Returns if the specified set of points form a - circle shape or otherwise. - - Circle shape must contain at least 8 points to be recognized. - The method returns always, of number of points in the specified - shape is less than 8. - - - - - Check if the specified set of points form a quadrilateral shape. - - - Shape's points to check. - - Returns if the specified set of points form a - quadrilateral shape or otherwise. - - - - - Check if the specified set of points form a quadrilateral shape. - - - Shape's points to check. - List of quadrilateral corners on successful return. - - Returns if the specified set of points form a - quadrilateral shape or otherwise. - - - - - Check if the specified set of points form a triangle shape. - - - Shape's points to check. - - Returns if the specified set of points form a - triangle shape or otherwise. - - - - - Check if the specified set of points form a triangle shape. - - - Shape's points to check. - List of triangle corners on successful return. - - Returns if the specified set of points form a - triangle shape or otherwise. - - - - - Check if the specified set of points form a convex polygon shape. - - - Shape's points to check. - List of polygon corners on successful return. - - Returns if the specified set of points form a - convex polygon shape or otherwise. - - The method is able to detect only triangles and quadrilaterals - for now. Check number of detected corners to resolve type of the detected polygon. - - - - - - Check sub type of a convex polygon. - - - Corners of the convex polygon to check. - - Return detected sub type of the specified shape. - - The method check corners of a convex polygon detecting - its subtype. Polygon's corners are usually retrieved using - method, but can be any list of 3-4 points (only sub types of triangles and - quadrilateral are checked). - - See and properties, - which set acceptable errors for polygon sub type checking. - - - - - - Check if a shape specified by the set of points fits a convex polygon - specified by the set of corners. - - - Shape's points to check. - Corners of convex polygon to check fitting into. - - Returns if the specified shape fits - the specified convex polygon or otherwise. - - The method checks if the set of specified points form the same shape - as the set of provided corners. - - - - - Minimum value of allowed shapes' distortion. - - - The property sets minimum value for allowed shapes' - distortion (in pixels). See documentation to - class for more details about this property. - - Default value is set to 0.5. - - - - - - Maximum value of allowed shapes' distortion, [0, 1]. - - - The property sets maximum value for allowed shapes' - distortion. The value is measured in [0, 1] range, which corresponds - to [0%, 100%] range, which means that maximum allowed shapes' - distortion is calculated relatively to shape's size. This results to - higher allowed distortion level for bigger shapes and smaller allowed - distortion for smaller shapers. See documentation to - class for more details about this property. - - Default value is set to 0.03 (3%). - - - - - - Maximum allowed angle error in degrees, [0, 20]. - - - The value sets maximum allowed difference between two angles to - treat them as equal. It is used by method to - check for parallel lines and angles of triangles and quadrilaterals. - For example, if angle between two lines equals 5 degrees and this properties value - is set to 7, then two compared lines are treated as parallel. - - Default value is set to 7. - - - - - - Maximum allowed difference in sides' length (relative to shapes' size), [0, 1]. - - - The values sets maximum allowed difference between two sides' length - to treat them as equal. The error value is set relative to shapes size and measured - in [0, 1] range, which corresponds to [0%, 100%] range. Absolute length error in pixels - is calculated as: - - LengthError * ( width + height ) / 2 - - , where width and height is the size of bounding rectangle for the - specified shape. - - - Default value is set to 0.1 (10%). - - - - - - Graham scan algorithm for finding convex hull. - - - The class implements - Graham scan algorithm for finding convex hull - of a given set of points. - - Sample usage: - - // generate some random points - Random rand = new Random( ); - List<IntPoint> points = new List<IntPoint>( ); - - for ( int i = 0; i < 10; i++ ) - { - points.Add( new IntPoint( - rand.Next( 200 ) - 100, - rand.Next( 200 ) - 100 ) ); - } - - // find the convex hull - IConvexHullAlgorithm hullFinder = new GrahamConvexHull( ); - List<IntPoint> hull = hullFinder.FindHull( points ); - - - - - - - Interface defining methods for algorithms, which search for convex hull of the specified points' set. - - - The interface defines a method, which should be implemented by different classes - performing convex hull search for specified set of points. - - All algorithms, implementing this interface, should follow two rules for the found convex hull: - - the first point in the returned list is the point with lowest X coordinate (and with lowest Y if - there are several points with the same X value); - points in the returned list are given in counter clockwise order - (Cartesian - coordinate system). - - - - - - - - Find convex hull for the given set of points. - - - Set of points to search convex hull for. - - Returns set of points, which form a convex hull for the given . - - - - - Find convex hull for the given set of points. - - - Set of points to search convex hull for. - - Returns set of points, which form a convex hull for the given . - The first point in the list is the point with lowest X coordinate (and with lowest Y if there are - several points with the same X value). Points are provided in counter clockwise order - (Cartesian - coordinate system). - - - - - Euclidean distance metric. - - - This class represents the - Euclidean distance metric. - - Sample usage: - - // instantiate new distance class - EuclideanDistance dist = new EuclideanDistance( ); - // create two vectors for inputs - double[] p = new double[] { 2.5, 3.5, 3.0, 3.5, 2.5, 3.0 }; - double[] q = new double[] { 3.0, 3.5, 1.5, 5.0, 3.5, 3.0 }; - // get distance between the two vectors - double distance = dist.GetDistance( p, q ); - - - - - - - Returns distance between two N-dimensional double vectors. - - - 1st point vector. - 2nd point vector. - - Returns Euclidean distance between two supplied vectors. - - Thrown if the two vectors are of different dimensions (if specified - array have different length). - - - - - Shape optimizer, which removes points within close range to shapes' body. - - - This shape optimizing algorithm checks all points of the shape and - removes those of them, which are in a certain distance to a line connecting previous and - the next points. In other words, it goes through all adjacent edges of a shape and checks - what is the distance between the corner formed by these two edges and a possible edge, which - could be used as substitution of these edges. If the distance is equal or smaller than - the specified value, then the point is removed, - so the two edges are substituted by a single one. When optimization process is done, - the new shape has reduced amount of points and none of the removed points are further away - from the new shape than the specified limit. - - The shape optimizer does not optimize shapes to less than 3 points, so optimized - shape always will have at least 3 points. - - - For example, the below circle shape comprised of 65 points, can be optimized to 8 points - by setting to 10.
- -
-
- -
- - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Maximum allowed distance between removed points - and optimized shape (see ). - - - - - Optimize specified shape. - - - Shape to be optimized. - - Returns final optimized shape, which may have reduced amount of points. - - - - - Maximum allowed distance between removed points and optimized shape, [0, ∞). - - - The property sets maximum allowed distance between points removed from original - shape and optimized shape - none of the removed points are further away - from the new shape than the specified limit. - - - Default value is set to 5. - - - - - Shape optimizer, which removes obtuse angles (close to flat) from a shape. - - - This shape optimizing algorithm checks all adjacent edges of a shape - and substitutes any 2 edges with a single edge if angle between them is greater than - . The algorithm makes sure there are not obtuse angles in - a shape, which are very close to flat line. - - The shape optimizer does not optimize shapes to less than 3 points, so optimized - shape always will have at least 3 points. - - - For example, the below circle shape comprised of 65 points, can be optimized to 10 points - by setting to 160.
- -
-
- -
- - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Maximum acceptable angle between two edges of a shape (see ). - - - - - Optimize specified shape. - - - Shape to be optimized. - - Returns final optimized shape, which may have reduced amount of points. - - - - - Maximum angle between adjacent edges to keep in a shape, [140, 180]. - - - The property sets maximum angle between adjacent edges, which is kept - during optimization. All edges, which have a greater angle between them, are substituted - by a single edge. - - Default value is set to 160. - - - - - Uniform random numbers generator. - - - The random numbers generator generates uniformly - distributed numbers in the specified range - values - are greater or equal to minimum range's value and less than maximum range's - value. - - The generator uses generator - to generate random numbers. - - Sample usage: - - // create instance of random generator - IRandomNumberGenerator generator = new UniformGenerator( new Range( 50, 100 ) ); - // generate random number - float randomNumber = generator.Next( ); - - - - - - - Initializes a new instance of the class. - - - Random numbers range. - - Initializes random numbers generator with zero seed. - - - - - Initializes a new instance of the class. - - - Random numbers range. - Seed value to initialize random numbers generator. - - - - - Generate next random number. - - - Returns next random number. - - - - - Set seed of the random numbers generator. - - - Seed value. - - Resets random numbers generator initializing it with - specified seed value. - - - - - Mean value of the generator. - - - - - - Variance value of the generator. - - - - - - Random numbers range. - - - Range of random numbers to generate. Generated numbers are - greater or equal to minimum range's value and less than maximum range's - value. - - - - - - Manhattan distance metric. - - - This class represents the - Manhattan distance metric - (aka City Block and Taxi Cab distance). - - Sample usage: - - // instantiate new distance class - ManhattanDistance dist = new ManhattanDistance( ); - // create two vectors for inputs - double[] p = new double[] { 2.5, 3.5, 3.0, 3.5, 2.5, 3.0 }; - double[] q = new double[] { 3.0, 3.5, 1.5, 5.0, 3.5, 3.0 }; - // get distance between the two vectors - double distance = dist.GetDistance( p, q ); - - - - - - - Returns distance between two N-dimensional double vectors. - - - 1st point vector. - 2nd point vector. - - Returns Manhattan distance between two supplied vectors. - - Thrown if the two vectors are of different dimensions (if specified - array have different length). - - - - - 4D Vector structure with X, Y, Z and W coordinates. - - - The structure incapsulates X, Y, Z and W coordinates of a 4D vector and - provides some operations with it. - - - - - X coordinate of the vector. - - - - - Y coordinate of the vector. - - - - - Z coordinate of the vector. - - - - - W coordinate of the vector. - - - - - Initializes a new instance of the structure. - - - X coordinate of the vector. - Y coordinate of the vector. - Z coordinate of the vector. - W coordinate of the vector. - - - - - Initializes a new instance of the structure. - - - Value, which is set to all 4 coordinates of the vector. - - - - - Returns a string representation of this object. - - - A string representation of this object. - - - - - Returns array representation of the vector. - - - Array with 4 values containing X/Y/Z/W coordinates. - - - - - Adds corresponding coordinates of two vectors. - - - The vector to add to. - The vector to add to the first vector. - - Returns a vector which coordinates are equal to sum of corresponding - coordinates of the two specified vectors. - - - - - Adds corresponding coordinates of two vectors. - - - The vector to add to. - The vector to add to the first vector. - - Returns a vector which coordinates are equal to sum of corresponding - coordinates of the two specified vectors. - - - - - Adds a value to all coordinates of the specified vector. - - - Vector to add the specified value to. - Value to add to all coordinates of the vector. - - Returns new vector with all coordinates increased by the specified value. - - - - - Adds a value to all coordinates of the specified vector. - - - Vector to add the specified value to. - Value to add to all coordinates of the vector. - - Returns new vector with all coordinates increased by the specified value. - - - - - Subtracts corresponding coordinates of two vectors. - - - The vector to subtract from. - The vector to subtract from the first vector. - - Returns a vector which coordinates are equal to difference of corresponding - coordinates of the two specified vectors. - - - - - Subtracts corresponding coordinates of two vectors. - - - The vector to subtract from. - The vector to subtract from the first vector. - - Returns a vector which coordinates are equal to difference of corresponding - coordinates of the two specified vectors. - - - - - Subtracts a value from all coordinates of the specified vector. - - - Vector to subtract the specified value from. - Value to subtract from all coordinates of the vector. - - Returns new vector with all coordinates decreased by the specified value. - - - - - Subtracts a value from all coordinates of the specified vector. - - - Vector to subtract the specified value from. - Value to subtract from all coordinates of the vector. - - Returns new vector with all coordinates decreased by the specified value. - - - - - Multiplies corresponding coordinates of two vectors. - - - The first vector to multiply. - The second vector to multiply. - - Returns a vector which coordinates are equal to multiplication of corresponding - coordinates of the two specified vectors. - - - - - Multiplies corresponding coordinates of two vectors. - - - The first vector to multiply. - The second vector to multiply. - - Returns a vector which coordinates are equal to multiplication of corresponding - coordinates of the two specified vectors. - - - - - Multiplies coordinates of the specified vector by the specified factor. - - - Vector to multiply coordinates of. - Factor to multiple coordinates of the specified vector by. - - Returns new vector with all coordinates multiplied by the specified factor. - - - - - Multiplies coordinates of the specified vector by the specified factor. - - - Vector to multiply coordinates of. - Factor to multiple coordinates of the specified vector by. - - Returns new vector with all coordinates multiplied by the specified factor. - - - - - Divides corresponding coordinates of two vectors. - - - The first vector to divide. - The second vector to devide. - - Returns a vector which coordinates are equal to coordinates of the first vector divided by - corresponding coordinates of the second vector. - - - - - Divides corresponding coordinates of two vectors. - - - The first vector to divide. - The second vector to devide. - - Returns a vector which coordinates are equal to coordinates of the first vector divided by - corresponding coordinates of the second vector. - - - - - Divides coordinates of the specified vector by the specified factor. - - - Vector to divide coordinates of. - Factor to divide coordinates of the specified vector by. - - Returns new vector with all coordinates divided by the specified factor. - - - - - Divides coordinates of the specified vector by the specified factor. - - - Vector to divide coordinates of. - Factor to divide coordinates of the specified vector by. - - Returns new vector with all coordinates divided by the specified factor. - - - - - Tests whether two specified vectors are equal. - - - The left-hand vector. - The right-hand vector. - - Returns if the two vectors are equal or otherwise. - - - - - Tests whether two specified vectors are not equal. - - - The left-hand vector. - The right-hand vector. - - Returns if the two vectors are not equal or otherwise. - - - - - Tests whether the vector equals to the specified one. - - - The vector to test equality with. - - Returns if the two vectors are equal or otherwise. - - - - - Tests whether the vector equals to the specified object. - - - The object to test equality with. - - Returns if the vector equals to the specified object or otherwise. - - - - - Returns the hashcode for this instance. - - - A 32-bit signed integer hash code. - - - - - Normalizes the vector by dividing it’s all coordinates with the vector's norm. - - - Returns the value of vectors’ norm before normalization. - - - - - Inverse the vector. - - - Returns a vector with all coordinates equal to 1.0 divided by the value of corresponding coordinate - in this vector (or equal to 0.0 if this vector has corresponding coordinate also set to 0.0). - - - - - Calculate absolute values of the vector. - - - Returns a vector with all coordinates equal to absolute values of this vector's coordinates. - - - - - Calculates dot product of two vectors. - - - First vector to use for dot product calculation. - Second vector to use for dot product calculation. - - Returns dot product of the two specified vectors. - - - - - Converts the vector to a 3D vector. - - - Returns 3D vector which has X/Y/Z coordinates equal to X/Y/Z coordinates - of this vector divided by . - - - - - Returns maximum value of the vector. - - - Returns maximum value of all 4 vector's coordinates. - - - - - Returns minimum value of the vector. - - - Returns minimum value of all 4 vector's coordinates. - - - - - Returns index of the coordinate with maximum value. - - - Returns index of the coordinate, which has the maximum value - 0 for X, - 1 for Y, 2 for Z or 3 for W. - - If there are multiple coordinates which have the same maximum value, the - property returns smallest index. - - - - - - Returns index of the coordinate with minimum value. - - - Returns index of the coordinate, which has the minimum value - 0 for X, - 1 for Y, 2 for Z or 3 for W. - - If there are multiple coordinates which have the same minimum value, the - property returns smallest index. - - - - - - Returns vector's norm. - - - Returns Euclidean norm of the vector, which is a - square root of the sum: X2+Y2+Z2+W2. - - - - - - Returns square of the vector's norm. - - - Return X2+Y2+Z2+W2, which is - a square of vector's norm or a dot product of this vector - with itself. - - - - - Uniform random numbers generator in the range of [0, 1). - - - The random number generator generates uniformly - distributed numbers in the range of [0, 1) - greater or equal to 0.0 - and less than 1.0. - - At this point the generator is based on the - internal .NET generator, but may be rewritten to - use faster generation algorithm. - - Sample usage: - - // create instance of random generator - IRandomNumberGenerator generator = new UniformOneGenerator( ); - // generate random number - float randomNumber = generator.Next( ); - - - - - - - Initializes a new instance of the class. - - - Initializes random numbers generator with zero seed. - - - - - Initializes a new instance of the class. - - - Seed value to initialize random numbers generator. - - - - - Generate next random number. - - - Returns next random number. - - - - - Set seed of the random numbers generator. - - - Seed value. - - Resets random numbers generator initializing it with - specified seed value. - - - - - Mean value of the generator. - - - - - - Variance value of the generator. - - - - - - Exponential random numbers generator. - - - The random number generator generates exponential - random numbers with specified rate value (lambda). - - The generator uses generator as a base - to generate random numbers. - - Sample usage: - - // create instance of random generator - IRandomNumberGenerator generator = new ExponentialGenerator( 5 ); - // generate random number - float randomNumber = generator.Next( ); - - - - - - - Initializes a new instance of the class. - - - Rate value. - - Rate value should be greater than zero. - - - - - Initializes a new instance of the class. - - - Rate value (inverse mean). - Seed value to initialize random numbers generator. - - Rate value should be greater than zero. - - - - - Generate next random number - - - Returns next random number. - - - - - Set seed of the random numbers generator. - - - Seed value. - - Resets random numbers generator initializing it with - specified seed value. - - - - - Rate value (inverse mean). - - - The rate value should be positive and non zero. - - - - - Mean value of the generator. - - - - - - Variance value of the generator. - - - - - - A structure representing 4x4 matrix. - - - The structure incapsulates elements of a 4x4 matrix and - provides some operations with it. - - - - - Row 0 column 0 element of the matrix. - - - - - Row 0 column 1 element of the matrix. - - - - - Row 0 column 2 element of the matrix. - - - - - Row 0 column 3 element of the matrix. - - - - - Row 1 column 0 element of the matrix. - - - - - Row 1 column 1 element of the matrix. - - - - - Row 1 column 2 element of the matrix. - - - - - Row 1 column 3 element of the matrix. - - - - - Row 2 column 0 element of the matrix. - - - - - Row 2 column 1 element of the matrix. - - - - - Row 2 column 2 element of the matrix. - - - - - Row 2 column 3 element of the matrix. - - - - - Row 3 column 0 element of the matrix. - - - - - Row 3 column 1 element of the matrix. - - - - - Row 3 column 2 element of the matrix. - - - - - Row 3 column 3 element of the matrix. - - - - - Returns array representation of the matrix. - - - Returns array which contains all elements of the matrix in the row-major order. - - - - - Creates rotation matrix around Y axis. - - - Rotation angle around Y axis in radians. - - Returns rotation matrix to rotate an object around Y axis. - - - - - Creates rotation matrix around X axis. - - - Rotation angle around X axis in radians. - - Returns rotation matrix to rotate an object around X axis. - - - - - Creates rotation matrix around Z axis. - - - Rotation angle around Z axis in radians. - - Returns rotation matrix to rotate an object around Z axis. - - - - - Creates rotation matrix to rotate an object around X, Y and Z axes. - - - Rotation angle around Y axis in radians. - Rotation angle around X axis in radians. - Rotation angle around Z axis in radians. - - Returns rotation matrix to rotate an object around all 3 axes. - - - The routine assumes roll-pitch-yaw rotation order, when creating rotation - matrix, i.e. an object is first rotated around Z axis, then around X axis and finally around - Y axis. - - - - - - Extract rotation angles from the rotation matrix. - - - Extracted rotation angle around Y axis in radians. - Extracted rotation angle around X axis in radians. - Extracted rotation angle around Z axis in radians. - - The routine assumes roll-pitch-yaw rotation order when extracting rotation angle. - Using extracted angles with the should provide same rotation matrix. - - - The method assumes the provided matrix represent valid rotation matrix. - - Sample usage: - - // assume we have a rotation matrix created like this - float yaw = 10.0f / 180 * Math.PI; - float pitch = 30.0f / 180 * Math.PI; - float roll = 45.0f / 180 * Math.PI; - - Matrix4x4 rotationMatrix = Matrix3x3.CreateFromYawPitchRoll( yaw, pitch, roll ); - // ... - - // now somewhere in the code you may want to get rotation - // angles back from a matrix assuming same rotation order - float extractedYaw; - float extractedPitch; - float extractedRoll; - - rotation.ExtractYawPitchRoll( out extractedYaw, out extractedPitch, out extractedRoll ); - - - - - - - Creates 4x4 tranformation matrix from 3x3 rotation matrix. - - - Source 3x3 rotation matrix. - - Returns 4x4 rotation matrix. - - The source 3x3 rotation matrix is copied into the top left corner of the result 4x4 matrix, - i.e. it represents 0th, 1st and 2nd row/column. The element is set to 1 and the rest - elements of 3rd row and 3rd column are set to zeros. - - - - - Creates translation matrix for the specified movement amount. - - - Vector which set direction and amount of movement. - - Returns translation matrix. - - The specified vector is copied to the 3rd column of the result matrix. - All diagonal elements are set to 1. The rest of matrix is initialized with zeros. - - - - - Creates a view matrix for the specified camera position and target point. - - - Position of camera. - Target point towards which camera is pointing. - - Returns a view matrix. - - Camera's "up" vector is supposed to be (0, 1, 0). - - - - - Creates a perspective projection matrix. - - - Width of the view volume at the near view plane. - Height of the view volume at the near view plane. - Distance to the near view plane. - Distance to the far view plane. - - Return a perspective projection matrix. - - Both near and far view planes' distances must be greater than zero. - Near plane must be closer than the far plane. - - - - - Creates a matrix from 4 rows specified as vectors. - - - First row of the matrix to create. - Second row of the matrix to create. - Third row of the matrix to create. - Fourth row of the matrix to create. - - Returns a matrix from specified rows. - - - - - Creates a matrix from 4 columns specified as vectors. - - - First column of the matrix to create. - Second column of the matrix to create. - Third column of the matrix to create. - Fourth column of the matrix to create. - - Returns a matrix from specified columns. - - - - - Creates a diagonal matrix using the specified vector as diagonal elements. - - - Vector to use for diagonal elements of the matrix. - - Returns a diagonal matrix. - - - - - Get row of the matrix. - - - Row index to get, [0, 3]. - - Returns specified row of the matrix as a vector. - - Invalid row index was specified. - - - - - Get column of the matrix. - - - Column index to get, [0, 3]. - - Returns specified column of the matrix as a vector. - - Invalid column index was specified. - - - - - Multiplies two specified matrices. - - - Matrix to multiply. - Matrix to multiply by. - - Return new matrix, which the result of multiplication of the two specified matrices. - - - - - Multiplies two specified matrices. - - - Matrix to multiply. - Matrix to multiply by. - - Return new matrix, which the result of multiplication of the two specified matrices. - - - - - Adds corresponding components of two matrices. - - - The matrix to add to. - The matrix to add to the first matrix. - - Returns a matrix which components are equal to sum of corresponding - components of the two specified matrices. - - - - - Adds corresponding components of two matrices. - - - The matrix to add to. - The matrix to add to the first matrix. - - Returns a matrix which components are equal to sum of corresponding - components of the two specified matrices. - - - - - Subtracts corresponding components of two matrices. - - - The matrix to subtract from. - The matrix to subtract from the first matrix. - - Returns a matrix which components are equal to difference of corresponding - components of the two specified matrices. - - - - - Subtracts corresponding components of two matrices. - - - The matrix to subtract from. - The matrix to subtract from the first matrix. - - Returns a matrix which components are equal to difference of corresponding - components of the two specified matrices. - - - - - Multiplies specified matrix by the specified vector. - - - Matrix to multiply by vector. - Vector to multiply matrix by. - - Returns new vector which is the result of multiplication of the specified matrix - by the specified vector. - - - - - Multiplies specified matrix by the specified vector. - - - Matrix to multiply by vector. - Vector to multiply matrix by. - - Returns new vector which is the result of multiplication of the specified matrix - by the specified vector. - - - - - Tests whether two specified matrices are equal. - - - The left-hand matrix. - The right-hand matrix. - - Returns if the two matrices are equal or otherwise. - - - - - Tests whether two specified matrices are not equal. - - - The left-hand matrix. - The right-hand matrix. - - Returns if the two matrices are not equal or otherwise. - - - - - Tests whether the matrix equals to the specified one. - - - The matrix to test equality with. - - Returns if the two matrices are equal or otherwise. - - - - - Tests whether the matrix equals to the specified object. - - - The object to test equality with. - - Returns if the matrix equals to the specified object or otherwise. - - - - - Returns the hashcode for this instance. - - - A 32-bit signed integer hash code. - - - - - Provides an identity matrix with all diagonal elements set to 1. - - - - - Enumeration of some basic shape types. - - - - - Unknown shape type. - - - - - Circle shape. - - - - - Triangle shape. - - - - - Quadrilateral shape. - - - - - Some common sub types of some basic shapes. - - - - - Unrecognized sub type of a shape (generic shape which does not have - any specific sub type). - - - - - Quadrilateral with one pair of parallel sides. - - - - - Quadrilateral with two pairs of parallel sides. - - - - - Parallelogram with perpendicular adjacent sides. - - - - - Parallelogram with all sides equal. - - - - - Rectangle with all sides equal. - - - - - Triangle with all sides/angles equal. - - - - - Triangle with two sides/angles equal. - - - - - Triangle with a 90 degrees angle. - - - - - Triangle with a 90 degrees angle and other two angles are equal. - - - - - Set of tools for processing collection of points in 2D space. - - - The static class contains set of routines, which provide different - operations with collection of points in 2D space. For example, finding the - furthest point from a specified point or line. - - Sample usage: - - // create points' list - List<IntPoint> points = new List<IntPoint>( ); - points.Add( new IntPoint( 10, 10 ) ); - points.Add( new IntPoint( 20, 15 ) ); - points.Add( new IntPoint( 15, 30 ) ); - points.Add( new IntPoint( 40, 12 ) ); - points.Add( new IntPoint( 30, 20 ) ); - // get furthest point from the specified point - IntPoint p1 = PointsCloud.GetFurthestPoint( points, new IntPoint( 15, 15 ) ); - Console.WriteLine( p1.X + ", " + p1.Y ); - // get furthest point from line - IntPoint p2 = PointsCloud.GetFurthestPointFromLine( points, - new IntPoint( 50, 0 ), new IntPoint( 0, 50 ) ); - Console.WriteLine( p2.X + ", " + p2.Y ); - - - - - - - Shift cloud by adding specified value to all points in the collection. - - - Collection of points to shift their coordinates. - Point to shift by. - - - - - Get bounding rectangle of the specified list of points. - - - Collection of points to get bounding rectangle for. - Point comprised of smallest X and Y coordinates. - Point comprised of biggest X and Y coordinates. - - - - - Get center of gravity for the specified list of points. - - - List of points to calculate center of gravity for. - - Returns center of gravity (mean X-Y values) for the specified list of points. - - - - - Find furthest point from the specified point. - - - Collection of points to search furthest point in. - The point to search furthest point from. - - Returns a point, which is the furthest away from the . - - - - - Find two furthest points from the specified line. - - - Collection of points to search furthest points in. - First point forming the line. - Second point forming the line. - First found furthest point. - Second found furthest point (which is on the - opposite side from the line compared to the ); - - The method finds two furthest points from the specified line, - where one point is on one side from the line and the second point is on - another side from the line. - - - - - Find two furthest points from the specified line. - - - Collection of points to search furthest points in. - First point forming the line. - Second point forming the line. - First found furthest point. - Distance between the first found point and the given line. - Second found furthest point (which is on the - opposite side from the line compared to the ); - Distance between the second found point and the given line. - - The method finds two furthest points from the specified line, - where one point is on one side from the line and the second point is on - another side from the line. - - - - - Find the furthest point from the specified line. - - - Collection of points to search furthest point in. - First point forming the line. - Second point forming the line. - - Returns a point, which is the furthest away from the - specified line. - - The method finds the furthest point from the specified line. - Unlike the - method, this method find only one point, which is the furthest away from the line - regardless of side from the line. - - - - - Find the furthest point from the specified line. - - - Collection of points to search furthest points in. - First point forming the line. - Second point forming the line. - Distance between the furthest found point and the given line. - - Returns a point, which is the furthest away from the - specified line. - - The method finds the furthest point from the specified line. - Unlike the - method, this method find only one point, which is the furthest away from the line - regardless of side from the line. - - - - - Find corners of quadrilateral or triangular area, which contains the specified collection of points. - - - Collection of points to search quadrilateral for. - - Returns a list of 3 or 4 points, which are corners of the quadrilateral or - triangular area filled by specified collection of point. The first point in the list - is the point with lowest X coordinate (and with lowest Y if there are several points - with the same X value). The corners are provided in counter clockwise order - (Cartesian - coordinate system). - - The method makes an assumption that the specified collection of points - form some sort of quadrilateral/triangular area. With this assumption it tries to find corners - of the area. - - The method does not search for bounding quadrilateral/triangular area, - where all specified points are inside of the found quadrilateral/triangle. Some of the - specified points potentially may be outside of the found quadrilateral/triangle, since the - method takes corners only from the specified collection of points, but does not calculate such - to form true bounding quadrilateral/triangle. - - See property for additional information. - - - - - - Relative distortion limit allowed for quadrilaterals, [0.0, 0.25]. - - - The value of this property is used to calculate distortion limit used by - , when processing potential corners and making decision - if the provided points form a quadrilateral or a triangle. The distortion limit is - calculated as: - - distrtionLimit = RelativeDistortionLimit * ( W * H ) / 2, - - where W and H are width and height of the "points cloud" passed to the - . - - - To explain the idea behind distortion limit, let’s suppose that quadrilateral finder routine found - the next candidates for corners:
-
- As we can see on the above picture, the shape there potentially can be a triangle, but not quadrilateral - (suppose that points list comes from a hand drawn picture or acquired from camera, so some - inaccuracy may exist). It may happen that the D point is just a distortion (noise, etc). - So the check what is the distance between a potential corner - (D in this case) and a line connecting two adjacent points (AB in this case). If the distance is smaller - then the distortion limit, then the point may be rejected, so the shape turns into triangle. -
- - An exception is the case when both C and D points are very close to the AB line, - so both their distances are less than distortion limit. In this case both points will be accepted as corners - - the shape is just a flat quadrilateral. - - Default value is set to 0.1. -
- -
- - - 3D Vector structure with X, Y and Z coordinates. - - - The structure incapsulates X, Y and Z coordinates of a 3D vector and - provides some operations with it. - - - - - X coordinate of the vector. - - - - - Y coordinate of the vector. - - - - - Z coordinate of the vector. - - - - - Initializes a new instance of the structure. - - - X coordinate of the vector. - Y coordinate of the vector. - Z coordinate of the vector. - - - - - Initializes a new instance of the structure. - - - Value, which is set to all 3 coordinates of the vector. - - - - - Returns a string representation of this object. - - - A string representation of this object. - - - - - Returns array representation of the vector. - - - Array with 3 values containing X/Y/Z coordinates. - - - - - Adds corresponding coordinates of two vectors. - - - The vector to add to. - The vector to add to the first vector. - - Returns a vector which coordinates are equal to sum of corresponding - coordinates of the two specified vectors. - - - - - Adds corresponding coordinates of two vectors. - - - The vector to add to. - The vector to add to the first vector. - - Returns a vector which coordinates are equal to sum of corresponding - coordinates of the two specified vectors. - - - - - Adds a value to all coordinates of the specified vector. - - - Vector to add the specified value to. - Value to add to all coordinates of the vector. - - Returns new vector with all coordinates increased by the specified value. - - - - - Adds a value to all coordinates of the specified vector. - - - Vector to add the specified value to. - Value to add to all coordinates of the vector. - - Returns new vector with all coordinates increased by the specified value. - - - - - Subtracts corresponding coordinates of two vectors. - - - The vector to subtract from. - The vector to subtract from the first vector. - - Returns a vector which coordinates are equal to difference of corresponding - coordinates of the two specified vectors. - - - - - Subtracts corresponding coordinates of two vectors. - - - The vector to subtract from. - The vector to subtract from the first vector. - - Returns a vector which coordinates are equal to difference of corresponding - coordinates of the two specified vectors. - - - - - Subtracts a value from all coordinates of the specified vector. - - - Vector to subtract the specified value from. - Value to subtract from all coordinates of the vector. - - Returns new vector with all coordinates decreased by the specified value. - - - - - Subtracts a value from all coordinates of the specified vector. - - - Vector to subtract the specified value from. - Value to subtract from all coordinates of the vector. - - Returns new vector with all coordinates decreased by the specified value. - - - - - Multiplies corresponding coordinates of two vectors. - - - The first vector to multiply. - The second vector to multiply. - - Returns a vector which coordinates are equal to multiplication of corresponding - coordinates of the two specified vectors. - - - - - Multiplies corresponding coordinates of two vectors. - - - The first vector to multiply. - The second vector to multiply. - - Returns a vector which coordinates are equal to multiplication of corresponding - coordinates of the two specified vectors. - - - - - Multiplies coordinates of the specified vector by the specified factor. - - - Vector to multiply coordinates of. - Factor to multiple coordinates of the specified vector by. - - Returns new vector with all coordinates multiplied by the specified factor. - - - - - Multiplies coordinates of the specified vector by the specified factor. - - - Vector to multiply coordinates of. - Factor to multiple coordinates of the specified vector by. - - Returns new vector with all coordinates multiplied by the specified factor. - - - - - Divides corresponding coordinates of two vectors. - - - The first vector to divide. - The second vector to devide. - - Returns a vector which coordinates are equal to coordinates of the first vector divided by - corresponding coordinates of the second vector. - - - - - Divides corresponding coordinates of two vectors. - - - The first vector to divide. - The second vector to devide. - - Returns a vector which coordinates are equal to coordinates of the first vector divided by - corresponding coordinates of the second vector. - - - - - Divides coordinates of the specified vector by the specified factor. - - - Vector to divide coordinates of. - Factor to divide coordinates of the specified vector by. - - Returns new vector with all coordinates divided by the specified factor. - - - - - Divides coordinates of the specified vector by the specified factor. - - - Vector to divide coordinates of. - Factor to divide coordinates of the specified vector by. - - Returns new vector with all coordinates divided by the specified factor. - - - - - Tests whether two specified vectors are equal. - - - The left-hand vector. - The right-hand vector. - - Returns if the two vectors are equal or otherwise. - - - - - Tests whether two specified vectors are not equal. - - - The left-hand vector. - The right-hand vector. - - Returns if the two vectors are not equal or otherwise. - - - - - Tests whether the vector equals to the specified one. - - - The vector to test equality with. - - Returns if the two vectors are equal or otherwise. - - - - - Tests whether the vector equals to the specified object. - - - The object to test equality with. - - Returns if the vector equals to the specified object or otherwise. - - - - - Returns the hashcode for this instance. - - - A 32-bit signed integer hash code. - - - - - Normalizes the vector by dividing it’s all coordinates with the vector's norm. - - - Returns the value of vectors’ norm before normalization. - - - - - Inverse the vector. - - - Returns a vector with all coordinates equal to 1.0 divided by the value of corresponding coordinate - in this vector (or equal to 0.0 if this vector has corresponding coordinate also set to 0.0). - - - - - Calculate absolute values of the vector. - - - Returns a vector with all coordinates equal to absolute values of this vector's coordinates. - - - - - Calculates cross product of two vectors. - - - First vector to use for cross product calculation. - Second vector to use for cross product calculation. - - Returns cross product of the two specified vectors. - - - - - Calculates dot product of two vectors. - - - First vector to use for dot product calculation. - Second vector to use for dot product calculation. - - Returns dot product of the two specified vectors. - - - - - Converts the vector to a 4D vector. - - - Returns 4D vector which is an extension of the 3D vector. - - The method returns a 4D vector which has X, Y and Z coordinates equal to the - coordinates of this 3D vector and W coordinate set to 1.0. - - - - - - Returns maximum value of the vector. - - - Returns maximum value of all 3 vector's coordinates. - - - - - Returns minimum value of the vector. - - - Returns minimum value of all 3 vector's coordinates. - - - - - Returns index of the coordinate with maximum value. - - - Returns index of the coordinate, which has the maximum value - 0 for X, - 1 for Y or 2 for Z. - - If there are multiple coordinates which have the same maximum value, the - property returns smallest index. - - - - - - Returns index of the coordinate with minimum value. - - - Returns index of the coordinate, which has the minimum value - 0 for X, - 1 for Y or 2 for Z. - - If there are multiple coordinates which have the same minimum value, the - property returns smallest index. - - - - - - Returns vector's norm. - - - Returns Euclidean norm of the vector, which is a - square root of the sum: X2+Y2+Z2. - - - - - - Returns square of the vector's norm. - - - Return X2+Y2+Z2, which is - a square of vector's norm or a dot product of this vector - with itself. - - - - - Cosine similarity metric. - - - This class represents the - Cosine Similarity metric. - - Sample usage: - - // instantiate new similarity class - CosineSimilarity sim = new CosineSimilarity( ); - // create two vectors for inputs - double[] p = new double[] { 2.5, 3.5, 3.0, 3.5, 2.5, 3.0 }; - double[] q = new double[] { 3.0, 3.5, 1.5, 5.0, 3.5, 3.0 }; - // get similarity between the two vectors - double similarityScore = sim.GetSimilarityScore( p, q ); - - - - - - - Returns similarity score for two N-dimensional double vectors. - - - 1st point vector. - 2nd point vector. - - Returns Cosine similarity between two supplied vectors. - - Thrown if the two vectors are of different dimensions (if specified - array have different length). - - - - - 3D pose estimation algorithm. - - - The class implements an algorithm for 3D object's pose estimation from it's - 2D coordinates obtained by perspective projection, when the object is described none coplanar points. - The idea of the implemented math and algorithm is described in "Model-Based Object Pose in 25 - Lines of Code" paper written by Daniel F. DeMenthon and Larry S. Davis (the implementation of - the algorithm is almost 1 to 1 translation of the pseudo code given by the paper, so should - be easy to follow). - - At this point the implementation works only with models described by 4 points, which is - the minimum number of points enough for 3D pose estimation. - - The 4 model's point must not be coplanar, i.e. must not reside all within - same planer. See for coplanar case. - - Read 3D Pose Estimation article for - additional information and samples. - - Sample usage: - - // points of real object - model - Vector3[] positObject = new Vector3[4] - { - new Vector3( 28, 28, -28 ), - new Vector3( -28, 28, -28 ), - new Vector3( 28, -28, -28 ), - new Vector3( 28, 28, 28 ), - }; - // focal length of camera used to capture the object - float focalLength = 640; // depends on your camera or projection system - // initialize POSIT object - Posit posit = new Posit( positObject, focalLength ); - - // 2D points of te object - projection - AForge.Point[] projectedPoints = new AForge.Point[4] - { - new AForge.Point( -4, 29 ), - new AForge.Point( -180, 86 ), - new AForge.Point( -5, -102 ), - new AForge.Point( 76, 137 ), - }; - // estimate pose - Matrix3x3 rotationMatrix; - Vector3 translationVector; - posit.EstimatePose( projectedPoints, - out rotationMatrix, out translationVector ); - - - - - - - - - Initializes a new instance of the class. - - - Array of vectors containing coordinates of four real model's point (points - must not be on the same plane). - Effective focal length of the camera used to capture the model. - - The model must have 4 points. - - - - - Estimate pose of a model from it's projected 2D coordinates. - - - 4 2D points of the model's projection. - Gets object's rotation. - Gets object's translation. - - 4 points must be be given for pose estimation. - - - - - Coordinates of the model points which pose should be estimated. - - - - - Effective focal length of the camera used to capture the model. - - - - - Histogram for continuous random values. - - - The class wraps histogram for continuous stochastic function, which is represented - by integer array and range of the function. Values of the integer array are treated - as total amount of hits on the corresponding subranges, which are calculated by splitting the - specified range into required amount of consequent ranges. - - For example, if the integer array is equal to { 1, 2, 4, 8, 16 } and the range is set - to [0, 1], then the histogram consists of next subranges: - - [0.0, 0.2] - 1 hit; - [0.2, 0.4] - 2 hits; - [0.4, 0.6] - 4 hits; - [0.6, 0.8] - 8 hits; - [0.8, 1.0] - 16 hits. - - - - Sample usage: - - // create histogram - ContinuousHistogram histogram = new ContinuousHistogram( - new int[] { 0, 0, 8, 4, 2, 4, 7, 1, 0 }, new Range( 0.0f, 1.0f ) ); - // get mean and standard deviation values - Console.WriteLine( "mean = " + histogram.Mean + ", std.dev = " + histogram.StdDev ); - - - - - - - Initializes a new instance of the class. - - - Values of the histogram. - Range of random values. - - Values of the integer array are treated as total amount of hits on the - corresponding subranges, which are calculated by splitting the specified range into - required amount of consequent ranges (see class - description for more information). - - - - - - Get range around median containing specified percentage of values. - - - Values percentage around median. - - Returns the range which containes specifies percentage of values. - - The method calculates range of stochastic variable, which summary probability - comprises the specified percentage of histogram's hits. - - Sample usage: - - // create histogram - ContinuousHistogram histogram = new ContinuousHistogram( - new int[] { 0, 0, 8, 4, 2, 4, 7, 1, 0 }, new Range( 0.0f, 1.0f ) ); - // get 50% range - Range range = histogram.GetRange( 0.5f ); - // show the range ([0.25, 0.75]) - Console.WriteLine( "50% range = [" + range.Min + ", " + range.Max + "]" ); - - - - - - - Update statistical value of the histogram. - - - The method recalculates statistical values of the histogram, like mean, - standard deviation, etc. The method should be called only in the case if histogram - values were retrieved through property and updated after that. - - - - - - Values of the histogram. - - - - - - Range of random values. - - - - - - Mean value. - - - The property allows to retrieve mean value of the histogram. - - Sample usage: - - // create histogram - ContinuousHistogram histogram = new ContinuousHistogram( - new int[] { 0, 0, 8, 4, 2, 4, 7, 1, 0 }, new Range( 0.0f, 1.0f ) ); - // get mean value (= 0.505 ) - Console.WriteLine( "mean = " + histogram.Mean.ToString( "F3" ) ); - - - - - - - Standard deviation. - - - The property allows to retrieve standard deviation value of the histogram. - - Sample usage: - - // create histogram - ContinuousHistogram histogram = new ContinuousHistogram( - new int[] { 0, 0, 8, 4, 2, 4, 7, 1, 0 }, new Range( 0.0f, 1.0f ) ); - // get std.dev. value (= 0.215) - Console.WriteLine( "std.dev. = " + histogram.StdDev.ToString( "F3" ) ); - - - - - - - Median value. - - - The property allows to retrieve median value of the histogram. - - Sample usage: - - // create histogram - ContinuousHistogram histogram = new ContinuousHistogram( - new int[] { 0, 0, 8, 4, 2, 4, 7, 1, 0 }, new Range( 0.0f, 1.0f ) ); - // get median value (= 0.500) - Console.WriteLine( "median = " + histogram.Median.ToString( "F3" ) ); - - - - - - - Minimum value. - - - The property allows to retrieve minimum value of the histogram with non zero - hits count. - - Sample usage: - - // create histogram - ContinuousHistogram histogram = new ContinuousHistogram( - new int[] { 0, 0, 8, 4, 2, 4, 7, 1, 0 }, new Range( 0.0f, 1.0f ) ); - // get min value (= 0.250) - Console.WriteLine( "min = " + histogram.Min.ToString( "F3" ) ); - - - - - - Maximum value. - - - The property allows to retrieve maximum value of the histogram with non zero - hits count. - - Sample usage: - - // create histogram - ContinuousHistogram histogram = new ContinuousHistogram( - new int[] { 0, 0, 8, 4, 2, 4, 7, 1, 0 }, new Range( 0.0f, 1.0f ) ); - // get max value (= 0.875) - Console.WriteLine( "max = " + histogram.Max.ToString( "F3" ) ); - - - - - - - A structure representing 3x3 matrix. - - - The structure incapsulates elements of a 3x3 matrix and - provides some operations with it. - - - - - Row 0 column 0 element of the matrix. - - - - - Row 0 column 1 element of the matrix. - - - - - Row 0 column 2 element of the matrix. - - - - - Row 1 column 0 element of the matrix. - - - - - Row 1 column 1 element of the matrix. - - - - - Row 1 column 2 element of the matrix. - - - - - Row 2 column 0 element of the matrix. - - - - - Row 2 column 1 element of the matrix. - - - - - Row 2 column 2 element of the matrix. - - - - - Returns array representation of the matrix. - - - Returns array which contains all elements of the matrix in the row-major order. - - - - - Creates rotation matrix around Y axis. - - - Rotation angle around Y axis in radians. - - Returns rotation matrix to rotate an object around Y axis. - - - - - Creates rotation matrix around X axis. - - - Rotation angle around X axis in radians. - - Returns rotation matrix to rotate an object around X axis. - - - - - Creates rotation matrix around Z axis. - - - Rotation angle around Z axis in radians. - - Returns rotation matrix to rotate an object around Z axis. - - - - - Creates rotation matrix to rotate an object around X, Y and Z axes. - - - Rotation angle around Y axis in radians. - Rotation angle around X axis in radians. - Rotation angle around Z axis in radians. - - Returns rotation matrix to rotate an object around all 3 axes. - - - The routine assumes roll-pitch-yaw rotation order, when creating rotation - matrix, i.e. an object is first rotated around Z axis, then around X axis and finally around - Y axis. - - - - - - Extract rotation angles from the rotation matrix. - - - Extracted rotation angle around Y axis in radians. - Extracted rotation angle around X axis in radians. - Extracted rotation angle around Z axis in radians. - - The routine assumes roll-pitch-yaw rotation order when extracting rotation angle. - Using extracted angles with the should provide same rotation matrix. - - - The method assumes the provided matrix represent valid rotation matrix. - - Sample usage: - - // assume we have a rotation matrix created like this - float yaw = 10.0f / 180 * Math.PI; - float pitch = 30.0f / 180 * Math.PI; - float roll = 45.0f / 180 * Math.PI; - - Matrix3x3 rotationMatrix = Matrix3x3.CreateFromYawPitchRoll( yaw, pitch, roll ); - // ... - - // now somewhere in the code you may want to get rotation - // angles back from a matrix assuming same rotation order - float extractedYaw; - float extractedPitch; - float extractedRoll; - - rotation.ExtractYawPitchRoll( out extractedYaw, out extractedPitch, out extractedRoll ); - - - - - - - Creates a matrix from 3 rows specified as vectors. - - - First row of the matrix to create. - Second row of the matrix to create. - Third row of the matrix to create. - - Returns a matrix from specified rows. - - - - - Creates a matrix from 3 columns specified as vectors. - - - First column of the matrix to create. - Second column of the matrix to create. - Third column of the matrix to create. - - Returns a matrix from specified columns. - - - - - Creates a diagonal matrix using the specified vector as diagonal elements. - - - Vector to use for diagonal elements of the matrix. - - Returns a diagonal matrix. - - - - - Get row of the matrix. - - - Row index to get, [0, 2]. - - Returns specified row of the matrix as a vector. - - Invalid row index was specified. - - - - - Get column of the matrix. - - - Column index to get, [0, 2]. - - Returns specified column of the matrix as a vector. - - Invalid column index was specified. - - - - - Multiplies two specified matrices. - - - Matrix to multiply. - Matrix to multiply by. - - Return new matrix, which the result of multiplication of the two specified matrices. - - - - - Multiplies two specified matrices. - - - Matrix to multiply. - Matrix to multiply by. - - Return new matrix, which the result of multiplication of the two specified matrices. - - - - - Adds corresponding components of two matrices. - - - The matrix to add to. - The matrix to add to the first matrix. - - Returns a matrix which components are equal to sum of corresponding - components of the two specified matrices. - - - - - Adds corresponding components of two matrices. - - - The matrix to add to. - The matrix to add to the first matrix. - - Returns a matrix which components are equal to sum of corresponding - components of the two specified matrices. - - - - - Subtracts corresponding components of two matrices. - - - The matrix to subtract from. - The matrix to subtract from the first matrix. - - Returns a matrix which components are equal to difference of corresponding - components of the two specified matrices. - - - - - Subtracts corresponding components of two matrices. - - - The matrix to subtract from. - The matrix to subtract from the first matrix. - - Returns a matrix which components are equal to difference of corresponding - components of the two specified matrices. - - - - - Multiplies specified matrix by the specified vector. - - - Matrix to multiply by vector. - Vector to multiply matrix by. - - Returns new vector which is the result of multiplication of the specified matrix - by the specified vector. - - - - - Multiplies specified matrix by the specified vector. - - - Matrix to multiply by vector. - Vector to multiply matrix by. - - Returns new vector which is the result of multiplication of the specified matrix - by the specified vector. - - - - - Multiplies matrix by the specified factor. - - - Matrix to multiply. - Factor to multiple the specified matrix by. - - Returns new matrix with all components equal to corresponding components of the - specified matrix multiples by the specified factor. - - - - - Multiplies matrix by the specified factor. - - - Matrix to multiply. - Factor to multiple the specified matrix by. - - Returns new matrix with all components equal to corresponding components of the - specified matrix multiples by the specified factor. - - - - - Adds specified value to all components of the specified matrix. - - - Matrix to add value to. - Value to add to all components of the specified matrix. - - Returns new matrix with all components equal to corresponding components of the - specified matrix increased by the specified value. - - - - - Adds specified value to all components of the specified matrix. - - - Matrix to add value to. - Value to add to all components of the specified matrix. - - Returns new matrix with all components equal to corresponding components of the - specified matrix increased by the specified value. - - - - - Tests whether two specified matrices are equal. - - - The left-hand matrix. - The right-hand matrix. - - Returns if the two matrices are equal or otherwise. - - - - - Tests whether two specified matrices are not equal. - - - The left-hand matrix. - The right-hand matrix. - - Returns if the two matrices are not equal or otherwise. - - - - - Tests whether the matrix equals to the specified one. - - - The matrix to test equality with. - - Returns if the two matrices are equal or otherwise. - - - - - Tests whether the matrix equals to the specified object. - - - The object to test equality with. - - Returns if the matrix equals to the specified object or otherwise. - - - - - Returns the hashcode for this instance. - - - A 32-bit signed integer hash code. - - - - - Transpose the matrix, AT. - - - Return a matrix which equals to transposition of this matrix. - - - - - Multiply the matrix by its transposition, A*AT. - - - Returns a matrix which is the result of multiplying this matrix by its transposition. - - - - - Multiply transposition of this matrix by itself, AT*A. - - - Returns a matrix which is the result of multiplying this matrix's transposition by itself. - - - - - Calculate adjugate of the matrix, adj(A). - - - Returns adjugate of the matrix. - - - - - Calculate inverse of the matrix, A-1. - - - Returns inverse of the matrix. - - Cannot calculate inverse of the matrix since it is singular. - - - - - Calculate pseudo inverse of the matrix, A+. - - - Returns pseudo inverse of the matrix. - - The pseudo inverse of the matrix is calculate through its - as V*E+*UT. - - - - - Calculate Singular Value Decomposition (SVD) of the matrix, such as A=U*E*VT. - - - Output parameter which gets 3x3 U matrix. - Output parameter which gets diagonal elements of the E matrix. - Output parameter which gets 3x3 V matrix. - - Having components U, E and V the source matrix can be reproduced using below code: - - Matrix3x3 source = u * Matrix3x3.Diagonal( e ) * v.Transpose( ); - - - - - - - Provides an identity matrix with all diagonal elements set to 1. - - - - - Calculates determinant of the matrix. - - - - - Perlin noise function. - - - The class implements 1-D and 2-D Perlin noise functions, which represent - sum of several smooth noise functions with different frequency and amplitude. The description - of Perlin noise function and its calculation may be found on - Hugo Elias's page. - - - The number of noise functions, which comprise the resulting Perlin noise function, is - set by property. Amplitude and frequency values for each octave - start from values, which are set by and - properties. - - Sample usage (clouds effect): - - // create Perlin noise function - PerlinNoise noise = new PerlinNoise( 8, 0.5, 1.0 / 32 ); - // generate clouds effect - float[,] texture = new float[height, width]; - - for ( int y = 0; y < height; y++ ) - { - for ( int x = 0; x < width; x++ ) - { - texture[y, x] = - Math.Max( 0.0f, Math.Min( 1.0f, - (float) noise.Function2D( x, y ) * 0.5f + 0.5f - ) ); - } - } - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Number of octaves (see property). - Persistence value (see property). - - - - - Initializes a new instance of the class. - - - Number of octaves (see property). - Persistence value (see property). - Initial frequency (see property). - Initial amplitude (see property). - - - - - 1-D Perlin noise function. - - - x value. - - Returns function's value at point . - - - - - 2-D Perlin noise function. - - - x value. - y value. - - Returns function's value at point (, ). - - - - - Ordinary noise function - - - - - Smoothed noise. - - - - - Cosine interpolation. - - - - - Initial frequency. - - - The property sets initial frequency of the first octave. Frequencies for - next octaves are calculated using the next equation:
- frequencyi = * 2i, - where i = [0, ). -
- - Default value is set to 1. -
- -
- - - Initial amplitude. - - - The property sets initial amplitude of the first octave. Amplitudes for - next octaves are calculated using the next equation:
- amplitudei = * i, - where i = [0, ). -
- - Default value is set to 1. -
- -
- - - Persistence value. - - - The property sets so called persistence value, which controls the way - how amplitude is calculated for each octave comprising - the Perlin noise function. - - Default value is set to 0.65. - - - - - - Number of octaves, [1, 32]. - - - The property sets the number of noise functions, which sum up the resulting - Perlin noise function. - - Default value is set to 4. - - - - - - Cosine distance metric. - - - This class represents the cosine distance metric (1 - cosine similarity) - . - - - Sample usage: - - // instantiate new distance class - CosineDistance dist = new CosineDistance(); - // create two vectors for inputs - double[] p = new double[] { 2.5, 3.5, 3.0, 3.5, 2.5, 3.0 }; - double[] q = new double[] { 3.0, 3.5, 1.5, 5.0, 3.5, 3.0 }; - // get distance between the two vectors - double distance = dist.GetDistance( p, q ); - - - - - - - Returns distance between two N-dimensional double vectors. - - - 1st point vector. - 2nd point vector. - - Returns Cosine distance between two supplied vectors. - - Thrown if the two vectors are of different dimensions (if specified - array have different length). - - - - - Complex number wrapper class. - - - The class encapsulates complex number and provides - set of different operators to manipulate it, lake adding, subtractio, - multiplication, etc. - - Sample usage: - - // define two complex numbers - Complex c1 = new Complex( 3, 9 ); - Complex c2 = new Complex( 8, 3 ); - // sum - Complex s1 = Complex.Add( c1, c2 ); - Complex s2 = c1 + c2; - Complex s3 = c1 + 5; - // difference - Complex d1 = Complex.Subtract( c1, c2 ); - Complex d2 = c1 - c2; - Complex d3 = c1 - 2; - - - - - - - Real part of the complex number. - - - - - Imaginary part of the complex number. - - - - - A double-precision complex number that represents zero. - - - - - A double-precision complex number that represents one. - - - - - A double-precision complex number that represents the squere root of (-1). - - - - - Initializes a new instance of the class. - - - Real part. - Imaginary part. - - - - - Initializes a new instance of the class. - - - Source complex number. - - - - - Adds two complex numbers. - - - A instance. - A instance. - - Returns new instance containing the sum of specified - complex numbers. - - - - - Adds scalar value to a complex number. - - - A instance. - A scalar value. - - Returns new instance containing the sum of specified - complex number and scalar value. - - - - - Adds two complex numbers and puts the result into the third complex number. - - - A instance. - A instance. - A instance to hold the result. - - - - - Adds scalar value to a complex number and puts the result into another complex number. - - - A instance. - A scalar value. - A instance to hold the result. - - - - - Subtracts one complex number from another. - - - A instance to subtract from. - A instance to be subtracted. - - Returns new instance containing the subtraction result (a - b). - - - - - Subtracts a scalar from a complex number. - - - A instance to subtract from. - A scalar value to be subtracted. - - Returns new instance containing the subtraction result (a - s). - - - - - Subtracts a complex number from a scalar value. - - - A scalar value to subtract from. - A instance to be subtracted. - - Returns new instance containing the subtraction result (s - a). - - - - - Subtracts one complex number from another and puts the result in the third complex number. - - - A instance to subtract from. - A instance to be subtracted. - A instance to hold the result. - - - - - Subtracts a scalar value from a complex number and puts the result into another complex number. - - - A instance to subtract from. - A scalar value to be subtracted. - A instance to hold the result. - - - - - Subtracts a complex number from a scalar value and puts the result into another complex number. - - - A scalar value to subtract from. - A instance to be subtracted. - A instance to hold the result. - - - - - Multiplies two complex numbers. - - - A instance. - A instance. - - Returns new instance containing the result of multiplication. - - - - - Multiplies a complex number by a scalar value. - - - A instance. - A scalar value. - - Returns new instance containing the result of multiplication. - - - - - Multiplies two complex numbers and puts the result in a third complex number. - - - A instance. - A instance. - A instance to hold the result. - - - - - Multiplies a complex number by a scalar value and puts the result into another complex number. - - - A instance. - A scalar value. - A instance to hold the result. - - - - - Divides one complex number by another complex number. - - - A instance. - A instance. - - Returns new instance containing the result. - - Can not divide by zero. - - - - - Divides a complex number by a scalar value. - - - A instance. - A scalar value. - - Returns new instance containing the result. - - Can not divide by zero. - - - - - Divides a scalar value by a complex number. - - - A scalar value. - A instance. - - Returns new instance containing the result. - - Can not divide by zero. - - - - - Divides one complex number by another complex number and puts the result in a third complex number. - - - A instance. - A instance. - A instance to hold the result. - - Can not divide by zero. - - - - - Divides a complex number by a scalar value and puts the result into another complex number. - - - A instance. - A scalar value. - A instance to hold the result. - - Can not divide by zero. - - - - - Divides a scalar value by a complex number and puts the result into another complex number. - - - A instance. - A scalar value. - A instance to hold the result. - - Can not divide by zero. - - - - - Negates a complex number. - - - A instance. - - Returns new instance containing the negated values. - - - - - Tests whether two complex numbers are approximately equal using default tolerance value. - - - A instance. - A instance. - - Return if the two vectors are approximately equal or otherwise. - - The default tolerance value, which is used for the test, equals to 8.8817841970012523233891E-16. - - - - - Tests whether two complex numbers are approximately equal given a tolerance value. - - - A instance. - A instance. - The tolerance value used to test approximate equality. - - The default tolerance value, which is used for the test, equals to 8.8817841970012523233891E-16. - - - - - Converts the specified string to its equivalent. - - - A string representation of a complex number. - - Returns new instance that represents the complex number - specified by the parameter. - - String representation of the complex number is not correctly formatted. - - - - - Try to convert the specified string to its equivalent. - - - A string representation of a complex number. - - instance to output the result to. - - Returns boolean value that indicates if the parse was successful or not. - - - - - Calculates square root of a complex number. - - - A instance. - - Returns new instance containing the square root of the specified - complex number. - - - - - Calculates natural (base e) logarithm of a complex number. - - - A instance. - - Returns new instance containing the natural logarithm of the specified - complex number. - - - - - Calculates exponent (e raised to the specified power) of a complex number. - - - A instance. - - Returns new instance containing the exponent of the specified - complex number. - - - - - Calculates Sine value of the complex number. - - - A instance. - - Returns new instance containing the Sine value of the specified - complex number. - - - - - Calculates Cosine value of the complex number. - - - A instance. - - Returns new instance containing the Cosine value of the specified - complex number. - - - - - Calculates Tangent value of the complex number. - - - A instance. - - Returns new instance containing the Tangent value of the specified - complex number. - - - - - Returns the hashcode for this instance. - - - A 32-bit signed integer hash code. - - - - Returns a value indicating whether this instance is equal to the specified object. - - - An object to compare to this instance. - - Returns if is a and has the same values as this instance or otherwise. - - - - - Returns a string representation of this object. - - - A string representation of this object. - - - - - Tests whether two specified complex numbers are equal. - - - The left-hand complex number. - The right-hand complex number. - - Returns if the two complex numbers are equal or otherwise. - - - - - Tests whether two specified complex numbers are not equal. - - - The left-hand complex number. - The right-hand complex number. - - Returns if the two complex numbers are not equal or otherwise. - - - - - Negates the complex number. - - - A instance. - - Returns new instance containing the negated values. - - - - - Adds two complex numbers. - - - A instance. - A instance. - - Returns new instance containing the sum. - - - - - Adds a complex number and a scalar value. - - - A instance. - A scalar value. - - Returns new instance containing the sum. - - - - - Adds a complex number and a scalar value. - - - A instance. - A scalar value. - - Returns new instance containing the sum. - - - - - Subtracts one complex number from another complex number. - - - A instance. - A instance. - - Returns new instance containing the difference. - - - - - Subtracts a scalar value from a complex number. - - - A instance. - A scalar value. - - Returns new instance containing the difference. - - - - - Subtracts a complex number from a scalar value. - - - A scalar value. - A instance. - - Returns new instance containing the difference. - - - - - Multiplies two complex numbers. - - - A instance. - A instance. - - Returns new instance containing the result of multiplication. - - - - - Multiplies a complex number by a scalar value. - - - A scalar value. - A instance. - - Returns new instance containing the result of multiplication. - - - - - Multiplies a complex number by a scalar value. - - - A instance. - A scalar value. - - Returns new instance containing the result of multiplication. - - - - - Divides one complex number by another complex number. - - - A instance. - A instance. - - A new Complex instance containing the result. - Returns new instance containing the result of division. - - - - - Divides a complex number by a scalar value. - - - A instance. - A scalar value. - - Returns new instance containing the result of division. - - - - - Divides a scalar value by a complex number. - - - A instance. - A scalar value. - - Returns new instance containing the result of division. - - - - - Converts from a single-precision real number to a complex number. - - - Single-precision real number to convert to complex number. - - Returns new instance containing complex number with - real part initialized to the specified value. - - - - - Converts from a double-precision real number to a complex number. - - - Double-precision real number to convert to complex number. - - Returns new instance containing complex number with - real part initialized to the specified value. - - - - - Creates an exact copy of this object. - - - Returns clone of the complex number. - - - - - Creates an exact copy of this object. - - - Returns clone of the complex number. - - - - - Populates a with the data needed to serialize the target object. - - - The to populate with data. - The destination (see ) for this serialization. - - - - - Magnitude value of the complex number. - - - Magnitude of the complex number, which equals to Sqrt( Re * Re + Im * Im ). - - - - - Phase value of the complex number. - - - Phase of the complex number, which equals to Atan( Im / Re ). - - - - - Squared magnitude value of the complex number. - - - - - Hamming distance metric. - - - This class represents the - Hamming distance metric. - - Sample usage: - - // instantiate new distance class - HammingDistance dist = new HammingDistance( ); - // create two vectors for inputs - double[] p = new double[] { 2.5, 3.5, 3.0, 3.5, 2.5, 3.0 }; - double[] q = new double[] { 3.0, 3.5, 1.5, 5.0, 3.5, 3.0 }; - // get distance between the two vectors - double distance = dist.GetDistance( p, q ); - - - - - - - Returns distance between two N-dimensional double vectors. - - - 1st point vector. - 2nd point vector. - - Returns Hamming distance between two supplied vectors. - - Thrown if the two vectors are of different dimensions (if specified - array have different length). - - - - - Euclidean similarity metric. - - - This class represents the - Euclidean Similarity metric, - which is calculated as 1.0 / ( 1.0 + EuclideanDistance ). - - Sample usage: - - // instantiate new similarity class - EuclideanSimilarity sim = new EuclideanSimilarity( ); - // create two vectors for inputs - double[] p = new double[] { 2.5, 3.5, 3.0, 3.5, 2.5, 3.0 }; - double[] q = new double[] { 3.0, 3.5, 1.5, 5.0, 3.5, 3.0 }; - // get simirarity between the two vectors - double similarityScore = sim.GetSimilarityScore( p, q ); - - - - - - - Returns similarity score for two N-dimensional double vectors. - - - 1st point vector. - 2nd point vector. - - Returns Euclidean similarity between two supplied vectors. - - Thrown if the two vectors are of different dimensions (if specified - array have different length). - - -
-
diff --git a/Externals/AForge.NET/AForge.Neuro.dll b/Externals/AForge.NET/AForge.Neuro.dll deleted file mode 100644 index 63a4a03e2..0000000000 Binary files a/Externals/AForge.NET/AForge.Neuro.dll and /dev/null differ diff --git a/Externals/AForge.NET/AForge.Neuro.xml b/Externals/AForge.NET/AForge.Neuro.xml deleted file mode 100644 index c974a0a67..0000000000 --- a/Externals/AForge.NET/AForge.Neuro.xml +++ /dev/null @@ -1,1792 +0,0 @@ - - - - AForge.Neuro - - - - - Unsupervised learning interface. - - - The interface describes methods, which should be implemented - by all unsupervised learning algorithms. Unsupervised learning is such - type of learning algorithms, where system's desired output is not known on - the learning stage. Given sample input values, it is expected, that - system will organize itself in the way to find similarities betweed provided - samples. - - - - - Runs learning iteration. - - - Input vector. - - Returns learning error. - - - - - Runs learning epoch. - - - Array of input vectors. - - Returns sum of learning errors. - - - - - Sigmoid activation function. - - - The class represents sigmoid activation function with - the next expression: - - 1 - f(x) = ------------------ - 1 + exp(-alpha * x) - - alpha * exp(-alpha * x ) - f'(x) = ---------------------------- = alpha * f(x) * (1 - f(x)) - (1 + exp(-alpha * x))^2 - - - - Output range of the function: [0, 1]. - - Functions graph: - - - - - - - Activation function interface. - - - All activation functions, which are supposed to be used with - neurons, which calculate their output as a function of weighted sum of - their inputs, should implement this interfaces. - - - - - - Calculates function value. - - - Function input value. - - Function output value, f(x). - - The method calculates function value at point . - - - - - Calculates function derivative. - - - Function input value. - - Function derivative, f'(x). - - The method calculates function derivative at point . - - - - - Calculates function derivative. - - - Function output value - the value, which was obtained - with the help of method. - - Function derivative, f'(x). - - The method calculates the same derivative value as the - method, but it takes not the input x value - itself, but the function value, which was calculated previously with - the help of method. - - Some applications require as function value, as derivative value, - so they can save the amount of calculations using this method to calculate derivative. - - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Sigmoid's alpha value. - - - - - Calculates function value. - - - Function input value. - - Function output value, f(x). - - The method calculates function value at point . - - - - - Calculates function derivative. - - - Function input value. - - Function derivative, f'(x). - - The method calculates function derivative at point . - - - - - Calculates function derivative. - - - Function output value - the value, which was obtained - with the help of method. - - Function derivative, f'(x). - - The method calculates the same derivative value as the - method, but it takes not the input x value - itself, but the function value, which was calculated previously with - the help of method. - - Some applications require as function value, as derivative value, - so they can save the amount of calculations using this method to calculate derivative. - - - - - - Creates a new object that is a copy of the current instance. - - - - A new object that is a copy of this instance. - - - - - - Sigmoid's alpha value. - - - The value determines steepness of the function. Increasing value of - this property changes sigmoid to look more like a threshold function. Decreasing - value of this property makes sigmoid to be very smooth (slowly growing from its - minimum value to its maximum value). - - Default value is set to 2. - - - - - - Base neural layer class. - - - This is a base neural layer class, which represents - collection of neurons. - - - - - Layer's inputs count. - - - - - Layer's neurons count. - - - - - Layer's neurons. - - - - - Layer's output vector. - - - - - Initializes a new instance of the class. - - - Layer's neurons count. - Layer's inputs count. - - Protected contructor, which initializes , - and members. - - - - - Compute output vector of the layer. - - - Input vector. - - Returns layer's output vector. - - The actual layer's output vector is determined by neurons, - which comprise the layer - consists of output values of layer's neurons. - The output vector is also stored in property. - - The method may be called safely from multiple threads to compute layer's - output value for the specified input values. However, the value of - property in multi-threaded environment is not predictable, - since it may hold layer's output computed from any of the caller threads. Multi-threaded - access to the method is useful in those cases when it is required to improve performance - by utilizing several threads and the computation is based on the immediate return value - of the method, but not on layer's output property. - - - - - - Randomize neurons of the layer. - - - Randomizes layer's neurons by calling method - of each neuron. - - - - - Layer's inputs count. - - - - - Layer's neurons. - - - - - - Layer's output vector. - - - The calculation way of layer's output vector is determined by neurons, - which comprise the layer. - - The property is not initialized (equals to ) until - method is called. - - - - - - Bipolar sigmoid activation function. - - - The class represents bipolar sigmoid activation function with - the next expression: - - 2 - f(x) = ------------------ - 1 - 1 + exp(-alpha * x) - - 2 * alpha * exp(-alpha * x ) - f'(x) = -------------------------------- = alpha * (1 - f(x)^2) / 2 - (1 + exp(-alpha * x))^2 - - - - Output range of the function: [-1, 1]. - - Functions graph: - - - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Sigmoid's alpha value. - - - - - Calculates function value. - - - Function input value. - - Function output value, f(x). - - The method calculates function value at point . - - - - - Calculates function derivative. - - - Function input value. - - Function derivative, f'(x). - - The method calculates function derivative at point . - - - - - Calculates function derivative. - - - Function output value - the value, which was obtained - with the help of method. - - Function derivative, f'(x). - - The method calculates the same derivative value as the - method, but it takes not the input x value - itself, but the function value, which was calculated previously with - the help of method. - - Some applications require as function value, as derivative value, - so they can save the amount of calculations using this method to calculate derivative. - - - - - - Creates a new object that is a copy of the current instance. - - - - A new object that is a copy of this instance. - - - - - - Sigmoid's alpha value. - - - The value determines steepness of the function. Increasing value of - this property changes sigmoid to look more like a threshold function. Decreasing - value of this property makes sigmoid to be very smooth (slowly growing from its - minimum value to its maximum value). - - Default value is set to 2. - - - - - - Kohonen Self Organizing Map (SOM) learning algorithm. - - - This class implements Kohonen's SOM learning algorithm and - is widely used in clusterization tasks. The class allows to train - Distance Networks. - - Sample usage (clustering RGB colors): - - // set range for randomization neurons' weights - Neuron.RandRange = new Range( 0, 255 ); - // create network - DistanceNetwork network = new DistanceNetwork( - 3, // thress inputs in the network - 100 * 100 ); // 10000 neurons - // create learning algorithm - SOMLearning trainer = new SOMLearning( network ); - // network's input - double[] input = new double[3]; - // loop - while ( !needToStop ) - { - input[0] = rand.Next( 256 ); - input[1] = rand.Next( 256 ); - input[2] = rand.Next( 256 ); - - trainer.Run( input ); - - // ... - // update learning rate and radius continuously, - // so networks may come steady state - } - - - - - - - Initializes a new instance of the class. - - - Neural network to train. - - This constructor supposes that a square network will be passed for training - - it should be possible to get square root of network's neurons amount. - - Invalid network size - square network is expected. - - - - - Initializes a new instance of the class. - - - Neural network to train. - Neural network's width. - Neural network's height. - - The constructor allows to pass network of arbitrary rectangular shape. - The amount of neurons in the network should be equal to width * height. - - - Invalid network size - network size does not correspond - to specified width and height. - - - - - Runs learning iteration. - - - Input vector. - - Returns learning error - summary absolute difference between neurons' weights - and appropriate inputs. The difference is measured according to the neurons - distance to the winner neuron. - - The method runs one learning iterations - finds winner neuron (the neuron - which has weights with values closest to the specified input vector) and updates its weight - (as well as weights of neighbor neurons) in the way to decrease difference with the specified - input vector. - - - - - Runs learning epoch. - - - Array of input vectors. - - Returns summary learning error for the epoch. See - method for details about learning error calculation. - - The method runs one learning epoch, by calling method - for each vector provided in the array. - - - - - Learning rate, [0, 1]. - - - Determines speed of learning. - - Default value equals to 0.1. - - - - - - Learning radius. - - - Determines the amount of neurons to be updated around - winner neuron. Neurons, which are in the circle of specified radius, - are updated during the learning procedure. Neurons, which are closer - to the winner neuron, get more update. - - In the case if learning rate is set to 0, then only winner - neuron's weights are updated. - - Default value equals to 7. - - - - - - Back propagation learning algorithm. - - - The class implements back propagation learning algorithm, - which is widely used for training multi-layer neural networks with - continuous activation functions. - - Sample usage (training network to calculate XOR function): - - // initialize input and output values - double[][] input = new double[4][] { - new double[] {0, 0}, new double[] {0, 1}, - new double[] {1, 0}, new double[] {1, 1} - }; - double[][] output = new double[4][] { - new double[] {0}, new double[] {1}, - new double[] {1}, new double[] {0} - }; - // create neural network - ActivationNetwork network = new ActivationNetwork( - SigmoidFunction( 2 ), - 2, // two inputs in the network - 2, // two neurons in the first layer - 1 ); // one neuron in the second layer - // create teacher - BackPropagationLearning teacher = new BackPropagationLearning( network ); - // loop - while ( !needToStop ) - { - // run epoch of learning procedure - double error = teacher.RunEpoch( input, output ); - // check error value to see if we need to stop - // ... - } - - - - - - - - - Supervised learning interface. - - - The interface describes methods, which should be implemented - by all supervised learning algorithms. Supervised learning is such - type of learning algorithms, where system's desired output is known on - the learning stage. So, given sample input values and desired outputs, - system should adopt its internals to produce correct (or close to correct) - result after the learning step is complete. - - - - - Runs learning iteration. - - - Input vector. - Desired output vector. - - Returns learning error. - - - - - Runs learning epoch. - - - Array of input vectors. - Array of output vectors. - - Returns sum of learning errors. - - - - - Initializes a new instance of the class. - - - Network to teach. - - - - - Runs learning iteration. - - - Input vector. - Desired output vector. - - Returns squared error (difference between current network's output and - desired output) divided by 2. - - Runs one learning iteration and updates neuron's - weights. - - - - - Runs learning epoch. - - - Array of input vectors. - Array of output vectors. - - Returns summary learning error for the epoch. See - method for details about learning error calculation. - - The method runs one learning epoch, by calling method - for each vector provided in the array. - - - - - Calculates error values for all neurons of the network. - - - Desired output vector. - - Returns summary squared error of the last layer divided by 2. - - - - - Calculate weights updates. - - - Network's input vector. - - - - - Update network'sweights. - - - - - - Learning rate, [0, 1]. - - - The value determines speed of learning. - - Default value equals to 0.1. - - - - - - Momentum, [0, 1]. - - - The value determines the portion of previous weight's update - to use on current iteration. Weight's update values are calculated on - each iteration depending on neuron's error. The momentum specifies the amount - of update to use from previous iteration and the amount of update - to use from current iteration. If the value is equal to 0.1, for example, - then 0.1 portion of previous update and 0.9 portion of current update are used - to update weight's value. - - Default value equals to 0.0. - - - - - - Perceptron learning algorithm. - - - This learning algorithm is used to train one layer neural - network of Activation Neurons - with the Threshold - activation function. - - See information about Perceptron - and its learning algorithm. - - - - - - Initializes a new instance of the class. - - - Network to teach. - - Invalid nuaral network. It should have one layer only. - - - - - Runs learning iteration. - - - Input vector. - Desired output vector. - - Returns absolute error - difference between current network's output and - desired output. - - Runs one learning iteration and updates neuron's - weights in the case if neuron's output is not equal to the - desired output. - - - - - Runs learning epoch. - - - Array of input vectors. - Array of output vectors. - - Returns summary learning error for the epoch. See - method for details about learning error calculation. - - The method runs one learning epoch, by calling method - for each vector provided in the array. - - - - - Learning rate, [0, 1]. - - - The value determines speed of learning. - - Default value equals to 0.1. - - - - - - Threshold activation function. - - - The class represents threshold activation function with - the next expression: - - f(x) = 1, if x >= 0, otherwise 0 - - - - Output range of the function: [0, 1]. - - Functions graph: - - - - - - - Initializes a new instance of the class. - - - - - Calculates function value. - - - Function input value. - - Function output value, f(x). - - The method calculates function value at point . - - - - - Calculates function derivative (not supported). - - - Input value. - - Always returns 0. - - The method is not supported, because it is not possible to - calculate derivative of the function. - - - - - Calculates function derivative (not supported). - - - Input value. - - Always returns 0. - - The method is not supported, because it is not possible to - calculate derivative of the function. - - - - - Creates a new object that is a copy of the current instance. - - - - A new object that is a copy of this instance. - - - - - - Base neural network class. - - - This is a base neural netwok class, which represents - collection of neuron's layers. - - - - - Network's inputs count. - - - - - Network's layers count. - - - - - Network's layers. - - - - - Network's output vector. - - - - - Initializes a new instance of the class. - - - Network's inputs count. - Network's layers count. - - Protected constructor, which initializes , - and members. - - - - - Compute output vector of the network. - - - Input vector. - - Returns network's output vector. - - The actual network's output vecor is determined by layers, - which comprise the layer - represents an output vector of the last layer - of the network. The output vector is also stored in property. - - The method may be called safely from multiple threads to compute network's - output value for the specified input values. However, the value of - property in multi-threaded environment is not predictable, - since it may hold network's output computed from any of the caller threads. Multi-threaded - access to the method is useful in those cases when it is required to improve performance - by utilizing several threads and the computation is based on the immediate return value - of the method, but not on network's output property. - - - - - - Randomize layers of the network. - - - Randomizes network's layers by calling method - of each layer. - - - - - Save network to specified file. - - - File name to save network into. - - The neural network is saved using .NET serialization (binary formatter is used). - - - - - Save network to specified file. - - - Stream to save network into. - - The neural network is saved using .NET serialization (binary formatter is used). - - - - - Load network from specified file. - - - File name to load network from. - - Returns instance of class with all properties initialized from file. - - Neural network is loaded from file using .NET serialization (binary formater is used). - - - - - Load network from specified file. - - - Stream to load network from. - - Returns instance of class with all properties initialized from file. - - Neural network is loaded from file using .NET serialization (binary formater is used). - - - - - Network's inputs count. - - - - - Network's layers. - - - - - Network's output vector. - - - The calculation way of network's output vector is determined by - layers, which comprise the network. - - The property is not initialized (equals to ) until - method is called. - - - - - - Distance network. - - - Distance network is a neural network of only one distance - layer. The network is a base for such neural networks as SOM, Elastic net, etc. - - - - - - Initializes a new instance of the class. - - - Network's inputs count. - Network's neurons count. - - The new network is randomized (see - method) after it is created. - - - - - Get winner neuron. - - - Index of the winner neuron. - - The method returns index of the neuron, which weights have - the minimum distance from network's input. - - - - - Fitness function used for chromosomes representing collection of neural network's weights. - - - - - - Initializes a new instance of the class. - - - Neural network for which fitness will be calculated. - Input data samples for neural network. - Output data sampels for neural network (desired output). - - Length of inputs and outputs arrays must be equal and greater than 0. - Length of each input vector must be equal to neural network's inputs count. - - - - - Evaluates chromosome. - - - Chromosome to evaluate. - - Returns chromosome's fitness value. - - The method calculates fitness value of the specified - chromosome. - - - - - Delta rule learning algorithm. - - - This learning algorithm is used to train one layer neural - network of Activation Neurons - with continuous activation function, see - for example. - - See information about delta rule - learning algorithm. - - - - - - Initializes a new instance of the class. - - - Network to teach. - - Invalid nuaral network. It should have one layer only. - - - - - Runs learning iteration. - - - Input vector. - Desired output vector. - - Returns squared error (difference between current network's output and - desired output) divided by 2. - - Runs one learning iteration and updates neuron's - weights. - - - - - Runs learning epoch. - - - Array of input vectors. - Array of output vectors. - - Returns summary learning error for the epoch. See - method for details about learning error calculation. - - The method runs one learning epoch, by calling method - for each vector provided in the array. - - - - - Learning rate, [0, 1]. - - - The value determines speed of learning. - - Default value equals to 0.1. - - - - - - Elastic network learning algorithm. - - - This class implements elastic network's learning algorithm and - allows to train Distance Networks. - - - - - - Initializes a new instance of the class. - - - Neural network to train. - - - - - Runs learning iteration. - - - Input vector. - - Returns learning error - summary absolute difference between neurons' - weights and appropriate inputs. The difference is measured according to the neurons - distance to the winner neuron. - - The method runs one learning iterations - finds winner neuron (the neuron - which has weights with values closest to the specified input vector) and updates its weight - (as well as weights of neighbor neurons) in the way to decrease difference with the specified - input vector. - - - - - Runs learning epoch. - - - Array of input vectors. - - Returns summary learning error for the epoch. See - method for details about learning error calculation. - - The method runs one learning epoch, by calling method - for each vector provided in the array. - - - - - Learning rate, [0, 1]. - - - Determines speed of learning. - - Default value equals to 0.1. - - - - - - Learning radius, [0, 1]. - - - Determines the amount of neurons to be updated around - winner neuron. Neurons, which are in the circle of specified radius, - are updated during the learning procedure. Neurons, which are closer - to the winner neuron, get more update. - - Default value equals to 0.5. - - - - - - Base neuron class. - - - This is a base neuron class, which encapsulates such - common properties, like neuron's input, output and weights. - - - - - Neuron's inputs count. - - - - - Nouron's wieghts. - - - - - Neuron's output value. - - - - - Random number generator. - - - The generator is used for neuron's weights randomization. - - - - - Random generator range. - - - Sets the range of random generator. Affects initial values of neuron's weight. - Default value is [0, 1]. - - - - - Initializes a new instance of the class. - - - Neuron's inputs count. - - The new neuron will be randomized (see method) - after it is created. - - - - - Randomize neuron. - - - Initialize neuron's weights with random values within the range specified - by . - - - - - Computes output value of neuron. - - - Input vector. - - Returns neuron's output value. - - The actual neuron's output value is determined by inherited class. - The output value is also stored in property. - - - - - Random number generator. - - - The property allows to initialize random generator with a custom seed. The generator is - used for neuron's weights randomization. - - - - - Random generator range. - - - Sets the range of random generator. Affects initial values of neuron's weight. - Default value is [0, 1]. - - - - - Neuron's inputs count. - - - - - Neuron's output value. - - - The calculation way of neuron's output value is determined by inherited class. - - - - - Neuron's weights. - - - - - Activation layer. - - - Activation layer is a layer of activation neurons. - The layer is usually used in multi-layer neural networks. - - - - - Initializes a new instance of the class. - - - Layer's neurons count. - Layer's inputs count. - Activation function of neurons of the layer. - - The new layer is randomized (see - method) after it is created. - - - - - Set new activation function for all neurons of the layer. - - - Activation function to set. - - The methods sets new activation function for each neuron by setting - their property. - - - - - Activation neuron. - - - Activation neuron computes weighted sum of its inputs, adds - threshold value and then applies activation function. - The neuron isusually used in multi-layer neural networks. - - - - - - - Threshold value. - - - The value is added to inputs weighted sum before it is passed to activation - function. - - - - - Activation function. - - - The function is applied to inputs weighted sum plus - threshold value. - - - - - Initializes a new instance of the class. - - - Neuron's inputs count. - Neuron's activation function. - - - - - Randomize neuron. - - - Calls base class Randomize method - to randomize neuron's weights and then randomizes threshold's value. - - - - - Computes output value of neuron. - - - Input vector. - - Returns neuron's output value. - - The output value of activation neuron is equal to value - of nueron's activation function, which parameter is weighted sum - of its inputs plus threshold value. The output value is also stored - in Output property. - - The method may be called safely from multiple threads to compute neuron's - output value for the specified input values. However, the value of - property in multi-threaded environment is not predictable, - since it may hold neuron's output computed from any of the caller threads. Multi-threaded - access to the method is useful in those cases when it is required to improve performance - by utilizing several threads and the computation is based on the immediate return value - of the method, but not on neuron's output property. - - - Wrong length of the input vector, which is not - equal to the expected value. - - - - - Threshold value. - - - The value is added to inputs weighted sum before it is passed to activation - function. - - - - - Neuron's activation function. - - - - - - Activation network. - - - Activation network is a base for multi-layer neural network - with activation functions. It consists of activation - layers. - - Sample usage: - - // create activation network - ActivationNetwork network = new ActivationNetwork( - new SigmoidFunction( ), // sigmoid activation function - 3, // 3 inputs - 4, 1 ); // 2 layers: - // 4 neurons in the firs layer - // 1 neuron in the second layer - - - - - - - Initializes a new instance of the class. - - - Activation function of neurons of the network. - Network's inputs count. - Array, which specifies the amount of neurons in - each layer of the neural network. - - The new network is randomized (see - method) after it is created. - - - - - Set new activation function for all neurons of the network. - - - Activation function to set. - - The method sets new activation function for all neurons by calling - method for each layer of the network. - - - - - Neural networks' evolutionary learning algorithm, which is based on Genetic Algorithms. - - - The class implements supervised neural network's learning algorithm, - which is based on Genetic Algorithms. For the given neural network, it create a population - of chromosomes, which represent neural network's - weights. Then, during the learning process, the genetic population evolves and weights, which - are represented by the best chromosome, are set to the source neural network. - - See class for additional information about genetic population - and evolutionary based search. - - Sample usage (training network to calculate XOR function): - - // initialize input and output values - double[][] input = new double[4][] { - new double[] {-1, 1}, new double[] {-1, 1}, - new double[] { 1, -1}, new double[] { 1, 1} - }; - double[][] output = new double[4][] { - new double[] {-1}, new double[] { 1}, - new double[] { 1}, new double[] {-1} - }; - // create neural network - ActivationNetwork network = new ActivationNetwork( - BipolarSigmoidFunction( 2 ), - 2, // two inputs in the network - 2, // two neurons in the first layer - 1 ); // one neuron in the second layer - // create teacher - EvolutionaryLearning teacher = new EvolutionaryLearning( network, - 100 ); // number of chromosomes in genetic population - // loop - while ( !needToStop ) - { - // run epoch of learning procedure - double error = teacher.RunEpoch( input, output ); - // check error value to see if we need to stop - // ... - } - - - - - - - - - - Initializes a new instance of the class. - - - Activation network to be trained. - Size of genetic population. - Random numbers generator used for initialization of genetic - population representing neural network's weights and thresholds (see ). - Random numbers generator used to generate random - factors for multiplication of network's weights and thresholds during genetic mutation - (ses .) - Random numbers generator used to generate random - values added to neural network's weights and thresholds during genetic mutation - (see ). - Method of selection best chromosomes in genetic population. - Crossover rate in genetic population (see - ). - Mutation rate in genetic population (see - ). - Rate of injection of random chromosomes during selection - in genetic population (see ). - - - - - Initializes a new instance of the class. - - - Activation network to be trained. - Size of genetic population. - - This version of constructor is used to create genetic population - for searching optimal neural network's weight using default set of parameters, which are: - - Selection method - elite; - Crossover rate - 0.75; - Mutation rate - 0.25; - Rate of injection of random chromosomes during selection - 0.20; - Random numbers generator for initializing new chromosome - - UniformGenerator( new Range( -1, 1 ) ); - Random numbers generator used during mutation for genes' multiplication - - ExponentialGenerator( 1 ); - Random numbers generator used during mutation for adding random value to genes - - UniformGenerator( new Range( -0.5f, 0.5f ) ). - - - In order to have full control over the above default parameters, it is possible to - used extended version of constructor, which allows to specify all of the parameters. - - - - - - Runs learning iteration. - - - Input vector. - Desired output vector. - - Returns learning error. - - The method is not implemented, since evolutionary learning algorithm is global - and requires all inputs/outputs in order to run its one epoch. Use - method instead. - - The method is not implemented by design. - - - - - Runs learning epoch. - - - Array of input vectors. - Array of output vectors. - - Returns summary squared learning error for the entire epoch. - - While running the neural network's learning process, it is required to - pass the same and values for each - epoch. On the very first run of the method it will initialize evolutionary fitness - function with the given input/output. So, changing input/output in middle of the learning - process, will break it. - - - - - Distance layer. - - - Distance layer is a layer of distance neurons. - The layer is usually a single layer of such networks as Kohonen Self - Organizing Map, Elastic Net, Hamming Memory Net. - - - - - Initializes a new instance of the class. - - - Layer's neurons count. - Layer's inputs count. - - The new layet is randomized (see - method) after it is created. - - - - - Resilient Backpropagation learning algorithm. - - - This class implements the resilient backpropagation (RProp) - learning algorithm. The RProp learning algorithm is one of the fastest learning - algorithms for feed-forward learning networks which use only first-order - information. - - Sample usage (training network to calculate XOR function): - - // initialize input and output values - double[][] input = new double[4][] { - new double[] {0, 0}, new double[] {0, 1}, - new double[] {1, 0}, new double[] {1, 1} - }; - double[][] output = new double[4][] { - new double[] {0}, new double[] {1}, - new double[] {1}, new double[] {0} - }; - // create neural network - ActivationNetwork network = new ActivationNetwork( - SigmoidFunction( 2 ), - 2, // two inputs in the network - 2, // two neurons in the first layer - 1 ); // one neuron in the second layer - // create teacher - ResilientBackpropagationLearning teacher = new ResilientBackpropagationLearning( network ); - // loop - while ( !needToStop ) - { - // run epoch of learning procedure - double error = teacher.RunEpoch( input, output ); - // check error value to see if we need to stop - // ... - } - - - - - - - Initializes a new instance of the class. - - - Network to teach. - - - - - Runs learning iteration. - - - Input vector. - Desired output vector. - - Returns squared error (difference between current network's output and - desired output) divided by 2. - - Runs one learning iteration and updates neuron's - weights. - - - - - Runs learning epoch. - - - Array of input vectors. - Array of output vectors. - - Returns summary learning error for the epoch. See - method for details about learning error calculation. - - The method runs one learning epoch, by calling method - for each vector provided in the array. - - - - - Resets current weight and threshold derivatives. - - - - - - Resets the current update steps using the given learning rate. - - - - - - Update network's weights. - - - - - - Calculates error values for all neurons of the network. - - - Desired output vector. - - Returns summary squared error of the last layer divided by 2. - - - - - Calculate weights updates - - - Network's input vector. - - - - - Learning rate. - - - The value determines speed of learning. - - Default value equals to 0.0125. - - - - - - Distance neuron. - - - Distance neuron computes its output as distance between - its weights and inputs - sum of absolute differences between weights' - values and corresponding inputs' values. The neuron is usually used in Kohonen - Self Organizing Map. - - - - - Initializes a new instance of the class. - - - Neuron's inputs count. - - - - - Computes output value of neuron. - - - Input vector. - - Returns neuron's output value. - - The output value of distance neuron is equal to the distance - between its weights and inputs - sum of absolute differences. - The output value is also stored in Output - property. - - The method may be called safely from multiple threads to compute neuron's - output value for the specified input values. However, the value of - property in multi-threaded environment is not predictable, - since it may hold neuron's output computed from any of the caller threads. Multi-threaded - access to the method is useful in those cases when it is required to improve performance - by utilizing several threads and the computation is based on the immediate return value - of the method, but not on neuron's output property. - - - Wrong length of the input vector, which is not - equal to the expected value. - - - - diff --git a/Externals/AForge.NET/AForge.Robotics.Lego.dll b/Externals/AForge.NET/AForge.Robotics.Lego.dll deleted file mode 100644 index 4dbb27ed0..0000000000 Binary files a/Externals/AForge.NET/AForge.Robotics.Lego.dll and /dev/null differ diff --git a/Externals/AForge.NET/AForge.Robotics.Lego.xml b/Externals/AForge.NET/AForge.Robotics.Lego.xml deleted file mode 100644 index 2b77a56da..0000000000 --- a/Externals/AForge.NET/AForge.Robotics.Lego.xml +++ /dev/null @@ -1,2044 +0,0 @@ - - - - AForge.Robotics.Lego - - - - - Enumeration of commands supported by Lego Mindstorms RXT brick. - - - - - Check whether or not the RCX is alive. - - - - - Play one of defined sounds. - - - - - Play tone of specified frequency. - - - - - Get ROM and firmware versions. - - - - - Get battery power. - - - - - Set time displayed on RCX brick. - - - - - Turm off RCX brick. - - - - - Get value. - - - - - Set sensor type. - - - - - Set sensor mode. - - - - - Clear sensor value. - - - - - Set IR transmiter's range. - - - - - Turn on/off motor. - - - - - Set motor's power. - - - - - Set motor's direction - - - - - Manipulation of Lego Mindstorms RCX device. - - - - The class allows to manipulate with Lego Mindstorms RCX device, - setting its motors' state, getting information about sensors' - values and performing some other manipulations. - - - The class supports both types of IR towers - USB and serial (see - ). - - The class uses GhostAPI to communicate with Lego RCX device, so its - libraries (GhostAPI.dll, PbkComm32.dll and PbkUsbPort.dll) should be placed into applications folder. - - The class is deprecated. - - Sample usage: - - // create an instance of RCX brick - RCXBrick rcx = new RCXBrick( ); - // connect to the device - if ( rcx.Connect( RCXBrick.IRTowerType.USB ) ) - { - // set forward direction of motor A - rcx.SetMotorDirection( RCXBrick.Motor.A, true ); - // set power of motor - rcx.SetMotorPower( RCXBrick.Motor.A, 1 ); - // turm motor on - rcx.SetMotorOn( RCXBrick.Motor.A, true ); - // ... - // turn off motors A, B and C - rcx.SetMotorOn( RCXBrick.Motor.ABC, false ); - - // get first sensor's value - short value; - - if ( rcx.GetSensorValue( RCXBrick.Sensor.First, out value ) ) - { - // ... - } - // ... - } - - - - - - - - Initializes a new instance of the class. - - - - - - Destroys the instance of the class. - - - - - - Connect to Lego RCX brick. - - - Type of IR tower to use for communication with RCX brick. - - Returns true on successful connection or false - otherwise. - - If connection to RCX brick was established before the call, existing connection will be reused. - If it is required to force reconnection, then method should be called before. - - - - - - Disconnnect from Lego RCX brick. - - - - - - Check if the RCX brick is alive and responds to messages. - - - Returns true if device is alive or false otherwise. - - - - - Play one of supported sounds. - - - Sound type to play. - - Returns true if command was executed successfully or false otherwise. - - - - - Play tone of specified frequency. - - - Tone frequency in Hz. - Tone duration in 1/100ths of a second. - - Returns true if command was executed successfully or false otherwise. - - - - - Get version information of RCX brick. - - - ROM version number. - Firmware version number. - - Returns true if command was executed successfully or false otherwise. - - - - - Get battery power of RCX brick. - - - RCX brick's battery power in millivolts. - - Returns true if command was executed successfully or false otherwise. - - - - - Set current time for the RCX brick. - - - Hours, [0..23]. - Minutes, [0..59]. - - Returns true if command was executed successfully or false otherwise. - - - - - Turn off the RCX brick. - - - Returns true if command was executed successfully or false otherwise. - - - - - Get sensor's value. - - - Sensor to get value of. - Retrieved sensor's value (units depend on current - sensor's type and mode). - - Returns true if command was executed successfully or false otherwise. - - - - - Set sensor's type. - - - Sensor to set type of. - Sensor type to set. - - Returns true if command was executed successfully or false otherwise. - - - - - Set sensor's mode. - - - Sensor to set mode of. - Sensor mode to set. - - Returns true if command was executed successfully or false otherwise. - - - - - Clear the counter associated with the specified sensor by setting it to a value of zero. - - - Sensor to clear value of. - - Returns true if command was executed successfully or false otherwise. - - - - - Turn on/off specified motors. - - - Motors to turn on/off. - True to turn motors on, otherwise false. - - Returns true if command was executed successfully or false otherwise. - - - - - Set power of specified motors. - - - Motors to set power of. - Power level to set, [0..7]. - - Returns true if command was executed successfully or false otherwise. - - - - - Set direction of specified motors. - - - Motors to set direction of. - True to set forward direction, false to set backward. - - Returns true if command was executed successfully or false otherwise. - - - - - Set IR transmitter's range. - - - True if long range should be set, otherwise false. - - Returns true if command was executed successfully or false otherwise. - - - - - Send command to Lego RCX brick and read reply. - - - Command to send. - Buffer to receive reply into. - Expected reply length. - - Returns true if the command was sent successfully and reply was - received, otherwise false. - - Communication can not be performed, because connection with - RCX brick was not established yet. - Reply buffer size is smaller than the reply data size. - Reply does not correspond to command (first byte of reply - should be complement (bitwise NOT) to the first byte of command orred with 0x08). - - - - - Check if connection to RCX brick is established. - - - - - - Type of IR tower used for communication with RCX. - - - - - USB IR tower. - - - - - RS232 IR tower. - - - - - Enumeration of sound type playable by Lego RCX brick. - - - - - Blip sound. - - - - - Double beep spund. - - - - - Downward tones sound. - - - - - Upward tones sound. - - - - - Low buzz sound. - - - - - Fast upward tones sound. - - - - - Enumeration of RCX brick sensor ports. - - - - - First sensor. - - - - - Second sensor. - - - - - Third sensor. - - - - - Enumeration of RCX brick sensor types. - - - Use method to set RCX sensor's type. - - - - - Raw sensor. - - - - - Touch sensor (default mode is boolean). - - - - - Temperature sensor (default mode is temperature in °C). - - - - - Light sensor (default mode is percentage). - - - - - Rotation sensor (default mode is angle). - - - - - Enumeration of RCX brick sensor modes. - - - Use method to set RCX sensor's mode. - - - - - Raw mode - value in [0, 1023]. - - - - - Boolean - either 0 or 1. - - - - - Number of boolean transitions. - - - - - Number of boolean transitions divided by two. - - - - - Raw value scaled to [0, 100]. - - - - - Temperature in °C - 1/10ths of a degree, [-19.8, 69.5]. - - - - - Temperature in °F - 1/10ths of a degree, [-3.6, 157.1]. - - - - - Angle - 1/16ths of a rotation, represented as a signed short. - - - - - Enumeration of RCX brick motor ports. - - - - - Motor A. - - - - - Motor B. - - - - - Motor C. - - - - - Motors A and B. - - - - - Motors A and C. - - - - - Motors B and C. - - - - - Motors A, B and C. - - - - - All motors (A, B and C). - - - - - Implementation of serial communication interface with LEGO Mindstorm NXT brick. - - - - - - Interface, which wraps communication functions with Lego Mindstorms NXT brick. - - - - - - Connect to NXT brick. - - - Returns true if connection was established successfully or false - otherwise. - - - - - Disconnect from NXT brick. - - - - - - Send message to NXT brick over the communication interface. - - - Buffer containing the message to send. - - Returns true if message was sent successfully or false - otherwise. - - This method assumes that message starts from the start of the - specified buffer and occupies entire buffer. - - - - - Send message to NXT brick over the communication interface. - - - Buffer containing the message to send. - Length of the message to send. - - Returns true if message was sent successfully or false - otherwise. - - This method assumes that message starts from the start of the - specified buffer. - - - - - Send message to NXT brick over the communication interface. - - - Buffer containing the message to send. - Offset of the message in the buffer. - Length of the message to send. - - Returns true if message was sent successfully or false - otherwise. - - - - - Read message from NXT brick over the communication interface. - - - Buffer to use for message reading. - On successful return the variable keeps message length. - - Returns true if message was read successfully or false - otherwise. - - - - - Read message from NXT brick over the communication interface. - - - Buffer to use for message reading. - Offset in the buffer for message. - On successful return the variable keeps message length. - - Returns true if message was read successfully or false - otherwise. - - - - - Get connection status. - - - - - - Maximum message size, which can be sent over this communication interface to NXT - brick. - - - - - - Initializes a new instance of the class. - - - Serial port name to use for communication. - - This constructor initializes serial port with default write and read - timeout values, which are 1000 milliseconds. - - - - - Initializes a new instance of the class. - - - Serial port name to use for communication. - Timeout value used for write operations. - Timeout value used for read operations. - - - - - Connect to NXT brick. - - - Returns true if connection was established successfully or false - otherwise. - - If communication interface was connected before the call, existing connection will be reused. - If it is required to force reconnection, then method should be called before. - - - - - - Disconnect from NXT brick. - - - - - Send message to NXT brick over the communication interface. - - - Buffer containing the message to send. - - Returns true if message was sent successfully or false - otherwise. - - This method assumes that message starts from the start of the - specified buffer and occupies entire buffer. - - - - - Send message to NXT brick over the communication interface. - - - Buffer containing the message to send. - Length of the message to send. - - Returns true if message was sent successfully or false - otherwise. - - This method assumes that message starts from the start of the - specified buffer. - - - - - Send message to NXT brick over the communication interface. - - - Buffer containing the message to send. - Offset of the message in the buffer. - Length of the message to send. - - Returns true if message was sent successfully or false - otherwise. - - - - - Read message from NXT brick over the communication interface. - - - Buffer to use for message reading. - On successful return the variable keeps message length. - - Returns true if message was read successfully or false - otherwise. - - - - - Read message from NXT brick over the communication interface. - - - Buffer to use for message reading. - Offset in the buffer for message. - On successful return the variable keeps message length. - - Returns true if message was read successfully or false - otherwise. - - - - - Serial port name used for communication. - - - - - - Get connection status. - - - - - - GhostAPI wrapper class. - - - GhostAPI is a library provided by Lego, to communicate with its - RCX robotics kit. - - - - - Mask of severity bits. - - - - - Success severity. - - - - - Informational severity. - - - - - Warning severity. - - - - - Error severity. - - - - - Creates Ghost communication stack. - - - Port implementation required. - Protocol implementation required. - Session implementation required. - Stack handle created by this function. - - GhostAPI error code. - - - - - Finds and selects the first available device. - - - Stack handle. - Buffer, which will be filled with the name of the selected port device. - Size of the specified buffer. - - GhostAPI error code. - - - - - Opens the currently selected device. - - - Handle of the stack to be opened. - - GhostAPI error code. - - - - - Closes the currently selected device. - - - Handle of the stack to be closed. - - GhostAPI error code. - - - - - Sets the current command interleave between the execute and download queue. - - - Stack handle. - Number of immediate command blocks. - Number of download slices. - - GhostAPI error code. - - - - - Set the current notification mode to WAIT. - - - Stack handle. - Must be IntPtr.Zero - no callback function. - - GhostAPI error code. - - - - - Creates a command queue (containing one command to start with) and return handle. - - - Queue handle created by this function. - - GhostAPI error code. - - - - - Releases a command queue. - - - Queue handle. - - GhostAPI error code. - - - - - Appends a command to the given command queue. - - - Queue handle. - Command buffer (command + parameters). - Length of the command buffer. - Length of the expected reply to this command. - - GhostAPI error code. - - - - - Submits a command queue on the EXECUTE queue. - - - Stack handle. - Queue handle. - - GhostAPI error code. - - - - - Gets the first command in the queue. - - Queue handle. - Retrieved command handle. - - GhostAPI error code. - - - - - Gets command reply length. - - - Command handle. - Reply length. - - GhostAPI error code. - - - - - Gets command reply. - - - Command handle. - Buffer for reply data. - Buffer size. - - GhostAPI error code. - - - - - Checks if return value has success severity. - - - Error return value. - - True if the return value has success severity. - - - - - Checks if return value has info severity. - - - Error return value. - - True if the return value has info severity. - - - - - Checks if return value has warning severity. - - - Error return value. - - True if the return value has warning severity. - - - - - Checks if return value has error severity. - - - Error return value. - - True if the return value has error severity. - - - - - Checks for successful return code, which has success or info severity. - - - Error return value. - - True if return value is successful. - - - - - Manipulation of Lego Mindstorms NXT device. - - - - The class allows to manipulate with Lego Mindstorms NXT device, - setting/getting its motors' state, getting information about sensors' - values and retrieving generic information about the NXT brick. - - - Only communication through Bluetooth (virtual serial port) is supported at this point. - - Sample usage: - - // create an instance of NXT brick - NXTBrick nxt = new NXTBrick( ); - // connect to the device - if ( nxt.Connect( "COM8" ) ) - { - // run motor A - NXTBrick.MotorState motorState = new NXTBrick.MotorState( ); - - motorState.Power = 70; - motorState.TurnRatio = 50; - motorState.Mode = NXTBrick.MotorMode.On; - motorState.Regulation = NXTBrick.MotorRegulationMode.Idle; - motorState.RunState = NXTBrick.MotorRunState.Running; - motorState.TachoLimit = 1000; - - nxt.SetMotorState( NXTBrick.Motor.A, motorState ); - - // get input value from the first sensor - NXTBrick.SensorValues sensorValues; - - if ( nxt.GetSensorValue( NXTBrick.Sensor.First, out sensorValues ) ) - { - // ... - } - // ... - } - - - - - - - Initializes a new instance of the class. - - - - - - Destroys the instance of the class. - - - - - - Connect to NXT brick. - - - Serial port name to use for communication, for example COM1. - - Returns true on successful connection or false - otherwise. - - If connection to NXT brick was established before the call, existing connection will be reused. - If it is required to force reconnection, then method should be called before. - - - - - - Disconnect from Lego NXT brick. - - - - - - Check if the NXT brick is alive and responds to messages. - - - Returns true if device is alive or false otherwise. - - The command also keeps NXT brick alive preventing it from sleep. - - - - - Play tone of specified frequency. - - - Tone frequency in Hz. - Tone duration in milliseconds. - - Returns true if device is alive or false otherwise. - - - - - Play tone of specified frequency. - - - Tone frequency in Hz. - Tone duration in milliseconds. - Wait reply from NXT (safer option) or not (faster option). - - Returns true if device is alive or false otherwise. - - - - - Get firmware version of NXT brick. - - - Protocol version number. - Firmware version number. - - Returns true if command was executed successfully or false otherwise. - - - - - Get information about NXT device. - - - Device name. - Bluetooth address. - Bluetooth signal strength. - Free user Flash. - - Returns true if command was executed successfully or false otherwise. - - - - - Get battery power of NXT brick. - - - NXT brick's battery power in millivolts. - - Returns true if command was executed successfully or false otherwise. - - - - - Set name of NXT device. - - - Device name to set for the brick. - - Returns true if command was executed successfully or false otherwise. - - - - - Reset motor's position. - - - Motor to reset. - Specifies if relative (to last movement) or absolute motor's - position should reset. - - Returns true if command was executed successfully or false otherwise. - - - - - Reset motor's position. - - - Motor to reset. - Specifies if relative (to last movement) or absolute motor's - position should reset. - Wait reply from NXT (safer option) or not (faster option). - - Returns true if command was executed successfully or false otherwise. - - - - - Set motor state. - - - Motor to set state for. - Motor's state to set. - - Returns true if command was executed successfully or false otherwise. - - - - - Set motor state. - - - Motor to set state for. - Motor's state to set. - Wait reply from NXT (safer option) or not (faster option). - - Returns true if command was executed successfully or false otherwise. - - - - - Get motor state. - - - Motor to get state for. - Motor's state. - - Returns true if command was executed successfully or false otherwise. - - - - - Set sensor's type and mode. - - - Sensor to set type of. - Sensor's type. - Sensor's mode. - - Returns true if command was executed successfully or false otherwise. - - - - - Set sensor's type and mode. - - - Sensor to set type of. - Sensor's type. - Sensor's mode. - Wait reply from NXT (safer option) or not (faster option). - - Returns true if command was executed successfully or false otherwise. - - - - - Get sensor's values. - - - Sensor to get values of. - etrieved sensor's values. - - Returns true if command was executed successfully or false otherwise. - - - - - Clear sensor's scaled value. - - - Sensor to clear value of. - - Returns true if command was executed successfully or false otherwise. - - - - - Clear sensor's scaled value. - - - Sensor to clear value of. - Wait reply from NXT (safer option) or not (faster option). - - Returns true if command was executed successfully or false otherwise. - - - - - Get status of Low Speed bus. - - - Sensor to get the status from. - Number of bytes that are ready to be read from the bus. - - Returns true if command was executed successfully or false otherwise. - - - - - Write to Low Speed bus. - - - Sensor to write to. - Data to send to the I2C device. - Number of bytes expected from device on reply, [0..16]. - Can be set to zero if I2C command does not suppose any reply. - - Returns true if command was executed successfully or false otherwise. - - Data length must be in the [1..16] range. - - - - - Write to Low Speed bus. - - - Sensor to write to. - Data to send to the I2C device. - Number of bytes expected from device on reply, [0..16]. - Can be set to zero if I2C command does not suppose any reply. - Wait reply from NXT (safer option) or not (faster option). - - Returns true if command was executed successfully or false otherwise. - - Data length must be in the [1..16] range. - - - - - Read data from Low Speed bus. - - - Sensor to read data from. - Array to read data to. - Bytes actually read from I2C device. - - Returns true if command was executed successfully or false otherwise. - - - - - Read value of ultrasonic distance sensor. - - - Sensor to read value from. - Distance value obtained from ultrasonic sensor, [0..255] cm. - - Returns true if command was executed successfully or false otherwise. - - The method retrieves value of ultrasonic distance sensor by - communicating with I2C device (writing to and reading from low speed bus). - The method first sends { 0x02, 0x42 } command to the specified device using - method. Then it waits until there is something available - to read using method. Finally it reads sensor's value - using device. See - this page - for details. - - Before using this method it is required to use - method to set sensor's type to - mode. It should be done - once after NXT brick is powered on. If sensor's type is not set properly, - the method will generate an exception. Also after setting sensor's - type application may need to wait a bit to give device some time - to initialize. - - - - - - Send command to Lego NXT brick and read reply. - - - Command to send. - Buffer to receive reply into. - - Returns true if the command was sent successfully and reply was - received, otherwise false. - - Communication can not be performed, because connection with - NXT brick was not established yet. - Reply buffer size is smaller than the reply data size. - Reply does not correspond to command (second byte of reply should - be equal to second byte of command). - Error occurred on NXT brick side. - - - - - Read data from HiTechnic color sensor (also color sensor v2). - - - Sensor to read from. - Found color number. - Found red value. - Found green value. - Found blue value. - - Returns true if the command was sent successfully and reply was - received, otherwise false. - - The method retrieves the color valuse of a HiTechnic color sensor - by communicating with I2C device (writing to and reading from low speed bus). - The method first sends { 0x02, 0x42 } command to the specified device using - method. Then it waits until there is something available - to read using method. Finally it reads sensor's value - using device. See - this page - for details. - - Before using this method it is required to use - method to set sensor's type to - mode. It should be done - once after NXT brick is powered on. If sensor's type is not set properly, - the method will generate an exception. Also after setting sensor's - type application may need to wait a bit to give device some time - to initialize. - - NXT Firmware version 1.24 must be loaded in the NXT for the HiTechnic color sensor to operate correctly. - You can check the firmware version using the method. - - The color sensor V2 must be configured to match the mains electricity frequency for your - country. Details on how to configure the Color Sensor V2 can be found at - - - - - - - Read data from HiTechnic compass sensor. - - - Sensor to read from. - The magnetic heading, [0, 359] degrees. - - Returns true if the command was sent successfully and reply was - received, otherwise false. - - The method retrieves the angle of a - HiTechnic compass sensor by - communicating with I2C device (writing to and reading from low speed bus). - The method first sends { 0x02, 0x42 } command to the specified device using - method. Then it waits until there is something available - to read using method. Finally it reads sensor's value - using device. See - this page - for details. - - Before using this method it is required to use - method to set sensor's type to - mode. It should be done - once after NXT brick is powered on. If sensor's type is not set properly, - the method will generate an exception. Also after setting sensor's - type application may need to wait a bit to give device some time - to initialize. - - The HiTechnic compass sensor will only operate correctly in a horizontal plane so you must keep the compass - level for it to read correctly. This is very important so remember this when you build it into your robot. - It is highly desirable to mount the compass at least 6 inches (15cm) away from the motors and 4 inches (10cm) away from the NXT brick - itself. Try to make sure it is firmly mounted, if it bounces around, the readings may bounce around too. - - - NXT Firmware version 1.03 must be loaded in the NXT for the compass to operate correctly. You can check the firmware version - using the method. - - - - - - Read data from HiTechnic acceleration/tilt sensor. The HiTechnic accelerometer/tilt sensor measures acceleration in - three axes. It measures also tilt along each axis. Using the sensor, you can measure the acceleration of your robot in the range - of -2g to 2g. - - - Sensor to read from. - Acceleration in X direction, with a scaling of approximately 200 counts per g. - Acceleration in Y direction, with a scaling of approximately 200 counts per g. - Acceleration in Z direction, with a scaling of approximately 200 counts per g. - - Returns true if the command was sent successfully and reply was - received, otherwise false. - - The method retrieves the acceleration in three directions of a - HiTechnic acceleration/tilt sensor by - communicating with I2C device (writing to and reading from low speed bus). - The method first sends { 0x02, 0x42 } command to the specified device using - method. Then it waits until there is something available - to read using method. Finally it reads sensor's value - using device. See - this page - for details. - - Before using this method it is required to use - method to set sensor's type to - mode. It should be done - once after NXT brick is powered onq If sensor's type is not set properly, - the method will generate an exception. Also after setting sensor's - type application may need to wait a bit to give device some time - to initialize. - - The acceleration sensor can also be used to measure tilt in three axes This is possible because gravity is perceived - as acceleration. When the sensor is stationary and in the normal horizontal position, the x and y axis will be near - zero, because they are horizontal, while the z axis will be near 200, which represents g. If you tilt the sensor then - gravity will also be detected on the other axis and the value for the z axis will go down. Since gravity is distributed - among the three component vectors, the tilt of the sensor can be determined. - - NXT Firmware version 1.05 or later must be loaded in the NXT for the acceleration/tilt sensor and other digital I2C - sensors to operate correctly. You can check the firmware version using the method. - - - - - - Check if connection to NXT brick is established. - - - - - - The event is raised every time a command is sent successfully. - - - - - - The event is raised every time a command is read successfully. - - - - - - Enumeration of NXT brick sensor ports. - - - - - First sensor. - - - - - Second sensor. - - - - - Third sensor. - - - - - Fourth sensor. - - - - - Enumeration of NXT brick sensor types. - - - - - - No sensor. - - - - - NXT or Legacy touch sensor. - - - - - Legacy temperature sensor. - - - - - Legacy light sensor. - - - - - Legacy rotation sensor. - - - - - NXT light sensor with floodlight enabled. - - - - - NXT light sensor with floodlight disabled. - - - - - NXT sound sensor (dB scaling). - - - - - NXT sound sensor (dBA scaling). - - - - - Unused - - - - - I2C digital sensor. - - - - - I2C digital sensor (9V power). - - - - - Unused. - - - - - NXT 2.0 color sensor in color detector mode. - - - - - NXT 2.0 color sensor in light sensor mode with red light on. - - - - - NXT 2.0 color sensor in light sensor mode with green light on. - - - - - NXT 2.0 color sensor in light sensor mode with blue light on. - - - - - NXT 2.0 color sensor in light sensor mode without light. - - - - - NXT 2.0 color sensor internal state (no functionality known yet). - - - - - Enumeration of NXT brick sensor modes. - - - - - - Raw mode. - - - - - Boolean mode. Report scaled value as 1 (TRUE) or 0 (FALSE). The firmware uses - inverse Boolean logic to match the physical characteristics of NXT sensors. Readings - are FALSE if raw value exceeds 55% of total range; reading are TRUE if raw value - is less than 45% of total range. - - - - - Report scaled value as number of transition between TRUE and FALSE. - - - - - Report scaled value as number of transitions from FALSE to TRUE, then back to FALSE. - - - - - Report scaled value as percentage of full scale reading for configured sensor type. - - - - - Scale terperature reading to degrees Celsius. - - - - - Scale terperature reading to degrees Fahrenheit. - - - - - Report scaled value as count of ticks on RCX-style rotation sensor. - - - - - Class describing sensor's values received from NXT brick's sensor port. - - - - - - Specifies if data value should be treated as valid data. - - - - - Specifies if calibration file was found and used for - field calculation. - - - - - Sensor type. - - - - - Sensor mode. - - - - - Raw A/D value (device dependent). - - - - - Normalized A/D value (sensor type dependent), [0, 1023]. - - - - - Scaled value (sensor mode dependent). - - - - - Value scaled according to calibration. - - - According to Lego notes the value is currently unused. - - - - - Enumeration of NXT brick motor ports. - - - - - - Motor A. - - - - - Motor B. - - - - - Motor C. - - - - - All motors (A, B and C). - - - - - Enumeration of supported motor modes. - - - Motor mode is a bit field, so several modes can be combined. - - - - - Mode is not set. - - - - - Turn on the motor. - - - - - Brake. - - - - - Turn on regulated mode. - - - - - Enumeration of motor regulation modes. - - - - - - No regulation will be enabled. - - - - - Power control will be enabled on specified motor. - - - - - Synchronization will be enabled. - - - Synchronization need to be enabled on two motors. - - - - - Enumeration of motor run states. - - - - - - Motor will be idle. - - - - - Motor will ramp-up. - - - - - Motor will be running. - - - - - Motor will ramp-down. - - - - - Class describing motor's state. - - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Power, [-100, 100]. - Turn ratio, [-100, 100]. - Mode (bit field). - Regulation mode. - Run state. - The value determines motor's run limit. - - - - - Power, [-100, 100]. - - - - - Turn ratio, [-100, 100]. - - - - - Mode (bit field). - - - - - Regulation mode. - - - - - Run state. - - - - - Tacho limit (0 - run forever). - - - The value determines motor's run limit. - - - - Number of counts since last reset of motor counter. - - - The value is ignored when motor's state is set. The value is - provided when motor's state is retrieved. - - - - Current position relative to last programmed movement. - - - The value is ignored when motor's state is set. The value is - provided when motor's state is retrieved. - - - - Current position relative to last reset of motor's rotation sensor. - - - The value is ignored when motor's state is set. The value is - provided when motor's state is retrieved. - - - - Enumeration of command types supported by Lego Mindstorms NXT brick. - - - - - - Direct command, which requires reply. - - - - - System command, which requires reply. - - - - - Reply command received from NXT brick. - - - - - Direct command, which does not require reply. - - - - - System command, which does not require reply. - - - - - Enumeration of system commands supported by Lego Mindstorms NXT brick. - - - - - - Get firmware version of NXT brick. - - - - - Set NXT brick name. - - - - - Get device information. - - - - - Enumeration of direct commands supported by Lego Mindstorms NXT brick. - - - - - - Keep NXT brick alive. - - - - - Play tone of specified frequency. - - - - - Get battery level. - - - - - Set output state. - - - - - Get output state. - - - - - Reset motor position. - - - - - Set input mode. - - - - - Get input values. - - - - - Get status of the Low Speed bus. - - - - - Write to the Low Speed bus. - - - - - Read from the Low Speed bus. - - - - - Reset input scaled value. - - - - diff --git a/Externals/AForge.NET/AForge.Robotics.Surveyor.dll b/Externals/AForge.NET/AForge.Robotics.Surveyor.dll deleted file mode 100644 index 0df035a46..0000000000 Binary files a/Externals/AForge.NET/AForge.Robotics.Surveyor.dll and /dev/null differ diff --git a/Externals/AForge.NET/AForge.Robotics.Surveyor.xml b/Externals/AForge.NET/AForge.Robotics.Surveyor.xml deleted file mode 100644 index 2330a5ee2..0000000000 --- a/Externals/AForge.NET/AForge.Robotics.Surveyor.xml +++ /dev/null @@ -1,1331 +0,0 @@ - - - - AForge.Robotics.Surveyor - - - - - Manipulation of Surveyor SVS (Stereo Vision System) board. - - - - The class allows to manipulate with Surveyor SVS - board (stereo vision system) - getting video from both cameras, manipulating motors and servos, - reading ultrasonic modules' values, sending direct commands, etc. - - - - This class essentially creates to instances of class to communicate - with both SVS's cameras (ports 10001 and 10002 are used) and directs all calls through them. - - Sample usage: - - SVS svs = new SVS( ); - // connect to SVS board - svs.Connect( "169.254.0.10" ); - // stop motors - svs.StopMotors( ); - // set video resolution and quality - svs.SetQuality( 7 ); - svs.SetResolution( SRV1.VideoResolution.Small ); - // get version string - string version = svs.GetVersion( ); - - // get left camera - SRV1Camera camera = svs.GetCamera( SVS.Camera.Left ); - - // set NewFrame event handler - camera.NewFrame += new NewFrameEventHandler( video_NewFrame ); - // start the video source - camera.Start( ); - // ... - - private void video_NewFrame( object sender, NewFrameEventArgs eventArgs ) - { - // get new frame - Bitmap bitmap = eventArgs.Frame; - // process the frame - } - - - - - - - - - - Initializes a new instance of the class. - - - - - - Connect to SVS board. - - - IP address of SVS board. - - The method establishes connection to SVS board. If it succeeds then - other methods can be used to manipulate the board. - - The method calls before making any connection - attempts to make sure previous connection is closed. - - - Failed connecting to SVS. - - - - - Disconnect from SVS device. - - - The method disconnects from SVS board making all other methods - unavailable (except method). In the case if user - obtained instance of left or right camera using - method, the video will be stopped automatically (and those - instances should be discarded). - - - - - - Get SVS's camera. - - - SVS camera to get. - - Returns object, which is connected to SVS's Blackfin camera. - Use method to start the camera and start receiving video - frames from it. - - The method provides an instance of , which can be used - for receiving continuous video frames from the SVS board. - In the case if only one image is required, the method can be used. - - Sample usage: - - // get SRV-1 camera - SRV1Camera camera = svs.GetCamera( SVS.Camera.Left ); - // set NewFrame event handler - camera.NewFrame += new NewFrameEventHandler( video_NewFrame ); - // start the video source - camera.Start( ); - // ... - - private void video_NewFrame( object sender, NewFrameEventArgs eventArgs ) - { - // get new frame - Bitmap bitmap = eventArgs.Frame; - // process the frame - } - - - - Not connected to SVS. Connect to SVS board before using - this method. - - - - - Get single image from the SVS board. - - - Camera to get image from. - - Returns image received from the specified camera of the SVS board or - if failed decoding provided response. - - The method provides single video frame retrieved from the specified SVS's - camera. However in many cases it is required to receive video frames one after another, so - the method is more preferred for continuous video frames. - - Not connected to SRV-1. Connect to SRV-1 before using - this method. - Connection lost or communicaton failure. Try to reconnect. - - - - - Get direct access to one of the SVS's SRV-1 Blackfin cameras. - - - SRV-1 Blackfin to get direct access to. - - Returns object connected to the requested - SRV-1 Blackfin camera. - - The method provides direct access to one of the SVS's SRV-1 - Blackfin cameras, so it could be possible to send some direct commands to it - using and methods. - - Not connected to SVS. Connect to SVS board before using - this method. - - - - - Get SVS board's firmware version string. - - - Returns SVS's version string. - - Not connected to SVS. Connect to SVS board before using - this method. - Connection lost or communicaton failure. Try to reconnect. - - - - - Get SVS's board's running time. - - - Returns SVS boards running time in milliseconds. - - Not connected to SVS. Connect to SVS board before using - this method. - Connection lost or communicaton failure. Try to reconnect. - Failed parsing response from SVS. - - - - - Run motors connected to the SVS board. - - - Left motor's speed, [-127, 127]. - Right motor's speed, [-127, 127]. - Time duration to run motors measured in number - of 10 milliseconds (0 for infinity), [0, 255]. - - The method sets specified speed to both motors connected to - the SVS board. The maximum absolute speed equals to 127, but the sign specifies - direction of motor's rotation (forward or backward). - - - Not connected to SVS. Connect to SVS board before using - this method. - - - - - Stop both motors. - - - The method stops both motors connected to the SVS board by calling - method specifying 0 for motors' speed. - - Not connected to SVS. Connect to SVS board before using - this method. - - - - - Enables fail safe mode - setting motors' speed after timeout. - - - Left motor's speed, [-127, 127]. - Right motor's speed, [-127, 127]. - - In the case if fail safe mode is enabled and no commands are received - by SVS robot withing 2 seconds, motors' speed will be set to the specified values. The command - is very useful to instruct robot to stop if no other commands were sent - within 2 last seconds (probably lost connection). - - Not connected to SVS. Connect to SVS board before using - this method. - - - - - Disable fail safe mode. - - - The method disable fail safe mode, which was set using - method. - - Not connected to SVS. Connect to SVS board before using - this method. - - - - - Control motors connected to SVS board using predefined commands. - - - Motor command to send to the SVS board. - - Controlling SVS motors with this method is only available - after at least one direct motor command is sent, which is done using or - methods. - - Not connected to SVS. Connect to SVS board before using - this method. - - - - - Direct servos control of the SVS board. - - - SVS's servo bank to control. - Left servo setting, [0, 100]. - Right servo setting, [0, 100]. - - The method performs servos control of the SVS board. - For and - banks it calls method for the corresponding - SRV-1 Blackfin camera. In the case of or , - the method sends 'Sab' SRV-1 command (see SRV-1 - Control Protocol) to the appropriate SRV-1 Blackfin camera. - - - Not connected to SVS. Connect to SVS board before using - this method. - - - - - Ping ultrasonic ranging modules. - - - SRV-1 Blackfin camera to check ultrasonic modules values. - - Returns array of ranges (distances) obtained from ultrasonic sensors. The ranges - are measured in inches. - - The method calls for the specified - SRV-1 Blackfin camera. - - Not connected to SVS. Connect to SVS board before using - this method. - Connection lost or communicaton failure. Try to reconnect. - Failed parsing response from SVS. - - - - - Read byte from I2C device. - - - SRV-1 Blackfin camera to access I2C device on. - I2C device ID (7 bit notation). - I2C device register to read. - - Returns byte read from the specified register of the specified I2C device. - - The IC2 device ID should be specified in 7 bit notation. This means that low bit of the ID - is not used for specifying read/write mode as in 8 bit notation. For example, if I2C device IDs are 0x44 for reading - and 0x45 for writing in 8 bit notation, then it equals to 0x22 device ID in 7 bit notation. - - - Not connected to SVS. Connect to SVS board before using - this method. - Connection lost or communicaton failure. Try to reconnect. - Failed parsing response from SRV-1. - - - - - Read word from I2C device. - - - SRV-1 Blackfin camera to access I2C device on. - I2C device ID (7 bit notation). - I2C device register to read. - - Returns word read from the specified register of the specified I2C device. - - The IC2 device ID should be specified in 7 bit notation. This means that low bit of the ID - is not used for specifying read/write mode as in 8 bit notation. For example, if I2C device IDs are 0x44 for reading - and 0x45 for writing in 8 bit notation, then it equals to 0x22 device ID in 7 bit notation. - - - Not connected to SVS. Connect to SVS board before using - this method. - Connection lost or communicaton failure. Try to reconnect. - Failed parsing response from SRV-1. - - - - - Write byte to I2C device. - - - SRV-1 Blackfin camera to access I2C device on. - I2C device ID (7 bit notation). - I2C device register to write to. - Byte to write to the specified register of the specified device. - - The IC2 device ID should be specified in 7 bit notation. This means that low bit of the ID - is not used for specifying read/write mode as in 8 bit notation. For example, if I2C device IDs are 0x44 for reading - and 0x45 for writing in 8 bit notation, then it equals to 0x22 device ID in 7 bit notation. - - - Not connected to SVS. Connect to SVS board before using - this method. - Connection lost or communicaton failure. Try to reconnect. - - - - - Write two bytes to I2C device. - - - SRV-1 Blackfin camera to access I2C device on. - I2C device ID (7 bit notation). - I2C device register to write to. - First byte to write to the specified register of the specified device. - Second byte to write to the specified register of the specified device. - - The IC2 device ID should be specified in 7 bit notation. This means that low bit of the ID - is not used for specifying read/write mode as in 8 bit notation. For example, if I2C device IDs are 0x44 for reading - and 0x45 for writing in 8 bit notation, then it equals to 0x22 device ID in 7 bit notation. - - - Not connected to SVS. Connect to SVS board before using - this method. - Connection lost or communicaton failure. Try to reconnect. - - - - - Set video quality for both cameras. - - - Video quality to set, [1, 8]. - - The method sets video quality for both SVS cameras, which is specified in [1, 8] range - 1 is - the highest quality level, 8 is the lowest quality level. - - Setting higher quality level and resolution - may increase delays for other requests sent to SVS. So if - robot is used not only for video, but also for controlling servos/motors, and higher - response level is required, then do not set very high quality and resolution. - - - - Not connected to SVS. Connect to SVS board before using - this method. - Invalid quality level was specified. - - - - - Set video resolution for both cameras. - - - Video resolution to set. - - - Setting higher quality level and resolution - may increase delays for other requests sent to SVS. So if - robot is used not only for video, but also for controlling servos/motors, and higher - response level is required, then do not set very high quality and resolution. - - - - Not connected to SVS. Connect to SVS board before using - this method. - - - - - Flip video capture for both cameras or not (for use with upside-down camera). - - - Specifies if video should be flipped (), - or not (). - - Not connected to SVS. Connect to SVS board before using - this method. - - - - - SVS's host address. - - - The property keeps SVS's IP address if the class is connected - to SVS board, otherwise it equals to . - - - - - Connection state. - - - The property equals to if the class is connected - to SVS board, otherwise it equals to . - - The property is not updated by the class, when connection was lost or - communication failure was detected (which results into - exception). The property only shows status of method. - - - - - - Enumeration of SVS's Blackfin cameras. - - - Since SVS board consists of two SRV-1 Blackfin cameras, the enumeration - is used by different methods to specify which one to access. - - - - - Left camera (default port number is 10000). - - - - - Right camera (default port number is 10001). - - - - - Enumeration of SVS's servos' banks. - - - - - First bank of the first () SRV-1 Blackfin camera, - timers 2 and 3 (marked as TMR2-1 and TMR3-1 on the SVS board). Note: these - timers on SVS board are supposed for controlling motors by default - (see and ), so use 0th - servos bank only when you've done proper configuration changes on SVS side. - - - - - Second bank of the first () SRV-1 Blackfin camera, - timers 6 and 7 (marked as TMR6-1 and TMR7-1 on the SVS board). - - - - - First bank of the second () SRV-1 Blackfin camera, - timers 2 and 3 (marked as TMR2-2 and TMR3-2 on the SVS board). - - - - - Second bank of the second () SRV-1 Blackfin camera, - timers 6 and 7 (marked as TMR6-2 and TMR7-2 on the SVS board). - - - - - Manipulation of Surveyor SRV-1 Blackfin robot/camera. - - - - The class allows to manipulate with Surveyor SRV-1 Blackfin Robot - - getting video from its camera, manipulating motors and servos, - reading ultrasonic modules' values, sending direct commands, etc. - - - - Sample usage: - - SRV1 srv = new SRV1( ); - // connect to SRV-1 robot - srv.Connect( "169.254.0.10", 10001 ); - // stop motors - srv.StopMotors( ); - // set video resolution and quality - srv.SetQuality( 7 ); - srv.SetResolution( SRV1.VideoResolution.Small ); - // get version string - string version = srv.GetVersion( ); - - // get robot's camera - SRV1Camera camera = srv.GetCamera( ); - - // set NewFrame event handler - camera.NewFrame += new NewFrameEventHandler( video_NewFrame ); - // start the video source - camera.Start( ); - // ... - - private void video_NewFrame( object sender, NewFrameEventArgs eventArgs ) - { - // get new frame - Bitmap bitmap = eventArgs.Frame; - // process the frame - } - - - - - - - - - Initializes a new instance of the class. - - - - - - Connect to SRV-1 Blackfin robot/camera. - - - IP address of SRV-1 robot. - Port number to connect to. - - The method establishes connection to SRV-1 Blackfin robot/camera. - If it succeeds then other methods can be used to manipulate the robot. - - The method calls before making any connection - attempts to make sure previous connection is closed. - - - Failed connecting to SRV-1. - - - - - Disconnect from SRV-1 Blackfin robot. - - - The method disconnects from SRV-1 robot making all other methods - unavailable (except method). In the case if user - obtained instance of camera using method, the video will - be stopped automatically (and those instances should be discarded). - - - - - - Get camera object for the SRV-1 Blackfin robot/camera. - - - Returns object, which is connected to SRV1 Blackfin camera. - Use method to start the camera and start receiving video - frames it. - - The method provides an instance of , which can be used - for receiving continuous video frames from the SRV-1 Blackfin camera. - In the case if only one image is required, the method can be used. - - Sample usage: - - // get SRV-1 camera - SRV1Camera camera = srv.GetCamera( ); - // set NewFrame event handler - camera.NewFrame += new NewFrameEventHandler( video_NewFrame ); - // start the video source - camera.Start( ); - // ... - - private void video_NewFrame( object sender, NewFrameEventArgs eventArgs ) - { - // get new frame - Bitmap bitmap = eventArgs.Frame; - // process the frame - } - - - - Not connected to SRV-1. Connect to SRV-1 robot/camera - before using this method. - - - - - Enqueue communication request. - - - Array of bytes (command) to send to SRV-1 Blackfin robot/camera. - - The method puts specified command into communication queue and leaves - immediately. Once internal communication thread becomes free from sending/receiving previous - commands/replies, it will send the queued command. - - The method is useful for those SRV-1 commands, which does not assume any response data - in the command's reply. - - Since the method only queues a communication request, it does not provide any status - of request's delivery and it does not generate any exceptions on failure. - - - - - - Enqueue communication request and wait for reply. - - - Array of bytes (command) to send to SRV-1 Blackfin robot/camera. - Buffer to read response into. - - Returns total bytes read into the response buffer. - - The method puts specified command into communication queue and waits until - the command is sent to SRV-1 Blackfin robot and reply is received. - - If SRV-1 responds with more data than response buffer can fit, then - the response buffer will take all the data it can store, but the rest of response - will be discarded. The only exception is image request - if response buffer is too - small to fit image response, then exception - is thrown. It is user's responsibility to provide response buffer of the correct - size. Check definition of the SRV-1 - Control Protocol for information about supported commands and responses. - - - Not connected to SRV-1. - Connection lost or communicaton failure. - Response buffer is too small. - - - - - Get single image from the SRV-1 Blackfin camera. - - - Returns image received from the SRV-1 Blackfin camera or - if failed decoding provided response. - - The method provides single video frame retrieved from the SRV-1 Blackfin - camera. However in many cases it is required to receive video frames one after another, so - the method is more preferred for continuous video frames. - - Not connected to SRV-1. Connect to SRV-1 before using - this method. - Connection lost or communicaton failure. Try to reconnect. - - - - - Get SRV-1 firmware version string. - - - Returns SRV-1 version string. - - Not connected to SRV-1. Connect to SRV-1 before using - this method. - Connection lost or communicaton failure. Try to reconnect. - - - - - Get SRV-1 running time. - - - Returns SRV-1 running time in milliseconds. - - Not connected to SRV-1. Connect to SRV-1 before using - this method. - Connection lost or communicaton failure. Try to reconnect. - Failed parsing response from SRV-1. - - - - - Run motors connected to SRV-1 robot. - - - Left motor's speed, [-127, 127]. - Right motor's speed, [-127, 127]. - Time duration to run motors measured in number - of 10 milliseconds (0 for infinity), [0, 255]. - - The method provides direct access to motors setting specified, - speed to both motors connected to the SRV-1 robot. The maximum absolute speed - equals to 127, but the sign specifies direction of motor's rotation (forward or backward). - - - The method sends 'Mabc' SRV-1 command (see SRV-1 - Control Protocol), which uses 2nd and 3rd timers for - controlling motors/servos. - - - - - - Stop both motors. - - - The method stops both motors connected to the SRV-1 robot by calling - method specifying 0 for motors' speed. - - - - - Enables fail safe mode - setting motors' speed after timeout. - - - Left motor's speed, [-127, 127]. - Right motor's speed, [-127, 127]. - - In the case if fail safe mode is enabled and no commands are received - by SRV-1 robot withing 2 seconds, motors' speed will be set to the specified values. The command - is very useful to instruct robot to stop if no other commands were sent - within 2 last seconds (probably lost connection). - - - - - Disable fail safe mode. - - - The method disable fail safe mode, which was set using - method. - - - - - Direct servos control of SRV-1 robot. - - - Left servo setting, [0, 100]. - Right servo setting, [0, 100]. - - Servo settings represent timing pulse widths ranging - from 1ms to 2ms. 0 corresponds to a 1ms pulse, 100 corresponds to a 2ms pulse, - and 50 is midrange with a 1.5ms pulse. - - The method sends 'sab' SRV-1 command (see SRV-1 - Control Protocol), which controls 2nd bank of servos - using 6th and 7th timers. - - - - - - Control SRV-1 robot's motors using predefined commands. - - - Motor command to send to the SRV-1 Blackfin robot. - - Controlling SRV-1 motors with this method is only available - after at least one direct motor command is sent, which is done using or - methods. - - - - - Set video quality. - - - Video quality to set, [1, 8]. - - The method sets video quality, which is specified in [1, 8] range - 1 is - the highest quality level, 8 is the lowest quality level. - - Setting higher quality level and resolution - may increase delays for other requests sent to SRV-1. So if - robot is used not only for video, but also for controlling servos/motors, and higher - response level is required, then do not set very high quality and resolution. - - - - Invalid quality level was specified. - - - - - Set video resolution. - - - Video resolution to set. - - - Setting higher quality level and resolution - may increase delays for other requests sent to SRV-1. So if - robot is used not only for video, but also for controlling servos/motors, and higher - response level is required, then do not set very high quality and resolution. - - - - Invalid resolution was specified. - - - - - Flip video capture or not (for use with upside-down camera). - - - Specifies if video should be flipped (), - or not (). - - - - - Ping ultrasonic ranging modules. - - - Returns array of ranges (distances) obtained from ultrasonic sensors. The ranges - are measured in inches. - - The method sends 'p' SRV-1 command (see SRV-1 - Control Protocol), which gets values from ultrasonic ranging modules attached to - pins 27, 28, 29, 30 with trigger on pin 18. Supports Maxbotics EZ0 and EZ1 ultrasonic modules. - - - Not connected to SRV-1. Connect to SRV-1 before using - this method. - Connection lost or communicaton failure. Try to reconnect. - Failed parsing response from SRV-1. - - - - - Read byte from I2C device. - - - I2C device ID (7 bit notation). - I2C device register to read. - - Returns byte read from the specified register of the specified I2C device. - - The IC2 device ID should be specified in 7 bit notation. This means that low bit of the ID - is not used for specifying read/write mode as in 8 bit notation. For example, if I2C device IDs are 0x44 for reading - and 0x45 for writing in 8 bit notation, then it equals to 0x22 device ID in 7 bit notation. - - - Not connected to SRV-1. Connect to SRV-1 before using - this method. - Connection lost or communicaton failure. Try to reconnect. - Failed parsing response from SRV-1. - - - - - Read word from I2C device. - - - I2C device ID (7 bit notation). - I2C device register to read. - - Returns word read from the specified register of the specified I2C device. - - The IC2 device ID should be specified in 7 bit notation. This means that low bit of the ID - is not used for specifying read/write mode as in 8 bit notation. For example, if I2C device IDs are 0x44 for reading - and 0x45 for writing in 8 bit notation, then it equals to 0x22 device ID in 7 bit notation. - - - Not connected to SRV-1. Connect to SRV-1 before using - this method. - Connection lost or communicaton failure. Try to reconnect. - Failed parsing response from SRV-1. - - - - - Write byte to I2C device. - - - I2C device ID (7 bit notation). - I2C device register to write to. - Byte to write to the specified register of the specified device. - - The IC2 device ID should be specified in 7 bit notation. This means that low bit of the ID - is not used for specifying read/write mode as in 8 bit notation. For example, if I2C device IDs are 0x44 for reading - and 0x45 for writing in 8 bit notation, then it equals to 0x22 device ID in 7 bit notation. - - - Not connected to SRV-1. Connect to SRV-1 before using - this method. - Connection lost or communicaton failure. Try to reconnect. - - - - - Write two bytes to I2C device. - - - I2C device ID (7 bit notation). - I2C device register to write to. - First byte to write to the specified register of the specified device. - Second byte to write to the specified register of the specified device. - - The IC2 device ID should be specified in 7 bit notation. This means that low bit of the ID - is not used for specifying read/write mode as in 8 bit notation. For example, if I2C device IDs are 0x44 for reading - and 0x45 for writing in 8 bit notation, then it equals to 0x22 device ID in 7 bit notation. - - - Not connected to SRV-1. Connect to SRV-1 before using - this method. - Connection lost or communicaton failure. Try to reconnect. - - - - - SRV-1 host address. - - - The property keeps SRV-1 IP address if the class is connected - to SRV-1 Blackfin robot/camera, otherwise it equals to . - - - - - SRV-1 port number. - - - The property keeps SRV-1 port number if the class is connected - to SRV-1 Blackfin robot/camera, otherwise it equals to 0. - - - - - Connection state. - - - The property equals to if the class is connected - to SRV-1 Blackfin robot/camera, otherwise it equals to . - - The property is not updated by the class, when connection was lost or - communication failure was detected (which results into - exception). The property only shows status of method. - - - - - - Enumeration of predefined motors' commands. - - - This enumeration defines set of motors' commands, which can - be executed using method. - - Controlling SRV-1 motors with these commands is only possible - after at least one direct motor command is sent, which is done using or - methods. - - The IncreaseSpeed and DecreaseSpeed commands do not have any effect - unless another driving command is sent. In other words, these do not increase/decrease speed of - current operation, but affect speed of all following commands. - - The RotateLeft and RotateRight commands may be useful only for the original - Surveyor SRV-1 Blackfin Robot. - For most of other robots, which may have different motors and moving base, these commands - will not be accurate – will not rotate for 20 degrees. - - - - - - - Robot drive forward. - - - - - Robot drive back. - - - - - Robot drive left. - - - - - Robot drive right. - - - - - Robot drift left. - - - - - Robot drift right. - - - - - Robot stop. - - - - - Robot drive back and right. - - - - - Robot drive back and left. - - - - - Robot rotate left 20 degrees. - - - - - - Robot rotate right 20 degrees. - - - - - - Increase motors' speed. - - - - - - Decrease motors' speed. - - - - - - Enumeration of Surveyor SRV-1 Blackfin cameras resolutions. - - - - - 160x120 - - - - - 320x240 - - - - - 640x480 - - - - - 1280x1024 - - - - - Provides access to video stream from Surveyor SRV-1 Blackfin camera. - - - The class allows to continuously receive video frames from - Surveyor SRV-1 Blackfin camera. It creates a background thread and periodically requests - new video frames from SRV-1 robot/camera, which are provided to user through - event. The video frame rate can be configured using - property, which sets time interval between frames. - - In order to get instance of this class, use - or methods. - - Sample usage: - - // get SRV-1 camera - SRV1Camera camera = srv.GetCamera( ); - // in the case you work with Surveyor SVS board - // the next line can be use - // SRV1Camera camera = svs.GetCamera( SVS.Camera.Left ); - - // set NewFrame event handler - camera.NewFrame += new NewFrameEventHandler( video_NewFrame ); - // start the video source - camera.Start( ); - // ... - - private void video_NewFrame( object sender, NewFrameEventArgs eventArgs ) - { - // get new frame - Bitmap bitmap = eventArgs.Frame; - // process the frame - } - - - - - - - Start video source. - - - Starts video source and return execution to caller. Video source - object creates background thread and notifies about new frames with the - help of event. - - Not connected to SRV-1. Connection to SRV-1 - was closed using method. New - instance must be obtained using or - methods. - - - - - - Signal video source to stop its work. - - - Signals video source to stop its background thread, stop to - provide new frames and free resources. - - - - - Wait for video source has stopped. - - - Waits for video source stopping after it was signalled to stop using - method. - - - - - Stop video source. - - - Stops video source aborting its thread. - - Since the method aborts background thread, its usage is highly not preferred - and should be done only if there are no other options. The correct way of stopping camera - is signaling it to stop and then - waiting for background thread's completion. - - - - - - Free resource. - - - - - - Set video quality. - - - Video quality to set, [1, 8]. - - The method sets video quality, which is specified in [1, 8] range - 1 is - the highest quality level, 8 is the lowest quality level. - - Setting higher quality level and resolution - may increase delays for other requests processed by class. So if - robot is used not only for video, but also for controlling servos/motors, and higher - response level is required, then do not set very high quality and resolution. - - - - Invalid quality level was specified. - - - - - Set video resolution. - - - Video resolution to set. - - - Setting higher quality level and resolution - may increase delays for other requests processed by class. So if - robot is used not only for video, but also for controlling servos/motors, and higher - response level is required, then do not set very high quality and resolution. - - - - - - - Flip video capture or not (for use with upside-down camera). - - - Specifies if video should be flipped (), - or not (). - - - - - Worker thread. - - - - - - New frame event. - - - Notifies clients about new available frame from video source. - - Since video source may have multiple clients, each client is responsible for - making a copy (cloning) of the passed video frame, because the video source disposes its - own original copy after notifying of clients. - - - - - - Video source error event. - - - This event is used to notify clients about any type of errors occurred in - video source object, for example internal exceptions. - - - - - Video playing finished event. - - - This event is used to notify clients that the video playing has finished. - - - - - - Frame interval. - - - The property sets the interval in milliseconds betwen frames. If the property is - set to 100, then the desired frame rate will be 10 frames per second. - - Default value is set to 0 - get new frames as fast as possible. - - - - - - Video source string. - - - - The property keeps connection string, which was used to connect to SRV-1 Blackfin camera. - - - - - - Received frames count. - - - Number of frames the video source provided from the moment of the last - access to the property. - - - - - - Received bytes count. - - - Number of bytes the video source provided from the moment of the last - access to the property. - - - - - - State of the video source. - - - Current state of video source object - running or not. - - - - diff --git a/Externals/AForge.NET/AForge.Robotics.TeRK.dll b/Externals/AForge.NET/AForge.Robotics.TeRK.dll deleted file mode 100644 index 184c0ffbc..0000000000 Binary files a/Externals/AForge.NET/AForge.Robotics.TeRK.dll and /dev/null differ diff --git a/Externals/AForge.NET/AForge.Robotics.TeRK.xml b/Externals/AForge.NET/AForge.Robotics.TeRK.xml deleted file mode 100644 index cf9173466..0000000000 --- a/Externals/AForge.NET/AForge.Robotics.TeRK.xml +++ /dev/null @@ -1,1025 +0,0 @@ - - - - AForge.Robotics.TeRK - - - - - Manipulation of Qwerk robotics board. - - - - The class allows to manipulate with Qwerk robotics board developed by - Charmed Labs and supported by - TeRK project. Using this class it is - possible to get access to different Qwerk's services, like digital inputs and outputs, - motors and servos, analog inputs, on-board LEDs, video camera, etc. - - - - Since TeRK project, which is the software core of Qwerk board, is - based on Internet Communication Engine (ICE), - the ICE runtime should be installed in order to use Qwerk classes. - - The class is deprecated. - - Sample usage: - - Qwerk qwerk = new Qwerk( ); - // connect to Qwerk - qwerk.Connect( "192.168.0.5" ); - // turn off all on-board LEDs - qwerk.GetLedsService( ).SetLedsState( Qwerk.LedState.Off ); - // get digital output service - Qwerk.DigitalOut outputs = qwerk.GetDigitalOutService( ); - // set all digital outputs to disabled state - outputs.SetOutputs( false ); - // enable zero output - outputs.SetOutput( 0, true ); - // get state of all analog inputs - short[] inputs = qwerk.GetAnalogInService( ).GetInputs( ); - // get state of all digital inputs - bool[] inputs = qwerk.GetDigitalInService( ).GetInputs( ); - - - - - - - Initializes a new instance of the class. - - - - - - Connect to Qwerk. - - - Qwerk's address or host name to connect to. - - Failed connecting to Qwerk. - Failed accessing to the requested service, - which may be due to the fact that something is wrong with Qwerk device or connection - was initiated not with Qwerk. - - - - - Disconnect from Qwerk device. - - - - - - Get Qwerk's LEDs service. - - - Returns Qwerk's LEDs service. - - For the list of possible exceptions, see documentation to - . - - - - - Get Qwerk's digital outputs service. - - - Returns Qwerk's digital outputs service. - - For the list of possible exceptions, see documentation to - . - - - - - Get Qwerk's digital inputs service. - - - Returns Qwerk's digital inputs service. - - For the list of possible exceptions, see documentation to - . - - - - - Get Qwerk's analog inputs service. - - - Returns Qwerk's analog inputs service. - - For the list of possible exceptions, see documentation to - . - - - - - Get Qwerk's video service. - - - Returns Qwerk's video service. - - For the list of possible exceptions, see documentation to - . - - - - - Get Qwerk's motors service. - - - Returns Qwerk's motors service. - - For the list of possible exceptions, see documentation to - . - - - - - Get Qwerk's servos service. - - - Returns Qwerk's servos service. - - For the list of possible exceptions, see documentation to - . - - - - - Get Qwerk's power level. - - - Returns Qwerk's power level in millivolts. - - Connestion to Qwerk is lost. - - - - - Qwerk's host address. - - - The property keeps Qwerk's host address if the class is connected - to Qwerk board, otherwise it equals to . - - - - - Connection state. - - - The property equals to if the class is connected - to Qwerk board, otherwise it equals to . - - - - - Provides access to Qwerk's servos' controllers. - - - The class allows to manipulate Qwerk's servos. The total number - of available servos equals to . - - Each servo has logical and physical positions, which may or may not be equal. - Both positions may vary in the [0, 255] range. Physical and logical positions are - equal, when servo's physical moving bound (range) is set to [0, 255] (see ). - In this case setting servo's logical position with method results - in servo's physical moving in the [0, 255] range. However, of physical bound is set - to [10, 20], for example, then physically the servo will move only in this range. But logical - position is still may be set in [0, 255] range, which is mapped to physical range. - - The class is deprecated. - - Sample usage: - - // get Qwerk's servos service - Qwerk.Servos servos = qwerk.GetServosService( ); - // stop all servos - servos.StopServos( ); - // set 0th servo's bounds - servos.SetBound( 0, new IntRange( 10, 100 ) ); - // set servo's position - servos.SetPosition( 0, 50 ); - // ... - - // get 0th servo's position - int currentPosition = servos.GetPosition( 0 ); - - - - - - - Number of available servos' controllers, 16. - - - - - Initializes a new instance of the class. - - - Reference to object, which is connected to Qwerk board. - - The passed reference to object is not connected to - Qwerk board. - Failed connecting to the requested service. - Failed accessing to the requested service. - - - - - Stop specified servo. - - - Servo to stop, [0, ). - - Returns current position of the specified servo. - - Invalid servo is specified. - No connection to Qwerk or its service. - Connestion to Qwerk is lost. - - - - - Stop all servos. - - - Returns array of current servos' positions. - - No connection to Qwerk or its service. - Connestion to Qwerk is lost. - - - - - Stop specified servos. - - - Mask array specifying which servos need to stop. - - Returns array of current servos' positions. - - The array specifies - which Qwerk's servo need to be stopped. If value of the - array is set to , then corresponding servo is stopped. - - - Incorrect length of array. - No connection to Qwerk or its service. - Connestion to Qwerk is lost. - - - - - Set position of a single servo. - - - Servo to set position for, [0, ). - Position to set for the specified servo, [0, 255]. - - Returns current position of the specified servo. - - The method sets position of single Qwerk's servo, which index is - specified. It is preferred to use for setting positions - of multiple servos, which does it at once. - - Invalid servo is specified. - No connection to Qwerk or its service. - Connestion to Qwerk is lost. - - - - - Set positions of specified servos. - - - Mask array specifying which servos need to be set. - Array of servos' positions to set. Each position is in [0, 255] range. - - Returns array of current servos' positions. - - The and arrays specify - which Qwerk's servo's state should be updated. If value of the - array is set to , then corresponding servo's state is changed to the state, - which is specified in array. - - - Incorrect length of or - array. - No connection to Qwerk or its service. - Connestion to Qwerk is lost. - - - - - Get current position of a single servo. - - - Servo to get position for, [0, ). - - Returns current position of the specified servo. - - Invalid servo is specified. - No connection to Qwerk or its service. - Connestion to Qwerk is lost. - - - - - Get current positions of all servos. - - - Returns array of current servos' positions. - - No connection to Qwerk or its service. - Connestion to Qwerk is lost. - - - - - Set bounds for the specified servo. - - - Servo to set bounds for, [0, ). - Bounds to set for the specified servo. - - The method sets servo's physical bounds in which it may move. - See documentation to for clarification. - - Invalid servo is specified. - No connection to Qwerk or its service. - Connestion to Qwerk is lost. - - - - - Set bounds for specified servos. - - - Mask array specifying which servos need to be set. - Array of servos' bounds. Each bound may be in [0, 255] range. - - The method sets servos' physical bounds in which they may move. - See documentation to for clarification. - - Incorrect length of , - or array. - No connection to Qwerk or its service. - Connestion to Qwerk is lost. - - - - - Get bounds for the specified servo. - - - Servo to get bounds for, [0, ). - - Returns configured bounds of the specified servo. - - Invalid servo is specified. - No connection to Qwerk or its service. - Connestion to Qwerk is lost. - - - - - Get bounds of all servos. - - - Returns array of configured servos' bounds. - - No connection to Qwerk or its service. - Connestion to Qwerk is lost. - - - - - Provides access to web camera connected to Qwerk. - - - The class allows to start Qwerk's camera and continuously receive - frames from it. The class creates background thread to poll Qwerk's camera and provides - them through event. The video frame rate can be configured - using property, which sets time interval between frames. - - The class is deprecated. - - Sample usage: - - // get Qwerk's video service - Qwerk.Video video = qwerk.GetVideoService( ); - // set NewFrame event handler - video.NewFrame += new NewFrameEventHandler( video_NewFrame ); - // start the video source - video.Start( ); - // ... - // signal to stop - video.SignalToStop( ); - // ... - - private void video_NewFrame( object sender, NewFrameEventArgs eventArgs ) - { - // get new frame - Bitmap bitmap = eventArgs.Frame; - // process the frame - } - - - - - - - Initializes a new instance of the class. - - - Reference to object, which is connected to Qwerk board. - - The passed reference to object is not connected to - Qwerk board. - Failed connecting to the requested service. - Failed accessing to the requested service. - - - - - Start video source. - - - Starts video source and return execution to caller. Video source - object creates background thread and notifies about new frames with the - help of event. - - - - - Signal video source to stop its work. - - - Signals video source to stop its background thread, stop to - provide new frames and free resources. - - - - - Wait for video source has stopped. - - - Waits for video source stopping after it was signalled to stop using - method. - - - - - Stop video source. - - - Stops video source aborting its thread. - - Since the method aborts background thread, its usage is highly not preferred - and should be done only if there are no other options. The correct way of stopping camera - is signaling it stop and then - waiting for background thread's completion. - - - - - - Free resource. - - - - - - Worker thread. - - - - - - New frame event. - - - Notifies clients about new available frame from video source. - - Since video source may have multiple clients, each client is responsible for - making a copy (cloning) of the passed video frame, because the video source disposes its - own original copy after notifying of clients. - - - - - - Video source error event. - - - This event is used to notify clients about any type of errors occurred in - video source object, for example internal exceptions. - - - - - Video playing finished event. - - - This event is used to notify clients that the video playing has finished. - - - - - - Frame interval. - - - The property sets the interval in milliseconds betwen frames. If the property is - set to 100, then the desired frame rate will be 10 frames per second. - - Default value is set to 0 - get new frames as fast as possible. - - - - - - Video source string. - - - - The property keeps connection string, which is used to connect to TeRK's video - streaming service. - - - - - - Received frames count. - - - Number of frames the video source provided from the moment of the last - access to the property. - - - - - - Received bytes count. - - - Number of bytes the video source provided from the moment of the last - access to the property. - - - - - - State of the video source. - - - Current state of video source object - running or not. - - - - - Enumeration of Qwerk's LEDs' states. - - - - - LED is off. - - - - - LED is on. - - - - - LES is on and blinking. - - - - - Provides access to Qwerk's on-board LEDs. - - - The class allows to manipulate Qwerk's on-boar LED's. The total number - of available on-board LEDs equals to . - - The class is deprecated. - - Sample usage: - - // get Qwerk's LEDs service - Qwerk.Leds leds = qwerk.GetLedsService( ); - // turn off all LEDs - leds.SetLedsState( Qwerk.LedState.Off ); - // set zero LED to blinking state - leds.SetLedState( 0, Qwerk.LedState.Blinking ); - // turn on 4th and 5th LEDs - bool[] mask = new bool[10] { - false, false, false, false, true, - true, false, false, false, false }; - Qwerk.LedState[] states = new Qwerk.LedState[10] { - Qwerk.LedState.Off, Qwerk.LedState.Off, Qwerk.LedState.Off, - Qwerk.LedState.Off, Qwerk.LedState.On, Qwerk.LedState.On, - Qwerk.LedState.Off, Qwerk.LedState.Off, Qwerk.LedState.Off, - Qwerk.LedState.Off }; - leds.SetLedsState( mask, states ); - - - - - - - Number of available on-board LEDs, 10. - - - - - Initializes a new instance of the class. - - - Reference to object, which is connected to Qwerk board. - - The passed reference to object is not connected to - Qwerk board. - Failed connecting to the requested service. - Failed accessing to the requested service. - - - - - Set state of specified LED. - - - LED to set state for, [0, ). - LED's state to set. - - The method sets state of one of Qwerk's LEDs, which index is specified. - - Invalid LED is specified. - No connection to Qwerk or its service. - Connestion to Qwerk is lost. - - - - - Set state of all LEDs. - - - State, which will be set to all LEDs. - - The method sets the same state to all Qwerk's on-board LEDs. - - No connection to Qwerk or its service. - Connestion to Qwerk is lost. - - - - - Set state of all LEDs. - - - Mask array specifying which LED's state need to be set. - Array of LEDs' states. - - The and arrays specify - which Qwerk's on-board LED's state should be updated. If value of the - array is set to , then corresponding LED's state is changed to the state, - which is specified in array. - - - Incorrect length of LEDs' masks or states array. - No connection to Qwerk or its service. - Connestion to Qwerk is lost. - - - - - Provides access to Qwerk's digital outputs. - - - The class allows to manipulate Qwerk's digital outputs. The total number - of available digital outputs equals to . - - The class is deprecated. - - Sample usage: - - // get Qwerk's digital outs service - Qwerk.DigitalOut digitalOuts = qwerk.GetDigitalOutService( ); - // disbale all outputs - digitalOuts.SetOutputs( false ); - // enable zero output - digitalOuts.SetOutput( 0, true ); - // enable 2nd and 3rd outputs - bool[] mask = new bool[4] { false, false, true, true }; - bool[] states = new bool[4] { false, false, true, true }; - digitalOuts.SetOutputs( mask, states ); - - - - - - - Number of available digital outputs, 4. - - - - - Initializes a new instance of the class. - - - Reference to object, which is connected to Qwerk board. - - The passed reference to object is not connected to - Qwerk board. - Failed connecting to the requested service. - Failed accessing to the requested service. - - - - - Set state of specified digital output. - - - Digital output to state for, [0, ). - Digital output's state to set. - - The method sets state of one of Qwerk's digital outputs, which index is - specified. The output is either enabled (state is set to or - disabled otherwise. - - Invalid output is specified. - No connection to Qwerk or its service. - Connestion to Qwerk is lost. - - - - - Set state of all digital outputs. - - - State, which will be set to all digital outputs. - - The method sets the same state to all Qwerk's digital outputs. - - No connection to Qwerk or its service. - Connestion to Qwerk is lost. - - - - - Set state of all digital outputs. - - - Mask array specifying which output's state need to be set. - Array of outputs' states. - - The and arrays specify - which Qwerk's digital output's state should be updated. If value of the - array is set to , then corresponding output's state is changed to the state, - which is specified in array. - - - Incorrect length of outputs' masks or states array. - No connection to Qwerk or its service. - Connestion to Qwerk is lost. - - - - - Provides access to Qwerk's motors' controllers. - - - The class allows to manipulate Qwerk's motors. The total number - of available motors equals to . - - The class is deprecated. - - Sample usage: - - // get Qwerk's motors service - Qwerk.Motors motors = qwerk.GetMotorsService( ); - // stop all motors - motors.StopMotors( ); - // run first motor - motors.SetMotorVelocity( 0, 10000 ); - - - - - - - Number of available motors' controllers, 4. - - - - - Initializes a new instance of the class. - - - Reference to object, which is connected to Qwerk board. - - The passed reference to object is not connected to - Qwerk board. - Failed connecting to the requested service. - Failed accessing to the requested service. - - - - - Stop specified motor. - - - Motor to stop, [0, ). - - Invalid motor is specified. - No connection to Qwerk or its service. - Connestion to Qwerk is lost. - - - - - Stop all motors. - - - No connection to Qwerk or its service. - Connestion to Qwerk is lost. - - - - - Set velocity of specified motor. - - - Motor to set velocity for, [0, ). - Velocity to set. - - The method sets specified motor's velocity, which is measured in - ticks per second. "Ticks" is a made-up term, which does not depend on specific motor, - but is an unknown in distance and rotation (see Qwerk documentation for details). - - Invalid motor is specified. - No connection to Qwerk or its service. - Connestion to Qwerk is lost. - - - - - Provides access to Qwerk's digital inputs. - - - The class allows to retrieve state of Qwerk's digital inputs. The total - number of available digital inputs equals to . - - The class is deprecated. - - Sample usage: - - // get Qwerk's digital inputs service - Qwerk.DigitalIn digitalIns = qwerk.GetDigitalInService( ); - // get state of 0th input - bool input0 = digitalIns.GetInput( 0 ); - // get state of all inputs - bool[] inputs = digitalIns.GetInputs( ); - - - - - - - Number of available digital inputs, 4. - - - - - Initializes a new instance of the class. - - - Reference to object, which is connected to Qwerk board. - - The passed reference to object is not connected to - Qwerk board. - Failed connecting to the requested service. - Failed accessing to the requested service. - - - - - Get state of the specified digital input. - - - Digital input to get state of, [0, ). - - Returns state of the requested input as boolean values - active/inactive. - - In the case if multiply inputs should be queried, it is much - preferred to use method, which retrieves state of all - inputs at once. - - Invalid input is specified. - Connestion to Qwerk is lost. - - - - - Get state of all available digital inputs. - - - Returns state of all digital inputs as boolean values - active/inactive. - - Connestion to Qwerk is lost. - - - - - Provides access to Qwerk's analog inputs. - - - The class allows to retrieve state of Qwerk's analog inputs. The total - number of available analog inputs equals to . - - The class is deprecated. - - Sample usage: - - // get Qwerk's analog inputs service - Qwerk.AnalogIn analogIns = qwerk.GetAnalogInService( ); - // get state of 0th input - short input0 = analogIns.GetInput( 0 ); - // get state of all inputs - short[] inputs = analogIns.GetInputs( ); - - - - - - - Number of available analog inputs, 8. - - - - - Initializes a new instance of the class. - - - Reference to object, which is connected to Qwerk board. - - The passed reference to object is not connected to - Qwerk board. - Failed connecting to the requested service. - Failed accessing to the requested service. - - - - - Get state of the specified analog input. - - - Analog input to get state of, [0, ). - - Returns state of the requested input measured in milli volts. - - In the case if multiply inputs should be queried, it is much - preferred to use method, which retrieves state of all - inputs at once. - - Invalid input is specified. - Connestion to Qwerk is lost. - - - - - Get state of all available analog inputs. - - - Returns state of all analog inputs measured in milli volts. - - Connestion to Qwerk is lost. - - - - - Service access failed exception. - - - The excetion is thrown in the case if the requested service can not - be accessed or does not exist on the Qwerk's board. - - - - - - Initializes a new instance of the class. - - - Exception's message. - - - - diff --git a/Externals/AForge.NET/AForge.Video.DirectShow.dll b/Externals/AForge.NET/AForge.Video.DirectShow.dll deleted file mode 100644 index e3f806f34..0000000000 Binary files a/Externals/AForge.NET/AForge.Video.DirectShow.dll and /dev/null differ diff --git a/Externals/AForge.NET/AForge.Video.DirectShow.xml b/Externals/AForge.NET/AForge.Video.DirectShow.xml deleted file mode 100644 index 5d62c107e..0000000000 --- a/Externals/AForge.NET/AForge.Video.DirectShow.xml +++ /dev/null @@ -1,4108 +0,0 @@ - - - - AForge.Video.DirectShow - - - - - A strongly-typed resource class, for looking up localized strings, etc. - - - - - Returns the cached ResourceManager instance used by this class. - - - - - Overrides the current thread's CurrentUICulture property for all - resource lookups using this strongly typed resource class. - - - - - This interface is exposed by all input and output pins of DirectShow filters. - - - - - - Connects the pin to another pin. - - - Other pin to connect to. - Type to use for the connections (optional). - - Return's HRESULT error code. - - - - - Makes a connection to this pin and is called by a connecting pin. - - - Connecting pin. - Media type of the samples to be streamed. - - Return's HRESULT error code. - - - - - Breaks the current pin connection. - - - Return's HRESULT error code. - - - - - Returns a pointer to the connecting pin. - - - Receives IPin interface of connected pin (if any). - - Return's HRESULT error code. - - - - - Returns the media type of this pin's connection. - - - Pointer to an structure. If the pin is connected, - the media type is returned. Otherwise, the structure is initialized to a default state in which - all elements are 0, with the exception of lSampleSize, which is set to 1, and - FixedSizeSamples, which is set to true. - - Return's HRESULT error code. - - - - - Retrieves information about this pin (for example, the name, owning filter, and direction). - - - structure that receives the pin information. - - Return's HRESULT error code. - - - - - Retrieves the direction for this pin. - - - Receives direction of the pin. - - Return's HRESULT error code. - - - - - Retrieves an identifier for the pin. - - - Pin identifier. - - Return's HRESULT error code. - - - - - Queries whether a given media type is acceptable by the pin. - - - structure that specifies the media type. - - Return's HRESULT error code. - - - - - Provides an enumerator for this pin's preferred media types. - - - Address of a variable that receives a pointer to the IEnumMediaTypes interface. - - Return's HRESULT error code. - - - - - Provides an array of the pins to which this pin internally connects. - - - Address of an array of IPin pointers. - On input, specifies the size of the array. When the method returns, - the value is set to the number of pointers returned in the array. - - Return's HRESULT error code. - - - - - Notifies the pin that no additional data is expected. - - - Return's HRESULT error code. - - - - - Begins a flush operation. - - - Return's HRESULT error code. - - - - - Ends a flush operation. - - - Return's HRESULT error code. - - - - - Specifies that samples following this call are grouped as a segment with a given start time, stop time, and rate. - - - Start time of the segment, relative to the original source, in 100-nanosecond units. - End time of the segment, relative to the original source, in 100-nanosecond units. - Rate at which this segment should be processed, as a percentage of the original rate. - - Return's HRESULT error code. - - - - - The interface provides methods for building a filter graph. An application can use it to add filters to - the graph, connect or disconnect filters, remove filters, and perform other basic operations. - - - - - - Adds a filter to the graph and gives it a name. - - - Filter to add to the graph. - Name of the filter. - - Return's HRESULT error code. - - - - - Removes a filter from the graph. - - - Filter to be removed from the graph. - - Return's HRESULT error code. - - - - - Provides an enumerator for all filters in the graph. - - - Filter enumerator. - - Return's HRESULT error code. - - - - - Finds a filter that was added with a specified name. - - - Name of filter to search for. - Interface of found filter. - - Return's HRESULT error code. - - - - - Connects two pins directly (without intervening filters). - - - Output pin. - Input pin. - Media type to use for the connection. - - Return's HRESULT error code. - - - - - Breaks the existing pin connection and reconnects it to the same pin. - - - Pin to disconnect and reconnect. - - Return's HRESULT error code. - - - - - Disconnects a specified pin. - - - Pin to disconnect. - - Return's HRESULT error code. - - - - - Sets the reference clock to the default clock. - - - Return's HRESULT error code. - - - - - The interface is exposed by source filters to set the file name and media type of the media file that they are to render. - - - - - - Loads the source filter with the file. - - - The name of the file to open. - Media type of the file. This can be null. - - Return's HRESULT error code. - - - - - Retrieves the current file. - - - Name of media file. - Receives media type. - - Return's HRESULT error code. - - - - - The interface controls certain video capture operations such as enumerating available - frame rates and image orientation. - - - - - - Retrieves the capabilities of the underlying hardware. - - - Pin to query capabilities from. - Get capabilities of the specified pin. - - Return's HRESULT error code. - - - - - Sets the video control mode of operation. - - - The pin to set the video control mode on. - Value specifying a combination of the flags to set the video control mode. - - Return's HRESULT error code. - - - - - Retrieves the video control mode of operation. - - - The pin to retrieve the video control mode from. - Gets combination of flags, which specify the video control mode. - - Return's HRESULT error code. - - - - - The method retrieves the actual frame rate, expressed as a frame duration in 100-nanosecond units. - USB (Universal Serial Bus) and IEEE 1394 cameras may provide lower frame rates than requested - because of bandwidth availability. This is only available during video streaming. - - - The pin to retrieve the frame rate from. - Gets frame rate in frame duration in 100-nanosecond units. - - Return's HRESULT error code. - - - - - Retrieves the maximum frame rate currently available based on bus bandwidth usage for connections - such as USB and IEEE 1394 camera devices where the maximum frame rate can be limited by bandwidth - availability. - - - The pin to retrieve the maximum frame rate from. - Index of the format to query for maximum frame rate. This index corresponds - to the order in which formats are enumerated by . - Frame image size (width and height) in pixels. - Gets maximum available frame rate. The frame rate is expressed as frame duration in 100-nanosecond units. - - Return's HRESULT error code. - - - - - Retrieves a list of available frame rates. - - - The pin to retrieve the maximum frame rate from. - Index of the format to query for maximum frame rate. This index corresponds - to the order in which formats are enumerated by . - Frame image size (width and height) in pixels. - Number of elements in the list of frame rates. - Array of frame rates in 100-nanosecond units. - - Return's HRESULT error code. - - - - - DirectShow filter categories. - - - - - Audio input device category. - - - Equals to CLSID_AudioInputDeviceCategory. - - - - - Video input device category. - - - Equals to CLSID_VideoInputDeviceCategory. - - - - - Video compressor category. - - - Equals to CLSID_VideoCompressorCategory. - - - - - Audio compressor category - - - Equals to CLSID_AudioCompressorCategory. - - - - - Provides the CLSID of an object that can be stored persistently in the system. Allows the object to specify which object - handler to use in the client process, as it is used in the default implementation of marshaling. - - - - - Retrieves the class identifier (CLSID) of the object. - - - - - - - The IAMCameraControl interface controls camera settings such as zoom, pan, aperture adjustment, - or shutter speed. To obtain this interface, query the filter that controls the camera. - - - - - Gets the range and default value of a specified camera property. - - - Specifies the property to query. - Receives the minimum value of the property. - Receives the maximum value of the property. - Receives the step size for the property. - Receives the default value of the property. - Receives a member of the CameraControlFlags enumeration, indicating whether the property is controlled automatically or manually. - - Return's HRESULT error code. - - - - - Sets a specified property on the camera. - - - Specifies the property to set. - Specifies the new value of the property. - Specifies the desired control setting, as a member of the CameraControlFlags enumeration. - - Return's HRESULT error code. - - - - - Gets the current setting of a camera property. - - - Specifies the property to retrieve. - Receives the value of the property. - Receives a member of the CameraControlFlags enumeration. - The returned value indicates whether the setting is controlled manually or automatically. - - Return's HRESULT error code. - - - - - Capabilities of video device such as frame size and frame rate. - - - - - Frame size supported by video device. - - - - - Average frame rate of video device for corresponding frame size. - - - - - Maximum frame rate of video device for corresponding frame size. - - - - - Number of bits per pixel provided by the camera. - - - - - Check if the video capability equals to the specified object. - - - Object to compare with. - - Returns true if both are equal are equal or false otherwise. - - - - - Check if two video capabilities are equal. - - - Second video capability to compare with. - - Returns true if both video capabilities are equal or false otherwise. - - - - - Get hash code of the object. - - - Returns hash code ot the object - - - - Equality operator. - - - First object to check. - Seconds object to check. - - Return true if both objects are equal or false otherwise. - - - - Inequality operator. - - - First object to check. - Seconds object to check. - - Return true if both objects are not equal or false otherwise. - - - - Frame rate supported by video device for corresponding frame size. - - - This field is depricated - should not be used. - Its value equals to . - - - - - - Specifies the physical type of pin (audio or video). - - - - - Default value of connection type. Physically it does not exist, but just either to specify that - connection type should not be changed (input) or was not determined (output). - - - - - Specifies a tuner pin for video. - - - - - Specifies a composite pin for video. - - - - - Specifies an S-Video (Y/C video) pin. - - - - - Specifies an RGB pin for video. - - - - - Specifies a YRYBY (Y, R–Y, B–Y) pin for video. - - - - - Specifies a serial digital pin for video. - - - - - Specifies a parallel digital pin for video. - - - - - Specifies a SCSI (Small Computer System Interface) pin for video. - - - - - Specifies an AUX (auxiliary) pin for video. - - - - - Specifies an IEEE 1394 pin for video. - - - - - Specifies a USB (Universal Serial Bus) pin for video. - - - - - Specifies a video decoder pin. - - - - - Specifies a video encoder pin. - - - - - Specifies a SCART (Peritel) pin for video. - - - - - Not used. - - - - - Specifies a tuner pin for audio. - - - - - Specifies a line pin for audio. - - - - - Specifies a microphone pin. - - - - - Specifies an AES/EBU (Audio Engineering Society/European Broadcast Union) digital pin for audio. - - - - - Specifies an S/PDIF (Sony/Philips Digital Interface Format) digital pin for audio. - - - - - Specifies a SCSI pin for audio. - - - - - Specifies an AUX pin for audio. - - - - - Specifies an IEEE 1394 pin for audio. - - - - - Specifies a USB pin for audio. - - - - - Specifies an audio decoder pin. - - - - - This enumeration indicates a pin's direction. - - - - - - Input pin. - - - - - Output pin. - - - - - The structure describes the format of a media sample. - - - - - - Globally unique identifier (GUID) that specifies the major type of the media sample. - - - - - GUID that specifies the subtype of the media sample. - - - - - If true, samples are of a fixed size. - - - - - If true, samples are compressed using temporal (interframe) compression. - - - - - Size of the sample in bytes. For compressed data, the value can be zero. - - - - - GUID that specifies the structure used for the format block. - - - - - Not used. - - - - - Size of the format block, in bytes. - - - - - Pointer to the format block. - - - - - Destroys the instance of the class. - - - - - - Dispose the object. - - - - - - Dispose the object - - - Indicates if disposing was initiated manually. - - - - - The structure contains information about a pin. - - - - - - Owning filter. - - - - - Direction of the pin. - - - - - Name of the pin. - - - - - Filter's name. - - - - - Owning graph. - - - - - The structure describes the bitmap and color information for a video image. - - - - - - structure that specifies the source video window. - - - - - structure that specifies the destination video window. - - - - - Approximate data rate of the video stream, in bits per second. - - - - - Data error rate, in bit errors per second. - - - - - The desired average display time of the video frames, in 100-nanosecond units. - - - - - structure that contains color and dimension information for the video image bitmap. - - - - - The structure describes the bitmap and color information for a video image (v2). - - - - - - structure that specifies the source video window. - - - - - structure that specifies the destination video window. - - - - - Approximate data rate of the video stream, in bits per second. - - - - - Data error rate, in bit errors per second. - - - - - The desired average display time of the video frames, in 100-nanosecond units. - - - - - Flags that specify how the video is interlaced. - - - - - Flag set to indicate that the duplication of the stream should be restricted. - - - - - The X dimension of picture aspect ratio. - - - - - The Y dimension of picture aspect ratio. - - - - - Reserved for future use. - - - - - Reserved for future use. - - - - - structure that contains color and dimension information for the video image bitmap. - - - - - The structure contains information about the dimensions and color format of a device-independent bitmap (DIB). - - - - - - Specifies the number of bytes required by the structure. - - - - - Specifies the width of the bitmap. - - - - - Specifies the height of the bitmap, in pixels. - - - - - Specifies the number of planes for the target device. This value must be set to 1. - - - - - Specifies the number of bits per pixel. - - - - - If the bitmap is compressed, this member is a FOURCC the specifies the compression. - - - - - Specifies the size, in bytes, of the image. - - - - - Specifies the horizontal resolution, in pixels per meter, of the target device for the bitmap. - - - - - Specifies the vertical resolution, in pixels per meter, of the target device for the bitmap. - - - - - Specifies the number of color indices in the color table that are actually used by the bitmap. - - - - - Specifies the number of color indices that are considered important for displaying the bitmap. - - - - - The structure defines the coordinates of the upper-left and lower-right corners of a rectangle. - - - - - - Specifies the x-coordinate of the upper-left corner of the rectangle. - - - - - Specifies the y-coordinate of the upper-left corner of the rectangle. - - - - - Specifies the x-coordinate of the lower-right corner of the rectangle. - - - - - Specifies the y-coordinate of the lower-right corner of the rectangle. - - - - - The CAUUID structure is a Counted Array of UUID or GUID types. - - - - - - Size of the array pointed to by pElems. - - - - - Pointer to an array of UUID values, each of which specifies UUID. - - - - - Performs manual marshaling of pElems to retrieve an array of Guid objects. - - - A managed representation of pElems. - - - - - Enumeration of DirectShow event codes. - - - - - Specifies a filter's state or the state of the filter graph. - - - - - Stopped. The filter is not processing data. - - - - - Paused. The filter is processing data, but not rendering it. - - - - - Running. The filter is processing and rendering data. - - - - - The interface is exposed by the Sample Grabber Filter. It enables an application to retrieve - individual media samples as they move through the filter graph. - - - - - - Specifies whether the filter should stop the graph after receiving one sample. - - - Boolean value specifying whether the filter should stop the graph after receiving one sample. - - Return's HRESULT error code. - - - - - Specifies the media type for the connection on the Sample Grabber's input pin. - - - Specifies the required media type. - - Return's HRESULT error code. - - - - - Retrieves the media type for the connection on the Sample Grabber's input pin. - - - structure, which receives media type. - - Return's HRESULT error code. - - - - - Specifies whether to copy sample data into a buffer as it goes through the filter. - - - Boolean value specifying whether to buffer sample data. - If true, the filter copies sample data into an internal buffer. - - Return's HRESULT error code. - - - - - Retrieves a copy of the sample that the filter received most recently. - - - Pointer to the size of the buffer. If pBuffer is NULL, this parameter receives the required size. - Pointer to a buffer to receive a copy of the sample, or NULL. - - Return's HRESULT error code. - - - - - Not currently implemented. - - - - - Return's HRESULT error code. - - - - - Specifies a callback method to call on incoming samples. - - - interface containing the callback method, or NULL to cancel the callback. - Index specifying the callback method. - - Return's HRESULT error code. - - - - - This interface builds capture graphs and other custom filter graphs. - - - - - - Specify filter graph for the capture graph builder to use. - - - Filter graph's interface. - - Return's HRESULT error code. - - - - - Retrieve the filter graph that the builder is using. - - - Filter graph's interface. - - Return's HRESULT error code. - - - - - Create file writing section of the filter graph. - - - GUID that represents either the media subtype of the output or the - class identifier (CLSID) of a multiplexer filter or file writer filter. - Output file name. - Receives the multiplexer's interface. - Receives the file writer's IFileSinkFilter interface. Can be NULL. - - Return's HRESULT error code. - - - - - Searche the graph for a specified interface, starting from a specified filter. - - - GUID that specifies the search criteria. - GUID that specifies the major media type of an output pin, or NULL. - interface of the filter. The method begins searching from this filter. - Interface identifier (IID) of the interface to locate. - Receives found interface. - - Return's HRESULT error code. - - - - - Connect an output pin on a source filter to a rendering filter, optionally through a compression filter. - - - Pin category. - Major-type GUID that specifies the media type of the output pin. - Starting filter for the connection. - Interface of an intermediate filter, such as a compression filter. Can be NULL. - Sink filter, such as a renderer or mux filter. - - Return's HRESULT error code. - - - - - Set the start and stop times for one or more streams of captured data. - - - Pin category. - Major-type GUID that specifies the media type. - interface that specifies which filter to control. - Start time. - Stop time. - Value that is sent as the second parameter of the - EC_STREAM_CONTROL_STARTED event notification. - Value that is sent as the second parameter of the - EC_STREAM_CONTROL_STOPPED event notification. - - Return's HRESULT error code. - - - - - Preallocate a capture file to a specified size. - - - File name to create or resize. - Size of the file to allocate, in bytes. - - Return's HRESULT error code. - - - - - Copy the valid media data from a capture file. - - - Old file name. - New file name. - Boolean value that specifies whether pressing the ESC key cancels the copy operation. - IAMCopyCaptureFileProgress interface to display progress information, or NULL. - - Return's HRESULT error code. - - - - - - - - Interface on a filter, or to an interface on a pin. - Pin direction (input or output). - Pin category. - Media type. - Boolean value that specifies whether the pin must be unconnected. - Zero-based index of the pin to retrieve, from the set of matching pins. - Interface of the matching pin. - - Return's HRESULT error code. - - - - - This interface provides methods that enable an application to build a filter graph. - - - - - - Adds a filter to the graph and gives it a name. - - - Filter to add to the graph. - Name of the filter. - - Return's HRESULT error code. - - - - - Removes a filter from the graph. - - - Filter to be removed from the graph. - - Return's HRESULT error code. - - - - - Provides an enumerator for all filters in the graph. - - - Filter enumerator. - - Return's HRESULT error code. - - - - - Finds a filter that was added with a specified name. - - - Name of filter to search for. - Interface of found filter. - - Return's HRESULT error code. - - - - - Connects two pins directly (without intervening filters). - - - Output pin. - Input pin. - Media type to use for the connection. - - Return's HRESULT error code. - - - - - Breaks the existing pin connection and reconnects it to the same pin. - - - Pin to disconnect and reconnect. - - Return's HRESULT error code. - - - - - Disconnects a specified pin. - - - Pin to disconnect. - - Return's HRESULT error code. - - - - - Sets the reference clock to the default clock. - - - Return's HRESULT error code. - - - - - Connects two pins. If they will not connect directly, this method connects them with intervening transforms. - - - Output pin. - Input pin. - - Return's HRESULT error code. - - - - - Adds a chain of filters to a specified output pin to render it. - - - Output pin. - - Return's HRESULT error code. - - - - - Builds a filter graph that renders the specified file. - - - Specifies a string that contains file name or device moniker. - Reserved. - - Return's HRESULT error code. - - - - - Adds a source filter to the filter graph for a specific file. - - - Specifies the name of the file to load. - Specifies a name for the source filter. - Variable that receives the interface of the source filter. - - Return's HRESULT error code. - - - - - Sets the file for logging actions taken when attempting to perform an operation. - - - Handle to the log file. - - Return's HRESULT error code. - - - - - Requests that the graph builder return as soon as possible from its current task. - - - Return's HRESULT error code. - - - - - Queries whether the current operation should continue. - - - Return's HRESULT error code. - - - - - The interface provides callback methods for the method. - - - - - - Callback method that receives a pointer to the media sample. - - - Starting time of the sample, in seconds. - Pointer to the sample's IMediaSample interface. - - Return's HRESULT error code. - - - - - Callback method that receives a pointer to the sample bufferю - - - Starting time of the sample, in seconds. - Pointer to a buffer that contains the sample data. - Length of the buffer pointed to by buffer, in bytes - - Return's HRESULT error code. - - - - - Local video device selection form. - - - The form provides a standard way of selecting local video - device (USB web camera, capture board, etc. - anything supporting DirectShow - interface), which can be reused across applications. It allows selecting video - device, video size and snapshots size (if device supports snapshots and - user needs them). - - - - - - - - Required designer variable. - - - - - Clean up any resources being used. - - true if managed resources should be disposed; otherwise, false. - - - - Required method for Designer support - do not modify - the contents of this method with the code editor. - - - - - Initializes a new instance of the class. - - - - - - Specifies if snapshot configuration should be done or not. - - - The property specifies if the dialog form should - allow configuration of snapshot sizes (if selected video source supports - snapshots). If the property is set to , then - the form will provide additional combo box enumerating supported - snapshot sizes. Otherwise the combo boxes will be hidden. - - - If the property is set to and selected - device supports snapshots, then - property of the configured device is set to - . - - Default value of the property is set to . - - - - - - Provides configured video device. - - - The property provides configured video device if user confirmed - the dialog using "OK" button. If user canceled the dialog, the property is - set to . - - - - - Moniker string of the selected video device. - - - The property allows to get moniker string of the selected device - on form completion or set video device which should be selected by default on - form loading. - - - - - Video frame size of the selected device. - - - The property allows to get video size of the selected device - on form completion or set the size to be selected by default on form loading. - - - - - - Snapshot frame size of the selected device. - - - The property allows to get snapshot size of the selected device - on form completion or set the size to be selected by default on form loading - (if property is set ). - - - - - Video input to use with video capture card. - - - The property allows to get video input of the selected device - on form completion or set it to be selected by default on form loading. - - - - - Some miscellaneous functions. - - - - - - Get filter's pin. - - - Filter to get pin of. - Pin's direction. - Pin's number. - - Returns filter's pin. - - - - - Get filter's input pin. - - - Filter to get pin of. - Pin's number. - - Returns filter's pin. - - - - - Get filter's output pin. - - - Filter to get pin of. - Pin's number. - - Returns filter's pin. - - - - - The interface indicates that an object supports property pages. - - - - - - Fills a counted array of GUID values where each GUID specifies the - CLSID of each property page that can be displayed in the property - sheet for this object. - - - Pointer to a CAUUID structure that must be initialized - and filled before returning. - - Return's HRESULT error code. - - - - - Enumerates pins on a filter. - - - - - - Retrieves a specified number of pins. - - - Number of pins to retrieve. - Array of size cPins that is filled with IPin pointers. - Receives the number of pins retrieved. - - Return's HRESULT error code. - - - - - Skips a specified number of pins in the enumeration sequence. - - - Number of pins to skip. - - Return's HRESULT error code. - - - - - Resets the enumeration sequence to the beginning. - - - Return's HRESULT error code. - - - - - Makes a copy of the enumerator with the same enumeration state. - - - Duplicate of the enumerator. - - Return's HRESULT error code. - - - - - This interface sets the output format on certain capture and compression filters, - for both audio and video. - - - - - - Set the output format on the pin. - - - Media type to set. - - Return's HRESULT error code. - - - - - Retrieves the audio or video stream's format. - - - Retrieved media type. - - Return's HRESULT error code. - - - - - Retrieve the number of format capabilities that this pin supports. - - - Variable that receives the number of format capabilities. - Variable that receives the size of the configuration structure in bytes. - - Return's HRESULT error code. - - - - - Retrieve a set of format capabilities. - - - Specifies the format capability to retrieve, indexed from zero. - Retrieved media type. - Byte array, which receives information about capabilities. - - Return's HRESULT error code. - - - - - Collection of filters' information objects. - - - The class allows to enumerate DirectShow filters of specified category. For - a list of categories see . - - Sample usage: - - // enumerate video devices - videoDevices = new FilterInfoCollection( FilterCategory.VideoInputDevice ); - // list devices - foreach ( FilterInfo device in videoDevices ) - { - // ... - } - - - - - - - Initializes a new instance of the class. - - - Guid of DirectShow filter category. See . - - Build collection of filters' information objects for the - specified filter category. - - - - - Get filter information object. - - - Index of filter information object to retrieve. - - Filter information object. - - - - - Video source for local video capture device (for example USB webcam). - - - This video source class captures video data from local video capture device, - like USB web camera (or internal), frame grabber, capture board - anything which - supports DirectShow interface. For devices which has a shutter button or - support external software triggering, the class also allows to do snapshots. Both - video size and snapshot size can be configured. - - Sample usage: - - // enumerate video devices - videoDevices = new FilterInfoCollection( FilterCategory.VideoInputDevice ); - // create video source - VideoCaptureDevice videoSource = new VideoCaptureDevice( videoDevices[0].MonikerString ); - // set NewFrame event handler - videoSource.NewFrame += new NewFrameEventHandler( video_NewFrame ); - // start the video source - videoSource.Start( ); - // ... - // signal to stop when you no longer need capturing - videoSource.SignalToStop( ); - // ... - - private void video_NewFrame( object sender, NewFrameEventArgs eventArgs ) - { - // get new frame - Bitmap bitmap = eventArgs.Frame; - // process the frame - } - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Moniker string of video capture device. - - - - - Start video source. - - - Starts video source and return execution to caller. Video source - object creates background thread and notifies about new frames with the - help of event. - - - - - Signal video source to stop its work. - - - Signals video source to stop its background thread, stop to - provide new frames and free resources. - - - - - Wait for video source has stopped. - - - Waits for source stopping after it was signalled to stop using - method. - - - - - Stop video source. - - - Stops video source aborting its thread. - - Since the method aborts background thread, its usage is highly not preferred - and should be done only if there are no other options. The correct way of stopping camera - is signaling it stop and then - waiting for background thread's completion. - - - - - - Free resource. - - - - - - Display property window for the video capture device providing its configuration - capabilities. - - - Handle of parent window. - - If you pass parent window's handle to this method, then the - displayed property page will become modal window and none of the controls from the - parent window will be accessible. In order to make it modeless it is required - to pass as parent window's handle. - - - - The video source does not support configuration property page. - - - - - Display property page of video crossbar (Analog Video Crossbar filter). - - - Handle of parent window. - - The Analog Video Crossbar filter is modeled after a general switching matrix, - with n inputs and m outputs. For example, a video card might have two external connectors: - a coaxial connector for TV, and an S-video input. These would be represented as input pins on - the filter. The displayed property page allows to configure the crossbar by selecting input - of a video card to use. - - This method can be invoked only when video source is running ( is - ). Otherwise it generates exception. - - Use method to check if running video source provides - crossbar configuration. - - - The video source must be running in order to display crossbar property page. - Crossbar configuration is not supported by currently running video source. - - - - - Check if running video source provides crossbar for configuration. - - - Returns if crossbar configuration is available or - otherwise. - - The method reports if the video source provides crossbar configuration - using . - - - - - - Simulates an external trigger. - - - The method simulates external trigger for video cameras, which support - providing still image snapshots. The effect is equivalent as pressing camera's shutter - button - a snapshot will be provided through event. - - The property must be set to - to enable receiving snapshots. - - - - - - Sets a specified property on the camera. - - - Specifies the property to set. - Specifies the new value of the property. - Specifies the desired control setting. - - Returns true on sucee or false otherwise. - - Video source is not specified - device moniker is not set. - Failed creating device object for moniker. - The video source does not support camera control. - - - - - Gets the current setting of a camera property. - - - Specifies the property to retrieve. - Receives the value of the property. - Receives the value indicating whether the setting is controlled manually or automatically - - Returns true on sucee or false otherwise. - - Video source is not specified - device moniker is not set. - Failed creating device object for moniker. - The video source does not support camera control. - - - - - Gets the range and default value of a specified camera property. - - - Specifies the property to query. - Receives the minimum value of the property. - Receives the maximum value of the property. - Receives the step size for the property. - Receives the default value of the property. - Receives a member of the enumeration, indicating whether the property is controlled automatically or manually. - - Returns true on sucee or false otherwise. - - Video source is not specified - device moniker is not set. - Failed creating device object for moniker. - The video source does not support camera control. - - - - - Worker thread. - - - - - - Notifies clients about new frame. - - - New frame's image. - - - - - Notifies clients about new snapshot frame. - - - New snapshot's image. - - - - - Current video input of capture card. - - - The property specifies video input to use for video devices like capture cards - (those which provide crossbar configuration). List of available video inputs can be obtained - from property. - - To check if the video device supports crossbar configuration, the - method can be used. - - This property can be set as before running video device, as while running it. - - By default this property is set to , which means video input - will not be set when running video device, but currently configured will be used. After video device - is started this property will be updated anyway to tell current video input. - - - - - - Available inputs of the video capture card. - - - The property provides list of video inputs for devices like video capture cards. - Such devices usually provide several video inputs, which can be selected using crossbar. - If video device represented by the object of this class supports crossbar, then this property - will list all video inputs. However if it is a regular USB camera, for example, which does not - provide crossbar configuration, the property will provide zero length array. - - Video input to be used can be selected using . See also - method, which provides crossbar configuration dialog. - - It is recomended not to call this property immediately after method, since - device may not start yet and provide its information. It is better to call the property - before starting device or a bit after (but not immediately after). - - - - - - Specifies if snapshots should be provided or not. - - - Some USB cameras/devices may have a shutter button, which may result into snapshot if it - is pressed. So the property specifies if the video source will try providing snapshots or not - it will - check if the camera supports providing still image snapshots. If camera supports snapshots and the property - is set to , then snapshots will be provided through - event. - - Check supported sizes of snapshots using property and set the - desired size using property. - - The property must be set before running the video source to take effect. - - Default value of the property is set to . - - - - - - New frame event. - - - Notifies clients about new available frame from video source. - - Since video source may have multiple clients, each client is responsible for - making a copy (cloning) of the passed video frame, because the video source disposes its - own original copy after notifying of clients. - - - - - - Snapshot frame event. - - - Notifies clients about new available snapshot frame - the one which comes when - camera's snapshot/shutter button is pressed. - - See documentation to for additional information. - - Since video source may have multiple clients, each client is responsible for - making a copy (cloning) of the passed snapshot frame, because the video source disposes its - own original copy after notifying of clients. - - - - - - - - Video source error event. - - - This event is used to notify clients about any type of errors occurred in - video source object, for example internal exceptions. - - - - - Video playing finished event. - - - This event is used to notify clients that the video playing has finished. - - - - - - Video source. - - - Video source is represented by moniker string of video capture device. - - - - - Received frames count. - - - Number of frames the video source provided from the moment of the last - access to the property. - - - - - - Received bytes count. - - - Number of bytes the video source provided from the moment of the last - access to the property. - - - - - - State of the video source. - - - Current state of video source object - running or not. - - - - - Obsolete - no longer in use - - - The property is obsolete. Use property instead. - Setting this property does not have any effect. - - - - - Obsolete - no longer in use - - - The property is obsolete. Use property instead. - Setting this property does not have any effect. - - - - - Obsolete - no longer in use. - - - The property is obsolete. Setting this property does not have any effect. - - - - - Video resolution to set. - - - The property allows to set one of the video resolutions supported by the camera. - Use property to get the list of supported video resolutions. - - The property must be set before camera is started to make any effect. - - Default value of the property is set to , which means default video - resolution is used. - - - - - - Snapshot resolution to set. - - - The property allows to set one of the snapshot resolutions supported by the camera. - Use property to get the list of supported snapshot resolutions. - - The property must be set before camera is started to make any effect. - - Default value of the property is set to , which means default snapshot - resolution is used. - - - - - - Video capabilities of the device. - - - The property provides list of device's video capabilities. - - It is recomended not to call this property immediately after method, since - device may not start yet and provide its information. It is better to call the property - before starting device or a bit after (but not immediately after). - - - - - - Snapshot capabilities of the device. - - - The property provides list of device's snapshot capabilities. - - If the array has zero length, then it means that this device does not support making - snapshots. - - See documentation to for additional information. - - It is recomended not to call this property immediately after method, since - device may not start yet and provide its information. It is better to call the property - before starting device or a bit after (but not immediately after). - - - - - - - - Source COM object of camera capture device. - - - The source COM object of camera capture device is exposed for the - case when user may need get direct access to the object for making some custom - configuration of camera through DirectShow interface, for example. - - - If camera is not running, the property is set to . - - - - - - The interface sets properties on the video window. - - - - - - Sets the video window caption. - - - Caption. - - Return's HRESULT error code. - - - - - Retrieves the video window caption. - - - Caption. - - Return's HRESULT error code. - - - - - Sets the window style on the video window. - - - Window style flags. - - Return's HRESULT error code. - - - - - Retrieves the window style on the video window. - - - Window style flags. - - Return's HRESULT error code. - - - - - Sets the extended window style on the video window. - - - Window extended style flags. - - Return's HRESULT error code. - - - - - Retrieves the extended window style on the video window. - - - Window extended style flags. - - Return's HRESULT error code. - - - - - Specifies whether the video renderer automatically shows the video window when it receives video data. - - - Specifies whether the video renderer automatically shows the video window. - - Return's HRESULT error code. - - - - - Queries whether the video renderer automatically shows the video window when it receives video data. - - - REceives window auto show flag. - - Return's HRESULT error code. - - - - - Shows, hides, minimizes, or maximizes the video window. - - - Window state. - - Return's HRESULT error code. - - - - - Queries whether the video window is visible, hidden, minimized, or maximized. - - - Window state. - - Return's HRESULT error code. - - - - - Specifies whether the video window realizes its palette in the background. - - - Value that specifies whether the video renderer realizes it palette in the background. - - Return's HRESULT error code. - - - - - Queries whether the video window realizes its palette in the background. - - - Receives state of background palette flag. - - Return's HRESULT error code. - - - - - Shows or hides the video window. - - - Value that specifies whether to show or hide the window. - - Return's HRESULT error code. - - - - - Queries whether the video window is visible. - - - Visibility flag. - - Return's HRESULT error code. - - - - - Sets the video window's x-coordinate. - - - Specifies the x-coordinate, in pixels. - - Return's HRESULT error code. - - - - - Retrieves the video window's x-coordinate. - - - x-coordinate, in pixels. - - Return's HRESULT error code. - - - - - Sets the width of the video window. - - - Specifies the width, in pixels. - - Return's HRESULT error code. - - - - - Retrieves the width of the video window. - - - Width, in pixels. - - Return's HRESULT error code. - - - - - Sets the video window's y-coordinate. - - - Specifies the y-coordinate, in pixels. - - Return's HRESULT error code. - - - - - Retrieves the video window's y-coordinate. - - - y-coordinate, in pixels. - - Return's HRESULT error code. - - - - - Sets the height of the video window. - - - Specifies the height, in pixels. - - Return's HRESULT error code. - - - - - Retrieves the height of the video window. - - - Height, in pixels. - - Return's HRESULT error code. - - - - - Specifies a parent window for the video windowю - - - Specifies a handle to the parent window. - - Return's HRESULT error code. - - - - - Retrieves the video window's parent window, if anyю - - - Parent window's handle. - - Return's HRESULT error code. - - - - - Specifies a window to receive mouse and keyboard messages from the video window. - - - Specifies a handle to the window. - - Return's HRESULT error code. - - - - - Retrieves the window that receives mouse and keyboard messages from the video window, if any. - - - Window's handle. - - Return's HRESULT error code. - - - - - Retrieves the color that appears around the edges of the destination rectangle. - - - Border's color. - - Return's HRESULT error code. - - - - - Sets the color that appears around the edges of the destination rectangle. - - - Specifies the border color. - - Return's HRESULT error code. - - - - - Queries whether the video renderer is in full-screen mode. - - - Full-screen mode. - - Return's HRESULT error code. - - - - - Enables or disables full-screen mode. - - - Boolean value that specifies whether to enable or disable full-screen mode. - - Return's HRESULT error code. - - - - - Places the video window at the top of the Z order. - - - Value that specifies whether to give the window focus. - - Return's HRESULT error code. - - - - - Forwards a message to the video window. - - - Handle to the window. - Specifies the message. - Message parameter. - Message parameter. - - Return's HRESULT error code. - - - - - Sets the position of the video windowю - - - Specifies the x-coordinate, in pixels. - Specifies the y-coordinate, in pixels. - Specifies the width, in pixels. - Specifies the height, in pixels. - - Return's HRESULT error code. - - - - - Retrieves the position of the video window. - - - x-coordinate, in pixels. - y-coordinate, in pixels. - Width, in pixels. - Height, in pixels. - - Return's HRESULT error code. - - - - - Retrieves the minimum ideal size for the video image. - - - Receives the minimum ideal width, in pixels. - Receives the minimum ideal height, in pixels. - - Return's HRESULT error code. - - - - - Retrieves the maximum ideal size for the video image. - - - Receives the maximum ideal width, in pixels. - Receives the maximum ideal height, in pixels. - - Return's HRESULT error code. - - - - - Retrieves the restored window position. - - - x-coordinate, in pixels. - y-coordinate, in pixels. - Width, in pixels. - Height, in pixels. - - Return's HRESULT error code. - - - - - Hides the cursor. - - - Specifies whether to hide or display the cursor. - - Return's HRESULT error code. - - - - - Queries whether the cursor is hidden. - - - Specifies if cursor is hidden or not. - - Return's HRESULT error code. - - - - - The IPropertyBag interface provides an object with a property bag in - which the object can persistently save its properties. - - - - - - Read a property from property bag. - - - Property name to read. - Property value. - Caller's error log. - - Return's HRESULT error code. - - - - - Write property to property bag. - - - Property name to read. - Property value. - - Return's HRESULT error code. - - - - - The interface provides methods for controlling the flow of data through the filter graph. - It includes methods for running, pausing, and stopping the graph. - - - - - - This method informs the filter to transition to the new state. - - - Return's HRESULT error code. - - - - - This method informs the filter to transition to the new state. - - - Return's HRESULT error code. - - - - - This method informs the filter to transition to the new (running) state. Passes a time value to synchronize independent streams. - - - Time value of the reference clock. The amount to be added to the IMediaSample time stamp to determine the time at which that sample should be rendered according to the reference clock. That is, it is the reference time at which a sample with a stream time of zero should be rendered. - - Return's HRESULT error code. - - - - - This method determines the filter's state. - - - Duration of the time-out, in milliseconds. To block indefinitely, pass INFINITE. - Returned state of the filter. States include stopped, paused, running, or intermediate (in the process of changing). - - Return's HRESULT error code. - - - - - This method identifies the reference clock to which the filter should synchronize activity. - - - Pointer to the IReferenceClock interface. - - Return's HRESULT error code. - - - - - This method retrieves the current reference clock in use by this filter. - - - Pointer to a reference clock; it will be set to the IReferenceClock interface. - - - Return's HRESULT error code. - - - - - The interface provides methods for controlling the flow of data through the filter graph. - It includes methods for running, pausing, and stopping the graph. - - - - - - Runs all the filters in the filter graph. - - - Return's HRESULT error code. - - - - - Pauses all filters in the filter graph. - - - Return's HRESULT error code. - - - - - Stops all the filters in the filter graph. - - - Return's HRESULT error code. - - - - - Retrieves the state of the filter graph. - - - Duration of the time-out, in milliseconds, or INFINITE to specify an infinite time-out. - Мariable that receives a member of the FILTER_STATE enumeration. - - Return's HRESULT error code. - - - - - Builds a filter graph that renders the specified file. - - - Name of the file to render - - Return's HRESULT error code. - - - - - Adds a source filter to the filter graph, for a specified file. - - - Name of the file containing the source video. - Receives interface of filter information object. - - Return's HRESULT error code. - - - - - Retrieves a collection of the filters in the filter graph. - - - Receives the IAMCollection interface. - - Return's HRESULT error code. - - - - - Retrieves a collection of all the filters listed in the registry. - - - Receives the IDispatch interface of IAMCollection object. - - Return's HRESULT error code. - - - - - Pauses the filter graph, allowing filters to queue data, and then stops the filter graph. - - - Return's HRESULT error code. - - - - - This interface extends the and - interfaces, which contain methods for building filter graphs. - - - - - - Adds a filter to the graph and gives it a name. - - - Filter to add to the graph. - Name of the filter. - - Return's HRESULT error code. - - - - - Removes a filter from the graph. - - - Filter to be removed from the graph. - - Return's HRESULT error code. - - - - - Provides an enumerator for all filters in the graph. - - - Filter enumerator. - - Return's HRESULT error code. - - - - - Finds a filter that was added with a specified name. - - - Name of filter to search for. - Interface of found filter. - - Return's HRESULT error code. - - - - - Connects two pins directly (without intervening filters). - - - Output pin. - Input pin. - Media type to use for the connection. - - Return's HRESULT error code. - - - - - Breaks the existing pin connection and reconnects it to the same pin. - - - Pin to disconnect and reconnect. - - Return's HRESULT error code. - - - - - Disconnects a specified pin. - - - Pin to disconnect. - - Return's HRESULT error code. - - - - - Sets the reference clock to the default clock. - - - Return's HRESULT error code. - - - - - Connects two pins. If they will not connect directly, this method connects them with intervening transforms. - - - Output pin. - Input pin. - - Return's HRESULT error code. - - - - - Adds a chain of filters to a specified output pin to render it. - - - Output pin. - - Return's HRESULT error code. - - - - - Builds a filter graph that renders the specified file. - - - Specifies a string that contains file name or device moniker. - Reserved. - - Return's HRESULT error code. - - - - - Adds a source filter to the filter graph for a specific file. - - - Specifies the name of the file to load. - Specifies a name for the source filter. - Variable that receives the interface of the source filter. - - Return's HRESULT error code. - - - - - Sets the file for logging actions taken when attempting to perform an operation. - - - Handle to the log file. - - Return's HRESULT error code. - - - - - Requests that the graph builder return as soon as possible from its current task. - - - Return's HRESULT error code. - - - - - Queries whether the current operation should continue. - - - Return's HRESULT error code. - - - - - - - - Moniker interface. - Bind context interface. - Name for the filter. - Receives source filter's IBaseFilter interface. - The caller must release the interface. - - Return's HRESULT error code. - - - - - Breaks the existing pin connection and reconnects it to the same pin, - using a specified media type. - - - Pin to disconnect and reconnect. - Media type to reconnect with. - - Return's HRESULT error code. - - - - - Render an output pin, with an option to use existing renderers only. - - - Interface of the output pin. - Flag that specifies how to render the pin. - Reserved. - - Return's HRESULT error code. - - - - - This interface is used by applications or other filters to determine - what filters exist in the filter graph. - - - - - - Retrieves the specified number of filters in the enumeration sequence. - - - Number of filters to retrieve. - Array in which to place interfaces. - Actual number of filters placed in the array. - - Return's HRESULT error code. - - - - - Skips a specified number of filters in the enumeration sequence. - - - Number of filters to skip. - - Return's HRESULT error code. - - - - - Resets the enumeration sequence to the beginning. - - - Return's HRESULT error code. - - - - - Makes a copy of the enumerator with the same enumeration state. - - - Duplicate of the enumerator. - - - Return's HRESULT error code. - - - - - - The ICreateDevEnum interface creates an enumerator for devices within a particular category, - such as video capture devices, audio capture devices, video compressors, and so forth. - - - - - - Creates a class enumerator for a specified device category. - - - Specifies the class identifier of the device category. - Address of a variable that receives an IEnumMoniker interface pointer - Bitwise combination of zero or more flags. If zero, the method enumerates every filter in the category. - - Return's HRESULT error code. - - - - - Some Win32 API used internally. - - - - - - Supplies a pointer to an implementation of IBindCtx (a bind context object). - This object stores information about a particular moniker-binding operation. - - - Reserved for future use; must be zero. - Address of IBindCtx* pointer variable that receives the - interface pointer to the new bind context object. - - Returns S_OK on success. - - - - - Converts a string into a moniker that identifies the object named by the string. - - - Pointer to the IBindCtx interface on the bind context object to be used in this binding operation. - Pointer to a zero-terminated wide character string containing the display name to be parsed. - Pointer to the number of characters of szUserName that were consumed. - Address of IMoniker* pointer variable that receives the interface pointer - to the moniker that was built from szUserName. - - Returns S_OK on success. - - - - - Copy a block of memory. - - - Destination pointer. - Source pointer. - Memory block's length to copy. - - Return's the value of dst - pointer to destination. - - - - - Invokes a new property frame, that is, a property sheet dialog box. - - - Parent window of property sheet dialog box. - Horizontal position for dialog box. - Vertical position for dialog box. - Dialog box caption. - Number of object pointers in ppUnk. - Pointer to the objects for property sheet. - Number of property pages in lpPageClsID. - Array of CLSIDs for each property page. - Locale identifier for property sheet locale. - Reserved. - Reserved. - - Returns S_OK on success. - - - - - The enumeration specifies a setting on a camera. - - - - - Pan control. - - - - - Tilt control. - - - - - Roll control. - - - - - Zoom control. - - - - - Exposure control. - - - - - Iris control. - - - - - Focus control. - - - - - The enumeration defines whether a camera setting is controlled manually or automatically. - - - - - No control flag. - - - - - Auto control Flag. - - - - - Manual control Flag. - - - - - Video input of a capture board. - - - The class is used to describe video input of devices like video capture boards, - which usually provide several inputs. - - - - - - Index of the video input. - - - - - Type of the video input. - - - - - Default video input. Used to specify that it should not be changed. - - - - - DirectShow filter information. - - - - - - Initializes a new instance of the class. - - - Filters's moniker string. - - - - - Initializes a new instance of the class. - - - Filter's moniker object. - - - - - Compare the object with another instance of this class. - - - Object to compare with. - - A signed number indicating the relative values of this instance and value. - - - - - Create an instance of the filter. - - - Filter's moniker string. - - Returns filter's object, which implements IBaseFilter interface. - - The returned filter's object should be released using Marshal.ReleaseComObject(). - - - - - Filter name. - - - - - Filters's moniker string. - - - - - - DirectShow class IDs. - - - - - System device enumerator. - - - Equals to CLSID_SystemDeviceEnum. - - - - - Filter graph. - - - Equals to CLSID_FilterGraph. - - - - - Sample grabber. - - - Equals to CLSID_SampleGrabber. - - - - - Capture graph builder. - - - Equals to CLSID_CaptureGraphBuilder2. - - - - - Async reader. - - - Equals to CLSID_AsyncReader. - - - - - DirectShow format types. - - - - - - VideoInfo. - - - Equals to FORMAT_VideoInfo. - - - - - VideoInfo2. - - - Equals to FORMAT_VideoInfo2. - - - - - DirectShow media types. - - - - - - Video. - - - Equals to MEDIATYPE_Video. - - - - - Interleaved. Used by Digital Video (DV). - - - Equals to MEDIATYPE_Interleaved. - - - - - Audio. - - - Equals to MEDIATYPE_Audio. - - - - - Text. - - - Equals to MEDIATYPE_Text. - - - - - Byte stream with no time stamps. - - - Equals to MEDIATYPE_Stream. - - - - - DirectShow media subtypes. - - - - - - YUY2 (packed 4:2:2). - - - Equals to MEDIASUBTYPE_YUYV. - - - - - IYUV. - - - Equals to MEDIASUBTYPE_IYUV. - - - - - A DV encoding format. (FOURCC 'DVSD') - - - Equals to MEDIASUBTYPE_DVSD. - - - - - RGB, 1 bit per pixel (bpp), palettized. - - - Equals to MEDIASUBTYPE_RGB1. - - - - - RGB, 4 bpp, palettized. - - - Equals to MEDIASUBTYPE_RGB4. - - - - - RGB, 8 bpp. - - - Equals to MEDIASUBTYPE_RGB8. - - - - - RGB 565, 16 bpp. - - - Equals to MEDIASUBTYPE_RGB565. - - - - - RGB 555, 16 bpp. - - - Equals to MEDIASUBTYPE_RGB555. - - - - - RGB, 24 bpp. - - - Equals to MEDIASUBTYPE_RGB24. - - - - - RGB, 32 bpp, no alpha channel. - - - Equals to MEDIASUBTYPE_RGB32. - - - - - Data from AVI file. - - - Equals to MEDIASUBTYPE_Avi. - - - - - Advanced Streaming Format (ASF). - - - Equals to MEDIASUBTYPE_Asf. - - - - - DirectShow pin categories. - - - - - - Capture pin. - - - Equals to PIN_CATEGORY_CAPTURE. - - - - - Still image pin. - - - Equals to PIN_CATEGORY_STILL. - - - - Equals to LOOK_UPSTREAM_ONLY. - - - Equals to LOOK_DOWNSTREAM_ONLY. - - - - The IReferenceClock interface provides the reference time for the filter graph. - - Filters that can act as a reference clock can expose this interface. It is also exposed by the System Reference Clock. - The filter graph manager uses this interface to synchronize the filter graph. Applications can use this interface to - retrieve the current reference time, or to request notification of an elapsed time. - - - - - The GetTime method retrieves the current reference time. - - - Pointer to a variable that receives the current time, in 100-nanosecond units. - - Return's HRESULT error code. - - - - - The AdviseTime method creates a one-shot advise request. - - - Base reference time, in 100-nanosecond units. See Remarks. - Stream offset time, in 100-nanosecond units. See Remarks. - Handle to an event, created by the caller. - Pointer to a variable that receives an identifier for the advise request. - - Return's HRESULT error code. - - - - - The AdvisePeriodic method creates a periodic advise request. - - - Time of the first notification, in 100-nanosecond units. Must be greater than zero and less than MAX_TIME. - Time between notifications, in 100-nanosecond units. Must be greater than zero. - Handle to a semaphore, created by the caller. - Pointer to a variable that receives an identifier for the advise request. - - Return's HRESULT error code. - - - - - The Unadvise method removes a pending advise request. - - - Identifier of the request to remove. Use the value returned by IReferenceClock::AdviseTime or IReferenceClock::AdvisePeriodic in the pdwAdviseToken parameter. - - Return's HRESULT error code. - - - - - The IAMCrossbar interface routes signals from an analog or digital source to a video capture filter. - - - - - Retrieves the number of input and output pins on the crossbar filter. - - - Variable that receives the number of output pins. - Variable that receives the number of input pins. - - Return's HRESULT error code. - - - - - Queries whether a specified input pin can be routed to a specified output pin. - - - Specifies the index of the output pin. - Specifies the index of input pin. - - Return's HRESULT error code. - - - - - Routes an input pin to an output pin. - - - Specifies the index of the output pin. - Specifies the index of the input pin. - - Return's HRESULT error code. - - - - - Retrieves the input pin that is currently routed to the specified output pin. - - - Specifies the index of the output pin. - Variable that receives the index of the input pin, or -1 if no input pin is routed to this output pin. - - Return's HRESULT error code. - - - - - Retrieves information about a specified pin. - - - Specifies the direction of the pin. Use one of the following values. - Specifies the index of the pin. - Variable that receives the index of the related pin, or –1 if no pin is related to this pin. - Variable that receives a member of the PhysicalConnectorType enumeration, indicating the pin's physical type. - - Return's HRESULT error code. - - - - - The IBaseFilter interface provides methods for controlling a filter. - All DirectShow filters expose this interface - - - - - - Returns the class identifier (CLSID) for the component object. - - - Points to the location of the CLSID on return. - - Return's HRESULT error code. - - - - - Stops the filter. - - - Return's HRESULT error code. - - - - - Pauses the filter. - - - Return's HRESULT error code. - - - - - Runs the filter. - - - Reference time corresponding to stream time 0. - - Return's HRESULT error code. - - - - - Retrieves the state of the filter (running, stopped, or paused). - - - Time-out interval, in milliseconds. - Pointer to a variable that receives filter's state. - - Return's HRESULT error code. - - - - - Sets the reference clock for the filter or the filter graph. - - - Pointer to the clock's IReferenceClock interface, or NULL. - - Return's HRESULT error code. - - - - - Retrieves the current reference clock. - - - Address of a variable that receives a pointer to the clock's IReferenceClock interface. - - Return's HRESULT error code. - - - - - Enumerates the pins on this filter. - - - Address of a variable that receives a pointer to the IEnumPins interface. - - Return's HRESULT error code. - - - - - Retrieves the pin with the specified identifier. - - - Pointer to a constant wide-character string that identifies the pin. - Address of a variable that receives a pointer to the pin's IPin interface. - - Return's HRESULT error code. - - - - - Retrieves information about the filter. - - - Pointer to FilterInfo structure. - - Return's HRESULT error code. - - - - - Notifies the filter that it has joined or left the filter graph. - - - Pointer to the Filter Graph Manager's IFilterGraph interface, or NULL - if the filter is leaving the graph. - String that specifies a name for the filter. - - Return's HRESULT error code. - - - - - Retrieves a string containing vendor information. - - - Receives a string containing the vendor information. - - Return's HRESULT error code. - - - - - The interface inherits contains methods for retrieving event notifications and for overriding the - filter graph's default handling of events. - - - - - Retrieves a handle to a manual-reset event that remains signaled while the queue contains event notifications. - - Pointer to a variable that receives the event handle. - - Return's HRESULT error code. - - - - - Retrieves the next event notification from the event queue. - - - Variable that receives the event code. - Pointer to a variable that receives the first event parameter. - Pointer to a variable that receives the second event parameter. - Time-out interval, in milliseconds. - - Return's HRESULT error code. - - - - - Waits for the filter graph to render all available data. - - - Time-out interval, in milliseconds. Pass zero to return immediately. - Pointer to a variable that receives an event code. - - Return's HRESULT error code. - - - - - Cancels the Filter Graph Manager's default handling for a specified event. - - - Event code for which to cancel default handling. - - Return's HRESULT error code. - - - - - Restores the Filter Graph Manager's default handling for a specified event. - - Event code for which to restore default handling. - - Return's HRESULT error code. - - - - - Frees resources associated with the parameters of an event. - - Event code. - First event parameter. - Second event parameter. - - Return's HRESULT error code. - - - - - Registers a window to process event notifications. - - - Handle to the window, or to stop receiving event messages. - Window message to be passed as the notification. - Value to be passed as the lParam parameter for the lMsg message. - - Return's HRESULT error code. - - - - - Enables or disables event notifications. - - - Value indicating whether to enable or disable event notifications. - - Return's HRESULT error code. - - - - - Determines whether event notifications are enabled. - - - Variable that receives current notification status. - - Return's HRESULT error code. - - - - - Video source for video files. - - - The video source provides access to video files. DirectShow is used to access video - files. - - Sample usage: - - // create video source - FileVideoSource videoSource = new FileVideoSource( fileName ); - // set NewFrame event handler - videoSource.NewFrame += new NewFrameEventHandler( video_NewFrame ); - // start the video source - videoSource.Start( ); - // ... - // signal to stop - videoSource.SignalToStop( ); - // ... - - // New frame event handler, which is invoked on each new available video frame - private void video_NewFrame( object sender, NewFrameEventArgs eventArgs ) - { - // get new frame - Bitmap bitmap = eventArgs.Frame; - // process the frame - } - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Video file name. - - - - - Start video source. - - - Starts video source and return execution to caller. Video source - object creates background thread and notifies about new frames with the - help of event. - - - - - Signal video source to stop its work. - - - Signals video source to stop its background thread, stop to - provide new frames and free resources. - - - - - Wait for video source has stopped. - - - Waits for source stopping after it was signalled to stop using - method. - - - - - Stop video source. - - - Stops video source aborting its thread. - - Since the method aborts background thread, its usage is highly not preferred - and should be done only if there are no other options. The correct way of stopping camera - is signaling it stop and then - waiting for background thread's completion. - - - - - - Free resource. - - - - - - Worker thread. - - - - - - Notifies client about new frame. - - - New frame's image. - - - - - New frame event. - - - Notifies clients about new available frame from video source. - - Since video source may have multiple clients, each client is responsible for - making a copy (cloning) of the passed video frame, because the video source disposes its - own original copy after notifying of clients. - - - - - - Video source error event. - - - This event is used to notify clients about any type of errors occurred in - video source object, for example internal exceptions. - - - - - Video playing finished event. - - - This event is used to notify clients that the video playing has finished. - - - - - - Video source. - - - Video source is represented by video file name. - - - - - Received frames count. - - - Number of frames the video source provided from the moment of the last - access to the property. - - - - - - Received bytes count. - - - Number of bytes the video source provided from the moment of the last - access to the property. - - - - - - State of the video source. - - - Current state of video source object - running or not. - - - - - Prevent video freezing after screen saver and workstation lock or not. - - - - The value specifies if the class should prevent video freezing during and - after screen saver or workstation lock. To prevent freezing the DirectShow graph - should not contain Renderer filter, which is added by Render() method - of graph. However, in some cases it may be required to call Render() method of graph, since - it may add some more filters, which may be required for playing video. So, the property is - a trade off - it is possible to prevent video freezing skipping adding renderer filter or - it is possible to keep renderer filter, but video may freeze during screen saver. - - The property may become obsolete in the future when approach to disable freezing - and adding all required filters is found. - - The property should be set before calling method - of the class to have effect. - - Default value of this property is set to false. - - - - - - - Enables/disables reference clock on the graph. - - - Disabling reference clocks causes DirectShow graph to run as fast as - it can process data. When enabled, it will process frames according to presentation - time of a video file. - - The property should be set before calling method - of the class to have effect. - - Default value of this property is set to true. - - - - - diff --git a/Externals/AForge.NET/AForge.Video.FFMPEG.dll b/Externals/AForge.NET/AForge.Video.FFMPEG.dll deleted file mode 100644 index 65b58f6bf..0000000000 Binary files a/Externals/AForge.NET/AForge.Video.FFMPEG.dll and /dev/null differ diff --git a/Externals/AForge.NET/AForge.Video.FFMPEG.xml b/Externals/AForge.NET/AForge.Video.FFMPEG.xml deleted file mode 100644 index e815a00d1..0000000000 --- a/Externals/AForge.NET/AForge.Video.FFMPEG.xml +++ /dev/null @@ -1,5761 +0,0 @@ - - - - "Video.FFMPEG" - - - - -Stop video source. - - - Stops video source aborting its thread. - - Since the method aborts background thread, its usage is highly not preferred -and should be done only if there are no other options. The correct way of stopping camera -is signaling it stop and then -waiting for background thread's completion. - - - - - -Wait for video source has stopped. - - Waits for source stopping after it was signalled to stop using - method. - - - -Signal video source to stop its work. - - Signals video source to stop its background thread, stop to -provide new frames and free resources. - - - -Start video source. - - Starts video source and return execution to caller. Video source -object creates background thread and notifies about new frames with the -help of event. - Video source is not specified. - - - -Initializes a new instance of the class. - - - - -Get frame interval from source or use manually specified. - - - The property specifies which frame rate to use for video playing. -If the property is set to , then video is played -with original frame rate, which is set in source video file. If the property is -set to , then custom frame rate is used, which is -calculated based on the manually specified frame interval. - Default value is set to . - - - - -Frame interval. - - - The property sets the interval in milliseconds between frames. If the property is -set to 100, then the desired frame rate will be 10 frames per second. - - Setting this property to 0 leads to no delay between video frames - frames -are read as fast as possible. - - - Setting this property has effect only when -is set to . - - Default value is set to 0. - - - - -State of the video source. - - Current state of video source object - running or not. - - - -Received bytes count. - - Number of bytes the video source provided from the moment of the last -access to the property. - - - - -Received frames count. - - Number of frames the video source provided from the moment of the last -access to the property. - - - - -Video source. - - - Video file name to play. - - - - -Video playing finished event. - - - This event is used to notify clients that the video playing has finished. - - - - -Video source error event. - - This event is used to notify clients about any type of errors occurred in -video source object, for example internal exceptions. - - - -New frame event. - - - Notifies clients about new available frame from video source. - - Since video source may have multiple clients, each client is responsible for -making a copy (cloning) of the passed video frame, because the video source disposes its -own original copy after notifying of clients. - - - - - -Video source for video files. - - - The video source provides access to video files using FFmpeg library. - - The class provides video only. Sound is not supported. - - - The class ignores presentation time of video frames while retrieving them from -video file. Instead it provides video frames according to the FPS rate of the video file -or the configured . - - - Make sure you have FFmpeg binaries (DLLs) in the output folder of your application in order -to use this class successfully. FFmpeg binaries can be found in Externals folder provided with AForge.NET -framework's distribution. - - Sample usage: - -// create video source -VideoFileSource videoSource = new VideoFileSource( fileName ); -// set NewFrame event handler -videoSource.NewFrame += new NewFrameEventHandler( video_NewFrame ); -// start the video source -videoSource.Start( ); -// ... - -// New frame event handler, which is invoked on each new available video frame -private void video_NewFrame( object sender, NewFrameEventArgs eventArgs ) -{ - // get new frame - Bitmap bitmap = eventArgs.Frame; - // process the frame -} - - - - - -Close currently opened video file if any. - - - - -Read next video frame of the currently opened video file. - - Returns next video frame of the opened file or if end of -file was reached. The returned video frame has 24 bpp color format. - Thrown if no video file was open. - A error occurred while reading next video frame. See exception message. - - - -Open video file with the specified name. - - Video file name to open. - Cannot open video file with the specified name. - A error occurred while opening the video file. See exception message. - - - -Disposes the object and frees its resources. - - - - -Initializes a new instance of the class. - - - - -Object's finalizer. - - - - -The property specifies if a video file is opened or not by this instance of the class. - - - - -Name of codec used for encoding the opened video file. - - Thrown if no video file was open. - - - -Number of video frames in the opened video file. - - - - - Warning: some video file formats may report different value -from the actual number of video frames in the file (subject to fix/investigate). - - - Thrown if no video file was open. - - - -Frame rate of the opened video file. - - Thrown if no video file was open. - - - -Frame height of the opened video file. - - Thrown if no video file was open. - - - -Frame width of the opened video file. - - Thrown if no video file was open. - - - -Class for reading video files utilizing FFmpeg library. - - - The class allows to read video files using FFmpeg library. - - Make sure you have FFmpeg binaries (DLLs) in the output folder of your application in order -to use this class successfully. FFmpeg binaries can be found in Externals folder provided with AForge.NET -framework's distribution. - - Sample usage: - -// create instance of video reader -VideoFileReader reader = new VideoFileReader( ); -// open video file -reader.Open( "test.avi" ); -// check some of its attributes -Console.WriteLine( "width: " + reader.Width ); -Console.WriteLine( "height: " + reader.Height ); -Console.WriteLine( "fps: " + reader.FrameRate ); -Console.WriteLine( "codec: " + reader.CodecName ); -// read 100 video frames out of it -for ( int i = 0; i < 100; i++ ) -{ - Bitmap videoFrame = reader.ReadVideoFrame( ); - // process the frame somehow - // ... - - // dispose the frame when it is no longer required - videoFrame.Dispose( ); -} -reader.Close( ); - - - - - Get the AVClass for swsContext. It can be used in combination with - AV_OPT_SEARCH_FAKE_OBJ for examining options. - - @see av_opt_find(). - - - - Convert an 8-bit paletted frame into a frame with a color depth of 24 bits. - - With the palette format "ABCD", the destination frame ends up with the format "ABC". - - @param src source frame buffer - @param dst destination frame buffer - @param num_pixels number of pixels to convert - @param palette array with [256] entries, which must match color arrangement (RGB or BGR) of src - - - - Convert an 8-bit paletted frame into a frame with a color depth of 32 bits. - - The output frame will have the same packed format as the palette. - - @param src source frame buffer - @param dst destination frame buffer - @param num_pixels number of pixels to convert - @param palette array with [256] entries, which must match color arrangement (RGB or BGR) of src - - - -Allocate and return a clone of the vector a, that is a vector -with the same coefficients as a. - - - -Scale all the coefficients of a so that their sum equals height. - - - -Scale all the coefficients of a by the scalar value. - - - -Allocate and return a vector with just one coefficient, with -value 1.0. - - - -Allocate and return a vector with length coefficients, all -with the same value c. - - - -Return a normalized Gaussian curve used to filter stuff -quality = 3 is high quality, lower is lower quality. - - - -Allocate and return an uninitialized vector with length coefficients. - - - -@return -1 if not supported - - - -@param inv_table the yuv2rgb coefficients, normally ff_yuv2rgb_coeffs[x] -@return -1 if not supported - - - - Scale the image slice in srcSlice and put the resulting scaled - slice in the image in dst. A slice is a sequence of consecutive - rows in an image. - - Slices have to be provided in sequential order, either in - top-bottom or bottom-top order. If slices are provided in - non-sequential order the behavior of the function is undefined. - - @param c the scaling context previously created with - sws_getContext() - @param srcSlice the array containing the pointers to the planes of - the source slice - @param srcStride the array containing the strides for each plane of - the source image - @param srcSliceY the position in the source image of the slice to - process, that is the number (counted starting from - zero) in the image of the first row of the slice - @param srcSliceH the height of the source slice, that is the number - of rows in the slice - @param dst the array containing the pointers to the planes of - the destination image - @param dstStride the array containing the strides for each plane of - the destination image - @return the height of the output slice - - - -Free the swscaler context swsContext. -If swsContext is NULL, then does nothing. - - - - Initialize the swscaler context sws_context. - - @return zero or positive value on success, a negative value on - error - - - -Allocate an empty SwsContext. This must be filled and passed to -sws_init_context(). For filling see AVOptions, options.c and -sws_setColorspaceDetails(). - - - Allocate and return an SwsContext. You need it to perform - scaling/conversion operations using sws_scale(). - - @param srcW the width of the source image - @param srcH the height of the source image - @param srcFormat the source image format - @param dstW the width of the destination image - @param dstH the height of the destination image - @param dstFormat the destination image format - @param flags specify which algorithm and options to use for rescaling - @return a pointer to an allocated context, or NULL in case of error - @note this function is to be removed after a saner alternative is - written - @deprecated Use sws_getCachedContext() instead. - - - Check if context can be reused, otherwise reallocate a new one. - - If context is NULL, just calls sws_getContext() to get a new - context. Otherwise, checks if the parameters are the ones already - saved in context. If that is the case, returns the current - context. Otherwise, frees context and gets a new context with - the new parameters. - - Be warned that srcFilter and dstFilter are not checked, they - are assumed to remain the same. - - - -Return a positive value if pix_fmt is a supported output format, 0 -otherwise. - - - -Return a positive value if pix_fmt is a supported input format, 0 -otherwise. - - - -Return the libswscale license. - - - -Return the libswscale build-time configuration. - - - -@} - -@file -@brief - external api for the swscale stuff - -Those FF_API_* defines are not part of public API. -They may change, break or disappear at any time. - -Return the LIBSWSCALE_VERSION_INT constant. - - - - Test if the given container can store a codec. - - @param std_compliance standards compliance level, one of FF_COMPLIANCE_* - - @return 1 if codec with ID codec_id can be stored in ofmt, 0 if it cannot. - A negative number if this information is not available. - - - - Return a positive value if the given filename has one of the given - extensions, 0 otherwise. - - @param extensions a comma-separated list of filename extensions - - - - Generate an SDP for an RTP session. - - @param ac array of AVFormatContexts describing the RTP streams. If the - array is composed by only one context, such context can contain - multiple AVStreams (one AVStream per RTP stream). Otherwise, - all the contexts in the array (an AVCodecContext per RTP stream) - must contain only one AVStream. - @param n_files number of AVCodecContexts contained in ac - @param buf buffer where the SDP will be stored (must be allocated by - the caller) - @param size the size of the buffer - @return 0 if OK, AVERROR_xxx on error - - - - Check whether filename actually is a numbered sequence generator. - - @param filename possible numbered sequence string - @return 1 if a valid numbered sequence string, 0 otherwise - - - - Return in 'buf' the path with '%d' replaced by a number. - - Also handles the '%0nd' format where 'n' is the total number - of digits and '%%'. - - @param buf destination buffer - @param buf_size destination buffer size - @param path numbered sequence string - @param number frame number - @return 0 if OK, -1 on format error - - - -@deprecated use av_find_info_tag in libavutil instead. - - - -Get the current time in microseconds. - - - - Parse datestr and return a corresponding number of microseconds. - - @param datestr String representing a date or a duration. - See av_parse_time() for the syntax of the provided string. - @deprecated in favor of av_parse_time() - - - -@deprecated Deprecated in favor of av_dump_format(). - - - - Split a URL string into components. - - The pointers to buffers for storing individual components may be null, - in order to ignore that component. Buffers for components not found are - set to empty strings. If the port is not found, it is set to a negative - value. - - @param proto the buffer for the protocol - @param proto_size the size of the proto buffer - @param authorization the buffer for the authorization - @param authorization_size the size of the authorization buffer - @param hostname the buffer for the host name - @param hostname_size the size of the hostname buffer - @param port_ptr a pointer to store the port number in - @param path the buffer for the path - @param path_size the size of the path buffer - @param url the URL to split - - - - Add an index entry into a sorted list. Update the entry if the list - already contains it. - - @param timestamp timestamp in the time base of the given stream - - - - Get the codec tag for the given codec id id. - If no codec tag is found returns 0. - - @param tags list of supported codec_id-codec_tag pairs, as stored - in AVInputFormat.codec_tag and AVOutputFormat.codec_tag - - - - Send a nice dump of a packet to the log. - - @param avcl A pointer to an arbitrary struct of which the first field is a - pointer to an AVClass struct. - @param level The importance level of the message, lower values signifying - higher importance. - @param pkt packet to dump - @param dump_payload True if the payload must be displayed, too. - @param st AVStream that the packet belongs to - - - - Send a nice dump of a packet to the specified file stream. - - @param f The file stream pointer where the dump should be sent to. - @param pkt packet to dump - @param dump_payload True if the payload must be displayed, too. - @param st AVStream that the packet belongs to - - - - Send a nice hexadecimal dump of a buffer to the log. - - @param avcl A pointer to an arbitrary struct of which the first field is a - pointer to an AVClass struct. - @param level The importance level of the message, lower values signifying - higher importance. - @param buf buffer - @param size buffer size - - @see av_hex_dump, av_pkt_dump2, av_pkt_dump_log2 - - - -@} - - @defgroup lavf_misc Utility functions - @ingroup libavf - @{ - - Miscelaneous utility functions related to both muxing and demuxing - (or neither). - - Send a nice hexadecimal dump of a buffer to the specified file stream. - - @param f The file stream pointer where the dump should be sent to. - @param buf buffer - @param size buffer size - - @see av_hex_dump_log, av_pkt_dump2, av_pkt_dump_log2 - - - -Get timing information for the data currently output. -The exact meaning of "currently output" depends on the format. -It is mostly relevant for devices that have an internal buffer and/or -work in real time. -@param s media file handle -@param stream stream in the media file -@param dts[out] DTS of the last packet output for the stream, in stream - time_base units -@param wall[out] absolute time when that packet whas output, - in microsecond -@return 0 if OK, AVERROR(ENOSYS) if the format does not support it -Note: some formats or devices may not allow to measure dts and wall -atomically. - - - - Return the output format in the list of registered output formats - which best matches the provided parameters, or return NULL if - there is no match. - - @param short_name if non-NULL checks if short_name matches with the - names of the registered formats - @param filename if non-NULL checks if filename terminates with the - extensions of the registered formats - @param mime_type if non-NULL checks if mime_type matches with the - MIME type of the registered formats - - - - Write the stream trailer to an output media file and free the - file private data. - - May only be called after a successful call to av_write_header. - - @param s media file handle - @return 0 if OK, AVERROR_xxx on error - - - - Write a packet to an output media file ensuring correct interleaving. - - The packet must contain one audio or video frame. - If the packets are already correctly interleaved, the application should - call av_write_frame() instead as it is slightly faster. It is also important - to keep in mind that completely non-interleaved input will need huge amounts - of memory to interleave with this, so it is preferable to interleave at the - demuxer level. - - @param s media file handle - @param pkt The packet containing the data to be written. Libavformat takes - ownership of the data and will free it when it sees fit using the packet's - @ref AVPacket.destruct "destruct" field. The caller must not access the data - after this function returns, as it may already be freed. - Packet's @ref AVPacket.stream_index "stream_index" field must be set to the - index of the corresponding stream in @ref AVFormatContext.streams - "s.streams". - It is very strongly recommended that timing information (@ref AVPacket.pts - "pts", @ref AVPacket.dts "dts" @ref AVPacket.duration "duration") is set to - correct values. - - @return 0 on success, a negative AVERROR on error. - - - - Allocate the stream private data and write the stream header to an - output media file. - @note: this sets stream time-bases, if possible to stream->codec->time_base - but for some formats it might also be some other time base - - @param s media file handle - @return 0 if OK, AVERROR_xxx on error - - @deprecated use avformat_write_header. - - - -@addtogroup lavf_encoding -@{ - - Allocate the stream private data and write the stream header to - an output media file. - - @param s Media file handle, must be allocated with avformat_alloc_context(). - Its oformat field must be set to the desired output format; - Its pb field must be set to an already openened AVIOContext. - @param options An AVDictionary filled with AVFormatContext and muxer-private options. - On return this parameter will be destroyed and replaced with a dict containing - options that were not found. May be NULL. - - @return 0 on success, negative AVERROR on failure. - - @see av_opt_find, av_dict_set, avio_open, av_oformat_next. - - - -@deprecated pass the options to avformat_write_header directly. - - - -@deprecated this function is not supposed to be called outside of lavf - - - -@} - - Add a new stream to a media file. - - Can only be called in the read_header() function. If the flag - AVFMTCTX_NOHEADER is in the format context, then new streams - can be added in read_packet too. - - @param s media file handle - @param id file-format-dependent stream ID - - - -Close an opened input AVFormatContext. Free it and all its contents -and set *s to NULL. - - - - @deprecated use avformat_close_input() - Close a media file (but not its codecs). - - @param s media file handle - - - -Free a AVFormatContext allocated by av_open_input_stream. -@param s context to free -@deprecated use av_close_input_file() - - - - Pause a network-based stream (e.g. RTSP stream). - - Use av_read_play() to resume it. - - - -Start playing a network-based stream (e.g. RTSP stream) at the -current position. - - - -Seek to the keyframe at timestamp. -'timestamp' in 'stream_index'. -@param stream_index If stream_index is (-1), a default -stream is selected, and timestamp is automatically converted -from AV_TIME_BASE units to the stream specific time_base. -@param timestamp Timestamp in AVStream.time_base units - or, if no stream is specified, in AV_TIME_BASE units. -@param flags flags which select direction and seeking mode -@return >= 0 on success - - - - Read a transport packet from a media file. - - This function is obsolete and should never be used. - Use av_read_frame() instead. - - @param s media file handle - @param pkt is filled - @return 0 if OK, AVERROR_xxx on error - - - - Find the "best" stream in the file. - The best stream is determined according to various heuristics as the most - likely to be what the user expects. - If the decoder parameter is non-NULL, av_find_best_stream will find the - default decoder for the stream's codec; streams for which no decoder can - be found are ignored. - - @param ic media file handle - @param type stream type: video, audio, subtitles, etc. - @param wanted_stream_nb user-requested stream number, - or -1 for automatic selection - @param related_stream try to find a stream related (eg. in the same - program) to this one, or -1 if none - @param decoder_ret if non-NULL, returns the decoder for the - selected stream - @param flags flags; none are currently defined - @return the non-negative stream number in case of success, - AVERROR_STREAM_NOT_FOUND if no stream with the requested type - could be found, - AVERROR_DECODER_NOT_FOUND if streams were found but no decoder - @note If av_find_best_stream returns successfully and decoder_ret is not - NULL, then *decoder_ret is guaranteed to be set to a valid AVCodec. - - - - Find the programs which belong to a given stream. - - @param ic media file handle - @param last the last found program, the search will start after this - program, or from the beginning if it is NULL - @param s stream index - @return the next program which belongs to s, NULL if no program is found or - the last program is not among the programs of ic. - - - - Read packets of a media file to get stream information. This - is useful for file formats with no headers such as MPEG. This - function also computes the real framerate in case of MPEG-2 repeat - frame mode. - The logical file position is not changed by this function; - examined packets may be buffered for later processing. - - @param ic media file handle - @param options If non-NULL, an ic.nb_streams long array of pointers to - dictionaries, where i-th member contains options for - codec corresponding to i-th stream. - On return each dictionary will be filled with options that were not found. - @return >=0 if OK, AVERROR_xxx on error - - @note this function isn't guaranteed to open all the codecs, so - options being non-empty at return is a perfectly normal behavior. - - @todo Let the user decide somehow what information is needed so that - we do not waste time getting stuff the user does not need. - - - - Read packets of a media file to get stream information. This - is useful for file formats with no headers such as MPEG. This - function also computes the real framerate in case of MPEG-2 repeat - frame mode. - The logical file position is not changed by this function; - examined packets may be buffered for later processing. - - @param ic media file handle - @return >=0 if OK, AVERROR_xxx on error - @todo Let the user decide somehow what information is needed so that - we do not waste time getting stuff the user does not need. - - @deprecated use avformat_find_stream_info. - - - - Open an input stream and read the header. The codecs are not opened. - The stream must be closed with av_close_input_file(). - - @param ps Pointer to user-supplied AVFormatContext (allocated by avformat_alloc_context). - May be a pointer to NULL, in which case an AVFormatContext is allocated by this - function and written into ps. - Note that a user-supplied AVFormatContext will be freed on failure. - @param filename Name of the stream to open. - @param fmt If non-NULL, this parameter forces a specific input format. - Otherwise the format is autodetected. - @param options A dictionary filled with AVFormatContext and demuxer-private options. - On return this parameter will be destroyed and replaced with a dict containing - options that were not found. May be NULL. - - @return 0 on success, a negative AVERROR on failure. - - @note If you want to use custom IO, preallocate the format context and set its pb field. - - - - Open a media file as input. The codecs are not opened. Only the file - header (if present) is read. - - @param ic_ptr The opened media file handle is put here. - @param filename filename to open - @param fmt If non-NULL, force the file format to use. - @param buf_size optional buffer size (zero if default is OK) - @param ap Additional parameters needed when opening the file - (NULL if default). - @return 0 if OK, AVERROR_xxx otherwise - - @deprecated use avformat_open_input instead. - - - -Allocate all the structures needed to read an input stream. - This does not open the needed codecs for decoding the stream[s]. -@deprecated use avformat_open_input instead. - - - - Probe a bytestream to determine the input format. Each time a probe returns - with a score that is too low, the probe buffer size is increased and another - attempt is made. When the maximum probe size is reached, the input format - with the highest score is returned. - - @param pb the bytestream to probe - @param fmt the input format is put here - @param filename the filename of the stream - @param logctx the log context - @param offset the offset within the bytestream to probe from - @param max_probe_size the maximum probe buffer size (zero for default) - @return 0 in case of success, a negative value corresponding to an - AVERROR code otherwise - - - - Guess the file format. - - @param is_opened Whether the file is already opened; determines whether - demuxers with or without AVFMT_NOFILE are probed. - @param score_ret The score of the best detection. - - - - Guess the file format. - - @param is_opened Whether the file is already opened; determines whether - demuxers with or without AVFMT_NOFILE are probed. - - - -@addtogroup lavf_decoding -@{ - -Find AVInputFormat based on the short name of the input format. - - - - Allocate an AVFormatContext for an output format. - avformat_free_context() can be used to free the context and - everything allocated by the framework within it. - - @param *ctx is set to the created format context, or to NULL in - case of failure - @param oformat format to use for allocating the context, if NULL - format_name and filename are used instead - @param format_name the name of output format to use for allocating the - context, if NULL filename is used instead - @param filename the name of the filename to use for allocating the - context, may be NULL - @return >= 0 in case of success, a negative AVERROR code in case of - failure - - - -@deprecated deprecated in favor of avformat_alloc_output_context2() - - - - Add a new stream to a media file. - - When demuxing, it is called by the demuxer in read_header(). If the - flag AVFMTCTX_NOHEADER is set in s.ctx_flags, then it may also - be called in read_packet(). - - When muxing, should be called by the user before avformat_write_header(). - - @param c If non-NULL, the AVCodecContext corresponding to the new stream - will be initialized to use this codec. This is needed for e.g. codec-specific - defaults to be set, so codec should be provided if it is known. - - @return newly created stream or NULL on error. - - - - Get the AVClass for AVFormatContext. It can be used in combination with - AV_OPT_SEARCH_FAKE_OBJ for examining options. - - @see av_opt_find(). - - - -Free an AVFormatContext and all its streams. -@param s context to free - - - -Allocate an AVFormatContext. -avformat_free_context() can be used to free the context and everything -allocated by the framework within it. - - - -If f is NULL, returns the first registered output format, -if f is non-NULL, returns the next registered output format after f -or NULL if f is the last one. - - - -If f is NULL, returns the first registered input format, -if f is non-NULL, returns the next registered input format after f -or NULL if f is the last one. - - - -Undo the initialization done by avformat_network_init. - - - - Do global initialization of network components. This is optional, - but recommended, since it avoids the overhead of implicitly - doing the setup for each session. - - Calling this function will become mandatory if using network - protocols at some major version bump. - - - - Initialize libavformat and register all the muxers, demuxers and - protocols. If you do not call this function, then you can select - exactly which formats you want to support. - - @see av_register_input_format() - @see av_register_output_format() - @see av_register_protocol() - - - -Return the libavformat license. - - - -Return the libavformat build-time configuration. - - - - @defgroup lavf_core Core functions - @ingroup libavf - - Functions for querying libavformat capabilities, allocating core structures, - etc. - @{ - -Return the LIBAVFORMAT_VERSION_INT constant. - - - -Max chunk size in bytes -Note, not all formats support this and unpredictable things may happen if it is used when not supported. -- encoding: Set by user via AVOptions (NO direct access) -- decoding: unused - - - -Max chunk time in microseconds. -Note, not all formats support this and unpredictable things may happen if it is used when not supported. -- encoding: Set by user via AVOptions (NO direct access) -- decoding: unused - - - -Audio preload in microseconds. -Note, not all formats support this and unpredictable things may happen if it is used when not supported. -- encoding: Set by user via AVOptions (NO direct access) -- decoding: unused - - - -Transport stream id. -This will be moved into demuxer private options. Thus no API/ABI compatibility - - - - Custom interrupt callbacks for the I/O layer. - - decoding: set by the user before avformat_open_input(). - encoding: set by the user before avformat_write_header() - (mainly useful for AVFMT_NOFILE formats). The callback - should also be passed to avio_open2() if it's used to - open the file. - - - -Error recognition; higher values will detect more errors but may -misdetect some more or less valid parts as errors. -- encoding: unused -- decoding: Set by user. - - - -decoding: number of frames used to probe fps - - - -Start time of the stream in real world time, in microseconds -since the unix epoch (00:00 1st January 1970). That is, pts=0 -in the stream was captured at this real world time. -- encoding: Set by user. -- decoding: Unused. - - - -Remaining size available for raw_packet_buffer, in bytes. -NOT PART OF PUBLIC API - - - -Flags to enable debugging. - - - -Maximum amount of memory in bytes to use for buffering frames -obtained from realtime capture devices. - - - -Maximum amount of memory in bytes to use for the index of each stream. -If the index exceeds this size, entries will be discarded as -needed to maintain a smaller size. This can lead to slower or less -accurate seeking (depends on demuxer). -Demuxers for which a full in-memory index is mandatory will ignore -this. -muxing : unused -demuxing: set by user - - - -decoding: maximum time (in AV_TIME_BASE units) during which the input should -be analyzed in avformat_find_stream_info(). - - - -decoding: size of data to probe; encoding: unused. - - - -@deprecated, use the 'loop' img2 demuxer private option. - - - - number of times to loop output in formats that support it - - @deprecated use the 'loop' private option in the gif muxer. - - - -use mpeg muxer private options instead - - - -Decoding: total stream bitrate in bit/s, 0 if not -available. Never set it directly if the file_size and the -duration are known as FFmpeg can compute it automatically. - - - -decoding: total file size, 0 if unknown - - - -Decoding: duration of the stream, in AV_TIME_BASE fractional -seconds. Only set this value if you know none of the individual stream -durations and also do not set any of them. This is deduced from the -AVStream values if not set. - - - -Decoding: position of the first frame of the component, in -AV_TIME_BASE fractional seconds. NEVER set this value directly: -It is deduced from the AVStream values. - - - -@deprecated use 'creation_time' metadata tag instead - - - - A list of all streams in the file. New streams are created with - avformat_new_stream(). - - decoding: streams are created by libavformat in avformat_open_input(). - If AVFMTCTX_NOHEADER is set in ctx_flags, then new streams may also - appear in av_read_frame(). - encoding: streams are created by the user before avformat_write_header(). - - - -Format private data. This is an AVOptions-enabled struct -if and only if iformat/oformat.priv_class is not NULL. - - - -A class for logging and AVOptions. Set by avformat_alloc_context(). -Exports (de)muxer private options if they exist. - - - -Format I/O context. -New fields can be added to the end with minor version bumps. -Removal, reordering and changes to existing fields require a major -version bump. -sizeof(AVFormatContext) must not be used outside libav*, use -avformat_alloc_context() to create an AVFormatContext. - - - -New fields can be added to the end with minor version bumps. -Removal, reordering and changes to existing fields require a major -version bump. -sizeof(AVProgram) must not be used outside libav*. - - - -flag to indicate that probing is requested -NOT PART OF PUBLIC API - - - -Stream Identifier -This is the MPEG-TS stream identifier +1 -0 means unknown - - - -Number of frames that have been demuxed during av_find_stream_info() - - - -Average framerate - - - -last packet in packet_buffer for this stream when muxing. -Used internally, NOT PART OF PUBLIC API, do not read or -write from outside of libav* - - -This buffer is only needed when packets were already buffered but -not decoded, for example to get the codec parameters in MPEG -streams. - - -Raw packets from the demuxer, prior to parsing and decoding. -This buffer is used for buffering packets until the codec can -be identified, as parsing cannot be done without knowing the -codec. - - - -Number of packets to buffer for codec probing -NOT PART OF PUBLIC API - - - - Timestamp corresponding to the last dts sync point. - - Initialized when AVCodecParserContext.dts_sync_point >= 0 and - a DTS is received from the underlying container. Otherwise set to - AV_NOPTS_VALUE by default. - - - -sample aspect ratio (0 if unknown) -- encoding: Set by user. -- decoding: Set by libavformat. - - - -Decoding: duration of the stream, in stream time base. -If a source file does not specify a duration, but does specify -a bitrate, this value will be estimated from bitrate and file size. - - - -Decoding: pts of the first frame of the stream in presentation order, in stream time base. -Only set this if you are absolutely 100% sure that the value you set -it to really is the pts of the first frame. -This may be undefined (AV_NOPTS_VALUE). -@note The ASF header does NOT contain a correct start_time the ASF -demuxer must NOT set this. - - - -Quality, as it has been removed from AVCodecContext and put in AVVideoFrame. -MN: dunno if that is the right place for it - - - -This is the fundamental unit of time (in seconds) in terms -of which frame timestamps are represented. For fixed-fps content, -time base should be 1/framerate and timestamp increments should be 1. -decoding: set by libavformat -encoding: set by libavformat in av_write_header - - - -encoding: pts generation when outputting stream - - - -Real base framerate of the stream. -This is the lowest framerate with which all timestamps can be -represented accurately (it is the least common multiple of all -framerates in the stream). Note, this value is just a guess! -For example, if the time base is 1/90000 and all frames have either -approximately 3600 or 1800 timer ticks, then r_frame_rate will be 50/1. - - - -Track should be used during playback by default. -Useful for subtitle track that should be displayed -even when user did not explicitly ask for subtitles. - -Stream structure. -New fields can be added to the end with minor version bumps. -Removal, reordering and changes to existing fields require a major -version bump. -sizeof(AVStream) must not be used outside libav*. - - - -@} - - - -Pause playing - only meaningful if using a network-based format -(RTSP). - - - -Start/resume playing - only meaningful if using a network-based format -(RTSP). - - - -General purpose read-only value that the format can use. - - - -If extensions are defined, then no probe is done. You should -usually not use extension format guessing because it is not -reliable enough - - - -Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_SHOW_IDS, -AVFMT_GENERIC_INDEX, AVFMT_TS_DISCONT, AVFMT_NOBINSEARCH, -AVFMT_NOGENSEARCH, AVFMT_NO_BYTE_SEEK. - - - -Get the next timestamp in stream[stream_index].time_base units. -@return the timestamp or AV_NOPTS_VALUE if an error occurred - - - -Seek to a given timestamp relative to the frames in -stream component stream_index. -@param stream_index Must not be -1. -@param flags Selects which direction should be preferred if no exact - match is available. -@return >= 0 on success (but not necessarily the new offset) - - - -Close the stream. The AVFormatContext and AVStreams are not -freed by this function - - - -Read the format header and initialize the AVFormatContext -structure. Return 0 if OK. 'ap' if non-NULL contains -additional parameters. Only used in raw format right -now. 'av_new_stream' should be called to create new streams. - - - -Tell if a given file has a chance of being parsed as this format. -The buffer provided is guaranteed to be AVPROBE_PADDING_SIZE bytes -big so you do not have to check for that unless you need more. - - - -Size of private data so that it can be allocated in the wrapper. - - - -Descriptive name for the format, meant to be more human-readable -than name. You should use the NULL_IF_CONFIG_SMALL() macro -to define it. - - - -A comma separated list of short names for the format. New names -may be appended with a minor bump. - - - -@} - -@addtogroup lavf_decoding -@{ - - - Can only be iformat or oformat, not both at the same time. - - decoding: set by avformat_open_input(). - encoding: set by the user. - - - - Test if the given codec can be stored in this container. - - @return 1 if the codec is supported, 0 if it is not. - A negative number if unknown. - - - -List of supported codec_id-codec_tag pairs, ordered by "better -choice first". The arrays are all terminated by CODEC_ID_NONE. - - - -can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_RAWPICTURE, -AVFMT_GLOBALHEADER, AVFMT_NOTIMESTAMPS, AVFMT_VARIABLE_FPS, -AVFMT_NODIMENSIONS, AVFMT_NOSTREAMS, AVFMT_ALLOW_FLUSH - - - -Write a packet. If AVFMT_ALLOW_FLUSH is set in flags, -pkt can be NULL in order to flush data buffered in the muxer. -When flushing, return 0 if there still is more data to flush, -or 1 if everything was flushed and there is no more buffered -data. - - - -size of private data so that it can be allocated in the wrapper - - - -Descriptive name for the format, meant to be more human-readable -than name. You should use the NULL_IF_CONFIG_SMALL() macro -to define it. - - - -Demuxer will use avio_open, no opened file should be provided by the caller. -@addtogroup lavf_encoding -@{ - - - -This structure contains the data a format has to probe a file. - - - - Read data and append it to the current content of the AVPacket. - If pkt->size is 0 this is identical to av_get_packet. - Note that this uses av_grow_packet and thus involves a realloc - which is inefficient. Thus this function should only be used - when there is no reasonable way to know (an upper bound of) - the final size. - - @param pkt packet - @param size amount of data to read - @return >0 (read size) if OK, AVERROR_xxx otherwise, previous data - will not be lost even if an error occurs. - - - -@} - - Allocate and read the payload of a packet and initialize its - fields with default values. - - @param pkt packet - @param size desired payload size - @return >0 (read size) if OK, AVERROR_xxx otherwise - - - -Free all the memory allocated for an AVDictionary struct. - - - -Copy metadata from one AVDictionary struct into another. -@param dst pointer to a pointer to a AVDictionary struct. If *dst is NULL, - this function will allocate a struct for you and put it in *dst -@param src pointer to source AVDictionary struct -@param flags flags to use when setting metadata in *dst -@note metadata is read using the AV_DICT_IGNORE_SUFFIX flag - - - -This function is provided for compatibility reason and currently does nothing. - - - - Get a metadata element with matching key. - - @param prev Set to the previous matching element to find the next. - If set to NULL the first matching element is returned. - @param flags Allows case as well as suffix-insensitive comparisons. - @return Found tag or NULL, changing key or value leads to undefined behavior. - - - -Seek to a given timestamp relative to some component stream. -Only meaningful if using a network streaming protocol (e.g. MMS.). -@param stream_index The stream index that the timestamp is relative to. - If stream_index is (-1) the timestamp should be in AV_TIME_BASE - units from the beginning of the presentation. - If a stream_index >= 0 is used and the protocol does not support - seeking based on component streams, the call will fail. -@param timestamp timestamp in AVStream.time_base units - or if there is no stream specified then in AV_TIME_BASE units. -@param flags Optional combination of AVSEEK_FLAG_BACKWARD, AVSEEK_FLAG_BYTE - and AVSEEK_FLAG_ANY. The protocol may silently ignore - AVSEEK_FLAG_BACKWARD and AVSEEK_FLAG_ANY, but AVSEEK_FLAG_BYTE will - fail if used and not supported. -@return >= 0 on success -@see AVInputFormat::read_seek - - - -Pause and resume playing - only meaningful if using a network streaming -protocol (e.g. MMS). -@param pause 1 for pause, 0 for resume - - - - Iterate through names of available protocols. - @note it is recommanded to use av_protocol_next() instead of this - - @param opaque A private pointer representing current protocol. - It must be a pointer to NULL on first iteration and will - be updated by successive calls to avio_enum_protocols. - @param output If set to 1, iterate over output protocols, - otherwise over input protocols. - - @return A static string containing the name of current protocol or NULL - - - - Return the written size and a pointer to the buffer. The buffer - must be freed with av_free(). - Padding of FF_INPUT_BUFFER_PADDING_SIZE is added to the buffer. - - @param s IO context - @param pbuffer pointer to a byte buffer - @return the length of the byte buffer - - - - Open a write only memory stream. - - @param s new IO context - @return zero if no error. - - - - Create and initialize a AVIOContext for accessing the - resource indicated by url. - @note When the resource indicated by url has been opened in - read+write mode, the AVIOContext can be used only for writing. - - @param s Used to return the pointer to the created AVIOContext. - In case of failure the pointed to value is set to NULL. - @param flags flags which control how the resource indicated by url - is to be opened - @param int_cb an interrupt callback to be used at the protocols level - @param options A dictionary filled with protocol-private options. On return - this parameter will be destroyed and replaced with a dict containing options - that were not found. May be NULL. - @return 0 in case of success, a negative value corresponding to an - AVERROR code in case of failure - - - -@name URL open modes -The flags argument to avio_open must be one of the following -constants, optionally ORed with other flags. -@{ - -@} - -Use non-blocking mode. -If this flag is set, operations on the context will return -AVERROR(EAGAIN) if they can not be performed immediately. -If this flag is not set, operations on the context will never return -AVERROR(EAGAIN). -Note that this flag does not affect the opening/connecting of the -context. Connecting a protocol will always block if necessary (e.g. on -network protocols) but never hang (e.g. on busy devices). -Warning: non-blocking protocols is work-in-progress; this flag may be -silently ignored. - - Create and initialize a AVIOContext for accessing the - resource indicated by url. - @note When the resource indicated by url has been opened in - read+write mode, the AVIOContext can be used only for writing. - - @param s Used to return the pointer to the created AVIOContext. - In case of failure the pointed to value is set to NULL. - @param flags flags which control how the resource indicated by url - is to be opened - @return 0 in case of success, a negative value corresponding to an - AVERROR code in case of failure - - - - @name Functions for reading from AVIOContext - @{ - - @note return 0 if EOF, so you cannot use it if EOF handling is - necessary - - - -Read size bytes from AVIOContext into buf. -@return number of bytes read or AVERROR - - - -@warning currently size is limited - - -feof() equivalent for AVIOContext. -@return non zero if and only if end of file - - - -Get the filesize. -@return filesize or AVERROR - - - -ftell() equivalent for AVIOContext. -@return position or AVERROR. - - - -Skip given number of bytes forward -@return new position or AVERROR. - - - -Convert an UTF-8 string to UTF-16LE and write it. -@return number of bytes written. - - - -Write a NULL-terminated string. -@return number of bytes written. - - - - Allocate and initialize an AVIOContext for buffered I/O. It must be later - freed with av_free(). - - @param buffer Memory block for input/output operations via AVIOContext. - The buffer must be allocated with av_malloc() and friends. - @param buffer_size The buffer size is very important for performance. - For protocols with fixed blocksize it should be set to this blocksize. - For others a typical size is a cache page, e.g. 4kb. - @param write_flag Set to 1 if the buffer should be writable, 0 otherwise. - @param opaque An opaque pointer to user-specific data. - @param read_packet A function for refilling the buffer, may be NULL. - @param write_packet A function for writing the buffer contents, may be NULL. - @param seek A function for seeking to specified byte position, may be NULL. - - @return Allocated AVIOContext or NULL on failure. - - - -The callback is called in blocking functions to test regulary if -asynchronous interruption is needed. AVERROR_EXIT is returned -in this case by the interrupted function. 'NULL' means no interrupt -callback is given. -@deprecated Use interrupt_callback in AVFormatContext/avio_open2 - instead. - - - - Return AVIO_FLAG_* access flags corresponding to the access permissions - of the resource in url, or a negative value corresponding to an - AVERROR code in case of failure. The returned access flags are - masked by the value in flags. - - @note This function is intrinsically unsafe, in the sense that the - checked resource may change its existence or permission status from - one call to another. Thus you should not trust the returned value, - unless you are sure that no other processes are accessing the - checked resource. - - - -Return a non-zero value if the resource indicated by url -exists, 0 otherwise. -@deprecated Use avio_check instead. - - - -return the written or read size - - -@deprecated use AVIOContext.max_packet_size directly. - - - -@deprecated Use AVIOContext.seekable field directly. - - - -@deprecated use avio_get_str instead - - - -@note unlike fgets, the EOL character is not returned and a whole - line is parsed. return NULL if first char read was EOF - - -@} - - - -@defgroup old_url_f_funcs Old url_f* functions -The following functions are deprecated, use the "avio_"-prefixed functions instead. -@{ -@ingroup lavf_io - - - -@} - - - -@defgroup old_avio_funcs Old put_/get_*() functions -The following functions are deprecated. Use the "avio_"-prefixed functions instead. -@{ -@ingroup lavf_io - - - -@} - - - - Register the URLProtocol protocol. - - @param size the size of the URLProtocol struct referenced - - - -returns the next registered protocol after the given protocol (the first if -NULL is given), or NULL if protocol is the last one. - - - -@defgroup old_url_funcs Old url_* functions -The following functions are deprecated. Use the buffered API based on #AVIOContext instead. -@{ -@ingroup lavf_io - - - -@name URL open modes -The flags argument to url_open and cosins must be one of the following -constants, optionally ORed with other flags. -@{ - -@} - -Use non-blocking mode. -If this flag is set, operations on the context will return -AVERROR(EAGAIN) if they can not be performed immediately. -If this flag is not set, operations on the context will never return -AVERROR(EAGAIN). -Note that this flag does not affect the opening/connecting of the -context. Connecting a protocol will always block if necessary (e.g. on -network protocols) but never hang (e.g. on busy devices). -Warning: non-blocking protocols is work-in-progress; this flag may be -silently ignored. - - - -@deprecated This struct is to be made private. Use the higher-level - AVIOContext-based API instead. - - - -URL Context. -New fields can be added to the end with minor version bumps. -Removal, reordering and changes to existing fields require a major -version bump. -sizeof(URLContext) must not be used outside libav*. -@deprecated This struct will be made private - - - - -Close currently opened video file if any. - - - - -Write new video frame with a specific timestamp into currently opened video file. - - Bitmap to add as a new video frame. - Frame timestamp, total time since recording started. - - The specified bitmap must be either color 24 or 32 bpp image or grayscale 8 bpp (indexed) image. - - The parameter allows user to specify presentation -time of the frame being saved. However, it is user's responsibility to make sure the value is increasing -over time. - - - Thrown if no video file was open. - The provided bitmap must be 24 or 32 bpp color image or 8 bpp grayscale image. - Bitmap size must be of the same as video size, which was specified on opening video file. - A error occurred while writing new video frame. See exception message. - - - -Write new video frame into currently opened video file. - - Bitmap to add as a new video frame. - - The specified bitmap must be either color 24 or 32 bpp image or grayscale 8 bpp (indexed) image. - - Thrown if no video file was open. - The provided bitmap must be 24 or 32 bpp color image or 8 bpp grayscale image. - Bitmap size must be of the same as video size, which was specified on opening video file. - A error occurred while writing new video frame. See exception message. - - - -Create video file with the specified name and attributes. - - Video file name to create. - Frame width of the video file. - Frame height of the video file. - Frame rate of the video file. - Video codec to use for compression. - Bit rate of the video stream. - - The methods creates new video file with the specified name. -If a file with such name already exists in the file system, it will be overwritten. - When adding new video frames using method, -the video frame must have width and height as specified during file opening. - - The bit rate parameter represents a trade-off value between video quality -and video file size. Higher bit rate value increase video quality and result in larger -file size. Smaller values result in opposite – worse quality and small video files. - - - Video file resolution must be a multiple of two. - Invalid video codec is specified. - A error occurred while creating new video file. See exception message. - Cannot open video file with the specified name. - - - -Create video file with the specified name and attributes. - - Video file name to create. - Frame width of the video file. - Frame height of the video file. - Frame rate of the video file. - Video codec to use for compression. - - The methods creates new video file with the specified name. -If a file with such name already exists in the file system, it will be overwritten. - When adding new video frames using method, -the video frame must have width and height as specified during file opening. - - Video file resolution must be a multiple of two. - Invalid video codec is specified. - A error occurred while creating new video file. See exception message. - Cannot open video file with the specified name. - - - -Create video file with the specified name and attributes. - - Video file name to create. - Frame width of the video file. - Frame height of the video file. - Frame rate of the video file. - - See documentation to the -for more information and the list of possible exceptions. - - The method opens the video file using -codec. - - - - - -Create video file with the specified name and attributes. - - Video file name to create. - Frame width of the video file. - Frame height of the video file. - - See documentation to the -for more information and the list of possible exceptions. - - The method opens the video file using -codec and 25 fps frame rate. - - - - - -Disposes the object and frees its resources. - - - - -Initializes a new instance of the class. - - - - -Object's finalizer. - - - - -The property specifies if a video file is opened or not by this instance of the class. - - - - -Codec to use for the video file. - - Thrown if no video file was open. - - - -Bit rate of the video stream. - - Thrown if no video file was open. - - - -Frame rate of the opened video file. - - Thrown if no video file was open. - - - -Frame height of the opened video file. - - Thrown if no video file was open. - - - -Frame width of the opened video file. - - Thrown if no video file was open. - - - -Class for writing video files utilizing FFmpeg library. - - - The class allows to write video files using FFmpeg library. - - Make sure you have FFmpeg binaries (DLLs) in the output folder of your application in order -to use this class successfully. FFmpeg binaries can be found in Externals folder provided with AForge.NET -framework's distribution. - - Sample usage: - -int width = 320; -int height = 240; - -// create instance of video writer -VideoFileWriter writer = new VideoFileWriter( ); -// create new video file -writer.Open( "test.avi", width, height, 25, VideoCodec.MPEG4 ); -// create a bitmap to save into the video file -Bitmap image = new Bitmap( width, height, PixelFormat.Format24bppRgb ); -// write 1000 video frames -for ( int i = 0; i < 1000; i++ ) -{ - image.SetPixel( i % width, i % height, Color.Red ); - writer.WriteVideoFrame( image ); -} -writer.Close( ); - - - - - Get the AVClass for AVFrame. It can be used in combination with - AV_OPT_SEARCH_FAKE_OBJ for examining options. - - @see av_opt_find(). - - - - Get the AVClass for AVCodecContext. It can be used in combination with - AV_OPT_SEARCH_FAKE_OBJ for examining options. - - @see av_opt_find(). - - - - Register a user provided lock manager supporting the operations - specified by AVLockOp. mutex points to a (void *) where the - lockmgr should store/get a pointer to a user allocated mutex. It's - NULL upon AV_LOCK_CREATE and != NULL for all other ops. - - @param cb User defined callback. Note: FFmpeg may invoke calls to this - callback during the call to av_lockmgr_register(). - Thus, the application must be prepared to handle that. - If cb is set to NULL the lockmgr will be unregistered. - Also note that during unregistration the previously registered - lockmgr callback may also be invoked. - - - -Lock operation used by lockmgr - - - -If hwaccel is NULL, returns the first registered hardware accelerator, -if hwaccel is non-NULL, returns the next registered hardware accelerator -after hwaccel, or NULL if hwaccel is the last one. - - - -Register the hardware accelerator hwaccel. - - - -Log a generic warning message asking for a sample. This function is -intended to be used internally by FFmpeg (libavcodec, libavformat, etc.) -only, and would normally not be used by applications. -@param[in] avc a pointer to an arbitrary struct of which the first field is -a pointer to an AVClass struct -@param[in] msg string containing an optional message, or NULL if no message - - - -Log a generic warning message about a missing feature. This function is -intended to be used internally by FFmpeg (libavcodec, libavformat, etc.) -only, and would normally not be used by applications. -@param[in] avc a pointer to an arbitrary struct of which the first field is -a pointer to an AVClass struct -@param[in] feature string containing the name of the missing feature -@param[in] want_sample indicates if samples are wanted which exhibit this feature. -If want_sample is non-zero, additional verbage will be added to the log -message which tells the user how to report samples to the development -mailing list. - - - - Encode extradata length to a buffer. Used by xiph codecs. - - @param s buffer to write to; must be at least (v/255+1) bytes long - @param v size of extradata in bytes - @return number of bytes written to the buffer. - - - -Pad image. - - - -Crop image top and left side. - - - -Copy image src to dst. Wraps av_picture_data_copy() above. - - - - Same behaviour av_fast_malloc but the buffer has additional - FF_INPUT_PADDING_SIZE at the end which will will always be 0. - - In addition the whole buffer will initially and after resizes - be 0-initialized so that no uninitialized data will ever appear. - - - - Allocate a buffer, reusing the given one if large enough. - - Contrary to av_fast_realloc the current buffer contents might not be - preserved and on error the old buffer is freed, thus no special - handling to avoid memleaks is necessary. - - @param ptr pointer to pointer to already allocated buffer, overwritten with pointer to new buffer - @param size size of the buffer *ptr points to - @param min_size minimum size of *ptr buffer after returning, *ptr will be NULL and - *size 0 if an error occurred. - - - - Reallocate the given block if it is not large enough, otherwise do nothing. - - @see av_realloc - - - -Previous frame byte position. - - - -Byte position of currently parsed frame in stream. - - - - Position of the packet in file. - - Analogous to cur_frame_pts/dts - - - - Presentation delay of current frame in units of AVCodecContext.time_base. - - Set to INT_MIN when dts_sync_point unused. Otherwise, it must - contain valid non-negative timestamp delta (presentation time of a frame - must not lie in the past). - - This delay represents the difference between decoding and presentation - time of the frame. - - For example, this corresponds to H.264 dpb_output_delay. - - - - Offset of the current timestamp against last timestamp sync point in - units of AVCodecContext.time_base. - - Set to INT_MIN when dts_sync_point unused. Otherwise, it must - contain a valid timestamp offset. - - Note that the timestamp of sync point has usually a nonzero - dts_ref_dts_delta, which refers to the previous sync point. Offset of - the next frame after timestamp sync point will be usually 1. - - For example, this corresponds to H.264 cpb_removal_delay. - - - - Time difference in stream time base units from the pts of this - packet to the point at which the output from the decoder has converged - independent from the availability of previous frames. That is, the - frames are virtually identical no matter if decoding started from - the very first frame or from this keyframe. - Is AV_NOPTS_VALUE if unknown. - This field is not the display duration of the current frame. - This field has no meaning if the packet does not have AV_PKT_FLAG_KEY - set. - - The purpose of this field is to allow seeking in streams that have no - keyframes in the conventional sense. It corresponds to the - recovery point SEI in H.264 and match_time_delta in NUT. It is also - essential for some types of subtitle streams to ensure that all - subtitles are correctly displayed after seeking. - - - -Set by parser to 1 for key frames and 0 for non-key frames. -It is initialized to -1, so if the parser doesn't set this flag, -old-style fallback using AV_PICTURE_TYPE_I picture type as key frames -will be used. - - - -Set if the parser has a valid file offset - - - This field is used for proper frame duration computation in lavf. - It signals, how much longer the frame duration of the current frame - is compared to normal frame duration. - - frame_duration = (1 + repeat_pict) * time_base - - It is used by codecs like H.264 to display telecined material. - - - -@deprecated Use av_get_bytes_per_sample() instead. - - - - Return codec bits per sample. - - @param[in] codec_id the codec - @return Number of bits per sample or zero if unknown for the given codec. - - - - Return a single letter to describe the given picture type pict_type. - - @param[in] pict_type the picture type - @return A single character representing the picture type. - @deprecated Use av_get_picture_type_char() instead. - - - -Flush buffers, should be called when seeking or when switching to a different stream. - - - - Register all the codecs, parsers and bitstream filters which were enabled at - configuration time. If you do not call this function you can select exactly - which formats you want to support, by using the individual registration - functions. - - @see avcodec_register - @see av_register_codec_parser - @see av_register_bitstream_filter - - - - Encode a video frame from pict into buf. - The input picture should be - stored using a specific format, namely avctx.pix_fmt. - - @param avctx the codec context - @param[out] buf the output buffer for the bitstream of encoded frame - @param[in] buf_size the size of the output buffer in bytes - @param[in] pict the input picture to encode - @return On error a negative value is returned, on success zero or the number - of bytes used from the output buffer. - - - - Fill audio frame data and linesize. - AVFrame extended_data channel pointers are allocated if necessary for - planar audio. - - @param frame the AVFrame - frame->nb_samples must be set prior to calling the - function. This function fills in frame->data, - frame->extended_data, frame->linesize[0]. - @param nb_channels channel count - @param sample_fmt sample format - @param buf buffer to use for frame data - @param buf_size size of buffer - @param align plane size sample alignment - @return 0 on success, negative error code on failure - - - - Encode a frame of audio. - - Takes input samples from frame and writes the next output packet, if - available, to avpkt. The output packet does not necessarily contain data for - the most recent frame, as encoders can delay, split, and combine input frames - internally as needed. - - @param avctx codec context - @param avpkt output AVPacket. - The user can supply an output buffer by setting - avpkt->data and avpkt->size prior to calling the - function, but if the size of the user-provided data is not - large enough, encoding will fail. All other AVPacket fields - will be reset by the encoder using av_init_packet(). If - avpkt->data is NULL, the encoder will allocate it. - The encoder will set avpkt->size to the size of the - output packet. - @param[in] frame AVFrame containing the raw audio data to be encoded. - May be NULL when flushing an encoder that has the - CODEC_CAP_DELAY capability set. - There are 2 codec capabilities that affect the allowed - values of frame->nb_samples. - If CODEC_CAP_SMALL_LAST_FRAME is set, then only the final - frame may be smaller than avctx->frame_size, and all other - frames must be equal to avctx->frame_size. - If CODEC_CAP_VARIABLE_FRAME_SIZE is set, then each frame - can have any number of samples. - If neither is set, frame->nb_samples must be equal to - avctx->frame_size for all frames. - @param[out] got_packet_ptr This field is set to 1 by libavcodec if the - output packet is non-empty, and to 0 if it is - empty. If the function returns an error, the - packet can be assumed to be invalid, and the - value of got_packet_ptr is undefined and should - not be used. - @return 0 on success, negative error code on failure - - - - Encode an audio frame from samples into buf. - - @deprecated Use avcodec_encode_audio2 instead. - - @note The output buffer should be at least FF_MIN_BUFFER_SIZE bytes large. - However, for codecs with avctx->frame_size equal to 0 (e.g. PCM) the user - will know how much space is needed because it depends on the value passed - in buf_size as described below. In that case a lower value can be used. - - @param avctx the codec context - @param[out] buf the output buffer - @param[in] buf_size the output buffer size - @param[in] samples the input buffer containing the samples - The number of samples read from this buffer is frame_size*channels, - both of which are defined in avctx. - For codecs which have avctx->frame_size equal to 0 (e.g. PCM) the number of - samples read from samples is equal to: - buf_size * 8 / (avctx->channels * av_get_bits_per_sample(avctx->codec_id)) - This also implies that av_get_bits_per_sample() must not return 0 for these - codecs. - @return On error a negative value is returned, on success zero or the number - of bytes used to encode the data read from the input buffer. - - - - Free all allocated data in the given subtitle struct. - - @param sub AVSubtitle to free. - - - - * Decode a subtitle message. - * Return a negative value on error, otherwise return the number of bytes used. - * If no subtitle could be decompressed, got_sub_ptr is zero. - * Otherwise, the subtitle is stored in *sub. - * Note that CODEC_CAP_DR1 is not available for subtitle codecs. This is for - * simplicity, because the performance difference is expect to be negligible - * and reusing a get_buffer written for video codecs would probably perform badly - * due to a potentially very different allocation pattern. - * - * @param avctx the codec context - * @param[out] sub The AVSubtitle in which the decoded subtitle will be stored, must be - freed with avsubtitle_free if *got_sub_ptr is set. - * @param[in,out] got_sub_ptr Zero if no subtitle could be decompressed, otherwise, it is nonzero. - * @param[in] avpkt The input AVPacket containing the input buffer. - - - - Decode the audio frame of size avpkt->size from avpkt->data into frame. - - Some decoders may support multiple frames in a single AVPacket. Such - decoders would then just decode the first frame. In this case, - avcodec_decode_audio4 has to be called again with an AVPacket containing - the remaining data in order to decode the second frame, etc... - Even if no frames are returned, the packet needs to be fed to the decoder - with remaining data until it is completely consumed or an error occurs. - - @warning The input buffer, avpkt->data must be FF_INPUT_BUFFER_PADDING_SIZE - larger than the actual read bytes because some optimized bitstream - readers read 32 or 64 bits at once and could read over the end. - - @note You might have to align the input buffer. The alignment requirements - depend on the CPU and the decoder. - - @param avctx the codec context - @param[out] frame The AVFrame in which to store decoded audio samples. - Decoders request a buffer of a particular size by setting - AVFrame.nb_samples prior to calling get_buffer(). The - decoder may, however, only utilize part of the buffer by - setting AVFrame.nb_samples to a smaller value in the - output frame. - @param[out] got_frame_ptr Zero if no frame could be decoded, otherwise it is - non-zero. - @param[in] avpkt The input AVPacket containing the input buffer. - At least avpkt->data and avpkt->size should be set. Some - decoders might also require additional fields to be set. - @return A negative error code is returned if an error occurred during - decoding, otherwise the number of bytes consumed from the input - AVPacket is returned. - - - - Wrapper function which calls avcodec_decode_audio4. - - @deprecated Use avcodec_decode_audio4 instead. - - Decode the audio frame of size avpkt->size from avpkt->data into samples. - Some decoders may support multiple frames in a single AVPacket, such - decoders would then just decode the first frame. In this case, - avcodec_decode_audio3 has to be called again with an AVPacket that contains - the remaining data in order to decode the second frame etc. - If no frame - could be outputted, frame_size_ptr is zero. Otherwise, it is the - decompressed frame size in bytes. - - @warning You must set frame_size_ptr to the allocated size of the - output buffer before calling avcodec_decode_audio3(). - - @warning The input buffer must be FF_INPUT_BUFFER_PADDING_SIZE larger than - the actual read bytes because some optimized bitstream readers read 32 or 64 - bits at once and could read over the end. - - @warning The end of the input buffer avpkt->data should be set to 0 to ensure that - no overreading happens for damaged MPEG streams. - - @warning You must not provide a custom get_buffer() when using - avcodec_decode_audio3(). Doing so will override it with - avcodec_default_get_buffer. Use avcodec_decode_audio4() instead, - which does allow the application to provide a custom get_buffer(). - - @note You might have to align the input buffer avpkt->data and output buffer - samples. The alignment requirements depend on the CPU: On some CPUs it isn't - necessary at all, on others it won't work at all if not aligned and on others - it will work but it will have an impact on performance. - - In practice, avpkt->data should have 4 byte alignment at minimum and - samples should be 16 byte aligned unless the CPU doesn't need it - (AltiVec and SSE do). - - @note Codecs which have the CODEC_CAP_DELAY capability set have a delay - between input and output, these need to be fed with avpkt->data=NULL, - avpkt->size=0 at the end to return the remaining frames. - - @param avctx the codec context - @param[out] samples the output buffer, sample type in avctx->sample_fmt - If the sample format is planar, each channel plane will - be the same size, with no padding between channels. - @param[in,out] frame_size_ptr the output buffer size in bytes - @param[in] avpkt The input AVPacket containing the input buffer. - You can create such packet with av_init_packet() and by then setting - data and size, some decoders might in addition need other fields. - All decoders are designed to use the least fields possible though. - @return On error a negative value is returned, otherwise the number of bytes - used or zero if no frame data was decompressed (used) from the input AVPacket. - - - -@deprecated Set s->thread_count before calling avcodec_open2() instead of calling this. - - - - Modify width and height values so that they will result in a memory - buffer that is acceptable for the codec if you also ensure that all - line sizes are a multiple of the respective linesize_align[i]. - - May only be used if a codec with CODEC_CAP_DR1 has been opened. - If CODEC_FLAG_EMU_EDGE is not set, the dimensions must have been increased - according to avcodec_get_edge_width() before. - - - - Modify width and height values so that they will result in a memory - buffer that is acceptable for the codec if you do not use any horizontal - padding. - - May only be used if a codec with CODEC_CAP_DR1 has been opened. - If CODEC_FLAG_EMU_EDGE is not set, the dimensions must have been increased - according to avcodec_get_edge_width() before. - - - - Return the amount of padding in pixels which the get_buffer callback must - provide around the edge of the image for codecs which do not have the - CODEC_FLAG_EMU_EDGE flag. - - @return Required padding in pixels. - - - - Allocate an AVFrame and set its fields to default values. The resulting - struct can be deallocated by simply calling av_free(). - - @return An AVFrame filled with default values or NULL on failure. - @see avcodec_get_frame_defaults - - - - Set the fields of the given AVFrame to default values. - - @param pic The AVFrame of which the fields should be set to default values. - - - - Copy the settings of the source AVCodecContext into the destination - AVCodecContext. The resulting destination codec context will be - unopened, i.e. you are required to call avcodec_open2() before you - can use this AVCodecContext to decode/encode video/audio data. - - @param dest target codec context, should be initialized with - avcodec_alloc_context3(), but otherwise uninitialized - @param src source codec context - @return AVERROR() on error (e.g. memory allocation error), 0 on success - - - - Allocate an AVCodecContext and set its fields to default values. The - resulting struct can be deallocated by simply calling av_free(). - - @param codec if non-NULL, allocate private data and initialize defaults - for the given codec. It is illegal to then call avcodec_open2() - with a different codec. - - @return An AVCodecContext filled with default values or NULL on failure. - @see avcodec_get_context_defaults - - - -THIS FUNCTION IS NOT YET PART OF THE PUBLIC API! - * we WILL change its arguments and name a few times! - - - Allocate an AVCodecContext and set its fields to default values. The - resulting struct can be deallocated by simply calling av_free(). - - @return An AVCodecContext filled with default values or NULL on failure. - @see avcodec_get_context_defaults - - @deprecated use avcodec_alloc_context3() - - - - Set the fields of the given AVCodecContext to default values corresponding - to the given codec (defaults may be codec-dependent). - - Do not call this function if a non-NULL codec has been passed - to avcodec_alloc_context3() that allocated this AVCodecContext. - If codec is non-NULL, it is illegal to call avcodec_open2() with a - different codec on this AVCodecContext. - - - -THIS FUNCTION IS NOT YET PART OF THE PUBLIC API! - * we WILL change its arguments and name a few times! - - - Set the fields of the given AVCodecContext to default values. - - @param s The AVCodecContext of which the fields should be set to default values. - @deprecated use avcodec_get_context_defaults3 - - - - Return a name for the specified profile, if available. - - @param codec the codec that is searched for the given profile - @param profile the profile value for which a name is requested - @return A name for the profile if found, NULL otherwise. - - - - Find a registered decoder with the specified name. - - @param name name of the requested decoder - @return A decoder if one was found, NULL otherwise. - - - - Find a registered decoder with a matching codec ID. - - @param id CodecID of the requested decoder - @return A decoder if one was found, NULL otherwise. - - - - Find a registered encoder with the specified name. - - @param name name of the requested encoder - @return An encoder if one was found, NULL otherwise. - - - - Find a registered encoder with a matching codec ID. - - @param id CodecID of the requested encoder - @return An encoder if one was found, NULL otherwise. - - - - Register the codec codec and initialize libavcodec. - - @warning either this function or avcodec_register_all() must be called - before any other libavcodec functions. - - @see avcodec_register_all() - - - -@deprecated this function is called automatically from avcodec_register() -and avcodec_register_all(), there is no need to call it manually - - - -Return the libavcodec license. - - - -Return the libavcodec build-time configuration. - - - -Return the LIBAVCODEC_VERSION_INT constant. - - - -If c is NULL, returns the first registered codec, -if c is non-NULL, returns the next registered codec after c, -or NULL if c is the last one. - - - -Tell if an image really has transparent alpha values. -@return ored mask of FF_ALPHA_xxx constants - - - - Compute what kind of losses will occur when converting from one specific - pixel format to another. - When converting from one pixel format to another, information loss may occur. - For example, when converting from RGB24 to GRAY, the color information will - be lost. Similarly, other losses occur when converting from some formats to - other formats. These losses can involve loss of chroma, but also loss of - resolution, loss of color depth, loss due to the color space conversion, loss - of the alpha bits or loss due to color quantization. - avcodec_get_fix_fmt_loss() informs you about the various types of losses - which will occur when converting from one pixel format to another. - - @param[in] dst_pix_fmt destination pixel format - @param[in] src_pix_fmt source pixel format - @param[in] has_alpha Whether the source pixel format alpha channel is used. - @return Combination of flags informing you what kind of losses will occur - (maximum loss for an invalid dst_pix_fmt). - - - - Put a string representing the codec tag codec_tag in buf. - - @param buf_size size in bytes of buf - @return the length of the string that would have been generated if - enough space had been available, excluding the trailing null - - - -Return a value representing the fourCC code associated to the -pixel format pix_fmt, or 0 if no associated fourCC code can be -found. - - - - Return the short name for a pixel format. - - \see av_get_pix_fmt(), av_get_pix_fmt_string(). - @deprecated Deprecated in favor of av_get_pix_fmt_name(). - - - -Get the name of a codec. -@return a static string identifying the codec; never NULL - - - - Calculate the size in bytes that a picture of the given width and height - would occupy if stored in the given picture format. - Note that this returns the size of a compact representation as generated - by avpicture_layout(), which can be smaller than the size required for e.g. - avpicture_fill(). - - @param pix_fmt the given picture format - @param width the width of the image - @param height the height of the image - @return Image data size in bytes or -1 on error (e.g. too large dimensions). - - - - Copy pixel data from an AVPicture into a buffer. - The data is stored compactly, without any gaps for alignment or padding - which may be applied by avpicture_fill(). - - @see avpicture_get_size() - - @param[in] src AVPicture containing image data - @param[in] pix_fmt The format in which the picture data is stored. - @param[in] width the width of the image in pixels. - @param[in] height the height of the image in pixels. - @param[out] dest A buffer into which picture data will be copied. - @param[in] dest_size The size of 'dest'. - @return The number of bytes written to dest, or a negative value (error code) on error. - - - - Fill in the AVPicture fields. - The fields of the given AVPicture are filled in by using the 'ptr' address - which points to the image data buffer. Depending on the specified picture - format, one or multiple image data pointers and line sizes will be set. - If a planar format is specified, several pointers will be set pointing to - the different picture planes and the line sizes of the different planes - will be stored in the lines_sizes array. - Call with ptr == NULL to get the required size for the ptr buffer. - - To allocate the buffer and fill in the AVPicture fields in one call, - use avpicture_alloc(). - - @param picture AVPicture whose fields are to be filled in - @param ptr Buffer which will contain or contains the actual image data - @param pix_fmt The format in which the picture data is stored. - @param width the width of the image in pixels - @param height the height of the image in pixels - @return size of the image data in bytes - - - - Free a picture previously allocated by avpicture_alloc(). - The data buffer used by the AVPicture is freed, but the AVPicture structure - itself is not. - - @param picture the AVPicture to be freed - - - - Allocate memory for a picture. Call avpicture_free() to free it. - - @see avpicture_fill() - - @param picture the picture to be filled in - @param pix_fmt the format of the picture - @param width the width of the picture - @param height the height of the picture - @return zero if successful, a negative value if not - - - - Compensate samplerate/timestamp drift. The compensation is done by changing - the resampler parameters, so no audible clicks or similar distortions occur - @param compensation_distance distance in output samples over which the compensation should be performed - @param sample_delta number of output samples which should be output less - - example: av_resample_compensate(c, 10, 500) - here instead of 510 samples only 500 samples would be output - - note, due to rounding the actual compensation might be slightly different, - especially if the compensation_distance is large and the in_rate used during init is small - - - -Resample an array of samples using a previously configured context. -@param src an array of unconsumed samples -@param consumed the number of samples of src which have been consumed are returned here -@param src_size the number of unconsumed samples available -@param dst_size the amount of space in samples available in dst -@param update_ctx If this is 0 then the context will not be modified, that way several channels can be resampled with the same context. -@return the number of samples written in dst or -1 if an error occurred - - - - * Initialize an audio resampler. - * Note, if either rate is not an integer then simply scale both rates up so they are. - * @param filter_length length of each FIR filter in the filterbank relative to the cutoff freq - * @param log2_phase_count log2 of the number of entries in the polyphase filterbank - * @param linear If 1 then the used FIR filter will be linearly interpolated - between the 2 closest, if 0 the closest will be used - * @param cutoff cutoff frequency, 1.0 corresponds to half the output sampling rate - - - - Free resample context. - - @param s a non-NULL pointer to a resample context previously - created with av_audio_resample_init() - - - - * Initialize audio resampling context. - * - * @param output_channels number of output channels - * @param input_channels number of input channels - * @param output_rate output sample rate - * @param input_rate input sample rate - * @param sample_fmt_out requested output sample format - * @param sample_fmt_in input sample format - * @param filter_length length of each FIR filter in the filterbank relative to the cutoff frequency - * @param log2_phase_count log2 of the number of entries in the polyphase filterbank - * @param linear if 1 then the used FIR filter will be linearly interpolated - between the 2 closest, if 0 the closest will be used - * @param cutoff cutoff frequency, 1.0 corresponds to half the output sampling rate - * @return allocated ReSampleContext, NULL if error occurred - - - - Get side information from packet. - - @param pkt packet - @param type desired side information type - @param size pointer for side information size to store (optional) - @return pointer to data if present or NULL otherwise - - - - Allocate new information of a packet. - - @param pkt packet - @param type side information type - @param size side information size - @return pointer to fresh allocated data or NULL otherwise - - - - Free a packet. - - @param pkt packet to free - - - -@warning This is a hack - the packet memory allocation stuff is broken. The -packet is allocated if it was not really allocated. - - - - Increase packet size, correctly zeroing padding - - @param pkt packet - @param grow_by number of bytes by which to increase the size of the packet - - - - Reduce packet size, correctly zeroing padding - - @param pkt packet - @param size new size - - - - Allocate the payload of a packet and initialize its fields with - default values. - - @param pkt packet - @param size wanted payload size - @return 0 if OK, AVERROR_xxx otherwise - - - - Initialize optional fields of a packet with default values. - - @param pkt packet - - - -Default packet destructor. - - - -@deprecated use NULL instead - - - -0 terminated ASS/SSA compatible event line. -The pressentation of this is unaffected by the other values in this -struct. - - - -data+linesize for the bitmap of this subtitle. -can be set for text/ass as well once they where rendered - - - -Formatted text, the ass field must be set by the decoder and is -authoritative. pict and text fields may contain approximations. - - - -Plain text, the text field must be set by the decoder and is -authoritative. ass and pict fields may contain approximations. - - - -four components are given, that's all. -the last component is alpha - - - - Size of HW accelerator private data. - - Private data is allocated with av_mallocz() before - AVCodecContext.get_buffer() and deallocated after - AVCodecContext.release_buffer(). - - - - Called at the end of each frame or field picture. - - The whole picture is parsed at this point and can now be sent - to the hardware accelerator. This function is mandatory. - - @param avctx the codec context - @return zero if successful, a negative value otherwise - - - - Callback for each slice. - - Meaningful slice information (codec specific) is guaranteed to - be parsed at this point. This function is mandatory. - - @param avctx the codec context - @param buf the slice data buffer base - @param buf_size the size of the slice in bytes - @return zero if successful, a negative value otherwise - - - - Called at the beginning of each frame or field picture. - - Meaningful frame information (codec specific) is guaranteed to - be parsed at this point. This function is mandatory. - - Note that buf can be NULL along with buf_size set to 0. - Otherwise, this means the whole frame is available at this point. - - @param avctx the codec context - @param buf the frame data buffer base - @param buf_size the size of the frame in bytes - @return zero if successful, a negative value otherwise - - - -Hardware accelerated codec capabilities. -see FF_HWACCEL_CODEC_CAP_* - - - - Codec implemented by the hardware accelerator. - - See CODEC_ID_xxx - - -Forced video codec_id. -Demuxing: Set by user. - - -Forced audio codec_id. -Demuxing: Set by user. - - -Forced subtitle codec_id. -Demuxing: Set by user. - - -@} - - -Guess the codec ID based upon muxer and filename. - - - Get the CodecID for the given codec tag tag. - If no codec id is found returns CODEC_ID_NONE. - - @param tags list of supported codec_id-codec_tag pairs, as stored - in AVInputFormat.codec_tag and AVOutputFormat.codec_tag - - - -Name of the hardware accelerated codec. -The name is globally unique among encoders and among decoders (but an -encoder and a decoder can share the same name). - - - - Encode data to an AVPacket. - - @param avctx codec context - @param avpkt output AVPacket (may contain a user-provided buffer) - @param[in] frame AVFrame containing the raw data to be encoded - @param[out] got_packet_ptr encoder sets to 0 or 1 to indicate that a - non-empty packet was returned in avpkt. - @return 0 on success, negative error code on failure - - - -Initialize codec static data, called from avcodec_register(). - - - -@} -Private codec-specific defaults. - - - - Copy necessary context variables from a previous thread context to the current one. - If not defined, the next thread will start automatically; otherwise, the codec - must call ff_thread_finish_setup(). - - dst and src will (rarely) point to the same context, in which case memcpy should be skipped. - - - -@name Frame-level threading support functions -@{ - -If defined, called on thread contexts when they are created. -If the codec allocates writable tables in init(), re-allocate them here. -priv_data will be set to a copy of the original. - - - -Descriptive name for the codec, meant to be more human readable than name. -You should use the NULL_IF_CONFIG_SMALL() macro to define it. - - - -Flush buffers. -Will be called when seeking - - - -Codec capabilities. -see CODEC_CAP_* - - - -Name of the codec implementation. -The name is globally unique among encoders and among decoders (but an -encoder and a decoder can share the same name). -This is the primary way to find a codec from the user perspective. - - - -AVCodec. - - - -AVProfile. - - - -Current statistics for PTS correction. -- decoding: maintained and used by libavcodec, not intended to be used by user apps -- encoding: unused - - - -Field order - * - encoding: set by libavcodec - * - decoding: Set by libavcodec - - - - Private context used for internal data. - - Unlike priv_data, this is not codec-specific. It is used in general - libavcodec functions. - - - -Error recognition; may misdetect some more or less valid parts as errors. -- encoding: unused -- decoding: Set by user. - - - -Type of service that the audio stream conveys. -- encoding: Set by user. -- decoding: Set by libavcodec. - - - -VBV delay coded in the last frame (in periods of a 27 MHz clock). -Used for compliant TS muxing. -- encoding: Set by libavcodec. -- decoding: unused. - - - -Set by the client if its custom get_buffer() callback can be called -from another thread, which allows faster multithreaded decoding. -draw_horiz_band() will be called from other threads regardless of this setting. -Ignored if the default get_buffer() is used. -- encoding: Set by user. -- decoding: Set by user. - - - -Which multithreading methods are in use by the codec. -- encoding: Set by libavcodec. -- decoding: Set by libavcodec. - - - - Which multithreading methods to use. - Use of FF_THREAD_FRAME will increase decoding delay by one frame per thread, - so clients which cannot provide future frames should not use it. - - - encoding: Set by user, otherwise the default is used. - - decoding: Set by user, otherwise the default is used. - - - - Whether this is a copy of the context which had init() called on it. - This is used by multithreading - shared tables and picture pointers - should be freed from the original context only. - - encoding: Set by libavcodec. - - decoding: Set by libavcodec. - - @deprecated this field has been moved to an internal context - - - -Current packet as passed into the decoder, to avoid having -to pass the packet into every function. Currently only valid -inside lavc and get/release_buffer callbacks. -- decoding: set by avcodec_decode_*, read by get_buffer() for setting pkt_pts -- encoding: unused - - - -Header containing style information for text subtitles. -For SUBTITLE_ASS subtitle type, it should contain the whole ASS -[Script Info] and [V4+ Styles] section, plus the [Events] line and -the Format line following. It shouldn't include any Dialogue line. -- encoding: Set/allocated/freed by user (before avcodec_open2()) -- decoding: Set/allocated/freed by libavcodec (by avcodec_open2()) - - - -Number of slices. -Indicates number of picture subdivisions. Used for parallelized -decoding. -- encoding: Set by user -- decoding: unused - - - -Number of passes to use for Cholesky factorization during LPC analysis -- encoding: Set by user -- decoding: unused - - - -Constant rate factor maximum -With CRF encoding mode and VBV restrictions enabled, prevents quality from being worse -than crf_max, even if doing so would violate VBV restrictions. -- encoding: Set by user. -- decoding: unused - - - -RC lookahead -Number of frames for frametype and ratecontrol lookahead -- encoding: Set by user -- decoding: unused - - - -PSY trellis -Strength of psychovisual optimization -- encoding: Set by user -- decoding: unused - - - -PSY RD -Strength of psychovisual optimization -- encoding: Set by user -- decoding: unused - - - -AQ strength -Reduces blocking and blurring in flat and textured areas. -- encoding: Set by user -- decoding: unused - - - -AQ mode -0: Disabled -1: Variance AQ (complexity mask) -2: Auto-variance AQ (experimental) -- encoding: Set by user -- decoding: unused - - - -explicit P-frame weighted prediction analysis method -0: off -1: fast blind weighting (one reference duplicate with -1 offset) -2: smart weighting (full fade detection analysis) -- encoding: Set by user. -- decoding: unused - - - -MPEG vs JPEG YUV range. -- encoding: Set by user -- decoding: Set by libavcodec - - - -YUV colorspace type. -- encoding: Set by user -- decoding: Set by libavcodec - - - -Color Transfer Characteristic. -- encoding: Set by user -- decoding: Set by libavcodec - - - -Chromaticity coordinates of the source primaries. -- encoding: Set by user -- decoding: Set by libavcodec - - - -Hardware accelerator context. -For some hardware accelerators, a global context needs to be -provided by the user. In that case, this holds display-dependent -data FFmpeg cannot instantiate itself. Please refer to the -FFmpeg HW accelerator documentation to know how to fill this -is. e.g. for VA API, this is a struct vaapi_context. -- encoding: unused -- decoding: Set by user - - - - For some codecs, the time base is closer to the field rate than the frame rate. - Most notably, H.264 and MPEG-2 specify time_base as half of frame duration - if no telecine is used ... - - Set to time_base ticks per frame. Default 1, e.g., H.264/MPEG-2 set it to 2. - - - -Hardware accelerator in use -- encoding: unused. -- decoding: Set by libavcodec - - -AVHWAccel. - - - -Request decoder to use this channel layout if it can (0 for default) -- encoding: unused -- decoding: Set by user. - - - -Audio channel layout. -- encoding: set by user. -- decoding: set by user, may be overwritten by libavcodec. - - - -Bits per sample/pixel of internal libavcodec pixel/sample format. -- encoding: set by user. -- decoding: set by libavcodec. - - - -opaque 64bit number (generally a PTS) that will be reordered and -output in AVFrame.reordered_opaque -@deprecated in favor of pkt_pts -- encoding: unused -- decoding: Set by user. - - - -Percentage of dynamic range compression to be applied by the decoder. -The default value is 1.0, corresponding to full compression. -- encoding: unused -- decoding: Set by user. -@deprecated use AC3 decoder private option instead. - - - -Decoder should decode to this many channels if it can (0 for default) -- encoding: unused -- decoding: Set by user. -@deprecated Deprecated in favor of request_channel_layout. - - - -@} - -GOP timecode frame start number -- encoding: Set by user, in non drop frame format -- decoding: Set by libavcodec (timecode in the 25 bits format, -1 if unset) - - - -- encoding: Set by user. -- decoding: unused - - - -- encoding: Set by user. -- decoding: unused - - - -search method for selecting prediction order -- encoding: Set by user. -- decoding: unused - - - -@name FLAC options -@deprecated Use FLAC encoder private options instead. -@{ - -LPC coefficient precision - used by FLAC encoder -- encoding: Set by user. -- decoding: unused - - - -- encoding: Set by user. -- decoding: unused - - - -- encoding: Set by user. -- decoding: unused - - - -- encoding: Set by user. -- decoding: unused - - - -Adjust sensitivity of b_frame_strategy 1. -- encoding: Set by user. -- decoding: unused - - - - - Note: Value depends upon the compare function used for fullpel ME. - - encoding: Set by user. - - decoding: unused - - - -Multiplied by qscale for each frame and added to scene_change_score. -- encoding: Set by user. -- decoding: unused - - - -Audio cutoff bandwidth (0 means "automatic") -- encoding: Set by user. -- decoding: unused - - - -direct MV prediction mode - 0 (none), 1 (spatial), 2 (temporal), 3 (auto) -- encoding: Set by user. -- decoding: unused - - - -macroblock subpartition sizes to consider - p8x8, p4x4, b8x8, i8x8, i4x4 -- encoding: Set by user. -- decoding: unused - - - -in-loop deblocking filter beta parameter -beta is in the range -6...6 -- encoding: Set by user. -- decoding: unused - - - -in-loop deblocking filter alphac0 parameter -alpha is in the range -6...6 -- encoding: Set by user. -- decoding: unused - - - -Reduce fluctuations in qp (before curve compression). -- encoding: Set by user. -- decoding: unused - - - -trellis RD quantization -- encoding: Set by user. -- decoding: unused - - - -Influence how often B-frames are used. -- encoding: Set by user. -- decoding: unused - - - -chroma qp offset from luma -- encoding: Set by user. -- decoding: unused - - - -number of reference frames -- encoding: Set by user. -- decoding: Set by lavc. - - - -minimum GOP size -- encoding: Set by user. -- decoding: unused - - - -constant quantization parameter rate control method -- encoding: Set by user. -- decoding: unused - @deprecated use 'cqp' libx264 private option - - - -constant rate factor - quality-based VBR - values ~correspond to qps -- encoding: Set by user. -- decoding: unused - @deprecated use 'crf' libx264 private option - - - - - - encoding: Set by user. - - decoding: unused - - - - - - encoding: Set by user. - - decoding: unused - - - - - - encoding: unused - - decoding: Set by user. - - - - - encoding: unused - - decoding: Set by user. - - - - - encoding: unused - - decoding: Set by user. - - - - - - encoding: Set by user. - - decoding: unused - - - -maximum MB lagrange multipler -- encoding: Set by user. -- decoding: unused - - - -minimum MB lagrange multipler -- encoding: Set by user. -- decoding: unused - - - -Border processing masking, raises the quantizer for mbs on the borders -of the picture. -- encoding: Set by user. -- decoding: unused - - - -frame skip comparison function -- encoding: Set by user. -- decoding: unused - - - -frame skip exponent -- encoding: Set by user. -- decoding: unused - - - -frame skip factor -- encoding: Set by user. -- decoding: unused - - - -frame skip threshold -- encoding: Set by user. -- decoding: unused - - - -Bitstream width / height, may be different from width/height if lowres enabled. -- encoding: unused -- decoding: Set by user before init if known. Codec should override / dynamically change if needed. - - - -low resolution decoding, 1-> 1/2 size, 2->1/4 size -- encoding: unused -- decoding: Set by user. - - - -level -- encoding: Set by user. -- decoding: Set by libavcodec. - - - -profile -- encoding: Set by user. -- decoding: Set by libavcodec. - - - -Number of macroblock rows at the bottom which are skipped. -- encoding: unused -- decoding: Set by user. - - - -Number of macroblock rows at the top which are skipped. -- encoding: unused -- decoding: Set by user. - - - -noise vs. sse weight for the nsse comparsion function -- encoding: Set by user. -- decoding: unused - - - -precision of the intra DC coefficient - 8 -- encoding: Set by user. -- decoding: unused - - - -Macroblock threshold below which the user specified macroblock types will be used. -- encoding: Set by user. -- decoding: unused - - - - Motion estimation threshold below which no motion estimation is - performed, but instead the user specified motion vectors are used. - - - encoding: Set by user. - - decoding: unused - - - -thread opaque -Can be used by execute() to store some per AVCodecContext stuff. -- encoding: set by execute() -- decoding: set by execute() - - - -The codec may call this to execute several independent things. -It will return only after finishing all tasks. -The user may replace this with some multithreaded implementation, -the default implementation will execute the parts serially. -@param count the number of things to execute -- encoding: Set by libavcodec, user can override. -- decoding: Set by libavcodec, user can override. - - - -thread count -is used to decide how many independent tasks should be passed to execute() -- encoding: Set by user. -- decoding: Set by user. - - - -quantizer noise shaping -- encoding: Set by user. -- decoding: unused - - - -MP3 antialias algorithm, see FF_AA_* below. -- encoding: unused -- decoding: Set by user. - - - -Simulates errors in the bitstream to test error concealment. -- encoding: Set by user. -- decoding: unused - - - -CODEC_FLAG2_* -- encoding: Set by user. -- decoding: Set by user. - - - - - - encoding: Set by user. - - decoding: unused - - - -Number of bits which should be loaded into the rc buffer before decoding starts. -- encoding: Set by user. -- decoding: unused - - - -Called at the beginning of a frame to get cr buffer for it. -Buffer type (size, hints) must be the same. libavcodec won't check it. -libavcodec will pass previous buffer in pic, function should return -same buffer or new buffer with old frame "painted" into it. -If pic.data[0] == NULL must behave like get_buffer(). -if CODEC_CAP_DR1 is not set then reget_buffer() must call -avcodec_default_reget_buffer() instead of providing buffers allocated by -some other means. -- encoding: unused -- decoding: Set by libavcodec, user can override. - - - -noise reduction strength -- encoding: Set by user. -- decoding: unused - - - -palette control structure -- encoding: ??? (no palette-enabled encoder yet) -- decoding: Set by user. - - - AVPaletteControl - This structure defines a method for communicating palette changes - between and demuxer and a decoder. - - @deprecated Use AVPacket to send palette changes instead. - This is totally broken. - - - -maximum Lagrange multipler -- encoding: Set by user. -- decoding: unused - - - -minimum Lagrange multipler -- encoding: Set by user. -- decoding: unused - - - -scene change detection threshold -0 is default, larger means fewer detected scene changes. -- encoding: Set by user. -- decoding: unused - - - -custom inter quantization matrix -- encoding: Set by user, can be NULL. -- decoding: Set by libavcodec. - - - -custom intra quantization matrix -- encoding: Set by user, can be NULL. -- decoding: Set by libavcodec. - - - -macroblock decision mode -- encoding: Set by user. -- decoding: unused - - - -XVideo Motion Acceleration -- encoding: forbidden -- decoding: set by decoder - - - -slice flags -- encoding: unused -- decoding: Set by user. - - - -context model -- encoding: Set by user. -- decoding: unused - - - -coder type -- encoding: Set by user. -- decoding: unused - - - -Global quality for codecs which cannot change it per frame. -This should be proportional to MPEG-1/2/4 qscale. -- encoding: Set by user. -- decoding: unused - - - -internal_buffers -Don't touch, used by libavcodec default_get_buffer(). -@deprecated this field was moved to an internal context - - - -internal_buffer count -Don't touch, used by libavcodec default_get_buffer(). -@deprecated this field was moved to an internal context - - - -color table ID -- encoding: unused -- decoding: Which clrtable should be used for 8bit RGB images. - Tables have to be stored somewhere. FIXME - - - -inter quantizer bias -- encoding: Set by user. -- decoding: unused - - - -intra quantizer bias -- encoding: Set by user. -- decoding: unused - - - - maximum motion estimation search range in subpel units - If 0 then no limit. - - - encoding: Set by user. - - decoding: unused - - - - DTG active format information (additional aspect ratio - information only used in DVB MPEG-2 transport streams) - 0 if not set. - - - encoding: unused - - decoding: Set by decoder. - - - -subpel ME quality -- encoding: Set by user. -- decoding: unused - - - -motion estimation prepass comparison function -- encoding: Set by user. -- decoding: unused - - - -prepass for motion estimation -- encoding: Set by user. -- decoding: unused - - - -amount of previous MV predictors (2a+1 x 2a+1 square) -- encoding: Set by user. -- decoding: unused - - - -interlaced DCT comparison function -- encoding: Set by user. -- decoding: unused - - - -macroblock comparison function (not supported yet) -- encoding: Set by user. -- decoding: unused - - - -subpixel motion estimation comparison function -- encoding: Set by user. -- decoding: unused - - - -motion estimation comparison function -- encoding: Set by user. -- decoding: unused - - - -debug -- encoding: Set by user. -- decoding: Set by user. - - - -debug -- encoding: Set by user. -- decoding: Set by user. - - - -the picture in the bitstream -- encoding: Set by libavcodec. -- decoding: Set by libavcodec. - - - -sample aspect ratio (0 if unknown) -That is the width of a pixel divided by the height of the pixel. -Numerator and denominator must be relatively prime and smaller than 256 for some video standards. -- encoding: Set by user. -- decoding: Set by libavcodec. - - - -prediction method (needed for huffyuv) -- encoding: Set by user. -- decoding: unused - - - -bits per sample/pixel from the demuxer (needed for huffyuv). -- encoding: Set by libavcodec. -- decoding: Set by user. - - - - dsp_mask could be add used to disable unwanted CPU features - CPU features (i.e. MMX, SSE. ...) - - With the FORCE flag you may instead enable given CPU features. - (Dangerous: Usable in case of misdetection, improper usage however will - result into program crash.) - - - -error concealment flags -- encoding: unused -- decoding: Set by user. - - - -slice offsets in the frame in bytes -- encoding: Set/allocated by libavcodec. -- decoding: Set/allocated by user (or NULL). - - - -slice count -- encoding: Set by libavcodec. -- decoding: Set by user (or 0). - - - -IDCT algorithm, see FF_IDCT_* below. -- encoding: Set by user. -- decoding: Set by user. - - - -darkness masking (0-> disabled) -- encoding: Set by user. -- decoding: unused - - - -p block masking (0-> disabled) -- encoding: Set by user. -- decoding: unused - - - -spatial complexity masking (0-> disabled) -- encoding: Set by user. -- decoding: unused - - - -temporary complexity masking (0-> disabled) -- encoding: Set by user. -- decoding: unused - - - -luminance masking (0-> disabled) -- encoding: Set by user. -- decoding: unused - - - -DCT algorithm, see FF_DCT_* below -- encoding: Set by user. -- decoding: unused - - - -initial complexity for pass1 ratecontrol -- encoding: Set by user. -- decoding: unused - - - -qscale offset between P and I-frames -- encoding: Set by user. -- decoding: unused - - - -decoder bitstream buffer size -- encoding: Set by user. -- decoding: unused - - - -minimum bitrate -- encoding: Set by user. -- decoding: unused - - - -maximum bitrate -- encoding: Set by user. -- decoding: unused - - - -rate control equation -- encoding: Set by user -- decoding: unused - - - -ratecontrol override, see RcOverride -- encoding: Allocated/set/freed by user. -- decoding: unused - - - -ratecontrol qmin qmax limiting method -0-> clipping, 1-> use a nice continous function to limit qscale wthin qmin/qmax. -- encoding: Set by user. -- decoding: unused - - - -pass2 encoding statistics input buffer -Concatenated stuff from stats_out of pass1 should be placed here. -- encoding: Allocated/set/freed by user. -- decoding: unused - - - -pass1 encoding statistics output buffer -- encoding: Set by libavcodec. -- decoding: unused - - - -0-> h263 quant 1-> mpeg quant -- encoding: Set by user. -- decoding: unused - - - -If true, only parsing is done. The frame data is returned. -Only MPEG audio decoders support this now. -- encoding: unused -- decoding: Set by user - - - -number of bytes per packet if constant and known or 0 -Used by some WAV based audio codecs. - - - -Size of the frame reordering buffer in the decoder. -For MPEG-2 it is 1 IPB or 0 low delay IP. -- encoding: Set by libavcodec. -- decoding: Set by libavcodec. - - - -Called to release buffers which were allocated with get_buffer. -A released buffer can be reused in get_buffer(). -pic.data[*] must be set to NULL. -May be called from a different thread if frame multithreading is used, -but not by more than one thread at once, so does not need to be reentrant. -- encoding: unused -- decoding: Set by libavcodec, user can override. - - - - Called at the beginning of each frame to get a buffer for it. - - The function will set AVFrame.data[], AVFrame.linesize[]. - AVFrame.extended_data[] must also be set, but it should be the same as - AVFrame.data[] except for planar audio with more channels than can fit - in AVFrame.data[]. In that case, AVFrame.data[] shall still contain as - many data pointers as it can hold. - - if CODEC_CAP_DR1 is not set then get_buffer() must call - avcodec_default_get_buffer() instead of providing buffers allocated by - some other means. - - AVFrame.data[] should be 32- or 16-byte-aligned unless the CPU doesn't - need it. avcodec_default_get_buffer() aligns the output buffer properly, - but if get_buffer() is overridden then alignment considerations should - be taken into account. - - @see avcodec_default_get_buffer() - - Video: - - If pic.reference is set then the frame will be read later by libavcodec. - avcodec_align_dimensions2() should be used to find the required width and - height, as they normally need to be rounded up to the next multiple of 16. - - If frame multithreading is used and thread_safe_callbacks is set, - it may be called from a different thread, but not from more than one at - once. Does not need to be reentrant. - - @see release_buffer(), reget_buffer() - @see avcodec_align_dimensions2() - - Audio: - - Decoders request a buffer of a particular size by setting - AVFrame.nb_samples prior to calling get_buffer(). The decoder may, - however, utilize only part of the buffer by setting AVFrame.nb_samples - to a smaller value in the output frame. - - Decoders cannot use the buffer after returning from - avcodec_decode_audio4(), so they will not call release_buffer(), as it - is assumed to be released immediately upon return. - - As a convenience, av_samples_get_buffer_size() and - av_samples_fill_arrays() in libavutil may be used by custom get_buffer() - functions to find the required data size and to fill data pointers and - linesize. In AVFrame.linesize, only linesize[0] may be set for audio - since all planes must be the same size. - - @see av_samples_get_buffer_size(), av_samples_fill_arrays() - - - encoding: unused - - decoding: Set by libavcodec, user can override. - - - -Error recognition; higher values will detect more errors but may -misdetect some more or less valid parts as errors. -- encoding: unused -- decoding: Set by user. - - - -qscale offset between IP and B-frames -- encoding: Set by user. -- decoding: unused - - - -strictly follow the standard (MPEG4, ...). -- encoding: Set by user. -- decoding: Set by user. -Setting this to STRICT or higher means the encoder and decoder will -generally do stupid things, whereas setting it to unofficial or lower -will mean the encoder might produce output that is not supported by all -spec-compliant decoders. Decoders don't differentiate between normal, -unofficial and experimental (that is, they always try to decode things -when they can) unless they are explicitly asked to behave stupidly -(=strictly conform to the specs) - - - -chroma single coeff elimination threshold -- encoding: Set by user. -- decoding: unused - - - -luma single coefficient elimination threshold -- encoding: Set by user. -- decoding: unused - - - -Work around bugs in encoders which sometimes cannot be detected automatically. -- encoding: Set by user -- decoding: Set by user - - - -Private data of the user, can be used to carry app specific stuff. -- encoding: Set by user. -- decoding: Set by user. - - - -number of bits used for the previously encoded frame -- encoding: Set by libavcodec. -- decoding: unused - - - -obsolete FIXME remove - - -maximum number of B-frames between non-B-frames -Note: The output will be delayed by max_b_frames+1 relative to the input. -- encoding: Set by user. -- decoding: unused - - - -maximum quantizer difference between frames -- encoding: Set by user. -- decoding: unused - - - -maximum quantizer -- encoding: Set by user. -- decoding: unused - - - -minimum quantizer -- encoding: Set by user. -- decoding: unused - - - -Encoding: Number of frames delay there will be from the encoder input to - the decoder output. (we assume the decoder matches the spec) -Decoding: Number of frames delay in addition to what a standard decoder - as specified in the spec would produce. -- encoding: Set by libavcodec. -- decoding: Set by libavcodec. - - - -Samples per packet, initialized when calling 'init'. - - - -If non NULL, 'draw_horiz_band' is called by the libavcodec -decoder to draw a horizontal band. It improves cache usage. Not -all codecs can do that. You must check the codec capabilities -beforehand. -When multithreading is used, it may be called from multiple threads -at the same time; threads might draw different parts of the same AVFrame, -or multiple AVFrames, and there is no guarantee that slices will be drawn -in order. -The function is also used by hardware acceleration APIs. -It is called at least once during frame decoding to pass -the data needed for hardware render. -In that mode instead of pixel data, AVFrame points to -a structure specific to the acceleration API. The application -reads the structure and can change some fields to indicate progress -or mark state. -- encoding: unused -- decoding: Set by user. -@param height the height of the slice -@param y the y position of the slice -@param type 1->top field, 2->bottom field, 3->frame -@param offset offset into the AVFrame.data from which the slice should be read - - - -Pixel format, see PIX_FMT_xxx. -May be set by the demuxer if known from headers. -May be overriden by the decoder if it knows better. -- encoding: Set by user. -- decoding: Set by user if known, overridden by libavcodec if known - - -callback to negotiate the pixelFormat -@param fmt is the list of formats which are supported by the codec, -it is terminated by -1 as 0 is a valid format, the formats are ordered by quality. -The first is always the native one. -@return the chosen format -- encoding: unused -- decoding: Set by user, if not set the native format will be chosen. - - - Supported pixel format. - - Only hardware accelerated formats are supported here. - - - -the number of pictures in a group of pictures, or 0 for intra_only -- encoding: Set by user. -- decoding: unused - - - -picture width / height. -- encoding: MUST be set by user. -- decoding: Set by libavcodec. -Note: For compatibility it is possible to set this instead of -coded_width/height before decoding. - - - -This is the fundamental unit of time (in seconds) in terms -of which frame timestamps are represented. For fixed-fps content, -timebase should be 1/framerate and timestamp increments should be -identically 1. -- encoding: MUST be set by user. -- decoding: Set by libavcodec. - - - -some codecs need / can use extradata like Huffman tables. -mjpeg: Huffman tables -rv10: additional flags -mpeg4: global headers (they can be in the bitstream or here) -The allocated memory should be FF_INPUT_BUFFER_PADDING_SIZE bytes larger -than extradata_size to avoid prolems if it is read with the bitstream reader. -The bytewise contents of extradata must not depend on the architecture or CPU endianness. -- encoding: Set/allocated/freed by libavcodec. -- decoding: Set/allocated/freed by user. - - - -Motion estimation algorithm used for video coding. -1 (zero), 2 (full), 3 (log), 4 (phods), 5 (epzs), 6 (x1), 7 (hex), -8 (umh), 9 (iter), 10 (tesa) [7, 8, 10 are x264 specific, 9 is snow specific] -- encoding: MUST be set by user. -- decoding: unused - - - -Some codecs need additional format info. It is stored here. -If any muxer uses this then ALL demuxers/parsers AND encoders for the -specific codec MUST set it correctly otherwise stream copy breaks. -In general use of this field by muxers is not recommended. -- encoding: Set by libavcodec. -- decoding: Set by libavcodec. (FIXME: Is this OK?) - - - -CODEC_FLAG_*. -- encoding: Set by user. -- decoding: Set by user. - - - -number of bits the bitstream is allowed to diverge from the reference. - the reference can be CBR (for CBR pass1) or VBR (for pass2) -- encoding: Set by user; unused for constant quantizer encoding. -- decoding: unused - - - -the average bitrate -- encoding: Set by user; unused for constant quantizer encoding. -- decoding: Set by libavcodec. 0 or some bitrate if this info is available in the stream. - - - -information on struct for av_log -- set by avcodec_alloc_context3 - - - -reordered pos from the last AVPacket that has been input into the decoder -Code outside libavcodec should access this field using: - av_opt_ptr(avcodec_get_frame_class(), frame, "pkt_pos"); -- encoding: unused -- decoding: Read by user. - - - -frame timestamp estimated using various heuristics, in stream time base -Code outside libavcodec should access this field using: - av_opt_ptr(avcodec_get_frame_class(), frame, "best_effort_timestamp"); -- encoding: unused -- decoding: set by libavcodec, read by user. - - - -format of the frame, -1 if unknown or unset -Values correspond to enum PixelFormat for video frames, -enum AVSampleFormat for audio) -- encoding: unused -- decoding: Read by user. - - - -width and height of the video frame -- encoding: unused -- decoding: Read by user. - - - -sample aspect ratio for the video frame, 0/1 if unknown\unspecified -- encoding: unused -- decoding: Read by user. - - - - pointers to the data planes/channels. - - For video, this should simply point to data[]. - - For planar audio, each channel has a separate data pointer, and - linesize[0] contains the size of each channel buffer. - For packed audio, there is just one data pointer, and linesize[0] - contains the total size of the buffer for all channels. - - Note: Both data and extended_data will always be set by get_buffer(), - but for planar audio with more channels that can fit in data, - extended_data must be used by the decoder in order to access all - channels. - - encoding: unused - decoding: set by AVCodecContext.get_buffer() - - - -number of audio samples (per channel) described by this frame -- encoding: unused -- decoding: Set by libavcodec - - - -used by multithreading to store frame-specific info -- encoding: Set by libavcodec. -- decoding: Set by libavcodec. - - - -the AVCodecContext which ff_thread_get_buffer() was last called on -- encoding: Set by libavcodec. -- decoding: Set by libavcodec. - - -main external API structure. -New fields can be added to the end with minor version bumps. -Removal, reordering and changes to existing fields require a major -version bump. -Please use AVOptions (av_opt* / av_set/get*()) to access these fields from user -applications. -sizeof(AVCodecContext) must not be used outside libav*. - - - -dts from the last AVPacket that has been input into the decoder -- encoding: unused -- decoding: Read by user. - - - -reordered pts from the last AVPacket that has been input into the decoder -- encoding: unused -- decoding: Read by user. - - - -hardware accelerator private data (FFmpeg-allocated) -- encoding: unused -- decoding: Set by libavcodec - - - -reordered opaque 64bit (generally an integer or a double precision float -PTS but can be anything). -The user sets AVCodecContext.reordered_opaque to represent the input at -that time, -the decoder reorders values as needed and sets AVFrame.reordered_opaque -to exactly one of the values provided by the user through AVCodecContext.reordered_opaque -@deprecated in favor of pkt_pts -- encoding: unused -- decoding: Read by user. - - - -motion reference frame index -the order in which these are stored can depend on the codec. -- encoding: Set by user. -- decoding: Set by libavcodec. - - - -DCT coefficients -- encoding: unused -- decoding: Set by libavcodec. - - - -codec suggestion on buffer type if != 0 -- encoding: unused -- decoding: Set by libavcodec. (before get_buffer() call)). - - - -Tell user application that palette has changed from previous frame. -- encoding: ??? (no palette-enabled encoder yet) -- decoding: Set by libavcodec. (default 0). - - - -Pan scan. -- encoding: Set by user. -- decoding: Set by libavcodec. - - - -If the content is interlaced, is top field displayed first. -- encoding: Set by user. -- decoding: Set by libavcodec. - - - -The content of the picture is interlaced. -- encoding: Set by user. -- decoding: Set by libavcodec. (default 0) - - - -When decoding, this signals how much the picture must be delayed. -extra_delay = repeat_pict / (2*fps) -- encoding: unused -- decoding: Set by libavcodec. - - - -for some private data of the user -- encoding: unused -- decoding: Set by user. - - - -log2 of the size of the block which a single vector in motion_val represents: -(4->16x16, 3->8x8, 2-> 4x4, 1-> 2x2) -- encoding: unused -- decoding: Set by libavcodec. - - - -macroblock type table -mb_type_base + mb_width + 2 -- encoding: Set by user. -- decoding: Set by libavcodec. - - - -mbskip_table[mb]>=1 if MB didn't change -stride= mb_width = (width+15)>>4 -- encoding: unused -- decoding: Set by libavcodec. - - - -QP store stride -- encoding: unused -- decoding: Set by libavcodec. - - - -QP table -- encoding: unused -- decoding: Set by libavcodec. - - - -is this picture used as reference -The values for this are the same as the MpegEncContext.picture_structure -variable, that is 1->top field, 2->bottom field, 3->frame/both fields. -Set to 4 for delayed, non-reference frames. -- encoding: unused -- decoding: Set by libavcodec. (before get_buffer() call)). - - - -@deprecated unused - - - -quality (between 1 (good) and FF_LAMBDA_MAX (bad)) -- encoding: Set by libavcodec. for coded_picture (and set by user for input). -- decoding: Set by libavcodec. - - - -picture number in display order -- encoding: set by -- decoding: Set by libavcodec. - - - -picture number in bitstream order -- encoding: set by -- decoding: Set by libavcodec. - - - -presentation timestamp in time_base units (time when frame should be shown to user) -If AV_NOPTS_VALUE then frame_rate = 1/time_base will be assumed. -- encoding: MUST be set by user. -- decoding: Set by libavcodec. - - - -1 -> keyframe, 0-> not -- encoding: Set by libavcodec. -- decoding: Set by libavcodec. - - - -pointer to the first allocated byte of the picture. Can be used in get_buffer/release_buffer. -This isn't used by libavcodec unless the default get/release_buffer() is used. -- encoding: -- decoding: - - - - Size, in bytes, of the data for each picture/channel plane. - - For audio, only linesize[0] may be set. For planar audio, each channel - plane must be the same size. - - - encoding: Set by user (video only) - - decoding: set by AVCodecContext.get_buffer() - - - -pointer to the picture/channel planes. -This might be different from the first allocated byte -- encoding: Set by user -- decoding: set by AVCodecContext.get_buffer() - - - -Audio Video Frame. -New fields can be added to the end of AVFRAME with minor version -bumps. Similarly fields that are marked as to be only accessed by -av_opt_ptr() can be reordered. This allows 2 forks to add fields -without breaking compatibility with each other. -Removal, reordering and changes in the remaining cases require -a major version bump. -sizeof(AVFrame) must not be used outside libavcodec. - - - - Time difference in AVStream->time_base units from the pts of this - packet to the point at which the output from the decoder has converged - independent from the availability of previous frames. That is, the - frames are virtually identical no matter if decoding started from - the very first frame or from this keyframe. - Is AV_NOPTS_VALUE if unknown. - This field is not the display duration of the current packet. - This field has no meaning if the packet does not have AV_PKT_FLAG_KEY - set. - - The purpose of this field is to allow seeking in streams that have no - keyframes in the conventional sense. It corresponds to the - recovery point SEI in H.264 and match_time_delta in NUT. It is also - essential for some types of subtitle streams to ensure that all - subtitles are correctly displayed after seeking. - - - -Duration of this packet in AVStream->time_base units, 0 if unknown. -Equals next_pts - this_pts in presentation order. - - - -A combination of AV_PKT_FLAG values - - - -Decompression timestamp in AVStream->time_base units; the time at which -the packet is decompressed. -Can be AV_NOPTS_VALUE if it is not stored in the file. - - - -Presentation timestamp in AVStream->time_base units; the time at which -the decompressed packet will be presented to the user. -Can be AV_NOPTS_VALUE if it is not stored in the file. -pts MUST be larger or equal to dts as presentation cannot happen before -decompression, unless one wants to view hex dumps. Some formats misuse -the terms dts and pts/cts to mean something different. Such timestamps -must be converted to true pts/dts before they are stored in AVPacket. - - - -position of the top left corner in 1/16 pel for up to 3 fields/frames -- encoding: Set by user. -- decoding: Set by libavcodec. - - - -width and height in 1/16 pel -- encoding: Set by user. -- decoding: Set by libavcodec. - - - -id -- encoding: Set by user. -- decoding: Set by libavcodec. - - - -The parent program guarantees that the input for B-frames containing -streams is not written to for at least s->max_b_frames+1 frames, if -this is not set the input will be copied. - -@defgroup deprecated_flags Deprecated codec flags -Use corresponding private codec options instead. -@{ - -@} - -Codec uses get_buffer() for allocating buffers and supports custom allocators. -If not set, it might not use get_buffer() at all or use operations that -assume the buffer was allocated by avcodec_default_get_buffer. - - Encoder or decoder requires flushing with NULL input at the end in order to - give the complete and correct output. - - NOTE: If this flag is not set, the codec is guaranteed to never be fed with - with NULL data. The user can still send NULL data to the public encode - or decode function, but libavcodec will not pass it along to the codec - unless this flag is set. - - Decoders: - The decoder has a non-zero delay and needs to be fed with avpkt->data=NULL, - avpkt->size=0 at the end to get the delayed data until the decoder no longer - returns frames. - - Encoders: - The encoder needs to be fed with NULL data at the end of encoding until the - encoder no longer returns data. - - NOTE: For encoders implementing the AVCodec.encode2() function, setting this - flag also means that the encoder must set the pts and duration for - each output packet. If this flag is not set, the pts and duration will - be determined by libavcodec from the input frame. - -Codec can be fed a final frame with a smaller size. -This can be used to prevent truncation of the last audio samples. - -Codec can export data for HW decoding (VDPAU). - -Codec can output multiple frames per AVPacket -Normally demuxers return one frame at a time, demuxers which do not do -are connected to a parser to split what they return into proper frames. -This flag is reserved to the very rare category of codecs which have a -bitstream that cannot be split into frames without timeconsuming -operations like full decoding. Demuxers carring such bitstreams thus -may return multiple frames in a packet. This has many disadvantages like -prohibiting stream copy in many cases thus it should only be considered -as a last resort. - -Codec is experimental and is thus avoided in favor of non experimental -encoders - -Codec should fill in channel configuration and samplerate instead of container - -Codec is able to deal with negative linesizes - -Codec supports frame-level multithreading. - -Codec supports slice-based (or partition-based) multithreading. - -Codec supports changed parameters at any point. - -Codec supports avctx->thread_count == 0 (auto). - -Audio encoder supports receiving a different number of samples in each call. - -Codec is lossless. - -Pan Scan area. -This specifies the area which should be displayed. -Note there may be multiple such areas for one frame. - - - -LPC analysis type - - -Determine which LPC analysis algorithm to use. -- encoding: Set by user -- decoding: unused - - - -X X 3 4 X X are luma samples, - 1 2 1-6 are possible chroma positions -X X 5 6 X 0 is undefined/unknown position - - -This defines the location of chroma samples. -- encoding: Set by user -- decoding: Set by libavcodec - - - -Return default channel layout for a given number of channels. - - - -Return the number of channels in the channel layout. - - - -@file -audio conversion routines - -@addtogroup lavu_audio -@{ - -@defgroup channel_masks Audio channel masks -@{ - -Channel mask value used for AVCodecContext.request_channel_layout - to indicate that the user requests the channel order of the decoder output - to be the native codec channel order. -@} -@defgroup channel_mask_c Audio channel convenience macros -@{ - -@} - - * Return a channel layout id that matches name, 0 if no match. - * name can be one or several of the following notations, - * separated by '+' or '|': - * - the name of an usual channel layout (mono, stereo, 4.0, quad, 5.0, - * 5.0(side), 5.1, 5.1(side), 7.1, 7.1(wide), downmix); - * - the name of a single channel (FL, FR, FC, LFE, BL, BR, FLC, FRC, BC, - * SL, SR, TC, TFL, TFC, TFR, TBL, TBC, TBR, DL, DR); - * - a number of channels, in decimal, optionnally followed by 'c', yielding - * the default channel layout for that number of channels (@see - * av_get_default_channel_layout); - * - a channel layout mask, in hexadecimal starting with "0x" (see the - * AV_CH_* macros). - + Example: "stereo+FC" = "2+FC" = "2c+1c" = "0x7" - - - -Free all the memory allocated for an AVDictionary struct -and all keys and values. - - - -Copy entries from one AVDictionary struct into another. -@param dst pointer to a pointer to a AVDictionary struct. If *dst is NULL, - this function will allocate a struct for you and put it in *dst -@param src pointer to source AVDictionary struct -@param flags flags to use when setting entries in *dst -@note metadata is read using the AV_DICT_IGNORE_SUFFIX flag - - - - Get a dictionary entry with matching key. - - @param prev Set to the previous matching element to find the next. - If set to NULL the first matching element is returned. - @param flags Allows case as well as suffix-insensitive comparisons. - @return Found entry or NULL, changing key or value leads to undefined behavior. - - - -Disables cpu detection and forces the specified flags. - - - -Return the flags which specify extensions supported by the CPU. - - - - Fill channel data pointers and linesize for samples with sample - format sample_fmt. - - The pointers array is filled with the pointers to the samples data: - for planar, set the start point of each channel's data within the buffer, - for packed, set the start point of the entire buffer only. - - The linesize array is filled with the aligned size of each channel's data - buffer for planar layout, or the aligned size of the buffer for all channels - for packed layout. - - @param[out] audio_data array to be filled with the pointer for each channel - @param[out] linesize calculated linesize - @param buf the pointer to a buffer containing the samples - @param nb_channels the number of channels - @param nb_samples the number of samples in a single channel - @param sample_fmt the sample format - @param align buffer size alignment (1 = no alignment required) - @return 0 on success or a negative error code on failure - - - - Get the required buffer size for the given audio parameters. - - @param[out] linesize calculated linesize, may be NULL - @param nb_channels the number of channels - @param nb_samples the number of samples in a single channel - @param sample_fmt the sample format - @return required buffer size, or negative error code on failure - - - - Check if the sample format is planar. - - @param sample_fmt the sample format to inspect - @return 1 if the sample format is planar, 0 if it is interleaved - - - - Return number of bytes per sample. - - @param sample_fmt the sample format - @return number of bytes per sample or zero if unknown for the given - sample format - - - -@deprecated Use av_get_bytes_per_sample() instead. - - - - Generate a string corresponding to the sample format with - sample_fmt, or a header if sample_fmt is negative. - - @param buf the buffer where to write the string - @param buf_size the size of buf - @param sample_fmt the number of the sample format to print the - corresponding info string, or a negative value to print the - corresponding header. - @return the pointer to the filled buffer or NULL if sample_fmt is - unknown or in case of other errors - - - -Return the name of sample_fmt, or NULL if sample_fmt is not -recognized. - - - -@} -@} - -all in native-endian format - - -Return a sample format corresponding to name, or AV_SAMPLE_FMT_NONE -on error. - - -audio sample format -- encoding: Set by user. -- decoding: Set by libavcodec. - - -desired sample format -- encoding: Not used. -- decoding: Set by user. -Decoder will decode to this format if it can. - - - -Return x default pointer in case p is NULL. - - - -av_dlog macros -Useful to print debug messages that shouldn't get compiled in normally. - -Skip repeated messages, this requires the user app to use av_log() instead of -(f)printf as the 2 would otherwise interfere and lead to -"Last message repeated x times" messages below (f)printf messages with some -bad luck. -Also to receive the last, "last repeated" line if any, the user app must -call av_log(NULL, AV_LOG_QUIET, "%s", ""); at the end - - - -Format a line of log the same way as the default callback. -@param line buffer to receive the formated line -@param line_size size of the buffer -@param print_prefix used to store whether the prefix must be printed; - must point to a persistent integer initially set to 1 - - - -Something went really wrong and we will crash now. - -Something went wrong and recovery is not possible. -For example, no header was found for a format which depends -on headers or an illegal combination of parameters is used. - -Something went wrong and cannot losslessly be recovered. -However, not all future data is affected. - -Something somehow does not look correct. This may or may not -lead to problems. An example would be the use of '-vstrict -2'. - -Stuff which is only useful for libav* developers. - - Send the specified message to the log if the level is less than or equal - to the current av_log_level. By default, all logging messages are sent to - stderr. This behavior can be altered by setting a different av_vlog callback - function. - - @param avcl A pointer to an arbitrary struct of which the first field is a - pointer to an AVClass struct. - @param level The importance level of the message, lower values signifying - higher importance. - @param fmt The format string (printf-compatible) that specifies how - subsequent arguments are converted to output. - @see av_vlog - - - - Return an AVClass corresponding to next potential - AVOptions-enabled child. - - The difference between child_next and this is that - child_next iterates over _already existing_ objects, while - child_class_next iterates over _all possible_ children. - - - -Return next AVOptions-enabled child or NULL - - - -Offset in the structure where a pointer to the parent context for loging is stored. -for example a decoder that uses eval.c could pass its AVCodecContext to eval as such -parent context. And a av_log() implementation could then display the parent context -can be NULL of course - - - -Offset in the structure where log_level_offset is stored. -0 means there is no such variable - - - -LIBAVUTIL_VERSION with which this structure was created. -This is used to allow fields to be added without requiring major -version bumps everywhere. - - - - a pointer to the first option specified in the class if any or NULL - - @see av_set_default_options() - - - -A pointer to a function which returns the name of a context -instance ctx associated with the class. - - - -The name of the class; usually it is the same name as the -context structure type to which the AVClass is associated. - - - - Compare 2 integers modulo mod. - That is we compare integers a and b for which only the least - significant log2(mod) bits are known. - - @param mod must be a power of 2 - @return a negative value if a is smaller than b - a positive value if a is greater than b - 0 if a equals b - - - -Compare 2 timestamps each in its own timebases. -The result of the function is undefined if one of the timestamps -is outside the int64_t range when represented in the others timebase. -@return -1 if ts_a is before ts_b, 1 if ts_a is after ts_b or 0 if they represent the same position - - - -Rescale a 64-bit integer by 2 rational numbers. - - - -Rescale a 64-bit integer with specified rounding. -A simple a*b/c isn't possible as it can overflow. - - - -Rescale a 64-bit integer with rounding to nearest. -A simple a*b/c isn't possible as it can overflow. - - - -@} - -@addtogroup lavu_math -@{ - - - -Find the nearest value in q_list to q. -@param q_list an array of rationals terminated by {0, 0} -@return the index of the nearest value found in the array - - - -@return 1 if q1 is nearer to q than q2, -1 if q2 is nearer -than q1, 0 if they have the same distance. - - - - Convert a double precision floating point number to a rational. - inf is expressed as {1,0} or {-1,0} depending on the sign. - - @param d double to convert - @param max the maximum allowed numerator and denominator - @return (AVRational) d - - - -Subtract one rational from another. -@param b first rational -@param c second rational -@return b-c - - - -Add two rationals. -@param b first rational -@param c second rational -@return b+c - - - -Divide one rational by another. -@param b first rational -@param c second rational -@return b/c - - - -Multiply two rationals. -@param b first rational -@param c second rational -@return b*c - - - -Convert rational to double. -@param a rational to convert -@return (double) a - - - -Set the maximum size that may me allocated in one block. - - - -Multiply two size_t values checking for overflow. -@return 0 if success, AVERROR(EINVAL) if overflow. - - - - Add an element to a dynamic array. - - @param tab_ptr Pointer to the array. - @param nb_ptr Pointer to the number of elements in the array. - @param elem Element to be added. - - - -Free a memory block which has been allocated with av_malloc(z)() or -av_realloc() and set the pointer pointing to it to NULL. -@param ptr Pointer to the pointer to the memory block which should -be freed. -@see av_free() - - - -Duplicate the string s. -@param s string to be duplicated -@return Pointer to a newly allocated string containing a -copy of s or NULL if the string cannot be allocated. - - - -Allocate a block of nmemb * size bytes with alignment suitable for all -memory accesses (including vectors if available on the CPU) and -zero all the bytes of the block. -The allocation will fail if nmemb * size is greater than or equal -to INT_MAX. -@param nmemb -@param size -@return Pointer to the allocated block, NULL if it cannot be allocated. - - - -Allocate a block of size bytes with alignment suitable for all -memory accesses (including vectors if available on the CPU) and -zero all the bytes of the block. -@param size Size in bytes for the memory block to be allocated. -@return Pointer to the allocated block, NULL if it cannot be allocated. -@see av_malloc() - - - -Free a memory block which has been allocated with av_malloc(z)() or -av_realloc(). -@param ptr Pointer to the memory block which should be freed. -@note ptr = NULL is explicitly allowed. -@note It is recommended that you use av_freep() instead. -@see av_freep() - - - -Allocate or reallocate a block of memory. -This function does the same thing as av_realloc, except: -- It takes two arguments and checks the result of the multiplication for - integer overflow. -- It frees the input block in case of failure, thus avoiding the memory - leak with the classic "buf = realloc(buf); if (!buf) return -1;". - - - -Allocate or reallocate a block of memory. -If ptr is NULL and size > 0, allocate a new block. If -size is zero, free the memory block pointed to by ptr. -@param ptr Pointer to a memory block already allocated with -av_malloc(z)() or av_realloc() or NULL. -@param size Size in bytes for the memory block to be allocated or -reallocated. -@return Pointer to a newly reallocated block or NULL if the block -cannot be reallocated or the function is used to free the memory block. -@see av_fast_realloc() - - - -@} - -@addtogroup lavu_mem -@{ - -Allocate a block of size bytes with alignment suitable for all -memory accesses (including vectors if available on the CPU). -@param size Size in bytes for the memory block to be allocated. -@return Pointer to the allocated block, NULL if the block cannot -be allocated. -@see av_mallocz() - - - - Convert a UTF-8 character (up to 4 bytes) to its 32-bit UCS-4 encoded form. - - @param val Output value, must be an lvalue of type uint32_t. - @param GET_BYTE Expression reading one byte from the input. - Evaluated up to 7 times (4 for the currently - assigned Unicode range). With a memory buffer - input, this could be *ptr++. - @param ERROR Expression to be evaluated on invalid input, - typically a goto statement. - - Convert a UTF-16 character (2 or 4 bytes) to its 32-bit UCS-4 encoded form. - - @param val Output value, must be an lvalue of type uint32_t. - @param GET_16BIT Expression returning two bytes of UTF-16 data converted - to native byte order. Evaluated one or two times. - @param ERROR Expression to be evaluated on invalid input, - typically a goto statement. - -@def PUT_UTF8(val, tmp, PUT_BYTE) -Convert a 32-bit Unicode character to its UTF-8 encoded form (up to 4 bytes long). -@param val is an input-only argument and should be of type uint32_t. It holds -a UCS-4 encoded Unicode character that is to be converted to UTF-8. If -val is given as a function it is executed only once. -@param tmp is a temporary variable and should be of type uint8_t. It -represents an intermediate value during conversion that is to be -output by PUT_BYTE. -@param PUT_BYTE writes the converted UTF-8 bytes to any proper destination. -It could be a function or a statement, and uses tmp as the input byte. -For example, PUT_BYTE could be "*output++ = tmp;" PUT_BYTE will be -executed up to 4 times for values in the valid UTF-8 range and up to -7 times in the general case, depending on the length of the converted -Unicode character. - -@def PUT_UTF16(val, tmp, PUT_16BIT) -Convert a 32-bit Unicode character to its UTF-16 encoded form (2 or 4 bytes). -@param val is an input-only argument and should be of type uint32_t. It holds -a UCS-4 encoded Unicode character that is to be converted to UTF-16. If -val is given as a function it is executed only once. -@param tmp is a temporary variable and should be of type uint16_t. It -represents an intermediate value during conversion that is to be -output by PUT_16BIT. -@param PUT_16BIT writes the converted UTF-16 data to any proper destination -in desired endianness. It could be a function or a statement, and uses tmp -as the input byte. For example, PUT_BYTE could be "*output++ = tmp;" -PUT_BYTE will be executed 1 or 2 times depending on input character. - -@file -memory handling functions - -@file -Macro definitions for various function/variable attributes - -@file -error code definitions - - @addtogroup lavu_error - - @{ - -This is semantically identical to AVERROR_BUG -it has been introduced in Libav after our AVERROR_BUG and with a modified value. - - Put a description of the AVERROR code errnum in errbuf. - In case of failure the global variable errno is set to indicate the - error. Even in case of failure av_strerror() will print a generic - error message indicating the errnum provided to errbuf. - - @param errnum error code to describe - @param errbuf buffer to which description is written - @param errbuf_size the size in bytes of errbuf - @return 0 on success, a negative value if a description for errnum - cannot be found - - - -Count number of bits set to one in x -@param x value to count bits of -@return the number of bits set to one in x - - - -Count number of bits set to one in x -@param x value to count bits of -@return the number of bits set to one in x - - - -Compute ceil(log2(x)). - * @param x value used to compute ceil(log2(x)) - * @return computed ceiling of log2(x) - - - -Clip a float value into the amin-amax range. -@param a value to clip -@param amin minimum value of the clip range -@param amax maximum value of the clip range -@return clipped value - - - -Clip a signed integer to an unsigned power of two range. -@param a value to clip -@param p bit position to clip at -@return clipped value - - - -Clip a signed 64-bit integer value into the -2147483648,2147483647 range. -@param a value to clip -@return clipped value - - - -Clip a signed integer value into the -32768,32767 range. -@param a value to clip -@return clipped value - - - -Clip a signed integer value into the 0-65535 range. -@param a value to clip -@return clipped value - - - -Clip a signed integer value into the -128,127 range. -@param a value to clip -@return clipped value - - - -Clip a signed integer value into the 0-255 range. -@param a value to clip -@return clipped value - - - -@file -common internal and external API header - -Clip a signed integer value into the amin-amax range. -@param a value to clip -@param amin minimum value of the clip range -@param amax maximum value of the clip range -@return clipped value - - - -@file -Macro definitions for various function/variable attributes - -Disable warnings about deprecated features -This is useful for sections of code kept for backward compatibility and -scheduled for removal. - -Mark a variable as used and prevent the compiler from optimizing it -away. This is useful for variables accessed only from inline -assembler without the compiler being aware. - - - -@} - -@file -common internal and external API header - - - - Return a single letter to describe the given picture type - pict_type. - - @param[in] pict_type the picture type @return a single character - representing the picture type, '?' if pict_type is unknown - - - - @defgroup lavu_const Constants - @{ - - @defgroup lavu_enc Encoding specific - - @note those definition should move to avcodec - @{ - - @} - @defgroup lavu_time Timestamp specific - - FFmpeg internal timebase and timestamp definitions - - @{ - - @brief Undefined timestamp value - - Usually reported by demuxer that work on containers that do not provide - either pts or dts. - -Internal time base represented as integer - -Internal time base represented as fractional value - - @} - @} - @defgroup lavu_picture Image related - - AVPicture types, pixel formats and basic image planes manipulation. - - @{ - - -Picture type of the frame, see ?_TYPE below. -- encoding: Set by libavcodec. for coded_picture (and set by user for input). -- decoding: Set by libavcodec. - - - -Return a string describing the media_type enum, NULL if media_type -is unknown. - - - -@} - -@addtogroup lavu_media Media Type -@brief Media Type - - - Type of codec implemented by the hardware accelerator. - - See AVMEDIA_TYPE_xxx - - -Get the type of the given codec. - - - -Return the libavutil license. - - - -Return the libavutil build-time configuration. - - - -@file -external API header - - @mainpage - - @section libav_intro Introduction - - This document describe the usage of the different libraries - provided by FFmpeg. - - @li @ref libavc "libavcodec" encoding/decoding library - @li @subpage libavfilter graph based frame editing library - @li @ref libavf "libavformat" I/O and muxing/demuxing library - @li @ref lavd "libavdevice" special devices muxing/demuxing library - @li @ref lavu "libavutil" common utility library - @li @subpage libpostproc post processing library - @li @subpage libswscale color conversion and scaling library - - - @defgroup lavu Common utility functions - - @brief - libavutil contains the code shared across all the other FFmpeg - libraries - - @note In order to use the functions provided by avutil you must include - the specific header. - - @{ - - @defgroup lavu_crypto Crypto and Hashing - - @{ - @} - - @defgroup lavu_math Maths - @{ - - @} - - @defgroup lavu_string String Manipulation - - @{ - - @} - - @defgroup lavu_mem Memory Management - - @{ - - @} - - @defgroup lavu_data Data Structures - @{ - - @} - - @defgroup lavu_audio Audio related - - @{ - - @} - - @defgroup lavu_error Error Codes - - @{ - - @} - - @defgroup lavu_misc Other - - @{ - - @defgroup lavu_internal Internal - - Not exported functions, for internal usage only - - @{ - - @} - - @defgroup preproc_misc Preprocessor String Macros - - String manipulation macros - - @{ - -@} - - @defgroup version_utils Library Version Macros - - Useful to check and match library version in order to maintain - backward compatibility. - - @{ - - @} - - @defgroup lavu_ver Version and Build diagnostics - - Macros and function useful to check at compiletime and at runtime - which version of libavutil is in use. - - @{ - - @} - - @defgroup depr_guards Deprecation guards - Those FF_API_* defines are not part of public API. - They may change, break or disappear at any time. - - They are used mostly internally to mark code that will be removed - on the next major version. - - @{ - -@} - -@addtogroup lavu_ver -@{ - -Return the LIBAVUTIL_VERSION_INT constant. - - - - -Enumeration of some video codecs from FFmpeg library, which are available for writing video files. - - - - -Raw (uncompressed) video. - - - - -MPEG-2 part 2. - - - - -Flash Video (FLV) / Sorenson Spark / Sorenson H.263. - - - - -H.263+ / H.263-1998 / H.263 version 2. - - - - -MPEG-4 part 2 Microsoft variant version 3. - - - - -MPEG-4 part 2 Microsoft variant version 2. - - - - -Windows Media Video 8. - - - - -Windows Media Video 7. - - - - -MPEG-4 part 2. - - - - -Default video codec, which FFmpeg library selects for the specified file format. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Externals/AForge.NET/AForge.Video.Kinect.dll b/Externals/AForge.NET/AForge.Video.Kinect.dll deleted file mode 100644 index ddcf3e08f..0000000000 Binary files a/Externals/AForge.NET/AForge.Video.Kinect.dll and /dev/null differ diff --git a/Externals/AForge.NET/AForge.Video.Kinect.xml b/Externals/AForge.NET/AForge.Video.Kinect.xml deleted file mode 100644 index a7b31d662..0000000000 --- a/Externals/AForge.NET/AForge.Video.Kinect.xml +++ /dev/null @@ -1,604 +0,0 @@ - - - - AForge.Video.Kinect - - - - - Kinect's LED color options. - - - - - The LED is off. - - - - - The LED is on and has green color. - - - - - The LED is on and has red color. - - - - - The LED is on and has yellow color. - - - - - The LED is blinking with green color. - - - - - The LED is blinking from red to yellow color. - - - - - Kinect's resolutions of video and depth cameras. - - - - - Low resolution. - - - - - Medium resolution. - - - - - Hight resolution. - - - - - Video source for Microsoft Kinect's depth sensor. - - - The video source captures depth data from Microsoft Kinect - depth sensor, which is aimed originally as a gaming device for XBox 360 platform. - - Prior to using the class, make sure you've installed Kinect's drivers - as described on Open Kinect - project's page. - - In order to run correctly the class requires freenect.dll library - to be put into solution's output folder. This can be found within the AForge.NET framework's - distribution in Externals folder. - - Sample usage: - - // create video source - KinectDepthCamera videoSource = new KinectDepthCamera( 0 ); - // set NewFrame event handler - videoSource.NewFrame += new NewFrameEventHandler( video_NewFrame ); - // start the video source - videoSource.Start( ); - // ... - - private void video_NewFrame( object sender, NewFrameEventArgs eventArgs ) - { - // get new frame - Bitmap bitmap = eventArgs.Frame; - // process the frame - } - - - - - - - Initializes a new instance of the class. - - - Kinect's device ID (index) to connect to. - - - - - Initializes a new instance of the class. - - - Kinect's device ID (index) to connect to. - Resolution of depth sensor to set. - - - - - Initializes a new instance of the class. - - - Kinect's device ID (index) to connect to. - Resolution of depth sensor to set. - Provide original depth image or colored depth map - (see property). - - - - - Start video source. - - - Starts video source and returns execution to caller. Video camera will be started - and will provide new video frames through the event. - - The specified resolution is not supported for the selected - mode of the Kinect depth sensor. - Could not connect to Kinect's depth sensor. - Another connection to the specified depth sensor is already running. - - - - - Signal video source to stop its work. - - - Calling this method is equivalent to calling - for Kinect video camera. - - - - - Wait for video source has stopped. - - - Calling this method is equivalent to calling - for Kinect video camera. - - - - - Stop video source. - - - The method stop the video source, so it no longer provides new video frames - and does not consume any resources. - - - - - - New frame event. - - - Notifies clients about new available frames from the video source. - - Since video source may have multiple clients, each client is responsible for - making a copy (cloning) of the passed video frame, because the video source disposes its - own original copy after notifying of clients. - - - - - - Video source error event. - - - This event is used to notify clients about any type of errors occurred in - video source object, for example internal exceptions. - - - - - Video playing finished event. - - - This event is used to notify clients that the video playing has finished. - - - - - - Provide original depth image or colored depth map. - - - The property specifies if the video source should provide original data - provided by Kinect's depth sensor or provide colored depth map. If the property is set to - , then the video source will provide 16 bpp grayscale images, where - 11 least significant bits represent data provided by the sensor. If the property is - set to , then the video source will provide 24 bpp color images, - which represents depth map. In this case depth is encoded by color gradient: - white->red->yellow->green->cyan->blue->black. So colors which are closer to white represent - objects which are closer to the Kinect sensor, but colors which are closer to black represent - objects which are further away from Kinect. - - The property must be set before running the video source to take effect. - - Default value is set to . - - - - - - Resolution of depth sensor to set. - - - The property must be set before running the video source to take effect. - - Default value of the property is set to . - - - - - - A string identifying the video source. - - - - - - State of the video source. - - - Current state of video source object - running or not. - - - - - Received bytes count. - - - Number of bytes the video source provided from the moment of the last - access to the property. - - - - - - Received frames count. - - - Number of frames the video source provided from the moment of the last - access to the property. - - - - - - The class provides access to Microsoft's Xbox Kinect - controller. - - - The class allows to manipulate Kinec device by changing its LED color, setting motor's - tilt value and accessing its camera. See and - classes, which provide access to actual video. - - - - In order to run correctly the class requires freenect.dll library - to be put into solution's output folder. This can be found within the AForge.NET framework's - distribution in Externals folder. - - Sample usage: - - // get Kinect device - Kinect kinectDevice = Kinect.GetDevice( 0 ); - // change LED color - kinectDevice.LedColor = LedColorOption.Yellow; - // set motor tilt angle to -10 degrees - kinectDevice.SetMotorTilt( -10 ); - // get video camera - KinectVideoCamera videoCamera = kinectDevice.GetVideoCamera( ); - - // see example for video camera also - - - - - - - Get initialized instance of the Kinect device. - - - ID of the Kinect device to get instance of, [0, ), - - Returns initialized Kinect device. Use method - when the device is no longer required. - - There is no Kinect device with specified ID connected to the system. - Failed connecting to the Kinect device specified ID. - - - - - Object finalizer/destructor makes sure unmanaged resource are freed if user did not call . - - - - - Dispose device freeing all associated unmanaged resources. - - - - - Set color of Kinect's LED. - - - LED color to set. - - Some error occurred with the device. Check error message. - - - - - Set motor's tilt value. - - - Tilt value to set, [-31, 30] degrees. - - Motor tilt has to be in the [-31, 31] range. - Some error occurred with the device. Check error message. - - - - - Get accelerometer values for 3 axes. - - - X axis value on the accelerometer. - Y axis value on the accelerometer. - Z axis value on the accelerometer. - - Units of all 3 values are m/s2. The g value used - for calculations is taken as 9.80665 m/s2. - - - - - Get Kinect's video camera. - - - Returns Kinect's video camera. - - The method simply creates instance of the class - by calling its appropriate constructor. Use method - to start the video then. - - - - - Get Kinect's depth camera. - - - Returns Kinect's depth camera. - - The method simply creates instance of the class - by calling its appropriate constructor. Use method - to start the video then. - - - - - ID of the opened Kinect device. - - - - - - Number of Kinect devices available in the system. - - - - - Enumeration of video camera modes for the . - - - - - 24 bit per pixel RGB mode. - - - - - 8 bit per pixel Bayer mode. - - - - - 8 bit per pixel Infra Red mode. - - - - - Video source for Microsoft Kinect's video camera. - - - The video source captures video data from Microsoft Kinect - video camera, which is aimed originally as a gaming device for XBox 360 platform. - - Prior to using the class, make sure you've installed Kinect's drivers - as described on Open Kinect - project's page. - - In order to run correctly the class requires freenect.dll library - to be put into solution's output folder. This can be found within the AForge.NET framework's - distribution in Externals folder. - - Sample usage: - - // create video source - KinectVideoCamera videoSource = new KinectVideoCamera( 0 ); - // set NewFrame event handler - videoSource.NewFrame += new NewFrameEventHandler( video_NewFrame ); - // start the video source - videoSource.Start( ); - // ... - - private void video_NewFrame( object sender, NewFrameEventArgs eventArgs ) - { - // get new frame - Bitmap bitmap = eventArgs.Frame; - // process the frame - } - - - - - - - Initializes a new instance of the class. - - - Kinect's device ID (index) to connect to. - - - - - Initializes a new instance of the class. - - - Kinect's device ID (index) to connect to. - Resolution of video camera to set. - - - - - Initializes a new instance of the class. - - - Kinect's device ID (index) to connect to. - Resolution of video camera to set. - Sets video camera mode. - - - - - Start video source. - - - Starts video source and returns execution to caller. Video camera will be started - and will provide new video frames through the event. - - The specified resolution is not supported for the selected - mode of the Kinect video camera. - Could not connect to Kinect's video camera. - Another connection to the specified video camera is already running. - - - - - Signal video source to stop its work. - - - Calling this method is equivalent to calling - for Kinect video camera. - - - - - Wait for video source has stopped. - - - Calling this method is equivalent to calling - for Kinect video camera. - - - - - Stop video source. - - - The method stops the video source, so it no longer provides new video frames - and does not consume any resources. - - - - - - New frame event. - - - Notifies clients about new available frames from the video source. - - Since video source may have multiple clients, each client is responsible for - making a copy (cloning) of the passed video frame, because the video source disposes its - own original copy after notifying of clients. - - - - - - Video source error event. - - - This event is used to notify clients about any type of errors occurred in - video source object, for example internal exceptions. - - - - - Video playing finished event. - - - This event is used to notify clients that the video playing has finished. - - - - - - Specifies video mode for the camera. - - - - The property must be set before running the video source to take effect. - - Default value of the property is set to . - - - - - - Resolution of video camera to set. - - - The property must be set before running the video source to take effect. - - Default value of the property is set to . - - - - - - A string identifying the video source. - - - - - - State of the video source. - - - Current state of video source object - running or not. - - - - - Received bytes count. - - - Number of bytes the video source provided from the moment of the last - access to the property. - - - - - - Received frames count. - - - Number of frames the video source provided from the moment of the last - access to the property. - - - - - diff --git a/Externals/AForge.NET/AForge.Video.VFW.dll b/Externals/AForge.NET/AForge.Video.VFW.dll deleted file mode 100644 index d7b5a3261..0000000000 Binary files a/Externals/AForge.NET/AForge.Video.VFW.dll and /dev/null differ diff --git a/Externals/AForge.NET/AForge.Video.VFW.xml b/Externals/AForge.NET/AForge.Video.VFW.xml deleted file mode 100644 index b1364fbac..0000000000 --- a/Externals/AForge.NET/AForge.Video.VFW.xml +++ /dev/null @@ -1,1098 +0,0 @@ - - - - AForge.Video.VFW - - - - - AVI files writing using Video for Windows interface. - - - The class allows to write AVI files using Video for Windows API. - - Sample usage: - - // instantiate AVI writer, use WMV3 codec - AVIWriter writer = new AVIWriter( "wmv3" ); - // create new AVI file and open it - writer.Open( "test.avi", 320, 240 ); - // create frame image - Bitmap image = new Bitmap( 320, 240 ); - - for ( int i = 0; i < 240; i++ ) - { - // update image - image.SetPixel( i, i, Color.Red ); - // add the image as a new frame of video file - writer.AddFrame( image ); - } - writer.Close( ); - - - - - - - Initializes a new instance of the class. - - - Initializes Video for Windows library. - - - - - Initializes a new instance of the class. - - - Codec to use for compression. - - Initializes Video for Windows library. - - - - - Destroys the instance of the class. - - - - - - Dispose the object. - - - Frees unmanaged resources used by the object. The object becomes unusable - after that. - - - - - Dispose the object. - - - Indicates if disposing was initiated manually. - - - - - Create new AVI file and open it for writing. - - - AVI file name to create. - Video width. - Video height. - - The method opens (creates) a video files, configure video codec and prepares - the stream for saving video frames with a help of method. - - Failed opening the specified file. - A error occurred while creating new video file. See exception message. - Insufficient memory for internal buffer. - Video file resolution must be a multiple of two. - - - - - Close video file. - - - - - - Add new frame to the AVI file. - - - New frame image. - - The method adds new video frame to an opened video file. The width and heights - of the frame should be the same as it was specified in method - (see and properties). - - Thrown if no video file was open. - Bitmap size must be of the same as video size, which was specified on opening video file. - A error occurred while writing new video frame. See exception message. - - - - - Width of video frames. - - - The property specifies the width of video frames, which are acceptable - by method for saving, which is set in - method. - - - - - Height of video frames. - - - The property specifies the height of video frames, which are acceptable - by method for saving, which is set in - method. - - - - - Current position in video stream. - - - The property tell current position in video stream, which actually equals - to the amount of frames added using method. - - - - - Desired playing frame rate. - - - The property sets the video frame rate, which should be use during playing - of the video to be saved. - - The property should be set befor opening new file to take effect. - - Default frame rate is set to 25. - - - - - Codec used for video compression. - - - The property sets the FOURCC code of video compression codec, which needs to - be used for video encoding. - - The property should be set befor opening new file to take effect. - - Default video codec is set "DIB ", which means no compression. - - - - - Compression video quality. - - - The property sets video quality used by codec in order to balance compression rate - and image quality. The quality is measured usually in the [0, 100] range. - - The property should be set befor opening new file to take effect. - - Default value is set to -1 - default compression quality of the codec. - - - - - AVI files reading using Video for Windows. - - - The class allows to read AVI files using Video for Windows API. - - Sample usage: - - // instantiate AVI reader - AVIReader reader = new AVIReader( ); - // open video file - reader.Open( "test.avi" ); - // read the video file - while ( reader.Position - reader.Start < reader.Length ) - { - // get next frame - Bitmap image = reader.GetNextFrame( ); - // .. process the frame somehow or display it - } - reader.Close( ); - - - - - - - Initializes a new instance of the class. - - - Initializes Video for Windows library. - - - - - Destroys the instance of the class. - - - - - - Dispose the object. - - - Frees unmanaged resources used by the object. The object becomes unusable - after that. - - - - - Dispose the object. - - - Indicates if disposing was initiated manually. - - - - - Open AVI file. - - - AVI file name to open. - - The method opens a video file and prepares the stream and decoder for - reading video frames with the help of method. - - - Failed opening the specified file. - A error occurred while opening the video file. See exception message. - - - - - - Close video file. - - - - - - Get next frame of opened video stream. - - - Returns next frame as a bitmap. - - The method reads and returns the next video frame in the opened video stream - at the position, which is set in property. - - Thrown if no video file was open. - A error occurred while reading next video frame. See exception message. - - - - - Width of video frames. - - - The property specifies the width of video frames within the opened video - file. - - - - - Height of video frames. - - - The property specifies the height of video frames within the opened video - file. - - - - - Current position in video stream. - - - Setting position outside of video range, will lead to reseting position to the start. - - - - - Starting position of video stream. - - - - - - Video stream length. - - - - - - Desired playing frame rate. - - - The property specifies the frame rate, which should be used to play the opened video - file. - - - - - Codec used for video compression. - - - The property tells about which codec was used to encode the opened video file. - - - - - AVI file video source. - - - The video source reads AVI files using Video for Windows. - - Sample usage: - - // create AVI file video source - AVIFileVideoSource source = new AVIFileVideoSource( "some file" ); - // set event handlers - source.NewFrame += new NewFrameEventHandler( video_NewFrame ); - // start the video source - source.Start( ); - // ... - // signal to stop - source.SignalToStop( ); - - // New frame event handler, which is invoked on each new available video frame - private void video_NewFrame( object sender, NewFrameEventArgs eventArgs ) - { - // get new frame - Bitmap bitmap = eventArgs.Frame; - // process the frame - } - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Video file name. - - - - - Start video source. - - - Starts video source and return execution to caller. Video source - object creates background thread and notifies about new frames with the - help of event. - - Video source is not specified. - - - - - Signal video source to stop its work. - - - Signals video source to stop its background thread, stop to - provide new frames and free resources. - - - - - Wait for video source has stopped. - - - Waits for source stopping after it was signalled to stop using - method. - - - - - Stop video source. - - - Stops video source aborting its thread. - - Since the method aborts background thread, its usage is highly not preferred - and should be done only if there are no other options. The correct way of stopping camera - is signaling it stop and then - waiting for background thread's completion. - - - - - - Free resource. - - - - - - Worker thread. - - - - - - New frame event. - - - Notifies clients about new available frame from video source. - - Since video source may have multiple clients, each client is responsible for - making a copy (cloning) of the passed video frame, because the video source disposes its - own original copy after notifying of clients. - - - - - - Video source error event. - - - This event is used to notify clients about any type of errors occurred in - video source object, for example internal exceptions. - - - - - Video playing finished event. - - - This event is used to notify clients that the video playing has finished. - - - - - - Frame interval. - - - The property sets the interval in milliseconds between frames. If the property is - set to 100, then the desired frame rate will be 10 frames per second. - - Setting this property to 0 leads to no delay between video frames - frames - are read as fast as possible. - - Default value is set to 0. - - - - - - Get frame interval from source or use manually specified. - - - The property specifies which frame rate to use for video playing. - If the property is set to , then video is played - with original frame rate, which is set in source AVI file. If the property is - set to , then custom frame rate is used, which is - calculated based on the manually specified frame interval. - - Default value is set to . - - - - - - Video source. - - - Video file name to play. - - - - - Received frames count. - - - Number of frames the video source provided from the moment of the last - access to the property. - - - - - - Received bytes count. - - - Number of bytes the video source provided from the moment of the last - access to the property. - - - - - - State of the video source. - - - Current state of video source object - running or not. - - - - - Windows API functions and structures. - - - The class provides Video for Windows and some other Win32 functions and structurs. - - - - - Copy a block of memory. - - - Destination pointer. - Source pointer. - Memory block's length to copy. - - Return's the value of dst - pointer to destination. - - - - - Initialize the AVIFile library. - - - - - - Exit the AVIFile library. - - - - - Open an AVI file. - - - Opened AVI file interface. - AVI file name. - Opening mode (see ). - Handler to use (null to use default). - - Returns zero on success or error code otherwise. - - - - - Release an open AVI stream. - - - Open AVI file interface. - - Returns the reference count of the file. - - - - - Get stream interface that is associated with a specified AVI file - - - Handler to an open AVI file. - Stream interface. - Stream type to open. - Count of the stream type. Identifies which occurrence of the specified stream type to access. - - - - - - - Create a new stream in an existing file and creates an interface to the new stream. - - - Handler to an open AVI file. - Stream interface. - Pointer to a structure containing information about the new stream. - - Returns zero if successful or an error otherwise. - - - - - Release an open AVI stream. - - - Handle to an open stream. - - Returns the current reference count of the stream. - - - - - Set the format of a stream at the specified position. - - - Handle to an open stream. - Position in the stream to receive the format. - Pointer to a structure containing the new format. - Size, in bytes, of the block of memory referenced by format. - - Returns zero if successful or an error otherwise. - - - - - Get the starting sample number for the stream. - - - Handle to an open stream. - - Returns the number if successful or – 1 otherwise. - - - - - Get the length of the stream. - - - Handle to an open stream. - - Returns the stream's length, in samples, if successful or -1 otherwise. - - - - - Obtain stream header information. - - - Handle to an open stream. - Pointer to a structure to contain the stream information. - Size, in bytes, of the structure used for streamInfo. - - Returns zero if successful or an error otherwise. - - - - - Prepare to decompress video frames from the specified video stream - - - Pointer to the video stream used as the video source. - Pointer to a structure that defines the desired video format. Specify NULL to use a default format. - - Returns an object that can be used with the function. - - - - - Prepare to decompress video frames from the specified video stream. - - - Pointer to the video stream used as the video source. - Pointer to a structure that defines the desired video format. Specify NULL to use a default format. - - Returns a GetFrame object that can be used with the function. - - - - - Releases resources used to decompress video frames. - - - Handle returned from the function. - - Returns zero if successful or an error otherwise. - - - - - Return the address of a decompressed video frame. - - - Pointer to a GetFrame object. - Position, in samples, within the stream of the desired frame. - - Returns a pointer to the frame data if successful or NULL otherwise. - - - - - Write data to a stream. - - - Handle to an open stream. - First sample to write. - Number of samples to write. - Pointer to a buffer containing the data to write. - Size of the buffer referenced by buffer. - Flag associated with this data. - Pointer to a buffer that receives the number of samples written. This can be set to NULL. - Pointer to a buffer that receives the number of bytes written. This can be set to NULL. - - Returns zero if successful or an error otherwise. - - - - - Retrieve the save options for a file and returns them in a buffer. - - - Handle to the parent window for the Compression Options dialog box. - Flags for displaying the Compression Options dialog box. - Number of streams that have their options set by the dialog box. - Pointer to an array of stream interface pointers. - Pointer to an array of pointers to AVICOMPRESSOPTIONS structures. - - Returns TRUE if the user pressed OK, FALSE for CANCEL, or an error otherwise. - - - - - Free the resources allocated by the AVISaveOptions function. - - - Count of the AVICOMPRESSOPTIONS structures referenced in options. - Pointer to an array of pointers to AVICOMPRESSOPTIONS structures. - - Returns 0. - - - - - Create a compressed stream from an uncompressed stream and a - compression filter, and returns the address of a pointer to - the compressed stream. - - - Pointer to a buffer that receives the compressed stream pointer. - Pointer to the stream to be compressed. - Pointer to a structure that identifies the type of compression to use and the options to apply. - Pointer to a class identifier used to create the stream. - - Returns 0 if successful or an error otherwise. - - - - - .NET replacement of mmioFOURCC macros. Converts four characters to code. - - - Four characters string. - - Returns the code created from provided characters. - - - - - Inverse to . Converts code to fout characters string. - - - Code to convert. - - Returns four characters string. - - - - - Version of for one stream only. - - - Stream to configure. - Stream options. - - Returns TRUE if the user pressed OK, FALSE for CANCEL, or an error otherwise. - - - - - Structure to define the coordinates of the upper-left and - lower-right corners of a rectangle. - - - - - - x-coordinate of the upper-left corner of the rectangle. - - - - - - y-coordinate of the upper-left corner of the rectangle. - - - - - - x-coordinate of the bottom-right corner of the rectangle. - - - - - - y-coordinate of the bottom-right corner of the rectangle. - - - - - - Structure, which contains information for a single stream . - - - - - - Four-character code indicating the stream type. - - - - - - Four-character code of the compressor handler that will compress this video stream when it is saved. - - - - - - Applicable flags for the stream. - - - - - - Capability flags; currently unused. - - - - - - Priority of the stream. - - - - - - Language of the stream. - - - - - - Time scale applicable for the stream. - - - Dividing rate by scale gives the playback rate in number of samples per second. - - - - - Rate in an integer format. - - - - - - Sample number of the first frame of the AVI file. - - - - - - Length of this stream. - - - The units are defined by rate and scale. - - - - - Audio skew. This member specifies how much to skew the audio data ahead of the video frames in interleaved files. - - - - - - Recommended buffer size, in bytes, for the stream. - - - - - - Quality indicator of the video data in the stream. - - - Quality is represented as a number between 0 and 10,000. - - - - - Size, in bytes, of a single data sample. - - - - - - Dimensions of the video destination rectangle. - - - - - - Number of times the stream has been edited. - - - - - - Number of times the stream format has changed. - - - - - - Description of the stream. - - - - - - Structure, which contains information about the dimensions and color format of a DIB. - - - - - - Specifies the number of bytes required by the structure. - - - - - - Specifies the width of the bitmap, in pixels. - - - - - - Specifies the height of the bitmap, in pixels. - - - If height is positive, the bitmap is a bottom-up DIB and its origin is - the lower-left corner. If height is negative, the bitmap is a top-down DIB and its - origin is the upper-left corner. - - - - - Specifies the number of planes for the target device. This value must be set to 1. - - - - - - Specifies the number of bits-per-pixel. - - - - - - Specifies the type of compression for a compressed bottom-up bitmap (top-down DIBs cannot be compressed). - - - - - - Specifies the size, in bytes, of the image. - - - - - - Specifies the horizontal resolution, in pixels-per-meter, of the target device for the bitmap. - - - - - - Specifies the vertical resolution, in pixels-per-meter, of the target device for the bitmap. - - - - - - Specifies the number of color indexes in the color table that are actually used by the bitmap. - - - - - - Specifies the number of color indexes that are required for displaying the bitmap. - - - - - - Structure, which contains information about a stream and how it is compressed and saved. - - - - - - Four-character code indicating the stream type. - - - - - - Four-character code for the compressor handler that will compress this video stream when it is saved. - - - - - - Maximum period between video key frames. - - - - - - Quality value passed to a video compressor. - - - - - - Video compressor data rate. - - - - - - Flags used for compression. - - - - - - Pointer to a structure defining the data format. - - - - - - Size, in bytes, of the data referenced by format. - - - - - - Video-compressor-specific data; used internally. - - - - - - Size, in bytes, of the data referenced by parameters. - - - - - Interleave factor for interspersing stream data with data from the first stream. - - - - - - File access modes. - - - - - diff --git a/Externals/AForge.NET/AForge.Video.Ximea.dll b/Externals/AForge.NET/AForge.Video.Ximea.dll deleted file mode 100644 index 6195346e0..0000000000 Binary files a/Externals/AForge.NET/AForge.Video.Ximea.dll and /dev/null differ diff --git a/Externals/AForge.NET/AForge.Video.Ximea.xml b/Externals/AForge.NET/AForge.Video.Ximea.xml deleted file mode 100644 index 688d30f9d..0000000000 --- a/Externals/AForge.NET/AForge.Video.Ximea.xml +++ /dev/null @@ -1,1122 +0,0 @@ - - - - AForge.Video.Ximea - - - - - XIMEA camera's LED state options. - - - - - Blink if link is ok (led 1), heartbeat mode (led 2). - - - - - Blink led if trigger detected. - - - - - Blink led if external signal detected. - - - - - Blink led during data streaming. - - - - - Blink led during sensor integration time. - - - - - Blink if device busy/not busy. - - - - - Blink led if link is OK. - - - - - Turn off LED. - - - - - Turn on LED. - - - - - Enumeration of image formats supported by XIMEA cameras. - - - - - 8 bits per pixel. - - - - - 16 bits per pixel. - - - - - RGB data format. - - - - - RGBA data format. - - - - - XIMEA camera's GPI port modes. - - - - - Input is off. - - - - - Trigger input. - - - - - External signal input. - - - - - Set of available configuration options for XIMEA cameras. - - - The class defines list of parameters, which are available - to set/get using corresponding methods of and - classes. - - - - - Get camera model name. Type string. - - - - - Get device serial number in decimal format. Type string, integer, float - - - - - Returns device type (1394, USB2.0, CURRERA…..). Type string. - - - - - Set/Get exposure time in microseconds. Type integer. - - - - - Get longest possible exposure to be set on camera in microseconds. Type integer. - - - - - Get shortest possible exposure to be set on camera in microseconds. Type integer. - - - - - Set/Get camera gain in dB. Type float. - - - - - Get highest possible camera gain in dB. Type float. - - - - - Get lowest possible camera gain in dB. Type float. - - - - - Set/Get width of the image provided by the camera (in pixels). Type integer. - - - - - Get maximal image width provided by the camera (in pixels). Type integer. - - - - - Get minimum image width provided by the camera (in pixels). Type integer. - - - - - Set/Get height of the image provided by the camera (in pixels). Type integer. - - - - - Get maximal image height provided by the camera (in pixels). Type integer. - - - - - Get minimum image height provided by the camera (in pixels). Type integer. - - - - - Set/Get image resolution by binning or skipping. Type integer. - - - - - Get highest value for binning or skipping. Type integer. - - - - - Get lowest value for binning or skipping. Type integer. - - - - - Get frames per second. Type float. - - - - - Get highest possible framerate for current camera settings. Type float. - - - - - Get lowest framerate for current camera settings. Type float. - - - - - Set/Get horizontal offset from the origin to the area of interest (in pixels). Type integer. - - - - - Get maximum horizontal offset from the origin to the area of interest (in pixels). Type integer. - - - - - Get minimum horizontal offset from the origin to the area of interest (in pixels). Type integer. - - - - - Set/Get vertical offset from the origin to the area of interest (in pixels). Type integer. - - - - - Get maximum vertical offset from the origin to the area of interest (in pixels). Type integer. - - - - - Get minimal vertical offset from the origin to the area of interest (in pixels). Type integer. - - - - - Set/Get white balance blue coefficient. Type float. - - - - - Set/Get white balance red coefficient. Type float. - - - - - Set/Get white balance green coefficient. Type float. - - - - - Set/Get sharpness strenght. Type float. - - - - - Set/Get luminosity gamma value. Type float. By default 1.0. - - - - - Set/Get chromaticity gamma value. Type float. By default 0. - - - - - Set default color correction matrx. - - - - - Set/Get image format provided by the camera. Type integer. Use - enumeraton for possible values. - - - - - Set/Get camera's trigger mode. Type integer. Use - enumeration for possible values. - - - - - Generates an internal trigger. must be set to . - Type integer. - - - - - Calculates white balance. Takes white balance from image center (should be white/grey object - in the center of scene). Type integer. - - - - - Enable/disable automatic white balance. Type integer. By default 0. - - - Set 0 to disable automatic white balance or 1 to enable. - - - - - Enable/disable bad pixels correction. Type integer. By default 0. - - - Set 0 to disable bad pixels correction or 1 to enable. - - - - - Set/Get acquisition buffer size in bytes. Type integer. By default 53248000. - - - Defines acquisition buffer size in bytes. This buffer contains images' - data from sensor. This parameter can be set only when acquisition is stopped. - - See for additional information. - - - - - - Set/Get maximum number of images to store in queue. Type integer. By default 4. - - - - - - See also for additional information. - - - - - - Set of configuration options to configure Automatic Exposure/Gain (AEAG) parameters. - - - - - Enable/disable automatic exposure/gain control. Type integer. By default 0. - - - Set 0 to disable automatic exposure/gain control or 1 to enable. - - - - - Set/Get maximum limit of exposure in AEAG procedure. Type integer. By default 100. Units - ms. - - - - - Set/Get maximum limit of gain in AEAG procedure. Type float. Default depends on camera type. Units - dB. - - - - - Set/Get exposure priority, [0, 1]. Type float. By default 0.8. - - - Setting the value to 0.5, for example, set exposure priority to 50% - and gain priority to 50%. - - - - - Set/Get average intensity of output signal AEAG should achieve (in %). Type float. By default 40. - - - - - Set of configuration options to configure camera's LEDs. Currently supported only for Currera-R cameras. - - - - - Selects camera LED to be used. Type integer. - - - - - Get highest LED number on camera. Type integer. - - - - - Get lowest LED number on camera. Type integer. - - - - - Set/Get LED functionality. Select LED by using parameter. - Use enumeration for possible parameter values. Type integer. - - - - - Set of configuration options to configure GPO (General Purpose Output) ports. - - - - - Select camera GPO port. Type integer. - - - - - Get highest GPO port number on camera. Type integer. - - - - - Get lowest GPO port number on camera. Type integer - - - - - Set/Get GPO port functionality. Select port by using parameter. - Use enumeration to set mode. Type integer. - - - - - Set of configuration options to access/configure GPI (General Purpose Input) ports. - - - - - Select camera GPI port. Type integer. - - - - - Get highest GPI port number on camera. Type integer. - - - - - Get lowest GPI port number on camera. Type integer - - - - - Set/Get GPI port functionality. Select port by using parameter. - Use enumeration to set mode. Type integer. - - - - - Get current GPI level. Type integer. - - - - - Set of configuration options to configure camera's LUT - Look-Up-Table. - Currently available only for Currera-R cameras. - - - - - Enable/Disable LUT. Type integer. Default 0. - - - Set 0 to disable LUT - sensor pixels are transferred directly. - Set 1 to enable LUT - sensor pixels are mapped through LUT. - - - - - Set/Get the index (offset) of the coefficient to access in the LUT. Type integer. - - - - - Get lowest LUT index (offset) of the coefficient to access in the LUT. Type integer. - - - - - Get highest LUT index (offset) of the coefficient to access in the LUT. Type integer. - - - - - Set/Get value in the LUT. Index of the value must be selected using - parameter. Type integer. - - - - - Get highest value to be set in LUT. Type integer. - - - - - Get lowest value to be set in LUT. Type integer. - - - - - Set of configuration options to access elements of Color Correction Matrix. - - - - - - Set/Get color correction matrix element [0][0]. Type float. By default 1.0. - - - - - Set/Get color correction matrix element [0][1]. Type float. By default 0.0. - - - - - Set/Get color correction matrix element [0][2]. Type float. By default 0.0. - - - - - Set/Get color correction matrix element [0][3]. Type float. By default 0.0. - - - - - Set/Get color correction matrix element [1][0]. Type float. By default 0.0. - - - - - Set/Get color correction matrix element [1][1]. Type float. By default 1.0. - - - - - Set/Get color correction matrix element [1][2]. Type float. By default 0.0. - - - - - Set/Get color correction matrix element [1][3]. Type float. By default 0.0. - - - - - Set/Get color correction matrix element [2][0]. Type float. By default 0.0. - - - - - Set/Get color correction matrix element [2][1]. Type float. By default 0.0. - - - - - Set/Get color correction matrix element [2][2]. Type float. By default 1.0. - - - - - Set/Get color correction matrix element [2][3]. Type float. By default 0.0. - - - - - Set/Get color correction matrix element [3][0]. Type float. By default 0.0. - - - - - Set/Get color correction matrix element [3][1]. Type float. By default 0.0. - - - - - Set/Get color correction matrix element [3][2]. Type float. By default 0.0. - - - - - Set/Get color correction matrix element [3][3]. Type float. By default 1.0. - - - - - XIMEA camera's GPO port modes. - - - - - Output off. - - - - - Logical level. - - - - - High during exposure (integration) time + readout time + data transfer time. - - - - - Low during exposure (integration) time + readout time + data trasnfer time. - - - - - High during exposure(integration) time. - - - - - Low during exposure(integration) time. - - - - - The class provides access to XIMEA cameras. - - - The class allows to perform image acquisition from XIMEA cameras. - It wraps XIMEA'a xiAPI, which means that users of this class will also require m3api.dll and a correct - TM file for the camera model connected to the system (both are provided with XIMEA API software package). - - Sample usage: - - XimeaCamera camera = new XimeaCamera( ); - - // open camera and start data acquisition - camera.Open( 0 ); - camera.StartAcquisition( ); - - // set exposure time to 10 milliseconds - camera.SetParam( CameraParameter.Exposure, 10 * 1000 ); - - // get image from the camera - Bitmap bitmap = camera.GetImage( ); - // process the image - // ... - - // dispose the image when it is no longer needed - bitmap.Dispose( ); - - // stop data acquisition and close the camera - camera.StopAcquisition( ); - camera.Close( ); - - - - - - - - - Open XIMEA camera. - - - Camera ID to open. - - Opens the specified XIMEA camera preparing it for starting video acquisition - which is done using method. The - property can be used at any time to find if a camera was opened or not. - - An error occurred while communicating with a camera. See error - message for additional information. - - - - - Close opened camera (if any) and release allocated resources. - - - The method also calls method if it was not - done by user. - - An error occurred while communicating with a camera. See error - message for additional information. - - - - - Begin camera's work cycle and start data acquisition from it. - - - The property can be used at any time to find if the - acquisition was started or not. - - An error occurred while communicating with a camera. See error - message for additional information. - No camera was opened, so can not access its methods. - - - - - End camera's work cycle and stops data acquisition. - - - An error occurred while communicating with a camera. See error - message for additional information. - No camera was opened, so can not access its methods. - - - - - Set camera's parameter. - - - Parameter name. - Integer parameter value. - - The method allows to control different camera's parameters, like exposure time, gain value, etc. - See class for the list of some possible configuration parameters. See - XIMEA documentation for the complete list of supported parameters. - - - An error occurred while communicating with a camera. See error - message for additional information. - No camera was opened, so can not access its methods. - - - - - Set camera's parameter. - - - Parameter name. - Float parameter value. - - The method allows to control different camera's parameters, like exposure time, gain value, etc. - See class for the list of some possible configuration parameters. See - XIMEA documentation for the complete list of supported parameters. - - - An error occurred while communicating with a camera. See error - message for additional information. - No camera was opened, so can not access its methods. - - - - - Get camera's parameter as integer value. - - - Parameter name to get from camera. - - Returns integer value of the requested parameter. - - See class for the list of some possible configuration parameters. See - XIMEA documentation for the complete list of supported parameters. - - An error occurred while communicating with a camera. See error - message for additional information. - No camera was opened, so can not access its methods. - - - - - Get camera's parameter as float value. - - - Parameter name to get from camera. - - Returns float value of the requested parameter. - - See class for the list of some possible configuration parameters. See - XIMEA documentation for the complete list of supported parameters. - - An error occurred while communicating with a camera. See error - message for additional information. - No camera was opened, so can not access its methods. - - - - - Get camera's parameter as string value. - - - Parameter name to get from camera. - - Returns string value of the requested parameter. - - See class for the list of some possible configuration parameters. See - XIMEA documentation for the complete list of supported parameters. - - An error occurred while communicating with a camera. See error - message for additional information. - No camera was opened, so can not access its methods. - - - - - Get image from the opened XIMEA camera. - - - Returns image retrieved from the camera. - - The method calls method specifying 5000 as the timeout - value. - - - - - Get image from the opened XIMEA camera. - - - Maximum time to wait in milliseconds till image becomes available. - - Returns image retrieved from the camera. - - The method calls method specifying - the makeCopy parameter. - - - - - Get image from the opened XIMEA camera. - - - Maximum time to wait in milliseconds till image becomes available. - Make a copy of the camera's image or not. - - Returns image retrieved from the camera. - - If the is set to , then the method - creates a managed copy of the camera's image, so the managed image stays valid even when the camera - is closed. However, setting this parameter to creates a managed image which is - just a wrapper around camera's unmanaged image. So if camera is closed and its resources are freed, the - managed image becomes no longer valid and accessing it will generate an exception. - - An error occurred while communicating with a camera. See error - message for additional information. - No camera was opened, so can not access its methods. - Time out value reached - no image is available within specified time value. - - - - - Get number of XIMEA camera connected to the system. - - - - - Specifies if camera's data acquisition is currently active for the opened camera (if any). - - - - - Specifies if a camera is currently opened by the instance of the class. - - - - - ID of the the recently opened XIMEA camera. - - - - - Enumeration of camera's trigger modes. - - - - - Camera works in free run mode. - - - - - External trigger (rising edge). - - - - - External trigger (falling edge). - - - - - Software (manual) trigger. - - - - - The class provides continues access to XIMEA cameras. - - - The video source class is aimed to provide continues access to XIMEA camera, when - images are continuosly acquired from camera and provided throw the event. - It just creates a background thread and gets new images from XIMEA camera - keeping the specified time interval between image acquisition. - Essentially it is a wrapper class around providing interface. - - Sample usage: - - // create video source for the XIMEA camera with ID 0 - XimeaVideoSource videoSource = new XimeaVideoSource( 0 ); - // set event handlers - videoSource.NewFrame += new NewFrameEventHandler( video_NewFrame ); - // start the video source - videoSource.Start( ); - - // set exposure time to 10 milliseconds - videoSource.SetParam( CameraParameter.Exposure, 10 * 1000 ); - - // ... - - // New frame event handler, which is invoked on each new available video frame - private void video_NewFrame( object sender, NewFrameEventArgs eventArgs ) - { - // get new frame - Bitmap bitmap = eventArgs.Frame; - // process the frame - } - - - - - - - - - Initializes a new instance of the class. - - - XIMEA camera ID (index) to connect to. - - - - - Start video source. - - - Starts video source and returns execution to caller. Video camera will be started - and will provide new video frames through the event. - - There is no XIMEA camera with specified ID connected to the system. - An error occurred while communicating with a camera. See error - message for additional information. - - - - - Signal video source to stop its work. - - - - - - - - Wait for video source has stopped. - - - - - - - - Stop video source. - - - The method stops the video source, so it no longer provides new video frames - and does not consume any resources. - - - - - - Set camera's parameter. - - - Parameter name. - Integer parameter value. - - The call is redirected to . - - - - - Set camera's parameter. - - - Parameter name. - Float parameter value. - - The call is redirected to . - - - - - Get camera's parameter as integer value. - - - Parameter name to get from camera. - - Returns integer value of the requested parameter. - - The call is redirected to . - - - - - Get camera's parameter as float value. - - - Parameter name to get from camera. - - Returns float value of the requested parameter. - - The call is redirected to . - - - - - Get camera's parameter as string value. - - - Parameter name to get from camera. - - Returns string value of the requested parameter. - - The call is redirected to . - - - - - New frame event. - - - Notifies clients about new available frames from the video source. - - Since video source may have multiple clients, each client is responsible for - making a copy (cloning) of the passed video frame, because the video source disposes its - own original copy after notifying of clients. - - - - - - Video source error event. - - - This event is used to notify clients about any type of errors occurred in - video source object, for example internal exceptions. - - - - - Video playing finished event. - - - This event is used to notify clients that the video playing has finished. - - - - - - A string identifying the video source. - - - - - - State of the video source. - - - Current state of video source object - running or not. - - - - - Received bytes count. - - - Number of bytes the video source provided from the moment of the last - access to the property. - - - - - - Received frames count. - - - Number of frames the video source provided from the moment of the last - access to the property. - - - - - - Time interval between frames. - - - The property sets the interval in milliseconds between getting new frames from the camera. - If the property is set to 100, then the desired frame rate should be about 10 frames per second. - - Setting this property to 0 leads to no delay between video frames - frames - are read as fast as possible. - - Default value is set to 200. - - - - - diff --git a/Externals/AForge.NET/AForge.Video.dll b/Externals/AForge.NET/AForge.Video.dll deleted file mode 100644 index dc67243ec..0000000000 Binary files a/Externals/AForge.NET/AForge.Video.dll and /dev/null differ diff --git a/Externals/AForge.NET/AForge.Video.xml b/Externals/AForge.NET/AForge.Video.xml deleted file mode 100644 index bde9a524f..0000000000 --- a/Externals/AForge.NET/AForge.Video.xml +++ /dev/null @@ -1,1190 +0,0 @@ - - - - AForge.Video - - - - - Proxy video source for asynchronous processing of another nested video source. - - - The class represents a simple proxy, which wraps the specified - with the aim of asynchronous processing of received video frames. The class intercepts - event from the nested video source and fires it to clients from its own thread, which is different from the thread - used by nested video source for video acquisition. This allows clients to perform processing of video frames - without blocking video acquisition thread, which continue to run and acquire next video frame while current is still - processed. - - For example, let’s suppose that it takes 100 ms for the nested video source to acquire single frame, so the original - frame rate is 10 frames per second. Also let’s assume that we have an image processing routine, which also takes - 100 ms to process a single frame. If the acquisition and processing are done sequentially, then resulting - frame rate will drop to 5 frames per second. However, if doing both in parallel, then there is a good chance to - keep resulting frame rate equal (or close) to the original frame rate. - - The class provides a bonus side effect - easer debugging of image processing routines, which are put into - event handler. In many cases video source classes fire their - event from a try/catch block, which makes it very hard to spot error made in user's code - the catch block simply - hides exception raised in user’s code. The does not have any try/catch blocks around - firing of event, so always user gets exception in the case it comes from his code. At the same time - nested video source is not affected by the user's exception, since it runs in different thread. - - Sample usage: - - // usage of AsyncVideoSource is the same as usage of any - // other video source class, so code change is very little - - // create nested video source, for example JPEGStream - JPEGStream stream = new JPEGStream( "some url" ); - // create async video source - AsyncVideoSource asyncSource = new AsyncVideoSource( stream ); - // set NewFrame event handler - asyncSource.NewFrame += new NewFrameEventHandler( video_NewFrame ); - // start the video source - asyncSource.Start( ); - // ... - - private void video_NewFrame( object sender, NewFrameEventArgs eventArgs ) - { - // get new frame - Bitmap bitmap = eventArgs.Frame; - // process the frame - } - - - - - - - Video source interface. - - - The interface describes common methods for different type of video sources. - - - - - Start video source. - - - Starts video source and return execution to caller. Video source - object creates background thread and notifies about new frames with the - help of event. - - - - - Signal video source to stop its work. - - - Signals video source to stop its background thread, stop to - provide new frames and free resources. - - - - - Wait for video source has stopped. - - - Waits for video source stopping after it was signalled to stop using - method. - - - - - Stop video source. - - - Stops video source aborting its thread. - - - - - New frame event. - - - This event is used to notify clients about new available video frame. - - Since video source may have multiple clients, each client is responsible for - making a copy (cloning) of the passed video frame, but video source is responsible for - disposing its own original copy after notifying of clients. - - - - - - Video source error event. - - - This event is used to notify clients about any type of errors occurred in - video source object, for example internal exceptions. - - - - - Video playing finished event. - - - This event is used to notify clients that the video playing has finished. - - - - - - Video source. - - - The meaning of the property depends on particular video source. - Depending on video source it may be a file name, URL or any other string - describing the video source. - - - - - Received frames count. - - - Number of frames the video source provided from the moment of the last - access to the property. - - - - - - Received bytes count. - - - Number of bytes the video source provided from the moment of the last - access to the property. - - - - - - State of the video source. - - - Current state of video source object - running or not. - - - - - Initializes a new instance of the class. - - - Nested video source which is the target for asynchronous processing. - - - - - Initializes a new instance of the class. - - - Nested video source which is the target for asynchronous processing. - Specifies if the object should skip frames from the nested video source - in the case if it is still busy processing the previous video frame. - - - - - Start video source. - - - Starts the nested video source and returns execution to caller. This object creates - an extra thread which is used to fire events, so the image processing could be - done on another thread without blocking video acquisition thread. - - - - - Signal video source to stop its work. - - - Signals video source to stop its background thread, stop to - provide new frames and free resources. - - - - - Wait for video source has stopped. - - - Waits for video source stopping after it was signalled to stop using - method. - - - - - Stop video source. - - - Stops nested video source by calling its method. - See documentation of the particular video source for additional details. - - - - - New frame event. - - - Notifies clients about new available frame from video source. - - This event is fired from a different thread other than the video acquisition thread created - by . This allows nested video frame to continue acquisition of the next - video frame while clients perform processing of the current video frame. - - Since video source may have multiple clients, each client is responsible for - making a copy (cloning) of the passed video frame, because the video source disposes its - own original copy after notifying of clients. - - - - - - Video source error event. - - - This event is used to notify clients about any type of errors occurred in - video source object, for example internal exceptions. - - Unlike event, this event is simply redirected to the corresponding - event of the , so it is fired from the thread of the nested video source. - - - - - - Video playing finished event. - - - This event is used to notify clients that the video playing has finished. - - Unlike event, this event is simply redirected to the corresponding - event of the , so it is fired from the thread of the nested video source. - - - - - - Nested video source which is the target for asynchronous processing. - - - The property is set through the class constructor. - - All calls to this object are actually redirected to the nested video source. The only - exception is the event, which is handled differently. This object gets - event from the nested class and then fires another - event, but from a different thread. - - - - - - Specifies if the object should skip frames from the nested video source when it is busy. - - - Specifies if the object should skip frames from the nested video source - in the case if it is still busy processing the previous video frame in its own thread. - - Default value is set to . - - - - - Video source string. - - - The property is redirected to the corresponding property of , - so check its documentation to find what it means. - - - - - Received frames count. - - - Number of frames the nested video source received from - the moment of the last access to the property. - - - - - - Received bytes count. - - - Number of bytes the nested video source received from - the moment of the last access to the property. - - - - - Processed frames count. - - - The property keeps the number of processed video frames since the last access to this property. - - - The value of this property equals to in most cases if the - property is set to - every received frame gets processed - sooner or later. However, if the property is set to , - then value of this property may be lower than the value of the property, which - means that nested video source performs acquisition faster than client perform processing of the received frame - and some frame are skipped from processing. - - - - - - State of the video source. - - - Current state of the video source object - running or not. - - - - - Screen capture video source. - - - The video source constantly captures the desktop screen. - - Sample usage: - - // get entire desktop area size - Rectangle screenArea = Rectangle.Empty; - foreach ( System.Windows.Forms.Screen screen in - System.Windows.Forms.Screen.AllScreens ) - { - screenArea = Rectangle.Union( screenArea, screen.Bounds ); - } - - // create screen capture video source - ScreenCaptureStream stream = new ScreenCaptureStream( screenArea ); - - // set NewFrame event handler - stream.NewFrame += new NewFrameEventHandler( video_NewFrame ); - - // start the video source - stream.Start( ); - - // ... - // signal to stop - stream.SignalToStop( ); - // ... - - private void video_NewFrame( object sender, NewFrameEventArgs eventArgs ) - { - // get new frame - Bitmap bitmap = eventArgs.Frame; - // process the frame - } - - - - - - - Initializes a new instance of the class. - - - Screen's rectangle to capture (the rectangle may cover multiple displays). - - - - - Initializes a new instance of the class. - - - Screen's rectangle to capture (the rectangle may cover multiple displays). - Time interval between making screen shots, ms. - - - - - Start video source. - - - Starts video source and return execution to caller. Video source - object creates background thread and notifies about new frames with the - help of event. - - Video source is not specified. - - - - - Signal video source to stop its work. - - - Signals video source to stop its background thread, stop to - provide new frames and free resources. - - - - - Wait for video source has stopped. - - - Waits for source stopping after it was signalled to stop using - method. - - - - - Stop video source. - - - Stops video source aborting its thread. - - Since the method aborts background thread, its usage is highly not preferred - and should be done only if there are no other options. The correct way of stopping camera - is signaling it stop and then - waiting for background thread's completion. - - - - - - Free resource. - - - - - - New frame event. - - - Notifies clients about new available frame from video source. - - Since video source may have multiple clients, each client is responsible for - making a copy (cloning) of the passed video frame, because the video source disposes its - own original copy after notifying of clients. - - - - - - Video source error event. - - - This event is used to notify clients about any type of errors occurred in - video source object, for example internal exceptions. - - - - - Video playing finished event. - - - This event is used to notify clients that the video playing has finished. - - - - - - Video source. - - - - - - Gets or sets the screen capture region. - - - This property specifies which region (rectangle) of the screen to capture. It may cover multiple displays - if those are available in the system. - - The property must be set before starting video source to have any effect. - - - - - - Time interval between making screen shots, ms. - - - The property specifies time interval in milliseconds between consequent screen captures. - Expected frame rate of the stream should be approximately 1000/FrameInteval. - - If the property is set to 0, then the stream will capture screen as fast as the system allows. - - Default value is set to 100. - - - - - - Received frames count. - - - Number of frames the video source provided from the moment of the last - access to the property. - - - - - - Received bytes count. - - - The property is not implemented for this video source and always returns 0. - - - - - - State of the video source. - - - Current state of video source object - running or not. - - - - - MJPEG video source. - - - The video source downloads JPEG images from the specified URL, which represents - MJPEG stream. - - Sample usage: - - // create MJPEG video source - MJPEGStream stream = new MJPEGStream( "some url" ); - // set event handlers - stream.NewFrame += new NewFrameEventHandler( video_NewFrame ); - // start the video source - stream.Start( ); - // ... - - - Some cameras produce HTTP header, which does not conform strictly to - standard, what leads to .NET exception. To avoid this exception the useUnsafeHeaderParsing - configuration option of httpWebRequest should be set, what may be done using application - configuration file. - - <configuration> - <system.net> - <settings> - <httpWebRequest useUnsafeHeaderParsing="true" /> - </settings> - </system.net> - </configuration> - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - URL, which provides MJPEG stream. - - - - - Start video source. - - - Starts video source and return execution to caller. Video source - object creates background thread and notifies about new frames with the - help of event. - - Video source is not specified. - - - - - Signal video source to stop its work. - - - Signals video source to stop its background thread, stop to - provide new frames and free resources. - - - - - Wait for video source has stopped. - - - Waits for source stopping after it was signalled to stop using - method. - - - - - Stop video source. - - - Stops video source aborting its thread. - - Since the method aborts background thread, its usage is highly not preferred - and should be done only if there are no other options. The correct way of stopping camera - is signaling it stop and then - waiting for background thread's completion. - - - - - - Free resource. - - - - - - New frame event. - - - Notifies clients about new available frame from video source. - - Since video source may have multiple clients, each client is responsible for - making a copy (cloning) of the passed video frame, because the video source disposes its - own original copy after notifying of clients. - - - - - - Video source error event. - - - This event is used to notify clients about any type of errors occurred in - video source object, for example internal exceptions. - - - - - Video playing finished event. - - - This event is used to notify clients that the video playing has finished. - - - - - - Use or not separate connection group. - - - The property indicates to open web request in separate connection group. - - - - - Video source. - - - URL, which provides MJPEG stream. - - - - - Login value. - - - Login required to access video source. - - - - - Password value. - - - Password required to access video source. - - - - - Gets or sets proxy information for the request. - - - The local computer or application config file may specify that a default - proxy to be used. If the Proxy property is specified, then the proxy settings from the Proxy - property overridea the local computer or application config file and the instance will use - the proxy settings specified. If no proxy is specified in a config file - and the Proxy property is unspecified, the request uses the proxy settings - inherited from Internet Explorer on the local computer. If there are no proxy settings - in Internet Explorer, the request is sent directly to the server. - - - - - - User agent to specify in HTTP request header. - - - Some IP cameras check what is the requesting user agent and depending - on it they provide video in different formats or do not provide it at all. The property - sets the value of user agent string, which is sent to camera in request header. - - - Default value is set to "Mozilla/5.0". If the value is set to , - the user agent string is not sent in request header. - - - - - - Received frames count. - - - Number of frames the video source provided from the moment of the last - access to the property. - - - - - - Received bytes count. - - - Number of bytes the video source provided from the moment of the last - access to the property. - - - - - - Request timeout value. - - - The property sets timeout value in milliseconds for web requests. - Default value is 10000 milliseconds. - - - - - State of the video source. - - - Current state of video source object - running or not. - - - - - Force using of basic authentication when connecting to the video source. - - - For some IP cameras (TrendNET IP cameras, for example) using standard .NET's authentication via credentials - does not seem to be working (seems like camera does not request for authentication, but expects corresponding headers to be - present on connection request). So this property allows to force basic authentication by adding required HTTP headers when - request is sent. - - Default value is set to . - - - - - - Video related exception. - - - The exception is thrown in the case of some video related issues, like - failure of initializing codec, compression, etc. - - - - - Initializes a new instance of the class. - - - Exception's message. - - - - - Delegate for new frame event handler. - - - Sender object. - Event arguments. - - - - - Delegate for video source error event handler. - - - Sender object. - Event arguments. - - - - - Delegate for playing finished event handler. - - - Sender object. - Reason of finishing video playing. - - - - - Reason of finishing video playing. - - - When video source class fire the event, they - need to specify reason of finishing video playing. For example, it may be end of stream reached. - - - - - Video playing has finished because it end was reached. - - - - - Video playing has finished because it was stopped by user. - - - - - Video playing has finished because the device was lost (unplugged). - - - - - Video playing has finished because of some error happened the video source (camera, stream, file, etc.). - A error reporting event usually is fired to provide error information. - - - - - Arguments for new frame event from video source. - - - - - - Initializes a new instance of the class. - - - New frame. - - - - - New frame from video source. - - - - - - Arguments for video source error event from video source. - - - - - - Initializes a new instance of the class. - - - Error description. - - - - - Video source error description. - - - - - - JPEG video source. - - - The video source constantly downloads JPEG files from the specified URL. - - Sample usage: - - // create JPEG video source - JPEGStream stream = new JPEGStream( "some url" ); - // set NewFrame event handler - stream.NewFrame += new NewFrameEventHandler( video_NewFrame ); - // start the video source - stream.Start( ); - // ... - // signal to stop - stream.SignalToStop( ); - // ... - - private void video_NewFrame( object sender, NewFrameEventArgs eventArgs ) - { - // get new frame - Bitmap bitmap = eventArgs.Frame; - // process the frame - } - - - Some cameras produce HTTP header, which does not conform strictly to - standard, what leads to .NET exception. To avoid this exception the useUnsafeHeaderParsing - configuration option of httpWebRequest should be set, what may be done using application - configuration file. - - <configuration> - <system.net> - <settings> - <httpWebRequest useUnsafeHeaderParsing="true" /> - </settings> - </system.net> - </configuration> - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - URL, which provides JPEG files. - - - - - Start video source. - - - Starts video source and return execution to caller. Video source - object creates background thread and notifies about new frames with the - help of event. - - Video source is not specified. - - - - - Signal video source to stop its work. - - - Signals video source to stop its background thread, stop to - provide new frames and free resources. - - - - - Wait for video source has stopped. - - - Waits for source stopping after it was signalled to stop using - method. - - - - - Stop video source. - - - Stops video source aborting its thread. - - Since the method aborts background thread, its usage is highly not preferred - and should be done only if there are no other options. The correct way of stopping camera - is signaling it stop and then - waiting for background thread's completion. - - - - - - Free resource. - - - - - - New frame event. - - - Notifies clients about new available frame from video source. - - Since video source may have multiple clients, each client is responsible for - making a copy (cloning) of the passed video frame, because the video source disposes its - own original copy after notifying of clients. - - - - - - Video source error event. - - - This event is used to notify clients about any type of errors occurred in - video source object, for example internal exceptions. - - - - - Video playing finished event. - - - This event is used to notify clients that the video playing has finished. - - - - - - Use or not separate connection group. - - - The property indicates to open web request in separate connection group. - - - - - Use or not caching. - - - If the property is set to true, then a fake random parameter will be added - to URL to prevent caching. It's required for clients, who are behind proxy server. - - - - - Frame interval. - - - The property sets the interval in milliseconds betwen frames. If the property is - set to 100, then the desired frame rate will be 10 frames per second. Default value is 0 - - get new frames as fast as possible. - - - - - Video source. - - - URL, which provides JPEG files. - - - - - Login value. - - - Login required to access video source. - - - - - Password value. - - - Password required to access video source. - - - - - Gets or sets proxy information for the request. - - - The local computer or application config file may specify that a default - proxy to be used. If the Proxy property is specified, then the proxy settings from the Proxy - property overridea the local computer or application config file and the instance will use - the proxy settings specified. If no proxy is specified in a config file - and the Proxy property is unspecified, the request uses the proxy settings - inherited from Internet Explorer on the local computer. If there are no proxy settings - in Internet Explorer, the request is sent directly to the server. - - - - - - Received frames count. - - - Number of frames the video source provided from the moment of the last - access to the property. - - - - - - Received bytes count. - - - Number of bytes the video source provided from the moment of the last - access to the property. - - - - - - Request timeout value. - - - The property sets timeout value in milliseconds for web requests. - - Default value is set 10000 milliseconds. - - - - - State of the video source. - - - Current state of video source object - running or not. - - - - - Force using of basic authentication when connecting to the video source. - - - For some IP cameras (TrendNET IP cameras, for example) using standard .NET's authentication via credentials - does not seem to be working (seems like camera does not request for authentication, but expects corresponding headers to be - present on connection request). So this property allows to force basic authentication by adding required HTTP headers when - request is sent. - - Default value is set to . - - - - - - Some internal utilities for handling arrays. - - - - - - Check if the array contains needle at specified position. - - - Source array to check for needle. - Needle we are searching for. - Start index in source array. - - Returns true if the source array contains the needle at - the specified index. Otherwise it returns false. - - - - - Find subarray in the source array. - - - Source array to search for needle. - Needle we are searching for. - Start index in source array. - Number of bytes in source array, where the needle is searched for. - - Returns starting position of the needle if it was found or -1 otherwise. - - - - diff --git a/Externals/AForge.NET/AForge.Vision.dll b/Externals/AForge.NET/AForge.Vision.dll deleted file mode 100644 index 089541803..0000000000 Binary files a/Externals/AForge.NET/AForge.Vision.dll and /dev/null differ diff --git a/Externals/AForge.NET/AForge.Vision.xml b/Externals/AForge.NET/AForge.Vision.xml deleted file mode 100644 index 51a5067aa..0000000000 --- a/Externals/AForge.NET/AForge.Vision.xml +++ /dev/null @@ -1,1370 +0,0 @@ - - - - AForge.Vision - - - - - Motion processing algorithm, which highlights motion areas. - - - The aim of this motion processing algorithm is to highlight - motion areas with grid pattern of the specified color. - - - Sample usage: - - // create motion detector - MotionDetector detector = new MotionDetector( - /* motion detection algorithm */, - new MotionAreaHighlighting( ) ); - - // continuously feed video frames to motion detector - while ( ... ) - { - // process new video frame - detector.ProcessFrame( videoFrame ); - } - - - - - - - - - - Interface of motion processing algorithm. - - - The interface specifies methods, which should be implemented - by all motion processng algorithms - algorithm which perform further post processing - of detected motion, which is done by motion detection algorithms (see ). - - - - - - - - - Process video and motion frames doing further post processing after - performed motion detection. - - - Original video frame. - Motion frame provided by motion detection - algorithm (see ). - - The method does father post processing of detected motion. - Type of motion post processing is specified by specific implementation - of the interface - it may motion - area highlighting, motion objects counting, etc. - - - - - Reset internal state of motion processing algorithm. - - - The method allows to reset internal state of motion processing - algorithm and prepare it for processing of next video stream or to restart - the algorithm. - - Some motion processing algorithms may not have any stored internal - states and may just process provided video frames without relying on any motion - history etc. In this case such algorithms provide empty implementation of this method. - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Color used to highlight motion regions. - - - - - Process video and motion frames doing further post processing after - performed motion detection. - - - Original video frame. - Motion frame provided by motion detection - algorithm (see ). - - Processes provided motion frame and highlights motion areas - on the original video frame with specified color. - - - Motion frame is not 8 bpp image, but it must be so. - Video frame must be 8 bpp grayscale image or 24/32 bpp color image. - - - - - Reset internal state of motion processing algorithm. - - - The method allows to reset internal state of motion processing - algorithm and prepare it for processing of next video stream or to restart - the algorithm. - - - - - Color used to highlight motion regions. - - - - Default value is set to red color. - - - - - - Interface of motion detector algorithm. - - - The interface specifies methods, which should be implemented - by all motion detection algorithms - algorithms which perform processing of video - frames in order to detect motion. Amount of detected motion may be checked using - property. Also property may - be used in order to see all the detected motion areas. For example, the property - is used by motion processing algorithms for further motion post processing, like - highlighting motion areas, counting number of detected moving object, etc. - - - - - - - - - - Process new video frame. - - - Video frame to process (detect motion in). - - Processes new frame from video source and detects motion in it. - - - - - Reset motion detector to initial state. - - - Resets internal state and variables of motion detection algorithm. - Usually this is required to be done before processing new video source, but - may be also done at any time to restart motion detection algorithm. - - - - - - Motion level value, [0, 1]. - - - Amount of changes in the last processed frame. For example, if value of - this property equals to 0.1, then it means that last processed frame has 10% of changes - (however it is up to specific implementation to decide how to compare specified frame). - - - - - - Motion frame containing detected areas of motion. - - - Motion frame is a grayscale image, which shows areas of detected motion. - All black pixels in the motion frame correspond to areas, where no motion is - detected. But white pixels correspond to areas, where motion is detected. - - - - - Motion processing algorithm, which counts separate moving objects and highlights them. - - - The aim of this motion processing algorithm is to count separate objects - in the motion frame, which is provided by motion detection algorithm. - In the case if property is set to , - found objects are also highlighted on the original video frame. The algorithm - counts and highlights only those objects, which size satisfies - and properties. - - The motion processing algorithm is supposed to be used only with motion detection - algorithms, which are based on finding difference with background frame - (see and - as simple implementations) and allow extract moving objects clearly. - - Sample usage: - - // create instance of motion detection algorithm - IMotionDetector motionDetector = new ... ; - // create instance of motion processing algorithm - BlobCountingObjectsProcessing motionProcessing = new BlobCountingObjectsProcessing( ); - // create motion detector - MotionDetector detector = new MotionDetector( motionDetector, motionProcessing ); - - // continuously feed video frames to motion detector - while ( ... ) - { - // process new video frame and check motion level - if ( detector.ProcessFrame( videoFrame ) > 0.02 ) - { - // check number of detected objects - if ( motionProcessing.ObjectsCount > 1 ) - { - // ... - } - } - } - - - - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Highlight motion regions or not (see property). - - - - - Initializes a new instance of the class. - - - Minimum width of acceptable object (see property). - Minimum height of acceptable object (see property). - - - - - Initializes a new instance of the class. - - - Minimum width of acceptable object (see property). - Minimum height of acceptable object (see property). - Color used to highlight motion regions. - - - - - Initializes a new instance of the class. - - - Minimum width of acceptable object (see property). - Minimum height of acceptable object (see property). - Highlight motion regions or not (see property). - - - - - Process video and motion frames doing further post processing after - performed motion detection. - - - Original video frame. - Motion frame provided by motion detection - algorithm (see ). - - Processes provided motion frame and counts number of separate - objects, which size satisfies and - properties. In the case if property is - set to , the found object are also highlighted on the - original video frame. - - - Motion frame is not 8 bpp image, but it must be so. - Video frame must be 8 bpp grayscale image or 24/32 bpp color image. - - - - - Reset internal state of motion processing algorithm. - - - The method allows to reset internal state of motion processing - algorithm and prepare it for processing of next video stream or to restart - the algorithm. - - - - - Highlight motion regions or not. - - - The property specifies if detected moving objects should be highlighted - with rectangle or not. - - Default value is set to . - - Turning the value on leads to additional processing time of video frame. - - - - - - Color used to highlight motion regions. - - - - Default value is set to red color. - - - - - - Minimum width of acceptable object. - - - The property sets minimum width of an object to count and highlight. If - objects have smaller width, they are not counted and are not highlighted. - - Default value is set to 10. - - - - - - Minimum height of acceptable object. - - - The property sets minimum height of an object to count and highlight. If - objects have smaller height, they are not counted and are not highlighted. - - Default value is set to 10. - - - - - - Number of detected objects. - - - The property provides number of moving objects detected by - the last call of method. - - - - - Rectangles of moving objects. - - - The property provides array of moving objects' rectangles - detected by the last call of method. - - - - - Motion processing algorithm, which performs grid processing of motion frame. - - - The aim of this motion processing algorithm is to do grid processing - of motion frame. This means that entire motion frame is divided by a grid into - certain amount of cells and the motion level is calculated for each cell. The - information about each cell's motion level may be retrieved using - property. - - In addition the algorithm can highlight those cells, which have motion - level above the specified threshold (see - property). To enable this it is required to set - property to . - - Sample usage: - - // create instance of motion detection algorithm - IMotionDetector motionDetector = new ... ; - // create instance of motion processing algorithm - GridMotionAreaProcessing motionProcessing = new GridMotionAreaProcessing( 16, 16 ); - // create motion detector - MotionDetector detector = new MotionDetector( motionDetector, motionProcessing ); - - // continuously feed video frames to motion detector - while ( ... ) - { - // process new video frame - detector.ProcessFrame( videoFrame ); - - // check motion level in 5th row 8th column - if ( motionProcessing.MotionGrid[5, 8] > 0.15 ) - { - // ... - } - } - - - - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Width of motion grid (see property). - Height of motion grid (see property). - - - - - Initializes a new instance of the class. - - - Width of motion grid (see property). - Height of motion grid (see property). - Highlight motion regions or not (see property). - - - - - Initializes a new instance of the class. - - - Width of motion grid (see property). - Height of motion grid (see property). - Highlight motion regions or not (see property). - Motion amount to highlight cell (see property). - - - - - Process video and motion frames doing further post processing after - performed motion detection. - - - Original video frame. - Motion frame provided by motion detection - algorithm (see ). - - Processes provided motion frame and calculates motion level - for each grid's cell. In the case if property is - set to , the cell with motion level above threshold are - highlighted. - - Motion frame is not 8 bpp image, but it must be so. - Video frame must be 8 bpp grayscale image or 24/32 bpp color image. - - - - - Reset internal state of motion processing algorithm. - - - The method allows to reset internal state of motion processing - algorithm and prepare it for processing of next video stream or to restart - the algorithm. - - - - - Color used to highlight motion regions. - - - - Default value is set to red color. - - - - - - Highlight motion regions or not. - - - The property specifies if motion grid should be highlighted - - if cell, which have motion level above the - specified value, should be highlighted. - - Default value is set to . - - Turning the value on leads to additional processing time of video frame. - - - - - - Motion amount to highlight cell. - - - The property specifies motion level threshold for highlighting grid's - cells. If motion level of a certain cell is higher than this value, then the cell - is highlighted. - - Default value is set to 0.15. - - - - - - Motion levels of each grid's cell. - - - The property represents an array of size - x, which keeps motion level - of each grid's cell. If certain cell has motion level equal to 0.2, then it - means that this cell has 20% of changes. - - - - - - Width of motion grid, [2, 64]. - - - The property specifies motion grid's width - number of grid' columns. - - Default value is set to 16. - - - - - - Height of motion grid, [2, 64]. - - - The property specifies motion grid's height - number of grid' rows. - - Default value is set to 16. - - - - - - Motion detection wrapper class, which performs motion detection and processing. - - - The class serves as a wrapper class for - motion detection and - motion processing algorithms, allowing to call them with - single call. Unlike motion detection and motion processing interfaces, the class also - provides additional methods for convenience, so the algorithms could be applied not - only to , but to .NET's class - as well. - - In addition to wrapping of motion detection and processing algorthms, the class provides - some additional functionality. Using property it is possible to specify - set of rectangular zones to observe - only motion in these zones is counted and post procesed. - - Sample usage: - - // create motion detector - MotionDetector detector = new MotionDetector( - new SimpleBackgroundModelingDetector( ), - new MotionAreaHighlighting( ) ); - - // continuously feed video frames to motion detector - while ( ... ) - { - // process new video frame and check motion level - if ( detector.ProcessFrame( videoFrame ) > 0.02 ) - { - // ring alarm or do somethng else - } - } - - - - - - - Initializes a new instance of the class. - - - Motion detection algorithm to apply to each video frame. - - - - - Initializes a new instance of the class. - - - Motion detection algorithm to apply to each video frame. - Motion processing algorithm to apply to each video frame after - motion detection is done. - - - - - Process new video frame. - - - Video frame to process (detect motion in). - - Returns amount of motion, which is provided - property of the motion detection algorithm in use. - - See for additional details. - - - - - - Process new video frame. - - - Video frame to process (detect motion in). - - Returns amount of motion, which is provided - property of the motion detection algorithm in use. - - See for additional details. - - - - - - Process new video frame. - - - Video frame to process (detect motion in). - - Returns amount of motion, which is provided - property of the motion detection algorithm in use. - - The method first of all applies motion detection algorithm to the specified video - frame to calculate motion level and - motion frame. After this it applies motion processing algorithm - (if it was set) to do further post processing, like highlighting motion areas, counting moving - objects, etc. - - In the case if property is set, this method will perform - motion filtering right after motion algorithm is done and before passing motion frame to motion - processing algorithm. The method does filtering right on the motion frame, which is produced - by motion detection algorithm. At the same time the method recalculates motion level and returns - new value, which takes motion zones into account (but the new value is not set back to motion detection - algorithm' property). - - - - - - - Reset motion detector to initial state. - - - The method resets motion detection and motion processing algotithms by calling - their and methods. - - - - - - Motion detection algorithm to apply to each video frame. - - - The property sets motion detection algorithm, which is used by - method in order to calculate - motion level and - motion frame. - - - - - - Motion processing algorithm to apply to each video frame after - motion detection is done. - - - The property sets motion processing algorithm, which is used by - method after motion detection in order to do further - post processing of motion frames. The aim of further post processing depends on - actual implementation of the specified motion processing algorithm - it can be - highlighting of motion area, objects counting, etc. - - - - - - Set of zones to detect motion in. - - - The property keeps array of rectangular zones, which are observed for motion detection. - Motion outside of these zones is ignored. - - In the case if this property is set, the method - will filter out all motion witch was detected by motion detection algorithm, but is not - located in the specified zones. - - - - - - Motion detector based on two continues frames difference. - - - The class implements the simplest motion detection algorithm, which is - based on difference of two continues frames. The difference frame - is thresholded and the amount of difference pixels is calculated. - To suppress stand-alone noisy pixels erosion morphological operator may be applied, which - is controlled by property. - - Although the class may be used on its own to perform motion detection, it is preferred - to use it in conjunction with class, which provides additional - features and allows to use moton post processing algorithms. - - Sample usage: - - // create motion detector - MotionDetector detector = new MotionDetector( - new TwoFramesDifferenceDetector( ), - new MotionAreaHighlighting( ) ); - - // continuously feed video frames to motion detector - while ( ... ) - { - // process new video frame and check motion level - if ( detector.ProcessFrame( videoFrame ) > 0.02 ) - { - // ring alarm or do somethng else - } - } - - - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Suppress noise in video frames or not (see property). - - - - - Process new video frame. - - - Video frame to process (detect motion in). - - Processes new frame from video source and detects motion in it. - - Check property to get information about amount of motion - (changes) in the processed frame. - - - - - - Reset motion detector to initial state. - - - Resets internal state and variables of motion detection algorithm. - Usually this is required to be done before processing new video source, but - may be also done at any time to restart motion detection algorithm. - - - - - - Difference threshold value, [1, 255]. - - - The value specifies the amount off difference between pixels, which is treated - as motion pixel. - - Default value is set to 15. - - - - - - Motion level value, [0, 1]. - - - Amount of changes in the last processed frame. For example, if value of - this property equals to 0.1, then it means that last processed frame has 10% difference - with previous frame. - - - - - - Motion frame containing detected areas of motion. - - - Motion frame is a grayscale image, which shows areas of detected motion. - All black pixels in the motion frame correspond to areas, where no motion is - detected. But white pixels correspond to areas, where motion is detected. - - The property is set to after processing of the first - video frame by the algorithm. - - - - - - Suppress noise in video frames or not. - - - The value specifies if additional filtering should be - done to suppress standalone noisy pixels by applying 3x3 erosion image processing - filter. - - Default value is set to . - - Turning the value on leads to more processing time of video frame. - - - - - - Motion processing algorithm, which highlights border of motion areas. - - - The aim of this motion processing algorithm is to highlight - borders of motion areas with the specified color. - - - The motion processing algorithm is supposed to be used only with motion detection - algorithms, which are based on finding difference with background frame - (see and - as simple implementations) and allow extract moving objects clearly. - - Sample usage: - - // create motion detector - MotionDetector detector = new MotionDetector( - /* motion detection algorithm */, - new MotionBorderHighlighting( ) ); - - // continuously feed video frames to motion detector - while ( ... ) - { - // process new video frame - detector.ProcessFrame( videoFrame ); - } - - - - - - - - - - Initializes a new instance of the class. - - - - - - Initializes a new instance of the class. - - - Color used to highlight motion regions. - - - - - Process video and motion frames doing further post processing after - performed motion detection. - - - Original video frame. - Motion frame provided by motion detection - algorithm (see ). - - Processes provided motion frame and highlights borders of motion areas - on the original video frame with specified color. - - - Motion frame is not 8 bpp image, but it must be so. - Video frame must be 8 bpp grayscale image or 24/32 bpp color image. - - - - - Reset internal state of motion processing algorithm. - - - The method allows to reset internal state of motion processing - algorithm and prepare it for processing of next video stream or to restart - the algorithm. - - - - - Color used to highlight motion regions. - - - - Default value is set to red color. - - - - - - Motion detector based on difference with predefined background frame. - - - The class implements motion detection algorithm, which is based on - difference of current video frame with predefined background frame. The difference frame - is thresholded and the amount of difference pixels is calculated. - To suppress stand-alone noisy pixels erosion morphological operator may be applied, which - is controlled by property. - - In the case if precise motion area's borders are required (for example, - for further motion post processing), then property - may be used to restore borders after noise suppression. - - In the case if custom background frame is not specified by using - method, the algorithm takes first video frame - as a background frame and calculates difference of further video frames with it. - - Unlike motion detection algorithm, this algorithm - allows to identify quite clearly all objects, which are not part of the background (scene) - - most likely moving objects. - - Sample usage: - - // create motion detector - MotionDetector detector = new MotionDetector( - new CustomFrameDifferenceDetector( ), - new MotionAreaHighlighting( ) ); - - // continuously feed video frames to motion detector - while ( ... ) - { - // process new video frame and check motion level - if ( detector.ProcessFrame( videoFrame ) > 0.02 ) - { - // ring alarm or do somethng else - } - } - - - - - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Suppress noise in video frames or not (see property). - - - - - Initializes a new instance of the class. - - - Suppress noise in video frames or not (see property). - Restore objects edges after noise suppression or not (see property). - - - - - Process new video frame. - - - Video frame to process (detect motion in). - - Processes new frame from video source and detects motion in it. - - Check property to get information about amount of motion - (changes) in the processed frame. - - - - - - Reset motion detector to initial state. - - - Resets internal state and variables of motion detection algorithm. - Usually this is required to be done before processing new video source, but - may be also done at any time to restart motion detection algorithm. - - In the case if custom background frame was set using - method, this method does not reset it. - The method resets only automatically generated background frame. - - - - - - - Set background frame. - - - Background frame to set. - - The method sets background frame, which will be used to calculate - difference with. - - - - - Set background frame. - - - Background frame to set. - - The method sets background frame, which will be used to calculate - difference with. - - - - - Set background frame. - - - Background frame to set. - - The method sets background frame, which will be used to calculate - difference with. - - - - - Difference threshold value, [1, 255]. - - - The value specifies the amount off difference between pixels, which is treated - as motion pixel. - - Default value is set to 15. - - - - - - Motion level value, [0, 1]. - - - Amount of changes in the last processed frame. For example, if value of - this property equals to 0.1, then it means that last processed frame has 10% difference - with defined background frame. - - - - - - Motion frame containing detected areas of motion. - - - Motion frame is a grayscale image, which shows areas of detected motion. - All black pixels in the motion frame correspond to areas, where no motion is - detected. But white pixels correspond to areas, where motion is detected. - - The property is set to after processing of the first - video frame by the algorithm in the case if custom background frame was not set manually - by using method (it will be not - after second call in this case). If correct custom background - was set then the property should bet set to estimated motion frame after - method call. - - - - - - Suppress noise in video frames or not. - - - The value specifies if additional filtering should be - done to suppress standalone noisy pixels by applying 3x3 erosion image processing - filter. See property, if it is required to restore - edges of objects, which are not noise. - - Default value is set to . - - Turning the value on leads to more processing time of video frame. - - - - - - Restore objects edges after noise suppression or not. - - - The value specifies if additional filtering should be done - to restore objects' edges after noise suppression by applying 3x3 dilatation - image processing filter. - - Default value is set to . - - Turning the value on leads to more processing time of video frame. - - - - - - Motion detector based on simple background modeling. - - - The class implements motion detection algorithm, which is based on - difference of current video frame with modeled background frame. - The difference frame is thresholded and the - amount of difference pixels is calculated. - To suppress stand-alone noisy pixels erosion morphological operator may be applied, which - is controlled by property. - - In the case if precise motion area's borders are required (for example, - for further motion post processing), then property - may be used to restore borders after noise suppression. - - As the first approximation of background frame, the first frame of video stream is taken. - During further video processing the background frame is constantly updated, so it - changes in the direction to decrease difference with current video frame (the background - frame is moved towards current frame). See - properties, which control the rate of - background frame update. - - Unlike motion detection algorithm, this algorithm - allows to identify quite clearly all objects, which are not part of the background (scene) - - most likely moving objects. And unlike motion - detection algorithm, this algorithm includes background adaptation feature, which allows it - to update its modeled background frame in order to take scene changes into account. - - Because of the adaptation feature of the algorithm, it may adopt - to background changes, what algorithm can not do. - However, if moving object stays on the scene for a while (so algorithm adopts to it and does - not treat it as a new moving object any more) and then starts to move again, the algorithm may - find two moving objects - the true one, which is really moving, and the false one, which does not (the - place, where the object stayed for a while). - - The algorithm is not applicable to such cases, when moving object resides - in camera's view most of the time (laptops camera monitoring a person sitting in front of it, - for example). The algorithm is mostly supposed for cases, when camera monitors some sort - of static scene, where moving objects appear from time to time - street, road, corridor, etc. - - - Sample usage: - - // create motion detector - MotionDetector detector = new MotionDetector( - new SimpleBackgroundModelingDetector( ), - new MotionAreaHighlighting( ) ); - - // continuously feed video frames to motion detector - while ( ... ) - { - // process new video frame and check motion level - if ( detector.ProcessFrame( videoFrame ) > 0.02 ) - { - // ring alarm or do somethng else - } - } - - - - - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - Suppress noise in video frames or not (see property). - - - - - Initializes a new instance of the class. - - - Suppress noise in video frames or not (see property). - Restore objects edges after noise suppression or not (see property). - - - - - Process new video frame. - - - Video frame to process (detect motion in). - - Processes new frame from video source and detects motion in it. - - Check property to get information about amount of motion - (changes) in the processed frame. - - - - - - Reset motion detector to initial state. - - - Resets internal state and variables of motion detection algorithm. - Usually this is required to be done before processing new video source, but - may be also done at any time to restart motion detection algorithm. - - - - - - Difference threshold value, [1, 255]. - - - The value specifies the amount off difference between pixels, which is treated - as motion pixel. - - Default value is set to 15. - - - - - - Motion level value, [0, 1]. - - - Amount of changes in the last processed frame. For example, if value of - this property equals to 0.1, then it means that last processed frame has 10% difference - with modeled background frame. - - - - - - Motion frame containing detected areas of motion. - - - Motion frame is a grayscale image, which shows areas of detected motion. - All black pixels in the motion frame correspond to areas, where no motion is - detected. But white pixels correspond to areas, where motion is detected. - - The property is set to after processing of the first - video frame by the algorithm. - - - - - - Suppress noise in video frames or not. - - - The value specifies if additional filtering should be - done to suppress standalone noisy pixels by applying 3x3 erosion image processing - filter. See property, if it is required to restore - edges of objects, which are not noise. - - Default value is set to . - - Turning the value on leads to more processing time of video frame. - - - - - - Restore objects edges after noise suppression or not. - - - The value specifies if additional filtering should be done - to restore objects' edges after noise suppression by applying 3x3 dilatation - image processing filter. - - Default value is set to . - - Turning the value on leads to more processing time of video frame. - - - - - - Frames per background update, [1, 50]. - - - The value controls the speed of modeled background adaptation to - scene changes. After each specified amount of frames the background frame is updated - in the direction to decrease difference with current processing frame. - - Default value is set to 2. - - The property has effect only in the case if - property is set to 0. Otherwise it does not have effect and background - update is managed according to the - property settings. - - - - - - Milliseconds per background update, [0, 5000]. - - - The value represents alternate way of controlling the speed of modeled - background adaptation to scene changes. The value sets number of milliseconds, which - should elapse between two consequent video frames to result in background update - for one intensity level. For example, if this value is set to 100 milliseconds and - the amount of time elapsed between two last video frames equals to 350, then background - frame will be update for 3 intensity levels in the direction to decrease difference - with current video frame (the remained 50 milliseconds will be added to time difference - between two next consequent frames, so the accuracy is preserved). - - Unlike background update method controlled using - method, the method guided by this property is not affected by changes - in frame rates. If, for some reasons, a video source starts to provide delays between - frames (frame rate drops down), the amount of background update still stays consistent. - When background update is controlled by this property, it is always possible to estimate - amount of time required to change, for example, absolutely black background (0 intensity - values) into absolutely white background (255 intensity values). If value of this - property is set to 100, then it will take approximately 25.5 seconds for such update - regardless of frame rate. - - Background update controlled by this property is slightly slower then - background update controlled by property, - so it has a bit greater impact on performance. - - If this property is set to 0, then corresponding background updating - method is not used (turned off), but background update guided by - property is used. - - Default value is set to 0. - - - - - diff --git a/Externals/AForge.NET/AForge.dll b/Externals/AForge.NET/AForge.dll deleted file mode 100644 index 311cfe5a9..0000000000 Binary files a/Externals/AForge.NET/AForge.dll and /dev/null differ diff --git a/Externals/AForge.NET/AForge.xml b/Externals/AForge.NET/AForge.xml deleted file mode 100644 index 441384713..0000000000 --- a/Externals/AForge.NET/AForge.xml +++ /dev/null @@ -1,1795 +0,0 @@ - - - - AForge - - - - - Event arguments holding a buffer sent or received during some communication process. - - - - - Initializes a new instance of the class. - - - Message being transfered during communication process. - - - - - Initializes a new instance of the class. - - - Buffer containing the message being transferred during communication process. - Starting index of the message within the buffer. - Length of the message within the buffer. - - - - - Get the transfered message. - - - Returns copy of the transfered message. - - - - - Get the transferred message as string. - - - Returns string encoding the transferred message. - - - - - Length of the transfered message. - - - - - Structure for representing a pair of coordinates of integer type. - - - The structure is used to store a pair of integer coordinates. - - Sample usage: - - // assigning coordinates in the constructor - IntPoint p1 = new IntPoint( 10, 20 ); - // creating a point and assigning coordinates later - IntPoint p2; - p2.X = 30; - p2.Y = 40; - // calculating distance between two points - float distance = p1.DistanceTo( p2 ); - - - - - - - X coordinate. - - - - - - Y coordinate. - - - - - - Initializes a new instance of the structure. - - - X axis coordinate. - Y axis coordinate. - - - - - Calculate Euclidean distance between two points. - - - Point to calculate distance to. - - Returns Euclidean distance between this point and - points. - - - - - Calculate squared Euclidean distance between two points. - - - Point to calculate distance to. - - Returns squared Euclidean distance between this point and - points. - - - - - Addition operator - adds values of two points. - - - First point for addition. - Second point for addition. - - Returns new point which coordinates equal to sum of corresponding - coordinates of specified points. - - - - - Addition operator - adds values of two points. - - - First point for addition. - Second point for addition. - - Returns new point which coordinates equal to sum of corresponding - coordinates of specified points. - - - - - Subtraction operator - subtracts values of two points. - - - Point to subtract from. - Point to subtract. - - Returns new point which coordinates equal to difference of corresponding - coordinates of specified points. - - - - - Subtraction operator - subtracts values of two points. - - - Point to subtract from. - Point to subtract. - - Returns new point which coordinates equal to difference of corresponding - coordinates of specified points. - - - - - Addition operator - adds scalar to the specified point. - - - Point to increase coordinates of. - Value to add to coordinates of the specified point. - - Returns new point which coordinates equal to coordinates of - the specified point increased by specified value. - - - - - Addition operator - adds scalar to the specified point. - - - Point to increase coordinates of. - Value to add to coordinates of the specified point. - - Returns new point which coordinates equal to coordinates of - the specified point increased by specified value. - - - - - Subtraction operator - subtracts scalar from the specified point. - - - Point to decrease coordinates of. - Value to subtract from coordinates of the specified point. - - Returns new point which coordinates equal to coordinates of - the specified point decreased by specified value. - - - - - Subtraction operator - subtracts scalar from the specified point. - - - Point to decrease coordinates of. - Value to subtract from coordinates of the specified point. - - Returns new point which coordinates equal to coordinates of - the specified point decreased by specified value. - - - - - Multiplication operator - multiplies coordinates of the specified point by scalar value. - - - Point to multiply coordinates of. - Multiplication factor. - - Returns new point which coordinates equal to coordinates of - the specified point multiplied by specified value. - - - - - Multiplication operator - multiplies coordinates of the specified point by scalar value. - - - Point to multiply coordinates of. - Multiplication factor. - - Returns new point which coordinates equal to coordinates of - the specified point multiplied by specified value. - - - - - Division operator - divides coordinates of the specified point by scalar value. - - - Point to divide coordinates of. - Division factor. - - Returns new point which coordinates equal to coordinates of - the specified point divided by specified value. - - - - - Division operator - divides coordinates of the specified point by scalar value. - - - Point to divide coordinates of. - Division factor. - - Returns new point which coordinates equal to coordinates of - the specified point divided by specified value. - - - - - Equality operator - checks if two points have equal coordinates. - - - First point to check. - Second point to check. - - Returns if coordinates of specified - points are equal. - - - - - Inequality operator - checks if two points have different coordinates. - - - First point to check. - Second point to check. - - Returns if coordinates of specified - points are not equal. - - - - - Check if this instance of equal to the specified one. - - - Another point to check equalty to. - - Return if objects are equal. - - - - - Get hash code for this instance. - - - Returns the hash code for this instance. - - - - - Implicit conversion to . - - - Integer point to convert to single precision point. - - Returns new single precision point which coordinates are implicitly converted - to floats from coordinates of the specified integer point. - - - - - Implicit conversion to . - - - Integer point to convert to double precision point. - - Returns new double precision point which coordinates are implicitly converted - to doubles from coordinates of the specified integer point. - - - - - Get string representation of the class. - - - Returns string, which contains values of the point in readable form. - - - - - Calculate Euclidean norm of the vector comprised of the point's - coordinates - distance from (0, 0) in other words. - - - Returns point's distance from (0, 0) point. - - - - - Evaluator of expressions written in reverse polish notation. - - - The class evaluates expressions writen in reverse postfix polish notation. - - The list of supported functuins is: - - Arithmetic functions: +, -, *, /; - sin - sine; - cos - cosine; - ln - natural logarithm; - exp - exponent; - sqrt - square root. - - - Arguments for these functions could be as usual constants, written as numbers, as variables, - writen as $<var_number> ($2, for example). The variable number is zero based index - of variables array. - - Sample usage: - - // expression written in polish notation - string expression = "2 $0 / 3 $1 * +"; - // variables for the expression - double[] vars = new double[] { 3, 4 }; - // expression evaluation - double result = PolishExpression.Evaluate( expression, vars ); - - - - - - - Evaluates specified expression. - - - Expression written in postfix polish notation. - Variables for the expression. - - Evaluated value of the expression. - - Unsupported function is used in the expression. - Incorrect postfix polish expression. - - - - - Represents a double range with minimum and maximum values. - - - - The class represents a double range with inclusive limits - - both minimum and maximum values of the range are included into it. - Mathematical notation of such range is [min, max]. - - Sample usage: - - // create [0.25, 1.5] range - DoubleRange range1 = new DoubleRange( 0.25, 1.5 ); - // create [1.00, 2.25] range - DoubleRange range2 = new DoubleRange( 1.00, 2.25 ); - // check if values is inside of the first range - if ( range1.IsInside( 0.75 ) ) - { - // ... - } - // check if the second range is inside of the first range - if ( range1.IsInside( range2 ) ) - { - // ... - } - // check if two ranges overlap - if ( range1.IsOverlapping( range2 ) ) - { - // ... - } - - - - - - - Initializes a new instance of the class. - - - Minimum value of the range. - Maximum value of the range. - - - - - Check if the specified value is inside of the range. - - - Value to check. - - True if the specified value is inside of the range or - false otherwise. - - - - - Check if the specified range is inside of the range. - - - Range to check. - - True if the specified range is inside of the range or - false otherwise. - - - - - Check if the specified range overlaps with the range. - - - Range to check for overlapping. - - True if the specified range overlaps with the range or - false otherwise. - - - - - Convert the signle precision range to integer range. - - - Specifies if inner integer range must be returned or outer range. - - Returns integer version of the range. - - If is set to , then the - returned integer range will always fit inside of the current single precision range. - If it is set to , then current single precision range will always - fit into the returned integer range. - - - - - Equality operator - checks if two ranges have equal min/max values. - - - First range to check. - Second range to check. - - Returns if min/max values of specified - ranges are equal. - - - - - Inequality operator - checks if two ranges have different min/max values. - - - First range to check. - Second range to check. - - Returns if min/max values of specified - ranges are not equal. - - - - - Check if this instance of equal to the specified one. - - - Another range to check equalty to. - - Return if objects are equal. - - - - - Get hash code for this instance. - - - Returns the hash code for this instance. - - - - - Get string representation of the class. - - - Returns string, which contains min/max values of the range in readable form. - - - - - Minimum value of the range. - - - The property represents minimum value (left side limit) or the range - - [min, max]. - - - - - Maximum value of the range. - - - The property represents maximum value (right side limit) or the range - - [min, max]. - - - - - Length of the range (deffirence between maximum and minimum values). - - - - - A delegate which is used by events notifying abount sent/received message. - - - Event sender. - Event arguments containing details about the transferred message. - - - - - Structure for representing a pair of coordinates of float type. - - - The structure is used to store a pair of floating point - coordinates with single precision. - - Sample usage: - - // assigning coordinates in the constructor - Point p1 = new Point( 10, 20 ); - // creating a point and assigning coordinates later - Point p2; - p2.X = 30; - p2.Y = 40; - // calculating distance between two points - float distance = p1.DistanceTo( p2 ); - - - - - - - X coordinate. - - - - - - Y coordinate. - - - - - - Initializes a new instance of the structure. - - - X axis coordinate. - Y axis coordinate. - - - - - Calculate Euclidean distance between two points. - - - Point to calculate distance to. - - Returns Euclidean distance between this point and - points. - - - - - Calculate squared Euclidean distance between two points. - - - Point to calculate distance to. - - Returns squared Euclidean distance between this point and - points. - - - - - Addition operator - adds values of two points. - - - First point for addition. - Second point for addition. - - Returns new point which coordinates equal to sum of corresponding - coordinates of specified points. - - - - - Addition operator - adds values of two points. - - - First point for addition. - Second point for addition. - - Returns new point which coordinates equal to sum of corresponding - coordinates of specified points. - - - - - Subtraction operator - subtracts values of two points. - - - Point to subtract from. - Point to subtract. - - Returns new point which coordinates equal to difference of corresponding - coordinates of specified points. - - - - - Subtraction operator - subtracts values of two points. - - - Point to subtract from. - Point to subtract. - - Returns new point which coordinates equal to difference of corresponding - coordinates of specified points. - - - - - Addition operator - adds scalar to the specified point. - - - Point to increase coordinates of. - Value to add to coordinates of the specified point. - - Returns new point which coordinates equal to coordinates of - the specified point increased by specified value. - - - - - Addition operator - adds scalar to the specified point. - - - Point to increase coordinates of. - Value to add to coordinates of the specified point. - - Returns new point which coordinates equal to coordinates of - the specified point increased by specified value. - - - - - Subtraction operator - subtracts scalar from the specified point. - - - Point to decrease coordinates of. - Value to subtract from coordinates of the specified point. - - Returns new point which coordinates equal to coordinates of - the specified point decreased by specified value. - - - - - Subtraction operator - subtracts scalar from the specified point. - - - Point to decrease coordinates of. - Value to subtract from coordinates of the specified point. - - Returns new point which coordinates equal to coordinates of - the specified point decreased by specified value. - - - - - Multiplication operator - multiplies coordinates of the specified point by scalar value. - - - Point to multiply coordinates of. - Multiplication factor. - - Returns new point which coordinates equal to coordinates of - the specified point multiplied by specified value. - - - - - Multiplication operator - multiplies coordinates of the specified point by scalar value. - - - Point to multiply coordinates of. - Multiplication factor. - - Returns new point which coordinates equal to coordinates of - the specified point multiplied by specified value. - - - - - Division operator - divides coordinates of the specified point by scalar value. - - - Point to divide coordinates of. - Division factor. - - Returns new point which coordinates equal to coordinates of - the specified point divided by specified value. - - - - - Division operator - divides coordinates of the specified point by scalar value. - - - Point to divide coordinates of. - Division factor. - - Returns new point which coordinates equal to coordinates of - the specified point divided by specified value. - - - - - Equality operator - checks if two points have equal coordinates. - - - First point to check. - Second point to check. - - Returns if coordinates of specified - points are equal. - - - - - Inequality operator - checks if two points have different coordinates. - - - First point to check. - Second point to check. - - Returns if coordinates of specified - points are not equal. - - - - - Check if this instance of equal to the specified one. - - - Another point to check equalty to. - - Return if objects are equal. - - - - - Get hash code for this instance. - - - Returns the hash code for this instance. - - - - - Explicit conversion to . - - - Single precision point to convert to integer point. - - Returns new integer point which coordinates are explicitly converted - to integers from coordinates of the specified single precision point by - casting float values to integers value. - - - - - Implicit conversion to . - - - Single precision point to convert to double precision point. - - Returns new double precision point which coordinates are implicitly converted - to doubles from coordinates of the specified single precision point. - - - - - Rounds the single precision point. - - - Returns new integer point, which coordinates equal to whole numbers - nearest to the corresponding coordinates of the single precision point. - - - - - Get string representation of the class. - - - Returns string, which contains values of the point in readable form. - - - - - Calculate Euclidean norm of the vector comprised of the point's - coordinates - distance from (0, 0) in other words. - - - Returns point's distance from (0, 0) point. - - - - - Represents an integer range with minimum and maximum values. - - - - The class represents an integer range with inclusive limits - - both minimum and maximum values of the range are included into it. - Mathematical notation of such range is [min, max]. - - Sample usage: - - // create [1, 10] range - IntRange range1 = new IntRange( 1, 10 ); - // create [5, 15] range - IntRange range2 = new IntRange( 5, 15 ); - // check if values is inside of the first range - if ( range1.IsInside( 7 ) ) - { - // ... - } - // check if the second range is inside of the first range - if ( range1.IsInside( range2 ) ) - { - // ... - } - // check if two ranges overlap - if ( range1.IsOverlapping( range2 ) ) - { - // ... - } - - - - - - - Initializes a new instance of the structure. - - - Minimum value of the range. - Maximum value of the range. - - - - - Check if the specified value is inside of the range. - - - Value to check. - - True if the specified value is inside of the range or - false otherwise. - - - - - Check if the specified range is inside of the range. - - - Range to check. - - True if the specified range is inside of the range or - false otherwise. - - - - - Check if the specified range overlaps with the range. - - - Range to check for overlapping. - - True if the specified range overlaps with the range or - false otherwise. - - - - - Implicit conversion to . - - - Integer range to convert to single precision range. - - Returns new single precision range which min/max values are implicitly converted - to floats from min/max values of the specified integer range. - - - - - Equality operator - checks if two ranges have equal min/max values. - - - First range to check. - Second range to check. - - Returns if min/max values of specified - ranges are equal. - - - - - Inequality operator - checks if two ranges have different min/max values. - - - First range to check. - Second range to check. - - Returns if min/max values of specified - ranges are not equal. - - - - - Check if this instance of equal to the specified one. - - - Another range to check equalty to. - - Return if objects are equal. - - - - - Get hash code for this instance. - - - Returns the hash code for this instance. - - - - - Get string representation of the class. - - - Returns string, which contains min/max values of the range in readable form. - - - - - Minimum value of the range. - - - The property represents minimum value (left side limit) or the range - - [min, max]. - - - - - Maximum value of the range. - - - The property represents maximum value (right side limit) or the range - - [min, max]. - - - - - Length of the range (deffirence between maximum and minimum values). - - - - - Thread safe version of the class. - - - The class inherits the and overrides - its random numbers generation methods providing thread safety by guarding call - to the base class with a lock. See documentation to for - additional information about the base class. - - - - - Initializes a new instance of the class. - - - See for more information. - - - - - Initializes a new instance of the class. - - - A number used to calculate a starting value for the pseudo-random number sequence. - If a negative number is specified, the absolute value of the number is used. - - - See for more information. - - - - - Returns a nonnegative random number. - - - Returns a 32-bit signed integer greater than or equal to zero and less than - . - - See for more information. - - - - - Returns a nonnegative random number less than the specified maximum. - - - The exclusive upper bound of the random number to be generated. - must be greater than or equal to zero. - - Returns a 32-bit signed integer greater than or equal to zero, and less than ; - that is, the range of return values ordinarily includes zero but not . - - See for more information. - - - - - Returns a random number within a specified range. - - - The inclusive lower bound of the random number returned. - The exclusive upper bound of the random number returned. - must be greater than or equal to . - - Returns a 32-bit signed integer greater than or equal to and less - than ; that is, the range of return values includes - but not . - - See for more information. - - - - - Fills the elements of a specified array of bytes with random numbers. - - - An array of bytes to contain random numbers. - - See for more information. - - - - - Returns a random number between 0.0 and 1.0. - - - Returns a double-precision floating point number greater than or equal to 0.0, and less than 1.0. - - See for more information. - - - - - Represents a range with minimum and maximum values, which are single precision numbers (floats). - - - - The class represents a single precision range with inclusive limits - - both minimum and maximum values of the range are included into it. - Mathematical notation of such range is [min, max]. - - Sample usage: - - // create [0.25, 1.5] range - Range range1 = new Range( 0.25f, 1.5f ); - // create [1.00, 2.25] range - Range range2 = new Range( 1.00f, 2.25f ); - // check if values is inside of the first range - if ( range1.IsInside( 0.75f ) ) - { - // ... - } - // check if the second range is inside of the first range - if ( range1.IsInside( range2 ) ) - { - // ... - } - // check if two ranges overlap - if ( range1.IsOverlapping( range2 ) ) - { - // ... - } - - - - - - - Initializes a new instance of the structure. - - - Minimum value of the range. - Maximum value of the range. - - - - - Check if the specified value is inside of the range. - - - Value to check. - - True if the specified value is inside of the range or - false otherwise. - - - - - Check if the specified range is inside of the range. - - - Range to check. - - True if the specified range is inside of the range or - false otherwise. - - - - - Check if the specified range overlaps with the range. - - - Range to check for overlapping. - - True if the specified range overlaps with the range or - false otherwise. - - - - - Convert the signle precision range to integer range. - - - Specifies if inner integer range must be returned or outer range. - - Returns integer version of the range. - - If is set to , then the - returned integer range will always fit inside of the current single precision range. - If it is set to , then current single precision range will always - fit into the returned integer range. - - - - - Equality operator - checks if two ranges have equal min/max values. - - - First range to check. - Second range to check. - - Returns if min/max values of specified - ranges are equal. - - - - - Inequality operator - checks if two ranges have different min/max values. - - - First range to check. - Second range to check. - - Returns if min/max values of specified - ranges are not equal. - - - - - Check if this instance of equal to the specified one. - - - Another range to check equalty to. - - Return if objects are equal. - - - - - Get hash code for this instance. - - - Returns the hash code for this instance. - - - - - Get string representation of the class. - - - Returns string, which contains min/max values of the range in readable form. - - - - - Minimum value of the range. - - - The property represents minimum value (left side limit) or the range - - [min, max]. - - - - - Maximum value of the range. - - - The property represents maximum value (right side limit) or the range - - [min, max]. - - - - - Length of the range (deffirence between maximum and minimum values). - - - - - The class provides support for parallel computations, paralleling loop's iterations. - - - The class allows to parallel loop's iteration computing them in separate threads, - what allows their simultaneous execution on multiple CPUs/cores. - - - - - - Executes a for-loop in which iterations may run in parallel. - - - Loop's start index. - Loop's stop index. - Loop's body. - - The method is used to parallel for-loop running its iterations in - different threads. The start and stop parameters define loop's - starting and ending loop's indexes. The number of iterations is equal to stop - start. - - - Sample usage: - - Parallel.For( 0, 20, delegate( int i ) - // which is equivalent to - // for ( int i = 0; i < 20; i++ ) - { - System.Diagnostics.Debug.WriteLine( "Iteration: " + i ); - // ... - } ); - - - - - - - Number of threads used for parallel computations. - - - The property sets how many worker threads are created for paralleling - loops' computations. - - By default the property is set to number of CPU's in the system - (see ). - - - - - - Delegate defining for-loop's body. - - - Loop's index. - - - - - Set of systems tools. - - - The class is a container of different system tools, which are used - across the framework. Some of these tools are platform specific, so their - implementation is different on different platform, like .NET and Mono. - - - - - - Copy block of unmanaged memory. - - - Destination pointer. - Source pointer. - Memory block's length to copy. - - Return's value of - pointer to destination. - - This function is required because of the fact that .NET does - not provide any way to copy unmanaged blocks, but provides only methods to - copy from unmanaged memory to managed memory and vise versa. - - - - - Copy block of unmanaged memory. - - - Destination pointer. - Source pointer. - Memory block's length to copy. - - Return's value of - pointer to destination. - - This function is required because of the fact that .NET does - not provide any way to copy unmanaged blocks, but provides only methods to - copy from unmanaged memory to managed memory and vise versa. - - - - - Fill memory region with specified value. - - - Destination pointer. - Filler byte's value. - Memory block's length to fill. - - Return's value of - pointer to destination. - - - - - Fill memory region with specified value. - - - Destination pointer. - Filler byte's value. - Memory block's length to fill. - - Return's value of - pointer to destination. - - - - - Connection failed exception. - - - The exception is thrown in the case if connection to device - has failed. - - - - - - Initializes a new instance of the class. - - - Exception's message. - - - - - Connection lost exception. - - - The exception is thrown in the case if connection to device - is lost. When the exception is caught, user may need to reconnect to the device. - - - - - - Initializes a new instance of the class. - - - Exception's message. - - - - - Not connected exception. - - - The exception is thrown in the case if connection to device - is not established, but user requests for its services. - - - - - - Initializes a new instance of the class. - - - Exception's message. - - - - - Device busy exception. - - - The exception is thrown in the case if access to certain device - is not available due to the fact that it is currently busy handling other request/connection. - - - - - - Initializes a new instance of the class. - - - Exception's message. - - - - - Device error exception. - - - The exception is thrown in the case if some error happens with a device, which - may need to be reported to user. - - - - - Initializes a new instance of the class. - - - Exception's message. - - - - - Structure for representing a pair of coordinates of double type. - - - The structure is used to store a pair of floating point - coordinates with double precision. - - Sample usage: - - // assigning coordinates in the constructor - DoublePoint p1 = new DoublePoint( 10, 20 ); - // creating a point and assigning coordinates later - DoublePoint p2; - p2.X = 30; - p2.Y = 40; - // calculating distance between two points - double distance = p1.DistanceTo( p2 ); - - - - - - - X coordinate. - - - - - - Y coordinate. - - - - - - Initializes a new instance of the structure. - - - X axis coordinate. - Y axis coordinate. - - - - - Calculate Euclidean distance between two points. - - - Point to calculate distance to. - - Returns Euclidean distance between this point and - points. - - - - - Calculate squared Euclidean distance between two points. - - - Point to calculate distance to. - - Returns squared Euclidean distance between this point and - points. - - - - - Addition operator - adds values of two points. - - - First point for addition. - Second point for addition. - - Returns new point which coordinates equal to sum of corresponding - coordinates of specified points. - - - - - Addition operator - adds values of two points. - - - First point for addition. - Second point for addition. - - Returns new point which coordinates equal to sum of corresponding - coordinates of specified points. - - - - - Subtraction operator - subtracts values of two points. - - - Point to subtract from. - Point to subtract. - - Returns new point which coordinates equal to difference of corresponding - coordinates of specified points. - - - - - Subtraction operator - subtracts values of two points. - - - Point to subtract from. - Point to subtract. - - Returns new point which coordinates equal to difference of corresponding - coordinates of specified points. - - - - - Addition operator - adds scalar to the specified point. - - - Point to increase coordinates of. - Value to add to coordinates of the specified point. - - Returns new point which coordinates equal to coordinates of - the specified point increased by specified value. - - - - - Addition operator - adds scalar to the specified point. - - - Point to increase coordinates of. - Value to add to coordinates of the specified point. - - Returns new point which coordinates equal to coordinates of - the specified point increased by specified value. - - - - - Subtraction operator - subtracts scalar from the specified point. - - - Point to decrease coordinates of. - Value to subtract from coordinates of the specified point. - - Returns new point which coordinates equal to coordinates of - the specified point decreased by specified value. - - - - - Subtraction operator - subtracts scalar from the specified point. - - - Point to decrease coordinates of. - Value to subtract from coordinates of the specified point. - - Returns new point which coordinates equal to coordinates of - the specified point decreased by specified value. - - - - - Multiplication operator - multiplies coordinates of the specified point by scalar value. - - - Point to multiply coordinates of. - Multiplication factor. - - Returns new point which coordinates equal to coordinates of - the specified point multiplied by specified value. - - - - - Multiplication operator - multiplies coordinates of the specified point by scalar value. - - - Point to multiply coordinates of. - Multiplication factor. - - Returns new point which coordinates equal to coordinates of - the specified point multiplied by specified value. - - - - - Division operator - divides coordinates of the specified point by scalar value. - - - Point to divide coordinates of. - Division factor. - - Returns new point which coordinates equal to coordinates of - the specified point divided by specified value. - - - - - Division operator - divides coordinates of the specified point by scalar value. - - - Point to divide coordinates of. - Division factor. - - Returns new point which coordinates equal to coordinates of - the specified point divided by specified value. - - - - - Equality operator - checks if two points have equal coordinates. - - - First point to check. - Second point to check. - - Returns if coordinates of specified - points are equal. - - - - - Inequality operator - checks if two points have different coordinates. - - - First point to check. - Second point to check. - - Returns if coordinates of specified - points are not equal. - - - - - Check if this instance of equal to the specified one. - - - Another point to check equalty to. - - Return if objects are equal. - - - - - Get hash code for this instance. - - - Returns the hash code for this instance. - - - - - Explicit conversion to . - - - Double precision point to convert to integer point. - - Returns new integer point which coordinates are explicitly converted - to integers from coordinates of the specified double precision point by - casting double values to integers value. - - - - - Explicit conversion to . - - - Double precision point to convert to single precision point. - - Returns new single precision point which coordinates are explicitly converted - to floats from coordinates of the specified double precision point by - casting double values to float value. - - - - - Rounds the double precision point. - - - Returns new integer point, which coordinates equal to whole numbers - nearest to the corresponding coordinates of the double precision point. - - - - - Get string representation of the class. - - - Returns string, which contains values of the point in readable form. - - - - - Calculate Euclidean norm of the vector comprised of the point's - coordinates - distance from (0, 0) in other words. - - - Returns point's distance from (0, 0) point. - - - - diff --git a/Externals/GhostAPI/AForge ReadMe.txt b/Externals/GhostAPI/AForge ReadMe.txt new file mode 100644 index 0000000000..1f8a67b22 --- /dev/null +++ b/Externals/GhostAPI/AForge ReadMe.txt @@ -0,0 +1 @@ +The folder contains GhostAPI files, which is the API provided by Lego for communication with RCX brick. \ No newline at end of file diff --git a/Externals/GhostAPI/GhostAPI.dll b/Externals/GhostAPI/GhostAPI.dll new file mode 100644 index 0000000000..6349d2f5c Binary files /dev/null and b/Externals/GhostAPI/GhostAPI.dll differ diff --git a/Externals/GhostAPI/PbkComm32.dll b/Externals/GhostAPI/PbkComm32.dll new file mode 100644 index 0000000000..d90746e2d Binary files /dev/null and b/Externals/GhostAPI/PbkComm32.dll differ diff --git a/Externals/GhostAPI/PbkUsbPort.dll b/Externals/GhostAPI/PbkUsbPort.dll new file mode 100644 index 0000000000..232250d87 Binary files /dev/null and b/Externals/GhostAPI/PbkUsbPort.dll differ diff --git a/Externals/GhostAPI/relnotes.txt b/Externals/GhostAPI/relnotes.txt new file mode 100644 index 0000000000..34f4c6b14 --- /dev/null +++ b/Externals/GhostAPI/relnotes.txt @@ -0,0 +1,158 @@ + +Welcome to the LEGO cross-platform layered communication package ("Ghost")! +Please read carefully these release notes to find out what this package contains, how to +install it, what is changed from the previous releases and so on. + +All the contents of this package are Copyright (C) 1998-2001 The LEGO Company + +Enjoy! +The folks at LEGO Technology Center - Billund, Denmark + +---------------------------- + +Contents +======== + + What's in the package + Installation + Windows + MacOS + Version History + + +What's in the package +===================== + +The package contains: + + o USB Tower drivers and API for Windows 98/ME/2000/MacOS9 + o Ghost communication stack for Windows/MacOS (Intel/PowerPC) + o Ghost API w/ for Windows/MacOS (Intel/PowerPC) + Header files + Libraries + o Samples for for Windows/MacOS (Intel/PowerPC) + o Documentation + USB Tower interface documentation + Ghost API documentation + +Installation +============ + + +Windows +------- + + 1. IF YOU HAVE A LEGO USB TOWER: + Plug in your tower. When Windows prompts you, insert this CD in the CD reader and continue. + If you downloaded this package from the internet, you may have to specify the actual directory + where the USB driver files are (\WIN32\DRIVER). + + 2. Launch setup.exe from the CD's root directory. + + +MacOS +----- + + 1. Copy the LEGO tower drivers from folder "Put into Extensionfolder" to your Mac's system extensions folder. + The shared libraries in "Binary" can be put into extensions folder, or placed together with the application. + + 2. Copy the LEGO Tower control panel into the control panel folder inside the Mac's system folder. + + 3. Copy the Lego Tower Help folder to the Help folder inside the Mac's system folder. + + 3. Just grab the whole GhostAPI folder and copy it anywhere onto your hard drive. + + 4. Plug in your LEGO USB TOWER. + + +Version History +=============== + +v. 1.0.0.102 (November 15 2001) +--------------------------- +* [GhostAPI] The GhostAPI now refuses to create a USB communication stack if it's running on Win95 (or earlier) + or WInNT4 (or earlier), as those OSes do not support USB (Win95 OSR 2.1 does but it's usage is deprecated by + Microsoft and the USB tower driver does not support it). GhCreateStack will return PBK_ERR_NOTFOUND. + + +v. 1.0.0.101 (July 24 2001) +--------------------------- +* Changed major version number to 1 as this API becomes an official release. Build number remains the same. + +v. 0.1.0.101 (June 19 2001) +--------------------------- +* Increased error checking in GhCreateStack() +* [Mac] New driver with control panel and help +* [Win] Fixed driver installation script (LTOWER.INF) to prevent Windows 98 from asking for the ROBOLAB CD. + + +v. 0.1.0.100 (June 8 2001) +-------------------------- +* [Mac] New driver with full vendor request support. +* [Mac] Final version of the serial port support + + +v. 0.1.0.99 (May 18 2001) +------------------------- +* [Win] Sample Windows program supports unlock firmware and motors off/on + +* [Mac only] New Mac USB Driver supporting exclusive access to the port and some settings functions +* [Mac only] Support for SetTimeout and GetTimeout in the USB port layer. USB timeouts are not fixed + any more, but proportional to the number of bytes requested for. +* [Mac only] Preliminary version of the serial port available. + + +v. 0.1.0.98 (May 18 2001) +------------------------- +* [Mac only] New Mac USB Driver supporting exclusive access to the port and some settings functions +* [Mac only] Support for SetTimeout and GetTimeout in the USB port layer. USB timeouts are not fixed + any more, but proportional to the number of bytes requested for. +* [Mac only] Preliminary version of the serial port available. + +v. 0.1.0.97 (May 15 2001) +------------------------- +* [Win only] Now the GhostAPI doesn't load the pbkusbport and pbkcomm32 dlls untile they are needed +* [Win only] Changed the GhostAPI DLL's base address from default to 0x23000000 (this will speed up + loading in most cases). + +v. 0.1.0.96 (May 10 2001) +------------------------- +* [Mac only] Added support for serial towers + +v. 0.1.0.95 (Apr 24 2001) +------------------------- +* Added functions to the GhostAPI: GhDiagSelectFirstPort, GhDiagSelectNextPort, GhDiagSelectSpecificDevice +* [Win only] Added PbkMouse.exe to Windows binary deliverables for correct functioning of Serial port when a serial mouse is attached + to the PC. + + +v. 0.1.0.94 (Apr 20 2001) +------------------------- +* [Mac only] Fixed a bug where an attempt of creating a serial tower stack on the Macintosh would crash. +* [Mac only] GhostAPI binary and stub renamed from "GhostAPI Classic" to just "GhostAPI" in order + to be consistent with the Windows Version +* [Mac only] The GhostAPI functions are no longer mangled by the compiler +* [Win only] The Windows version now comes with a spiffy installation program +* Added function to Windows and Mac sample programs to download a minimal RCX program + +v. 0.1.0.93 (Apr 18 2001) +------------------------- +* Added new functions GhSetQueueContext and GhGetQueueContext, which give support to + notification context values. +* Windows sample program updated to show usage of GhSetQueueContext. +* Corrected bug in the Windows sample program - it was trying to destroy a queue both + in the notification function + and after calling GhExecute (if it returned PBOK). + +v. 0.1.0.92 (April 6 2001) +-------------------------- +* First Mac version released. +* GhGetRetries and GhSetRetries: changed parameter types from int and int* to int32 and int32* + +v. 0.1.0.91 (Mar 21 2001) +--------------------------- +* Removed C++ mangling from exported function names + +v. 0.1.0.90 (Mar 6 2001) +--------------------------- +* First released version (Win32 only). Code complete. diff --git a/Externals/NUnit/NUnitFitTests.html b/Externals/NUnit/NUnitFitTests.html new file mode 100644 index 0000000000..b7eb5c911 --- /dev/null +++ b/Externals/NUnit/NUnitFitTests.html @@ -0,0 +1,277 @@ + + + +

NUnit Acceptance Tests

+

+ Developers love self-referential programs! Hence, NUnit has always run all it's + own tests, even those that are not really unit tests. +

Now, beginning with NUnit 2.4, NUnit has top-level tests using Ward Cunningham's + FIT framework. At this time, the tests are pretty rudimentary, but it's a start + and it's a framework for doing more. +

Running the Tests

+

Open a console or shell window and navigate to the NUnit bin directory, which + contains this file. To run the test under Microsoft .Net, enter the command +

    runFile NUnitFitTests.html TestResults.html .
+ To run it under Mono, enter +
    mono runFile.exe NUnitFitTests.html TestResults.html .
+ Note the space and dot at the end of each command. The results of your test + will be in TestResults.html in the same directory. +

Platform and CLR Version

+ + + + +
NUnit.Fixtures.PlatformInfo
+

Verify Unit Tests

+

+ Load and run the NUnit unit tests, verifying that the results are as expected. + When these tests are run on different platforms, different numbers of tests may + be skipped, so the values for Skipped and Run tests are informational only. +

+ The number of tests in each assembly should be constant across all platforms - + any discrepancy usually means that one of the test source files was not + compiled on the platform. There should be no failures and no tests ignored. +

Note: + At the moment, the nunit.extensions.tests assembly is failing because the + fixture doesn't initialize addins in the test domain. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NUnit.Fixtures.AssemblyRunner
AssemblyTests()Run()Skipped()Ignored()Failures()
nunit.framework.tests.dll397  00
nunit.core.tests.dll355  00
nunit.util.tests.dll238  00
nunit.mocks.tests.dll43  00
nunit.extensions.tests.dll5  00
nunit-console.tests.dll40  00
nunit.uikit.tests.dll34  00
nunit-gui.tests.dll15  00
nunit.fixtures.tests.dll6  00
+

Code Snippet Tests

+

+ These tests create a test assembly from a snippet of code and then load and run + the tests that it contains, verifying that the structure of the loaded tests is + as expected and that the number of tests run, skipped, ignored or failed is + correct. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NUnit.Fixtures.SnippetRunner
CodeTree()Run()Skipped()Ignored()Failures()
public class TestClass
+{
+}
+
EMPTY0000
using NUnit.Framework;
+
+[TestFixture]
+public class TestClass
+{
+}
+
TestClass0000
using NUnit.Framework;
+
+[TestFixture]
+public class TestClass
+{
+    [Test]
+    public void T1() { }
+    [Test]
+    public void T2() { }
+    [Test]
+    public void T3() { }
+}
+
TestClass
+>T1
+>T2
+>T3
+
3000
using NUnit.Framework;
+
+[TestFixture]
+public class TestClass1
+{
+    [Test]
+    public void T1() { }
+}
+
+[TestFixture]
+public class TestClass2
+{
+    [Test]
+    public void T2() { }
+    [Test]
+    public void T3() { }
+}
+
TestClass1
+>T1
+TestClass2
+>T2
+>T3
+
3000
using NUnit.Framework;
+
+[TestFixture]
+public class TestClass
+{
+    [Test]
+    public void T1() { }
+    [Test, Ignore]
+    public void T2() { }
+    [Test]
+    public void T3() { }
+}
+
TestClass
+>T1
+>T2
+>T3
+
2010
using NUnit.Framework;
+
+[TestFixture]
+public class TestClass
+{
+    [Test]
+    public void T1() { }
+    [Test, Explicit]
+    public void T2() { }
+    [Test]
+    public void T3() { }
+}
+
TestClass
+>T1
+>T2
+>T3
+
2100
+

Summary Information

+ + + + +
fit.Summary
+ + diff --git a/Externals/NUnit/NUnitTests.config b/Externals/NUnit/NUnitTests.config new file mode 100644 index 0000000000..92f10d75f --- /dev/null +++ b/Externals/NUnit/NUnitTests.config @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Externals/NUnit/NUnitTests.nunit b/Externals/NUnit/NUnitTests.nunit new file mode 100644 index 0000000000..b2d55eb5a --- /dev/null +++ b/Externals/NUnit/NUnitTests.nunit @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/Externals/NUnit/TestResult-net-3.5.xml b/Externals/NUnit/TestResult-net-3.5.xml new file mode 100644 index 0000000000..b7a939fc5 --- /dev/null +++ b/Externals/NUnit/TestResult-net-3.5.xml @@ -0,0 +1,6025 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ]]]]>]]> + + + + + in message ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Externals/NUnit/agent.conf b/Externals/NUnit/agent.conf new file mode 100644 index 0000000000..b4cf5509e --- /dev/null +++ b/Externals/NUnit/agent.conf @@ -0,0 +1,4 @@ + + 8080 + . + \ No newline at end of file diff --git a/Externals/NUnit/agent.log.conf b/Externals/NUnit/agent.log.conf new file mode 100644 index 0000000000..6a9ced8b0 --- /dev/null +++ b/Externals/NUnit/agent.log.conf @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/Externals/NUnit/framework/nunit.framework.dll b/Externals/NUnit/framework/nunit.framework.dll new file mode 100644 index 0000000000..ed6550bb0 Binary files /dev/null and b/Externals/NUnit/framework/nunit.framework.dll differ diff --git a/Externals/NUnit/framework/nunit.framework.xml b/Externals/NUnit/framework/nunit.framework.xml new file mode 100644 index 0000000000..532d82867 --- /dev/null +++ b/Externals/NUnit/framework/nunit.framework.xml @@ -0,0 +1,10984 @@ + + + + nunit.framework + + + + + The different targets a test action attribute can be applied to + + + + + Default target, which is determined by where the action attribute is attached + + + + + Target a individual test case + + + + + Target a suite of test cases + + + + + Delegate used by tests that execute code and + capture any thrown exception. + + + + + The Assert class contains a collection of static methods that + implement the most common assertions used in NUnit. + + + + + We don't actually want any instances of this object, but some people + like to inherit from it to add other static methods. Hence, the + protected constructor disallows any instances of this object. + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + Throws a with the message and arguments + that are passed in. This allows a test to be cut short, with a result + of success returned to NUnit. + + The message to initialize the with. + Arguments to be used in formatting the message + + + + Throws a with the message and arguments + that are passed in. This allows a test to be cut short, with a result + of success returned to NUnit. + + The message to initialize the with. + + + + Throws a with the message and arguments + that are passed in. This allows a test to be cut short, with a result + of success returned to NUnit. + + + + + Throws an with the message and arguments + that are passed in. This is used by the other Assert functions. + + The message to initialize the with. + Arguments to be used in formatting the message + + + + Throws an with the message that is + passed in. This is used by the other Assert functions. + + The message to initialize the with. + + + + Throws an . + This is used by the other Assert functions. + + + + + Throws an with the message and arguments + that are passed in. This causes the test to be reported as ignored. + + The message to initialize the with. + Arguments to be used in formatting the message + + + + Throws an with the message that is + passed in. This causes the test to be reported as ignored. + + The message to initialize the with. + + + + Throws an . + This causes the test to be reported as ignored. + + + + + Throws an with the message and arguments + that are passed in. This causes the test to be reported as inconclusive. + + The message to initialize the with. + Arguments to be used in formatting the message + + + + Throws an with the message that is + passed in. This causes the test to be reported as inconclusive. + + The message to initialize the with. + + + + Throws an . + This causes the test to be reported as Inconclusive. + + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint expression to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display if the condition is false + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display if the condition is false + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + An ActualValueDelegate returning the value to be tested + A Constraint expression to be applied + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + An ActualValueDelegate returning the value to be tested + A Constraint expression to be applied + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + An ActualValueDelegate returning the value to be tested + A Constraint expression to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that the code represented by a delegate throws an exception + that satisfies the constraint provided. + + A TestDelegate to be executed + A ThrowsConstraint used in the test + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + Used as a synonym for That in rare cases where a private setter + causes a Visual Basic compilation error. + + The actual value to test + A Constraint to be applied + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + Used as a synonym for That in rare cases where a private setter + causes a Visual Basic compilation error. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + Used as a synonym for That in rare cases where a private setter + causes a Visual Basic compilation error. + + + This method is provided for use by VB developers needing to test + the value of properties with private setters. + + The actual value to test + A Constraint expression to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws a particular exception when called. + + A constraint to be satisfied by the exception + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws a particular exception when called. + + A constraint to be satisfied by the exception + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws a particular exception when called. + + A constraint to be satisfied by the exception + A TestDelegate + + + + Verifies that a delegate throws a particular exception when called. + + The exception Type expected + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws a particular exception when called. + + The exception Type expected + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws a particular exception when called. + + The exception Type expected + A TestDelegate + + + + Verifies that a delegate throws a particular exception when called. + + Type of the expected exception + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws a particular exception when called. + + Type of the expected exception + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws a particular exception when called. + + Type of the expected exception + A TestDelegate + + + + Verifies that a delegate throws an exception when called + and returns it. + + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws an exception when called + and returns it. + + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws an exception when called + and returns it. + + A TestDelegate + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + + + + Verifies that a delegate does not throw an exception + + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate does not throw an exception. + + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate does not throw an exception. + + A TestDelegate + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display in case of failure + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display in case of failure + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + The message to display in case of failure + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + The message to display in case of failure + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + + + + Verifies that two ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two unsigned ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two unsigned ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two unsigned ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two unsigned longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two unsigned longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two unsigned longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two decimals are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two decimals are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two decimals are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message to display in case of failure + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message to display in case of failure + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + + + + Verifies that two objects are equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are not equal an is thrown. + + The value that is expected + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two objects are equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are not equal an is thrown. + + The value that is expected + The actual value + The message to display in case of failure + + + + Verifies that two objects are equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are not equal an is thrown. + + The value that is expected + The actual value + + + + Verifies that two ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two unsigned ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two unsigned ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two unsigned ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two unsigned longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two unsigned longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two unsigned longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two decimals are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two decimals are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two decimals are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two floats are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two floats are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two floats are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two doubles are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two doubles are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two doubles are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two objects are not equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are equal an is thrown. + + The value that is expected + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two objects are not equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are equal an is thrown. + + The value that is expected + The actual value + The message to display in case of failure + + + + Verifies that two objects are not equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are equal an is thrown. + + The value that is expected + The actual value + + + + Asserts that two objects refer to the same object. If they + are not the same an is thrown. + + The expected object + The actual object + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that two objects refer to the same object. If they + are not the same an is thrown. + + The expected object + The actual object + The message to display in case of failure + + + + Asserts that two objects refer to the same object. If they + are not the same an is thrown. + + The expected object + The actual object + + + + Asserts that two objects do not refer to the same object. If they + are the same an is thrown. + + The expected object + The actual object + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that two objects do not refer to the same object. If they + are the same an is thrown. + + The expected object + The actual object + The message to display in case of failure + + + + Asserts that two objects do not refer to the same object. If they + are the same an is thrown. + + The expected object + The actual object + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + The message to display in case of failure + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + The message to display in case of failure + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + + + + Assert that a string is empty - that is equal to string.Empty + + The string to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that a string is empty - that is equal to string.Empty + + The string to be tested + The message to display in case of failure + + + + Assert that a string is empty - that is equal to string.Empty + + The string to be tested + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing ICollection + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing ICollection + The message to display in case of failure + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing ICollection + + + + Assert that a string is not empty - that is not equal to string.Empty + + The string to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that a string is not empty - that is not equal to string.Empty + + The string to be tested + The message to display in case of failure + + + + Assert that a string is not empty - that is not equal to string.Empty + + The string to be tested + + + + Assert that an array, list or other collection is not empty + + An array, list or other collection implementing ICollection + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that an array, list or other collection is not empty + + An array, list or other collection implementing ICollection + The message to display in case of failure + + + + Assert that an array, list or other collection is not empty + + An array, list or other collection implementing ICollection + + + + Assert that a string is either null or equal to string.Empty + + The string to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that a string is either null or equal to string.Empty + + The string to be tested + The message to display in case of failure + + + + Assert that a string is either null or equal to string.Empty + + The string to be tested + + + + Assert that a string is not null or empty + + The string to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that a string is not null or empty + + The string to be tested + The message to display in case of failure + + + + Assert that a string is not null or empty + + The string to be tested + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Asserts that an object is contained in a list. + + The expected object + The list to be examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is contained in a list. + + The expected object + The list to be examined + The message to display in case of failure + + + + Asserts that an object is contained in a list. + + The expected object + The list to be examined + + + + Helper for Assert.AreEqual(double expected, double actual, ...) + allowing code generation to work consistently. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Gets the number of assertions executed so far and + resets the counter to zero. + + + + + AssertionHelper is an optional base class for user tests, + allowing the use of shorter names for constraints and + asserts and avoiding conflict with the definition of + , from which it inherits much of its + behavior, in certain mock object frameworks. + + + + + Helper class with properties and methods that supply + a number of constraints used in Asserts. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding only if a specified number of them succeed. + + + + + Returns a new PropertyConstraintExpression, which will either + test for the existence of the named property on the object + being tested or apply any following constraint to that property. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns a constraint that tests two items for equality + + + + + Returns a constraint that tests that two references are the same object + + + + + Returns a constraint that tests whether the + actual value is greater than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a collection containing the same elements as the + collection supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a subset of the collection supplied as an argument. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a new ContainsConstraint. This constraint + will, in turn, make use of the appropriate second-level + constraint, depending on the type of the actual argument. + This overload is only used if the item sought is a string, + since any other type implies that we are looking for a + collection member. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the regular expression supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the regular expression supplied as an argument. + + + + + Returns a constraint that fails if the actual + value matches the pattern supplied as an argument. + + + + + Returns a constraint that tests whether the path provided + is the same as an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is the same path or under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is the same path or under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the actual value falls + within a specified range. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if at least one of them succeeds. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them fail. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Length property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Count property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Message property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the InnerException property of the object being tested. + + + + + Returns a constraint that tests for null + + + + + Returns a constraint that tests for True + + + + + Returns a constraint that tests for False + + + + + Returns a constraint that tests for a positive value + + + + + Returns a constraint that tests for a negative value + + + + + Returns a constraint that tests for NaN + + + + + Returns a constraint that tests for empty + + + + + Returns a constraint that tests whether a collection + contains all unique items. + + + + + Returns a constraint that tests whether an object graph is serializable in binary format. + + + + + Returns a constraint that tests whether an object graph is serializable in xml format. + + + + + Returns a constraint that tests whether a collection is ordered + + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. Works + identically to Assert.That. + + The actual value to test + A Constraint to be applied + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. Works + identically to Assert.That. + + The actual value to test + A Constraint to be applied + The message to be displayed in case of failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. Works + identically to Assert.That. + + The actual value to test + A Constraint to be applied + The message to be displayed in case of failure + Arguments to use in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . Works Identically to + . + + The evaluated condition + The message to display if the condition is false + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . Works Identically to + . + + The evaluated condition + The message to display if the condition is false + + + + Asserts that a condition is true. If the condition is false the method throws + an . Works Identically to . + + The evaluated condition + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + A Constraint expression to be applied + An ActualValueDelegate returning the value to be tested + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + A Constraint expression to be applied + An ActualValueDelegate returning the value to be tested + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + An ActualValueDelegate returning the value to be tested + A Constraint expression to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that the code represented by a delegate throws an exception + that satisfies the constraint provided. + + A TestDelegate to be executed + A ThrowsConstraint used in the test + + + + Returns a ListMapper based on a collection. + + The original collection + + + + + Provides static methods to express the assumptions + that must be met for a test to give a meaningful + result. If an assumption is not met, the test + should produce an inconclusive result. + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display if the condition is false + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display if the condition is false + + + + Asserts that a condition is true. If the condition is false the + method throws an . + + The evaluated condition + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + An ActualValueDelegate returning the value to be tested + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + An ActualValueDelegate returning the value to be tested + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + An ActualValueDelegate returning the value to be tested + A Constraint expression to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + The message that will be displayed on failure + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that the code represented by a delegate throws an exception + that satisfies the constraint provided. + + A TestDelegate to be executed + A ThrowsConstraint used in the test + + + + Waits for pending asynchronous operations to complete, if appropriate, + and returns a proper result of the invocation by unwrapping task results + + The raw result of the method invocation + The unwrapped result, if necessary + + + + A set of Assert methods operationg on one or more collections + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + Asserts that all items contained in collection are of the type specified by expectedType. + + IEnumerable containing objects to be considered + System.Type that all objects in collection must be instances of + + + + Asserts that all items contained in collection are of the type specified by expectedType. + + IEnumerable containing objects to be considered + System.Type that all objects in collection must be instances of + The message that will be displayed on failure + + + + Asserts that all items contained in collection are of the type specified by expectedType. + + IEnumerable containing objects to be considered + System.Type that all objects in collection must be instances of + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that all items contained in collection are not equal to null. + + IEnumerable containing objects to be considered + + + + Asserts that all items contained in collection are not equal to null. + + IEnumerable containing objects to be considered + The message that will be displayed on failure + + + + Asserts that all items contained in collection are not equal to null. + + IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Ensures that every object contained in collection exists within the collection + once and only once. + + IEnumerable of objects to be considered + + + + Ensures that every object contained in collection exists within the collection + once and only once. + + IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Ensures that every object contained in collection exists within the collection + once and only once. + + IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + The message that will be displayed on failure + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are equivalent, containing the same objects but the match may be in any order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + + + + Asserts that expected and actual are equivalent, containing the same objects but the match may be in any order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Asserts that expected and actual are equivalent, containing the same objects but the match may be in any order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are not exactly equal. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + + + + Asserts that expected and actual are not exactly equal. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + + + + Asserts that expected and actual are not exactly equal. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Asserts that expected and actual are not exactly equal. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + The message that will be displayed on failure + + + + Asserts that expected and actual are not exactly equal. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are not exactly equal. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are not equivalent. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + + + + Asserts that expected and actual are not equivalent. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Asserts that expected and actual are not equivalent. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that collection contains actual as an item. + + IEnumerable of objects to be considered + Object to be found within collection + + + + Asserts that collection contains actual as an item. + + IEnumerable of objects to be considered + Object to be found within collection + The message that will be displayed on failure + + + + Asserts that collection contains actual as an item. + + IEnumerable of objects to be considered + Object to be found within collection + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that collection does not contain actual as an item. + + IEnumerable of objects to be considered + Object that cannot exist within collection + + + + Asserts that collection does not contain actual as an item. + + IEnumerable of objects to be considered + Object that cannot exist within collection + The message that will be displayed on failure + + + + Asserts that collection does not contain actual as an item. + + IEnumerable of objects to be considered + Object that cannot exist within collection + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that the superset does not contain the subset + + The IEnumerable subset to be considered + The IEnumerable superset to be considered + + + + Asserts that the superset does not contain the subset + + The IEnumerable subset to be considered + The IEnumerable superset to be considered + The message that will be displayed on failure + + + + Asserts that the superset does not contain the subset + + The IEnumerable subset to be considered + The IEnumerable superset to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that the superset contains the subset. + + The IEnumerable subset to be considered + The IEnumerable superset to be considered + + + + Asserts that the superset contains the subset. + + The IEnumerable subset to be considered + The IEnumerable superset to be considered + The message that will be displayed on failure + + + + Asserts that the superset contains the subset. + + The IEnumerable subset to be considered + The IEnumerable superset to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + + + + Assert that an array,list or other collection is empty + + An array, list or other collection implementing IEnumerable + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + + + + Assert that an array,list or other collection is empty + + An array, list or other collection implementing IEnumerable + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + A custom comparer to perform the comparisons + The message to be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + A custom comparer to perform the comparisons + The message to be displayed on failure + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + A custom comparer to perform the comparisons + + + + Helper class with properties and methods that supply + a number of constraints used in Asserts. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Summary description for DirectoryAssert + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + We don't actually want any instances of this object, but some people + like to inherit from it to add other static methods. Hence, the + protected constructor disallows any instances of this object. + + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + The message to display if directories are not equal + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + The message to display if directories are not equal + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + The message to display if directories are not equal + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + The message to display if directories are equal + Arguments to be used in formatting the message + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + The message to display if directories are equal + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + The message to display if directories are not equal + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + The message to display if directories are not equal + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + The message to display if directories are not equal + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + The message to display if directories are not equal + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + Arguments to be used in formatting the message + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + Arguments to be used in formatting the message + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + Arguments to be used in formatting the message + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + Arguments to be used in formatting the message + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + + + + Summary description for FileAssert. + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + We don't actually want any instances of this object, but some people + like to inherit from it to add other static methods. Hence, the + protected constructor disallows any instances of this object. + + + + + Verifies that two Streams are equal. Two Streams are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The expected Stream + The actual Stream + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Verifies that two Streams are equal. Two Streams are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The expected Stream + The actual Stream + The message to display if objects are not equal + + + + Verifies that two Streams are equal. Two Streams are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The expected Stream + The actual Stream + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A file containing the value that is expected + A file containing the actual value + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A file containing the value that is expected + A file containing the actual value + The message to display if objects are not equal + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A file containing the value that is expected + A file containing the actual value + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + The message to display if objects are not equal + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + + + + Asserts that two Streams are not equal. If they are equal + an is thrown. + + The expected Stream + The actual Stream + The message to be displayed when the two Stream are the same. + Arguments to be used in formatting the message + + + + Asserts that two Streams are not equal. If they are equal + an is thrown. + + The expected Stream + The actual Stream + The message to be displayed when the Streams are the same. + + + + Asserts that two Streams are not equal. If they are equal + an is thrown. + + The expected Stream + The actual Stream + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + A file containing the value that is expected + A file containing the actual value + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + A file containing the value that is expected + A file containing the actual value + The message to display if objects are not equal + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + A file containing the value that is expected + A file containing the actual value + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + The message to display if objects are not equal + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + + + + GlobalSettings is a place for setting default values used + by the framework in performing asserts. + + + + + Default tolerance for floating point equality + + + + + Class used to guard against unexpected argument values + by throwing an appropriate exception. + + + + + Throws an exception if an argument is null + + The value to be tested + The name of the argument + + + + Throws an exception if a string argument is null or empty + + The value to be tested + The name of the argument + + + + Helper class with properties and methods that supply + a number of constraints used in Asserts. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding only if a specified number of them succeed. + + + + + Returns a new PropertyConstraintExpression, which will either + test for the existence of the named property on the object + being tested or apply any following constraint to that property. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if at least one of them succeeds. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them fail. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Length property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Count property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Message property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the InnerException property of the object being tested. + + + + + Interface implemented by a user fixture in order to + validate any expected exceptions. It is only called + for test methods marked with the ExpectedException + attribute. + + + + + Method to handle an expected exception + + The exception to be handled + + + + Helper class with properties and methods that supply + a number of constraints used in Asserts. + + + + + Returns a constraint that tests two items for equality + + + + + Returns a constraint that tests that two references are the same object + + + + + Returns a constraint that tests whether the + actual value is greater than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a collection containing the same elements as the + collection supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a subset of the collection supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the regular expression supplied as an argument. + + + + + Returns a constraint that tests whether the path provided + is the same as an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is the same path or under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the actual value falls + within a specified range. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. + + + + + Returns a constraint that tests for null + + + + + Returns a constraint that tests for True + + + + + Returns a constraint that tests for False + + + + + Returns a constraint that tests for a positive value + + + + + Returns a constraint that tests for a negative value + + + + + Returns a constraint that tests for NaN + + + + + Returns a constraint that tests for empty + + + + + Returns a constraint that tests whether a collection + contains all unique items. + + + + + Returns a constraint that tests whether an object graph is serializable in binary format. + + + + + Returns a constraint that tests whether an object graph is serializable in xml format. + + + + + Returns a constraint that tests whether a collection is ordered + + + + + The ITestCaseData interface is implemented by a class + that is able to return complete testcases for use by + a parameterized test method. + + NOTE: This interface is used in both the framework + and the core, even though that results in two different + types. However, sharing the source code guarantees that + the various implementations will be compatible and that + the core is able to reflect successfully over the + framework implementations of ITestCaseData. + + + + + Gets the argument list to be provided to the test + + + + + Gets the expected result + + + + + Indicates whether a result has been specified. + This is necessary because the result may be + null, so it's value cannot be checked. + + + + + Gets the expected exception Type + + + + + Gets the FullName of the expected exception + + + + + Gets the name to be used for the test + + + + + Gets the description of the test + + + + + Gets a value indicating whether this is ignored. + + true if ignored; otherwise, false. + + + + Gets a value indicating whether this is explicit. + + true if explicit; otherwise, false. + + + + Gets the ignore reason. + + The ignore reason. + + + + The Iz class is a synonym for Is intended for use in VB, + which regards Is as a keyword. + + + + + The List class is a helper class with properties and methods + that supply a number of constraints used with lists and collections. + + + + + List.Map returns a ListMapper, which can be used to map + the original collection to another collection. + + + + + + + ListMapper is used to transform a collection used as an actual argument + producing another collection to be used in the assertion. + + + + + Construct a ListMapper based on a collection + + The collection to be transformed + + + + Produces a collection containing all the values of a property + + The collection of property values + + + + + Randomizer returns a set of random values in a repeatable + way, to allow re-running of tests if necessary. + + + + + Get a randomizer for a particular member, returning + one that has already been created if it exists. + This ensures that the same values are generated + each time the tests are reloaded. + + + + + Get a randomizer for a particular parameter, returning + one that has already been created if it exists. + This ensures that the same values are generated + each time the tests are reloaded. + + + + + Construct a randomizer using a random seed + + + + + Construct a randomizer using a specified seed + + + + + Return an array of random doubles between 0.0 and 1.0. + + + + + + + Return an array of random doubles with values in a specified range. + + + + + Return an array of random ints with values in a specified range. + + + + + Get a random seed for use in creating a randomizer. + + + + + The SpecialValue enum is used to represent TestCase arguments + that cannot be used as arguments to an Attribute. + + + + + Null represents a null value, which cannot be used as an + argument to an attribute under .NET 1.x + + + + + Basic Asserts on strings. + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + + + + Asserts that a string is not found within another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + + + + Asserts that a string starts with another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string starts with another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string starts with another string. + + The expected string + The string to be examined + + + + Asserts that a string does not start with another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string does not start with another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string does not start with another string. + + The expected string + The string to be examined + + + + Asserts that a string ends with another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string ends with another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string ends with another string. + + The expected string + The string to be examined + + + + Asserts that a string does not end with another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string does not end with another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string does not end with another string. + + The expected string + The string to be examined + + + + Asserts that two strings are equal, without regard to case. + + The expected string + The actual string + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that two strings are equal, without regard to case. + + The expected string + The actual string + The message to display in case of failure + + + + Asserts that two strings are equal, without regard to case. + + The expected string + The actual string + + + + Asserts that two strings are not equal, without regard to case. + + The expected string + The actual string + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that two strings are Notequal, without regard to case. + + The expected string + The actual string + The message to display in case of failure + + + + Asserts that two strings are not equal, without regard to case. + + The expected string + The actual string + + + + Asserts that a string matches an expected regular expression pattern. + + The regex pattern to be matched + The actual string + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string matches an expected regular expression pattern. + + The regex pattern to be matched + The actual string + The message to display in case of failure + + + + Asserts that a string matches an expected regular expression pattern. + + The regex pattern to be matched + The actual string + + + + Asserts that a string does not match an expected regular expression pattern. + + The regex pattern to be used + The actual string + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string does not match an expected regular expression pattern. + + The regex pattern to be used + The actual string + The message to display in case of failure + + + + Asserts that a string does not match an expected regular expression pattern. + + The regex pattern to be used + The actual string + + + + The TestCaseData class represents a set of arguments + and other parameter info to be used for a parameterized + test case. It provides a number of instance modifiers + for use in initializing the test case. + + Note: Instance modifiers are getters that return + the same instance after modifying it's state. + + + + + The argument list to be provided to the test + + + + + The expected result to be returned + + + + + Set to true if this has an expected result + + + + + The expected exception Type + + + + + The FullName of the expected exception + + + + + The name to be used for the test + + + + + The description of the test + + + + + A dictionary of properties, used to add information + to tests without requiring the class to change. + + + + + If true, indicates that the test case is to be ignored + + + + + If true, indicates that the test case is marked explicit + + + + + The reason for ignoring a test case + + + + + Initializes a new instance of the class. + + The arguments. + + + + Initializes a new instance of the class. + + The argument. + + + + Initializes a new instance of the class. + + The first argument. + The second argument. + + + + Initializes a new instance of the class. + + The first argument. + The second argument. + The third argument. + + + + Sets the expected result for the test + + The expected result + A modified TestCaseData + + + + Sets the expected exception type for the test + + Type of the expected exception. + The modified TestCaseData instance + + + + Sets the expected exception type for the test + + FullName of the expected exception. + The modified TestCaseData instance + + + + Sets the name of the test case + + The modified TestCaseData instance + + + + Sets the description for the test case + being constructed. + + The description. + The modified TestCaseData instance. + + + + Applies a category to the test + + + + + + + Applies a named property to the test + + + + + + + + Applies a named property to the test + + + + + + + + Applies a named property to the test + + + + + + + + Ignores this TestCase. + + + + + + Ignores this TestCase, specifying the reason. + + The reason. + + + + + Marks this TestCase as Explicit + + + + + + Marks this TestCase as Explicit, specifying the reason. + + The reason. + + + + + Gets the argument list to be provided to the test + + + + + Gets the expected result + + + + + Returns true if the result has been set + + + + + Gets the expected exception Type + + + + + Gets the FullName of the expected exception + + + + + Gets the name to be used for the test + + + + + Gets the description of the test + + + + + Gets a value indicating whether this is ignored. + + true if ignored; otherwise, false. + + + + Gets a value indicating whether this is explicit. + + true if explicit; otherwise, false. + + + + Gets the ignore reason. + + The ignore reason. + + + + Gets a list of categories associated with this test. + + + + + Gets the property dictionary for this test + + + + + Provide the context information of the current test + + + + + Constructs a TestContext using the provided context dictionary + + A context dictionary + + + + Get the current test context. This is created + as needed. The user may save the context for + use within a test, but it should not be used + outside the test for which it is created. + + + + + Gets a TestAdapter representing the currently executing test in this context. + + + + + Gets a ResultAdapter representing the current result for the test + executing in this context. + + + + + Gets the directory containing the current test assembly. + + + + + Gets the directory to be used for outputing files created + by this test run. + + + + + TestAdapter adapts a Test for consumption by + the user test code. + + + + + Constructs a TestAdapter for this context + + The context dictionary + + + + The name of the test. + + + + + The FullName of the test + + + + + The properties of the test. + + + + + ResultAdapter adapts a TestResult for consumption by + the user test code. + + + + + Construct a ResultAdapter for a context + + The context holding the result + + + + The TestState of current test. This maps to the ResultState + used in nunit.core and is subject to change in the future. + + + + + The TestStatus of current test. This enum will be used + in future versions of NUnit and so is to be preferred + to the TestState value. + + + + + Provides details about a test + + + + + Creates an instance of TestDetails + + The fixture that the test is a member of, if available. + The method that implements the test, if available. + The full name of the test. + A string representing the type of test, e.g. "Test Case". + Indicates if the test represents a suite of tests. + + + + The fixture that the test is a member of, if available. + + + + + The method that implements the test, if available. + + + + + The full name of the test. + + + + + A string representing the type of test, e.g. "Test Case". + + + + + Indicates if the test represents a suite of tests. + + + + + The ResultState enum indicates the result of running a test + + + + + The result is inconclusive + + + + + The test was not runnable. + + + + + The test has been skipped. + + + + + The test has been ignored. + + + + + The test succeeded + + + + + The test failed + + + + + The test encountered an unexpected exception + + + + + The test was cancelled by the user + + + + + The TestStatus enum indicates the result of running a test + + + + + The test was inconclusive + + + + + The test has skipped + + + + + The test succeeded + + + + + The test failed + + + + + Helper class with static methods used to supply constraints + that operate on strings. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the Regex pattern supplied as an argument. + + + + + Returns a constraint that fails if the actual + value matches the pattern supplied as an argument. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. + + + + + TextMessageWriter writes constraint descriptions and messages + in displayable form as a text stream. It tailors the display + of individual message components to form the standard message + format of NUnit assertion failure messages. + + + + + MessageWriter is the abstract base for classes that write + constraint descriptions and messages in some form. The + class has separate methods for writing various components + of a message, allowing implementations to tailor the + presentation as needed. + + + + + Construct a MessageWriter given a culture + + + + + Method to write single line message with optional args, usually + written to precede the general failure message. + + The message to be written + Any arguments used in formatting the message + + + + Method to write single line message with optional args, usually + written to precede the general failure message, at a givel + indentation level. + + The indentation level of the message + The message to be written + Any arguments used in formatting the message + + + + Display Expected and Actual lines for a constraint. This + is called by MessageWriter's default implementation of + WriteMessageTo and provides the generic two-line display. + + The constraint that failed + + + + Display Expected and Actual lines for given values. This + method may be called by constraints that need more control over + the display of actual and expected values than is provided + by the default implementation. + + The expected value + The actual value causing the failure + + + + Display Expected and Actual lines for given values, including + a tolerance value on the Expected line. + + The expected value + The actual value causing the failure + The tolerance within which the test was made + + + + Display the expected and actual string values on separate lines. + If the mismatch parameter is >=0, an additional line is displayed + line containing a caret that points to the mismatch point. + + The expected string value + The actual string value + The point at which the strings don't match or -1 + If true, case is ignored in locating the point where the strings differ + If true, the strings should be clipped to fit the line + + + + Writes the text for a connector. + + The connector. + + + + Writes the text for a predicate. + + The predicate. + + + + Writes the text for an expected value. + + The expected value. + + + + Writes the text for a modifier + + The modifier. + + + + Writes the text for an actual value. + + The actual value. + + + + Writes the text for a generalized value. + + The value. + + + + Writes the text for a collection value, + starting at a particular point, to a max length + + The collection containing elements to write. + The starting point of the elements to write + The maximum number of elements to write + + + + Abstract method to get the max line length + + + + + Prefix used for the expected value line of a message + + + + + Prefix used for the actual value line of a message + + + + + Length of a message prefix + + + + + Construct a TextMessageWriter + + + + + Construct a TextMessageWriter, specifying a user message + and optional formatting arguments. + + + + + + + Method to write single line message with optional args, usually + written to precede the general failure message, at a givel + indentation level. + + The indentation level of the message + The message to be written + Any arguments used in formatting the message + + + + Display Expected and Actual lines for a constraint. This + is called by MessageWriter's default implementation of + WriteMessageTo and provides the generic two-line display. + + The constraint that failed + + + + Display Expected and Actual lines for given values. This + method may be called by constraints that need more control over + the display of actual and expected values than is provided + by the default implementation. + + The expected value + The actual value causing the failure + + + + Display Expected and Actual lines for given values, including + a tolerance value on the expected line. + + The expected value + The actual value causing the failure + The tolerance within which the test was made + + + + Display the expected and actual string values on separate lines. + If the mismatch parameter is >=0, an additional line is displayed + line containing a caret that points to the mismatch point. + + The expected string value + The actual string value + The point at which the strings don't match or -1 + If true, case is ignored in string comparisons + If true, clip the strings to fit the max line length + + + + Writes the text for a connector. + + The connector. + + + + Writes the text for a predicate. + + The predicate. + + + + Write the text for a modifier. + + The modifier. + + + + Writes the text for an expected value. + + The expected value. + + + + Writes the text for an actual value. + + The actual value. + + + + Writes the text for a generalized value. + + The value. + + + + Writes the text for a collection value, + starting at a particular point, to a max length + + The collection containing elements to write. + The starting point of the elements to write + The maximum number of elements to write + + + + Write the generic 'Expected' line for a constraint + + The constraint that failed + + + + Write the generic 'Expected' line for a given value + + The expected value + + + + Write the generic 'Expected' line for a given value + and tolerance. + + The expected value + The tolerance within which the test was made + + + + Write the generic 'Actual' line for a constraint + + The constraint for which the actual value is to be written + + + + Write the generic 'Actual' line for a given value + + The actual value causing a failure + + + + Gets or sets the maximum line length for this writer + + + + + Helper class with properties and methods that supply + constraints that operate on exceptions. + + + + + Creates a constraint specifying the exact type of exception expected + + + + + Creates a constraint specifying the exact type of exception expected + + + + + Creates a constraint specifying the type of exception expected + + + + + Creates a constraint specifying the type of exception expected + + + + + Creates a constraint specifying an expected exception + + + + + Creates a constraint specifying an exception with a given InnerException + + + + + Creates a constraint specifying an expected TargetInvocationException + + + + + Creates a constraint specifying an expected TargetInvocationException + + + + + Creates a constraint specifying an expected TargetInvocationException + + + + + Creates a constraint specifying that no exception is thrown + + + + + Attribute used to apply a category to a test + + + + + The name of the category + + + + + Construct attribute for a given category based on + a name. The name may not contain the characters ',', + '+', '-' or '!'. However, this is not checked in the + constructor since it would cause an error to arise at + as the test was loaded without giving a clear indication + of where the problem is located. The error is handled + in NUnitFramework.cs by marking the test as not + runnable. + + The name of the category + + + + Protected constructor uses the Type name as the name + of the category. + + + + + The name of the category + + + + + Used to mark a field for use as a datapoint when executing a theory + within the same fixture that requires an argument of the field's Type. + + + + + Used to mark an array as containing a set of datapoints to be used + executing a theory within the same fixture that requires an argument + of the Type of the array elements. + + + + + Attribute used to provide descriptive text about a + test case or fixture. + + + + + Construct the attribute + + Text describing the test + + + + Gets the test description + + + + + Enumeration indicating how the expected message parameter is to be used + + + + Expect an exact match + + + Expect a message containing the parameter string + + + Match the regular expression provided as a parameter + + + Expect a message that starts with the parameter string + + + + ExpectedExceptionAttribute + + + + + + Constructor for a non-specific exception + + + + + Constructor for a given type of exception + + The type of the expected exception + + + + Constructor for a given exception name + + The full name of the expected exception + + + + Gets or sets the expected exception type + + + + + Gets or sets the full Type name of the expected exception + + + + + Gets or sets the expected message text + + + + + Gets or sets the user message displayed in case of failure + + + + + Gets or sets the type of match to be performed on the expected message + + + + + Gets the name of a method to be used as an exception handler + + + + + ExplicitAttribute marks a test or test fixture so that it will + only be run if explicitly executed from the gui or command line + or if it is included by use of a filter. The test will not be + run simply because an enclosing suite is run. + + + + + Default constructor + + + + + Constructor with a reason + + The reason test is marked explicit + + + + The reason test is marked explicit + + + + + Attribute used to mark a test that is to be ignored. + Ignored tests result in a warning message when the + tests are run. + + + + + Constructs the attribute without giving a reason + for ignoring the test. + + + + + Constructs the attribute giving a reason for ignoring the test + + The reason for ignoring the test + + + + The reason for ignoring a test + + + + + Abstract base for Attributes that are used to include tests + in the test run based on environmental settings. + + + + + Constructor with no included items specified, for use + with named property syntax. + + + + + Constructor taking one or more included items + + Comma-delimited list of included items + + + + Name of the item that is needed in order for + a test to run. Multiple itemss may be given, + separated by a comma. + + + + + Name of the item to be excluded. Multiple items + may be given, separated by a comma. + + + + + The reason for including or excluding the test + + + + + PlatformAttribute is used to mark a test fixture or an + individual method as applying to a particular platform only. + + + + + Constructor with no platforms specified, for use + with named property syntax. + + + + + Constructor taking one or more platforms + + Comma-deliminted list of platforms + + + + CultureAttribute is used to mark a test fixture or an + individual method as applying to a particular Culture only. + + + + + Constructor with no cultures specified, for use + with named property syntax. + + + + + Constructor taking one or more cultures + + Comma-deliminted list of cultures + + + + Marks a test to use a combinatorial join of any argument data + provided. NUnit will create a test case for every combination of + the arguments provided. This can result in a large number of test + cases and so should be used judiciously. This is the default join + type, so the attribute need not be used except as documentation. + + + + + PropertyAttribute is used to attach information to a test as a name/value pair.. + + + + + Construct a PropertyAttribute with a name and string value + + The name of the property + The property value + + + + Construct a PropertyAttribute with a name and int value + + The name of the property + The property value + + + + Construct a PropertyAttribute with a name and double value + + The name of the property + The property value + + + + Constructor for derived classes that set the + property dictionary directly. + + + + + Constructor for use by derived classes that use the + name of the type as the property name. Derived classes + must ensure that the Type of the property value is + a standard type supported by the BCL. Any custom + types will cause a serialization Exception when + in the client. + + + + + Gets the property dictionary for this attribute + + + + + Default constructor + + + + + Marks a test to use pairwise join of any argument data provided. + NUnit will attempt too excercise every pair of argument values at + least once, using as small a number of test cases as it can. With + only two arguments, this is the same as a combinatorial join. + + + + + Default constructor + + + + + Marks a test to use a sequential join of any argument data + provided. NUnit will use arguements for each parameter in + sequence, generating test cases up to the largest number + of argument values provided and using null for any arguments + for which it runs out of values. Normally, this should be + used with the same number of arguments for each parameter. + + + + + Default constructor + + + + + Summary description for MaxTimeAttribute. + + + + + Construct a MaxTimeAttribute, given a time in milliseconds. + + The maximum elapsed time in milliseconds + + + + RandomAttribute is used to supply a set of random values + to a single parameter of a parameterized test. + + + + + ValuesAttribute is used to provide literal arguments for + an individual parameter of a test. + + + + + Abstract base class for attributes that apply to parameters + and supply data for the parameter. + + + + + Gets the data to be provided to the specified parameter + + + + + The collection of data to be returned. Must + be set by any derived attribute classes. + We use an object[] so that the individual + elements may have their type changed in GetData + if necessary. + + + + + Construct with one argument + + + + + + Construct with two arguments + + + + + + + Construct with three arguments + + + + + + + + Construct with an array of arguments + + + + + + Get the collection of values to be used as arguments + + + + + Construct a set of doubles from 0.0 to 1.0, + specifying only the count. + + + + + + Construct a set of doubles from min to max + + + + + + + + Construct a set of ints from min to max + + + + + + + + Get the collection of values to be used as arguments + + + + + RangeAttribute is used to supply a range of values to an + individual parameter of a parameterized test. + + + + + Construct a range of ints using default step of 1 + + + + + + + Construct a range of ints specifying the step size + + + + + + + + Construct a range of longs + + + + + + + + Construct a range of doubles + + + + + + + + Construct a range of floats + + + + + + + + RepeatAttribute may be applied to test case in order + to run it multiple times. + + + + + Construct a RepeatAttribute + + The number of times to run the test + + + + RequiredAddinAttribute may be used to indicate the names of any addins + that must be present in order to run some or all of the tests in an + assembly. If the addin is not loaded, the entire assembly is marked + as NotRunnable. + + + + + Initializes a new instance of the class. + + The required addin. + + + + Gets the name of required addin. + + The required addin name. + + + + Summary description for SetCultureAttribute. + + + + + Construct given the name of a culture + + + + + + Summary description for SetUICultureAttribute. + + + + + Construct given the name of a culture + + + + + + SetUpAttribute is used in a TestFixture to identify a method + that is called immediately before each test is run. It is + also used in a SetUpFixture to identify the method that is + called once, before any of the subordinate tests are run. + + + + + Attribute used to mark a class that contains one-time SetUp + and/or TearDown methods that apply to all the tests in a + namespace or an assembly. + + + + + Attribute used to mark a static (shared in VB) property + that returns a list of tests. + + + + + Attribute used in a TestFixture to identify a method that is + called immediately after each test is run. It is also used + in a SetUpFixture to identify the method that is called once, + after all subordinate tests have run. In either case, the method + is guaranteed to be called, even if an exception is thrown. + + + + + Provide actions to execute before and after tests. + + + + + When implemented by an attribute, this interface implemented to provide actions to execute before and after tests. + + + + + Executed before each test is run + + Provides details about the test that is going to be run. + + + + Executed after each test is run + + Provides details about the test that has just been run. + + + + Provides the target for the action attribute + + The target for the action attribute + + + + Method called before each test + + Info about the test to be run + + + + Method called after each test + + Info about the test that was just run + + + + Gets or sets the ActionTargets for this attribute + + + + + Adding this attribute to a method within a + class makes the method callable from the NUnit test runner. There is a property + called Description which is optional which you can provide a more detailed test + description. This class cannot be inherited. + + + + [TestFixture] + public class Fixture + { + [Test] + public void MethodToTest() + {} + + [Test(Description = "more detailed description")] + publc void TestDescriptionMethod() + {} + } + + + + + + Descriptive text for this test + + + + + TestCaseAttribute is used to mark parameterized test cases + and provide them with their arguments. + + + + + Construct a TestCaseAttribute with a list of arguments. + This constructor is not CLS-Compliant + + + + + + Construct a TestCaseAttribute with a single argument + + + + + + Construct a TestCaseAttribute with a two arguments + + + + + + + Construct a TestCaseAttribute with a three arguments + + + + + + + + Gets the list of arguments to a test case + + + + + Gets or sets the expected result. Use + ExpectedResult by preference. + + The result. + + + + Gets or sets the expected result. + + The result. + + + + Gets a flag indicating whether an expected + result has been set. + + + + + Gets a list of categories associated with this test; + + + + + Gets or sets the category associated with this test. + May be a single category or a comma-separated list. + + + + + Gets or sets the expected exception. + + The expected exception. + + + + Gets or sets the name the expected exception. + + The expected name of the exception. + + + + Gets or sets the expected message of the expected exception + + The expected message of the exception. + + + + Gets or sets the type of match to be performed on the expected message + + + + + Gets or sets the description. + + The description. + + + + Gets or sets the name of the test. + + The name of the test. + + + + Gets or sets the ignored status of the test + + + + + Gets or sets the ignored status of the test + + + + + Gets or sets the explicit status of the test + + + + + Gets or sets the reason for not running the test + + + + + Gets or sets the reason for not running the test. + Set has the side effect of marking the test as ignored. + + The ignore reason. + + + + FactoryAttribute indicates the source to be used to + provide test cases for a test method. + + + + + Construct with the name of the data source, which must + be a property, field or method of the test class itself. + + An array of the names of the factories that will provide data + + + + Construct with a Type, which must implement IEnumerable + + The Type that will provide data + + + + Construct with a Type and name. + that don't support params arrays. + + The Type that will provide data + The name of the method, property or field that will provide data + + + + The name of a the method, property or fiend to be used as a source + + + + + A Type to be used as a source + + + + + Gets or sets the category associated with this test. + May be a single category or a comma-separated list. + + + + + [TestFixture] + public class ExampleClass + {} + + + + + Default constructor + + + + + Construct with a object[] representing a set of arguments. + In .NET 2.0, the arguments may later be separated into + type arguments and constructor arguments. + + + + + + Descriptive text for this fixture + + + + + Gets and sets the category for this fixture. + May be a comma-separated list of categories. + + + + + Gets a list of categories for this fixture + + + + + The arguments originally provided to the attribute + + + + + Gets or sets a value indicating whether this should be ignored. + + true if ignore; otherwise, false. + + + + Gets or sets the ignore reason. May set Ignored as a side effect. + + The ignore reason. + + + + Get or set the type arguments. If not set + explicitly, any leading arguments that are + Types are taken as type arguments. + + + + + Attribute used to identify a method that is + called before any tests in a fixture are run. + + + + + Attribute used to identify a method that is called after + all the tests in a fixture have run. The method is + guaranteed to be called, even if an exception is thrown. + + + + + Adding this attribute to a method within a + class makes the method callable from the NUnit test runner. There is a property + called Description which is optional which you can provide a more detailed test + description. This class cannot be inherited. + + + + [TestFixture] + public class Fixture + { + [Test] + public void MethodToTest() + {} + + [Test(Description = "more detailed description")] + publc void TestDescriptionMethod() + {} + } + + + + + + Used on a method, marks the test with a timeout value in milliseconds. + The test will be run in a separate thread and is cancelled if the timeout + is exceeded. Used on a method or assembly, sets the default timeout + for all contained test methods. + + + + + Construct a TimeoutAttribute given a time in milliseconds + + The timeout value in milliseconds + + + + Marks a test that must run in the STA, causing it + to run in a separate thread if necessary. + + On methods, you may also use STAThreadAttribute + to serve the same purpose. + + + + + Construct a RequiresSTAAttribute + + + + + Marks a test that must run in the MTA, causing it + to run in a separate thread if necessary. + + On methods, you may also use MTAThreadAttribute + to serve the same purpose. + + + + + Construct a RequiresMTAAttribute + + + + + Marks a test that must run on a separate thread. + + + + + Construct a RequiresThreadAttribute + + + + + Construct a RequiresThreadAttribute, specifying the apartment + + + + + ValueSourceAttribute indicates the source to be used to + provide data for one parameter of a test method. + + + + + Construct with the name of the factory - for use with languages + that don't support params arrays. + + The name of the data source to be used + + + + Construct with a Type and name - for use with languages + that don't support params arrays. + + The Type that will provide data + The name of the method, property or field that will provide data + + + + The name of a the method, property or fiend to be used as a source + + + + + A Type to be used as a source + + + + + AllItemsConstraint applies another constraint to each + item in a collection, succeeding if they all succeed. + + + + + Abstract base class used for prefixes + + + + + The Constraint class is the base of all built-in constraints + within NUnit. It provides the operator overloads used to combine + constraints. + + + + + The IConstraintExpression interface is implemented by all + complete and resolvable constraints and expressions. + + + + + Return the top-level constraint for this expression + + + + + + Static UnsetObject used to detect derived constraints + failing to set the actual value. + + + + + The actual value being tested against a constraint + + + + + The display name of this Constraint for use by ToString() + + + + + Argument fields used by ToString(); + + + + + The builder holding this constraint + + + + + Construct a constraint with no arguments + + + + + Construct a constraint with one argument + + + + + Construct a constraint with two arguments + + + + + Sets the ConstraintBuilder holding this constraint + + + + + Write the failure message to the MessageWriter provided + as an argument. The default implementation simply passes + the constraint and the actual value to the writer, which + then displays the constraint description and the value. + + Constraints that need to provide additional details, + such as where the error occured can override this. + + The MessageWriter on which to display the message + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Test whether the constraint is satisfied by an + ActualValueDelegate that returns the value to be tested. + The default implementation simply evaluates the delegate + but derived classes may override it to provide for delayed + processing. + + An + True for success, false for failure + + + + Test whether the constraint is satisfied by a given reference. + The default implementation simply dereferences the value but + derived classes may override it to provide for delayed processing. + + A reference to the value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + Default override of ToString returns the constraint DisplayName + followed by any arguments within angle brackets. + + + + + + Returns the string representation of this constraint + + + + + This operator creates a constraint that is satisfied only if both + argument constraints are satisfied. + + + + + This operator creates a constraint that is satisfied if either + of the argument constraints is satisfied. + + + + + This operator creates a constraint that is satisfied if the + argument constraint is not satisfied. + + + + + Returns a DelayedConstraint with the specified delay time. + + The delay in milliseconds. + + + + + Returns a DelayedConstraint with the specified delay time + and polling interval. + + The delay in milliseconds. + The interval at which to test the constraint. + + + + + The display name of this Constraint for use by ToString(). + The default value is the name of the constraint with + trailing "Constraint" removed. Derived classes may set + this to another name in their constructors. + + + + + Returns a ConstraintExpression by appending And + to the current constraint. + + + + + Returns a ConstraintExpression by appending And + to the current constraint. + + + + + Returns a ConstraintExpression by appending Or + to the current constraint. + + + + + Class used to detect any derived constraints + that fail to set the actual value in their + Matches override. + + + + + The base constraint + + + + + Construct given a base constraint + + + + + + Construct an AllItemsConstraint on top of an existing constraint + + + + + + Apply the item constraint to each item in the collection, + failing if any item fails. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + AndConstraint succeeds only if both members succeed. + + + + + BinaryConstraint is the abstract base of all constraints + that combine two other constraints in some fashion. + + + + + The first constraint being combined + + + + + The second constraint being combined + + + + + Construct a BinaryConstraint from two other constraints + + The first constraint + The second constraint + + + + Create an AndConstraint from two other constraints + + The first constraint + The second constraint + + + + Apply both member constraints to an actual value, succeeding + succeeding only if both of them succeed. + + The actual value + True if the constraints both succeeded + + + + Write a description for this contraint to a MessageWriter + + The MessageWriter to receive the description + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + AssignableFromConstraint is used to test that an object + can be assigned from a given Type. + + + + + TypeConstraint is the abstract base for constraints + that take a Type as their expected value. + + + + + The expected Type used by the constraint + + + + + Construct a TypeConstraint for a given Type + + + + + + Write the actual value for a failing constraint test to a + MessageWriter. TypeConstraints override this method to write + the name of the type. + + The writer on which the actual value is displayed + + + + Construct an AssignableFromConstraint for the type provided + + + + + + Test whether an object can be assigned from the specified type + + The object to be tested + True if the object can be assigned a value of the expected Type, otherwise false. + + + + Write a description of this constraint to a MessageWriter + + The MessageWriter to use + + + + AssignableToConstraint is used to test that an object + can be assigned to a given Type. + + + + + Construct an AssignableToConstraint for the type provided + + + + + + Test whether an object can be assigned to the specified type + + The object to be tested + True if the object can be assigned a value of the expected Type, otherwise false. + + + + Write a description of this constraint to a MessageWriter + + The MessageWriter to use + + + + AttributeConstraint tests that a specified attribute is present + on a Type or other provider and that the value of the attribute + satisfies some other constraint. + + + + + Constructs an AttributeConstraint for a specified attriute + Type and base constraint. + + + + + + + Determines whether the Type or other provider has the + expected attribute and if its value matches the + additional constraint specified. + + + + + Writes a description of the attribute to the specified writer. + + + + + Writes the actual value supplied to the specified writer. + + + + + Returns a string representation of the constraint. + + + + + AttributeExistsConstraint tests for the presence of a + specified attribute on a Type. + + + + + Constructs an AttributeExistsConstraint for a specific attribute Type + + + + + + Tests whether the object provides the expected attribute. + + A Type, MethodInfo, or other ICustomAttributeProvider + True if the expected attribute is present, otherwise false + + + + Writes the description of the constraint to the specified writer + + + + + BasicConstraint is the abstract base for constraints that + perform a simple comparison to a constant value. + + + + + Initializes a new instance of the class. + + The expected. + The description. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + BinarySerializableConstraint tests whether + an object is serializable in binary format. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + Returns the string representation + + + + + CollectionConstraint is the abstract base class for + constraints that operate on collections. + + + + + Construct an empty CollectionConstraint + + + + + Construct a CollectionConstraint + + + + + + Determines whether the specified enumerable is empty. + + The enumerable. + + true if the specified enumerable is empty; otherwise, false. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Protected method to be implemented by derived classes + + + + + + + CollectionContainsConstraint is used to test whether a collection + contains an expected object as a member. + + + + + CollectionItemsEqualConstraint is the abstract base class for all + collection constraints that apply some notion of item equality + as a part of their operation. + + + + + Construct an empty CollectionConstraint + + + + + Construct a CollectionConstraint + + + + + + Flag the constraint to use the supplied EqualityAdapter. + NOTE: For internal use only. + + The EqualityAdapter to use. + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied Comparison object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Compares two collection members for equality + + + + + Return a new CollectionTally for use in making tests + + The collection to be included in the tally + + + + Flag the constraint to ignore case and return self. + + + + + Construct a CollectionContainsConstraint + + + + + + Test whether the expected item is contained in the collection + + + + + + + Write a descripton of the constraint to a MessageWriter + + + + + + CollectionEquivalentCOnstraint is used to determine whether two + collections are equivalent. + + + + + Construct a CollectionEquivalentConstraint + + + + + + Test whether two collections are equivalent + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + CollectionOrderedConstraint is used to test whether a collection is ordered. + + + + + Construct a CollectionOrderedConstraint + + + + + Modifies the constraint to use an IComparer and returns self. + + + + + Modifies the constraint to use an IComparer<T> and returns self. + + + + + Modifies the constraint to use a Comparison<T> and returns self. + + + + + Modifies the constraint to test ordering by the value of + a specified property and returns self. + + + + + Test whether the collection is ordered + + + + + + + Write a description of the constraint to a MessageWriter + + + + + + Returns the string representation of the constraint. + + + + + + If used performs a reverse comparison + + + + + CollectionSubsetConstraint is used to determine whether + one collection is a subset of another + + + + + Construct a CollectionSubsetConstraint + + The collection that the actual value is expected to be a subset of + + + + Test whether the actual collection is a subset of + the expected collection provided. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + CollectionTally counts (tallies) the number of + occurences of each object in one or more enumerations. + + + + + Construct a CollectionTally object from a comparer and a collection + + + + + Try to remove an object from the tally + + The object to remove + True if successful, false if the object was not found + + + + Try to remove a set of objects from the tally + + The objects to remove + True if successful, false if any object was not found + + + + The number of objects remaining in the tally + + + + + ComparisonAdapter class centralizes all comparisons of + values in NUnit, adapting to the use of any provided + IComparer, IComparer<T> or Comparison<T> + + + + + Returns a ComparisonAdapter that wraps an IComparer + + + + + Returns a ComparisonAdapter that wraps an IComparer<T> + + + + + Returns a ComparisonAdapter that wraps a Comparison<T> + + + + + Compares two objects + + + + + Gets the default ComparisonAdapter, which wraps an + NUnitComparer object. + + + + + Construct a ComparisonAdapter for an IComparer + + + + + Compares two objects + + + + + + + + Construct a default ComparisonAdapter + + + + + ComparisonAdapter<T> extends ComparisonAdapter and + allows use of an IComparer<T> or Comparison<T> + to actually perform the comparison. + + + + + Construct a ComparisonAdapter for an IComparer<T> + + + + + Compare a Type T to an object + + + + + Construct a ComparisonAdapter for a Comparison<T> + + + + + Compare a Type T to an object + + + + + Abstract base class for constraints that compare values to + determine if one is greater than, equal to or less than + the other. This class supplies the Using modifiers. + + + + + ComparisonAdapter to be used in making the comparison + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + + + Modifies the constraint to use an IComparer and returns self + + + + + Modifies the constraint to use an IComparer<T> and returns self + + + + + Modifies the constraint to use a Comparison<T> and returns self + + + + + Delegate used to delay evaluation of the actual value + to be used in evaluating a constraint + + + + + ConstraintBuilder maintains the stacks that are used in + processing a ConstraintExpression. An OperatorStack + is used to hold operators that are waiting for their + operands to be reognized. a ConstraintStack holds + input constraints as well as the results of each + operator applied. + + + + + Initializes a new instance of the class. + + + + + Appends the specified operator to the expression by first + reducing the operator stack and then pushing the new + operator on the stack. + + The operator to push. + + + + Appends the specified constraint to the expresson by pushing + it on the constraint stack. + + The constraint to push. + + + + Sets the top operator right context. + + The right context. + + + + Reduces the operator stack until the topmost item + precedence is greater than or equal to the target precedence. + + The target precedence. + + + + Resolves this instance, returning a Constraint. If the builder + is not currently in a resolvable state, an exception is thrown. + + The resolved constraint + + + + Gets a value indicating whether this instance is resolvable. + + + true if this instance is resolvable; otherwise, false. + + + + + OperatorStack is a type-safe stack for holding ConstraintOperators + + + + + Initializes a new instance of the class. + + The builder. + + + + Pushes the specified operator onto the stack. + + The op. + + + + Pops the topmost operator from the stack. + + + + + + Gets a value indicating whether this is empty. + + true if empty; otherwise, false. + + + + Gets the topmost operator without modifying the stack. + + The top. + + + + ConstraintStack is a type-safe stack for holding Constraints + + + + + Initializes a new instance of the class. + + The builder. + + + + Pushes the specified constraint. As a side effect, + the constraint's builder field is set to the + ConstraintBuilder owning this stack. + + The constraint. + + + + Pops this topmost constrait from the stack. + As a side effect, the constraint's builder + field is set to null. + + + + + + Gets a value indicating whether this is empty. + + true if empty; otherwise, false. + + + + Gets the topmost constraint without modifying the stack. + + The topmost constraint + + + + ConstraintExpression represents a compound constraint in the + process of being constructed from a series of syntactic elements. + + Individual elements are appended to the expression as they are + reognized. Once an actual Constraint is appended, the expression + returns a resolvable Constraint. + + + + + ConstraintExpressionBase is the abstract base class for the + ConstraintExpression class, which represents a + compound constraint in the process of being constructed + from a series of syntactic elements. + + NOTE: ConstraintExpressionBase is separate because the + ConstraintExpression class was generated in earlier + versions of NUnit. The two classes may be combined + in a future version. + + + + + The ConstraintBuilder holding the elements recognized so far + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the + class passing in a ConstraintBuilder, which may be pre-populated. + + The builder. + + + + Returns a string representation of the expression as it + currently stands. This should only be used for testing, + since it has the side-effect of resolving the expression. + + + + + + Appends an operator to the expression and returns the + resulting expression itself. + + + + + Appends a self-resolving operator to the expression and + returns a new ResolvableConstraintExpression. + + + + + Appends a constraint to the expression and returns that + constraint, which is associated with the current state + of the expression being built. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the + class passing in a ConstraintBuilder, which may be pre-populated. + + The builder. + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding only if a specified number of them succeed. + + + + + Returns a new PropertyConstraintExpression, which will either + test for the existence of the named property on the object + being tested or apply any following constraint to that property. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns the constraint provided as an argument - used to allow custom + custom constraints to easily participate in the syntax. + + + + + Returns the constraint provided as an argument - used to allow custom + custom constraints to easily participate in the syntax. + + + + + Returns a constraint that tests two items for equality + + + + + Returns a constraint that tests that two references are the same object + + + + + Returns a constraint that tests whether the + actual value is greater than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a collection containing the same elements as the + collection supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a subset of the collection supplied as an argument. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a new ContainsConstraint. This constraint + will, in turn, make use of the appropriate second-level + constraint, depending on the type of the actual argument. + This overload is only used if the item sought is a string, + since any other type implies that we are looking for a + collection member. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the regular expression supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the regular expression supplied as an argument. + + + + + Returns a constraint that tests whether the path provided + is the same as an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is the same path or under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is the same path or under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the actual value falls + within a specified range. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if at least one of them succeeds. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them fail. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Length property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Count property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Message property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the InnerException property of the object being tested. + + + + + With is currently a NOP - reserved for future use. + + + + + Returns a constraint that tests for null + + + + + Returns a constraint that tests for True + + + + + Returns a constraint that tests for False + + + + + Returns a constraint that tests for a positive value + + + + + Returns a constraint that tests for a negative value + + + + + Returns a constraint that tests for NaN + + + + + Returns a constraint that tests for empty + + + + + Returns a constraint that tests whether a collection + contains all unique items. + + + + + Returns a constraint that tests whether an object graph is serializable in binary format. + + + + + Returns a constraint that tests whether an object graph is serializable in xml format. + + + + + Returns a constraint that tests whether a collection is ordered + + + + + ContainsConstraint tests a whether a string contains a substring + or a collection contains an object. It postpones the decision of + which test to use until the type of the actual argument is known. + This allows testing whether a string is contained in a collection + or as a substring of another string using the same syntax. + + + + + Initializes a new instance of the class. + + The expected. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied Comparison object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to ignore case and return self. + + + + + Applies a delay to the match so that a match can be evaluated in the future. + + + + + Creates a new DelayedConstraint + + The inner constraint two decorate + The time interval after which the match is performed + If the value of is less than 0 + + + + Creates a new DelayedConstraint + + The inner constraint two decorate + The time interval after which the match is performed + The time interval used for polling + If the value of is less than 0 + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for if the base constraint fails, false if it succeeds + + + + Test whether the constraint is satisfied by a delegate + + The delegate whose value is to be tested + True for if the base constraint fails, false if it succeeds + + + + Test whether the constraint is satisfied by a given reference. + Overridden to wait for the specified delay period before + calling the base constraint with the dereferenced value. + + A reference to the value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a MessageWriter. + + The writer on which the actual value is displayed + + + + Returns the string representation of the constraint. + + + + + EmptyCollectionConstraint tests whether a collection is empty. + + + + + Check that the collection is empty + + + + + + + Write the constraint description to a MessageWriter + + + + + + EmptyConstraint tests a whether a string or collection is empty, + postponing the decision about which test is applied until the + type of the actual argument is known. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + EmptyDirectoryConstraint is used to test that a directory is empty + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + EmptyStringConstraint tests whether a string is empty. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + EndsWithConstraint can test whether a string ends + with an expected substring. + + + + + StringConstraint is the abstract base for constraints + that operate on strings. It supports the IgnoreCase + modifier for string operations. + + + + + The expected value + + + + + Indicates whether tests should be case-insensitive + + + + + Constructs a StringConstraint given an expected value + + The expected value + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Test whether the constraint is satisfied by a given string + + The string to be tested + True for success, false for failure + + + + Modify the constraint to ignore case in matching. + + + + + Initializes a new instance of the class. + + The expected string + + + + Test whether the constraint is matched by the actual value. + This is a template method, which calls the IsMatch method + of the derived class. + + + + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + EqualConstraint is able to compare an actual value with the + expected value provided in its constructor. Two objects are + considered equal if both are null, or if both have the same + value. NUnit has special semantics for some object types. + + + + + If true, strings in error messages will be clipped + + + + + NUnitEqualityComparer used to test equality. + + + + + Initializes a new instance of the class. + + The expected value. + + + + Flag the constraint to use a tolerance when determining equality. + + Tolerance value to be used + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied Comparison object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write a failure message. Overridden to provide custom + failure messages for EqualConstraint. + + The MessageWriter to write to + + + + Write description of this constraint + + The MessageWriter to write to + + + + Display the failure information for two collections that did not match. + + The MessageWriter on which to display + The expected collection. + The actual collection + The depth of this failure in a set of nested collections + + + + Displays a single line showing the types and sizes of the expected + and actual enumerations, collections or arrays. If both are identical, + the value is only shown once. + + The MessageWriter on which to display + The expected collection or array + The actual collection or array + The indentation level for the message line + + + + Displays a single line showing the point in the expected and actual + arrays at which the comparison failed. If the arrays have different + structures or dimensions, both values are shown. + + The MessageWriter on which to display + The expected array + The actual array + Index of the failure point in the underlying collections + The indentation level for the message line + + + + Display the failure information for two IEnumerables that did not match. + + The MessageWriter on which to display + The expected enumeration. + The actual enumeration + The depth of this failure in a set of nested collections + + + + Flag the constraint to ignore case and return self. + + + + + Flag the constraint to suppress string clipping + and return self. + + + + + Flag the constraint to compare arrays as collections + and return self. + + + + + Switches the .Within() modifier to interpret its tolerance as + a distance in representable values (see remarks). + + Self. + + Ulp stands for "unit in the last place" and describes the minimum + amount a given value can change. For any integers, an ulp is 1 whole + digit. For floating point values, the accuracy of which is better + for smaller numbers and worse for larger numbers, an ulp depends + on the size of the number. Using ulps for comparison of floating + point results instead of fixed tolerances is safer because it will + automatically compensate for the added inaccuracy of larger numbers. + + + + + Switches the .Within() modifier to interpret its tolerance as + a percentage that the actual values is allowed to deviate from + the expected value. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in days. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in hours. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in minutes. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in seconds. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in milliseconds. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in clock ticks. + + Self + + + + EqualityAdapter class handles all equality comparisons + that use an IEqualityComparer, IEqualityComparer<T> + or a ComparisonAdapter. + + + + + Compares two objects, returning true if they are equal + + + + + Returns true if the two objects can be compared by this adapter. + The base adapter cannot handle IEnumerables except for strings. + + + + + Returns an EqualityAdapter that wraps an IComparer. + + + + + Returns an EqualityAdapter that wraps an IEqualityComparer. + + + + + Returns an EqualityAdapter that wraps an IEqualityComparer<T>. + + + + + Returns an EqualityAdapter that wraps an IComparer<T>. + + + + + Returns an EqualityAdapter that wraps a Comparison<T>. + + + + + EqualityAdapter that wraps an IComparer. + + + + + Returns true if the two objects can be compared by this adapter. + Generic adapter requires objects of the specified type. + + + + + EqualityAdapter that wraps an IComparer. + + + + + EqualityAdapterList represents a list of EqualityAdapters + in a common class across platforms. + + + + + ExactCountConstraint applies another constraint to each + item in a collection, succeeding only if a specified + number of items succeed. + + + + + Construct an ExactCountConstraint on top of an existing constraint + + + + + + + Apply the item constraint to each item in the collection, + succeeding only if the expected number of items pass. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + ExactTypeConstraint is used to test that an object + is of the exact type provided in the constructor + + + + + Construct an ExactTypeConstraint for a given Type + + The expected Type. + + + + Test that an object is of the exact type specified + + The actual value. + True if the tested object is of the exact type provided, otherwise false. + + + + Write the description of this constraint to a MessageWriter + + The MessageWriter to use + + + + ExceptionTypeConstraint is a special version of ExactTypeConstraint + used to provided detailed info about the exception thrown in + an error message. + + + + + Constructs an ExceptionTypeConstraint + + + + + Write the actual value for a failing constraint test to a + MessageWriter. Overriden to write additional information + in the case of an Exception. + + The MessageWriter to use + + + + FailurePoint class represents one point of failure + in an equality test. + + + + + The location of the failure + + + + + The expected value + + + + + The actual value + + + + + Indicates whether the expected value is valid + + + + + Indicates whether the actual value is valid + + + + + FailurePointList represents a set of FailurePoints + in a cross-platform way. + + + + + FalseConstraint tests that the actual value is false + + + + + Initializes a new instance of the class. + + + + Helper routines for working with floating point numbers + + + The floating point comparison code is based on this excellent article: + http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm + + + "ULP" means Unit in the Last Place and in the context of this library refers to + the distance between two adjacent floating point numbers. IEEE floating point + numbers can only represent a finite subset of natural numbers, with greater + accuracy for smaller numbers and lower accuracy for very large numbers. + + + If a comparison is allowed "2 ulps" of deviation, that means the values are + allowed to deviate by up to 2 adjacent floating point values, which might be + as low as 0.0000001 for small numbers or as high as 10.0 for large numbers. + + + + + Compares two floating point values for equality + First floating point value to be compared + Second floating point value t be compared + + Maximum number of representable floating point values that are allowed to + be between the left and the right floating point values + + True if both numbers are equal or close to being equal + + + Floating point values can only represent a finite subset of natural numbers. + For example, the values 2.00000000 and 2.00000024 can be stored in a float, + but nothing inbetween them. + + + This comparison will count how many possible floating point values are between + the left and the right number. If the number of possible values between both + numbers is less than or equal to maxUlps, then the numbers are considered as + being equal. + + + Implementation partially follows the code outlined here: + http://www.anttirt.net/2007/08/19/proper-floating-point-comparisons/ + + + + + Compares two double precision floating point values for equality + First double precision floating point value to be compared + Second double precision floating point value t be compared + + Maximum number of representable double precision floating point values that are + allowed to be between the left and the right double precision floating point values + + True if both numbers are equal or close to being equal + + + Double precision floating point values can only represent a limited series of + natural numbers. For example, the values 2.0000000000000000 and 2.0000000000000004 + can be stored in a double, but nothing inbetween them. + + + This comparison will count how many possible double precision floating point + values are between the left and the right number. If the number of possible + values between both numbers is less than or equal to maxUlps, then the numbers + are considered as being equal. + + + Implementation partially follows the code outlined here: + http://www.anttirt.net/2007/08/19/proper-floating-point-comparisons/ + + + + + + Reinterprets the memory contents of a floating point value as an integer value + + + Floating point value whose memory contents to reinterpret + + + The memory contents of the floating point value interpreted as an integer + + + + + Reinterprets the memory contents of a double precision floating point + value as an integer value + + + Double precision floating point value whose memory contents to reinterpret + + + The memory contents of the double precision floating point value + interpreted as an integer + + + + + Reinterprets the memory contents of an integer as a floating point value + + Integer value whose memory contents to reinterpret + + The memory contents of the integer value interpreted as a floating point value + + + + + Reinterprets the memory contents of an integer value as a double precision + floating point value + + Integer whose memory contents to reinterpret + + The memory contents of the integer interpreted as a double precision + floating point value + + + + Union of a floating point variable and an integer + + + The union's value as a floating point variable + + + The union's value as an integer + + + The union's value as an unsigned integer + + + Union of a double precision floating point variable and a long + + + The union's value as a double precision floating point variable + + + The union's value as a long + + + The union's value as an unsigned long + + + + Tests whether a value is greater than the value supplied to its constructor + + + + + The value against which a comparison is to be made + + + + + Initializes a new instance of the class. + + The expected value. + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Tests whether a value is greater than or equal to the value supplied to its constructor + + + + + The value against which a comparison is to be made + + + + + Initializes a new instance of the class. + + The expected value. + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + InstanceOfTypeConstraint is used to test that an object + is of the same type provided or derived from it. + + + + + Construct an InstanceOfTypeConstraint for the type provided + + The expected Type + + + + Test whether an object is of the specified type or a derived type + + The object to be tested + True if the object is of the provided type or derives from it, otherwise false. + + + + Write a description of this constraint to a MessageWriter + + The MessageWriter to use + + + + Tests whether a value is less than the value supplied to its constructor + + + + + The value against which a comparison is to be made + + + + + Initializes a new instance of the class. + + The expected value. + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Tests whether a value is less than or equal to the value supplied to its constructor + + + + + The value against which a comparison is to be made + + + + + Initializes a new instance of the class. + + The expected value. + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Static methods used in creating messages + + + + + Static string used when strings are clipped + + + + + Returns the representation of a type as used in NUnitLite. + This is the same as Type.ToString() except for arrays, + which are displayed with their declared sizes. + + + + + + + Converts any control characters in a string + to their escaped representation. + + The string to be converted + The converted string + + + + Return the a string representation for a set of indices into an array + + Array of indices for which a string is needed + + + + Get an array of indices representing the point in a enumerable, + collection or array corresponding to a single int index into the + collection. + + The collection to which the indices apply + Index in the collection + Array of indices + + + + Clip a string to a given length, starting at a particular offset, returning the clipped + string with ellipses representing the removed parts + + The string to be clipped + The maximum permitted length of the result string + The point at which to start clipping + The clipped string + + + + Clip the expected and actual strings in a coordinated fashion, + so that they may be displayed together. + + + + + + + + + Shows the position two strings start to differ. Comparison + starts at the start index. + + The expected string + The actual string + The index in the strings at which comparison should start + Boolean indicating whether case should be ignored + -1 if no mismatch found, or the index where mismatch found + + + + NaNConstraint tests that the actual value is a double or float NaN + + + + + Test that the actual value is an NaN + + + + + + + Write the constraint description to a specified writer + + + + + + NoItemConstraint applies another constraint to each + item in a collection, failing if any of them succeeds. + + + + + Construct a NoItemConstraint on top of an existing constraint + + + + + + Apply the item constraint to each item in the collection, + failing if any item fails. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + NotConstraint negates the effect of some other constraint + + + + + Initializes a new instance of the class. + + The base constraint to be negated. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for if the base constraint fails, false if it succeeds + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a MessageWriter. + + The writer on which the actual value is displayed + + + + NullConstraint tests that the actual value is null + + + + + Initializes a new instance of the class. + + + + + NullEmptyStringConstraint tests whether a string is either null or empty. + + + + + Constructs a new NullOrEmptyStringConstraint + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + The Numerics class contains common operations on numeric values. + + + + + Checks the type of the object, returning true if + the object is a numeric type. + + The object to check + true if the object is a numeric type + + + + Checks the type of the object, returning true if + the object is a floating point numeric type. + + The object to check + true if the object is a floating point numeric type + + + + Checks the type of the object, returning true if + the object is a fixed point numeric type. + + The object to check + true if the object is a fixed point numeric type + + + + Test two numeric values for equality, performing the usual numeric + conversions and using a provided or default tolerance. If the tolerance + provided is Empty, this method may set it to a default tolerance. + + The expected value + The actual value + A reference to the tolerance in effect + True if the values are equal + + + + Compare two numeric values, performing the usual numeric conversions. + + The expected value + The actual value + The relationship of the values to each other + + + + NUnitComparer encapsulates NUnit's default behavior + in comparing two objects. + + + + + Compares two objects + + + + + + + + Returns the default NUnitComparer. + + + + + Generic version of NUnitComparer + + + + + + Compare two objects of the same type + + + + + NUnitEqualityComparer encapsulates NUnit's handling of + equality tests between objects. + + + + + + + + + + Compares two objects for equality within a tolerance + + The first object to compare + The second object to compare + The tolerance to use in the comparison + + + + + If true, all string comparisons will ignore case + + + + + If true, arrays will be treated as collections, allowing + those of different dimensions to be compared + + + + + Comparison objects used in comparisons for some constraints. + + + + + List of points at which a failure occured. + + + + + RecursionDetector used to check for recursion when + evaluating self-referencing enumerables. + + + + + Compares two objects for equality within a tolerance, setting + the tolerance to the actual tolerance used if an empty + tolerance is supplied. + + + + + Helper method to compare two arrays + + + + + Method to compare two DirectoryInfo objects + + first directory to compare + second directory to compare + true if equivalent, false if not + + + + Returns the default NUnitEqualityComparer + + + + + Gets and sets a flag indicating whether case should + be ignored in determining equality. + + + + + Gets and sets a flag indicating that arrays should be + compared as collections, without regard to their shape. + + + + + Gets the list of external comparers to be used to + test for equality. They are applied to members of + collections, in place of NUnit's own logic. + + + + + Gets the list of failure points for the last Match performed. + The list consists of objects to be interpreted by the caller. + This generally means that the caller may only make use of + objects it has placed on the list at a particular depthy. + + + + + RecursionDetector detects when a comparison + between two enumerables has reached a point + where the same objects that were previously + compared are again being compared. This allows + the caller to stop the comparison if desired. + + + + + Check whether two objects have previously + been compared, returning true if they have. + The two objects are remembered, so that a + second call will always return true. + + + + + OrConstraint succeeds if either member succeeds + + + + + Create an OrConstraint from two other constraints + + The first constraint + The second constraint + + + + Apply the member constraints to an actual value, succeeding + succeeding as soon as one of them succeeds. + + The actual value + True if either constraint succeeded + + + + Write a description for this contraint to a MessageWriter + + The MessageWriter to receive the description + + + + PathConstraint serves as the abstract base of constraints + that operate on paths and provides several helper methods. + + + + + The expected path used in the constraint + + + + + Flag indicating whether a caseInsensitive comparison should be made + + + + + Construct a PathConstraint for a give expected path + + The expected path + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Returns true if the expected path and actual path match + + + + + Returns the string representation of this constraint + + + + + Transform the provided path to its canonical form so that it + may be more easily be compared with other paths. + + The original path + The path in canonical form + + + + Test whether one path in canonical form is under another. + + The first path - supposed to be the parent path + The second path - supposed to be the child path + Indicates whether case should be ignored + + + + + Modifies the current instance to be case-insensitve + and returns it. + + + + + Modifies the current instance to be case-sensitve + and returns it. + + + + + Predicate constraint wraps a Predicate in a constraint, + returning success if the predicate is true. + + + + + Construct a PredicateConstraint from a predicate + + + + + Determines whether the predicate succeeds when applied + to the actual value. + + + + + Writes the description to a MessageWriter + + + + + PropertyConstraint extracts a named property and uses + its value as the actual value for a chained constraint. + + + + + Initializes a new instance of the class. + + The name. + The constraint to apply to the property. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + Returns the string representation of the constraint. + + + + + + PropertyExistsConstraint tests that a named property + exists on the object provided through Match. + + Originally, PropertyConstraint provided this feature + in addition to making optional tests on the vaue + of the property. The two constraints are now separate. + + + + + Initializes a new instance of the class. + + The name of the property. + + + + Test whether the property exists for a given object + + The object to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. + + The writer on which the actual value is displayed + + + + Returns the string representation of the constraint. + + + + + + RangeConstraint tests whether two values are within a + specified range. + + + + + Initializes a new instance of the class. + + From. + To. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + RegexConstraint can test whether a string matches + the pattern provided. + + + + + Initializes a new instance of the class. + + The pattern. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + ResolvableConstraintExpression is used to represent a compound + constraint being constructed at a point where the last operator + may either terminate the expression or may have additional + qualifying constraints added to it. + + It is used, for example, for a Property element or for + an Exception element, either of which may be optionally + followed by constraints that apply to the property or + exception. + + + + + Create a new instance of ResolvableConstraintExpression + + + + + Create a new instance of ResolvableConstraintExpression, + passing in a pre-populated ConstraintBuilder. + + + + + Resolve the current expression to a Constraint + + + + + This operator creates a constraint that is satisfied only if both + argument constraints are satisfied. + + + + + This operator creates a constraint that is satisfied only if both + argument constraints are satisfied. + + + + + This operator creates a constraint that is satisfied only if both + argument constraints are satisfied. + + + + + This operator creates a constraint that is satisfied if either + of the argument constraints is satisfied. + + + + + This operator creates a constraint that is satisfied if either + of the argument constraints is satisfied. + + + + + This operator creates a constraint that is satisfied if either + of the argument constraints is satisfied. + + + + + This operator creates a constraint that is satisfied if the + argument constraint is not satisfied. + + + + + Appends an And Operator to the expression + + + + + Appends an Or operator to the expression. + + + + + ReusableConstraint wraps a constraint expression after + resolving it so that it can be reused consistently. + + + + + Construct a ReusableConstraint from a constraint expression + + The expression to be resolved and reused + + + + Converts a constraint to a ReusableConstraint + + The constraint to be converted + A ReusableConstraint + + + + Returns the string representation of the constraint. + + A string representing the constraint + + + + Resolves the ReusableConstraint by returning the constraint + that it originally wrapped. + + A resolved constraint + + + + SameAsConstraint tests whether an object is identical to + the object passed to its constructor + + + + + Initializes a new instance of the class. + + The expected object. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Summary description for SamePathConstraint. + + + + + Initializes a new instance of the class. + + The expected path + + + + Test whether the constraint is satisfied by a given value + + The expected path + The actual path + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + SamePathOrUnderConstraint tests that one path is under another + + + + + Initializes a new instance of the class. + + The expected path + + + + Test whether the constraint is satisfied by a given value + + The expected path + The actual path + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + SomeItemsConstraint applies another constraint to each + item in a collection, succeeding if any of them succeeds. + + + + + Construct a SomeItemsConstraint on top of an existing constraint + + + + + + Apply the item constraint to each item in the collection, + succeeding if any item succeeds. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + StartsWithConstraint can test whether a string starts + with an expected substring. + + + + + Initializes a new instance of the class. + + The expected string + + + + Test whether the constraint is matched by the actual value. + This is a template method, which calls the IsMatch method + of the derived class. + + + + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + SubPathConstraint tests that the actual path is under the expected path + + + + + Initializes a new instance of the class. + + The expected path + + + + Test whether the constraint is satisfied by a given value + + The expected path + The actual path + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + SubstringConstraint can test whether a string contains + the expected substring. + + + + + Initializes a new instance of the class. + + The expected. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + ThrowsConstraint is used to test the exception thrown by + a delegate by applying a constraint to it. + + + + + Initializes a new instance of the class, + using a constraint to be applied to the exception. + + A constraint to apply to the caught exception. + + + + Executes the code of the delegate and captures any exception. + If a non-null base constraint was provided, it applies that + constraint to the exception. + + A delegate representing the code to be tested + True if an exception is thrown and the constraint succeeds, otherwise false + + + + Converts an ActualValueDelegate to a TestDelegate + before calling the primary overload. + + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + Returns the string representation of this constraint + + + + + Get the actual exception thrown - used by Assert.Throws. + + + + + ThrowsNothingConstraint tests that a delegate does not + throw an exception. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True if no exception is thrown, otherwise false + + + + Test whether the constraint is satisfied by a given delegate + + Delegate returning the value to be tested + True if no exception is thrown, otherwise false + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. Overridden in ThrowsNothingConstraint to write + information about the exception that was actually caught. + + The writer on which the actual value is displayed + + + + The Tolerance class generalizes the notion of a tolerance + within which an equality test succeeds. Normally, it is + used with numeric types, but it can be used with any + type that supports taking a difference between two + objects and comparing that difference to a value. + + + + + Constructs a linear tolerance of a specdified amount + + + + + Constructs a tolerance given an amount and ToleranceMode + + + + + Tests that the current Tolerance is linear with a + numeric value, throwing an exception if it is not. + + + + + Returns an empty Tolerance object, equivalent to + specifying no tolerance. In most cases, it results + in an exact match but for floats and doubles a + default tolerance may be used. + + + + + Returns a zero Tolerance object, equivalent to + specifying an exact match. + + + + + Gets the ToleranceMode for the current Tolerance + + + + + Gets the value of the current Tolerance instance. + + + + + Returns a new tolerance, using the current amount as a percentage. + + + + + Returns a new tolerance, using the current amount in Ulps. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of days. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of hours. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of minutes. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of seconds. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of milliseconds. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of clock ticks. + + + + + Returns true if the current tolerance is empty. + + + + + Modes in which the tolerance value for a comparison can be interpreted. + + + + + The tolerance was created with a value, without specifying + how the value would be used. This is used to prevent setting + the mode more than once and is generally changed to Linear + upon execution of the test. + + + + + The tolerance is used as a numeric range within which + two compared values are considered to be equal. + + + + + Interprets the tolerance as the percentage by which + the two compared values my deviate from each other. + + + + + Compares two values based in their distance in + representable numbers. + + + + + TrueConstraint tests that the actual value is true + + + + + Initializes a new instance of the class. + + + + + UniqueItemsConstraint tests whether all the items in a + collection are unique. + + + + + Check that all items are unique. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + XmlSerializableConstraint tests whether + an object is serializable in XML format. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + Returns the string representation of this constraint + + + + + Represents a constraint that succeeds if all the + members of a collection match a base constraint. + + + + + Abstract base for operators that indicate how to + apply a constraint to items in a collection. + + + + + PrefixOperator takes a single constraint and modifies + it's action in some way. + + + + + The ConstraintOperator class is used internally by a + ConstraintBuilder to represent an operator that + modifies or combines constraints. + + Constraint operators use left and right precedence + values to determine whether the top operator on the + stack should be reduced before pushing a new operator. + + + + + The precedence value used when the operator + is about to be pushed to the stack. + + + + + The precedence value used when the operator + is on the top of the stack. + + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + + The syntax element preceding this operator + + + + + The syntax element folowing this operator + + + + + The precedence value used when the operator + is about to be pushed to the stack. + + + + + The precedence value used when the operator + is on the top of the stack. + + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + + Returns the constraint created by applying this + prefix to another constraint. + + + + + + + Constructs a CollectionOperator + + + + + Returns a constraint that will apply the argument + to the members of a collection, succeeding if + they all succeed. + + + + + Operator that requires both it's arguments to succeed + + + + + Abstract base class for all binary operators + + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + + Abstract method that produces a constraint by applying + the operator to its left and right constraint arguments. + + + + + Gets the left precedence of the operator + + + + + Gets the right precedence of the operator + + + + + Construct an AndOperator + + + + + Apply the operator to produce an AndConstraint + + + + + Operator that tests for the presence of a particular attribute + on a type and optionally applies further tests to the attribute. + + + + + Abstract base class for operators that are able to reduce to a + constraint whether or not another syntactic element follows. + + + + + Construct an AttributeOperator for a particular Type + + The Type of attribute tested + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + Represents a constraint that succeeds if the specified + count of members of a collection match a base constraint. + + + + + Construct an ExactCountOperator for a specified count + + The expected count + + + + Returns a constraint that will apply the argument + to the members of a collection, succeeding if + none of them succeed. + + + + + Represents a constraint that succeeds if none of the + members of a collection match a base constraint. + + + + + Returns a constraint that will apply the argument + to the members of a collection, succeeding if + none of them succeed. + + + + + Negates the test of the constraint it wraps. + + + + + Constructs a new NotOperator + + + + + Returns a NotConstraint applied to its argument. + + + + + Operator that requires at least one of it's arguments to succeed + + + + + Construct an OrOperator + + + + + Apply the operator to produce an OrConstraint + + + + + Operator used to test for the presence of a named Property + on an object and optionally apply further tests to the + value of that property. + + + + + Constructs a PropOperator for a particular named property + + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + + Gets the name of the property to which the operator applies + + + + + Represents a constraint that succeeds if any of the + members of a collection match a base constraint. + + + + + Returns a constraint that will apply the argument + to the members of a collection, succeeding if + any of them succeed. + + + + + Operator that tests that an exception is thrown and + optionally applies further tests to the exception. + + + + + Construct a ThrowsOperator + + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + Represents a constraint that simply wraps the + constraint provided as an argument, without any + further functionality, but which modifes the + order of evaluation because of its precedence. + + + + + Constructor for the WithOperator + + + + + Returns a constraint that wraps its argument + + + + + Thrown when an assertion failed. + + + + The error message that explains + the reason for the exception + + + The error message that explains + the reason for the exception + The exception that caused the + current exception + + + + Serialization Constructor + + + + + Thrown when an assertion failed. + + + + + + + The error message that explains + the reason for the exception + The exception that caused the + current exception + + + + Serialization Constructor + + + + + Thrown when a test executes inconclusively. + + + + The error message that explains + the reason for the exception + + + The error message that explains + the reason for the exception + The exception that caused the + current exception + + + + Serialization Constructor + + + + + Thrown when an assertion failed. + + + + + + + The error message that explains + the reason for the exception + The exception that caused the + current exception + + + + Serialization Constructor + + + + + + + + + + + Compares two objects of a given Type for equality within a tolerance + + The first object to compare + The second object to compare + The tolerance to use in the comparison + + + + diff --git a/Externals/NUnit/framework/nunit.mocks.dll b/Externals/NUnit/framework/nunit.mocks.dll new file mode 100644 index 0000000000..bbad40e4e Binary files /dev/null and b/Externals/NUnit/framework/nunit.mocks.dll differ diff --git a/Externals/NUnit/framework/pnunit.framework.dll b/Externals/NUnit/framework/pnunit.framework.dll new file mode 100644 index 0000000000..1fca36829 Binary files /dev/null and b/Externals/NUnit/framework/pnunit.framework.dll differ diff --git a/Externals/NUnit/launcher.log.conf b/Externals/NUnit/launcher.log.conf new file mode 100644 index 0000000000..6a9ced8b0 --- /dev/null +++ b/Externals/NUnit/launcher.log.conf @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/Externals/NUnit/lib/Images/Ellipsis.gif b/Externals/NUnit/lib/Images/Ellipsis.gif new file mode 100644 index 0000000000..e11f26b6e Binary files /dev/null and b/Externals/NUnit/lib/Images/Ellipsis.gif differ diff --git a/Externals/NUnit/lib/Images/Tree/Circles/Failure.jpg b/Externals/NUnit/lib/Images/Tree/Circles/Failure.jpg new file mode 100644 index 0000000000..c245548b9 Binary files /dev/null and b/Externals/NUnit/lib/Images/Tree/Circles/Failure.jpg differ diff --git a/Externals/NUnit/lib/Images/Tree/Circles/Ignored.jpg b/Externals/NUnit/lib/Images/Tree/Circles/Ignored.jpg new file mode 100644 index 0000000000..0549b7058 Binary files /dev/null and b/Externals/NUnit/lib/Images/Tree/Circles/Ignored.jpg differ diff --git a/Externals/NUnit/lib/Images/Tree/Circles/Inconclusive.jpg b/Externals/NUnit/lib/Images/Tree/Circles/Inconclusive.jpg new file mode 100644 index 0000000000..8d36153cd Binary files /dev/null and b/Externals/NUnit/lib/Images/Tree/Circles/Inconclusive.jpg differ diff --git a/Externals/NUnit/lib/Images/Tree/Circles/Skipped.jpg b/Externals/NUnit/lib/Images/Tree/Circles/Skipped.jpg new file mode 100644 index 0000000000..3d84255cc Binary files /dev/null and b/Externals/NUnit/lib/Images/Tree/Circles/Skipped.jpg differ diff --git a/Externals/NUnit/lib/Images/Tree/Circles/Success.jpg b/Externals/NUnit/lib/Images/Tree/Circles/Success.jpg new file mode 100644 index 0000000000..15ec1b7fb Binary files /dev/null and b/Externals/NUnit/lib/Images/Tree/Circles/Success.jpg differ diff --git a/Externals/NUnit/lib/Images/Tree/Classic/Failure.jpg b/Externals/NUnit/lib/Images/Tree/Classic/Failure.jpg new file mode 100644 index 0000000000..658905fd9 Binary files /dev/null and b/Externals/NUnit/lib/Images/Tree/Classic/Failure.jpg differ diff --git a/Externals/NUnit/lib/Images/Tree/Classic/Ignored.jpg b/Externals/NUnit/lib/Images/Tree/Classic/Ignored.jpg new file mode 100644 index 0000000000..95b7fdbd1 Binary files /dev/null and b/Externals/NUnit/lib/Images/Tree/Classic/Ignored.jpg differ diff --git a/Externals/NUnit/lib/Images/Tree/Classic/Inconclusive.jpg b/Externals/NUnit/lib/Images/Tree/Classic/Inconclusive.jpg new file mode 100644 index 0000000000..32a0ff72f Binary files /dev/null and b/Externals/NUnit/lib/Images/Tree/Classic/Inconclusive.jpg differ diff --git a/Externals/NUnit/lib/Images/Tree/Classic/Skipped.jpg b/Externals/NUnit/lib/Images/Tree/Classic/Skipped.jpg new file mode 100644 index 0000000000..3d84255cc Binary files /dev/null and b/Externals/NUnit/lib/Images/Tree/Classic/Skipped.jpg differ diff --git a/Externals/NUnit/lib/Images/Tree/Classic/Success.jpg b/Externals/NUnit/lib/Images/Tree/Classic/Success.jpg new file mode 100644 index 0000000000..3d8e76092 Binary files /dev/null and b/Externals/NUnit/lib/Images/Tree/Classic/Success.jpg differ diff --git a/Externals/NUnit/lib/Images/Tree/Default/Failure.png b/Externals/NUnit/lib/Images/Tree/Default/Failure.png new file mode 100644 index 0000000000..2e400b276 Binary files /dev/null and b/Externals/NUnit/lib/Images/Tree/Default/Failure.png differ diff --git a/Externals/NUnit/lib/Images/Tree/Default/Ignored.png b/Externals/NUnit/lib/Images/Tree/Default/Ignored.png new file mode 100644 index 0000000000..05715cbbc Binary files /dev/null and b/Externals/NUnit/lib/Images/Tree/Default/Ignored.png differ diff --git a/Externals/NUnit/lib/Images/Tree/Default/Inconclusive.png b/Externals/NUnit/lib/Images/Tree/Default/Inconclusive.png new file mode 100644 index 0000000000..4807b7ced Binary files /dev/null and b/Externals/NUnit/lib/Images/Tree/Default/Inconclusive.png differ diff --git a/Externals/NUnit/lib/Images/Tree/Default/Skipped.png b/Externals/NUnit/lib/Images/Tree/Default/Skipped.png new file mode 100644 index 0000000000..7c9fc64e3 Binary files /dev/null and b/Externals/NUnit/lib/Images/Tree/Default/Skipped.png differ diff --git a/Externals/NUnit/lib/Images/Tree/Default/Success.png b/Externals/NUnit/lib/Images/Tree/Default/Success.png new file mode 100644 index 0000000000..2a301508c Binary files /dev/null and b/Externals/NUnit/lib/Images/Tree/Default/Success.png differ diff --git a/Externals/NUnit/lib/Images/Tree/Visual Studio/Failure.png b/Externals/NUnit/lib/Images/Tree/Visual Studio/Failure.png new file mode 100644 index 0000000000..ba03e8485 Binary files /dev/null and b/Externals/NUnit/lib/Images/Tree/Visual Studio/Failure.png differ diff --git a/Externals/NUnit/lib/Images/Tree/Visual Studio/Ignored.png b/Externals/NUnit/lib/Images/Tree/Visual Studio/Ignored.png new file mode 100644 index 0000000000..9271d6e75 Binary files /dev/null and b/Externals/NUnit/lib/Images/Tree/Visual Studio/Ignored.png differ diff --git a/Externals/NUnit/lib/Images/Tree/Visual Studio/Inconclusive.png b/Externals/NUnit/lib/Images/Tree/Visual Studio/Inconclusive.png new file mode 100644 index 0000000000..76219b5c0 Binary files /dev/null and b/Externals/NUnit/lib/Images/Tree/Visual Studio/Inconclusive.png differ diff --git a/Externals/NUnit/lib/Images/Tree/Visual Studio/SeriousWarning.png b/Externals/NUnit/lib/Images/Tree/Visual Studio/SeriousWarning.png new file mode 100644 index 0000000000..6a578ccaa Binary files /dev/null and b/Externals/NUnit/lib/Images/Tree/Visual Studio/SeriousWarning.png differ diff --git a/Externals/NUnit/lib/Images/Tree/Visual Studio/Skipped.png b/Externals/NUnit/lib/Images/Tree/Visual Studio/Skipped.png new file mode 100644 index 0000000000..7c9fc64e3 Binary files /dev/null and b/Externals/NUnit/lib/Images/Tree/Visual Studio/Skipped.png differ diff --git a/Externals/NUnit/lib/Images/Tree/Visual Studio/Success.png b/Externals/NUnit/lib/Images/Tree/Visual Studio/Success.png new file mode 100644 index 0000000000..346fe8f92 Binary files /dev/null and b/Externals/NUnit/lib/Images/Tree/Visual Studio/Success.png differ diff --git a/Externals/NUnit/lib/Images/pinned.gif b/Externals/NUnit/lib/Images/pinned.gif new file mode 100644 index 0000000000..cb07448dd Binary files /dev/null and b/Externals/NUnit/lib/Images/pinned.gif differ diff --git a/Externals/NUnit/lib/Images/unpinned.gif b/Externals/NUnit/lib/Images/unpinned.gif new file mode 100644 index 0000000000..f25fbb533 Binary files /dev/null and b/Externals/NUnit/lib/Images/unpinned.gif differ diff --git a/Externals/NUnit/lib/NSubstitute.dll b/Externals/NUnit/lib/NSubstitute.dll new file mode 100644 index 0000000000..fba0966cd Binary files /dev/null and b/Externals/NUnit/lib/NSubstitute.dll differ diff --git a/Externals/NUnit/lib/NSubstitute.xml b/Externals/NUnit/lib/NSubstitute.xml new file mode 100644 index 0000000000..217f01d7d --- /dev/null +++ b/Externals/NUnit/lib/NSubstitute.xml @@ -0,0 +1,259 @@ + + + + NSubstitute + + + + + Argument matchers used for specifying calls to substitutes. + + + + + Match any argument value compatible with type . + + + + + + + Match argument that is equal to . + + + + + + + + Match argument that satisfies . + If the throws an exception for an argument it will be treated as non-matching. + + + + + + + + Invoke any argument as soon as a matching call is made to the substitute. + + + + + + Invoke any argument with specified argument as soon as a matching call is made to the substitute. + + + + + + + + Invoke any argument with specified arguments as soon as a matching call is made to the substitute. + + + + + + + + + + Invoke any argument with specified arguments as soon as a matching call is made to the substitute. + + + + + + + + + + + + Invoke any argument with specified arguments as soon as a matching call is made to the substitute. + + + + + + + + + + + + + + Invoke any argument with specified arguments as soon as a matching call is made to the substitute. + + + Arguments to pass to delegate. + + + + + Capture any argument compatible with type and use it to call the function + as soon as a matching call is made to the substitute. + + + + + + + + Provides a specification for arguments for use with . + Can additionally implement to give descriptions when arguments do not match. + + + + + Checks whether the satisfies the condition of the matcher. + If this throws an exception the argument will be treated as non-matching. + + + + + + + Describes how the does not match the condition specified by this class, or + if a detailed description can not be provided for the argument. + + + Description of the non-match, or if no description can be provided. + + + + Combines two enumerables into a new enumerable using the given selector. + + + + + + + + + + This implementation was sanity-checked against the + Edulinq implementation and + Eric Lippert's implementation. + + + + + Checks if the instance can be used when a is expected. + + + + + + + + Join the using . + + + + + + + + Delegates to ThreadLocal<T>, but wraps Value property access in try/catch to swallow ObjectDisposedExceptions. + These can occur if the Value property is accessed from the finalizer thread. Because we can't detect this, we'll + just swallow the exception (the finalizer thread won't be using any of the values from thread local storage anyway). + + + + + + Provides a specification for arguments for use with . + Can additionally implement to give descriptions when arguments do not match. + + Matches arguments of type or compatible type. + + + + Checks whether the satisfies the condition of the matcher. + If this throws an exception the argument will be treated as non-matching. + + + + + + + Raise an event for an EventHandler<TEventArgs> event with the provided and . + + + + + Raise an event for an EventHandler<TEventArgs> event with the substitute as the sender and the provided . + + + + + Raise an event for an EventHandler<EventArgsT> event with the substitute as the sender + and with a default instance of . + + + + + Raise an event for an EventHandler or EventHandler<EventArgs> event with the substitute + as the sender and with empty EventArgs. + + + + + Raise an event of type with the provided arguments. If no arguments are provided + NSubstitute will try and provide reasonble defaults. + + + + + Create a substitute for one or more types. For example: Substitute.For<ISomeType>() + + + + + Substitute for an interface or class. + Be careful when specifying a class, as all non-virtual members will actually be executed. Only virtual members + can be recorded or have return values specified. + + The type of interface or class to substitute. + Arguments required to construct a class being substituted. Not required for interfaces or classes with default constructors. + A substitute for the interface or class. + + + + Substitute for multiple interfaces or a class that implements an interface. At most one class can be specified. + Be careful when specifying a class, as all non-virtual members will actually be executed. Only virtual members + can be recorded or have return values specified. + + The type of interface or class to substitute. + An additional interface or class (maximum of one class) the substitute should implement. + Arguments required to construct a class being substituted. Not required for interfaces or classes with default constructors. + A substitute of type T1, that also implements T2. + + + + Substitute for multiple interfaces or a class that implements multiple interfaces. At most one class can be specified. + If additional interfaces are required use the overload. + Be careful when specifying a class, as all non-virtual members will actually be executed. Only virtual members + can be recorded or have return values specified. + + The type of interface or class to substitute. + An additional interface or class (maximum of one class) the substitute should implement. + An additional interface or class (maximum of one class) the substitute should implement. + Arguments required to construct a class being substituted. Not required for interfaces or classes with default constructors. + A substitute of type T1, that also implements T2 and T3. + + + + Substitute for multiple interfaces or a class that implements multiple interfaces. At most one class can be specified. + Be careful when specifying a class, as all non-virtual members will actually be executed. Only virtual members + can be recorded or have return values specified. + + The types of interfaces or a type of class and multiple interfaces the substitute should implement. + Arguments required to construct a class being substituted. Not required for interfaces or classes with default constructors. + A substitute implementing the specified types. + + + diff --git a/Externals/NUnit/lib/Rhino.Mocks.dll b/Externals/NUnit/lib/Rhino.Mocks.dll new file mode 100644 index 0000000000..3fc4b2ae4 Binary files /dev/null and b/Externals/NUnit/lib/Rhino.Mocks.dll differ diff --git a/Externals/NUnit/lib/Rhino.Mocks.xml b/Externals/NUnit/lib/Rhino.Mocks.xml new file mode 100644 index 0000000000..5d9370d48 --- /dev/null +++ b/Externals/NUnit/lib/Rhino.Mocks.xml @@ -0,0 +1,5413 @@ + + + + Rhino.Mocks + + + + + Defines constraints and return values for arguments of a mock. + Only use Arg inside a method call on a mock that is recording. + Example: + ExpectCall( + mock.foo( + Arg<int>.Is.GreaterThan(2), + Arg<string>.Is.Anything + )); + Use Arg.Text for string specific constraints + Use Arg<ListClass>.List for list specific constraints + + + + + + Register the predicate as a constraint for the current call. + + The predicate. + default(T) + + Allow you to use code to create constraints + + demo.AssertWasCalled(x => x.Bar(Arg{string}.Matches(a => a.StartsWith("b") && a.Contains("ba")))); + + + + + + Define a complex constraint for this argument by passing several constraints + combined with operators. (Use Is in simple cases.) + Example: Arg<string>.Matches(Is.Equal("Hello") || Text.EndsWith("u")); + + Constraints using Is, Text and List + Dummy to satisfy the compiler + + + + Define a Ref argument. + + Constraints for this argument + value returned by the mock + + + + + Define a out parameter. Use it together with the keyword out and use the + Dummy field available by the return value. + Example: mock.foo( out Arg<string>.Out("hello").Dummy ); + + + + + + + Define a simple constraint for this argument. (Use Matches in simple cases.) + Example: + Arg<int>.Is.Anthing + Arg<string>.Is.Equal("hello") + + + + + Define Constraints on list arguments. + + + + + Use the Arg class (without generic) to define Text constraints + + + + + Evaluate an equal constraint for . + + The object the parameter should equal to + + + + Define constraints on text arguments. + + + + + Used to manage the static state of the Arg<T> class"/> + + + + + Resets the static state + + + + + Returns return values for the out and ref parameters + Note: the array returned has the size of the number of out and ref + argument definitions + + + + + + Returns the constraints for all arguments. + Out arguments have an Is.Anything constraint and are also in the list. + + + + + + What should BackToRecord clear + + + + + Retain all expectations and behaviors and return to mock + + + + + All expectations + + + + + Event subscribers for this instance + + + + + Methods that should be forwarded to the base class implementation + + + + + Properties that should behave like properties + + + + + Remove all the behavior of the object + + + + + Interface for constraints + + + + + Determines if the object pass the constraints + + + + + And operator for constraints + + + + + Not operator for constraints + + + + + Or operator for constraints + + + + + Allow overriding of || or && + + + + + + + Allow overriding of || or && + + + + + + + Gets the message for this constraint + + + + + + Constrain that the public field has a specified value + + + + + Constrain that the public field matches another constraint. + + + + + Creates a new instance. + + Name of the public field. + Constraint to place on the public field value. + + + + Creates a new instance, specifying a disambiguating + for the public field. + + The type that declares the public field, used to disambiguate between public fields. + Name of the public field. + Constraint to place on the public field value. + + + + Determines if the object passes the constraint. + + + + + Gets the message for this constraint + + + + + + Creates a new instance. + + Name of the public field. + Expected value. + + + + Creates a new instance, specifying a disambiguating + for the public field. + + The type that declares the public field, used to disambiguate between public fields. + Name of the public field. + Expected value. + + + + Constrain that the property has a specified value + + + + + Constrain that the property matches another constraint. + + + + + Creates a new instance. + + Name of the property. + Constraint to place on the property value. + + + + Creates a new instance, specifying a disambiguating + for the property. + + The type that declares the property, used to disambiguate between properties. + Name of the property. + Constraint to place on the property value. + + + + Determines if the object passes the constraint. + + + + + Gets the message for this constraint + + + + + + Creates a new instance. + + Name of the property. + Expected value. + + + + Creates a new instance, specifying a disambiguating + for the property. + + The type that declares the property, used to disambiguate between properties. + Name of the property. + Expected value. + + + + Constrain that the parameter must be of the specified type + + + + + Creates a new instance. + + Type. + + + + Determines if the object pass the constraints + + + + + Gets the message for this constraint + + + + + + Constraint that determines whether an object is the same object as another. + + + + + Creates a new instance. + + Obj. + + + + Determines if the object passes the constraints. + + + + + Gets the message for this constraint. + + + + + Evaluate a parameter using constraints + + + + + Create new instance + + + + + + Determines if the object pass the constraints + + + + + Gets the message for this constraint + + + + + + A constraint based on lambda expression, we are using Expression{T} + because we want to be able to get good error reporting on that. + + + + + Initializes a new instance of the class. + + The expr. + + + + Determines if the object pass the constraints + + + + + + + Gets the message for this constraint + + + + + + Constrain that the list contains the same items as the parameter list + + + + + Creates a new instance. + + In list. + + + + Determines if the object pass the constraints + + + + + Gets the message for this constraint + + + + + + Constrain that the parameter is one of the items in the list + + + + + Creates a new instance. + + In list. + + + + Determines if the object pass the constraints + + + + + Gets the message for this constraint + + + + + + Constrain that the object is inside the parameter list + + + + + Creates a new instance. + + In list. + + + + Determines if the object pass the constraints + + + + + Gets the message for this constraint + + + + + + Applies another AbstractConstraint to the collection count. + + + + + Creates a new instance. + + The constraint that should be applied to the collection count. + + + + Determines if the parameter conforms to this constraint. + + + + + Gets the message for this constraint. + + + + + Applies another AbstractConstraint to a specific list element. + + + + + Creates a new instance. + + The zero-based index of the list element. + The constraint that should be applied to the list element. + + + + Determines if the parameter conforms to this constraint. + + + + + Gets the message for this constraint + + + + + + Applies another AbstractConstraint to a specific generic keyed list element. + + + + + Creates a new instance. + + The key of the list element. + The constraint that should be applied to the list element. + + + + Determines if the parameter conforms to this constraint. + + + + + Gets the message for this constraint + + + + + + Constrains that all elements are in the parameter list + + + + + Initializes a new instance of the class. + + The these. + + + + Determines if the object pass the constraints + + + + + + + Gets the message for this constraint + + + + + + Combines two constraints, constraint pass if either is fine. + + + + + Creates a new instance. + + C1. + C2. + + + + Determines if the object pass the constraints + + + + + Gets the message for this constraint + + + + + + Negate a constraint + + + + + Creates a new instance. + + C1. + + + + Determines if the object pass the constraints + + + + + Gets the message for this constraint + + + + + + Combines two constraints + + + + + + Creates a new instance. + + C1. + C2. + + + + Determines if the object pass the constraints + + + + + Gets the message for this constraint + + + + + + Constrain the argument to validate according to regex pattern + + + + + Creates a new instance. + + Pattern. + + + + Determines if the object pass the constraints + + + + + Gets the message for this constraint + + + + + + Constraint that evaluate whatever an argument contains the specified string. + + + + + Creates a new instance. + + Inner string. + + + + Determines if the object pass the constraints + + + + + Gets the message for this constraint + + + + + + Constraint that evaluate whatever an argument ends with the specified string + + + + + Creates a new instance. + + End. + + + + Determines if the object pass the constraints + + + + + Gets the message for this constraint + + + + + + Constraint that evaluate whatever an argument start with the specified string + + + + + Creates a new instance. + + Start. + + + + Determines if the object pass the constraints + + + + + Gets the message for this constraint + + + + + + Constraint that evaluate whatever an object equals another + + + + + Creates a new instance. + + Obj. + + + + Determines if the object pass the constraints + + + + + Gets the message for this constraint + + + + + + Constraint that always returns true + + + + + Determines if the object pass the constraints + + + + + Gets the message for this constraint + + + + + + Constraint that evaluate whatever a comparable is greater than another + + + + + Creates a new instance. + + + + + Determines if the object pass the constraints + + + + + Gets the message for this constraint + + + + + + Initializes a new constraint object. + + The expected object, The actual object is passed in as a parameter to the method + + + + Evaluate this constraint. + + The actual object that was passed in the method call to the mock. + True when the constraint is met, else false. + + + + Checks if the properties of the object + are the same as the properies of the object. + + The expected object + The actual object + True when both objects have the same values, else False. + + + + + + + + + This is the real heart of the beast. + + + + Used by CheckReferenceType to check all properties of the reference type. + + The expected object + The actual object + True when both objects have the same values, else False. + + + + Used by CheckReferenceType to check all fields of the reference type. + + The expected object + The actual object + True when both objects have the same values, else False. + + + + Checks the items of both collections + + The expected collection + + True if both collections contain the same items in the same order. + + + + Builds a propertyname from the Stack _properties like 'Order.Product.Price' + to be used in the error message. + + A nested property name. + + + + Rhino.Mocks uses this property to generate an error message. + + + A message telling the tester why the constraint failed. + + + + + Provides access to the constraintes defined in the class to be used in context + with the syntax. + + The type of the argument + + + + Evaluate a greater than constraint for . + + The object the parameter should be greater than + + + + Evaluate a less than constraint for . + + The object the parameter should be less than + + + + Evaluate a less than or equal constraint for . + + The object the parameter should be less than or equal to + + + + Evaluate a greater than or equal constraint for . + + The object the parameter should be greater than or equal to + + + + Evaluate an equal constraint for . + + The object the parameter should equal to + + + + Evaluate a not equal constraint for . + + The object the parameter should not equal to + + + + Evaluate a same as constraint. + + The object the parameter should the same as. + + + + Evaluate a not same as constraint. + + The object the parameter should not be the same as. + + + + Throws NotSupportedException. Don't use Equals to define constraints. Use Equal instead. + + + + + + + Serves as a hash function for a particular type. + + + A hash code for the current . + + + + + A constraints that accept anything + + + + + + A constraint that accept only nulls + + + + + + A constraint that accept only non null values + + + + + + A constraint that accept only value of the specified type. + The check is performed on the type that has been defined + as the argument type. + + + + + Provides access to the constraints defined in the class to be used in context + with the syntax. + + + + + Determines whether the specified object is in the parameter. + The parameter must be IEnumerable. + + Obj. + + + + + Determines whatever the parameter is in the collection. + + + + + Determines that the parameter collection is identical to the specified collection + + + + + Determines that the parameter collection has the specified number of elements. + + The constraint that should be applied to the collection count. + + + + Determines that an element of the parameter collections conforms to another AbstractConstraint. + + The zero-based index of the list element. + The constraint which should be applied to the list element. + + + + Determines that all elements of the specified collection are in the the parameter collection + + The collection to compare against + The constraint which should be applied to the list parameter. + + + + Throws NotSupportedException. Don't use Equals to define constraints. Use Equal instead. + + + + + + + Serves as a hash function for a particular type. + + + A hash code for the current . + + + + + Provides a dummy field to pass as out or ref argument. + + + + + + Dummy field to satisfy the compiler. Used for out and ref arguments. + + + + + Central location for constraints for object's public fields + + + + + Constrains the parameter to have a public field with the specified value + + Name of the public field. + Expected value. + + + + + Constrains the parameter to have a public field with the specified value. + + The type that declares the public field, used to disambiguate between public fields. + Name of the public field. + Expected value. + + + + + Constrains the parameter to have a public field satisfying a specified constraint. + + Name of the public field. + Constraint for the public field. + + + + Constrains the parameter to have a public field satisfying a specified constraint. + + The type that declares the public field, used to disambiguate between public fields. + Name of the public field. + Constraint for the public field. + + + + Determines whether the parameter has the specified public field and that it is null. + + Name of the public field. + + + + + Determines whether the parameter has the specified public field and that it is null. + + The type that declares the public field, used to disambiguate between public fields. + Name of the public field. + + + + + Determines whether the parameter has the specified public field and that it is not null. + + Name of the public field. + + + + + Determines whether the parameter has the specified public field and that it is not null. + + The type that declares the public field, used to disambiguate between public fields. + Name of the public field. + + + + + Central location for constraints + + + + + Evaluate a greater than constraint for . + + The object the parameter should be greater than + + + + Evaluate a less than constraint for . + + The object the parameter should be less than + + + + Evaluate a less than or equal constraint for . + + The object the parameter should be less than or equal to + + + + Evaluate a greater than or equal constraint for . + + The object the parameter should be greater than or equal to + + + + Evaluate an equal constraint for . + + The object the parameter should equal to + + + + Evaluate a not equal constraint for . + + The object the parameter should not equal to + + + + Evaluate a same as constraint. + + The object the parameter should the same as. + + + + Evaluate a not same as constraint. + + The object the parameter should not be the same as. + + + + A constraints that accept anything + + + + + + A constraint that accept only nulls + + + + + + A constraint that accept only non null values + + + + + + A constraint that accept only value of the specified type + + + + + A constraint that accept only value of the specified type + + + + + Evaluate a parameter using a predicate + + The predicate to use + + + + Central location for constraints about lists and collections + + + + + Determines whether the specified obj is in the parameter. + The parameter must be IEnumerable. + + Obj. + + + + + Determines whatever the parameter is in the collection. + + + + + Determines that the parameter collection is identical to the specified collection + + + + + Determines that the parameter collection has the specified number of elements. + + The constraint that should be applied to the collection count. + + + + Determines that an element of the parameter collections conforms to another AbstractConstraint. + + The zero-based index of the list element. + The constraint which should be applied to the list element. + + + + Determines that an element of the parameter collections conforms to another AbstractConstraint. + + The key of the element. + The constraint which should be applied to the element. + + + + Determines that all elements of the specified collection are in the the parameter collection + + The collection to compare against + The constraint which should be applied to the list parameter. + + + + Central location for constraints for object's properties + + + + + Constrains the parameter to have property with the specified value + + Name of the property. + Expected value. + + + + + Constrains the parameter to have property with the specified value. + + The type that declares the property, used to disambiguate between properties. + Name of the property. + Expected value. + + + + + Constrains the parameter to have a property satisfying a specified constraint. + + Name of the property. + Constraint for the property. + + + + Constrains the parameter to have a property satisfying a specified constraint. + + The type that declares the property, used to disambiguate between properties. + Name of the property. + Constraint for the property. + + + + Determines whether the parameter has the specified property and that it is null. + + Name of the property. + + + + + Determines whether the parameter has the specified property and that it is null. + + The type that declares the property, used to disambiguate between properties. + Name of the property. + + + + + Determines whether the parameter has the specified property and that it is not null. + + Name of the property. + + + + + Determines whether the parameter has the specified property and that it is not null. + + The type that declares the property, used to disambiguate between properties. + Name of the property. + + + + + constraints the parameter to have the exact same property values as the expected object. + + An object, of the same type as the parameter, whose properties are set with the expected values. + An instance of the constraint that will do the actual check. + + The parameter's public property values and public field values will be matched against the expected object's + public property values and public field values. The first mismatch will be reported and no further matching is done. + The matching is recursive for any property or field that has properties or fields of it's own. + Collections are supported through IEnumerable, which means the constraint will check if the actual and expected + collection contain the same values in the same order, where the values contained by the collection can have properties + and fields of their own that will be checked as well because of the recursive nature of this constraint. + + + + + Central location for all text related constraints + + + + + Constrain the argument to starts with the specified string + + + + + Constrain the argument to end with the specified string + + + + + Constrain the argument to contain the specified string + + + + + Constrain the argument to validate according to regex pattern + + + + + Provides access to the constraintes defined in the class to be used in context + with the syntax. + + + + + Constrain the argument to starts with the specified string + + + + + + Constrain the argument to end with the specified string + + + + + Constrain the argument to contain the specified string + + + + + Constrain the argument to validate according to regex pattern + + + + + Throws NotSupportedException. Don't use Equals to define constraints. Use Equal instead. + + + + + + + Serves as a hash function for a particular type. + + + A hash code for the current . + + + + + This class defines a lot of method signatures, which we will use + to allow compatability on net-2.0 + + + + + dummy + + + + + dummy + + + + + dummy + + + + + dummy + + + + + dummy + + + + + dummy + + + + + dummy + + + + + dummy + + + + + dummy + + + + + dummy + + + + + dummy + + + + + dummy + + + dummy + + + + + dummy + + + + + dummy + + + + + dummy + + + + + dummy + + + + + dummy + + + + + dummy + + + + + dummy + + + + + dummy + + + + + dummy + + + + + Allows expectations to be set on methods that should never be called. + For methods with void return value, you need to use LastCall or + DoNotExpect.Call() with a delegate. + + + + + Sets LastCall.Repeat.Never() on /any/ proxy on /any/ repository on the current thread. + This method if not safe for multi threading scenarios. + + + + + Accepts a delegate that will execute inside the method which + LastCall.Repeat.Never() will be applied to. + It is expected to be used with anonymous delegates / lambda expressions and only one + method should be called. + + + IService mockSrv = mocks.CreateMock(typeof(IService)) as IService; + DoNotExpect.Call(delegate{ mockSrv.Stop(); }); + ... + + + + + An expectaton violation was detected. + + + + + Creates a new instance. + + Message. + + + + Serialization constructor + + + + + Signals that an object was call on a mock repository which doesn't + belong to this mock repository or not a mock + + + + + Creates a new instance. + + Message. + + + + Serialization constructor + + + + + Allows to set expectation on methods that has return values. + For methods with void return value, you need to use LastCall + + + + + The method options for the last call on /any/ proxy on /any/ repository on the current thread. + This method if not safe for multi threading scenarios, use . + + + + + Accepts a delegate that will execute inside the method, and then return the resulting + instance. + It is expected to be used with anonymous delegates / lambda expressions and only one + method should be called. + + + IService mockSrv = mocks.CreateMock(typeof(IService)) as IService; + Expect.Call(delegate{ mockSrv.Start(); }).Throw(new NetworkException()); + ... + + + + + Get the method options for the last method call on the mockInstance. + + + + + A delegate that can be used to get better syntax on Expect.Call(delegate { foo.DoSomething(); }); + + + + + Abstract class that holds common information for + expectations. + + + + + Interface to validate that a method call is correct. + + + + + Validate the arguments for the method. + This method can be called numerous times, so be careful about side effects + + The arguments with which the method was called + + + + Add an actual method call to this expectation + + + + + Returns the return value or throw the exception and setup any output / ref parameters + that has been set. + + + + + Builds the verification failure message. + + + + + + Gets the error message. + + + + + + Range of expected calls + + + + + Number of call actually made for this method + + + + + If this expectation is still waiting for calls. + + + + + The return value for a method matching this expectation + + + + + Gets or sets the exception to throw on a method matching this expectation. + + + + + Gets a value indicating whether this instance's action is staisfied. + A staisfied instance means that there are no more requirements from + this method. A method with non void return value must register either + a return value or an exception to throw. + + + + + Gets the method this expectation is for. + + + + + Gets or sets what special condtions there are for this method + repeating. + + + + + Gets a value indicating whether this expectation was satisfied + + + + + Specify whatever this expectation has a return value set + You can't check ReturnValue for this because a valid return value include null. + + + + + An action to execute when the method is matched. + + + + + Set the out / ref parameters for the method call. + The indexing is zero based and ignores any non out/ref parameter. + It is possible not to pass all the parameters. This method can be called only once. + + + + + Documentation Message + + + + + Gets the invocation for this expectation + + The invocation. + + + + Occurs when the exceptation is match on a method call + + + + + Allow to set the return value in the future, if it was already set. + + + + + Number of actuall calls made that passed this expectation + + + + + Range of expected calls that should pass this expectation. + + + + + The return value for a method matching this expectation + + + + + The exception to throw on a method matching this expectation. + + + + + The method this expectation is for. + + + + + The return value for this method was set + + + + + Whether this method will repeat + unlimited number of times. + + + + + A delegate that will be run when the + expectation is matched. + + + + + The arguments that matched this expectation. + + + + + Documentation message + + + + + The method originalInvocation + + + + + Get the hash code + + + + + Add an actual actualMethodCall call to this expectation + + + + + Builds the verification failure message. + + + + + + Returns the return value or throw the exception and setup output / ref parameters + + + + + Validate the arguments for the method on the child methods + + The arguments with which the method was called + + + + Creates a new instance. + + The originalInvocation for this method, required because it contains the generic type infromation + Number of method calls for this expectations + + + + Creates a new instance. + + Expectation. + + + + Validate the arguments for the method on the child methods + + The arguments with which the method was called + + + + Determines if this object equal to obj + + + + + The error message for these arguments + + + + + Asserts that the delegate has the same parameters as the expectation's method call + + + + + Setter for the outpur / ref parameters for this expecataion. + Can only be set once. + + + + + Specify whether this expectation has a return value set + You can't check ReturnValue for this because a valid return value include null. + + + + + Gets the method this expectation is for. + + + + + Gets the originalInvocation for this expectation + + The originalInvocation. + + + + Gets or sets what special condtions there are for this method + + + + + Range of expected calls + + + + + Number of call actually made for this method + + + + + If this expectation is still waiting for calls. + + + + + Gets a value indicating whether this expectation was satisfied + + + + + The return value for a method matching this expectation + + + + + An action to execute when the method is matched. + + + + + Gets or sets the exception to throw on a method matching this expectation. + + + + + Gets a value indicating whether this instance's action is staisfied. + A staisfied instance means that there are no more requirements from + this method. A method with non void return value must register either + a return value or an exception to throw or an action to execute. + + + + + Documentation message + + + + + Occurs when the exceptation is match on a method call + + + + + Allow to set the return value in the future, if it was already set. + + + + + Gets the error message. + + + + + + Expectation that matches any arguments for the method. + + + + + Creates a new instance. + + Invocation for this expectation + Number of method calls for this expectations + + + + Creates a new instance. + + Expectation. + + + + Validate the arguments for the method. + + The arguments with which the method was called + + + + Determines if the object equal to expectation + + + + + Get the hash code + + + + + Gets the error message. + + + + + + Summary description for ArgsEqualExpectation. + + + + + Creates a new instance. + + Expected args. + The invocation for this expectation + Number of method calls for this expectations + + + + Validate the arguments for the method. + + The arguments with which the method was called + + + + Determines if the object equal to expectation + + + + + Get the hash code + + + + + Gets the error message. + + + + + + Get the expected args. + + + + + Call a specified callback to verify the expectation + + + + + Creates a new instance. + + Expectation. + Callback. + + + + Creates a new instance. + + Invocation for this expectation + Callback. + Number of method calls for this expectations + + + + Validate the arguments for the method on the child methods + + The arguments with which the method was called + + + + Determines if the object equal to expectation + + + + + Get the hash code + + + + + Gets the error message. + + + + + + Expect the method's arguments to match the contraints + + + + + Creates a new instance. + + Invocation for this expectation + Constraints. + Number of method calls for this expectations + + + + Creates a new instance. + + Expectation. + Constraints. + + + + Validate the arguments for the method. + + The arguments with which the method was called + + + + Determines if the object equal to expectation + + + + + Get the hash code + + + + + Gets the error message. + + + + + + Doesn't log anything, just makes happy noises + + + + + Log expectations - allows to see what is going on inside Rhino Mocks + + + + + Logs the expectation as is was recorded + + The invocation. + The expectation. + + + + Logs the expectation as it was recorded + + The invocation. + The expectation. + + + + Logs the unexpected method call. + + The invocation. + The message. + + + + Logs the expectation as is was recorded + + The invocation. + The expectation. + + + + Logs the expectation as it was recorded + + The invocation. + The expectation. + + + + Logs the unexpected method call. + + The invocation. + The message. + + + + Operation on a remoting proxy + + + It is not possible to directly communicate to a real proxy via transparent proxy. + Transparent proxy impersonates a user type and only methods of that user type are callable. + The only methods that are guaranteed to exist on any transparent proxy are methods defined + in Object: namely ToString(), GetHashCode(), and Equals()). + + These three methods are the only way to tell the real proxy to do something. + Equals() is the most suitable of all, since it accepts an arbitrary object parameter. + The RemotingProxy code is built so that if it is compared to an IRemotingProxyOperation, + transparentProxy.Equals(operation) will call operation.Process(realProxy). + This way we can retrieve a real proxy from transparent proxy and perform + arbitrary operation on it. + + + + + Generates remoting proxies and provides utility functions + + + + + Create the proxy using remoting + + + + + Check whether an object is a transparent proxy with a RemotingProxy behind it + + Object to check + true if the object is a transparent proxy with a RemotingProxy instance behind it, false otherwise + We use Equals() method to communicate with the real proxy behind the object. + See IRemotingProxyOperation for more details + + + + Retrieve a mocked object from a transparent proxy + + Transparent proxy with a RemotingProxy instance behind it + Mocked object associated with the proxy + We use Equals() method to communicate with the real proxy behind the object. + See IRemotingProxyOperation for more details + + + + Implementation of IInvocation based on remoting proxy + + Some methods are marked NotSupported since they either don't make sense + for remoting proxies, or they are never called by Rhino Mocks + + + + Rudimetry implementation that simply logs methods calls as text. + + + + + Initializes a new instance of the class. + + The writer. + + + + Logs the expectation as it was recorded + + The invocation. + The expectation. + + + + Logs the expectation as it was recorded + + The invocation. + The expectation. + + + + Logs the unexpected method call. + + The invocation. + The message. + + + + Behave like a stub, all properties and events acts normally, methods calls + return default values by default (but can use expectations to set them up), etc. + + + + + Records all the expectations for a mock + + + + + Different actions on this mock + + + + + Add a method call for this state' mock. + + The invocation for this method + The method that was called + The arguments this method was called with + + + + Verify that this mock expectations have passed. + + + + + Verify that we can move to replay state and move + to the reply state. + + + + + Gets a mock state that match the original mock state of the object. + + + + + Get the options for the last method call + + + + + Set the exception to throw when Verify is called. + This is used to report exception that may have happened but where caught in the code. + This way, they are reported anyway when Verify() is called. + + + + + This method is called to indicate that a property behavior call. + This is done so we generate good error message in the common case of people using + Stubbed properties with Return(). + + + + + Gets the matching verify state for this state + + + + + Get the options for the last method call + + + + + Get the options for the last method call + + + + + Set the exception to throw when Verify is called. + This is used to report exception that may have happened but where caught in the code. + This way, they are reported anyway when Verify() is called. + + + + + This method is called to indicate that a property behavior call. + This is done so we generate good error message in the common case of people using + Stubbed properties with Return(). + + + + + Creates a new instance. + + Repository. + The proxy that generates the method calls + + + + Add a method call for this state' mock. + + The invocation for this method + The method that was called + The arguments this method was called with + + + + Verify that we can move to replay state and move + to the reply state. + + + + + Verify that we can move to replay state and move + to the reply state. + + + + + Verify that this mock expectations have passed. + + + + + Gets a mock state that match the original mock state of the object. + + + + + Asserts the previous method is closed (had an expectation set on it so we can replay it correctly) + + + + + Get the default call count range expectation + + + + + + Gets the last expectation. + + + + + Gets the total method calls count. + + + + + Get the options for the last method call + + + + + Gets the matching verify state for this state + + + + + Initializes a new instance of the class. + + The proxy that generates the method calls + Repository. + + + + We don't care much about expectations here, so we will remove the expectation if + it is not closed. + + + + + Verify that we can move to replay state and move + to the reply state. + + + + + + Get the default call count range expectation + + + + + + Validate expectations on recorded methods, but in general completely ignoring them. + Similar to except that it would return a + when BackToRecord is called. + + + + + Validate all expectations on a mock + + + + + The repository for this state + + + + + The proxy object for this state + + + + + Get the options for the last method call + + + + + Creates a new instance. + + The previous state for this method + + + + Add a method call for this state' mock. + + The invocation for this method + The method that was called + The arguments this method was called with + + + + Add a method call for this state' mock. + This allows derived method to cleanly get a the setupresult behavior while adding + their own. + + The invocation for this method + The method that was called + The arguments this method was called with + + + + Set the exception to throw when Verify is called. + This is used to report exception that may have happened but where caught in the code. + This way, they are reported anyway when Verify() is called. + + + + + not relevant + + + + + Verify that this mock expectations have passed. + + + + + Verify that we can move to replay state and move + to the reply state. + + + + + Gets a mock state that match the original mock state of the object. + + + + + Get the options for the last method call + + + + + Gets the matching verify state for this state + + + + + Initializes a new instance of the class. + + The previous state for this method + + + + Add a method call for this state' mock. + + The invocation for this method + The method that was called + The arguments this method was called with + + + + Gets a mock state that matches the original mock state of the object. + + + + + Write rhino mocks log info to the trace + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + if set to true [log recorded]. + if set to true [log replayed]. + if set to true [log unexpected]. + + + + Logs the expectation as is was recorded + + The invocation. + The expectation. + + + + Logs the expectation as it was recorded + + The invocation. + The expectation. + + + + Logs the unexpected method call. + + The invocation. + The message. + + + + Writes log information as stack traces about rhino mocks activity + + + + + Allows to redirect output to a different location. + + + + + Logs the expectation as is was recorded + + The invocation. + The expectation. + + + + Logs the expectation as it was recorded + + The invocation. + The expectation. + + + + Logs the unexpected method call. + + The invocation. + The message. + + + + Marker interface used to indicate that this is a partial mock. + + + + + Options for CallOriginalMethod + + + + + No expectation is created, the method will be called directly + + + + + Normal expectation is created, but when the method is later called, it will also call the original method + + + + + This is a data structure that is used by + to pass + the current method to the relevant delegate + + + + + Initializes a new instance of the class. + + The invocation. + + + + Gets the args for this method invocation + + + + + Get the method that was caused this invocation + + + + + Gets or sets the return value for this method invocation + + The return value. + + + + Adds optional new usage: + using(mockRepository.Record()) { + Expect.Call(mock.Method()).Return(retVal); + } + using(mockRepository.Playback()) { + // Execute code + } + N.B. mockRepository.ReplayAll() and mockRepository.VerifyAll() + calls are taken care of by Record/Playback + + + Creates proxied instances of types. + + + + Generates a stub without needing a + Arguments for 's constructor + The of stub to create. + The stub + + + + Generates a stub without needing a + The of stub. + Arguments for the 's constructor. + The stub + + + + Generate a mock object without needing a + type of mock object to create. + Arguments for 's constructor + the mock object + + + + Generate a multi-mock object without needing a + The typeof object to generate a mock for. + A second interface to generate a multi-mock for. + Arguments for 's constructor + the multi-mock object + + + + Generate a multi-mock object without without needing a + The typeof object to generate a mock for. + An interface to generate a multi-mock for. + A second interface to generate a multi-mock for. + Arguments for 's constructor + the multi-mock object + + + + Creates a multi-mock without without needing a + The type of mock to create, this can be a class + Any extra interfaces to add to the multi-mock, these can only be interfaces. + Arguments for 's constructor + the multi-mock object + + + + Creates a strict mock without without needing a + Any arguments required for the 's constructor + The type of mock object to create. + The mock object with strict replay semantics + + + + Creates a strict multi-mock without needing a + Any arguments required for the 's constructor + The type of mock object to create, this can be a class. + An interface to generate a multi-mock for, this must be an interface! + The multi-mock object with strict replay semantics + + + + Creates a strict multi-mock without needing a + Any arguments required for the 's constructor + The type of mock object to create, this can be a class. + An interface to generate a multi-mock for, this must be an interface! + A second interface to generate a multi-mock for, this must be an interface! + The multi-mock object with strict replay semantics + + + + Creates a strict multi-mock without needing a + The type of mock object to create, this can be a class + Any extra interfaces to generate a multi-mock for, these must be interaces! + Any arguments for the 's constructor + The strict multi-mock object + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Generate a mock object with dynamic replay semantics and remoting without needing the mock repository + + + + + Generate a mock object with strict replay semantics and remoting without needing the mock repository + + + + Helper method to create a mock object without a repository instance and put the object back into replay mode. + The type of mock object to create + A delegate that uses a mock repository instance to create the underlying mock + The mock object in the replay mode. + + + + + + + + + + + + + + This is a map of types to ProxyGenerators. + + + + + This is used to record the last repository that has a method called on it. + + + + + this is used to get to the last proxy on this repository. + + + + + For mock delegates, maps the proxy instance from intercepted invocations + back to the delegate that was originally returned to client code, if any. + + + + + All the proxies in the mock repositories + + + + + This is here because we can't put it in any of the recorders, since repeatable methods + have no orderring, and if we try to handle them using the usual manner, we would get into + wierd situations where repeatable method that was defined in an orderring block doesn't + exists until we enter this block. + + + + + Creates a new instance. + + + + + Move the repository to ordered mode + + + + + Move the repository to un-ordered mode + + + + + Creates a mock for the specified type. + + Type. + Arguments for the class' constructor, if mocking a concrete class + + + + Creates a strict mock for the specified type. + + Type. + Arguments for the class' constructor, if mocking a concrete class + + + + Creates a remoting mock for the specified type. + + Type. + Arguments for the class' constructor, if mocking a concrete class + + + + Creates a strict remoting mock for the specified type. + + Type. + Arguments for the class' constructor, if mocking a concrete class + + + + Creates a remoting mock for the specified type. + + + Arguments for the class' constructor, if mocking a concrete class + + + + + Creates a strict remoting mock for the specified type. + + + Arguments for the class' constructor, if mocking a concrete class + + + + + Creates a mock from several types, with strict semantics. + Only may be a class. + + + + + Creates a strict mock from several types, with strict semantics. + Only may be a class. + + + + + Creates a mock from several types, with strict semantics. + Only may be a class. + + The main type to mock. + Extra interface types to mock. + Arguments for the class' constructor, if mocking a concrete class. + + + + Creates a strict mock from several types, with strict semantics. + Only may be a class. + + The main type to mock. + Extra interface types to mock. + Arguments for the class' constructor, if mocking a concrete class. + + + + Creates a mock from several types, with dynamic semantics. + Only may be a class. + + The main type to mock. + Extra interface types to mock. + + + + Creates a mock from several types, with dynamic semantics. + Only may be a class. + + The main type to mock. + Extra interface types to mock. + Arguments for the class' constructor, if mocking a concrete class. + + + Creates a dynamic mock for the specified type. + Type. + Arguments for the class' constructor, if mocking a concrete class + + + Creates a dynamic mock for the specified type. + Type. + Arguments for the class' constructor, if mocking a concrete class + + + Creates a dynamic mock for the specified type. + + Arguments for the class' constructor, if mocking a concrete class + + + + Creates a mock object that defaults to calling the class methods if no expectation is set on the method. + Type. + Arguments for the class' constructor. + + + Creates a mock object that defaults to calling the class methods. + Type. + Extra interface types to mock. + + + Creates a mock object that defaults to calling the class methods. + Type. + Extra interface types to mock. + Arguments for the class' constructor. + + + Creates a mock object using remoting proxies + Type to mock - must be MarshalByRefObject + Mock object + Proxy mock can mock non-virtual methods, but not static methods + Creates the mock state for this proxy + + + + Cause the mock state to change to replay, any further call is compared to the + ones that were called in the record state. + + This method *cannot* be called from inside an ordering. + the object to move to replay state + + + + Cause the mock state to change to replay, any further call is compared to the + ones that were called in the record state. + + the object to move to replay state + + + + Move the mocked object back to record state.You can (and it's recommended) to run {Verify()} before you use this method. + Will delete all current expectations! + + + + Move the mocked object back to record state. + Optionally, can delete all current expectations, but allows more granularity about how + it would behave with regard to the object state. + + + + + Verify that all the expectations for this object were fulfilled. + + the object to verify the expectations for + + + + Get the method options for the last call on + mockedInstance. + + The mock object + Method options for the last call + + + + Maps an invocation proxy back to the mock object instance that was originally + returned to client code which might have been a delegate to this proxy. + + The mock object proxy from the intercepted invocation + The mock object + + + This is provided to allow advance extention functionality, where Rhino Mocks standard functionality is not enough. + The type to mock + Delegate that create the first state of the mocked object (usualy the record state). + Additional types to be implemented, this can be only interfaces + optional arguments for the constructor + + + + + Method: GetMockedObject + Get an IProxy from a mocked object instance, or throws if the + object is not a mock object. + + + + + Method: GetMockedObjectOrNull + Get an IProxy from a mocked object instance, or null if the + object is not a mock object. + + + + Pops the recorder. + + + Pushes the recorder. + New recorder. + + + + All the mock objects in this repository will be moved + to record state. + + + + + All the mock objects in this repository will be moved + to record state. + + + + + Replay all the mocks from this repository + + + + + Verify all the mocks from this repository + + + + + Gets the proxy generator for a specific type. Having a single ProxyGenerator + with multiple types linearly degrades the performance so this implementation + keeps one ProxyGenerator per type. + + + + Set the exception to be thrown when verified is called. + + + + Creates a mock for the spesified type with strict mocking semantics. + Strict semantics means that any call that wasn't explicitly recorded is considered an error and would cause an exception to be thrown. + + Arguments for the class' constructor, if mocking a concrete class + + + + Creates a mock for the spesified type with strict mocking semantics. + Strict semantics means that any call that wasn't explicitly recorded is considered an error and would cause an exception to be thrown. + + Arguments for the class' constructor, if mocking a concrete class + + + + Creates a dynamic mock for the specified type. + + Arguments for the class' constructor, if mocking a concrete class + + + + Creates a mock object from several types. + + + + + Creates a strict mock object from several types. + + + + + Create a mock object from several types with dynamic semantics. + + + + + Create a mock object from several types with partial semantics. + + + + + Create a mock object from several types with strict semantics. + + Extra interface types to mock. + Arguments for the class' constructor, if mocking a concrete class + + + + Create a strict mock object from several types with strict semantics. + + Extra interface types to mock. + Arguments for the class' constructor, if mocking a concrete class + + + + Create a mock object from several types with dynamic semantics. + + Extra interface types to mock. + Arguments for the class' constructor, if mocking a concrete class + + + + Create a mock object from several types with partial semantics. + + Extra interface types to mock. + Arguments for the class' constructor, if mocking a concrete class + + + + Create a mock object with from a class that defaults to calling the class methods + + Arguments for the class' constructor, if mocking a concrete class + + + + Create a stub object, one that has properties and events ready for use, and + can have methods called on it. It requires an explicit step in order to create + an expectation for a stub. + + The arguments for constructor. + + + + Create a stub object, one that has properties and events ready for use, and + can have methods called on it. It requires an explicit step in order to create + an expectation for a stub. + + The type. + The arguments for constructor. + The stub + + + + Returns true if the passed mock is currently in replay mode. + + The mock to test. + True if the mock is in replay mode, false otherwise. + + + + Determines whether the specified proxy is a stub. + + The proxy. + + + + Register a call on a prperty behavior + + + + + + Gets the recorder. + + + + + + Gets the replayer for this repository. + + + + + + Gets the last proxy which had a method call. + + + + + Delegate: CreateMockState + This is used internally to cleanly handle the creation of different + RecordMockStates. + + + + + A set of extension methods that adds Arrange Act Assert mode to Rhino Mocks + + + + + Create an expectation on this mock for this action to occur + + + The mock. + The action. + + + + + Reset all expectations on this mock object + + + The mock. + + + + Reset the selected expectation on this mock object + + + The mock. + The options to reset the expectations on this mock. + + + + Cause the mock state to change to replay, any further call is compared to the + ones that were called in the record state. + + the mocked object to move to replay state + + + + Gets the mock repository for this specificied mock object + + + The mock. + + + + + Create an expectation on this mock for this action to occur + + + + The mock. + The action. + + + + + Tell the mock object to perform a certain action when a matching + method is called. + Does not create an expectation for this method. + + + The mock. + The action. + + + + + Tell the mock object to perform a certain action when a matching + method is called. + Does not create an expectation for this method. + + + + The mock. + The action. + + + + + Gets the arguments for calls made on this mock object and the method that was called + in the action. + + + The mock. + The action. + + + Here we will get all the arguments for all the calls made to DoSomething(int) + + var argsForCalls = foo54.GetArgumentsForCallsMadeOn(x => x.DoSomething(0)) + + + + + + Gets the arguments for calls made on this mock object and the method that was called + in the action and matches the given constraints + + + The mock. + The action. + The setup constraints. + + + Here we will get all the arguments for all the calls made to DoSomething(int) + + var argsForCalls = foo54.GetArgumentsForCallsMadeOn(x => x.DoSomething(0)) + + + + + + Asserts that a particular method was called on this mock object + + + The mock. + The action. + + + + Asserts that a particular method was called on this mock object that match + a particular constraint set. + + + The mock. + The action. + The setup constraints. + + + + Asserts that a particular method was called on this mock object that match + a particular constraint set. + + + The mock. + The action. + + + + Asserts that a particular method was called on this mock object that match + a particular constraint set. + + + The mock. + The action. + The setup constraints. + + + + Asserts that a particular method was NOT called on this mock object + + + The mock. + The action. + + + + Asserts that a particular method was NOT called on this mock object that match + a particular constraint set. + + + The mock. + The action. + The setup constraints. + + + + Asserts that a particular method was NOT called on this mock object + + + The mock. + The action. + + + + Asserts that a particular method was NOT called on this mock object + + + The mock. + The action. + The setup constraints. + + + + Finds the approprite implementation type of this item. + This is the class or an interface outside of the rhino mocks. + + The mocked obj. + + + + + Verifies all expectations on this mock object + + The mock object. + + + + Gets the event raiser for the event that was called in the action passed + + The type of the event source. + The mock object. + The event subscription. + + + + + Raise the specified event using the passed arguments. + The even is extracted from the passed labmda + + The type of the event source. + The mock object. + The event subscription. + The sender. + The instance containing the event data. + + + + Raise the specified event using the passed arguments. + The even is extracted from the passed labmda + + The type of the event source. + The mock object. + The event subscription. + The args. + + + TODO: Make this better! It currently breaks down when mocking classes or + ABC's that call other virtual methods which are getting intercepted too. I wish + we could just walk Expression{Action{Action{T}} to assert only a single + method is being made. + + The workaround is to not call foo.AssertWasCalled .. rather foo.VerifyAllExpectations() + The type of mock object + The mock repository + The actual mock object to assert expectations on. + + + + Fake type that disallow creating it. + Should have been System.Type, but we can't use it. + + + + + Utility class for dealing with messing generics scenarios. + + + + + There are issues with trying to get this to work correctly with open generic types, since this is an edge case, + I am letting the runtime handle it. + + + + + Gets the real type, including de-constructing and constructing the type of generic + methods parameters. + + The type. + The invocation. + + + + + Because we need to support complex types here (simple generics were handled above) we + need to be aware of the following scenarios: + List[T] and List[Foo[T]] + + + + + ExpectationsList + + + + + Dictionary + + + + + Dictionary class + + + + + Create a new instance of ProxyStateDictionary + + + + + Allows to call a method and immediately get it's options. + + + + + Interface to allow calling a method and immediately get it's options. + + + + + Get the method options for the call + + The method call should go here, the return value is ignored + + + + Creates a new instance. + + + + + Get the method options for the call + + The method call should go here, the return value is ignored + + + + Allows to call a method and immediately get it's options. + Set the expected number for the call to Any() + + + + + Creates a new instance. + + Proxy. + Mocked instance. + + + + Get the method options for the call + + The method call should go here, the return value is ignored + + + + This class is reponsible for taking a delegate and creating a wrapper + interface around it, so it can be mocked. + + + + + The scope for all the delegate interfaces create by this mock repository. + + + + + Gets a type with an "Invoke" method suitable for use as a target of the + specified delegate type. + + + + + + + Raise events for all subscribers for an event + + + + + Raise events for all subscribers for an event + + + + + Raise the event + + + + + The most common form for the event handler signature + + + + + Create an event raiser for the specified event on this instance. + + + + + Creates a new instance of EventRaiser + + + + + Raise the event + + + + + The most common signature for events + Here to allow intellisense to make better guesses about how + it should suggest parameters. + + + + + Allows to define what would happen when a method + is called. + + + + + Allows to define what would happen when a method + is called. + + + + + Set the return value for the method. + + The object the method will return + IRepeat that defines how many times the method will return this value + + + + Allow to override this return value in the future + + IRepeat that defines how many times the method will return this value + + + + Throws the specified exception when the method is called. + + Exception to throw + + + + Ignores the arguments for this method. Any argument will be matched + againt this method. + + + + + Add constraints for the method's arguments. + + + + + Set a callback method for the last call + + + + + Set a delegate to be called when the expectation is matched. + The delegate return value will be returned from the expectation. + + + + + Set a delegate to be called when the expectation is matched. + The delegate return value will be returned from the expectation. + + + + + Set a delegate to be called when the expectation is matched. + The delegate return value will be returned from the expectation. + + + + + Set a delegate to be called when the expectation is matched. + The delegate return value will be returned from the expectation. + + + + + Set a delegate to be called when the expectation is matched. + The delegate return value will be returned from the expectation. + + + + + Set a delegate to be called when the expectation is matched. + The delegate return value will be returned from the expectation. + + + + + Set a delegate to be called when the expectation is matched. + The delegate return value will be returned from the expectation. + + + + + Set a delegate to be called when the expectation is matched. + The delegate return value will be returned from the expectation. + + + + + Set a delegate to be called when the expectation is matched. + The delegate return value will be returned from the expectation. + + + + + Set a delegate to be called when the expectation is matched. + The delegate return value will be returned from the expectation. + + + + + Set a delegate to be called when the expectation is matched. + The delegate return value will be returned from the expectation. + + + + + Set a delegate to be called when the expectation is matched. + The delegate return value will be returned from the expectation. + + + + + Set a delegate to be called when the expectation is matched + and allow to optionally modify the invocation as needed + + + + + Call the original method on the class, bypassing the mocking layers. + + + + + + Call the original method on the class, optionally bypassing the mocking layers. + + + + + + Use the property as a simple property, getting/setting the values without + causing mock expectations. + + + + + Expect last (property) call as property setting, ignore the argument given + + + + + + Expect last (property) call as property setting with a given argument. + + + + + + + Get an event raiser for the last subscribed event. + + + + + Set the parameter values for out and ref parameters. + This is done using zero based indexing, and _ignoring_ any non out/ref parameter. + + + + + Documentation message for the expectation + + Message + + + + Better syntax to define repeats. + + + + + Allows to specify the number of time for method calls + + + + + Repeat the method twice. + + + + + Repeat the method once. + + + + + Repeat the method at least once, then repeat as many time as it would like. + + + + + Repeat the method any number of times. + This has special affects in that this method would now ignore orderring. + + + + + Set the range to repeat an action. + + Min. + Max. + + + + Set the amount of times to repeat an action. + + + + + This method must not appear in the replay state. + This has special affects in that this method would now ignore orderring. + + + + + Creates a new instance. + + the repository for this expectation + the recorder for this proxy + the proxy for this expectation + Expectation. + + + + Add constraints for the method's arguments. + + + + + Set a callback method for the last call + + + + + Set a callback method for the last call + + + + + Set a callback method for the last call + + + + + Set a callback method for the last call + + + + + Set a callback method for the last call + + + + + Set a callback method for the last call + + + + + Set a callback method for the last call + + + + + Set a callback method for the last call + + + + + Set a callback method for the last call + + + + + Set a callback method for the last call + + + + + Set a callback method for the last call + + + + + Set a callback method for the last call + + + + + Set a delegate to be called when the expectation is matched. + The delegate return value will be returned from the expectation. + + + + + Set a delegate to be called when the expectation is matched. + The delegate return value will be returned from the expectation. + + + + + Set the return value for the method. + + The object the method will return + IRepeat that defines how many times the method will return this value + + + + Set the return value for the method, but allow to override this return value in the future + + IRepeat that defines how many times the method will return this value + + + + Throws the specified exception when the method is called. + + Exception to throw + + + + Ignores the arguments for this method. Any argument will be matched + againt this method. + + + + + Call the original method on the class, bypassing the mocking layers. + + + + + + Call the original method on the class, optionally bypassing the mocking layers + + + + + + Use the property as a simple property, getting/setting the values without + causing mock expectations. + + + + + Expect last (property) call as property setting, ignore the argument given + + + + + + Expect last (property) call as property setting with a given argument. + + + + + + + Gets the event raiser for the last event + + + + + Set the parameter values for out and ref parameters. + This is done using zero based indexing, and _ignoring_ any non out/ref parameter. + + + + + Repeat the method twice. + + + + + Repeat the method once. + + + + + Repeat the method at least once, then repeat as many time as it would like. + + + + + This method must not appear in the replay state. + + + + + Documentation message for the expectation + + Message + + + + Repeat the method any number of times. + + + + + Set the range to repeat an action. + + Min. + Max. + + + + Set the amount of times to repeat an action. + + + + + Better syntax to define repeats. + + + + + This class will provide hash code for hashtables without needing + to call the GetHashCode() on the object, which may very well be mocked. + This class has no state so it is a singelton to avoid creating a lot of objects + that does the exact same thing. See flyweight patterns. + + + + + Get the hash code for a proxy object without calling GetHashCode() + on the object. + + + + + Compares two instances of mocked objects + + + + + Compare two mocked objects + + + + + The next hash code value for a mock object. + This is safe for multi threading. + + + + + The sole instance of + + + + + This is a dummy type that is used merely to give DynamicProxy the proxy instance that + it needs to create IProxy's types. + + + + + Interface to find the repository of a mocked object + + + + + Return true if it should call the original method on the object + instead of pass it to the message chain. + + The method to call + + + + Register a method to be called on the object directly + + + + + Register a property on the object that will behave as a simple property + + + + + Check if the method was registered as a property method. + + + + + Do get/set on the property, according to need. + + + + + Do add/remove on the event + + + + + Get the subscribers of a spesific event + + + + + Gets the declaring type of the method, taking into acccount the possible generic + parameters that it was created with. + + + + + Clears the state of the object, remove original calls, property behavior, subscribed events, etc. + + + + + Get all the method calls arguments that were made against this object with the specificed + method. + + + Only method calls in replay mode are counted + + + + + Records the method call + + + + + Mocks that are tied to this mock lifestyle + + + + + The unique hash code of this mock, which is not related + to the value of the GetHashCode() call on the object. + + + + + Gets the repository. + + + + + Gets the implemented types by this mocked object + + The implemented. + + + + Gets or sets the constructor arguments. + + The constructor arguments. + + + + The mocked instance that this is representing + + + + + Create a new instance of + + + + + Return true if it should call the original method on the object + instead of pass it to the message chain. + + The method to call + + + + Register a method to be called on the object directly + + + + + Register a property on the object that will behave as a simple property + Return true if there is already a value for the property + + + + + Check if the method was registered as a property method. + + + + + Do get/set on the property, according to need. + + + + + Do add/remove on the event + + + + + Get the subscribers of a spesific event + + + + + Gets the declaring type of the method, taking into acccount the possible generic + parameters that it was created with. + + + + + Get all the method calls arguments that were made against this object with the specificed + method. + + + + + Only method calls in replay mode are counted + + + + + Records the method call + + + + + + + Clears the state of the object, remove original calls, property behavior, subscribed events, etc. + + + + + Mocks that are tied to this mock lifestyle + + + + + The unique hash code of this proxy, which is not related + to the value of the GetHashCode() call on the object. + + + + + Gets the repository. + + + + + Gets or sets the constructor arguments. + + The constructor arguments. + + + + The mocked instance that this is representing + + + + + Gets the implemented types by this mocked object + + The implemented. + + + + Range for expected method calls + + + + + Creates a new instance. + + Min. + Max. + + + + Return the string representation of this range. + + + + + Gets or sets the min. + + + + + + Gets or sets the max. + + + + + + Records all the expectations for a mock and + return a ReplayDynamicMockState when Replay() + is called. + + + + + Creates a new instance. + + Repository. + The proxy that generates the method calls + + + + Verify that we can move to replay state and move + to the reply state. + + + + + Get the default call count range expectation + + + + + + Gets a mock state that match the original mock state of the object. + + + + + Records all the expectations for a mock and + return a ReplayPartialMockState when Replay() + is called. + + + + + Creates a new instance. + + Repository. + The proxy that generates the method calls + + + + Verify that we can move to replay state and move + to the reply state. + + + + + Gets a mock state that matches the original mock state of the object. + + + + + Options for special repeat option + + + + + This method can be called only as many times as the IMethodOptions.Expect allows. + + + + + This method should never be called + + + + + This method can be call any number of times + + + + + This method will call the original method + + + + + This method will call the original method, bypassing the mocking layer + + + + + This method will simulate simple property behavior + + + + + Validate all expectations on a mock and ignores calls to + any method that was not setup properly. + + + + + Creates a new instance. + + The previous state for this method + + + + Add a method call for this state' mock. + + The invocation for this method + The method that was called + The arguments this method was called with + + + + Gets a mock state that match the original mock state of the object. + + + + + Validate all expectations on a mock and ignores calls to + any method that was not setup properly. + + + + + Creates a new instance. + + The previous state for this method + + + + Add a method call for this state' mock. + + The invocation for this method + The method that was called + The arguments this method was called with + + + + Gets a mock state that match the original mock state of the object. + + + + + Summary description for RhinoInterceptor. + + + + + Creates a new instance. + + + + + Intercept a method call and direct it to the repository. + + + + + Validate arguments for methods + + + + + Validate that the passed argument is not null. + + The object to validate + The name of the argument + + If the obj is null, an ArgumentNullException with the passed name + is thrown. + + + + + Validate that the arguments are equal. + + Expected args. + Actual Args. + + + + Validate that the two arguments are equals, including validation for + when the arguments are collections, in which case it will validate their values. + + + + + This method is safe for use even if any of the objects is a mocked object + that override equals. + + + + + Throw an object already verified when accessed + + + + + Create a new instance of VerifiedMockState + + The previous mock state, used to get the initial record state + + + + Add a method call for this state' mock. + + The invocation for this method + The method that was called + The arguments this method was called with + + + + Verify that this mock expectations have passed. + + + + + Verify that we can move to replay state and move + to the reply state. + + + + + Gets a mock state that match the original mock state of the object. + + + + + Get the options for the last method call + + + + + Set the exception to throw when Verify is called. + This is used to report exception that may have happened but where caught in the code. + This way, they are reported anyway when Verify() is called. + + + + + not relevant + + + + + Gets the matching verify state for this state + + + + + Get the options for the last method call + + + + + Records the actions on all the mocks created by a repository. + + + + + Records the specified call with the specified args on the mocked object. + + + + + Get the expectation for this method on this object with this arguments + + + + + This check the methods that were setup using the SetupResult.For() + or LastCall.Repeat.Any() and that bypass the whole expectation model. + + + + + Gets the all expectations for a mocked object and method combination, + regardless of the expected arguments / callbacks / contraints. + + Mocked object. + Method. + List of all relevant expectation + + + + Gets the all expectations for proxy. + + Mocked object. + List of all relevant expectation + + + + Removes all the repeatable expectations for proxy. + + Mocked object. + + + + Replaces the old expectation with the new expectation for the specified proxy/method pair. + This replace ALL expectations that equal to old expectations. + + Proxy. + Method. + Old expectation. + New expectation. + + + + Adds the recorder and turn it into the active recorder. + + Recorder. + + + + Moves to previous recorder. + + + + + Gets the recorded expectation or null. + + + + + Gets the next expected calls string. + + + + + Moves to parent recorder. + + + + + Set the expectation so it can repeat any number of times. + + + + + Removes the expectation from the recorder + + + + + Clear the replayer to call (and all its chain of replayers) + This also removes it from the list of expectations, so it will never be considered again + + + + + Get the expectation for this method on this object with this arguments + + + + + Gets a value indicating whether this instance has expectations that weren't satisfied yet. + + + true if this instance has expectations; otherwise, false. + + + + + Allows to set various options for the last method call on + a specified object. + If the method has a return value, it's recommended to use Expect + + + + + Allows to get an interface to work on the last call. + + The mocked object + Interface that allows to set options for the last method call on this object + + + + Set the return value for the method. + + The object the method will return + IRepeat that defines how many times the method will return this value + + + + Set the return value for the method. This overload is needed for LastCall.Return(null) + + The object the method will return + IRepeat that defines how many times the method will return this value + + + + Throws the specified exception when the method is called. + + Exception to throw + + + + Ignores the arguments for this method. Any argument will be matched + againt this method. + + + + + Add constraints for the method's arguments. + + + + + Set a callback method for the last call + + + + + Set a callback method for the last call + + + + + Set a callback method for the last call + + + + + Set a callback method for the last call + + + + + Set a callback method for the last call + + + + + Set a callback method for the last call + + + + + Set a callback method for the last call + + + + + Set a callback method for the last call + + + + + Set a callback method for the last call + + + + + Set a callback method for the last call + + + + + Set a callback method for the last call + + + + + Set a callback method for the last call + + + + + Call the original method on the class, bypassing the mocking layers, for the last call. + + + + + Call the original method on the class, optionally bypassing the mocking layers, for the last call. + + + + + Set a delegate to be called when the expectation is matched. + The delegate return value will be returned from the expectation. + + + + + Gets an interface that will raise the last event when called. + + + + + Set the parameter values for out and ref parameters. + This is done using zero based indexing, and _ignoring_ any non out/ref parameter. + + + + + Documentation message for the expectation + + Message + + + + Use the property as a simple property, getting/setting the values without + causing mock expectations. + + + + + Better syntax to define repeats. + + + + + Base class for method recorders, handle delegating to inner recorder if needed. + + + + + List of the expected actions on for this recorder + The legal values are: + * Expectations + * Method Recorders + + + + + The current recorder. + + + + + The current replayer; + + + + + The parent recorder of this one, may be null. + + + + + This contains a list of all the replayers that should be ignored + for a spesific method call. A replayer gets into this list by calling + ClearReplayerToCall() on its parent. This list is Clear()ed on each new invocation. + + + + + All the repeatable methods calls. + + + + + Counts the recursion depth of the current expectation search stack + + + + + Creates a new instance. + + + + + Creates a new instance. + + Parent recorder. + Repeatable methods + + + + Records the specified call with the specified args on the mocked object. + + + + + Get the expectation for this method on this object with this arguments + + + + + Gets the all expectations for a mocked object and method combination, + regardless of the expected arguments / callbacks / contraints. + + Mocked object. + Method. + List of all relevant expectation + + + + Gets the all expectations for proxy. + + Mocked object. + List of all relevant expectation + + + + Replaces the old expectation with the new expectation for the specified proxy/method pair. + This replace ALL expectations that equal to old expectations. + + Proxy. + Method. + Old expectation. + New expectation. + + + + Remove the all repeatable expectations for proxy. + + Mocked object. + + + + Set the expectation so it can repeat any number of times. + + + + + Removes the expectation from the recorder + + + + + Adds the recorder and turn it into the active recorder. + + Recorder. + + + + Moves to previous recorder. + + + + + Moves to parent recorder. + + + + + Gets the recorded expectation or null. + + + + + Clear the replayer to call (and all its chain of replayers). + This also removes it from the list of expectations, so it will never be considered again + + + + + Get the expectation for this method on this object with this arguments + + + + + Gets the next expected calls string. + + + + + Handles the real getting of the recorded expectation or null. + + + + + Handle the real execution of this method for the derived class + + + + + Handle the real execution of this method for the derived class + + + + + Handle the real execution of this method for the derived class + + + + + Handle the real execution of this method for the derived class + + + + + Handle the real execution of this method for the derived class + + + + + Handle the real execution of this method for the derived class + + + + + Should this replayer be considered valid for this call? + + + + + This check the methods that were setup using the SetupResult.For() + or LastCall.Repeat.Any() and that bypass the whole expectation model. + + + + + Gets a value indicating whether this instance has expectations that weren't satisfied yet. + + + true if this instance has expectations; otherwise, false. + + + + + Handle the real execution of this method for the derived class + + + + + Ordered collection of methods, methods must arrive in specified order + in order to pass. + + + + + Unordered collection of method records, any expectation that exist + will be matched. + + + + + The parent recorder we have redirected to. + Useful for certain edge cases in orderring. + See: FieldProblem_Entropy for the details. + + + + + Creates a new instance. + + Parent recorder. + Repeatable methods + + + + Creates a new instance. + + + + + Records the specified call with the specified args on the mocked object. + + Mocked object. + Method. + Expectation. + + + + Get the expectation for this method on this object with this arguments + + Invocation for this method + Mocked object. + Method. + Args. + True is the call was recorded, false otherwise + + + + Gets the all expectations for a mocked object and method combination, + regardless of the expected arguments / callbacks / contraints. + + Mocked object. + Method. + List of all relevant expectation + + + + Gets the all expectations for proxy. + + Mocked object. + List of all relevant expectation + + + + Replaces the old expectation with the new expectation for the specified proxy/method pair. + This replace ALL expectations that equal to old expectations. + + Proxy. + Method. + Old expectation. + New expectation. + + + + Handle the real execution of this method for the derived class + + + + + Handles the real getting of the recorded expectation or null. + + + + + Handle the real execution of this method for the derived class + + + + + Gets the next expected calls string. + + + + + Create an exception for an unexpected method call. + + + + + Gets a value indicating whether this instance has expectations that weren't satisfied yet. + + + true if this instance has expectations; otherwise, false. + + + + + Creates a new instance. + + Parent recorder. + Repetable methods + + + + Creates a new instance. + + + + + Handles the real getting of the recorded expectation or null. + + + + + Get the expectation for this method on this object with this arguments + + + + + Gets the next expected calls string. + + + + + Hold an expectation for a method call on an object + + + + + Creates a new instance. + + Proxy. + Method. + Expectation. + + + + Determines if the object equal to this instance + + Obj. + + + + + Gets the hash code. + + + + + + Gets the proxy. + + + + + + Gets the method. + + + + + + Gets the expectation. + + + + + + Holds a pair of mocked object and a method + and allows to compare them against each other. + This allows us to have a distinction between mockOne.MyMethod() and + mockTwo.MyMethod()... + + + + + Creates a new instance. + + Proxy. + Method. + + + + Determines whatever obj equals to this instance. + ProxyMethodPairs are equal when they point to the same /instance/ of + an object, and to the same method. + + Obj. + + + + + Gets the hash code. + + + + + + Gets the proxy. + + + + + + Gets the method. + + + + + + Change the recorder from ordered to unordered and vice versa + + + + + Creates a new instance. + + + + + Disposes this instance. + + + + + Accessor for the current mocker + + + + + The current mocker + + + + + Used for [assembly: InternalsVisibleTo(RhinoMocks.StrongName)] + Used for [assembly: InternalsVisibleTo(RhinoMocks.NormalName)] + + + + + Strong name for the Dynamic Proxy assemblies. Used for InternalsVisibleTo specification. + + + + + Normal name for dynamic proxy assemblies. Used for InternalsVisibleTo specification. + + + + + Logs all method calls for methods + + + + + Setup method calls to repeat any number of times. + + + + + Get the method options and set the last method call to repeat + any number of times. + This also means that the method would transcend ordering + + + + + Get the method options for the last method call on the mockInstance and set it + to repeat any number of times. + This also means that the method would transcend ordering + + + + + Utility class for working with method calls. + + + + + Return the string representation of a method call and its arguments. + + The method + The method arguments + Invocation of the method, used to get the generics arguments + Delegate to format the parameter + The string representation of this method call + + + + Return the string representation of a method call and its arguments. + + The invocation of the method, used to get the generic parameters + The method + The method arguments + The string representation of this method call + + + + Delegate to format the argument for the string representation of + the method call. + + + + + Utility to get the default value for a type + + + + + The default value for a type. + Null for reference types and void + 0 for value types. + First element for enums + Note that we need to get the value even for opened generic types, such as those from + generic methods. + + Type. + The invocation. + the default value + + + + Allows easier access to MockRepository, works closely with Mocker.Current to + allow access to a context where the mock repository is automatially verified at + the end of the code block. + + + + + Initialize a code block where Mocker.Current is initialized. + At the end of the code block, all the expectation will be verified. + This overload will create a new MockRepository. + + The code that will be executed under the mock context + + + + Initialize a code block where Mocker.Current is initialized. + At the end of the code block, all the expectation will be verified. + This overload will create a new MockRepository. + + The mock repository to use, at the end of the code block, VerifyAll() will be called on the repository. + The code that will be executed under the mock context + + + + Create a FluentMocker + + The mock repository to use. + + + + A method with no arguments and no return value that will be called under the mock context. + + + + + FluentMocker implements some kind of fluent interface attempt + for saying "With the Mocks [mocks], Expecting (in same order) [things] verify [that]." + + + + + Interface to verify previously defined expectations + + + + + Verifies if a piece of code + + + + + Defines unordered expectations + + A delegate describing the expectations + an IMockVerifier + + + + Defines ordered expectations + + A delegate describing the expectations + an IMockVerifier + + + + Verifies previously defined expectations + + + + + This delegate is compatible with the System.Func{T,R} signature + We have to define our own to get compatability with 2.0 + + + + + This attribute is here so we can get better Pex integration + Using this means that Pex will not try to inspect the work of + the actual proxies being generated by Rhino Mocks + + + + diff --git a/Externals/NUnit/lib/log4net.dll b/Externals/NUnit/lib/log4net.dll new file mode 100644 index 0000000000..20a2e1c47 Binary files /dev/null and b/Externals/NUnit/lib/log4net.dll differ diff --git a/Externals/NUnit/lib/nunit-console-runner.dll b/Externals/NUnit/lib/nunit-console-runner.dll new file mode 100644 index 0000000000..f6bdf7edb Binary files /dev/null and b/Externals/NUnit/lib/nunit-console-runner.dll differ diff --git a/Externals/NUnit/lib/nunit-gui-runner.dll b/Externals/NUnit/lib/nunit-gui-runner.dll new file mode 100644 index 0000000000..be2f39a07 Binary files /dev/null and b/Externals/NUnit/lib/nunit-gui-runner.dll differ diff --git a/Externals/NUnit/lib/nunit.core.dll b/Externals/NUnit/lib/nunit.core.dll new file mode 100644 index 0000000000..0156d2d73 Binary files /dev/null and b/Externals/NUnit/lib/nunit.core.dll differ diff --git a/Externals/NUnit/lib/nunit.core.interfaces.dll b/Externals/NUnit/lib/nunit.core.interfaces.dll new file mode 100644 index 0000000000..32d9b1fd0 Binary files /dev/null and b/Externals/NUnit/lib/nunit.core.interfaces.dll differ diff --git a/Externals/NUnit/lib/nunit.uiexception.dll b/Externals/NUnit/lib/nunit.uiexception.dll new file mode 100644 index 0000000000..2a926b265 Binary files /dev/null and b/Externals/NUnit/lib/nunit.uiexception.dll differ diff --git a/Externals/NUnit/lib/nunit.uikit.dll b/Externals/NUnit/lib/nunit.uikit.dll new file mode 100644 index 0000000000..f0e9ae22b Binary files /dev/null and b/Externals/NUnit/lib/nunit.uikit.dll differ diff --git a/Externals/NUnit/lib/nunit.util.dll b/Externals/NUnit/lib/nunit.util.dll new file mode 100644 index 0000000000..c7e029476 Binary files /dev/null and b/Externals/NUnit/lib/nunit.util.dll differ diff --git a/Externals/NUnit/license.txt b/Externals/NUnit/license.txt new file mode 100644 index 0000000000..3b2ad7401 --- /dev/null +++ b/Externals/NUnit/license.txt @@ -0,0 +1,15 @@ +Copyright 2002-2014 Charlie Poole +Copyright 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov +Copyright 2000-2002 Philip A. Craig + +This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment (see the following) in the product documentation is required. + +Portions Copyright 2002-2014 Charlie Poole or Copyright 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov or Copyright 2000-2002 Philip A. Craig + +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source distribution. diff --git a/Externals/NUnit/nunit-agent-x86.exe b/Externals/NUnit/nunit-agent-x86.exe new file mode 100644 index 0000000000..39c908f49 Binary files /dev/null and b/Externals/NUnit/nunit-agent-x86.exe differ diff --git a/Externals/NUnit/nunit-agent-x86.exe.config b/Externals/NUnit/nunit-agent-x86.exe.config new file mode 100644 index 0000000000..43adb3b8d --- /dev/null +++ b/Externals/NUnit/nunit-agent-x86.exe.config @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Externals/NUnit/nunit-agent.exe b/Externals/NUnit/nunit-agent.exe new file mode 100644 index 0000000000..98718baeb Binary files /dev/null and b/Externals/NUnit/nunit-agent.exe differ diff --git a/Externals/NUnit/nunit-agent.exe.config b/Externals/NUnit/nunit-agent.exe.config new file mode 100644 index 0000000000..43adb3b8d --- /dev/null +++ b/Externals/NUnit/nunit-agent.exe.config @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Externals/NUnit/nunit-console-x86.exe b/Externals/NUnit/nunit-console-x86.exe new file mode 100644 index 0000000000..8f5eb9244 Binary files /dev/null and b/Externals/NUnit/nunit-console-x86.exe differ diff --git a/Externals/NUnit/nunit-console-x86.exe.config b/Externals/NUnit/nunit-console-x86.exe.config new file mode 100644 index 0000000000..c873deb48 --- /dev/null +++ b/Externals/NUnit/nunit-console-x86.exe.config @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + diff --git a/Externals/NUnit/nunit-console.exe b/Externals/NUnit/nunit-console.exe new file mode 100644 index 0000000000..e24be6abc Binary files /dev/null and b/Externals/NUnit/nunit-console.exe differ diff --git a/Externals/NUnit/nunit-console.exe.config b/Externals/NUnit/nunit-console.exe.config new file mode 100644 index 0000000000..c873deb48 --- /dev/null +++ b/Externals/NUnit/nunit-console.exe.config @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + diff --git a/Externals/NUnit/nunit-editor.exe b/Externals/NUnit/nunit-editor.exe new file mode 100644 index 0000000000..b8b4c6f84 Binary files /dev/null and b/Externals/NUnit/nunit-editor.exe differ diff --git a/Externals/NUnit/nunit-x86.exe b/Externals/NUnit/nunit-x86.exe new file mode 100644 index 0000000000..90a7c76a2 Binary files /dev/null and b/Externals/NUnit/nunit-x86.exe differ diff --git a/Externals/NUnit/nunit-x86.exe.config b/Externals/NUnit/nunit-x86.exe.config new file mode 100644 index 0000000000..7009cac86 --- /dev/null +++ b/Externals/NUnit/nunit-x86.exe.config @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + diff --git a/Externals/NUnit/nunit.exe b/Externals/NUnit/nunit.exe new file mode 100644 index 0000000000..9f2408684 Binary files /dev/null and b/Externals/NUnit/nunit.exe differ diff --git a/Externals/NUnit/nunit.exe.config b/Externals/NUnit/nunit.exe.config new file mode 100644 index 0000000000..7009cac86 --- /dev/null +++ b/Externals/NUnit/nunit.exe.config @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + diff --git a/Externals/NUnit/nunit.framework.dll b/Externals/NUnit/nunit.framework.dll new file mode 100644 index 0000000000..ed6550bb0 Binary files /dev/null and b/Externals/NUnit/nunit.framework.dll differ diff --git a/Externals/NUnit/nunit.framework.xml b/Externals/NUnit/nunit.framework.xml new file mode 100644 index 0000000000..532d82867 --- /dev/null +++ b/Externals/NUnit/nunit.framework.xml @@ -0,0 +1,10984 @@ + + + + nunit.framework + + + + + The different targets a test action attribute can be applied to + + + + + Default target, which is determined by where the action attribute is attached + + + + + Target a individual test case + + + + + Target a suite of test cases + + + + + Delegate used by tests that execute code and + capture any thrown exception. + + + + + The Assert class contains a collection of static methods that + implement the most common assertions used in NUnit. + + + + + We don't actually want any instances of this object, but some people + like to inherit from it to add other static methods. Hence, the + protected constructor disallows any instances of this object. + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + Throws a with the message and arguments + that are passed in. This allows a test to be cut short, with a result + of success returned to NUnit. + + The message to initialize the with. + Arguments to be used in formatting the message + + + + Throws a with the message and arguments + that are passed in. This allows a test to be cut short, with a result + of success returned to NUnit. + + The message to initialize the with. + + + + Throws a with the message and arguments + that are passed in. This allows a test to be cut short, with a result + of success returned to NUnit. + + + + + Throws an with the message and arguments + that are passed in. This is used by the other Assert functions. + + The message to initialize the with. + Arguments to be used in formatting the message + + + + Throws an with the message that is + passed in. This is used by the other Assert functions. + + The message to initialize the with. + + + + Throws an . + This is used by the other Assert functions. + + + + + Throws an with the message and arguments + that are passed in. This causes the test to be reported as ignored. + + The message to initialize the with. + Arguments to be used in formatting the message + + + + Throws an with the message that is + passed in. This causes the test to be reported as ignored. + + The message to initialize the with. + + + + Throws an . + This causes the test to be reported as ignored. + + + + + Throws an with the message and arguments + that are passed in. This causes the test to be reported as inconclusive. + + The message to initialize the with. + Arguments to be used in formatting the message + + + + Throws an with the message that is + passed in. This causes the test to be reported as inconclusive. + + The message to initialize the with. + + + + Throws an . + This causes the test to be reported as Inconclusive. + + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint expression to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display if the condition is false + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display if the condition is false + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + An ActualValueDelegate returning the value to be tested + A Constraint expression to be applied + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + An ActualValueDelegate returning the value to be tested + A Constraint expression to be applied + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + An ActualValueDelegate returning the value to be tested + A Constraint expression to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that the code represented by a delegate throws an exception + that satisfies the constraint provided. + + A TestDelegate to be executed + A ThrowsConstraint used in the test + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + Used as a synonym for That in rare cases where a private setter + causes a Visual Basic compilation error. + + The actual value to test + A Constraint to be applied + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + Used as a synonym for That in rare cases where a private setter + causes a Visual Basic compilation error. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + Used as a synonym for That in rare cases where a private setter + causes a Visual Basic compilation error. + + + This method is provided for use by VB developers needing to test + the value of properties with private setters. + + The actual value to test + A Constraint expression to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws a particular exception when called. + + A constraint to be satisfied by the exception + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws a particular exception when called. + + A constraint to be satisfied by the exception + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws a particular exception when called. + + A constraint to be satisfied by the exception + A TestDelegate + + + + Verifies that a delegate throws a particular exception when called. + + The exception Type expected + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws a particular exception when called. + + The exception Type expected + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws a particular exception when called. + + The exception Type expected + A TestDelegate + + + + Verifies that a delegate throws a particular exception when called. + + Type of the expected exception + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws a particular exception when called. + + Type of the expected exception + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws a particular exception when called. + + Type of the expected exception + A TestDelegate + + + + Verifies that a delegate throws an exception when called + and returns it. + + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws an exception when called + and returns it. + + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws an exception when called + and returns it. + + A TestDelegate + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + + + + Verifies that a delegate does not throw an exception + + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate does not throw an exception. + + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate does not throw an exception. + + A TestDelegate + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display in case of failure + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display in case of failure + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + The message to display in case of failure + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + The message to display in case of failure + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + + + + Verifies that two ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two unsigned ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two unsigned ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two unsigned ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two unsigned longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two unsigned longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two unsigned longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two decimals are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two decimals are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two decimals are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message to display in case of failure + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message to display in case of failure + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + + + + Verifies that two objects are equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are not equal an is thrown. + + The value that is expected + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two objects are equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are not equal an is thrown. + + The value that is expected + The actual value + The message to display in case of failure + + + + Verifies that two objects are equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are not equal an is thrown. + + The value that is expected + The actual value + + + + Verifies that two ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two unsigned ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two unsigned ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two unsigned ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two unsigned longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two unsigned longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two unsigned longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two decimals are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two decimals are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two decimals are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two floats are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two floats are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two floats are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two doubles are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two doubles are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two doubles are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two objects are not equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are equal an is thrown. + + The value that is expected + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two objects are not equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are equal an is thrown. + + The value that is expected + The actual value + The message to display in case of failure + + + + Verifies that two objects are not equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are equal an is thrown. + + The value that is expected + The actual value + + + + Asserts that two objects refer to the same object. If they + are not the same an is thrown. + + The expected object + The actual object + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that two objects refer to the same object. If they + are not the same an is thrown. + + The expected object + The actual object + The message to display in case of failure + + + + Asserts that two objects refer to the same object. If they + are not the same an is thrown. + + The expected object + The actual object + + + + Asserts that two objects do not refer to the same object. If they + are the same an is thrown. + + The expected object + The actual object + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that two objects do not refer to the same object. If they + are the same an is thrown. + + The expected object + The actual object + The message to display in case of failure + + + + Asserts that two objects do not refer to the same object. If they + are the same an is thrown. + + The expected object + The actual object + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + The message to display in case of failure + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + The message to display in case of failure + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + + + + Assert that a string is empty - that is equal to string.Empty + + The string to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that a string is empty - that is equal to string.Empty + + The string to be tested + The message to display in case of failure + + + + Assert that a string is empty - that is equal to string.Empty + + The string to be tested + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing ICollection + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing ICollection + The message to display in case of failure + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing ICollection + + + + Assert that a string is not empty - that is not equal to string.Empty + + The string to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that a string is not empty - that is not equal to string.Empty + + The string to be tested + The message to display in case of failure + + + + Assert that a string is not empty - that is not equal to string.Empty + + The string to be tested + + + + Assert that an array, list or other collection is not empty + + An array, list or other collection implementing ICollection + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that an array, list or other collection is not empty + + An array, list or other collection implementing ICollection + The message to display in case of failure + + + + Assert that an array, list or other collection is not empty + + An array, list or other collection implementing ICollection + + + + Assert that a string is either null or equal to string.Empty + + The string to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that a string is either null or equal to string.Empty + + The string to be tested + The message to display in case of failure + + + + Assert that a string is either null or equal to string.Empty + + The string to be tested + + + + Assert that a string is not null or empty + + The string to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that a string is not null or empty + + The string to be tested + The message to display in case of failure + + + + Assert that a string is not null or empty + + The string to be tested + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Asserts that an object is contained in a list. + + The expected object + The list to be examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is contained in a list. + + The expected object + The list to be examined + The message to display in case of failure + + + + Asserts that an object is contained in a list. + + The expected object + The list to be examined + + + + Helper for Assert.AreEqual(double expected, double actual, ...) + allowing code generation to work consistently. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Gets the number of assertions executed so far and + resets the counter to zero. + + + + + AssertionHelper is an optional base class for user tests, + allowing the use of shorter names for constraints and + asserts and avoiding conflict with the definition of + , from which it inherits much of its + behavior, in certain mock object frameworks. + + + + + Helper class with properties and methods that supply + a number of constraints used in Asserts. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding only if a specified number of them succeed. + + + + + Returns a new PropertyConstraintExpression, which will either + test for the existence of the named property on the object + being tested or apply any following constraint to that property. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns a constraint that tests two items for equality + + + + + Returns a constraint that tests that two references are the same object + + + + + Returns a constraint that tests whether the + actual value is greater than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a collection containing the same elements as the + collection supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a subset of the collection supplied as an argument. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a new ContainsConstraint. This constraint + will, in turn, make use of the appropriate second-level + constraint, depending on the type of the actual argument. + This overload is only used if the item sought is a string, + since any other type implies that we are looking for a + collection member. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the regular expression supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the regular expression supplied as an argument. + + + + + Returns a constraint that fails if the actual + value matches the pattern supplied as an argument. + + + + + Returns a constraint that tests whether the path provided + is the same as an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is the same path or under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is the same path or under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the actual value falls + within a specified range. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if at least one of them succeeds. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them fail. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Length property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Count property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Message property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the InnerException property of the object being tested. + + + + + Returns a constraint that tests for null + + + + + Returns a constraint that tests for True + + + + + Returns a constraint that tests for False + + + + + Returns a constraint that tests for a positive value + + + + + Returns a constraint that tests for a negative value + + + + + Returns a constraint that tests for NaN + + + + + Returns a constraint that tests for empty + + + + + Returns a constraint that tests whether a collection + contains all unique items. + + + + + Returns a constraint that tests whether an object graph is serializable in binary format. + + + + + Returns a constraint that tests whether an object graph is serializable in xml format. + + + + + Returns a constraint that tests whether a collection is ordered + + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. Works + identically to Assert.That. + + The actual value to test + A Constraint to be applied + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. Works + identically to Assert.That. + + The actual value to test + A Constraint to be applied + The message to be displayed in case of failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. Works + identically to Assert.That. + + The actual value to test + A Constraint to be applied + The message to be displayed in case of failure + Arguments to use in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . Works Identically to + . + + The evaluated condition + The message to display if the condition is false + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . Works Identically to + . + + The evaluated condition + The message to display if the condition is false + + + + Asserts that a condition is true. If the condition is false the method throws + an . Works Identically to . + + The evaluated condition + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + A Constraint expression to be applied + An ActualValueDelegate returning the value to be tested + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + A Constraint expression to be applied + An ActualValueDelegate returning the value to be tested + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + An ActualValueDelegate returning the value to be tested + A Constraint expression to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that the code represented by a delegate throws an exception + that satisfies the constraint provided. + + A TestDelegate to be executed + A ThrowsConstraint used in the test + + + + Returns a ListMapper based on a collection. + + The original collection + + + + + Provides static methods to express the assumptions + that must be met for a test to give a meaningful + result. If an assumption is not met, the test + should produce an inconclusive result. + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display if the condition is false + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display if the condition is false + + + + Asserts that a condition is true. If the condition is false the + method throws an . + + The evaluated condition + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + An ActualValueDelegate returning the value to be tested + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + An ActualValueDelegate returning the value to be tested + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + An ActualValueDelegate returning the value to be tested + A Constraint expression to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + The message that will be displayed on failure + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that the code represented by a delegate throws an exception + that satisfies the constraint provided. + + A TestDelegate to be executed + A ThrowsConstraint used in the test + + + + Waits for pending asynchronous operations to complete, if appropriate, + and returns a proper result of the invocation by unwrapping task results + + The raw result of the method invocation + The unwrapped result, if necessary + + + + A set of Assert methods operationg on one or more collections + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + Asserts that all items contained in collection are of the type specified by expectedType. + + IEnumerable containing objects to be considered + System.Type that all objects in collection must be instances of + + + + Asserts that all items contained in collection are of the type specified by expectedType. + + IEnumerable containing objects to be considered + System.Type that all objects in collection must be instances of + The message that will be displayed on failure + + + + Asserts that all items contained in collection are of the type specified by expectedType. + + IEnumerable containing objects to be considered + System.Type that all objects in collection must be instances of + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that all items contained in collection are not equal to null. + + IEnumerable containing objects to be considered + + + + Asserts that all items contained in collection are not equal to null. + + IEnumerable containing objects to be considered + The message that will be displayed on failure + + + + Asserts that all items contained in collection are not equal to null. + + IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Ensures that every object contained in collection exists within the collection + once and only once. + + IEnumerable of objects to be considered + + + + Ensures that every object contained in collection exists within the collection + once and only once. + + IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Ensures that every object contained in collection exists within the collection + once and only once. + + IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + The message that will be displayed on failure + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are equivalent, containing the same objects but the match may be in any order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + + + + Asserts that expected and actual are equivalent, containing the same objects but the match may be in any order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Asserts that expected and actual are equivalent, containing the same objects but the match may be in any order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are not exactly equal. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + + + + Asserts that expected and actual are not exactly equal. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + + + + Asserts that expected and actual are not exactly equal. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Asserts that expected and actual are not exactly equal. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + The message that will be displayed on failure + + + + Asserts that expected and actual are not exactly equal. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are not exactly equal. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are not equivalent. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + + + + Asserts that expected and actual are not equivalent. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Asserts that expected and actual are not equivalent. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that collection contains actual as an item. + + IEnumerable of objects to be considered + Object to be found within collection + + + + Asserts that collection contains actual as an item. + + IEnumerable of objects to be considered + Object to be found within collection + The message that will be displayed on failure + + + + Asserts that collection contains actual as an item. + + IEnumerable of objects to be considered + Object to be found within collection + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that collection does not contain actual as an item. + + IEnumerable of objects to be considered + Object that cannot exist within collection + + + + Asserts that collection does not contain actual as an item. + + IEnumerable of objects to be considered + Object that cannot exist within collection + The message that will be displayed on failure + + + + Asserts that collection does not contain actual as an item. + + IEnumerable of objects to be considered + Object that cannot exist within collection + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that the superset does not contain the subset + + The IEnumerable subset to be considered + The IEnumerable superset to be considered + + + + Asserts that the superset does not contain the subset + + The IEnumerable subset to be considered + The IEnumerable superset to be considered + The message that will be displayed on failure + + + + Asserts that the superset does not contain the subset + + The IEnumerable subset to be considered + The IEnumerable superset to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that the superset contains the subset. + + The IEnumerable subset to be considered + The IEnumerable superset to be considered + + + + Asserts that the superset contains the subset. + + The IEnumerable subset to be considered + The IEnumerable superset to be considered + The message that will be displayed on failure + + + + Asserts that the superset contains the subset. + + The IEnumerable subset to be considered + The IEnumerable superset to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + + + + Assert that an array,list or other collection is empty + + An array, list or other collection implementing IEnumerable + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + + + + Assert that an array,list or other collection is empty + + An array, list or other collection implementing IEnumerable + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + A custom comparer to perform the comparisons + The message to be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + A custom comparer to perform the comparisons + The message to be displayed on failure + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + A custom comparer to perform the comparisons + + + + Helper class with properties and methods that supply + a number of constraints used in Asserts. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Summary description for DirectoryAssert + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + We don't actually want any instances of this object, but some people + like to inherit from it to add other static methods. Hence, the + protected constructor disallows any instances of this object. + + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + The message to display if directories are not equal + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + The message to display if directories are not equal + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + The message to display if directories are not equal + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + The message to display if directories are equal + Arguments to be used in formatting the message + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + The message to display if directories are equal + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + The message to display if directories are not equal + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + The message to display if directories are not equal + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + The message to display if directories are not equal + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + The message to display if directories are not equal + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + Arguments to be used in formatting the message + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + Arguments to be used in formatting the message + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + Arguments to be used in formatting the message + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + Arguments to be used in formatting the message + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + + + + Summary description for FileAssert. + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + We don't actually want any instances of this object, but some people + like to inherit from it to add other static methods. Hence, the + protected constructor disallows any instances of this object. + + + + + Verifies that two Streams are equal. Two Streams are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The expected Stream + The actual Stream + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Verifies that two Streams are equal. Two Streams are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The expected Stream + The actual Stream + The message to display if objects are not equal + + + + Verifies that two Streams are equal. Two Streams are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The expected Stream + The actual Stream + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A file containing the value that is expected + A file containing the actual value + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A file containing the value that is expected + A file containing the actual value + The message to display if objects are not equal + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A file containing the value that is expected + A file containing the actual value + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + The message to display if objects are not equal + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + + + + Asserts that two Streams are not equal. If they are equal + an is thrown. + + The expected Stream + The actual Stream + The message to be displayed when the two Stream are the same. + Arguments to be used in formatting the message + + + + Asserts that two Streams are not equal. If they are equal + an is thrown. + + The expected Stream + The actual Stream + The message to be displayed when the Streams are the same. + + + + Asserts that two Streams are not equal. If they are equal + an is thrown. + + The expected Stream + The actual Stream + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + A file containing the value that is expected + A file containing the actual value + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + A file containing the value that is expected + A file containing the actual value + The message to display if objects are not equal + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + A file containing the value that is expected + A file containing the actual value + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + The message to display if objects are not equal + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + + + + GlobalSettings is a place for setting default values used + by the framework in performing asserts. + + + + + Default tolerance for floating point equality + + + + + Class used to guard against unexpected argument values + by throwing an appropriate exception. + + + + + Throws an exception if an argument is null + + The value to be tested + The name of the argument + + + + Throws an exception if a string argument is null or empty + + The value to be tested + The name of the argument + + + + Helper class with properties and methods that supply + a number of constraints used in Asserts. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding only if a specified number of them succeed. + + + + + Returns a new PropertyConstraintExpression, which will either + test for the existence of the named property on the object + being tested or apply any following constraint to that property. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if at least one of them succeeds. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them fail. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Length property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Count property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Message property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the InnerException property of the object being tested. + + + + + Interface implemented by a user fixture in order to + validate any expected exceptions. It is only called + for test methods marked with the ExpectedException + attribute. + + + + + Method to handle an expected exception + + The exception to be handled + + + + Helper class with properties and methods that supply + a number of constraints used in Asserts. + + + + + Returns a constraint that tests two items for equality + + + + + Returns a constraint that tests that two references are the same object + + + + + Returns a constraint that tests whether the + actual value is greater than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a collection containing the same elements as the + collection supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a subset of the collection supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the regular expression supplied as an argument. + + + + + Returns a constraint that tests whether the path provided + is the same as an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is the same path or under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the actual value falls + within a specified range. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. + + + + + Returns a constraint that tests for null + + + + + Returns a constraint that tests for True + + + + + Returns a constraint that tests for False + + + + + Returns a constraint that tests for a positive value + + + + + Returns a constraint that tests for a negative value + + + + + Returns a constraint that tests for NaN + + + + + Returns a constraint that tests for empty + + + + + Returns a constraint that tests whether a collection + contains all unique items. + + + + + Returns a constraint that tests whether an object graph is serializable in binary format. + + + + + Returns a constraint that tests whether an object graph is serializable in xml format. + + + + + Returns a constraint that tests whether a collection is ordered + + + + + The ITestCaseData interface is implemented by a class + that is able to return complete testcases for use by + a parameterized test method. + + NOTE: This interface is used in both the framework + and the core, even though that results in two different + types. However, sharing the source code guarantees that + the various implementations will be compatible and that + the core is able to reflect successfully over the + framework implementations of ITestCaseData. + + + + + Gets the argument list to be provided to the test + + + + + Gets the expected result + + + + + Indicates whether a result has been specified. + This is necessary because the result may be + null, so it's value cannot be checked. + + + + + Gets the expected exception Type + + + + + Gets the FullName of the expected exception + + + + + Gets the name to be used for the test + + + + + Gets the description of the test + + + + + Gets a value indicating whether this is ignored. + + true if ignored; otherwise, false. + + + + Gets a value indicating whether this is explicit. + + true if explicit; otherwise, false. + + + + Gets the ignore reason. + + The ignore reason. + + + + The Iz class is a synonym for Is intended for use in VB, + which regards Is as a keyword. + + + + + The List class is a helper class with properties and methods + that supply a number of constraints used with lists and collections. + + + + + List.Map returns a ListMapper, which can be used to map + the original collection to another collection. + + + + + + + ListMapper is used to transform a collection used as an actual argument + producing another collection to be used in the assertion. + + + + + Construct a ListMapper based on a collection + + The collection to be transformed + + + + Produces a collection containing all the values of a property + + The collection of property values + + + + + Randomizer returns a set of random values in a repeatable + way, to allow re-running of tests if necessary. + + + + + Get a randomizer for a particular member, returning + one that has already been created if it exists. + This ensures that the same values are generated + each time the tests are reloaded. + + + + + Get a randomizer for a particular parameter, returning + one that has already been created if it exists. + This ensures that the same values are generated + each time the tests are reloaded. + + + + + Construct a randomizer using a random seed + + + + + Construct a randomizer using a specified seed + + + + + Return an array of random doubles between 0.0 and 1.0. + + + + + + + Return an array of random doubles with values in a specified range. + + + + + Return an array of random ints with values in a specified range. + + + + + Get a random seed for use in creating a randomizer. + + + + + The SpecialValue enum is used to represent TestCase arguments + that cannot be used as arguments to an Attribute. + + + + + Null represents a null value, which cannot be used as an + argument to an attribute under .NET 1.x + + + + + Basic Asserts on strings. + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + + + + Asserts that a string is not found within another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + + + + Asserts that a string starts with another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string starts with another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string starts with another string. + + The expected string + The string to be examined + + + + Asserts that a string does not start with another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string does not start with another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string does not start with another string. + + The expected string + The string to be examined + + + + Asserts that a string ends with another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string ends with another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string ends with another string. + + The expected string + The string to be examined + + + + Asserts that a string does not end with another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string does not end with another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string does not end with another string. + + The expected string + The string to be examined + + + + Asserts that two strings are equal, without regard to case. + + The expected string + The actual string + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that two strings are equal, without regard to case. + + The expected string + The actual string + The message to display in case of failure + + + + Asserts that two strings are equal, without regard to case. + + The expected string + The actual string + + + + Asserts that two strings are not equal, without regard to case. + + The expected string + The actual string + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that two strings are Notequal, without regard to case. + + The expected string + The actual string + The message to display in case of failure + + + + Asserts that two strings are not equal, without regard to case. + + The expected string + The actual string + + + + Asserts that a string matches an expected regular expression pattern. + + The regex pattern to be matched + The actual string + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string matches an expected regular expression pattern. + + The regex pattern to be matched + The actual string + The message to display in case of failure + + + + Asserts that a string matches an expected regular expression pattern. + + The regex pattern to be matched + The actual string + + + + Asserts that a string does not match an expected regular expression pattern. + + The regex pattern to be used + The actual string + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string does not match an expected regular expression pattern. + + The regex pattern to be used + The actual string + The message to display in case of failure + + + + Asserts that a string does not match an expected regular expression pattern. + + The regex pattern to be used + The actual string + + + + The TestCaseData class represents a set of arguments + and other parameter info to be used for a parameterized + test case. It provides a number of instance modifiers + for use in initializing the test case. + + Note: Instance modifiers are getters that return + the same instance after modifying it's state. + + + + + The argument list to be provided to the test + + + + + The expected result to be returned + + + + + Set to true if this has an expected result + + + + + The expected exception Type + + + + + The FullName of the expected exception + + + + + The name to be used for the test + + + + + The description of the test + + + + + A dictionary of properties, used to add information + to tests without requiring the class to change. + + + + + If true, indicates that the test case is to be ignored + + + + + If true, indicates that the test case is marked explicit + + + + + The reason for ignoring a test case + + + + + Initializes a new instance of the class. + + The arguments. + + + + Initializes a new instance of the class. + + The argument. + + + + Initializes a new instance of the class. + + The first argument. + The second argument. + + + + Initializes a new instance of the class. + + The first argument. + The second argument. + The third argument. + + + + Sets the expected result for the test + + The expected result + A modified TestCaseData + + + + Sets the expected exception type for the test + + Type of the expected exception. + The modified TestCaseData instance + + + + Sets the expected exception type for the test + + FullName of the expected exception. + The modified TestCaseData instance + + + + Sets the name of the test case + + The modified TestCaseData instance + + + + Sets the description for the test case + being constructed. + + The description. + The modified TestCaseData instance. + + + + Applies a category to the test + + + + + + + Applies a named property to the test + + + + + + + + Applies a named property to the test + + + + + + + + Applies a named property to the test + + + + + + + + Ignores this TestCase. + + + + + + Ignores this TestCase, specifying the reason. + + The reason. + + + + + Marks this TestCase as Explicit + + + + + + Marks this TestCase as Explicit, specifying the reason. + + The reason. + + + + + Gets the argument list to be provided to the test + + + + + Gets the expected result + + + + + Returns true if the result has been set + + + + + Gets the expected exception Type + + + + + Gets the FullName of the expected exception + + + + + Gets the name to be used for the test + + + + + Gets the description of the test + + + + + Gets a value indicating whether this is ignored. + + true if ignored; otherwise, false. + + + + Gets a value indicating whether this is explicit. + + true if explicit; otherwise, false. + + + + Gets the ignore reason. + + The ignore reason. + + + + Gets a list of categories associated with this test. + + + + + Gets the property dictionary for this test + + + + + Provide the context information of the current test + + + + + Constructs a TestContext using the provided context dictionary + + A context dictionary + + + + Get the current test context. This is created + as needed. The user may save the context for + use within a test, but it should not be used + outside the test for which it is created. + + + + + Gets a TestAdapter representing the currently executing test in this context. + + + + + Gets a ResultAdapter representing the current result for the test + executing in this context. + + + + + Gets the directory containing the current test assembly. + + + + + Gets the directory to be used for outputing files created + by this test run. + + + + + TestAdapter adapts a Test for consumption by + the user test code. + + + + + Constructs a TestAdapter for this context + + The context dictionary + + + + The name of the test. + + + + + The FullName of the test + + + + + The properties of the test. + + + + + ResultAdapter adapts a TestResult for consumption by + the user test code. + + + + + Construct a ResultAdapter for a context + + The context holding the result + + + + The TestState of current test. This maps to the ResultState + used in nunit.core and is subject to change in the future. + + + + + The TestStatus of current test. This enum will be used + in future versions of NUnit and so is to be preferred + to the TestState value. + + + + + Provides details about a test + + + + + Creates an instance of TestDetails + + The fixture that the test is a member of, if available. + The method that implements the test, if available. + The full name of the test. + A string representing the type of test, e.g. "Test Case". + Indicates if the test represents a suite of tests. + + + + The fixture that the test is a member of, if available. + + + + + The method that implements the test, if available. + + + + + The full name of the test. + + + + + A string representing the type of test, e.g. "Test Case". + + + + + Indicates if the test represents a suite of tests. + + + + + The ResultState enum indicates the result of running a test + + + + + The result is inconclusive + + + + + The test was not runnable. + + + + + The test has been skipped. + + + + + The test has been ignored. + + + + + The test succeeded + + + + + The test failed + + + + + The test encountered an unexpected exception + + + + + The test was cancelled by the user + + + + + The TestStatus enum indicates the result of running a test + + + + + The test was inconclusive + + + + + The test has skipped + + + + + The test succeeded + + + + + The test failed + + + + + Helper class with static methods used to supply constraints + that operate on strings. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the Regex pattern supplied as an argument. + + + + + Returns a constraint that fails if the actual + value matches the pattern supplied as an argument. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. + + + + + TextMessageWriter writes constraint descriptions and messages + in displayable form as a text stream. It tailors the display + of individual message components to form the standard message + format of NUnit assertion failure messages. + + + + + MessageWriter is the abstract base for classes that write + constraint descriptions and messages in some form. The + class has separate methods for writing various components + of a message, allowing implementations to tailor the + presentation as needed. + + + + + Construct a MessageWriter given a culture + + + + + Method to write single line message with optional args, usually + written to precede the general failure message. + + The message to be written + Any arguments used in formatting the message + + + + Method to write single line message with optional args, usually + written to precede the general failure message, at a givel + indentation level. + + The indentation level of the message + The message to be written + Any arguments used in formatting the message + + + + Display Expected and Actual lines for a constraint. This + is called by MessageWriter's default implementation of + WriteMessageTo and provides the generic two-line display. + + The constraint that failed + + + + Display Expected and Actual lines for given values. This + method may be called by constraints that need more control over + the display of actual and expected values than is provided + by the default implementation. + + The expected value + The actual value causing the failure + + + + Display Expected and Actual lines for given values, including + a tolerance value on the Expected line. + + The expected value + The actual value causing the failure + The tolerance within which the test was made + + + + Display the expected and actual string values on separate lines. + If the mismatch parameter is >=0, an additional line is displayed + line containing a caret that points to the mismatch point. + + The expected string value + The actual string value + The point at which the strings don't match or -1 + If true, case is ignored in locating the point where the strings differ + If true, the strings should be clipped to fit the line + + + + Writes the text for a connector. + + The connector. + + + + Writes the text for a predicate. + + The predicate. + + + + Writes the text for an expected value. + + The expected value. + + + + Writes the text for a modifier + + The modifier. + + + + Writes the text for an actual value. + + The actual value. + + + + Writes the text for a generalized value. + + The value. + + + + Writes the text for a collection value, + starting at a particular point, to a max length + + The collection containing elements to write. + The starting point of the elements to write + The maximum number of elements to write + + + + Abstract method to get the max line length + + + + + Prefix used for the expected value line of a message + + + + + Prefix used for the actual value line of a message + + + + + Length of a message prefix + + + + + Construct a TextMessageWriter + + + + + Construct a TextMessageWriter, specifying a user message + and optional formatting arguments. + + + + + + + Method to write single line message with optional args, usually + written to precede the general failure message, at a givel + indentation level. + + The indentation level of the message + The message to be written + Any arguments used in formatting the message + + + + Display Expected and Actual lines for a constraint. This + is called by MessageWriter's default implementation of + WriteMessageTo and provides the generic two-line display. + + The constraint that failed + + + + Display Expected and Actual lines for given values. This + method may be called by constraints that need more control over + the display of actual and expected values than is provided + by the default implementation. + + The expected value + The actual value causing the failure + + + + Display Expected and Actual lines for given values, including + a tolerance value on the expected line. + + The expected value + The actual value causing the failure + The tolerance within which the test was made + + + + Display the expected and actual string values on separate lines. + If the mismatch parameter is >=0, an additional line is displayed + line containing a caret that points to the mismatch point. + + The expected string value + The actual string value + The point at which the strings don't match or -1 + If true, case is ignored in string comparisons + If true, clip the strings to fit the max line length + + + + Writes the text for a connector. + + The connector. + + + + Writes the text for a predicate. + + The predicate. + + + + Write the text for a modifier. + + The modifier. + + + + Writes the text for an expected value. + + The expected value. + + + + Writes the text for an actual value. + + The actual value. + + + + Writes the text for a generalized value. + + The value. + + + + Writes the text for a collection value, + starting at a particular point, to a max length + + The collection containing elements to write. + The starting point of the elements to write + The maximum number of elements to write + + + + Write the generic 'Expected' line for a constraint + + The constraint that failed + + + + Write the generic 'Expected' line for a given value + + The expected value + + + + Write the generic 'Expected' line for a given value + and tolerance. + + The expected value + The tolerance within which the test was made + + + + Write the generic 'Actual' line for a constraint + + The constraint for which the actual value is to be written + + + + Write the generic 'Actual' line for a given value + + The actual value causing a failure + + + + Gets or sets the maximum line length for this writer + + + + + Helper class with properties and methods that supply + constraints that operate on exceptions. + + + + + Creates a constraint specifying the exact type of exception expected + + + + + Creates a constraint specifying the exact type of exception expected + + + + + Creates a constraint specifying the type of exception expected + + + + + Creates a constraint specifying the type of exception expected + + + + + Creates a constraint specifying an expected exception + + + + + Creates a constraint specifying an exception with a given InnerException + + + + + Creates a constraint specifying an expected TargetInvocationException + + + + + Creates a constraint specifying an expected TargetInvocationException + + + + + Creates a constraint specifying an expected TargetInvocationException + + + + + Creates a constraint specifying that no exception is thrown + + + + + Attribute used to apply a category to a test + + + + + The name of the category + + + + + Construct attribute for a given category based on + a name. The name may not contain the characters ',', + '+', '-' or '!'. However, this is not checked in the + constructor since it would cause an error to arise at + as the test was loaded without giving a clear indication + of where the problem is located. The error is handled + in NUnitFramework.cs by marking the test as not + runnable. + + The name of the category + + + + Protected constructor uses the Type name as the name + of the category. + + + + + The name of the category + + + + + Used to mark a field for use as a datapoint when executing a theory + within the same fixture that requires an argument of the field's Type. + + + + + Used to mark an array as containing a set of datapoints to be used + executing a theory within the same fixture that requires an argument + of the Type of the array elements. + + + + + Attribute used to provide descriptive text about a + test case or fixture. + + + + + Construct the attribute + + Text describing the test + + + + Gets the test description + + + + + Enumeration indicating how the expected message parameter is to be used + + + + Expect an exact match + + + Expect a message containing the parameter string + + + Match the regular expression provided as a parameter + + + Expect a message that starts with the parameter string + + + + ExpectedExceptionAttribute + + + + + + Constructor for a non-specific exception + + + + + Constructor for a given type of exception + + The type of the expected exception + + + + Constructor for a given exception name + + The full name of the expected exception + + + + Gets or sets the expected exception type + + + + + Gets or sets the full Type name of the expected exception + + + + + Gets or sets the expected message text + + + + + Gets or sets the user message displayed in case of failure + + + + + Gets or sets the type of match to be performed on the expected message + + + + + Gets the name of a method to be used as an exception handler + + + + + ExplicitAttribute marks a test or test fixture so that it will + only be run if explicitly executed from the gui or command line + or if it is included by use of a filter. The test will not be + run simply because an enclosing suite is run. + + + + + Default constructor + + + + + Constructor with a reason + + The reason test is marked explicit + + + + The reason test is marked explicit + + + + + Attribute used to mark a test that is to be ignored. + Ignored tests result in a warning message when the + tests are run. + + + + + Constructs the attribute without giving a reason + for ignoring the test. + + + + + Constructs the attribute giving a reason for ignoring the test + + The reason for ignoring the test + + + + The reason for ignoring a test + + + + + Abstract base for Attributes that are used to include tests + in the test run based on environmental settings. + + + + + Constructor with no included items specified, for use + with named property syntax. + + + + + Constructor taking one or more included items + + Comma-delimited list of included items + + + + Name of the item that is needed in order for + a test to run. Multiple itemss may be given, + separated by a comma. + + + + + Name of the item to be excluded. Multiple items + may be given, separated by a comma. + + + + + The reason for including or excluding the test + + + + + PlatformAttribute is used to mark a test fixture or an + individual method as applying to a particular platform only. + + + + + Constructor with no platforms specified, for use + with named property syntax. + + + + + Constructor taking one or more platforms + + Comma-deliminted list of platforms + + + + CultureAttribute is used to mark a test fixture or an + individual method as applying to a particular Culture only. + + + + + Constructor with no cultures specified, for use + with named property syntax. + + + + + Constructor taking one or more cultures + + Comma-deliminted list of cultures + + + + Marks a test to use a combinatorial join of any argument data + provided. NUnit will create a test case for every combination of + the arguments provided. This can result in a large number of test + cases and so should be used judiciously. This is the default join + type, so the attribute need not be used except as documentation. + + + + + PropertyAttribute is used to attach information to a test as a name/value pair.. + + + + + Construct a PropertyAttribute with a name and string value + + The name of the property + The property value + + + + Construct a PropertyAttribute with a name and int value + + The name of the property + The property value + + + + Construct a PropertyAttribute with a name and double value + + The name of the property + The property value + + + + Constructor for derived classes that set the + property dictionary directly. + + + + + Constructor for use by derived classes that use the + name of the type as the property name. Derived classes + must ensure that the Type of the property value is + a standard type supported by the BCL. Any custom + types will cause a serialization Exception when + in the client. + + + + + Gets the property dictionary for this attribute + + + + + Default constructor + + + + + Marks a test to use pairwise join of any argument data provided. + NUnit will attempt too excercise every pair of argument values at + least once, using as small a number of test cases as it can. With + only two arguments, this is the same as a combinatorial join. + + + + + Default constructor + + + + + Marks a test to use a sequential join of any argument data + provided. NUnit will use arguements for each parameter in + sequence, generating test cases up to the largest number + of argument values provided and using null for any arguments + for which it runs out of values. Normally, this should be + used with the same number of arguments for each parameter. + + + + + Default constructor + + + + + Summary description for MaxTimeAttribute. + + + + + Construct a MaxTimeAttribute, given a time in milliseconds. + + The maximum elapsed time in milliseconds + + + + RandomAttribute is used to supply a set of random values + to a single parameter of a parameterized test. + + + + + ValuesAttribute is used to provide literal arguments for + an individual parameter of a test. + + + + + Abstract base class for attributes that apply to parameters + and supply data for the parameter. + + + + + Gets the data to be provided to the specified parameter + + + + + The collection of data to be returned. Must + be set by any derived attribute classes. + We use an object[] so that the individual + elements may have their type changed in GetData + if necessary. + + + + + Construct with one argument + + + + + + Construct with two arguments + + + + + + + Construct with three arguments + + + + + + + + Construct with an array of arguments + + + + + + Get the collection of values to be used as arguments + + + + + Construct a set of doubles from 0.0 to 1.0, + specifying only the count. + + + + + + Construct a set of doubles from min to max + + + + + + + + Construct a set of ints from min to max + + + + + + + + Get the collection of values to be used as arguments + + + + + RangeAttribute is used to supply a range of values to an + individual parameter of a parameterized test. + + + + + Construct a range of ints using default step of 1 + + + + + + + Construct a range of ints specifying the step size + + + + + + + + Construct a range of longs + + + + + + + + Construct a range of doubles + + + + + + + + Construct a range of floats + + + + + + + + RepeatAttribute may be applied to test case in order + to run it multiple times. + + + + + Construct a RepeatAttribute + + The number of times to run the test + + + + RequiredAddinAttribute may be used to indicate the names of any addins + that must be present in order to run some or all of the tests in an + assembly. If the addin is not loaded, the entire assembly is marked + as NotRunnable. + + + + + Initializes a new instance of the class. + + The required addin. + + + + Gets the name of required addin. + + The required addin name. + + + + Summary description for SetCultureAttribute. + + + + + Construct given the name of a culture + + + + + + Summary description for SetUICultureAttribute. + + + + + Construct given the name of a culture + + + + + + SetUpAttribute is used in a TestFixture to identify a method + that is called immediately before each test is run. It is + also used in a SetUpFixture to identify the method that is + called once, before any of the subordinate tests are run. + + + + + Attribute used to mark a class that contains one-time SetUp + and/or TearDown methods that apply to all the tests in a + namespace or an assembly. + + + + + Attribute used to mark a static (shared in VB) property + that returns a list of tests. + + + + + Attribute used in a TestFixture to identify a method that is + called immediately after each test is run. It is also used + in a SetUpFixture to identify the method that is called once, + after all subordinate tests have run. In either case, the method + is guaranteed to be called, even if an exception is thrown. + + + + + Provide actions to execute before and after tests. + + + + + When implemented by an attribute, this interface implemented to provide actions to execute before and after tests. + + + + + Executed before each test is run + + Provides details about the test that is going to be run. + + + + Executed after each test is run + + Provides details about the test that has just been run. + + + + Provides the target for the action attribute + + The target for the action attribute + + + + Method called before each test + + Info about the test to be run + + + + Method called after each test + + Info about the test that was just run + + + + Gets or sets the ActionTargets for this attribute + + + + + Adding this attribute to a method within a + class makes the method callable from the NUnit test runner. There is a property + called Description which is optional which you can provide a more detailed test + description. This class cannot be inherited. + + + + [TestFixture] + public class Fixture + { + [Test] + public void MethodToTest() + {} + + [Test(Description = "more detailed description")] + publc void TestDescriptionMethod() + {} + } + + + + + + Descriptive text for this test + + + + + TestCaseAttribute is used to mark parameterized test cases + and provide them with their arguments. + + + + + Construct a TestCaseAttribute with a list of arguments. + This constructor is not CLS-Compliant + + + + + + Construct a TestCaseAttribute with a single argument + + + + + + Construct a TestCaseAttribute with a two arguments + + + + + + + Construct a TestCaseAttribute with a three arguments + + + + + + + + Gets the list of arguments to a test case + + + + + Gets or sets the expected result. Use + ExpectedResult by preference. + + The result. + + + + Gets or sets the expected result. + + The result. + + + + Gets a flag indicating whether an expected + result has been set. + + + + + Gets a list of categories associated with this test; + + + + + Gets or sets the category associated with this test. + May be a single category or a comma-separated list. + + + + + Gets or sets the expected exception. + + The expected exception. + + + + Gets or sets the name the expected exception. + + The expected name of the exception. + + + + Gets or sets the expected message of the expected exception + + The expected message of the exception. + + + + Gets or sets the type of match to be performed on the expected message + + + + + Gets or sets the description. + + The description. + + + + Gets or sets the name of the test. + + The name of the test. + + + + Gets or sets the ignored status of the test + + + + + Gets or sets the ignored status of the test + + + + + Gets or sets the explicit status of the test + + + + + Gets or sets the reason for not running the test + + + + + Gets or sets the reason for not running the test. + Set has the side effect of marking the test as ignored. + + The ignore reason. + + + + FactoryAttribute indicates the source to be used to + provide test cases for a test method. + + + + + Construct with the name of the data source, which must + be a property, field or method of the test class itself. + + An array of the names of the factories that will provide data + + + + Construct with a Type, which must implement IEnumerable + + The Type that will provide data + + + + Construct with a Type and name. + that don't support params arrays. + + The Type that will provide data + The name of the method, property or field that will provide data + + + + The name of a the method, property or fiend to be used as a source + + + + + A Type to be used as a source + + + + + Gets or sets the category associated with this test. + May be a single category or a comma-separated list. + + + + + [TestFixture] + public class ExampleClass + {} + + + + + Default constructor + + + + + Construct with a object[] representing a set of arguments. + In .NET 2.0, the arguments may later be separated into + type arguments and constructor arguments. + + + + + + Descriptive text for this fixture + + + + + Gets and sets the category for this fixture. + May be a comma-separated list of categories. + + + + + Gets a list of categories for this fixture + + + + + The arguments originally provided to the attribute + + + + + Gets or sets a value indicating whether this should be ignored. + + true if ignore; otherwise, false. + + + + Gets or sets the ignore reason. May set Ignored as a side effect. + + The ignore reason. + + + + Get or set the type arguments. If not set + explicitly, any leading arguments that are + Types are taken as type arguments. + + + + + Attribute used to identify a method that is + called before any tests in a fixture are run. + + + + + Attribute used to identify a method that is called after + all the tests in a fixture have run. The method is + guaranteed to be called, even if an exception is thrown. + + + + + Adding this attribute to a method within a + class makes the method callable from the NUnit test runner. There is a property + called Description which is optional which you can provide a more detailed test + description. This class cannot be inherited. + + + + [TestFixture] + public class Fixture + { + [Test] + public void MethodToTest() + {} + + [Test(Description = "more detailed description")] + publc void TestDescriptionMethod() + {} + } + + + + + + Used on a method, marks the test with a timeout value in milliseconds. + The test will be run in a separate thread and is cancelled if the timeout + is exceeded. Used on a method or assembly, sets the default timeout + for all contained test methods. + + + + + Construct a TimeoutAttribute given a time in milliseconds + + The timeout value in milliseconds + + + + Marks a test that must run in the STA, causing it + to run in a separate thread if necessary. + + On methods, you may also use STAThreadAttribute + to serve the same purpose. + + + + + Construct a RequiresSTAAttribute + + + + + Marks a test that must run in the MTA, causing it + to run in a separate thread if necessary. + + On methods, you may also use MTAThreadAttribute + to serve the same purpose. + + + + + Construct a RequiresMTAAttribute + + + + + Marks a test that must run on a separate thread. + + + + + Construct a RequiresThreadAttribute + + + + + Construct a RequiresThreadAttribute, specifying the apartment + + + + + ValueSourceAttribute indicates the source to be used to + provide data for one parameter of a test method. + + + + + Construct with the name of the factory - for use with languages + that don't support params arrays. + + The name of the data source to be used + + + + Construct with a Type and name - for use with languages + that don't support params arrays. + + The Type that will provide data + The name of the method, property or field that will provide data + + + + The name of a the method, property or fiend to be used as a source + + + + + A Type to be used as a source + + + + + AllItemsConstraint applies another constraint to each + item in a collection, succeeding if they all succeed. + + + + + Abstract base class used for prefixes + + + + + The Constraint class is the base of all built-in constraints + within NUnit. It provides the operator overloads used to combine + constraints. + + + + + The IConstraintExpression interface is implemented by all + complete and resolvable constraints and expressions. + + + + + Return the top-level constraint for this expression + + + + + + Static UnsetObject used to detect derived constraints + failing to set the actual value. + + + + + The actual value being tested against a constraint + + + + + The display name of this Constraint for use by ToString() + + + + + Argument fields used by ToString(); + + + + + The builder holding this constraint + + + + + Construct a constraint with no arguments + + + + + Construct a constraint with one argument + + + + + Construct a constraint with two arguments + + + + + Sets the ConstraintBuilder holding this constraint + + + + + Write the failure message to the MessageWriter provided + as an argument. The default implementation simply passes + the constraint and the actual value to the writer, which + then displays the constraint description and the value. + + Constraints that need to provide additional details, + such as where the error occured can override this. + + The MessageWriter on which to display the message + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Test whether the constraint is satisfied by an + ActualValueDelegate that returns the value to be tested. + The default implementation simply evaluates the delegate + but derived classes may override it to provide for delayed + processing. + + An + True for success, false for failure + + + + Test whether the constraint is satisfied by a given reference. + The default implementation simply dereferences the value but + derived classes may override it to provide for delayed processing. + + A reference to the value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + Default override of ToString returns the constraint DisplayName + followed by any arguments within angle brackets. + + + + + + Returns the string representation of this constraint + + + + + This operator creates a constraint that is satisfied only if both + argument constraints are satisfied. + + + + + This operator creates a constraint that is satisfied if either + of the argument constraints is satisfied. + + + + + This operator creates a constraint that is satisfied if the + argument constraint is not satisfied. + + + + + Returns a DelayedConstraint with the specified delay time. + + The delay in milliseconds. + + + + + Returns a DelayedConstraint with the specified delay time + and polling interval. + + The delay in milliseconds. + The interval at which to test the constraint. + + + + + The display name of this Constraint for use by ToString(). + The default value is the name of the constraint with + trailing "Constraint" removed. Derived classes may set + this to another name in their constructors. + + + + + Returns a ConstraintExpression by appending And + to the current constraint. + + + + + Returns a ConstraintExpression by appending And + to the current constraint. + + + + + Returns a ConstraintExpression by appending Or + to the current constraint. + + + + + Class used to detect any derived constraints + that fail to set the actual value in their + Matches override. + + + + + The base constraint + + + + + Construct given a base constraint + + + + + + Construct an AllItemsConstraint on top of an existing constraint + + + + + + Apply the item constraint to each item in the collection, + failing if any item fails. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + AndConstraint succeeds only if both members succeed. + + + + + BinaryConstraint is the abstract base of all constraints + that combine two other constraints in some fashion. + + + + + The first constraint being combined + + + + + The second constraint being combined + + + + + Construct a BinaryConstraint from two other constraints + + The first constraint + The second constraint + + + + Create an AndConstraint from two other constraints + + The first constraint + The second constraint + + + + Apply both member constraints to an actual value, succeeding + succeeding only if both of them succeed. + + The actual value + True if the constraints both succeeded + + + + Write a description for this contraint to a MessageWriter + + The MessageWriter to receive the description + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + AssignableFromConstraint is used to test that an object + can be assigned from a given Type. + + + + + TypeConstraint is the abstract base for constraints + that take a Type as their expected value. + + + + + The expected Type used by the constraint + + + + + Construct a TypeConstraint for a given Type + + + + + + Write the actual value for a failing constraint test to a + MessageWriter. TypeConstraints override this method to write + the name of the type. + + The writer on which the actual value is displayed + + + + Construct an AssignableFromConstraint for the type provided + + + + + + Test whether an object can be assigned from the specified type + + The object to be tested + True if the object can be assigned a value of the expected Type, otherwise false. + + + + Write a description of this constraint to a MessageWriter + + The MessageWriter to use + + + + AssignableToConstraint is used to test that an object + can be assigned to a given Type. + + + + + Construct an AssignableToConstraint for the type provided + + + + + + Test whether an object can be assigned to the specified type + + The object to be tested + True if the object can be assigned a value of the expected Type, otherwise false. + + + + Write a description of this constraint to a MessageWriter + + The MessageWriter to use + + + + AttributeConstraint tests that a specified attribute is present + on a Type or other provider and that the value of the attribute + satisfies some other constraint. + + + + + Constructs an AttributeConstraint for a specified attriute + Type and base constraint. + + + + + + + Determines whether the Type or other provider has the + expected attribute and if its value matches the + additional constraint specified. + + + + + Writes a description of the attribute to the specified writer. + + + + + Writes the actual value supplied to the specified writer. + + + + + Returns a string representation of the constraint. + + + + + AttributeExistsConstraint tests for the presence of a + specified attribute on a Type. + + + + + Constructs an AttributeExistsConstraint for a specific attribute Type + + + + + + Tests whether the object provides the expected attribute. + + A Type, MethodInfo, or other ICustomAttributeProvider + True if the expected attribute is present, otherwise false + + + + Writes the description of the constraint to the specified writer + + + + + BasicConstraint is the abstract base for constraints that + perform a simple comparison to a constant value. + + + + + Initializes a new instance of the class. + + The expected. + The description. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + BinarySerializableConstraint tests whether + an object is serializable in binary format. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + Returns the string representation + + + + + CollectionConstraint is the abstract base class for + constraints that operate on collections. + + + + + Construct an empty CollectionConstraint + + + + + Construct a CollectionConstraint + + + + + + Determines whether the specified enumerable is empty. + + The enumerable. + + true if the specified enumerable is empty; otherwise, false. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Protected method to be implemented by derived classes + + + + + + + CollectionContainsConstraint is used to test whether a collection + contains an expected object as a member. + + + + + CollectionItemsEqualConstraint is the abstract base class for all + collection constraints that apply some notion of item equality + as a part of their operation. + + + + + Construct an empty CollectionConstraint + + + + + Construct a CollectionConstraint + + + + + + Flag the constraint to use the supplied EqualityAdapter. + NOTE: For internal use only. + + The EqualityAdapter to use. + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied Comparison object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Compares two collection members for equality + + + + + Return a new CollectionTally for use in making tests + + The collection to be included in the tally + + + + Flag the constraint to ignore case and return self. + + + + + Construct a CollectionContainsConstraint + + + + + + Test whether the expected item is contained in the collection + + + + + + + Write a descripton of the constraint to a MessageWriter + + + + + + CollectionEquivalentCOnstraint is used to determine whether two + collections are equivalent. + + + + + Construct a CollectionEquivalentConstraint + + + + + + Test whether two collections are equivalent + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + CollectionOrderedConstraint is used to test whether a collection is ordered. + + + + + Construct a CollectionOrderedConstraint + + + + + Modifies the constraint to use an IComparer and returns self. + + + + + Modifies the constraint to use an IComparer<T> and returns self. + + + + + Modifies the constraint to use a Comparison<T> and returns self. + + + + + Modifies the constraint to test ordering by the value of + a specified property and returns self. + + + + + Test whether the collection is ordered + + + + + + + Write a description of the constraint to a MessageWriter + + + + + + Returns the string representation of the constraint. + + + + + + If used performs a reverse comparison + + + + + CollectionSubsetConstraint is used to determine whether + one collection is a subset of another + + + + + Construct a CollectionSubsetConstraint + + The collection that the actual value is expected to be a subset of + + + + Test whether the actual collection is a subset of + the expected collection provided. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + CollectionTally counts (tallies) the number of + occurences of each object in one or more enumerations. + + + + + Construct a CollectionTally object from a comparer and a collection + + + + + Try to remove an object from the tally + + The object to remove + True if successful, false if the object was not found + + + + Try to remove a set of objects from the tally + + The objects to remove + True if successful, false if any object was not found + + + + The number of objects remaining in the tally + + + + + ComparisonAdapter class centralizes all comparisons of + values in NUnit, adapting to the use of any provided + IComparer, IComparer<T> or Comparison<T> + + + + + Returns a ComparisonAdapter that wraps an IComparer + + + + + Returns a ComparisonAdapter that wraps an IComparer<T> + + + + + Returns a ComparisonAdapter that wraps a Comparison<T> + + + + + Compares two objects + + + + + Gets the default ComparisonAdapter, which wraps an + NUnitComparer object. + + + + + Construct a ComparisonAdapter for an IComparer + + + + + Compares two objects + + + + + + + + Construct a default ComparisonAdapter + + + + + ComparisonAdapter<T> extends ComparisonAdapter and + allows use of an IComparer<T> or Comparison<T> + to actually perform the comparison. + + + + + Construct a ComparisonAdapter for an IComparer<T> + + + + + Compare a Type T to an object + + + + + Construct a ComparisonAdapter for a Comparison<T> + + + + + Compare a Type T to an object + + + + + Abstract base class for constraints that compare values to + determine if one is greater than, equal to or less than + the other. This class supplies the Using modifiers. + + + + + ComparisonAdapter to be used in making the comparison + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + + + Modifies the constraint to use an IComparer and returns self + + + + + Modifies the constraint to use an IComparer<T> and returns self + + + + + Modifies the constraint to use a Comparison<T> and returns self + + + + + Delegate used to delay evaluation of the actual value + to be used in evaluating a constraint + + + + + ConstraintBuilder maintains the stacks that are used in + processing a ConstraintExpression. An OperatorStack + is used to hold operators that are waiting for their + operands to be reognized. a ConstraintStack holds + input constraints as well as the results of each + operator applied. + + + + + Initializes a new instance of the class. + + + + + Appends the specified operator to the expression by first + reducing the operator stack and then pushing the new + operator on the stack. + + The operator to push. + + + + Appends the specified constraint to the expresson by pushing + it on the constraint stack. + + The constraint to push. + + + + Sets the top operator right context. + + The right context. + + + + Reduces the operator stack until the topmost item + precedence is greater than or equal to the target precedence. + + The target precedence. + + + + Resolves this instance, returning a Constraint. If the builder + is not currently in a resolvable state, an exception is thrown. + + The resolved constraint + + + + Gets a value indicating whether this instance is resolvable. + + + true if this instance is resolvable; otherwise, false. + + + + + OperatorStack is a type-safe stack for holding ConstraintOperators + + + + + Initializes a new instance of the class. + + The builder. + + + + Pushes the specified operator onto the stack. + + The op. + + + + Pops the topmost operator from the stack. + + + + + + Gets a value indicating whether this is empty. + + true if empty; otherwise, false. + + + + Gets the topmost operator without modifying the stack. + + The top. + + + + ConstraintStack is a type-safe stack for holding Constraints + + + + + Initializes a new instance of the class. + + The builder. + + + + Pushes the specified constraint. As a side effect, + the constraint's builder field is set to the + ConstraintBuilder owning this stack. + + The constraint. + + + + Pops this topmost constrait from the stack. + As a side effect, the constraint's builder + field is set to null. + + + + + + Gets a value indicating whether this is empty. + + true if empty; otherwise, false. + + + + Gets the topmost constraint without modifying the stack. + + The topmost constraint + + + + ConstraintExpression represents a compound constraint in the + process of being constructed from a series of syntactic elements. + + Individual elements are appended to the expression as they are + reognized. Once an actual Constraint is appended, the expression + returns a resolvable Constraint. + + + + + ConstraintExpressionBase is the abstract base class for the + ConstraintExpression class, which represents a + compound constraint in the process of being constructed + from a series of syntactic elements. + + NOTE: ConstraintExpressionBase is separate because the + ConstraintExpression class was generated in earlier + versions of NUnit. The two classes may be combined + in a future version. + + + + + The ConstraintBuilder holding the elements recognized so far + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the + class passing in a ConstraintBuilder, which may be pre-populated. + + The builder. + + + + Returns a string representation of the expression as it + currently stands. This should only be used for testing, + since it has the side-effect of resolving the expression. + + + + + + Appends an operator to the expression and returns the + resulting expression itself. + + + + + Appends a self-resolving operator to the expression and + returns a new ResolvableConstraintExpression. + + + + + Appends a constraint to the expression and returns that + constraint, which is associated with the current state + of the expression being built. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the + class passing in a ConstraintBuilder, which may be pre-populated. + + The builder. + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding only if a specified number of them succeed. + + + + + Returns a new PropertyConstraintExpression, which will either + test for the existence of the named property on the object + being tested or apply any following constraint to that property. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns the constraint provided as an argument - used to allow custom + custom constraints to easily participate in the syntax. + + + + + Returns the constraint provided as an argument - used to allow custom + custom constraints to easily participate in the syntax. + + + + + Returns a constraint that tests two items for equality + + + + + Returns a constraint that tests that two references are the same object + + + + + Returns a constraint that tests whether the + actual value is greater than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a collection containing the same elements as the + collection supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a subset of the collection supplied as an argument. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a new ContainsConstraint. This constraint + will, in turn, make use of the appropriate second-level + constraint, depending on the type of the actual argument. + This overload is only used if the item sought is a string, + since any other type implies that we are looking for a + collection member. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the regular expression supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the regular expression supplied as an argument. + + + + + Returns a constraint that tests whether the path provided + is the same as an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is the same path or under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is the same path or under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the actual value falls + within a specified range. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if at least one of them succeeds. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them fail. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Length property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Count property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Message property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the InnerException property of the object being tested. + + + + + With is currently a NOP - reserved for future use. + + + + + Returns a constraint that tests for null + + + + + Returns a constraint that tests for True + + + + + Returns a constraint that tests for False + + + + + Returns a constraint that tests for a positive value + + + + + Returns a constraint that tests for a negative value + + + + + Returns a constraint that tests for NaN + + + + + Returns a constraint that tests for empty + + + + + Returns a constraint that tests whether a collection + contains all unique items. + + + + + Returns a constraint that tests whether an object graph is serializable in binary format. + + + + + Returns a constraint that tests whether an object graph is serializable in xml format. + + + + + Returns a constraint that tests whether a collection is ordered + + + + + ContainsConstraint tests a whether a string contains a substring + or a collection contains an object. It postpones the decision of + which test to use until the type of the actual argument is known. + This allows testing whether a string is contained in a collection + or as a substring of another string using the same syntax. + + + + + Initializes a new instance of the class. + + The expected. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied Comparison object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to ignore case and return self. + + + + + Applies a delay to the match so that a match can be evaluated in the future. + + + + + Creates a new DelayedConstraint + + The inner constraint two decorate + The time interval after which the match is performed + If the value of is less than 0 + + + + Creates a new DelayedConstraint + + The inner constraint two decorate + The time interval after which the match is performed + The time interval used for polling + If the value of is less than 0 + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for if the base constraint fails, false if it succeeds + + + + Test whether the constraint is satisfied by a delegate + + The delegate whose value is to be tested + True for if the base constraint fails, false if it succeeds + + + + Test whether the constraint is satisfied by a given reference. + Overridden to wait for the specified delay period before + calling the base constraint with the dereferenced value. + + A reference to the value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a MessageWriter. + + The writer on which the actual value is displayed + + + + Returns the string representation of the constraint. + + + + + EmptyCollectionConstraint tests whether a collection is empty. + + + + + Check that the collection is empty + + + + + + + Write the constraint description to a MessageWriter + + + + + + EmptyConstraint tests a whether a string or collection is empty, + postponing the decision about which test is applied until the + type of the actual argument is known. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + EmptyDirectoryConstraint is used to test that a directory is empty + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + EmptyStringConstraint tests whether a string is empty. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + EndsWithConstraint can test whether a string ends + with an expected substring. + + + + + StringConstraint is the abstract base for constraints + that operate on strings. It supports the IgnoreCase + modifier for string operations. + + + + + The expected value + + + + + Indicates whether tests should be case-insensitive + + + + + Constructs a StringConstraint given an expected value + + The expected value + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Test whether the constraint is satisfied by a given string + + The string to be tested + True for success, false for failure + + + + Modify the constraint to ignore case in matching. + + + + + Initializes a new instance of the class. + + The expected string + + + + Test whether the constraint is matched by the actual value. + This is a template method, which calls the IsMatch method + of the derived class. + + + + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + EqualConstraint is able to compare an actual value with the + expected value provided in its constructor. Two objects are + considered equal if both are null, or if both have the same + value. NUnit has special semantics for some object types. + + + + + If true, strings in error messages will be clipped + + + + + NUnitEqualityComparer used to test equality. + + + + + Initializes a new instance of the class. + + The expected value. + + + + Flag the constraint to use a tolerance when determining equality. + + Tolerance value to be used + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied Comparison object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write a failure message. Overridden to provide custom + failure messages for EqualConstraint. + + The MessageWriter to write to + + + + Write description of this constraint + + The MessageWriter to write to + + + + Display the failure information for two collections that did not match. + + The MessageWriter on which to display + The expected collection. + The actual collection + The depth of this failure in a set of nested collections + + + + Displays a single line showing the types and sizes of the expected + and actual enumerations, collections or arrays. If both are identical, + the value is only shown once. + + The MessageWriter on which to display + The expected collection or array + The actual collection or array + The indentation level for the message line + + + + Displays a single line showing the point in the expected and actual + arrays at which the comparison failed. If the arrays have different + structures or dimensions, both values are shown. + + The MessageWriter on which to display + The expected array + The actual array + Index of the failure point in the underlying collections + The indentation level for the message line + + + + Display the failure information for two IEnumerables that did not match. + + The MessageWriter on which to display + The expected enumeration. + The actual enumeration + The depth of this failure in a set of nested collections + + + + Flag the constraint to ignore case and return self. + + + + + Flag the constraint to suppress string clipping + and return self. + + + + + Flag the constraint to compare arrays as collections + and return self. + + + + + Switches the .Within() modifier to interpret its tolerance as + a distance in representable values (see remarks). + + Self. + + Ulp stands for "unit in the last place" and describes the minimum + amount a given value can change. For any integers, an ulp is 1 whole + digit. For floating point values, the accuracy of which is better + for smaller numbers and worse for larger numbers, an ulp depends + on the size of the number. Using ulps for comparison of floating + point results instead of fixed tolerances is safer because it will + automatically compensate for the added inaccuracy of larger numbers. + + + + + Switches the .Within() modifier to interpret its tolerance as + a percentage that the actual values is allowed to deviate from + the expected value. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in days. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in hours. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in minutes. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in seconds. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in milliseconds. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in clock ticks. + + Self + + + + EqualityAdapter class handles all equality comparisons + that use an IEqualityComparer, IEqualityComparer<T> + or a ComparisonAdapter. + + + + + Compares two objects, returning true if they are equal + + + + + Returns true if the two objects can be compared by this adapter. + The base adapter cannot handle IEnumerables except for strings. + + + + + Returns an EqualityAdapter that wraps an IComparer. + + + + + Returns an EqualityAdapter that wraps an IEqualityComparer. + + + + + Returns an EqualityAdapter that wraps an IEqualityComparer<T>. + + + + + Returns an EqualityAdapter that wraps an IComparer<T>. + + + + + Returns an EqualityAdapter that wraps a Comparison<T>. + + + + + EqualityAdapter that wraps an IComparer. + + + + + Returns true if the two objects can be compared by this adapter. + Generic adapter requires objects of the specified type. + + + + + EqualityAdapter that wraps an IComparer. + + + + + EqualityAdapterList represents a list of EqualityAdapters + in a common class across platforms. + + + + + ExactCountConstraint applies another constraint to each + item in a collection, succeeding only if a specified + number of items succeed. + + + + + Construct an ExactCountConstraint on top of an existing constraint + + + + + + + Apply the item constraint to each item in the collection, + succeeding only if the expected number of items pass. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + ExactTypeConstraint is used to test that an object + is of the exact type provided in the constructor + + + + + Construct an ExactTypeConstraint for a given Type + + The expected Type. + + + + Test that an object is of the exact type specified + + The actual value. + True if the tested object is of the exact type provided, otherwise false. + + + + Write the description of this constraint to a MessageWriter + + The MessageWriter to use + + + + ExceptionTypeConstraint is a special version of ExactTypeConstraint + used to provided detailed info about the exception thrown in + an error message. + + + + + Constructs an ExceptionTypeConstraint + + + + + Write the actual value for a failing constraint test to a + MessageWriter. Overriden to write additional information + in the case of an Exception. + + The MessageWriter to use + + + + FailurePoint class represents one point of failure + in an equality test. + + + + + The location of the failure + + + + + The expected value + + + + + The actual value + + + + + Indicates whether the expected value is valid + + + + + Indicates whether the actual value is valid + + + + + FailurePointList represents a set of FailurePoints + in a cross-platform way. + + + + + FalseConstraint tests that the actual value is false + + + + + Initializes a new instance of the class. + + + + Helper routines for working with floating point numbers + + + The floating point comparison code is based on this excellent article: + http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm + + + "ULP" means Unit in the Last Place and in the context of this library refers to + the distance between two adjacent floating point numbers. IEEE floating point + numbers can only represent a finite subset of natural numbers, with greater + accuracy for smaller numbers and lower accuracy for very large numbers. + + + If a comparison is allowed "2 ulps" of deviation, that means the values are + allowed to deviate by up to 2 adjacent floating point values, which might be + as low as 0.0000001 for small numbers or as high as 10.0 for large numbers. + + + + + Compares two floating point values for equality + First floating point value to be compared + Second floating point value t be compared + + Maximum number of representable floating point values that are allowed to + be between the left and the right floating point values + + True if both numbers are equal or close to being equal + + + Floating point values can only represent a finite subset of natural numbers. + For example, the values 2.00000000 and 2.00000024 can be stored in a float, + but nothing inbetween them. + + + This comparison will count how many possible floating point values are between + the left and the right number. If the number of possible values between both + numbers is less than or equal to maxUlps, then the numbers are considered as + being equal. + + + Implementation partially follows the code outlined here: + http://www.anttirt.net/2007/08/19/proper-floating-point-comparisons/ + + + + + Compares two double precision floating point values for equality + First double precision floating point value to be compared + Second double precision floating point value t be compared + + Maximum number of representable double precision floating point values that are + allowed to be between the left and the right double precision floating point values + + True if both numbers are equal or close to being equal + + + Double precision floating point values can only represent a limited series of + natural numbers. For example, the values 2.0000000000000000 and 2.0000000000000004 + can be stored in a double, but nothing inbetween them. + + + This comparison will count how many possible double precision floating point + values are between the left and the right number. If the number of possible + values between both numbers is less than or equal to maxUlps, then the numbers + are considered as being equal. + + + Implementation partially follows the code outlined here: + http://www.anttirt.net/2007/08/19/proper-floating-point-comparisons/ + + + + + + Reinterprets the memory contents of a floating point value as an integer value + + + Floating point value whose memory contents to reinterpret + + + The memory contents of the floating point value interpreted as an integer + + + + + Reinterprets the memory contents of a double precision floating point + value as an integer value + + + Double precision floating point value whose memory contents to reinterpret + + + The memory contents of the double precision floating point value + interpreted as an integer + + + + + Reinterprets the memory contents of an integer as a floating point value + + Integer value whose memory contents to reinterpret + + The memory contents of the integer value interpreted as a floating point value + + + + + Reinterprets the memory contents of an integer value as a double precision + floating point value + + Integer whose memory contents to reinterpret + + The memory contents of the integer interpreted as a double precision + floating point value + + + + Union of a floating point variable and an integer + + + The union's value as a floating point variable + + + The union's value as an integer + + + The union's value as an unsigned integer + + + Union of a double precision floating point variable and a long + + + The union's value as a double precision floating point variable + + + The union's value as a long + + + The union's value as an unsigned long + + + + Tests whether a value is greater than the value supplied to its constructor + + + + + The value against which a comparison is to be made + + + + + Initializes a new instance of the class. + + The expected value. + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Tests whether a value is greater than or equal to the value supplied to its constructor + + + + + The value against which a comparison is to be made + + + + + Initializes a new instance of the class. + + The expected value. + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + InstanceOfTypeConstraint is used to test that an object + is of the same type provided or derived from it. + + + + + Construct an InstanceOfTypeConstraint for the type provided + + The expected Type + + + + Test whether an object is of the specified type or a derived type + + The object to be tested + True if the object is of the provided type or derives from it, otherwise false. + + + + Write a description of this constraint to a MessageWriter + + The MessageWriter to use + + + + Tests whether a value is less than the value supplied to its constructor + + + + + The value against which a comparison is to be made + + + + + Initializes a new instance of the class. + + The expected value. + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Tests whether a value is less than or equal to the value supplied to its constructor + + + + + The value against which a comparison is to be made + + + + + Initializes a new instance of the class. + + The expected value. + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Static methods used in creating messages + + + + + Static string used when strings are clipped + + + + + Returns the representation of a type as used in NUnitLite. + This is the same as Type.ToString() except for arrays, + which are displayed with their declared sizes. + + + + + + + Converts any control characters in a string + to their escaped representation. + + The string to be converted + The converted string + + + + Return the a string representation for a set of indices into an array + + Array of indices for which a string is needed + + + + Get an array of indices representing the point in a enumerable, + collection or array corresponding to a single int index into the + collection. + + The collection to which the indices apply + Index in the collection + Array of indices + + + + Clip a string to a given length, starting at a particular offset, returning the clipped + string with ellipses representing the removed parts + + The string to be clipped + The maximum permitted length of the result string + The point at which to start clipping + The clipped string + + + + Clip the expected and actual strings in a coordinated fashion, + so that they may be displayed together. + + + + + + + + + Shows the position two strings start to differ. Comparison + starts at the start index. + + The expected string + The actual string + The index in the strings at which comparison should start + Boolean indicating whether case should be ignored + -1 if no mismatch found, or the index where mismatch found + + + + NaNConstraint tests that the actual value is a double or float NaN + + + + + Test that the actual value is an NaN + + + + + + + Write the constraint description to a specified writer + + + + + + NoItemConstraint applies another constraint to each + item in a collection, failing if any of them succeeds. + + + + + Construct a NoItemConstraint on top of an existing constraint + + + + + + Apply the item constraint to each item in the collection, + failing if any item fails. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + NotConstraint negates the effect of some other constraint + + + + + Initializes a new instance of the class. + + The base constraint to be negated. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for if the base constraint fails, false if it succeeds + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a MessageWriter. + + The writer on which the actual value is displayed + + + + NullConstraint tests that the actual value is null + + + + + Initializes a new instance of the class. + + + + + NullEmptyStringConstraint tests whether a string is either null or empty. + + + + + Constructs a new NullOrEmptyStringConstraint + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + The Numerics class contains common operations on numeric values. + + + + + Checks the type of the object, returning true if + the object is a numeric type. + + The object to check + true if the object is a numeric type + + + + Checks the type of the object, returning true if + the object is a floating point numeric type. + + The object to check + true if the object is a floating point numeric type + + + + Checks the type of the object, returning true if + the object is a fixed point numeric type. + + The object to check + true if the object is a fixed point numeric type + + + + Test two numeric values for equality, performing the usual numeric + conversions and using a provided or default tolerance. If the tolerance + provided is Empty, this method may set it to a default tolerance. + + The expected value + The actual value + A reference to the tolerance in effect + True if the values are equal + + + + Compare two numeric values, performing the usual numeric conversions. + + The expected value + The actual value + The relationship of the values to each other + + + + NUnitComparer encapsulates NUnit's default behavior + in comparing two objects. + + + + + Compares two objects + + + + + + + + Returns the default NUnitComparer. + + + + + Generic version of NUnitComparer + + + + + + Compare two objects of the same type + + + + + NUnitEqualityComparer encapsulates NUnit's handling of + equality tests between objects. + + + + + + + + + + Compares two objects for equality within a tolerance + + The first object to compare + The second object to compare + The tolerance to use in the comparison + + + + + If true, all string comparisons will ignore case + + + + + If true, arrays will be treated as collections, allowing + those of different dimensions to be compared + + + + + Comparison objects used in comparisons for some constraints. + + + + + List of points at which a failure occured. + + + + + RecursionDetector used to check for recursion when + evaluating self-referencing enumerables. + + + + + Compares two objects for equality within a tolerance, setting + the tolerance to the actual tolerance used if an empty + tolerance is supplied. + + + + + Helper method to compare two arrays + + + + + Method to compare two DirectoryInfo objects + + first directory to compare + second directory to compare + true if equivalent, false if not + + + + Returns the default NUnitEqualityComparer + + + + + Gets and sets a flag indicating whether case should + be ignored in determining equality. + + + + + Gets and sets a flag indicating that arrays should be + compared as collections, without regard to their shape. + + + + + Gets the list of external comparers to be used to + test for equality. They are applied to members of + collections, in place of NUnit's own logic. + + + + + Gets the list of failure points for the last Match performed. + The list consists of objects to be interpreted by the caller. + This generally means that the caller may only make use of + objects it has placed on the list at a particular depthy. + + + + + RecursionDetector detects when a comparison + between two enumerables has reached a point + where the same objects that were previously + compared are again being compared. This allows + the caller to stop the comparison if desired. + + + + + Check whether two objects have previously + been compared, returning true if they have. + The two objects are remembered, so that a + second call will always return true. + + + + + OrConstraint succeeds if either member succeeds + + + + + Create an OrConstraint from two other constraints + + The first constraint + The second constraint + + + + Apply the member constraints to an actual value, succeeding + succeeding as soon as one of them succeeds. + + The actual value + True if either constraint succeeded + + + + Write a description for this contraint to a MessageWriter + + The MessageWriter to receive the description + + + + PathConstraint serves as the abstract base of constraints + that operate on paths and provides several helper methods. + + + + + The expected path used in the constraint + + + + + Flag indicating whether a caseInsensitive comparison should be made + + + + + Construct a PathConstraint for a give expected path + + The expected path + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Returns true if the expected path and actual path match + + + + + Returns the string representation of this constraint + + + + + Transform the provided path to its canonical form so that it + may be more easily be compared with other paths. + + The original path + The path in canonical form + + + + Test whether one path in canonical form is under another. + + The first path - supposed to be the parent path + The second path - supposed to be the child path + Indicates whether case should be ignored + + + + + Modifies the current instance to be case-insensitve + and returns it. + + + + + Modifies the current instance to be case-sensitve + and returns it. + + + + + Predicate constraint wraps a Predicate in a constraint, + returning success if the predicate is true. + + + + + Construct a PredicateConstraint from a predicate + + + + + Determines whether the predicate succeeds when applied + to the actual value. + + + + + Writes the description to a MessageWriter + + + + + PropertyConstraint extracts a named property and uses + its value as the actual value for a chained constraint. + + + + + Initializes a new instance of the class. + + The name. + The constraint to apply to the property. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + Returns the string representation of the constraint. + + + + + + PropertyExistsConstraint tests that a named property + exists on the object provided through Match. + + Originally, PropertyConstraint provided this feature + in addition to making optional tests on the vaue + of the property. The two constraints are now separate. + + + + + Initializes a new instance of the class. + + The name of the property. + + + + Test whether the property exists for a given object + + The object to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. + + The writer on which the actual value is displayed + + + + Returns the string representation of the constraint. + + + + + + RangeConstraint tests whether two values are within a + specified range. + + + + + Initializes a new instance of the class. + + From. + To. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + RegexConstraint can test whether a string matches + the pattern provided. + + + + + Initializes a new instance of the class. + + The pattern. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + ResolvableConstraintExpression is used to represent a compound + constraint being constructed at a point where the last operator + may either terminate the expression or may have additional + qualifying constraints added to it. + + It is used, for example, for a Property element or for + an Exception element, either of which may be optionally + followed by constraints that apply to the property or + exception. + + + + + Create a new instance of ResolvableConstraintExpression + + + + + Create a new instance of ResolvableConstraintExpression, + passing in a pre-populated ConstraintBuilder. + + + + + Resolve the current expression to a Constraint + + + + + This operator creates a constraint that is satisfied only if both + argument constraints are satisfied. + + + + + This operator creates a constraint that is satisfied only if both + argument constraints are satisfied. + + + + + This operator creates a constraint that is satisfied only if both + argument constraints are satisfied. + + + + + This operator creates a constraint that is satisfied if either + of the argument constraints is satisfied. + + + + + This operator creates a constraint that is satisfied if either + of the argument constraints is satisfied. + + + + + This operator creates a constraint that is satisfied if either + of the argument constraints is satisfied. + + + + + This operator creates a constraint that is satisfied if the + argument constraint is not satisfied. + + + + + Appends an And Operator to the expression + + + + + Appends an Or operator to the expression. + + + + + ReusableConstraint wraps a constraint expression after + resolving it so that it can be reused consistently. + + + + + Construct a ReusableConstraint from a constraint expression + + The expression to be resolved and reused + + + + Converts a constraint to a ReusableConstraint + + The constraint to be converted + A ReusableConstraint + + + + Returns the string representation of the constraint. + + A string representing the constraint + + + + Resolves the ReusableConstraint by returning the constraint + that it originally wrapped. + + A resolved constraint + + + + SameAsConstraint tests whether an object is identical to + the object passed to its constructor + + + + + Initializes a new instance of the class. + + The expected object. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Summary description for SamePathConstraint. + + + + + Initializes a new instance of the class. + + The expected path + + + + Test whether the constraint is satisfied by a given value + + The expected path + The actual path + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + SamePathOrUnderConstraint tests that one path is under another + + + + + Initializes a new instance of the class. + + The expected path + + + + Test whether the constraint is satisfied by a given value + + The expected path + The actual path + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + SomeItemsConstraint applies another constraint to each + item in a collection, succeeding if any of them succeeds. + + + + + Construct a SomeItemsConstraint on top of an existing constraint + + + + + + Apply the item constraint to each item in the collection, + succeeding if any item succeeds. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + StartsWithConstraint can test whether a string starts + with an expected substring. + + + + + Initializes a new instance of the class. + + The expected string + + + + Test whether the constraint is matched by the actual value. + This is a template method, which calls the IsMatch method + of the derived class. + + + + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + SubPathConstraint tests that the actual path is under the expected path + + + + + Initializes a new instance of the class. + + The expected path + + + + Test whether the constraint is satisfied by a given value + + The expected path + The actual path + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + SubstringConstraint can test whether a string contains + the expected substring. + + + + + Initializes a new instance of the class. + + The expected. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + ThrowsConstraint is used to test the exception thrown by + a delegate by applying a constraint to it. + + + + + Initializes a new instance of the class, + using a constraint to be applied to the exception. + + A constraint to apply to the caught exception. + + + + Executes the code of the delegate and captures any exception. + If a non-null base constraint was provided, it applies that + constraint to the exception. + + A delegate representing the code to be tested + True if an exception is thrown and the constraint succeeds, otherwise false + + + + Converts an ActualValueDelegate to a TestDelegate + before calling the primary overload. + + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + Returns the string representation of this constraint + + + + + Get the actual exception thrown - used by Assert.Throws. + + + + + ThrowsNothingConstraint tests that a delegate does not + throw an exception. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True if no exception is thrown, otherwise false + + + + Test whether the constraint is satisfied by a given delegate + + Delegate returning the value to be tested + True if no exception is thrown, otherwise false + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. Overridden in ThrowsNothingConstraint to write + information about the exception that was actually caught. + + The writer on which the actual value is displayed + + + + The Tolerance class generalizes the notion of a tolerance + within which an equality test succeeds. Normally, it is + used with numeric types, but it can be used with any + type that supports taking a difference between two + objects and comparing that difference to a value. + + + + + Constructs a linear tolerance of a specdified amount + + + + + Constructs a tolerance given an amount and ToleranceMode + + + + + Tests that the current Tolerance is linear with a + numeric value, throwing an exception if it is not. + + + + + Returns an empty Tolerance object, equivalent to + specifying no tolerance. In most cases, it results + in an exact match but for floats and doubles a + default tolerance may be used. + + + + + Returns a zero Tolerance object, equivalent to + specifying an exact match. + + + + + Gets the ToleranceMode for the current Tolerance + + + + + Gets the value of the current Tolerance instance. + + + + + Returns a new tolerance, using the current amount as a percentage. + + + + + Returns a new tolerance, using the current amount in Ulps. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of days. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of hours. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of minutes. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of seconds. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of milliseconds. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of clock ticks. + + + + + Returns true if the current tolerance is empty. + + + + + Modes in which the tolerance value for a comparison can be interpreted. + + + + + The tolerance was created with a value, without specifying + how the value would be used. This is used to prevent setting + the mode more than once and is generally changed to Linear + upon execution of the test. + + + + + The tolerance is used as a numeric range within which + two compared values are considered to be equal. + + + + + Interprets the tolerance as the percentage by which + the two compared values my deviate from each other. + + + + + Compares two values based in their distance in + representable numbers. + + + + + TrueConstraint tests that the actual value is true + + + + + Initializes a new instance of the class. + + + + + UniqueItemsConstraint tests whether all the items in a + collection are unique. + + + + + Check that all items are unique. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + XmlSerializableConstraint tests whether + an object is serializable in XML format. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + Returns the string representation of this constraint + + + + + Represents a constraint that succeeds if all the + members of a collection match a base constraint. + + + + + Abstract base for operators that indicate how to + apply a constraint to items in a collection. + + + + + PrefixOperator takes a single constraint and modifies + it's action in some way. + + + + + The ConstraintOperator class is used internally by a + ConstraintBuilder to represent an operator that + modifies or combines constraints. + + Constraint operators use left and right precedence + values to determine whether the top operator on the + stack should be reduced before pushing a new operator. + + + + + The precedence value used when the operator + is about to be pushed to the stack. + + + + + The precedence value used when the operator + is on the top of the stack. + + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + + The syntax element preceding this operator + + + + + The syntax element folowing this operator + + + + + The precedence value used when the operator + is about to be pushed to the stack. + + + + + The precedence value used when the operator + is on the top of the stack. + + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + + Returns the constraint created by applying this + prefix to another constraint. + + + + + + + Constructs a CollectionOperator + + + + + Returns a constraint that will apply the argument + to the members of a collection, succeeding if + they all succeed. + + + + + Operator that requires both it's arguments to succeed + + + + + Abstract base class for all binary operators + + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + + Abstract method that produces a constraint by applying + the operator to its left and right constraint arguments. + + + + + Gets the left precedence of the operator + + + + + Gets the right precedence of the operator + + + + + Construct an AndOperator + + + + + Apply the operator to produce an AndConstraint + + + + + Operator that tests for the presence of a particular attribute + on a type and optionally applies further tests to the attribute. + + + + + Abstract base class for operators that are able to reduce to a + constraint whether or not another syntactic element follows. + + + + + Construct an AttributeOperator for a particular Type + + The Type of attribute tested + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + Represents a constraint that succeeds if the specified + count of members of a collection match a base constraint. + + + + + Construct an ExactCountOperator for a specified count + + The expected count + + + + Returns a constraint that will apply the argument + to the members of a collection, succeeding if + none of them succeed. + + + + + Represents a constraint that succeeds if none of the + members of a collection match a base constraint. + + + + + Returns a constraint that will apply the argument + to the members of a collection, succeeding if + none of them succeed. + + + + + Negates the test of the constraint it wraps. + + + + + Constructs a new NotOperator + + + + + Returns a NotConstraint applied to its argument. + + + + + Operator that requires at least one of it's arguments to succeed + + + + + Construct an OrOperator + + + + + Apply the operator to produce an OrConstraint + + + + + Operator used to test for the presence of a named Property + on an object and optionally apply further tests to the + value of that property. + + + + + Constructs a PropOperator for a particular named property + + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + + Gets the name of the property to which the operator applies + + + + + Represents a constraint that succeeds if any of the + members of a collection match a base constraint. + + + + + Returns a constraint that will apply the argument + to the members of a collection, succeeding if + any of them succeed. + + + + + Operator that tests that an exception is thrown and + optionally applies further tests to the exception. + + + + + Construct a ThrowsOperator + + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + Represents a constraint that simply wraps the + constraint provided as an argument, without any + further functionality, but which modifes the + order of evaluation because of its precedence. + + + + + Constructor for the WithOperator + + + + + Returns a constraint that wraps its argument + + + + + Thrown when an assertion failed. + + + + The error message that explains + the reason for the exception + + + The error message that explains + the reason for the exception + The exception that caused the + current exception + + + + Serialization Constructor + + + + + Thrown when an assertion failed. + + + + + + + The error message that explains + the reason for the exception + The exception that caused the + current exception + + + + Serialization Constructor + + + + + Thrown when a test executes inconclusively. + + + + The error message that explains + the reason for the exception + + + The error message that explains + the reason for the exception + The exception that caused the + current exception + + + + Serialization Constructor + + + + + Thrown when an assertion failed. + + + + + + + The error message that explains + the reason for the exception + The exception that caused the + current exception + + + + Serialization Constructor + + + + + + + + + + + Compares two objects of a given Type for equality within a tolerance + + The first object to compare + The second object to compare + The tolerance to use in the comparison + + + + diff --git a/Externals/NUnit/nunit.mocks.dll b/Externals/NUnit/nunit.mocks.dll new file mode 100644 index 0000000000..bbad40e4e Binary files /dev/null and b/Externals/NUnit/nunit.mocks.dll differ diff --git a/Externals/NUnit/pnunit-agent.exe b/Externals/NUnit/pnunit-agent.exe new file mode 100644 index 0000000000..d90c62fb0 Binary files /dev/null and b/Externals/NUnit/pnunit-agent.exe differ diff --git a/Externals/NUnit/pnunit-agent.exe.config b/Externals/NUnit/pnunit-agent.exe.config new file mode 100644 index 0000000000..2da8776dc --- /dev/null +++ b/Externals/NUnit/pnunit-agent.exe.config @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Externals/NUnit/pnunit-launcher.exe b/Externals/NUnit/pnunit-launcher.exe new file mode 100644 index 0000000000..626d3359c Binary files /dev/null and b/Externals/NUnit/pnunit-launcher.exe differ diff --git a/Externals/NUnit/pnunit-launcher.exe.config b/Externals/NUnit/pnunit-launcher.exe.config new file mode 100644 index 0000000000..2da8776dc --- /dev/null +++ b/Externals/NUnit/pnunit-launcher.exe.config @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Externals/NUnit/pnunit.framework.dll b/Externals/NUnit/pnunit.framework.dll new file mode 100644 index 0000000000..1fca36829 Binary files /dev/null and b/Externals/NUnit/pnunit.framework.dll differ diff --git a/Externals/NUnit/pnunit.tests.dll b/Externals/NUnit/pnunit.tests.dll new file mode 100644 index 0000000000..dc9496bb7 Binary files /dev/null and b/Externals/NUnit/pnunit.tests.dll differ diff --git a/Externals/NUnit/runpnunit.bat b/Externals/NUnit/runpnunit.bat new file mode 100644 index 0000000000..f41cb5a6b --- /dev/null +++ b/Externals/NUnit/runpnunit.bat @@ -0,0 +1,3 @@ +start pnunit-agent 8080 . +start pnunit-agent 8081 . +pnunit-launcher test.conf diff --git a/Externals/NUnit/test.conf b/Externals/NUnit/test.conf new file mode 100644 index 0000000000..63cc7bd44 --- /dev/null +++ b/Externals/NUnit/test.conf @@ -0,0 +1,82 @@ + + + + + + + + + + + Testing + + + Testing + pnunit.tests.dll + TestLibraries.Testing.EqualTo19 + $agent_host:8080 + + + + + + + Parallel_Tests + + + ParallelTest_A_Test + pnunit.tests.dll + TestLibraries.ParallelExample.ParallelTest_A + $agent_host:8080 + + + 2 + + + + ParallelTest_B_Test + pnunit.tests.dll + TestLibraries.ParallelExample.ParallelTest_B + $agent_host:8080 + + 1 + + + + + + + + + Parallel_Barriers + + + Parallel_Barriers_TestA + pnunit.tests.dll + TestLibraries.ParallelExampleWithBarriers.ParallelTestWithBarriersA + $agent_host:8080 + + + + START_BARRIER + WAIT_BARRIER + + + + Parallel_Barriers_TestB + pnunit.tests.dll + TestLibraries.ParallelExampleWithBarriers.ParallelTestWithBarriersB + $agent_host:8081 + + + + START_BARRIER + WAIT_BARRIER + + + + + + + + \ No newline at end of file diff --git a/Externals/NUnit/tests/mock-assembly.dll b/Externals/NUnit/tests/mock-assembly.dll new file mode 100644 index 0000000000..de54f7cae Binary files /dev/null and b/Externals/NUnit/tests/mock-assembly.dll differ diff --git a/Externals/NUnit/tests/nonamespace-assembly.dll b/Externals/NUnit/tests/nonamespace-assembly.dll new file mode 100644 index 0000000000..957be6489 Binary files /dev/null and b/Externals/NUnit/tests/nonamespace-assembly.dll differ diff --git a/Externals/NUnit/tests/nunit-console.tests.dll b/Externals/NUnit/tests/nunit-console.tests.dll new file mode 100644 index 0000000000..ab2d6488a Binary files /dev/null and b/Externals/NUnit/tests/nunit-console.tests.dll differ diff --git a/Externals/NUnit/tests/nunit-editor.tests.dll b/Externals/NUnit/tests/nunit-editor.tests.dll new file mode 100644 index 0000000000..4837335b1 Binary files /dev/null and b/Externals/NUnit/tests/nunit-editor.tests.dll differ diff --git a/Externals/NUnit/tests/nunit-gui.tests.dll b/Externals/NUnit/tests/nunit-gui.tests.dll new file mode 100644 index 0000000000..7067b90e4 Binary files /dev/null and b/Externals/NUnit/tests/nunit-gui.tests.dll differ diff --git a/Externals/NUnit/tests/nunit.core.tests.dll b/Externals/NUnit/tests/nunit.core.tests.dll new file mode 100644 index 0000000000..da4c027bf Binary files /dev/null and b/Externals/NUnit/tests/nunit.core.tests.dll differ diff --git a/Externals/NUnit/tests/nunit.core.tests.net45.dll b/Externals/NUnit/tests/nunit.core.tests.net45.dll new file mode 100644 index 0000000000..083a9f54b Binary files /dev/null and b/Externals/NUnit/tests/nunit.core.tests.net45.dll differ diff --git a/Externals/NUnit/tests/nunit.framework.dll b/Externals/NUnit/tests/nunit.framework.dll new file mode 100644 index 0000000000..ed6550bb0 Binary files /dev/null and b/Externals/NUnit/tests/nunit.framework.dll differ diff --git a/Externals/NUnit/tests/nunit.framework.tests.dll b/Externals/NUnit/tests/nunit.framework.tests.dll new file mode 100644 index 0000000000..f83cec12a Binary files /dev/null and b/Externals/NUnit/tests/nunit.framework.tests.dll differ diff --git a/Externals/NUnit/tests/nunit.framework.tests.net45.dll b/Externals/NUnit/tests/nunit.framework.tests.net45.dll new file mode 100644 index 0000000000..47b8db0c5 Binary files /dev/null and b/Externals/NUnit/tests/nunit.framework.tests.net45.dll differ diff --git a/Externals/NUnit/tests/nunit.mocks.tests.dll b/Externals/NUnit/tests/nunit.mocks.tests.dll new file mode 100644 index 0000000000..6847781c3 Binary files /dev/null and b/Externals/NUnit/tests/nunit.mocks.tests.dll differ diff --git a/Externals/NUnit/tests/nunit.uiexception.tests.dll b/Externals/NUnit/tests/nunit.uiexception.tests.dll new file mode 100644 index 0000000000..4c6ce233a Binary files /dev/null and b/Externals/NUnit/tests/nunit.uiexception.tests.dll differ diff --git a/Externals/NUnit/tests/nunit.uikit.tests.dll b/Externals/NUnit/tests/nunit.uikit.tests.dll new file mode 100644 index 0000000000..0009bbaef Binary files /dev/null and b/Externals/NUnit/tests/nunit.uikit.tests.dll differ diff --git a/Externals/NUnit/tests/nunit.util.tests.dll b/Externals/NUnit/tests/nunit.util.tests.dll new file mode 100644 index 0000000000..3cb908569 Binary files /dev/null and b/Externals/NUnit/tests/nunit.util.tests.dll differ diff --git a/Externals/NUnit/tests/test-assembly-net45.dll b/Externals/NUnit/tests/test-assembly-net45.dll new file mode 100644 index 0000000000..3e64e070c Binary files /dev/null and b/Externals/NUnit/tests/test-assembly-net45.dll differ diff --git a/Externals/NUnit/tests/test-assembly.dll b/Externals/NUnit/tests/test-assembly.dll new file mode 100644 index 0000000000..281adf3d9 Binary files /dev/null and b/Externals/NUnit/tests/test-assembly.dll differ diff --git a/Externals/NUnit/tests/test-utilities.dll b/Externals/NUnit/tests/test-utilities.dll new file mode 100644 index 0000000000..80fa25fe2 Binary files /dev/null and b/Externals/NUnit/tests/test-utilities.dll differ diff --git a/Externals/TeRK/AForge ReadMe.txt b/Externals/TeRK/AForge ReadMe.txt new file mode 100644 index 0000000000..b32315ea9 --- /dev/null +++ b/Externals/TeRK/AForge ReadMe.txt @@ -0,0 +1,13 @@ +The TeRK.dll is a .NET assembly, which contains built of TeRK C# types generated from TeRK ICE definition. + +TeRK is Copyright 2007 Carnegie Mellon University Robotics +http://www.terk.ri.cmu.edu/ + +ICE is Copyright 2008 ZeroC, Inc +http://www.zeroc.com/ice.html + +The TeRK.dll assembly is built by Andrew Kirillov for AForge.NET project +andrew.kirillov@aforgenet.com + + +Note: The TeRK.dll requires Ice.dll and Glacier2.dll, which are part of ICE package. \ No newline at end of file diff --git a/Externals/TeRK/TeRK.dll b/Externals/TeRK/TeRK.dll new file mode 100644 index 0000000000..9489eaa11 Binary files /dev/null and b/Externals/TeRK/TeRK.dll differ diff --git a/Externals/ffmpeg/AForge ReadMe.txt b/Externals/ffmpeg/AForge ReadMe.txt new file mode 100644 index 0000000000..04fcef271 --- /dev/null +++ b/Externals/ffmpeg/AForge ReadMe.txt @@ -0,0 +1,5 @@ +The folder contains files from Sared and Dev packages of FFMPEG 32-bit build taken from +http://ffmpeg.zeranoe.com/builds/ +Note: few files which are not used by AForge.NET were removed to save space. + +Please, refer to README.txt file for details about FFMPEG build. diff --git a/Externals/ffmpeg/README.txt b/Externals/ffmpeg/README.txt new file mode 100644 index 0000000000..b4472b004 --- /dev/null +++ b/Externals/ffmpeg/README.txt @@ -0,0 +1,80 @@ +This is a FFmpeg Win32 shared build by Kyle Schwarz. + +Zeranoe's FFmpeg Builds Home Page: http://ffmpeg.zeranoe.com/builds/ + +Built on Jan 27 2012 18:37:07 + +FFmpeg version git-01fcbdf + libavutil 51. 34.101 / 51. 34.101 + libavcodec 53. 60.100 / 53. 60.100 + libavformat 53. 31.100 / 53. 31.100 + libavdevice 53. 4.100 / 53. 4.100 + libavfilter 2. 60.100 / 2. 60.100 + libswscale 2. 1.100 / 2. 1.100 + libswresample 0. 6.100 / 0. 6.100 + libpostproc 52. 0.100 / 52. 0.100 + +FFmpeg configured with: + --disable-static + --enable-shared + --enable-gpl + --enable-version3 + --disable-w32threads + --enable-runtime-cpudetect + --enable-avisynth + --enable-bzlib + --enable-frei0r + --enable-libopencore-amrnb + --enable-libopencore-amrwb + --enable-libfreetype + --enable-libgsm + --enable-libmp3lame + --enable-libopenjpeg + --enable-librtmp + --enable-libschroedinger + --enable-libspeex + --enable-libtheora + --enable-libvo-aacenc + --enable-libvo-amrwbenc + --enable-libvorbis + --enable-libvpx + --enable-libx264 + --enable-libxavs + --enable-libxvid + --enable-zlib + +The source code for this FFmpeg build can be found at: + http://ffmpeg.zeranoe.com/builds/source/ffmpeg/ + +This version of FFmpeg was built on: + Ubuntu Desktop 10.04: http://www.ubuntu.com/desktop + +The cross-compile toolchain used to compile this FFmpeg was: + MinGW-w64: http://mingw-w64.sourceforge.net/ + winpthreads (part of MinGW-w64) + +The GCC version used to compile this FFmpeg was: + GCC 4.6.2: http://gcc.gnu.org/ + +The external libaries compiled into this FFmpeg are: + bzip2 1.0.6 http://www.bzip.org + Frei0r 1.3 http://frei0r.dyne.org/ + opencore-amr 0.1.2 http://sourceforge.net/projects/opencore-amr/ + FreeType 2.4.6 http://www.freetype.org/ + gsm 1.0.13 http://libgsm.sourcearchive.com/ + LAME 3.98.4 http://lame.sourceforge.net/ + OpenJPEG 1.4 http://www.openjpeg.org/ + RTMP git-60218d0a http://rtmpdump.mplayerhq.hu/ + Schroedinger 1.0.10 http://diracvideo.org/ + Speex 1.2rc1 http://www.speex.org/ + Theora 1.1.1 http://www.theora.org/ + vo-aacenc 0.1.1 http://sourceforge.net/projects/opencore-amr/ + vo-amrwbenc 0.1.1 http://sourceforge.net/projects/opencore-amr/ + Vorbis 1.3.2 http://www.vorbis.com/ + libvpx v0.9.7-p1 http://www.webmproject.org/code/ + x264 git-bcd41db http://www.videolan.org/developers/x264.html + XAVS r55 http://xavs.sourceforge.net/ + Xvid 1.3.2 http://www.xvid.org/ + zlib 1.2.5 http://zlib.net/ + +License for each library can be found in the licenses folder. diff --git a/Externals/ffmpeg/include/libavcodec/avcodec.h b/Externals/ffmpeg/include/libavcodec/avcodec.h new file mode 100644 index 0000000000..62e90be01 --- /dev/null +++ b/Externals/ffmpeg/include/libavcodec/avcodec.h @@ -0,0 +1,4877 @@ +/* + * copyright (c) 2001 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_AVCODEC_H +#define AVCODEC_AVCODEC_H + +/** + * @file + * external API header + */ + +#include +#include "libavutil/samplefmt.h" +#include "libavutil/avutil.h" +#include "libavutil/cpu.h" +#include "libavutil/dict.h" +#include "libavutil/log.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" + +#include "libavcodec/version.h" +/** + * @defgroup libavc Encoding/Decoding Library + * @{ + * + * @defgroup lavc_decoding Decoding + * @{ + * @} + * + * @defgroup lavc_encoding Encoding + * @{ + * @} + * + * @defgroup lavc_codec Codecs + * @{ + * @defgroup lavc_codec_native Native Codecs + * @{ + * @} + * @defgroup lavc_codec_wrappers External library wrappers + * @{ + * @} + * @defgroup lavc_codec_hwaccel Hardware Accelerators bridge + * @{ + * @} + * @} + * @defgroup lavc_internal Internal + * @{ + * @} + * @} + * + */ + + +/** + * Identify the syntax and semantics of the bitstream. + * The principle is roughly: + * Two decoders with the same ID can decode the same streams. + * Two encoders with the same ID can encode compatible streams. + * There may be slight deviations from the principle due to implementation + * details. + * + * If you add a codec ID to this list, add it so that + * 1. no value of a existing codec ID changes (that would break ABI), + * 2. Give it a value which when taken as ASCII is recognized uniquely by a human as this specific codec. + * This ensures that 2 forks can independantly add CodecIDs without producing conflicts. + */ +enum CodecID { + CODEC_ID_NONE, + + /* video codecs */ + CODEC_ID_MPEG1VIDEO, + CODEC_ID_MPEG2VIDEO, ///< preferred ID for MPEG-1/2 video decoding + CODEC_ID_MPEG2VIDEO_XVMC, + CODEC_ID_H261, + CODEC_ID_H263, + CODEC_ID_RV10, + CODEC_ID_RV20, + CODEC_ID_MJPEG, + CODEC_ID_MJPEGB, + CODEC_ID_LJPEG, + CODEC_ID_SP5X, + CODEC_ID_JPEGLS, + CODEC_ID_MPEG4, + CODEC_ID_RAWVIDEO, + CODEC_ID_MSMPEG4V1, + CODEC_ID_MSMPEG4V2, + CODEC_ID_MSMPEG4V3, + CODEC_ID_WMV1, + CODEC_ID_WMV2, + CODEC_ID_H263P, + CODEC_ID_H263I, + CODEC_ID_FLV1, + CODEC_ID_SVQ1, + CODEC_ID_SVQ3, + CODEC_ID_DVVIDEO, + CODEC_ID_HUFFYUV, + CODEC_ID_CYUV, + CODEC_ID_H264, + CODEC_ID_INDEO3, + CODEC_ID_VP3, + CODEC_ID_THEORA, + CODEC_ID_ASV1, + CODEC_ID_ASV2, + CODEC_ID_FFV1, + CODEC_ID_4XM, + CODEC_ID_VCR1, + CODEC_ID_CLJR, + CODEC_ID_MDEC, + CODEC_ID_ROQ, + CODEC_ID_INTERPLAY_VIDEO, + CODEC_ID_XAN_WC3, + CODEC_ID_XAN_WC4, + CODEC_ID_RPZA, + CODEC_ID_CINEPAK, + CODEC_ID_WS_VQA, + CODEC_ID_MSRLE, + CODEC_ID_MSVIDEO1, + CODEC_ID_IDCIN, + CODEC_ID_8BPS, + CODEC_ID_SMC, + CODEC_ID_FLIC, + CODEC_ID_TRUEMOTION1, + CODEC_ID_VMDVIDEO, + CODEC_ID_MSZH, + CODEC_ID_ZLIB, + CODEC_ID_QTRLE, + CODEC_ID_SNOW, + CODEC_ID_TSCC, + CODEC_ID_ULTI, + CODEC_ID_QDRAW, + CODEC_ID_VIXL, + CODEC_ID_QPEG, + CODEC_ID_PNG, + CODEC_ID_PPM, + CODEC_ID_PBM, + CODEC_ID_PGM, + CODEC_ID_PGMYUV, + CODEC_ID_PAM, + CODEC_ID_FFVHUFF, + CODEC_ID_RV30, + CODEC_ID_RV40, + CODEC_ID_VC1, + CODEC_ID_WMV3, + CODEC_ID_LOCO, + CODEC_ID_WNV1, + CODEC_ID_AASC, + CODEC_ID_INDEO2, + CODEC_ID_FRAPS, + CODEC_ID_TRUEMOTION2, + CODEC_ID_BMP, + CODEC_ID_CSCD, + CODEC_ID_MMVIDEO, + CODEC_ID_ZMBV, + CODEC_ID_AVS, + CODEC_ID_SMACKVIDEO, + CODEC_ID_NUV, + CODEC_ID_KMVC, + CODEC_ID_FLASHSV, + CODEC_ID_CAVS, + CODEC_ID_JPEG2000, + CODEC_ID_VMNC, + CODEC_ID_VP5, + CODEC_ID_VP6, + CODEC_ID_VP6F, + CODEC_ID_TARGA, + CODEC_ID_DSICINVIDEO, + CODEC_ID_TIERTEXSEQVIDEO, + CODEC_ID_TIFF, + CODEC_ID_GIF, +#if LIBAVCODEC_VERSION_MAJOR == 53 + CODEC_ID_FFH264, +#endif + CODEC_ID_DXA, + CODEC_ID_DNXHD, + CODEC_ID_THP, + CODEC_ID_SGI, + CODEC_ID_C93, + CODEC_ID_BETHSOFTVID, + CODEC_ID_PTX, + CODEC_ID_TXD, + CODEC_ID_VP6A, + CODEC_ID_AMV, + CODEC_ID_VB, + CODEC_ID_PCX, + CODEC_ID_SUNRAST, + CODEC_ID_INDEO4, + CODEC_ID_INDEO5, + CODEC_ID_MIMIC, + CODEC_ID_RL2, +#if LIBAVCODEC_VERSION_MAJOR == 53 + CODEC_ID_8SVX_EXP, + CODEC_ID_8SVX_FIB, +#endif + CODEC_ID_ESCAPE124, + CODEC_ID_DIRAC, + CODEC_ID_BFI, + CODEC_ID_CMV, + CODEC_ID_MOTIONPIXELS, + CODEC_ID_TGV, + CODEC_ID_TGQ, + CODEC_ID_TQI, + CODEC_ID_AURA, + CODEC_ID_AURA2, + CODEC_ID_V210X, + CODEC_ID_TMV, + CODEC_ID_V210, + CODEC_ID_DPX, + CODEC_ID_MAD, + CODEC_ID_FRWU, + CODEC_ID_FLASHSV2, + CODEC_ID_CDGRAPHICS, + CODEC_ID_R210, + CODEC_ID_ANM, + CODEC_ID_BINKVIDEO, + CODEC_ID_IFF_ILBM, + CODEC_ID_IFF_BYTERUN1, + CODEC_ID_KGV1, + CODEC_ID_YOP, + CODEC_ID_VP8, + CODEC_ID_PICTOR, + CODEC_ID_ANSI, + CODEC_ID_A64_MULTI, + CODEC_ID_A64_MULTI5, + CODEC_ID_R10K, + CODEC_ID_MXPEG, + CODEC_ID_LAGARITH, + CODEC_ID_PRORES, + CODEC_ID_JV, + CODEC_ID_DFA, + CODEC_ID_WMV3IMAGE, + CODEC_ID_VC1IMAGE, +#if LIBAVCODEC_VERSION_MAJOR == 53 + CODEC_ID_G723_1_DEPRECATED, + CODEC_ID_G729_DEPRECATED, +#endif + CODEC_ID_UTVIDEO_DEPRECATED, + CODEC_ID_BMV_VIDEO, + CODEC_ID_VBLE, + CODEC_ID_DXTORY, + CODEC_ID_V410, + CODEC_ID_XWD, + CODEC_ID_Y41P = MKBETAG('Y','4','1','P'), + CODEC_ID_UTVIDEO = 0x800, + CODEC_ID_ESCAPE130 = MKBETAG('E','1','3','0'), + CODEC_ID_AVRP = MKBETAG('A','V','R','P'), + + CODEC_ID_G2M = MKBETAG( 0 ,'G','2','M'), + CODEC_ID_V308 = MKBETAG('V','3','0','8'), + CODEC_ID_YUV4 = MKBETAG('Y','U','V','4'), + + /* various PCM "codecs" */ + CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs + CODEC_ID_PCM_S16LE = 0x10000, + CODEC_ID_PCM_S16BE, + CODEC_ID_PCM_U16LE, + CODEC_ID_PCM_U16BE, + CODEC_ID_PCM_S8, + CODEC_ID_PCM_U8, + CODEC_ID_PCM_MULAW, + CODEC_ID_PCM_ALAW, + CODEC_ID_PCM_S32LE, + CODEC_ID_PCM_S32BE, + CODEC_ID_PCM_U32LE, + CODEC_ID_PCM_U32BE, + CODEC_ID_PCM_S24LE, + CODEC_ID_PCM_S24BE, + CODEC_ID_PCM_U24LE, + CODEC_ID_PCM_U24BE, + CODEC_ID_PCM_S24DAUD, + CODEC_ID_PCM_ZORK, + CODEC_ID_PCM_S16LE_PLANAR, + CODEC_ID_PCM_DVD, + CODEC_ID_PCM_F32BE, + CODEC_ID_PCM_F32LE, + CODEC_ID_PCM_F64BE, + CODEC_ID_PCM_F64LE, + CODEC_ID_PCM_BLURAY, + CODEC_ID_PCM_LXF, + CODEC_ID_S302M, + CODEC_ID_PCM_S8_PLANAR, + + /* various ADPCM codecs */ + CODEC_ID_ADPCM_IMA_QT = 0x11000, + CODEC_ID_ADPCM_IMA_WAV, + CODEC_ID_ADPCM_IMA_DK3, + CODEC_ID_ADPCM_IMA_DK4, + CODEC_ID_ADPCM_IMA_WS, + CODEC_ID_ADPCM_IMA_SMJPEG, + CODEC_ID_ADPCM_MS, + CODEC_ID_ADPCM_4XM, + CODEC_ID_ADPCM_XA, + CODEC_ID_ADPCM_ADX, + CODEC_ID_ADPCM_EA, + CODEC_ID_ADPCM_G726, + CODEC_ID_ADPCM_CT, + CODEC_ID_ADPCM_SWF, + CODEC_ID_ADPCM_YAMAHA, + CODEC_ID_ADPCM_SBPRO_4, + CODEC_ID_ADPCM_SBPRO_3, + CODEC_ID_ADPCM_SBPRO_2, + CODEC_ID_ADPCM_THP, + CODEC_ID_ADPCM_IMA_AMV, + CODEC_ID_ADPCM_EA_R1, + CODEC_ID_ADPCM_EA_R3, + CODEC_ID_ADPCM_EA_R2, + CODEC_ID_ADPCM_IMA_EA_SEAD, + CODEC_ID_ADPCM_IMA_EA_EACS, + CODEC_ID_ADPCM_EA_XAS, + CODEC_ID_ADPCM_EA_MAXIS_XA, + CODEC_ID_ADPCM_IMA_ISS, + CODEC_ID_ADPCM_G722, + CODEC_ID_ADPCM_IMA_APC, + + /* AMR */ + CODEC_ID_AMR_NB = 0x12000, + CODEC_ID_AMR_WB, + + /* RealAudio codecs*/ + CODEC_ID_RA_144 = 0x13000, + CODEC_ID_RA_288, + + /* various DPCM codecs */ + CODEC_ID_ROQ_DPCM = 0x14000, + CODEC_ID_INTERPLAY_DPCM, + CODEC_ID_XAN_DPCM, + CODEC_ID_SOL_DPCM, + + /* audio codecs */ + CODEC_ID_MP2 = 0x15000, + CODEC_ID_MP3, ///< preferred ID for decoding MPEG audio layer 1, 2 or 3 + CODEC_ID_AAC, + CODEC_ID_AC3, + CODEC_ID_DTS, + CODEC_ID_VORBIS, + CODEC_ID_DVAUDIO, + CODEC_ID_WMAV1, + CODEC_ID_WMAV2, + CODEC_ID_MACE3, + CODEC_ID_MACE6, + CODEC_ID_VMDAUDIO, +#if LIBAVCODEC_VERSION_MAJOR == 53 + CODEC_ID_SONIC, + CODEC_ID_SONIC_LS, +#endif + CODEC_ID_FLAC, + CODEC_ID_MP3ADU, + CODEC_ID_MP3ON4, + CODEC_ID_SHORTEN, + CODEC_ID_ALAC, + CODEC_ID_WESTWOOD_SND1, + CODEC_ID_GSM, ///< as in Berlin toast format + CODEC_ID_QDM2, + CODEC_ID_COOK, + CODEC_ID_TRUESPEECH, + CODEC_ID_TTA, + CODEC_ID_SMACKAUDIO, + CODEC_ID_QCELP, + CODEC_ID_WAVPACK, + CODEC_ID_DSICINAUDIO, + CODEC_ID_IMC, + CODEC_ID_MUSEPACK7, + CODEC_ID_MLP, + CODEC_ID_GSM_MS, /* as found in WAV */ + CODEC_ID_ATRAC3, + CODEC_ID_VOXWARE, + CODEC_ID_APE, + CODEC_ID_NELLYMOSER, + CODEC_ID_MUSEPACK8, + CODEC_ID_SPEEX, + CODEC_ID_WMAVOICE, + CODEC_ID_WMAPRO, + CODEC_ID_WMALOSSLESS, + CODEC_ID_ATRAC3P, + CODEC_ID_EAC3, + CODEC_ID_SIPR, + CODEC_ID_MP1, + CODEC_ID_TWINVQ, + CODEC_ID_TRUEHD, + CODEC_ID_MP4ALS, + CODEC_ID_ATRAC1, + CODEC_ID_BINKAUDIO_RDFT, + CODEC_ID_BINKAUDIO_DCT, + CODEC_ID_AAC_LATM, + CODEC_ID_QDMC, + CODEC_ID_CELT, +#if LIBAVCODEC_VERSION_MAJOR > 53 + CODEC_ID_G723_1_DEPRECATED, + CODEC_ID_G729_DEPRECATED, + CODEC_ID_8SVX_EXP, + CODEC_ID_8SVX_FIB, +#endif + CODEC_ID_BMV_AUDIO, + CODEC_ID_G729 = 0x15800, + CODEC_ID_G723_1= 0x15801, + CODEC_ID_FFWAVESYNTH = MKBETAG('F','F','W','S'), + CODEC_ID_8SVX_RAW = MKBETAG('8','S','V','X'), + + /* subtitle codecs */ + CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. + CODEC_ID_DVD_SUBTITLE = 0x17000, + CODEC_ID_DVB_SUBTITLE, + CODEC_ID_TEXT, ///< raw UTF-8 text + CODEC_ID_XSUB, + CODEC_ID_SSA, + CODEC_ID_MOV_TEXT, + CODEC_ID_HDMV_PGS_SUBTITLE, + CODEC_ID_DVB_TELETEXT, + CODEC_ID_SRT, + CODEC_ID_MICRODVD = MKBETAG('m','D','V','D'), + + /* other specific kind of codecs (generally used for attachments) */ + CODEC_ID_FIRST_UNKNOWN = 0x18000, ///< A dummy ID pointing at the start of various fake codecs. + CODEC_ID_TTF = 0x18000, + CODEC_ID_BINTEXT = MKBETAG('B','T','X','T'), + CODEC_ID_XBIN = MKBETAG('X','B','I','N'), + CODEC_ID_IDF = MKBETAG( 0 ,'I','D','F'), + + CODEC_ID_PROBE = 0x19000, ///< codec_id is not known (like CODEC_ID_NONE) but lavf should attempt to identify it + + CODEC_ID_MPEG2TS = 0x20000, /**< _FAKE_ codec to indicate a raw MPEG-2 TS + * stream (only used by libavformat) */ + CODEC_ID_MPEG4SYSTEMS = 0x20001, /**< _FAKE_ codec to indicate a MPEG-4 Systems + * stream (only used by libavformat) */ + CODEC_ID_FFMETADATA = 0x21000, ///< Dummy codec for streams containing only metadata information. +}; + +#if FF_API_OLD_SAMPLE_FMT +#define SampleFormat AVSampleFormat + +#define SAMPLE_FMT_NONE AV_SAMPLE_FMT_NONE +#define SAMPLE_FMT_U8 AV_SAMPLE_FMT_U8 +#define SAMPLE_FMT_S16 AV_SAMPLE_FMT_S16 +#define SAMPLE_FMT_S32 AV_SAMPLE_FMT_S32 +#define SAMPLE_FMT_FLT AV_SAMPLE_FMT_FLT +#define SAMPLE_FMT_DBL AV_SAMPLE_FMT_DBL +#define SAMPLE_FMT_NB AV_SAMPLE_FMT_NB +#endif + +#if FF_API_OLD_AUDIOCONVERT +#include "libavutil/audioconvert.h" + +/* Audio channel masks */ +#define CH_FRONT_LEFT AV_CH_FRONT_LEFT +#define CH_FRONT_RIGHT AV_CH_FRONT_RIGHT +#define CH_FRONT_CENTER AV_CH_FRONT_CENTER +#define CH_LOW_FREQUENCY AV_CH_LOW_FREQUENCY +#define CH_BACK_LEFT AV_CH_BACK_LEFT +#define CH_BACK_RIGHT AV_CH_BACK_RIGHT +#define CH_FRONT_LEFT_OF_CENTER AV_CH_FRONT_LEFT_OF_CENTER +#define CH_FRONT_RIGHT_OF_CENTER AV_CH_FRONT_RIGHT_OF_CENTER +#define CH_BACK_CENTER AV_CH_BACK_CENTER +#define CH_SIDE_LEFT AV_CH_SIDE_LEFT +#define CH_SIDE_RIGHT AV_CH_SIDE_RIGHT +#define CH_TOP_CENTER AV_CH_TOP_CENTER +#define CH_TOP_FRONT_LEFT AV_CH_TOP_FRONT_LEFT +#define CH_TOP_FRONT_CENTER AV_CH_TOP_FRONT_CENTER +#define CH_TOP_FRONT_RIGHT AV_CH_TOP_FRONT_RIGHT +#define CH_TOP_BACK_LEFT AV_CH_TOP_BACK_LEFT +#define CH_TOP_BACK_CENTER AV_CH_TOP_BACK_CENTER +#define CH_TOP_BACK_RIGHT AV_CH_TOP_BACK_RIGHT +#define CH_STEREO_LEFT AV_CH_STEREO_LEFT +#define CH_STEREO_RIGHT AV_CH_STEREO_RIGHT + +/** Channel mask value used for AVCodecContext.request_channel_layout + to indicate that the user requests the channel order of the decoder output + to be the native codec channel order. */ +#define CH_LAYOUT_NATIVE AV_CH_LAYOUT_NATIVE + +/* Audio channel convenience macros */ +#define CH_LAYOUT_MONO AV_CH_LAYOUT_MONO +#define CH_LAYOUT_STEREO AV_CH_LAYOUT_STEREO +#define CH_LAYOUT_2_1 AV_CH_LAYOUT_2_1 +#define CH_LAYOUT_SURROUND AV_CH_LAYOUT_SURROUND +#define CH_LAYOUT_4POINT0 AV_CH_LAYOUT_4POINT0 +#define CH_LAYOUT_2_2 AV_CH_LAYOUT_2_2 +#define CH_LAYOUT_QUAD AV_CH_LAYOUT_QUAD +#define CH_LAYOUT_5POINT0 AV_CH_LAYOUT_5POINT0 +#define CH_LAYOUT_5POINT1 AV_CH_LAYOUT_5POINT1 +#define CH_LAYOUT_5POINT0_BACK AV_CH_LAYOUT_5POINT0_BACK +#define CH_LAYOUT_5POINT1_BACK AV_CH_LAYOUT_5POINT1_BACK +#define CH_LAYOUT_7POINT0 AV_CH_LAYOUT_7POINT0 +#define CH_LAYOUT_7POINT1 AV_CH_LAYOUT_7POINT1 +#define CH_LAYOUT_7POINT1_WIDE AV_CH_LAYOUT_7POINT1_WIDE +#define CH_LAYOUT_STEREO_DOWNMIX AV_CH_LAYOUT_STEREO_DOWNMIX +#endif + +#if FF_API_OLD_DECODE_AUDIO +/* in bytes */ +#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio +#endif + +/** + * Required number of additionally allocated bytes at the end of the input bitstream for decoding. + * This is mainly needed because some optimized bitstream readers read + * 32 or 64 bit at once and could read over the end.
+ * Note: If the first 23 bits of the additional bytes are not 0, then damaged + * MPEG bitstreams could cause overread and segfault. + */ +#define FF_INPUT_BUFFER_PADDING_SIZE 16 + +/** + * minimum encoding buffer size + * Used to avoid some checks during header writing. + */ +#define FF_MIN_BUFFER_SIZE 16384 + + +/** + * motion estimation type. + */ +enum Motion_Est_ID { + ME_ZERO = 1, ///< no search, that is use 0,0 vector whenever one is needed + ME_FULL, + ME_LOG, + ME_PHODS, + ME_EPZS, ///< enhanced predictive zonal search + ME_X1, ///< reserved for experiments + ME_HEX, ///< hexagon based search + ME_UMH, ///< uneven multi-hexagon search + ME_ITER, ///< iterative search + ME_TESA, ///< transformed exhaustive search algorithm +}; + +enum AVDiscard{ + /* We leave some space between them for extensions (drop some + * keyframes for intra-only or drop just some bidir frames). */ + AVDISCARD_NONE =-16, ///< discard nothing + AVDISCARD_DEFAULT= 0, ///< discard useless packets like 0 size packets in avi + AVDISCARD_NONREF = 8, ///< discard all non reference + AVDISCARD_BIDIR = 16, ///< discard all bidirectional frames + AVDISCARD_NONKEY = 32, ///< discard all frames except keyframes + AVDISCARD_ALL = 48, ///< discard all +}; + +enum AVColorPrimaries{ + AVCOL_PRI_BT709 =1, ///< also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP177 Annex B + AVCOL_PRI_UNSPECIFIED=2, + AVCOL_PRI_BT470M =4, + AVCOL_PRI_BT470BG =5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM + AVCOL_PRI_SMPTE170M =6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC + AVCOL_PRI_SMPTE240M =7, ///< functionally identical to above + AVCOL_PRI_FILM =8, + AVCOL_PRI_NB , ///< Not part of ABI +}; + +enum AVColorTransferCharacteristic{ + AVCOL_TRC_BT709 =1, ///< also ITU-R BT1361 + AVCOL_TRC_UNSPECIFIED=2, + AVCOL_TRC_GAMMA22 =4, ///< also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM + AVCOL_TRC_GAMMA28 =5, ///< also ITU-R BT470BG + AVCOL_TRC_SMPTE240M =7, + AVCOL_TRC_NB , ///< Not part of ABI +}; + +enum AVColorSpace{ + AVCOL_SPC_RGB =0, + AVCOL_SPC_BT709 =1, ///< also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / SMPTE RP177 Annex B + AVCOL_SPC_UNSPECIFIED=2, + AVCOL_SPC_FCC =4, + AVCOL_SPC_BT470BG =5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601 + AVCOL_SPC_SMPTE170M =6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC / functionally identical to above + AVCOL_SPC_SMPTE240M =7, + AVCOL_SPC_YCGCO =8, + AVCOL_SPC_NB , ///< Not part of ABI +}; + +enum AVColorRange{ + AVCOL_RANGE_UNSPECIFIED=0, + AVCOL_RANGE_MPEG =1, ///< the normal 219*2^(n-8) "MPEG" YUV ranges + AVCOL_RANGE_JPEG =2, ///< the normal 2^n-1 "JPEG" YUV ranges + AVCOL_RANGE_NB , ///< Not part of ABI +}; + +/** + * X X 3 4 X X are luma samples, + * 1 2 1-6 are possible chroma positions + * X X 5 6 X 0 is undefined/unknown position + */ +enum AVChromaLocation{ + AVCHROMA_LOC_UNSPECIFIED=0, + AVCHROMA_LOC_LEFT =1, ///< mpeg2/4, h264 default + AVCHROMA_LOC_CENTER =2, ///< mpeg1, jpeg, h263 + AVCHROMA_LOC_TOPLEFT =3, ///< DV + AVCHROMA_LOC_TOP =4, + AVCHROMA_LOC_BOTTOMLEFT =5, + AVCHROMA_LOC_BOTTOM =6, + AVCHROMA_LOC_NB , ///< Not part of ABI +}; + +#if FF_API_FLAC_GLOBAL_OPTS +/** + * LPC analysis type + */ +enum AVLPCType { + AV_LPC_TYPE_DEFAULT = -1, ///< use the codec default LPC type + AV_LPC_TYPE_NONE = 0, ///< do not use LPC prediction or use all zero coefficients + AV_LPC_TYPE_FIXED = 1, ///< fixed LPC coefficients + AV_LPC_TYPE_LEVINSON = 2, ///< Levinson-Durbin recursion + AV_LPC_TYPE_CHOLESKY = 3, ///< Cholesky factorization + AV_LPC_TYPE_NB , ///< Not part of ABI +}; +#endif + +enum AVAudioServiceType { + AV_AUDIO_SERVICE_TYPE_MAIN = 0, + AV_AUDIO_SERVICE_TYPE_EFFECTS = 1, + AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED = 2, + AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED = 3, + AV_AUDIO_SERVICE_TYPE_DIALOGUE = 4, + AV_AUDIO_SERVICE_TYPE_COMMENTARY = 5, + AV_AUDIO_SERVICE_TYPE_EMERGENCY = 6, + AV_AUDIO_SERVICE_TYPE_VOICE_OVER = 7, + AV_AUDIO_SERVICE_TYPE_KARAOKE = 8, + AV_AUDIO_SERVICE_TYPE_NB , ///< Not part of ABI +}; + +typedef struct RcOverride{ + int start_frame; + int end_frame; + int qscale; // If this is 0 then quality_factor will be used instead. + float quality_factor; +} RcOverride; + +#define FF_MAX_B_FRAMES 16 + +/* encoding support + These flags can be passed in AVCodecContext.flags before initialization. + Note: Not everything is supported yet. +*/ + +#define CODEC_FLAG_QSCALE 0x0002 ///< Use fixed qscale. +#define CODEC_FLAG_4MV 0x0004 ///< 4 MV per MB allowed / advanced prediction for H.263. +#define CODEC_FLAG_QPEL 0x0010 ///< Use qpel MC. +#define CODEC_FLAG_GMC 0x0020 ///< Use GMC. +#define CODEC_FLAG_MV0 0x0040 ///< Always try a MB with MV=<0,0>. +/** + * The parent program guarantees that the input for B-frames containing + * streams is not written to for at least s->max_b_frames+1 frames, if + * this is not set the input will be copied. + */ +#define CODEC_FLAG_INPUT_PRESERVED 0x0100 +#define CODEC_FLAG_PASS1 0x0200 ///< Use internal 2pass ratecontrol in first pass mode. +#define CODEC_FLAG_PASS2 0x0400 ///< Use internal 2pass ratecontrol in second pass mode. +#define CODEC_FLAG_GRAY 0x2000 ///< Only decode/encode grayscale. +#define CODEC_FLAG_EMU_EDGE 0x4000 ///< Don't draw edges. +#define CODEC_FLAG_PSNR 0x8000 ///< error[?] variables will be set during encoding. +#define CODEC_FLAG_TRUNCATED 0x00010000 /** Input bitstream might be truncated at a random + location instead of only at frame boundaries. */ +#define CODEC_FLAG_NORMALIZE_AQP 0x00020000 ///< Normalize adaptive quantization. +#define CODEC_FLAG_INTERLACED_DCT 0x00040000 ///< Use interlaced DCT. +#define CODEC_FLAG_LOW_DELAY 0x00080000 ///< Force low delay. +#define CODEC_FLAG_GLOBAL_HEADER 0x00400000 ///< Place global headers in extradata instead of every keyframe. +#define CODEC_FLAG_BITEXACT 0x00800000 ///< Use only bitexact stuff (except (I)DCT). +/* Fx : Flag for h263+ extra options */ +#define CODEC_FLAG_AC_PRED 0x01000000 ///< H.263 advanced intra coding / MPEG-4 AC prediction +#define CODEC_FLAG_CBP_RD 0x04000000 ///< Use rate distortion optimization for cbp. +#define CODEC_FLAG_QP_RD 0x08000000 ///< Use rate distortion optimization for qp selectioon. +#define CODEC_FLAG_LOOP_FILTER 0x00000800 ///< loop filter +#define CODEC_FLAG_INTERLACED_ME 0x20000000 ///< interlaced motion estimation +#define CODEC_FLAG_CLOSED_GOP 0x80000000 +#define CODEC_FLAG2_FAST 0x00000001 ///< Allow non spec compliant speedup tricks. +#define CODEC_FLAG2_STRICT_GOP 0x00000002 ///< Strictly enforce GOP size. +#define CODEC_FLAG2_NO_OUTPUT 0x00000004 ///< Skip bitstream encoding. +#define CODEC_FLAG2_LOCAL_HEADER 0x00000008 ///< Place global headers at every keyframe instead of in extradata. +#define CODEC_FLAG2_SKIP_RD 0x00004000 ///< RD optimal MB level residual skipping +#define CODEC_FLAG2_CHUNKS 0x00008000 ///< Input bitstream might be truncated at a packet boundaries instead of only at frame boundaries. +#define CODEC_FLAG2_SHOW_ALL 0x00400000 ///< Show all frames before the first keyframe +/** + * @defgroup deprecated_flags Deprecated codec flags + * Use corresponding private codec options instead. + * @{ + */ +#if FF_API_MPEGVIDEO_GLOBAL_OPTS +#define CODEC_FLAG_OBMC 0x00000001 ///< OBMC +#define CODEC_FLAG_H263P_AIV 0x00000008 ///< H.263 alternative inter VLC +#define CODEC_FLAG_PART 0x0080 ///< Use data partitioning. +#define CODEC_FLAG_ALT_SCAN 0x00100000 ///< Use alternate scan. +#define CODEC_FLAG_H263P_UMV 0x02000000 ///< unlimited motion vector +#define CODEC_FLAG_H263P_SLICE_STRUCT 0x10000000 +#define CODEC_FLAG_SVCD_SCAN_OFFSET 0x40000000 ///< Will reserve space for SVCD scan offset user data. +#define CODEC_FLAG2_INTRA_VLC 0x00000800 ///< Use MPEG-2 intra VLC table. +#define CODEC_FLAG2_DROP_FRAME_TIMECODE 0x00002000 ///< timecode is in drop frame format. +#define CODEC_FLAG2_NON_LINEAR_QUANT 0x00010000 ///< Use MPEG-2 nonlinear quantizer. +#endif +#if FF_API_MJPEG_GLOBAL_OPTS +#define CODEC_FLAG_EXTERN_HUFF 0x1000 ///< Use external Huffman table (for MJPEG). +#endif +#if FF_API_X264_GLOBAL_OPTS +#define CODEC_FLAG2_BPYRAMID 0x00000010 ///< H.264 allow B-frames to be used as references. +#define CODEC_FLAG2_WPRED 0x00000020 ///< H.264 weighted biprediction for B-frames +#define CODEC_FLAG2_MIXED_REFS 0x00000040 ///< H.264 one reference per partition, as opposed to one reference per macroblock +#define CODEC_FLAG2_8X8DCT 0x00000080 ///< H.264 high profile 8x8 transform +#define CODEC_FLAG2_FASTPSKIP 0x00000100 ///< H.264 fast pskip +#define CODEC_FLAG2_AUD 0x00000200 ///< H.264 access unit delimiters +#define CODEC_FLAG2_BRDO 0x00000400 ///< B-frame rate-distortion optimization +#define CODEC_FLAG2_MBTREE 0x00040000 ///< Use macroblock tree ratecontrol (x264 only) +#define CODEC_FLAG2_PSY 0x00080000 ///< Use psycho visual optimizations. +#define CODEC_FLAG2_SSIM 0x00100000 ///< Compute SSIM during encoding, error[] values are undefined. +#define CODEC_FLAG2_INTRA_REFRESH 0x00200000 ///< Use periodic insertion of intra blocks instead of keyframes. +#endif +#if FF_API_SNOW_GLOBAL_OPTS +#define CODEC_FLAG2_MEMC_ONLY 0x00001000 ///< Only do ME/MC (I frames -> ref, P frame -> ME+MC). +#endif +#if FF_API_LAME_GLOBAL_OPTS +#define CODEC_FLAG2_BIT_RESERVOIR 0x00020000 ///< Use a bit reservoir when encoding if possible +#endif +/** + * @} + */ + +/* Unsupported options : + * Syntax Arithmetic coding (SAC) + * Reference Picture Selection + * Independent Segment Decoding */ +/* /Fx */ +/* codec capabilities */ + +#define CODEC_CAP_DRAW_HORIZ_BAND 0x0001 ///< Decoder can use draw_horiz_band callback. +/** + * Codec uses get_buffer() for allocating buffers and supports custom allocators. + * If not set, it might not use get_buffer() at all or use operations that + * assume the buffer was allocated by avcodec_default_get_buffer. + */ +#define CODEC_CAP_DR1 0x0002 +#if FF_API_PARSE_FRAME +/* If 'parse_only' field is true, then avcodec_parse_frame() can be used. */ +#define CODEC_CAP_PARSE_ONLY 0x0004 +#endif +#define CODEC_CAP_TRUNCATED 0x0008 +/* Codec can export data for HW decoding (XvMC). */ +#define CODEC_CAP_HWACCEL 0x0010 +/** + * Encoder or decoder requires flushing with NULL input at the end in order to + * give the complete and correct output. + * + * NOTE: If this flag is not set, the codec is guaranteed to never be fed with + * with NULL data. The user can still send NULL data to the public encode + * or decode function, but libavcodec will not pass it along to the codec + * unless this flag is set. + * + * Decoders: + * The decoder has a non-zero delay and needs to be fed with avpkt->data=NULL, + * avpkt->size=0 at the end to get the delayed data until the decoder no longer + * returns frames. + * + * Encoders: + * The encoder needs to be fed with NULL data at the end of encoding until the + * encoder no longer returns data. + * + * NOTE: For encoders implementing the AVCodec.encode2() function, setting this + * flag also means that the encoder must set the pts and duration for + * each output packet. If this flag is not set, the pts and duration will + * be determined by libavcodec from the input frame. + */ +#define CODEC_CAP_DELAY 0x0020 +/** + * Codec can be fed a final frame with a smaller size. + * This can be used to prevent truncation of the last audio samples. + */ +#define CODEC_CAP_SMALL_LAST_FRAME 0x0040 +/** + * Codec can export data for HW decoding (VDPAU). + */ +#define CODEC_CAP_HWACCEL_VDPAU 0x0080 +/** + * Codec can output multiple frames per AVPacket + * Normally demuxers return one frame at a time, demuxers which do not do + * are connected to a parser to split what they return into proper frames. + * This flag is reserved to the very rare category of codecs which have a + * bitstream that cannot be split into frames without timeconsuming + * operations like full decoding. Demuxers carring such bitstreams thus + * may return multiple frames in a packet. This has many disadvantages like + * prohibiting stream copy in many cases thus it should only be considered + * as a last resort. + */ +#define CODEC_CAP_SUBFRAMES 0x0100 +/** + * Codec is experimental and is thus avoided in favor of non experimental + * encoders + */ +#define CODEC_CAP_EXPERIMENTAL 0x0200 +/** + * Codec should fill in channel configuration and samplerate instead of container + */ +#define CODEC_CAP_CHANNEL_CONF 0x0400 + +/** + * Codec is able to deal with negative linesizes + */ +#define CODEC_CAP_NEG_LINESIZES 0x0800 + +/** + * Codec supports frame-level multithreading. + */ +#define CODEC_CAP_FRAME_THREADS 0x1000 +/** + * Codec supports slice-based (or partition-based) multithreading. + */ +#define CODEC_CAP_SLICE_THREADS 0x2000 +/** + * Codec supports changed parameters at any point. + */ +#define CODEC_CAP_PARAM_CHANGE 0x4000 +/** + * Codec supports avctx->thread_count == 0 (auto). + */ +#define CODEC_CAP_AUTO_THREADS 0x8000 +/** + * Audio encoder supports receiving a different number of samples in each call. + */ +#define CODEC_CAP_VARIABLE_FRAME_SIZE 0x10000 +/** + * Codec is lossless. + */ +#define CODEC_CAP_LOSSLESS 0x80000000 + +//The following defines may change, don't expect compatibility if you use them. +#define MB_TYPE_INTRA4x4 0x0001 +#define MB_TYPE_INTRA16x16 0x0002 //FIXME H.264-specific +#define MB_TYPE_INTRA_PCM 0x0004 //FIXME H.264-specific +#define MB_TYPE_16x16 0x0008 +#define MB_TYPE_16x8 0x0010 +#define MB_TYPE_8x16 0x0020 +#define MB_TYPE_8x8 0x0040 +#define MB_TYPE_INTERLACED 0x0080 +#define MB_TYPE_DIRECT2 0x0100 //FIXME +#define MB_TYPE_ACPRED 0x0200 +#define MB_TYPE_GMC 0x0400 +#define MB_TYPE_SKIP 0x0800 +#define MB_TYPE_P0L0 0x1000 +#define MB_TYPE_P1L0 0x2000 +#define MB_TYPE_P0L1 0x4000 +#define MB_TYPE_P1L1 0x8000 +#define MB_TYPE_L0 (MB_TYPE_P0L0 | MB_TYPE_P1L0) +#define MB_TYPE_L1 (MB_TYPE_P0L1 | MB_TYPE_P1L1) +#define MB_TYPE_L0L1 (MB_TYPE_L0 | MB_TYPE_L1) +#define MB_TYPE_QUANT 0x00010000 +#define MB_TYPE_CBP 0x00020000 +//Note bits 24-31 are reserved for codec specific use (h264 ref0, mpeg1 0mv, ...) + +/** + * Pan Scan area. + * This specifies the area which should be displayed. + * Note there may be multiple such areas for one frame. + */ +typedef struct AVPanScan{ + /** + * id + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int id; + + /** + * width and height in 1/16 pel + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int width; + int height; + + /** + * position of the top left corner in 1/16 pel for up to 3 fields/frames + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int16_t position[3][2]; +}AVPanScan; + +#define FF_QSCALE_TYPE_MPEG1 0 +#define FF_QSCALE_TYPE_MPEG2 1 +#define FF_QSCALE_TYPE_H264 2 +#define FF_QSCALE_TYPE_VP56 3 + +#define FF_BUFFER_TYPE_INTERNAL 1 +#define FF_BUFFER_TYPE_USER 2 ///< direct rendering buffers (image is (de)allocated by user) +#define FF_BUFFER_TYPE_SHARED 4 ///< Buffer from somewhere else; don't deallocate image (data/base), all other tables are not shared. +#define FF_BUFFER_TYPE_COPY 8 ///< Just a (modified) copy of some other buffer, don't deallocate anything. + +#if FF_API_OLD_FF_PICT_TYPES +/* DEPRECATED, directly use the AV_PICTURE_TYPE_* enum values */ +#define FF_I_TYPE AV_PICTURE_TYPE_I ///< Intra +#define FF_P_TYPE AV_PICTURE_TYPE_P ///< Predicted +#define FF_B_TYPE AV_PICTURE_TYPE_B ///< Bi-dir predicted +#define FF_S_TYPE AV_PICTURE_TYPE_S ///< S(GMC)-VOP MPEG4 +#define FF_SI_TYPE AV_PICTURE_TYPE_SI ///< Switching Intra +#define FF_SP_TYPE AV_PICTURE_TYPE_SP ///< Switching Predicted +#define FF_BI_TYPE AV_PICTURE_TYPE_BI +#endif + +#define FF_BUFFER_HINTS_VALID 0x01 // Buffer hints value is meaningful (if 0 ignore). +#define FF_BUFFER_HINTS_READABLE 0x02 // Codec will read from buffer. +#define FF_BUFFER_HINTS_PRESERVE 0x04 // User must not alter buffer content. +#define FF_BUFFER_HINTS_REUSABLE 0x08 // Codec will reuse the buffer (update). + +enum AVPacketSideDataType { + AV_PKT_DATA_PALETTE, + AV_PKT_DATA_NEW_EXTRADATA, + AV_PKT_DATA_PARAM_CHANGE, +}; + +typedef struct AVPacket { + /** + * Presentation timestamp in AVStream->time_base units; the time at which + * the decompressed packet will be presented to the user. + * Can be AV_NOPTS_VALUE if it is not stored in the file. + * pts MUST be larger or equal to dts as presentation cannot happen before + * decompression, unless one wants to view hex dumps. Some formats misuse + * the terms dts and pts/cts to mean something different. Such timestamps + * must be converted to true pts/dts before they are stored in AVPacket. + */ + int64_t pts; + /** + * Decompression timestamp in AVStream->time_base units; the time at which + * the packet is decompressed. + * Can be AV_NOPTS_VALUE if it is not stored in the file. + */ + int64_t dts; + uint8_t *data; + int size; + int stream_index; + /** + * A combination of AV_PKT_FLAG values + */ + int flags; + /** + * Additional packet data that can be provided by the container. + * Packet can contain several types of side information. + */ + struct { + uint8_t *data; + int size; + enum AVPacketSideDataType type; + } *side_data; + int side_data_elems; + + /** + * Duration of this packet in AVStream->time_base units, 0 if unknown. + * Equals next_pts - this_pts in presentation order. + */ + int duration; + void (*destruct)(struct AVPacket *); + void *priv; + int64_t pos; ///< byte position in stream, -1 if unknown + + /** + * Time difference in AVStream->time_base units from the pts of this + * packet to the point at which the output from the decoder has converged + * independent from the availability of previous frames. That is, the + * frames are virtually identical no matter if decoding started from + * the very first frame or from this keyframe. + * Is AV_NOPTS_VALUE if unknown. + * This field is not the display duration of the current packet. + * This field has no meaning if the packet does not have AV_PKT_FLAG_KEY + * set. + * + * The purpose of this field is to allow seeking in streams that have no + * keyframes in the conventional sense. It corresponds to the + * recovery point SEI in H.264 and match_time_delta in NUT. It is also + * essential for some types of subtitle streams to ensure that all + * subtitles are correctly displayed after seeking. + */ + int64_t convergence_duration; +} AVPacket; +#define AV_PKT_FLAG_KEY 0x0001 ///< The packet contains a keyframe +#define AV_PKT_FLAG_CORRUPT 0x0002 ///< The packet content is corrupted + +/** + * An AV_PKT_DATA_PARAM_CHANGE side data packet is laid out as follows: + * u32le param_flags + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT) + * s32le channel_count + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT) + * u64le channel_layout + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) + * s32le sample_rate + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS) + * s32le width + * s32le height + */ + +enum AVSideDataParamChangeFlags { + AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT = 0x0001, + AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT = 0x0002, + AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE = 0x0004, + AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS = 0x0008, +}; + +/** + * Audio Video Frame. + * New fields can be added to the end of AVFRAME with minor version + * bumps. Similarly fields that are marked as to be only accessed by + * av_opt_ptr() can be reordered. This allows 2 forks to add fields + * without breaking compatibility with each other. + * Removal, reordering and changes in the remaining cases require + * a major version bump. + * sizeof(AVFrame) must not be used outside libavcodec. + */ +typedef struct AVFrame { +#if FF_API_DATA_POINTERS +#define AV_NUM_DATA_POINTERS 4 +#else +#define AV_NUM_DATA_POINTERS 8 +#endif + /** + * pointer to the picture/channel planes. + * This might be different from the first allocated byte + * - encoding: Set by user + * - decoding: set by AVCodecContext.get_buffer() + */ + uint8_t *data[AV_NUM_DATA_POINTERS]; + + /** + * Size, in bytes, of the data for each picture/channel plane. + * + * For audio, only linesize[0] may be set. For planar audio, each channel + * plane must be the same size. + * + * - encoding: Set by user (video only) + * - decoding: set by AVCodecContext.get_buffer() + */ + int linesize[AV_NUM_DATA_POINTERS]; + + /** + * pointer to the first allocated byte of the picture. Can be used in get_buffer/release_buffer. + * This isn't used by libavcodec unless the default get/release_buffer() is used. + * - encoding: + * - decoding: + */ + uint8_t *base[AV_NUM_DATA_POINTERS]; + /** + * 1 -> keyframe, 0-> not + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + int key_frame; + + /** + * Picture type of the frame, see ?_TYPE below. + * - encoding: Set by libavcodec. for coded_picture (and set by user for input). + * - decoding: Set by libavcodec. + */ + enum AVPictureType pict_type; + + /** + * presentation timestamp in time_base units (time when frame should be shown to user) + * If AV_NOPTS_VALUE then frame_rate = 1/time_base will be assumed. + * - encoding: MUST be set by user. + * - decoding: Set by libavcodec. + */ + int64_t pts; + + /** + * picture number in bitstream order + * - encoding: set by + * - decoding: Set by libavcodec. + */ + int coded_picture_number; + /** + * picture number in display order + * - encoding: set by + * - decoding: Set by libavcodec. + */ + int display_picture_number; + + /** + * quality (between 1 (good) and FF_LAMBDA_MAX (bad)) + * - encoding: Set by libavcodec. for coded_picture (and set by user for input). + * - decoding: Set by libavcodec. + */ + int quality; + +#if FF_API_AVFRAME_AGE + /** + * @deprecated unused + */ + attribute_deprecated int age; +#endif + + /** + * is this picture used as reference + * The values for this are the same as the MpegEncContext.picture_structure + * variable, that is 1->top field, 2->bottom field, 3->frame/both fields. + * Set to 4 for delayed, non-reference frames. + * - encoding: unused + * - decoding: Set by libavcodec. (before get_buffer() call)). + */ + int reference; + + /** + * QP table + * - encoding: unused + * - decoding: Set by libavcodec. + */ + int8_t *qscale_table; + /** + * QP store stride + * - encoding: unused + * - decoding: Set by libavcodec. + */ + int qstride; + + /** + * mbskip_table[mb]>=1 if MB didn't change + * stride= mb_width = (width+15)>>4 + * - encoding: unused + * - decoding: Set by libavcodec. + */ + uint8_t *mbskip_table; + + /** + * motion vector table + * @code + * example: + * int mv_sample_log2= 4 - motion_subsample_log2; + * int mb_width= (width+15)>>4; + * int mv_stride= (mb_width << mv_sample_log2) + 1; + * motion_val[direction][x + y*mv_stride][0->mv_x, 1->mv_y]; + * @endcode + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int16_t (*motion_val[2])[2]; + + /** + * macroblock type table + * mb_type_base + mb_width + 2 + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + uint32_t *mb_type; + + /** + * log2 of the size of the block which a single vector in motion_val represents: + * (4->16x16, 3->8x8, 2-> 4x4, 1-> 2x2) + * - encoding: unused + * - decoding: Set by libavcodec. + */ + uint8_t motion_subsample_log2; + + /** + * for some private data of the user + * - encoding: unused + * - decoding: Set by user. + */ + void *opaque; + + /** + * error + * - encoding: Set by libavcodec. if flags&CODEC_FLAG_PSNR. + * - decoding: unused + */ + uint64_t error[AV_NUM_DATA_POINTERS]; + + /** + * type of the buffer (to keep track of who has to deallocate data[*]) + * - encoding: Set by the one who allocates it. + * - decoding: Set by the one who allocates it. + * Note: User allocated (direct rendering) & internal buffers cannot coexist currently. + */ + int type; + + /** + * When decoding, this signals how much the picture must be delayed. + * extra_delay = repeat_pict / (2*fps) + * - encoding: unused + * - decoding: Set by libavcodec. + */ + int repeat_pict; + + /** + * + */ + int qscale_type; + + /** + * The content of the picture is interlaced. + * - encoding: Set by user. + * - decoding: Set by libavcodec. (default 0) + */ + int interlaced_frame; + + /** + * If the content is interlaced, is top field displayed first. + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int top_field_first; + + /** + * Pan scan. + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + AVPanScan *pan_scan; + + /** + * Tell user application that palette has changed from previous frame. + * - encoding: ??? (no palette-enabled encoder yet) + * - decoding: Set by libavcodec. (default 0). + */ + int palette_has_changed; + + /** + * codec suggestion on buffer type if != 0 + * - encoding: unused + * - decoding: Set by libavcodec. (before get_buffer() call)). + */ + int buffer_hints; + + /** + * DCT coefficients + * - encoding: unused + * - decoding: Set by libavcodec. + */ + short *dct_coeff; + + /** + * motion reference frame index + * the order in which these are stored can depend on the codec. + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int8_t *ref_index[2]; + + /** + * reordered opaque 64bit (generally an integer or a double precision float + * PTS but can be anything). + * The user sets AVCodecContext.reordered_opaque to represent the input at + * that time, + * the decoder reorders values as needed and sets AVFrame.reordered_opaque + * to exactly one of the values provided by the user through AVCodecContext.reordered_opaque + * @deprecated in favor of pkt_pts + * - encoding: unused + * - decoding: Read by user. + */ + int64_t reordered_opaque; + + /** + * hardware accelerator private data (FFmpeg-allocated) + * - encoding: unused + * - decoding: Set by libavcodec + */ + void *hwaccel_picture_private; + + /** + * reordered pts from the last AVPacket that has been input into the decoder + * - encoding: unused + * - decoding: Read by user. + */ + int64_t pkt_pts; + + /** + * dts from the last AVPacket that has been input into the decoder + * - encoding: unused + * - decoding: Read by user. + */ + int64_t pkt_dts; + + /** + * the AVCodecContext which ff_thread_get_buffer() was last called on + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + struct AVCodecContext *owner; + + /** + * used by multithreading to store frame-specific info + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + void *thread_opaque; + + /** + * number of audio samples (per channel) described by this frame + * - encoding: unused + * - decoding: Set by libavcodec + */ + int nb_samples; + + /** + * pointers to the data planes/channels. + * + * For video, this should simply point to data[]. + * + * For planar audio, each channel has a separate data pointer, and + * linesize[0] contains the size of each channel buffer. + * For packed audio, there is just one data pointer, and linesize[0] + * contains the total size of the buffer for all channels. + * + * Note: Both data and extended_data will always be set by get_buffer(), + * but for planar audio with more channels that can fit in data, + * extended_data must be used by the decoder in order to access all + * channels. + * + * encoding: unused + * decoding: set by AVCodecContext.get_buffer() + */ + uint8_t **extended_data; + + /** + * sample aspect ratio for the video frame, 0/1 if unknown\unspecified + * - encoding: unused + * - decoding: Read by user. + */ + AVRational sample_aspect_ratio; + + /** + * width and height of the video frame + * - encoding: unused + * - decoding: Read by user. + */ + int width, height; + + /** + * format of the frame, -1 if unknown or unset + * Values correspond to enum PixelFormat for video frames, + * enum AVSampleFormat for audio) + * - encoding: unused + * - decoding: Read by user. + */ + int format; + + /** + * frame timestamp estimated using various heuristics, in stream time base + * Code outside libavcodec should access this field using: + * av_opt_ptr(avcodec_get_frame_class(), frame, "best_effort_timestamp"); + * - encoding: unused + * - decoding: set by libavcodec, read by user. + */ + int64_t best_effort_timestamp; + + /** + * reordered pos from the last AVPacket that has been input into the decoder + * Code outside libavcodec should access this field using: + * av_opt_ptr(avcodec_get_frame_class(), frame, "pkt_pos"); + * - encoding: unused + * - decoding: Read by user. + */ + int64_t pkt_pos; + +} AVFrame; + +struct AVCodecInternal; + +enum AVFieldOrder { + AV_FIELD_UNKNOWN, + AV_FIELD_PROGRESSIVE, + AV_FIELD_TT, //< Top coded_first, top displayed first + AV_FIELD_BB, //< Bottom coded first, bottom displayed first + AV_FIELD_TB, //< Top coded first, bottom displayed first + AV_FIELD_BT, //< Bottom coded first, top displayed first +}; + +/** + * main external API structure. + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * Please use AVOptions (av_opt* / av_set/get*()) to access these fields from user + * applications. + * sizeof(AVCodecContext) must not be used outside libav*. + */ +typedef struct AVCodecContext { + /** + * information on struct for av_log + * - set by avcodec_alloc_context3 + */ + const AVClass *av_class; + /** + * the average bitrate + * - encoding: Set by user; unused for constant quantizer encoding. + * - decoding: Set by libavcodec. 0 or some bitrate if this info is available in the stream. + */ + int bit_rate; + + /** + * number of bits the bitstream is allowed to diverge from the reference. + * the reference can be CBR (for CBR pass1) or VBR (for pass2) + * - encoding: Set by user; unused for constant quantizer encoding. + * - decoding: unused + */ + int bit_rate_tolerance; + + /** + * CODEC_FLAG_*. + * - encoding: Set by user. + * - decoding: Set by user. + */ + int flags; + + /** + * Some codecs need additional format info. It is stored here. + * If any muxer uses this then ALL demuxers/parsers AND encoders for the + * specific codec MUST set it correctly otherwise stream copy breaks. + * In general use of this field by muxers is not recommended. + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. (FIXME: Is this OK?) + */ + int sub_id; + + /** + * Motion estimation algorithm used for video coding. + * 1 (zero), 2 (full), 3 (log), 4 (phods), 5 (epzs), 6 (x1), 7 (hex), + * 8 (umh), 9 (iter), 10 (tesa) [7, 8, 10 are x264 specific, 9 is snow specific] + * - encoding: MUST be set by user. + * - decoding: unused + */ + int me_method; + + /** + * some codecs need / can use extradata like Huffman tables. + * mjpeg: Huffman tables + * rv10: additional flags + * mpeg4: global headers (they can be in the bitstream or here) + * The allocated memory should be FF_INPUT_BUFFER_PADDING_SIZE bytes larger + * than extradata_size to avoid prolems if it is read with the bitstream reader. + * The bytewise contents of extradata must not depend on the architecture or CPU endianness. + * - encoding: Set/allocated/freed by libavcodec. + * - decoding: Set/allocated/freed by user. + */ + uint8_t *extradata; + int extradata_size; + + /** + * This is the fundamental unit of time (in seconds) in terms + * of which frame timestamps are represented. For fixed-fps content, + * timebase should be 1/framerate and timestamp increments should be + * identically 1. + * - encoding: MUST be set by user. + * - decoding: Set by libavcodec. + */ + AVRational time_base; + + /* video only */ + /** + * picture width / height. + * - encoding: MUST be set by user. + * - decoding: Set by libavcodec. + * Note: For compatibility it is possible to set this instead of + * coded_width/height before decoding. + */ + int width, height; + +#define FF_ASPECT_EXTENDED 15 + + /** + * the number of pictures in a group of pictures, or 0 for intra_only + * - encoding: Set by user. + * - decoding: unused + */ + int gop_size; + + /** + * Pixel format, see PIX_FMT_xxx. + * May be set by the demuxer if known from headers. + * May be overriden by the decoder if it knows better. + * - encoding: Set by user. + * - decoding: Set by user if known, overridden by libavcodec if known + */ + enum PixelFormat pix_fmt; + + /** + * If non NULL, 'draw_horiz_band' is called by the libavcodec + * decoder to draw a horizontal band. It improves cache usage. Not + * all codecs can do that. You must check the codec capabilities + * beforehand. + * When multithreading is used, it may be called from multiple threads + * at the same time; threads might draw different parts of the same AVFrame, + * or multiple AVFrames, and there is no guarantee that slices will be drawn + * in order. + * The function is also used by hardware acceleration APIs. + * It is called at least once during frame decoding to pass + * the data needed for hardware render. + * In that mode instead of pixel data, AVFrame points to + * a structure specific to the acceleration API. The application + * reads the structure and can change some fields to indicate progress + * or mark state. + * - encoding: unused + * - decoding: Set by user. + * @param height the height of the slice + * @param y the y position of the slice + * @param type 1->top field, 2->bottom field, 3->frame + * @param offset offset into the AVFrame.data from which the slice should be read + */ + void (*draw_horiz_band)(struct AVCodecContext *s, + const AVFrame *src, int offset[AV_NUM_DATA_POINTERS], + int y, int type, int height); + + /* audio only */ + int sample_rate; ///< samples per second + int channels; ///< number of audio channels + + /** + * audio sample format + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + enum AVSampleFormat sample_fmt; ///< sample format + + /* The following data should not be initialized. */ + /** + * Samples per packet, initialized when calling 'init'. + */ + int frame_size; + int frame_number; ///< audio or video frame number + + /** + * Encoding: Number of frames delay there will be from the encoder input to + * the decoder output. (we assume the decoder matches the spec) + * Decoding: Number of frames delay in addition to what a standard decoder + * as specified in the spec would produce. + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + int delay; + + /* - encoding parameters */ + float qcompress; ///< amount of qscale change between easy & hard scenes (0.0-1.0) + float qblur; ///< amount of qscale smoothing over time (0.0-1.0) + + /** + * minimum quantizer + * - encoding: Set by user. + * - decoding: unused + */ + int qmin; + + /** + * maximum quantizer + * - encoding: Set by user. + * - decoding: unused + */ + int qmax; + + /** + * maximum quantizer difference between frames + * - encoding: Set by user. + * - decoding: unused + */ + int max_qdiff; + + /** + * maximum number of B-frames between non-B-frames + * Note: The output will be delayed by max_b_frames+1 relative to the input. + * - encoding: Set by user. + * - decoding: unused + */ + int max_b_frames; + + /** + * qscale factor between IP and B-frames + * If > 0 then the last P-frame quantizer will be used (q= lastp_q*factor+offset). + * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset). + * - encoding: Set by user. + * - decoding: unused + */ + float b_quant_factor; + + /** obsolete FIXME remove */ + int rc_strategy; +#define FF_RC_STRATEGY_XVID 1 + + int b_frame_strategy; + + struct AVCodec *codec; + + void *priv_data; + + int rtp_payload_size; /* The size of the RTP payload: the coder will */ + /* do its best to deliver a chunk with size */ + /* below rtp_payload_size, the chunk will start */ + /* with a start code on some codecs like H.263. */ + /* This doesn't take account of any particular */ + /* headers inside the transmitted RTP payload. */ + + + /* The RTP callback: This function is called */ + /* every time the encoder has a packet to send. */ + /* It depends on the encoder if the data starts */ + /* with a Start Code (it should). H.263 does. */ + /* mb_nb contains the number of macroblocks */ + /* encoded in the RTP payload. */ + void (*rtp_callback)(struct AVCodecContext *avctx, void *data, int size, int mb_nb); + + /* statistics, used for 2-pass encoding */ + int mv_bits; + int header_bits; + int i_tex_bits; + int p_tex_bits; + int i_count; + int p_count; + int skip_count; + int misc_bits; + + /** + * number of bits used for the previously encoded frame + * - encoding: Set by libavcodec. + * - decoding: unused + */ + int frame_bits; + + /** + * Private data of the user, can be used to carry app specific stuff. + * - encoding: Set by user. + * - decoding: Set by user. + */ + void *opaque; + + char codec_name[32]; + enum AVMediaType codec_type; /* see AVMEDIA_TYPE_xxx */ + enum CodecID codec_id; /* see CODEC_ID_xxx */ + + /** + * fourcc (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A'). + * This is used to work around some encoder bugs. + * A demuxer should set this to what is stored in the field used to identify the codec. + * If there are multiple such fields in a container then the demuxer should choose the one + * which maximizes the information about the used codec. + * If the codec tag field in a container is larger than 32 bits then the demuxer should + * remap the longer ID to 32 bits with a table or other structure. Alternatively a new + * extra_codec_tag + size could be added but for this a clear advantage must be demonstrated + * first. + * - encoding: Set by user, if not then the default based on codec_id will be used. + * - decoding: Set by user, will be converted to uppercase by libavcodec during init. + */ + unsigned int codec_tag; + + /** + * Work around bugs in encoders which sometimes cannot be detected automatically. + * - encoding: Set by user + * - decoding: Set by user + */ + int workaround_bugs; +#define FF_BUG_AUTODETECT 1 ///< autodetection +#define FF_BUG_OLD_MSMPEG4 2 +#define FF_BUG_XVID_ILACE 4 +#define FF_BUG_UMP4 8 +#define FF_BUG_NO_PADDING 16 +#define FF_BUG_AMV 32 +#define FF_BUG_AC_VLC 0 ///< Will be removed, libavcodec can now handle these non-compliant files by default. +#define FF_BUG_QPEL_CHROMA 64 +#define FF_BUG_STD_QPEL 128 +#define FF_BUG_QPEL_CHROMA2 256 +#define FF_BUG_DIRECT_BLOCKSIZE 512 +#define FF_BUG_EDGE 1024 +#define FF_BUG_HPEL_CHROMA 2048 +#define FF_BUG_DC_CLIP 4096 +#define FF_BUG_MS 8192 ///< Work around various bugs in Microsoft's broken decoders. +#define FF_BUG_TRUNCATED 16384 +//#define FF_BUG_FAKE_SCALABILITY 16 //Autodetection should work 100%. + + /** + * luma single coefficient elimination threshold + * - encoding: Set by user. + * - decoding: unused + */ + int luma_elim_threshold; + + /** + * chroma single coeff elimination threshold + * - encoding: Set by user. + * - decoding: unused + */ + int chroma_elim_threshold; + + /** + * strictly follow the standard (MPEG4, ...). + * - encoding: Set by user. + * - decoding: Set by user. + * Setting this to STRICT or higher means the encoder and decoder will + * generally do stupid things, whereas setting it to unofficial or lower + * will mean the encoder might produce output that is not supported by all + * spec-compliant decoders. Decoders don't differentiate between normal, + * unofficial and experimental (that is, they always try to decode things + * when they can) unless they are explicitly asked to behave stupidly + * (=strictly conform to the specs) + */ + int strict_std_compliance; +#define FF_COMPLIANCE_VERY_STRICT 2 ///< Strictly conform to an older more strict version of the spec or reference software. +#define FF_COMPLIANCE_STRICT 1 ///< Strictly conform to all the things in the spec no matter what consequences. +#define FF_COMPLIANCE_NORMAL 0 +#define FF_COMPLIANCE_UNOFFICIAL -1 ///< Allow unofficial extensions +#define FF_COMPLIANCE_EXPERIMENTAL -2 ///< Allow nonstandardized experimental things. + + /** + * qscale offset between IP and B-frames + * - encoding: Set by user. + * - decoding: unused + */ + float b_quant_offset; + +#if FF_API_ER + /** + * Error recognition; higher values will detect more errors but may + * misdetect some more or less valid parts as errors. + * - encoding: unused + * - decoding: Set by user. + */ + attribute_deprecated int error_recognition; +#define FF_ER_CAREFUL 1 +#define FF_ER_COMPLIANT 2 +#define FF_ER_AGGRESSIVE 3 +#define FF_ER_VERY_AGGRESSIVE 4 +#define FF_ER_EXPLODE 5 +#endif /* FF_API_ER */ + + /** + * Called at the beginning of each frame to get a buffer for it. + * + * The function will set AVFrame.data[], AVFrame.linesize[]. + * AVFrame.extended_data[] must also be set, but it should be the same as + * AVFrame.data[] except for planar audio with more channels than can fit + * in AVFrame.data[]. In that case, AVFrame.data[] shall still contain as + * many data pointers as it can hold. + * + * if CODEC_CAP_DR1 is not set then get_buffer() must call + * avcodec_default_get_buffer() instead of providing buffers allocated by + * some other means. + * + * AVFrame.data[] should be 32- or 16-byte-aligned unless the CPU doesn't + * need it. avcodec_default_get_buffer() aligns the output buffer properly, + * but if get_buffer() is overridden then alignment considerations should + * be taken into account. + * + * @see avcodec_default_get_buffer() + * + * Video: + * + * If pic.reference is set then the frame will be read later by libavcodec. + * avcodec_align_dimensions2() should be used to find the required width and + * height, as they normally need to be rounded up to the next multiple of 16. + * + * If frame multithreading is used and thread_safe_callbacks is set, + * it may be called from a different thread, but not from more than one at + * once. Does not need to be reentrant. + * + * @see release_buffer(), reget_buffer() + * @see avcodec_align_dimensions2() + * + * Audio: + * + * Decoders request a buffer of a particular size by setting + * AVFrame.nb_samples prior to calling get_buffer(). The decoder may, + * however, utilize only part of the buffer by setting AVFrame.nb_samples + * to a smaller value in the output frame. + * + * Decoders cannot use the buffer after returning from + * avcodec_decode_audio4(), so they will not call release_buffer(), as it + * is assumed to be released immediately upon return. + * + * As a convenience, av_samples_get_buffer_size() and + * av_samples_fill_arrays() in libavutil may be used by custom get_buffer() + * functions to find the required data size and to fill data pointers and + * linesize. In AVFrame.linesize, only linesize[0] may be set for audio + * since all planes must be the same size. + * + * @see av_samples_get_buffer_size(), av_samples_fill_arrays() + * + * - encoding: unused + * - decoding: Set by libavcodec, user can override. + */ + int (*get_buffer)(struct AVCodecContext *c, AVFrame *pic); + + /** + * Called to release buffers which were allocated with get_buffer. + * A released buffer can be reused in get_buffer(). + * pic.data[*] must be set to NULL. + * May be called from a different thread if frame multithreading is used, + * but not by more than one thread at once, so does not need to be reentrant. + * - encoding: unused + * - decoding: Set by libavcodec, user can override. + */ + void (*release_buffer)(struct AVCodecContext *c, AVFrame *pic); + + /** + * Size of the frame reordering buffer in the decoder. + * For MPEG-2 it is 1 IPB or 0 low delay IP. + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + int has_b_frames; + + /** + * number of bytes per packet if constant and known or 0 + * Used by some WAV based audio codecs. + */ + int block_align; + +#if FF_API_PARSE_FRAME + /** + * If true, only parsing is done. The frame data is returned. + * Only MPEG audio decoders support this now. + * - encoding: unused + * - decoding: Set by user + */ + attribute_deprecated int parse_only; +#endif + + /** + * 0-> h263 quant 1-> mpeg quant + * - encoding: Set by user. + * - decoding: unused + */ + int mpeg_quant; + + /** + * pass1 encoding statistics output buffer + * - encoding: Set by libavcodec. + * - decoding: unused + */ + char *stats_out; + + /** + * pass2 encoding statistics input buffer + * Concatenated stuff from stats_out of pass1 should be placed here. + * - encoding: Allocated/set/freed by user. + * - decoding: unused + */ + char *stats_in; + + /** + * ratecontrol qmin qmax limiting method + * 0-> clipping, 1-> use a nice continous function to limit qscale wthin qmin/qmax. + * - encoding: Set by user. + * - decoding: unused + */ + float rc_qsquish; + + float rc_qmod_amp; + int rc_qmod_freq; + + /** + * ratecontrol override, see RcOverride + * - encoding: Allocated/set/freed by user. + * - decoding: unused + */ + RcOverride *rc_override; + int rc_override_count; + + /** + * rate control equation + * - encoding: Set by user + * - decoding: unused + */ + const char *rc_eq; + + /** + * maximum bitrate + * - encoding: Set by user. + * - decoding: unused + */ + int rc_max_rate; + + /** + * minimum bitrate + * - encoding: Set by user. + * - decoding: unused + */ + int rc_min_rate; + + /** + * decoder bitstream buffer size + * - encoding: Set by user. + * - decoding: unused + */ + int rc_buffer_size; + float rc_buffer_aggressivity; + + /** + * qscale factor between P and I-frames + * If > 0 then the last p frame quantizer will be used (q= lastp_q*factor+offset). + * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset). + * - encoding: Set by user. + * - decoding: unused + */ + float i_quant_factor; + + /** + * qscale offset between P and I-frames + * - encoding: Set by user. + * - decoding: unused + */ + float i_quant_offset; + + /** + * initial complexity for pass1 ratecontrol + * - encoding: Set by user. + * - decoding: unused + */ + float rc_initial_cplx; + + /** + * DCT algorithm, see FF_DCT_* below + * - encoding: Set by user. + * - decoding: unused + */ + int dct_algo; +#define FF_DCT_AUTO 0 +#define FF_DCT_FASTINT 1 +#define FF_DCT_INT 2 +#define FF_DCT_MMX 3 +#define FF_DCT_MLIB 4 +#define FF_DCT_ALTIVEC 5 +#define FF_DCT_FAAN 6 + + /** + * luminance masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float lumi_masking; + + /** + * temporary complexity masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float temporal_cplx_masking; + + /** + * spatial complexity masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float spatial_cplx_masking; + + /** + * p block masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float p_masking; + + /** + * darkness masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float dark_masking; + + /** + * IDCT algorithm, see FF_IDCT_* below. + * - encoding: Set by user. + * - decoding: Set by user. + */ + int idct_algo; +#define FF_IDCT_AUTO 0 +#define FF_IDCT_INT 1 +#define FF_IDCT_SIMPLE 2 +#define FF_IDCT_SIMPLEMMX 3 +#define FF_IDCT_LIBMPEG2MMX 4 +#define FF_IDCT_PS2 5 +#define FF_IDCT_MLIB 6 +#define FF_IDCT_ARM 7 +#define FF_IDCT_ALTIVEC 8 +#define FF_IDCT_SH4 9 +#define FF_IDCT_SIMPLEARM 10 +#define FF_IDCT_H264 11 +#define FF_IDCT_VP3 12 +#define FF_IDCT_IPP 13 +#define FF_IDCT_XVIDMMX 14 +#define FF_IDCT_CAVS 15 +#define FF_IDCT_SIMPLEARMV5TE 16 +#define FF_IDCT_SIMPLEARMV6 17 +#define FF_IDCT_SIMPLEVIS 18 +#define FF_IDCT_WMV2 19 +#define FF_IDCT_FAAN 20 +#define FF_IDCT_EA 21 +#define FF_IDCT_SIMPLENEON 22 +#define FF_IDCT_SIMPLEALPHA 23 +#define FF_IDCT_BINK 24 + + /** + * slice count + * - encoding: Set by libavcodec. + * - decoding: Set by user (or 0). + */ + int slice_count; + /** + * slice offsets in the frame in bytes + * - encoding: Set/allocated by libavcodec. + * - decoding: Set/allocated by user (or NULL). + */ + int *slice_offset; + + /** + * error concealment flags + * - encoding: unused + * - decoding: Set by user. + */ + int error_concealment; +#define FF_EC_GUESS_MVS 1 +#define FF_EC_DEBLOCK 2 + + /** + * dsp_mask could be add used to disable unwanted CPU features + * CPU features (i.e. MMX, SSE. ...) + * + * With the FORCE flag you may instead enable given CPU features. + * (Dangerous: Usable in case of misdetection, improper usage however will + * result into program crash.) + */ + unsigned dsp_mask; + + /** + * bits per sample/pixel from the demuxer (needed for huffyuv). + * - encoding: Set by libavcodec. + * - decoding: Set by user. + */ + int bits_per_coded_sample; + + /** + * prediction method (needed for huffyuv) + * - encoding: Set by user. + * - decoding: unused + */ + int prediction_method; +#define FF_PRED_LEFT 0 +#define FF_PRED_PLANE 1 +#define FF_PRED_MEDIAN 2 + + /** + * sample aspect ratio (0 if unknown) + * That is the width of a pixel divided by the height of the pixel. + * Numerator and denominator must be relatively prime and smaller than 256 for some video standards. + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + AVRational sample_aspect_ratio; + + /** + * the picture in the bitstream + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + AVFrame *coded_frame; + + /** + * debug + * - encoding: Set by user. + * - decoding: Set by user. + */ + int debug; +#define FF_DEBUG_PICT_INFO 1 +#define FF_DEBUG_RC 2 +#define FF_DEBUG_BITSTREAM 4 +#define FF_DEBUG_MB_TYPE 8 +#define FF_DEBUG_QP 16 +#define FF_DEBUG_MV 32 +#define FF_DEBUG_DCT_COEFF 0x00000040 +#define FF_DEBUG_SKIP 0x00000080 +#define FF_DEBUG_STARTCODE 0x00000100 +#define FF_DEBUG_PTS 0x00000200 +#define FF_DEBUG_ER 0x00000400 +#define FF_DEBUG_MMCO 0x00000800 +#define FF_DEBUG_BUGS 0x00001000 +#define FF_DEBUG_VIS_QP 0x00002000 +#define FF_DEBUG_VIS_MB_TYPE 0x00004000 +#define FF_DEBUG_BUFFERS 0x00008000 +#define FF_DEBUG_THREADS 0x00010000 + + /** + * debug + * - encoding: Set by user. + * - decoding: Set by user. + */ + int debug_mv; +#define FF_DEBUG_VIS_MV_P_FOR 0x00000001 //visualize forward predicted MVs of P frames +#define FF_DEBUG_VIS_MV_B_FOR 0x00000002 //visualize forward predicted MVs of B frames +#define FF_DEBUG_VIS_MV_B_BACK 0x00000004 //visualize backward predicted MVs of B frames + + /** + * error + * - encoding: Set by libavcodec if flags&CODEC_FLAG_PSNR. + * - decoding: unused + */ + uint64_t error[AV_NUM_DATA_POINTERS]; + + /** + * motion estimation comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int me_cmp; + /** + * subpixel motion estimation comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int me_sub_cmp; + /** + * macroblock comparison function (not supported yet) + * - encoding: Set by user. + * - decoding: unused + */ + int mb_cmp; + /** + * interlaced DCT comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int ildct_cmp; +#define FF_CMP_SAD 0 +#define FF_CMP_SSE 1 +#define FF_CMP_SATD 2 +#define FF_CMP_DCT 3 +#define FF_CMP_PSNR 4 +#define FF_CMP_BIT 5 +#define FF_CMP_RD 6 +#define FF_CMP_ZERO 7 +#define FF_CMP_VSAD 8 +#define FF_CMP_VSSE 9 +#define FF_CMP_NSSE 10 +#define FF_CMP_W53 11 +#define FF_CMP_W97 12 +#define FF_CMP_DCTMAX 13 +#define FF_CMP_DCT264 14 +#define FF_CMP_CHROMA 256 + + /** + * ME diamond size & shape + * - encoding: Set by user. + * - decoding: unused + */ + int dia_size; + + /** + * amount of previous MV predictors (2a+1 x 2a+1 square) + * - encoding: Set by user. + * - decoding: unused + */ + int last_predictor_count; + + /** + * prepass for motion estimation + * - encoding: Set by user. + * - decoding: unused + */ + int pre_me; + + /** + * motion estimation prepass comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int me_pre_cmp; + + /** + * ME prepass diamond size & shape + * - encoding: Set by user. + * - decoding: unused + */ + int pre_dia_size; + + /** + * subpel ME quality + * - encoding: Set by user. + * - decoding: unused + */ + int me_subpel_quality; + + /** + * callback to negotiate the pixelFormat + * @param fmt is the list of formats which are supported by the codec, + * it is terminated by -1 as 0 is a valid format, the formats are ordered by quality. + * The first is always the native one. + * @return the chosen format + * - encoding: unused + * - decoding: Set by user, if not set the native format will be chosen. + */ + enum PixelFormat (*get_format)(struct AVCodecContext *s, const enum PixelFormat * fmt); + + /** + * DTG active format information (additional aspect ratio + * information only used in DVB MPEG-2 transport streams) + * 0 if not set. + * + * - encoding: unused + * - decoding: Set by decoder. + */ + int dtg_active_format; +#define FF_DTG_AFD_SAME 8 +#define FF_DTG_AFD_4_3 9 +#define FF_DTG_AFD_16_9 10 +#define FF_DTG_AFD_14_9 11 +#define FF_DTG_AFD_4_3_SP_14_9 13 +#define FF_DTG_AFD_16_9_SP_14_9 14 +#define FF_DTG_AFD_SP_4_3 15 + + /** + * maximum motion estimation search range in subpel units + * If 0 then no limit. + * + * - encoding: Set by user. + * - decoding: unused + */ + int me_range; + + /** + * intra quantizer bias + * - encoding: Set by user. + * - decoding: unused + */ + int intra_quant_bias; +#define FF_DEFAULT_QUANT_BIAS 999999 + + /** + * inter quantizer bias + * - encoding: Set by user. + * - decoding: unused + */ + int inter_quant_bias; + + /** + * color table ID + * - encoding: unused + * - decoding: Which clrtable should be used for 8bit RGB images. + * Tables have to be stored somewhere. FIXME + */ + int color_table_id; + +#if FF_API_INTERNAL_CONTEXT + /** + * internal_buffer count + * Don't touch, used by libavcodec default_get_buffer(). + * @deprecated this field was moved to an internal context + */ + attribute_deprecated int internal_buffer_count; + + /** + * internal_buffers + * Don't touch, used by libavcodec default_get_buffer(). + * @deprecated this field was moved to an internal context + */ + attribute_deprecated void *internal_buffer; +#endif + + /** + * Global quality for codecs which cannot change it per frame. + * This should be proportional to MPEG-1/2/4 qscale. + * - encoding: Set by user. + * - decoding: unused + */ + int global_quality; + +#define FF_CODER_TYPE_VLC 0 +#define FF_CODER_TYPE_AC 1 +#define FF_CODER_TYPE_RAW 2 +#define FF_CODER_TYPE_RLE 3 +#define FF_CODER_TYPE_DEFLATE 4 + /** + * coder type + * - encoding: Set by user. + * - decoding: unused + */ + int coder_type; + + /** + * context model + * - encoding: Set by user. + * - decoding: unused + */ + int context_model; +#if 0 + /** + * + * - encoding: unused + * - decoding: Set by user. + */ + uint8_t * (*realloc)(struct AVCodecContext *s, uint8_t *buf, int buf_size); +#endif + + /** + * slice flags + * - encoding: unused + * - decoding: Set by user. + */ + int slice_flags; +#define SLICE_FLAG_CODED_ORDER 0x0001 ///< draw_horiz_band() is called in coded order instead of display +#define SLICE_FLAG_ALLOW_FIELD 0x0002 ///< allow draw_horiz_band() with field slices (MPEG2 field pics) +#define SLICE_FLAG_ALLOW_PLANE 0x0004 ///< allow draw_horiz_band() with 1 component at a time (SVQ1) + + /** + * XVideo Motion Acceleration + * - encoding: forbidden + * - decoding: set by decoder + */ + int xvmc_acceleration; + + /** + * macroblock decision mode + * - encoding: Set by user. + * - decoding: unused + */ + int mb_decision; +#define FF_MB_DECISION_SIMPLE 0 ///< uses mb_cmp +#define FF_MB_DECISION_BITS 1 ///< chooses the one which needs the fewest bits +#define FF_MB_DECISION_RD 2 ///< rate distortion + + /** + * custom intra quantization matrix + * - encoding: Set by user, can be NULL. + * - decoding: Set by libavcodec. + */ + uint16_t *intra_matrix; + + /** + * custom inter quantization matrix + * - encoding: Set by user, can be NULL. + * - decoding: Set by libavcodec. + */ + uint16_t *inter_matrix; + + /** + * fourcc from the AVI stream header (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A'). + * This is used to work around some encoder bugs. + * - encoding: unused + * - decoding: Set by user, will be converted to uppercase by libavcodec during init. + */ + unsigned int stream_codec_tag; + + /** + * scene change detection threshold + * 0 is default, larger means fewer detected scene changes. + * - encoding: Set by user. + * - decoding: unused + */ + int scenechange_threshold; + + /** + * minimum Lagrange multipler + * - encoding: Set by user. + * - decoding: unused + */ + int lmin; + + /** + * maximum Lagrange multipler + * - encoding: Set by user. + * - decoding: unused + */ + int lmax; + +#if FF_API_PALETTE_CONTROL + /** + * palette control structure + * - encoding: ??? (no palette-enabled encoder yet) + * - decoding: Set by user. + */ + struct AVPaletteControl *palctrl; +#endif + + /** + * noise reduction strength + * - encoding: Set by user. + * - decoding: unused + */ + int noise_reduction; + + /** + * Called at the beginning of a frame to get cr buffer for it. + * Buffer type (size, hints) must be the same. libavcodec won't check it. + * libavcodec will pass previous buffer in pic, function should return + * same buffer or new buffer with old frame "painted" into it. + * If pic.data[0] == NULL must behave like get_buffer(). + * if CODEC_CAP_DR1 is not set then reget_buffer() must call + * avcodec_default_reget_buffer() instead of providing buffers allocated by + * some other means. + * - encoding: unused + * - decoding: Set by libavcodec, user can override. + */ + int (*reget_buffer)(struct AVCodecContext *c, AVFrame *pic); + + /** + * Number of bits which should be loaded into the rc buffer before decoding starts. + * - encoding: Set by user. + * - decoding: unused + */ + int rc_initial_buffer_occupancy; + + /** + * + * - encoding: Set by user. + * - decoding: unused + */ + int inter_threshold; + + /** + * CODEC_FLAG2_* + * - encoding: Set by user. + * - decoding: Set by user. + */ + int flags2; + + /** + * Simulates errors in the bitstream to test error concealment. + * - encoding: Set by user. + * - decoding: unused + */ + int error_rate; + +#if FF_API_ANTIALIAS_ALGO + /** + * MP3 antialias algorithm, see FF_AA_* below. + * - encoding: unused + * - decoding: Set by user. + */ + attribute_deprecated int antialias_algo; +#define FF_AA_AUTO 0 +#define FF_AA_FASTINT 1 //not implemented yet +#define FF_AA_INT 2 +#define FF_AA_FLOAT 3 +#endif + + /** + * quantizer noise shaping + * - encoding: Set by user. + * - decoding: unused + */ + int quantizer_noise_shaping; + + /** + * thread count + * is used to decide how many independent tasks should be passed to execute() + * - encoding: Set by user. + * - decoding: Set by user. + */ + int thread_count; + + /** + * The codec may call this to execute several independent things. + * It will return only after finishing all tasks. + * The user may replace this with some multithreaded implementation, + * the default implementation will execute the parts serially. + * @param count the number of things to execute + * - encoding: Set by libavcodec, user can override. + * - decoding: Set by libavcodec, user can override. + */ + int (*execute)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg), void *arg2, int *ret, int count, int size); + + /** + * thread opaque + * Can be used by execute() to store some per AVCodecContext stuff. + * - encoding: set by execute() + * - decoding: set by execute() + */ + void *thread_opaque; + + /** + * Motion estimation threshold below which no motion estimation is + * performed, but instead the user specified motion vectors are used. + * + * - encoding: Set by user. + * - decoding: unused + */ + int me_threshold; + + /** + * Macroblock threshold below which the user specified macroblock types will be used. + * - encoding: Set by user. + * - decoding: unused + */ + int mb_threshold; + + /** + * precision of the intra DC coefficient - 8 + * - encoding: Set by user. + * - decoding: unused + */ + int intra_dc_precision; + + /** + * noise vs. sse weight for the nsse comparsion function + * - encoding: Set by user. + * - decoding: unused + */ + int nsse_weight; + + /** + * Number of macroblock rows at the top which are skipped. + * - encoding: unused + * - decoding: Set by user. + */ + int skip_top; + + /** + * Number of macroblock rows at the bottom which are skipped. + * - encoding: unused + * - decoding: Set by user. + */ + int skip_bottom; + + /** + * profile + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int profile; +#define FF_PROFILE_UNKNOWN -99 +#define FF_PROFILE_RESERVED -100 + +#define FF_PROFILE_AAC_MAIN 0 +#define FF_PROFILE_AAC_LOW 1 +#define FF_PROFILE_AAC_SSR 2 +#define FF_PROFILE_AAC_LTP 3 + +#define FF_PROFILE_DTS 20 +#define FF_PROFILE_DTS_ES 30 +#define FF_PROFILE_DTS_96_24 40 +#define FF_PROFILE_DTS_HD_HRA 50 +#define FF_PROFILE_DTS_HD_MA 60 + +#define FF_PROFILE_MPEG2_422 0 +#define FF_PROFILE_MPEG2_HIGH 1 +#define FF_PROFILE_MPEG2_SS 2 +#define FF_PROFILE_MPEG2_SNR_SCALABLE 3 +#define FF_PROFILE_MPEG2_MAIN 4 +#define FF_PROFILE_MPEG2_SIMPLE 5 + +#define FF_PROFILE_H264_CONSTRAINED (1<<9) // 8+1; constraint_set1_flag +#define FF_PROFILE_H264_INTRA (1<<11) // 8+3; constraint_set3_flag + +#define FF_PROFILE_H264_BASELINE 66 +#define FF_PROFILE_H264_CONSTRAINED_BASELINE (66|FF_PROFILE_H264_CONSTRAINED) +#define FF_PROFILE_H264_MAIN 77 +#define FF_PROFILE_H264_EXTENDED 88 +#define FF_PROFILE_H264_HIGH 100 +#define FF_PROFILE_H264_HIGH_10 110 +#define FF_PROFILE_H264_HIGH_10_INTRA (110|FF_PROFILE_H264_INTRA) +#define FF_PROFILE_H264_HIGH_422 122 +#define FF_PROFILE_H264_HIGH_422_INTRA (122|FF_PROFILE_H264_INTRA) +#define FF_PROFILE_H264_HIGH_444 144 +#define FF_PROFILE_H264_HIGH_444_PREDICTIVE 244 +#define FF_PROFILE_H264_HIGH_444_INTRA (244|FF_PROFILE_H264_INTRA) +#define FF_PROFILE_H264_CAVLC_444 44 + +#define FF_PROFILE_VC1_SIMPLE 0 +#define FF_PROFILE_VC1_MAIN 1 +#define FF_PROFILE_VC1_COMPLEX 2 +#define FF_PROFILE_VC1_ADVANCED 3 + +#define FF_PROFILE_MPEG4_SIMPLE 0 +#define FF_PROFILE_MPEG4_SIMPLE_SCALABLE 1 +#define FF_PROFILE_MPEG4_CORE 2 +#define FF_PROFILE_MPEG4_MAIN 3 +#define FF_PROFILE_MPEG4_N_BIT 4 +#define FF_PROFILE_MPEG4_SCALABLE_TEXTURE 5 +#define FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION 6 +#define FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE 7 +#define FF_PROFILE_MPEG4_HYBRID 8 +#define FF_PROFILE_MPEG4_ADVANCED_REAL_TIME 9 +#define FF_PROFILE_MPEG4_CORE_SCALABLE 10 +#define FF_PROFILE_MPEG4_ADVANCED_CODING 11 +#define FF_PROFILE_MPEG4_ADVANCED_CORE 12 +#define FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE 13 +#define FF_PROFILE_MPEG4_SIMPLE_STUDIO 14 +#define FF_PROFILE_MPEG4_ADVANCED_SIMPLE 15 + + /** + * level + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int level; +#define FF_LEVEL_UNKNOWN -99 + + /** + * low resolution decoding, 1-> 1/2 size, 2->1/4 size + * - encoding: unused + * - decoding: Set by user. + */ + int lowres; + + /** + * Bitstream width / height, may be different from width/height if lowres enabled. + * - encoding: unused + * - decoding: Set by user before init if known. Codec should override / dynamically change if needed. + */ + int coded_width, coded_height; + + /** + * frame skip threshold + * - encoding: Set by user. + * - decoding: unused + */ + int frame_skip_threshold; + + /** + * frame skip factor + * - encoding: Set by user. + * - decoding: unused + */ + int frame_skip_factor; + + /** + * frame skip exponent + * - encoding: Set by user. + * - decoding: unused + */ + int frame_skip_exp; + + /** + * frame skip comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int frame_skip_cmp; + + /** + * Border processing masking, raises the quantizer for mbs on the borders + * of the picture. + * - encoding: Set by user. + * - decoding: unused + */ + float border_masking; + + /** + * minimum MB lagrange multipler + * - encoding: Set by user. + * - decoding: unused + */ + int mb_lmin; + + /** + * maximum MB lagrange multipler + * - encoding: Set by user. + * - decoding: unused + */ + int mb_lmax; + + /** + * + * - encoding: Set by user. + * - decoding: unused + */ + int me_penalty_compensation; + + /** + * + * - encoding: unused + * - decoding: Set by user. + */ + enum AVDiscard skip_loop_filter; + + /** + * + * - encoding: unused + * - decoding: Set by user. + */ + enum AVDiscard skip_idct; + + /** + * + * - encoding: unused + * - decoding: Set by user. + */ + enum AVDiscard skip_frame; + + /** + * + * - encoding: Set by user. + * - decoding: unused + */ + int bidir_refine; + + /** + * + * - encoding: Set by user. + * - decoding: unused + */ + int brd_scale; + +#if FF_API_X264_GLOBAL_OPTS + /** + * constant rate factor - quality-based VBR - values ~correspond to qps + * - encoding: Set by user. + * - decoding: unused + * @deprecated use 'crf' libx264 private option + */ + attribute_deprecated float crf; + + /** + * constant quantization parameter rate control method + * - encoding: Set by user. + * - decoding: unused + * @deprecated use 'cqp' libx264 private option + */ + attribute_deprecated int cqp; +#endif + + /** + * minimum GOP size + * - encoding: Set by user. + * - decoding: unused + */ + int keyint_min; + + /** + * number of reference frames + * - encoding: Set by user. + * - decoding: Set by lavc. + */ + int refs; + + /** + * chroma qp offset from luma + * - encoding: Set by user. + * - decoding: unused + */ + int chromaoffset; + +#if FF_API_X264_GLOBAL_OPTS + /** + * Influence how often B-frames are used. + * - encoding: Set by user. + * - decoding: unused + */ + attribute_deprecated int bframebias; +#endif + + /** + * trellis RD quantization + * - encoding: Set by user. + * - decoding: unused + */ + int trellis; + +#if FF_API_X264_GLOBAL_OPTS + /** + * Reduce fluctuations in qp (before curve compression). + * - encoding: Set by user. + * - decoding: unused + */ + attribute_deprecated float complexityblur; + + /** + * in-loop deblocking filter alphac0 parameter + * alpha is in the range -6...6 + * - encoding: Set by user. + * - decoding: unused + */ + attribute_deprecated int deblockalpha; + + /** + * in-loop deblocking filter beta parameter + * beta is in the range -6...6 + * - encoding: Set by user. + * - decoding: unused + */ + attribute_deprecated int deblockbeta; + + /** + * macroblock subpartition sizes to consider - p8x8, p4x4, b8x8, i8x8, i4x4 + * - encoding: Set by user. + * - decoding: unused + */ + attribute_deprecated int partitions; +#define X264_PART_I4X4 0x001 /* Analyze i4x4 */ +#define X264_PART_I8X8 0x002 /* Analyze i8x8 (requires 8x8 transform) */ +#define X264_PART_P8X8 0x010 /* Analyze p16x8, p8x16 and p8x8 */ +#define X264_PART_P4X4 0x020 /* Analyze p8x4, p4x8, p4x4 */ +#define X264_PART_B8X8 0x100 /* Analyze b16x8, b8x16 and b8x8 */ + + /** + * direct MV prediction mode - 0 (none), 1 (spatial), 2 (temporal), 3 (auto) + * - encoding: Set by user. + * - decoding: unused + */ + attribute_deprecated int directpred; +#endif + + /** + * Audio cutoff bandwidth (0 means "automatic") + * - encoding: Set by user. + * - decoding: unused + */ + int cutoff; + + /** + * Multiplied by qscale for each frame and added to scene_change_score. + * - encoding: Set by user. + * - decoding: unused + */ + int scenechange_factor; + + /** + * + * Note: Value depends upon the compare function used for fullpel ME. + * - encoding: Set by user. + * - decoding: unused + */ + int mv0_threshold; + + /** + * Adjust sensitivity of b_frame_strategy 1. + * - encoding: Set by user. + * - decoding: unused + */ + int b_sensitivity; + + /** + * - encoding: Set by user. + * - decoding: unused + */ + int compression_level; +#define FF_COMPRESSION_DEFAULT -1 + + /** + * - encoding: Set by user. + * - decoding: unused + */ + int min_prediction_order; + + /** + * - encoding: Set by user. + * - decoding: unused + */ + int max_prediction_order; + +#if FF_API_FLAC_GLOBAL_OPTS + /** + * @name FLAC options + * @deprecated Use FLAC encoder private options instead. + * @{ + */ + + /** + * LPC coefficient precision - used by FLAC encoder + * - encoding: Set by user. + * - decoding: unused + */ + attribute_deprecated int lpc_coeff_precision; + + /** + * search method for selecting prediction order + * - encoding: Set by user. + * - decoding: unused + */ + attribute_deprecated int prediction_order_method; + + /** + * - encoding: Set by user. + * - decoding: unused + */ + attribute_deprecated int min_partition_order; + + /** + * - encoding: Set by user. + * - decoding: unused + */ + attribute_deprecated int max_partition_order; + /** + * @} + */ +#endif + + /** + * GOP timecode frame start number + * - encoding: Set by user, in non drop frame format + * - decoding: Set by libavcodec (timecode in the 25 bits format, -1 if unset) + */ + int64_t timecode_frame_start; + +#if FF_API_REQUEST_CHANNELS + /** + * Decoder should decode to this many channels if it can (0 for default) + * - encoding: unused + * - decoding: Set by user. + * @deprecated Deprecated in favor of request_channel_layout. + */ + int request_channels; +#endif + +#if FF_API_DRC_SCALE + /** + * Percentage of dynamic range compression to be applied by the decoder. + * The default value is 1.0, corresponding to full compression. + * - encoding: unused + * - decoding: Set by user. + * @deprecated use AC3 decoder private option instead. + */ + attribute_deprecated float drc_scale; +#endif + + /** + * opaque 64bit number (generally a PTS) that will be reordered and + * output in AVFrame.reordered_opaque + * @deprecated in favor of pkt_pts + * - encoding: unused + * - decoding: Set by user. + */ + int64_t reordered_opaque; + + /** + * Bits per sample/pixel of internal libavcodec pixel/sample format. + * - encoding: set by user. + * - decoding: set by libavcodec. + */ + int bits_per_raw_sample; + + /** + * Audio channel layout. + * - encoding: set by user. + * - decoding: set by user, may be overwritten by libavcodec. + */ + uint64_t channel_layout; + + /** + * Request decoder to use this channel layout if it can (0 for default) + * - encoding: unused + * - decoding: Set by user. + */ + uint64_t request_channel_layout; + + /** + * Ratecontrol attempt to use, at maximum, of what can be used without an underflow. + * - encoding: Set by user. + * - decoding: unused. + */ + float rc_max_available_vbv_use; + + /** + * Ratecontrol attempt to use, at least, times the amount needed to prevent a vbv overflow. + * - encoding: Set by user. + * - decoding: unused. + */ + float rc_min_vbv_overflow_use; + + /** + * Hardware accelerator in use + * - encoding: unused. + * - decoding: Set by libavcodec + */ + struct AVHWAccel *hwaccel; + + /** + * For some codecs, the time base is closer to the field rate than the frame rate. + * Most notably, H.264 and MPEG-2 specify time_base as half of frame duration + * if no telecine is used ... + * + * Set to time_base ticks per frame. Default 1, e.g., H.264/MPEG-2 set it to 2. + */ + int ticks_per_frame; + + /** + * Hardware accelerator context. + * For some hardware accelerators, a global context needs to be + * provided by the user. In that case, this holds display-dependent + * data FFmpeg cannot instantiate itself. Please refer to the + * FFmpeg HW accelerator documentation to know how to fill this + * is. e.g. for VA API, this is a struct vaapi_context. + * - encoding: unused + * - decoding: Set by user + */ + void *hwaccel_context; + + /** + * Chromaticity coordinates of the source primaries. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorPrimaries color_primaries; + + /** + * Color Transfer Characteristic. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorTransferCharacteristic color_trc; + + /** + * YUV colorspace type. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorSpace colorspace; + + /** + * MPEG vs JPEG YUV range. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorRange color_range; + + /** + * This defines the location of chroma samples. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVChromaLocation chroma_sample_location; + + /** + * The codec may call this to execute several independent things. + * It will return only after finishing all tasks. + * The user may replace this with some multithreaded implementation, + * the default implementation will execute the parts serially. + * Also see avcodec_thread_init and e.g. the --enable-pthread configure option. + * @param c context passed also to func + * @param count the number of things to execute + * @param arg2 argument passed unchanged to func + * @param ret return values of executed functions, must have space for "count" values. May be NULL. + * @param func function that will be called count times, with jobnr from 0 to count-1. + * threadnr will be in the range 0 to c->thread_count-1 < MAX_THREADS and so that no + * two instances of func executing at the same time will have the same threadnr. + * @return always 0 currently, but code should handle a future improvement where when any call to func + * returns < 0 no further calls to func may be done and < 0 is returned. + * - encoding: Set by libavcodec, user can override. + * - decoding: Set by libavcodec, user can override. + */ + int (*execute2)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg, int jobnr, int threadnr), void *arg2, int *ret, int count); + +#if FF_API_X264_GLOBAL_OPTS + /** + * explicit P-frame weighted prediction analysis method + * 0: off + * 1: fast blind weighting (one reference duplicate with -1 offset) + * 2: smart weighting (full fade detection analysis) + * - encoding: Set by user. + * - decoding: unused + */ + attribute_deprecated int weighted_p_pred; + + /** + * AQ mode + * 0: Disabled + * 1: Variance AQ (complexity mask) + * 2: Auto-variance AQ (experimental) + * - encoding: Set by user + * - decoding: unused + */ + attribute_deprecated int aq_mode; + + /** + * AQ strength + * Reduces blocking and blurring in flat and textured areas. + * - encoding: Set by user + * - decoding: unused + */ + attribute_deprecated float aq_strength; + + /** + * PSY RD + * Strength of psychovisual optimization + * - encoding: Set by user + * - decoding: unused + */ + attribute_deprecated float psy_rd; + + /** + * PSY trellis + * Strength of psychovisual optimization + * - encoding: Set by user + * - decoding: unused + */ + attribute_deprecated float psy_trellis; + + /** + * RC lookahead + * Number of frames for frametype and ratecontrol lookahead + * - encoding: Set by user + * - decoding: unused + */ + attribute_deprecated int rc_lookahead; + + /** + * Constant rate factor maximum + * With CRF encoding mode and VBV restrictions enabled, prevents quality from being worse + * than crf_max, even if doing so would violate VBV restrictions. + * - encoding: Set by user. + * - decoding: unused + */ + attribute_deprecated float crf_max; +#endif + + int log_level_offset; + +#if FF_API_FLAC_GLOBAL_OPTS + /** + * Determine which LPC analysis algorithm to use. + * - encoding: Set by user + * - decoding: unused + */ + attribute_deprecated enum AVLPCType lpc_type; + + /** + * Number of passes to use for Cholesky factorization during LPC analysis + * - encoding: Set by user + * - decoding: unused + */ + attribute_deprecated int lpc_passes; +#endif + + /** + * Number of slices. + * Indicates number of picture subdivisions. Used for parallelized + * decoding. + * - encoding: Set by user + * - decoding: unused + */ + int slices; + + /** + * Header containing style information for text subtitles. + * For SUBTITLE_ASS subtitle type, it should contain the whole ASS + * [Script Info] and [V4+ Styles] section, plus the [Events] line and + * the Format line following. It shouldn't include any Dialogue line. + * - encoding: Set/allocated/freed by user (before avcodec_open2()) + * - decoding: Set/allocated/freed by libavcodec (by avcodec_open2()) + */ + uint8_t *subtitle_header; + int subtitle_header_size; + + /** + * Current packet as passed into the decoder, to avoid having + * to pass the packet into every function. Currently only valid + * inside lavc and get/release_buffer callbacks. + * - decoding: set by avcodec_decode_*, read by get_buffer() for setting pkt_pts + * - encoding: unused + */ + AVPacket *pkt; + +#if FF_API_INTERNAL_CONTEXT + /** + * Whether this is a copy of the context which had init() called on it. + * This is used by multithreading - shared tables and picture pointers + * should be freed from the original context only. + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + * + * @deprecated this field has been moved to an internal context + */ + attribute_deprecated int is_copy; +#endif + + /** + * Which multithreading methods to use. + * Use of FF_THREAD_FRAME will increase decoding delay by one frame per thread, + * so clients which cannot provide future frames should not use it. + * + * - encoding: Set by user, otherwise the default is used. + * - decoding: Set by user, otherwise the default is used. + */ + int thread_type; +#define FF_THREAD_FRAME 1 ///< Decode more than one frame at once +#define FF_THREAD_SLICE 2 ///< Decode more than one part of a single frame at once + + /** + * Which multithreading methods are in use by the codec. + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + int active_thread_type; + + /** + * Set by the client if its custom get_buffer() callback can be called + * from another thread, which allows faster multithreaded decoding. + * draw_horiz_band() will be called from other threads regardless of this setting. + * Ignored if the default get_buffer() is used. + * - encoding: Set by user. + * - decoding: Set by user. + */ + int thread_safe_callbacks; + + /** + * VBV delay coded in the last frame (in periods of a 27 MHz clock). + * Used for compliant TS muxing. + * - encoding: Set by libavcodec. + * - decoding: unused. + */ + uint64_t vbv_delay; + + /** + * Type of service that the audio stream conveys. + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + enum AVAudioServiceType audio_service_type; + + /** + * desired sample format + * - encoding: Not used. + * - decoding: Set by user. + * Decoder will decode to this format if it can. + */ + enum AVSampleFormat request_sample_fmt; + + /** + * Error recognition; may misdetect some more or less valid parts as errors. + * - encoding: unused + * - decoding: Set by user. + */ + int err_recognition; +#define AV_EF_CRCCHECK (1<<0) +#define AV_EF_BITSTREAM (1<<1) +#define AV_EF_BUFFER (1<<2) +#define AV_EF_EXPLODE (1<<3) + +#define AV_EF_CAREFUL (1<<16) +#define AV_EF_COMPLIANT (1<<17) +#define AV_EF_AGGRESSIVE (1<<18) + + /** + * Private context used for internal data. + * + * Unlike priv_data, this is not codec-specific. It is used in general + * libavcodec functions. + */ + struct AVCodecInternal *internal; + + /** Field order + * - encoding: set by libavcodec + * - decoding: Set by libavcodec + */ + enum AVFieldOrder field_order; + + /** + * Current statistics for PTS correction. + * - decoding: maintained and used by libavcodec, not intended to be used by user apps + * - encoding: unused + */ + int64_t pts_correction_num_faulty_pts; /// Number of incorrect PTS values so far + int64_t pts_correction_num_faulty_dts; /// Number of incorrect DTS values so far + int64_t pts_correction_last_pts; /// PTS of the last frame + int64_t pts_correction_last_dts; /// DTS of the last frame + +} AVCodecContext; + +/** + * AVProfile. + */ +typedef struct AVProfile { + int profile; + const char *name; ///< short name for the profile +} AVProfile; + +typedef struct AVCodecDefault AVCodecDefault; + +/** + * AVCodec. + */ +typedef struct AVCodec { + /** + * Name of the codec implementation. + * The name is globally unique among encoders and among decoders (but an + * encoder and a decoder can share the same name). + * This is the primary way to find a codec from the user perspective. + */ + const char *name; + enum AVMediaType type; + enum CodecID id; + int priv_data_size; + int (*init)(AVCodecContext *); + int (*encode)(AVCodecContext *, uint8_t *buf, int buf_size, void *data); + int (*close)(AVCodecContext *); + int (*decode)(AVCodecContext *, void *outdata, int *outdata_size, AVPacket *avpkt); + /** + * Codec capabilities. + * see CODEC_CAP_* + */ + int capabilities; + struct AVCodec *next; + /** + * Flush buffers. + * Will be called when seeking + */ + void (*flush)(AVCodecContext *); + const AVRational *supported_framerates; ///< array of supported framerates, or NULL if any, array is terminated by {0,0} + const enum PixelFormat *pix_fmts; ///< array of supported pixel formats, or NULL if unknown, array is terminated by -1 + /** + * Descriptive name for the codec, meant to be more human readable than name. + * You should use the NULL_IF_CONFIG_SMALL() macro to define it. + */ + const char *long_name; + const int *supported_samplerates; ///< array of supported audio samplerates, or NULL if unknown, array is terminated by 0 + const enum AVSampleFormat *sample_fmts; ///< array of supported sample formats, or NULL if unknown, array is terminated by -1 + const uint64_t *channel_layouts; ///< array of support channel layouts, or NULL if unknown. array is terminated by 0 + uint8_t max_lowres; ///< maximum value for lowres supported by the decoder + const AVClass *priv_class; ///< AVClass for the private context + const AVProfile *profiles; ///< array of recognized profiles, or NULL if unknown, array is terminated by {FF_PROFILE_UNKNOWN} + + /** + * @name Frame-level threading support functions + * @{ + */ + /** + * If defined, called on thread contexts when they are created. + * If the codec allocates writable tables in init(), re-allocate them here. + * priv_data will be set to a copy of the original. + */ + int (*init_thread_copy)(AVCodecContext *); + /** + * Copy necessary context variables from a previous thread context to the current one. + * If not defined, the next thread will start automatically; otherwise, the codec + * must call ff_thread_finish_setup(). + * + * dst and src will (rarely) point to the same context, in which case memcpy should be skipped. + */ + int (*update_thread_context)(AVCodecContext *dst, const AVCodecContext *src); + /** @} */ + + /** + * Private codec-specific defaults. + */ + const AVCodecDefault *defaults; + + /** + * Initialize codec static data, called from avcodec_register(). + */ + void (*init_static_data)(struct AVCodec *codec); + + /** + * Encode data to an AVPacket. + * + * @param avctx codec context + * @param avpkt output AVPacket (may contain a user-provided buffer) + * @param[in] frame AVFrame containing the raw data to be encoded + * @param[out] got_packet_ptr encoder sets to 0 or 1 to indicate that a + * non-empty packet was returned in avpkt. + * @return 0 on success, negative error code on failure + */ + int (*encode2)(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, + int *got_packet_ptr); +} AVCodec; + +/** + * AVHWAccel. + */ +typedef struct AVHWAccel { + /** + * Name of the hardware accelerated codec. + * The name is globally unique among encoders and among decoders (but an + * encoder and a decoder can share the same name). + */ + const char *name; + + /** + * Type of codec implemented by the hardware accelerator. + * + * See AVMEDIA_TYPE_xxx + */ + enum AVMediaType type; + + /** + * Codec implemented by the hardware accelerator. + * + * See CODEC_ID_xxx + */ + enum CodecID id; + + /** + * Supported pixel format. + * + * Only hardware accelerated formats are supported here. + */ + enum PixelFormat pix_fmt; + + /** + * Hardware accelerated codec capabilities. + * see FF_HWACCEL_CODEC_CAP_* + */ + int capabilities; + + struct AVHWAccel *next; + + /** + * Called at the beginning of each frame or field picture. + * + * Meaningful frame information (codec specific) is guaranteed to + * be parsed at this point. This function is mandatory. + * + * Note that buf can be NULL along with buf_size set to 0. + * Otherwise, this means the whole frame is available at this point. + * + * @param avctx the codec context + * @param buf the frame data buffer base + * @param buf_size the size of the frame in bytes + * @return zero if successful, a negative value otherwise + */ + int (*start_frame)(AVCodecContext *avctx, const uint8_t *buf, uint32_t buf_size); + + /** + * Callback for each slice. + * + * Meaningful slice information (codec specific) is guaranteed to + * be parsed at this point. This function is mandatory. + * + * @param avctx the codec context + * @param buf the slice data buffer base + * @param buf_size the size of the slice in bytes + * @return zero if successful, a negative value otherwise + */ + int (*decode_slice)(AVCodecContext *avctx, const uint8_t *buf, uint32_t buf_size); + + /** + * Called at the end of each frame or field picture. + * + * The whole picture is parsed at this point and can now be sent + * to the hardware accelerator. This function is mandatory. + * + * @param avctx the codec context + * @return zero if successful, a negative value otherwise + */ + int (*end_frame)(AVCodecContext *avctx); + + /** + * Size of HW accelerator private data. + * + * Private data is allocated with av_mallocz() before + * AVCodecContext.get_buffer() and deallocated after + * AVCodecContext.release_buffer(). + */ + int priv_data_size; +} AVHWAccel; + +/** + * four components are given, that's all. + * the last component is alpha + */ +typedef struct AVPicture { + uint8_t *data[AV_NUM_DATA_POINTERS]; + int linesize[AV_NUM_DATA_POINTERS]; ///< number of bytes per line +} AVPicture; + +#define AVPALETTE_SIZE 1024 +#define AVPALETTE_COUNT 256 +#if FF_API_PALETTE_CONTROL +/** + * AVPaletteControl + * This structure defines a method for communicating palette changes + * between and demuxer and a decoder. + * + * @deprecated Use AVPacket to send palette changes instead. + * This is totally broken. + */ +typedef struct AVPaletteControl { + + /* Demuxer sets this to 1 to indicate the palette has changed; + * decoder resets to 0. */ + int palette_changed; + + /* 4-byte ARGB palette entries, stored in native byte order; note that + * the individual palette components should be on a 8-bit scale; if + * the palette data comes from an IBM VGA native format, the component + * data is probably 6 bits in size and needs to be scaled. */ + unsigned int palette[AVPALETTE_COUNT]; + +} AVPaletteControl attribute_deprecated; +#endif + +enum AVSubtitleType { + SUBTITLE_NONE, + + SUBTITLE_BITMAP, ///< A bitmap, pict will be set + + /** + * Plain text, the text field must be set by the decoder and is + * authoritative. ass and pict fields may contain approximations. + */ + SUBTITLE_TEXT, + + /** + * Formatted text, the ass field must be set by the decoder and is + * authoritative. pict and text fields may contain approximations. + */ + SUBTITLE_ASS, +}; + +typedef struct AVSubtitleRect { + int x; ///< top left corner of pict, undefined when pict is not set + int y; ///< top left corner of pict, undefined when pict is not set + int w; ///< width of pict, undefined when pict is not set + int h; ///< height of pict, undefined when pict is not set + int nb_colors; ///< number of colors in pict, undefined when pict is not set + + /** + * data+linesize for the bitmap of this subtitle. + * can be set for text/ass as well once they where rendered + */ + AVPicture pict; + enum AVSubtitleType type; + + char *text; ///< 0 terminated plain UTF-8 text + + /** + * 0 terminated ASS/SSA compatible event line. + * The pressentation of this is unaffected by the other values in this + * struct. + */ + char *ass; +} AVSubtitleRect; + +typedef struct AVSubtitle { + uint16_t format; /* 0 = graphics */ + uint32_t start_display_time; /* relative to packet pts, in ms */ + uint32_t end_display_time; /* relative to packet pts, in ms */ + unsigned num_rects; + AVSubtitleRect **rects; + int64_t pts; ///< Same as packet pts, in AV_TIME_BASE +} AVSubtitle; + +/* packet functions */ + +/** + * @deprecated use NULL instead + */ +attribute_deprecated void av_destruct_packet_nofree(AVPacket *pkt); + +/** + * Default packet destructor. + */ +void av_destruct_packet(AVPacket *pkt); + +/** + * Initialize optional fields of a packet with default values. + * + * @param pkt packet + */ +void av_init_packet(AVPacket *pkt); + +/** + * Allocate the payload of a packet and initialize its fields with + * default values. + * + * @param pkt packet + * @param size wanted payload size + * @return 0 if OK, AVERROR_xxx otherwise + */ +int av_new_packet(AVPacket *pkt, int size); + +/** + * Reduce packet size, correctly zeroing padding + * + * @param pkt packet + * @param size new size + */ +void av_shrink_packet(AVPacket *pkt, int size); + +/** + * Increase packet size, correctly zeroing padding + * + * @param pkt packet + * @param grow_by number of bytes by which to increase the size of the packet + */ +int av_grow_packet(AVPacket *pkt, int grow_by); + +/** + * @warning This is a hack - the packet memory allocation stuff is broken. The + * packet is allocated if it was not really allocated. + */ +int av_dup_packet(AVPacket *pkt); + +/** + * Free a packet. + * + * @param pkt packet to free + */ +void av_free_packet(AVPacket *pkt); + +/** + * Allocate new information of a packet. + * + * @param pkt packet + * @param type side information type + * @param size side information size + * @return pointer to fresh allocated data or NULL otherwise + */ +uint8_t* av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + int size); + +/** + * Get side information from packet. + * + * @param pkt packet + * @param type desired side information type + * @param size pointer for side information size to store (optional) + * @return pointer to data if present or NULL otherwise + */ +uint8_t* av_packet_get_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + int *size); + +int av_packet_merge_side_data(AVPacket *pkt); + +int av_packet_split_side_data(AVPacket *pkt); + + +/* resample.c */ + +struct ReSampleContext; +struct AVResampleContext; + +typedef struct ReSampleContext ReSampleContext; + +/** + * Initialize audio resampling context. + * + * @param output_channels number of output channels + * @param input_channels number of input channels + * @param output_rate output sample rate + * @param input_rate input sample rate + * @param sample_fmt_out requested output sample format + * @param sample_fmt_in input sample format + * @param filter_length length of each FIR filter in the filterbank relative to the cutoff frequency + * @param log2_phase_count log2 of the number of entries in the polyphase filterbank + * @param linear if 1 then the used FIR filter will be linearly interpolated + between the 2 closest, if 0 the closest will be used + * @param cutoff cutoff frequency, 1.0 corresponds to half the output sampling rate + * @return allocated ReSampleContext, NULL if error occurred + */ +ReSampleContext *av_audio_resample_init(int output_channels, int input_channels, + int output_rate, int input_rate, + enum AVSampleFormat sample_fmt_out, + enum AVSampleFormat sample_fmt_in, + int filter_length, int log2_phase_count, + int linear, double cutoff); + +int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples); + +/** + * Free resample context. + * + * @param s a non-NULL pointer to a resample context previously + * created with av_audio_resample_init() + */ +void audio_resample_close(ReSampleContext *s); + + +/** + * Initialize an audio resampler. + * Note, if either rate is not an integer then simply scale both rates up so they are. + * @param filter_length length of each FIR filter in the filterbank relative to the cutoff freq + * @param log2_phase_count log2 of the number of entries in the polyphase filterbank + * @param linear If 1 then the used FIR filter will be linearly interpolated + between the 2 closest, if 0 the closest will be used + * @param cutoff cutoff frequency, 1.0 corresponds to half the output sampling rate + */ +struct AVResampleContext *av_resample_init(int out_rate, int in_rate, int filter_length, int log2_phase_count, int linear, double cutoff); + +/** + * Resample an array of samples using a previously configured context. + * @param src an array of unconsumed samples + * @param consumed the number of samples of src which have been consumed are returned here + * @param src_size the number of unconsumed samples available + * @param dst_size the amount of space in samples available in dst + * @param update_ctx If this is 0 then the context will not be modified, that way several channels can be resampled with the same context. + * @return the number of samples written in dst or -1 if an error occurred + */ +int av_resample(struct AVResampleContext *c, short *dst, short *src, int *consumed, int src_size, int dst_size, int update_ctx); + + +/** + * Compensate samplerate/timestamp drift. The compensation is done by changing + * the resampler parameters, so no audible clicks or similar distortions occur + * @param compensation_distance distance in output samples over which the compensation should be performed + * @param sample_delta number of output samples which should be output less + * + * example: av_resample_compensate(c, 10, 500) + * here instead of 510 samples only 500 samples would be output + * + * note, due to rounding the actual compensation might be slightly different, + * especially if the compensation_distance is large and the in_rate used during init is small + */ +void av_resample_compensate(struct AVResampleContext *c, int sample_delta, int compensation_distance); +void av_resample_close(struct AVResampleContext *c); + +/** + * Allocate memory for a picture. Call avpicture_free() to free it. + * + * @see avpicture_fill() + * + * @param picture the picture to be filled in + * @param pix_fmt the format of the picture + * @param width the width of the picture + * @param height the height of the picture + * @return zero if successful, a negative value if not + */ +int avpicture_alloc(AVPicture *picture, enum PixelFormat pix_fmt, int width, int height); + +/** + * Free a picture previously allocated by avpicture_alloc(). + * The data buffer used by the AVPicture is freed, but the AVPicture structure + * itself is not. + * + * @param picture the AVPicture to be freed + */ +void avpicture_free(AVPicture *picture); + +/** + * Fill in the AVPicture fields. + * The fields of the given AVPicture are filled in by using the 'ptr' address + * which points to the image data buffer. Depending on the specified picture + * format, one or multiple image data pointers and line sizes will be set. + * If a planar format is specified, several pointers will be set pointing to + * the different picture planes and the line sizes of the different planes + * will be stored in the lines_sizes array. + * Call with ptr == NULL to get the required size for the ptr buffer. + * + * To allocate the buffer and fill in the AVPicture fields in one call, + * use avpicture_alloc(). + * + * @param picture AVPicture whose fields are to be filled in + * @param ptr Buffer which will contain or contains the actual image data + * @param pix_fmt The format in which the picture data is stored. + * @param width the width of the image in pixels + * @param height the height of the image in pixels + * @return size of the image data in bytes + */ +int avpicture_fill(AVPicture *picture, uint8_t *ptr, + enum PixelFormat pix_fmt, int width, int height); + +/** + * Copy pixel data from an AVPicture into a buffer. + * The data is stored compactly, without any gaps for alignment or padding + * which may be applied by avpicture_fill(). + * + * @see avpicture_get_size() + * + * @param[in] src AVPicture containing image data + * @param[in] pix_fmt The format in which the picture data is stored. + * @param[in] width the width of the image in pixels. + * @param[in] height the height of the image in pixels. + * @param[out] dest A buffer into which picture data will be copied. + * @param[in] dest_size The size of 'dest'. + * @return The number of bytes written to dest, or a negative value (error code) on error. + */ +int avpicture_layout(const AVPicture* src, enum PixelFormat pix_fmt, int width, int height, + unsigned char *dest, int dest_size); + +/** + * Calculate the size in bytes that a picture of the given width and height + * would occupy if stored in the given picture format. + * Note that this returns the size of a compact representation as generated + * by avpicture_layout(), which can be smaller than the size required for e.g. + * avpicture_fill(). + * + * @param pix_fmt the given picture format + * @param width the width of the image + * @param height the height of the image + * @return Image data size in bytes or -1 on error (e.g. too large dimensions). + */ +int avpicture_get_size(enum PixelFormat pix_fmt, int width, int height); +void avcodec_get_chroma_sub_sample(enum PixelFormat pix_fmt, int *h_shift, int *v_shift); + +/** + * Get the name of a codec. + * @return a static string identifying the codec; never NULL + */ +const char *avcodec_get_name(enum CodecID id); + +#if FF_API_GET_PIX_FMT_NAME +/** + * Return the short name for a pixel format. + * + * \see av_get_pix_fmt(), av_get_pix_fmt_string(). + * @deprecated Deprecated in favor of av_get_pix_fmt_name(). + */ +attribute_deprecated +const char *avcodec_get_pix_fmt_name(enum PixelFormat pix_fmt); +#endif + +void avcodec_set_dimensions(AVCodecContext *s, int width, int height); + +/** + * Return a value representing the fourCC code associated to the + * pixel format pix_fmt, or 0 if no associated fourCC code can be + * found. + */ +unsigned int avcodec_pix_fmt_to_codec_tag(enum PixelFormat pix_fmt); + +/** + * Put a string representing the codec tag codec_tag in buf. + * + * @param buf_size size in bytes of buf + * @return the length of the string that would have been generated if + * enough space had been available, excluding the trailing null + */ +size_t av_get_codec_tag_string(char *buf, size_t buf_size, unsigned int codec_tag); + +#define FF_LOSS_RESOLUTION 0x0001 /**< loss due to resolution change */ +#define FF_LOSS_DEPTH 0x0002 /**< loss due to color depth change */ +#define FF_LOSS_COLORSPACE 0x0004 /**< loss due to color space conversion */ +#define FF_LOSS_ALPHA 0x0008 /**< loss of alpha bits */ +#define FF_LOSS_COLORQUANT 0x0010 /**< loss due to color quantization */ +#define FF_LOSS_CHROMA 0x0020 /**< loss of chroma (e.g. RGB to gray conversion) */ + +/** + * Compute what kind of losses will occur when converting from one specific + * pixel format to another. + * When converting from one pixel format to another, information loss may occur. + * For example, when converting from RGB24 to GRAY, the color information will + * be lost. Similarly, other losses occur when converting from some formats to + * other formats. These losses can involve loss of chroma, but also loss of + * resolution, loss of color depth, loss due to the color space conversion, loss + * of the alpha bits or loss due to color quantization. + * avcodec_get_fix_fmt_loss() informs you about the various types of losses + * which will occur when converting from one pixel format to another. + * + * @param[in] dst_pix_fmt destination pixel format + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @return Combination of flags informing you what kind of losses will occur + * (maximum loss for an invalid dst_pix_fmt). + */ +int avcodec_get_pix_fmt_loss(enum PixelFormat dst_pix_fmt, enum PixelFormat src_pix_fmt, + int has_alpha); + +/** + * Find the best pixel format to convert to given a certain source pixel + * format. When converting from one pixel format to another, information loss + * may occur. For example, when converting from RGB24 to GRAY, the color + * information will be lost. Similarly, other losses occur when converting from + * some formats to other formats. avcodec_find_best_pix_fmt() searches which of + * the given pixel formats should be used to suffer the least amount of loss. + * The pixel formats from which it chooses one, are determined by the + * pix_fmt_mask parameter. + * + * Note, only the first 64 pixel formats will fit in pix_fmt_mask. + * + * @code + * src_pix_fmt = PIX_FMT_YUV420P; + * pix_fmt_mask = (1 << PIX_FMT_YUV422P) | (1 << PIX_FMT_RGB24); + * dst_pix_fmt = avcodec_find_best_pix_fmt(pix_fmt_mask, src_pix_fmt, alpha, &loss); + * @endcode + * + * @param[in] pix_fmt_mask bitmask determining which pixel format to choose from + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @param[out] loss_ptr Combination of flags informing you what kind of losses will occur. + * @return The best pixel format to convert to or -1 if none was found. + */ +enum PixelFormat avcodec_find_best_pix_fmt(int64_t pix_fmt_mask, enum PixelFormat src_pix_fmt, + int has_alpha, int *loss_ptr); + +/** + * Find the best pixel format to convert to given a certain source pixel + * format and a selection of two destination pixel formats. When converting from + * one pixel format to another, information loss may occur. For example, when converting + * from RGB24 to GRAY, the color information will be lost. Similarly, other losses occur when + * converting from some formats to other formats. avcodec_find_best_pix_fmt2() selects which of + * the given pixel formats should be used to suffer the least amount of loss. + * + * If one of the destination formats is PIX_FMT_NONE the other pixel format (if valid) will be + * returned. + * + * @code + * src_pix_fmt = PIX_FMT_YUV420P; + * dst_pix_fmt1= PIX_FMT_RGB24; + * dst_pix_fmt2= PIX_FMT_GRAY8; + * dst_pix_fmt3= PIX_FMT_RGB8; + * loss= FF_LOSS_CHROMA; // don't care about chroma loss, so chroma loss will be ignored. + * dst_pix_fmt = avcodec_find_best_pix_fmt2(dst_pix_fmt1, dst_pix_fmt2, src_pix_fmt, alpha, &loss); + * dst_pix_fmt = avcodec_find_best_pix_fmt2(dst_pix_fmt, dst_pix_fmt3, src_pix_fmt, alpha, &loss); + * @endcode + * + * @param[in] dst_pix_fmt1 One of the two destination pixel formats to choose from + * @param[in] dst_pix_fmt2 The other of the two destination pixel formats to choose from + * @param[in] src_pix_fmt Source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @param[in, out] loss_ptr Combination of loss flags. In: selects which of the losses to ignore, i.e. + * NULL or value of zero means we care about all losses. Out: the loss + * that occurs when converting from src to selected dst pixel format. + * @return The best pixel format to convert to or -1 if none was found. + */ +enum PixelFormat avcodec_find_best_pix_fmt2(enum PixelFormat dst_pix_fmt1, enum PixelFormat dst_pix_fmt2, + enum PixelFormat src_pix_fmt, int has_alpha, int *loss_ptr); + +#if FF_API_GET_ALPHA_INFO +#define FF_ALPHA_TRANSP 0x0001 /* image has some totally transparent pixels */ +#define FF_ALPHA_SEMI_TRANSP 0x0002 /* image has some transparent pixels */ + +/** + * Tell if an image really has transparent alpha values. + * @return ored mask of FF_ALPHA_xxx constants + */ +attribute_deprecated +int img_get_alpha_info(const AVPicture *src, + enum PixelFormat pix_fmt, int width, int height); +#endif + +/* deinterlace a picture */ +/* deinterlace - if not supported return -1 */ +int avpicture_deinterlace(AVPicture *dst, const AVPicture *src, + enum PixelFormat pix_fmt, int width, int height); + +/* external high level API */ + +/** + * If c is NULL, returns the first registered codec, + * if c is non-NULL, returns the next registered codec after c, + * or NULL if c is the last one. + */ +AVCodec *av_codec_next(AVCodec *c); + +/** + * Return the LIBAVCODEC_VERSION_INT constant. + */ +unsigned avcodec_version(void); + +/** + * Return the libavcodec build-time configuration. + */ +const char *avcodec_configuration(void); + +/** + * Return the libavcodec license. + */ +const char *avcodec_license(void); + +#if FF_API_AVCODEC_INIT +/** + * @deprecated this function is called automatically from avcodec_register() + * and avcodec_register_all(), there is no need to call it manually + */ +attribute_deprecated +void avcodec_init(void); +#endif + +/** + * Register the codec codec and initialize libavcodec. + * + * @warning either this function or avcodec_register_all() must be called + * before any other libavcodec functions. + * + * @see avcodec_register_all() + */ +void avcodec_register(AVCodec *codec); + +/** + * Find a registered encoder with a matching codec ID. + * + * @param id CodecID of the requested encoder + * @return An encoder if one was found, NULL otherwise. + */ +AVCodec *avcodec_find_encoder(enum CodecID id); + +/** + * Find a registered encoder with the specified name. + * + * @param name name of the requested encoder + * @return An encoder if one was found, NULL otherwise. + */ +AVCodec *avcodec_find_encoder_by_name(const char *name); + +/** + * Find a registered decoder with a matching codec ID. + * + * @param id CodecID of the requested decoder + * @return A decoder if one was found, NULL otherwise. + */ +AVCodec *avcodec_find_decoder(enum CodecID id); + +/** + * Find a registered decoder with the specified name. + * + * @param name name of the requested decoder + * @return A decoder if one was found, NULL otherwise. + */ +AVCodec *avcodec_find_decoder_by_name(const char *name); +void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode); + +/** + * Return a name for the specified profile, if available. + * + * @param codec the codec that is searched for the given profile + * @param profile the profile value for which a name is requested + * @return A name for the profile if found, NULL otherwise. + */ +const char *av_get_profile_name(const AVCodec *codec, int profile); + +#if FF_API_ALLOC_CONTEXT +/** + * Set the fields of the given AVCodecContext to default values. + * + * @param s The AVCodecContext of which the fields should be set to default values. + * @deprecated use avcodec_get_context_defaults3 + */ +attribute_deprecated +void avcodec_get_context_defaults(AVCodecContext *s); + +/** THIS FUNCTION IS NOT YET PART OF THE PUBLIC API! + * we WILL change its arguments and name a few times! */ +attribute_deprecated +void avcodec_get_context_defaults2(AVCodecContext *s, enum AVMediaType); +#endif + +/** + * Set the fields of the given AVCodecContext to default values corresponding + * to the given codec (defaults may be codec-dependent). + * + * Do not call this function if a non-NULL codec has been passed + * to avcodec_alloc_context3() that allocated this AVCodecContext. + * If codec is non-NULL, it is illegal to call avcodec_open2() with a + * different codec on this AVCodecContext. + */ +int avcodec_get_context_defaults3(AVCodecContext *s, AVCodec *codec); + +#if FF_API_ALLOC_CONTEXT +/** + * Allocate an AVCodecContext and set its fields to default values. The + * resulting struct can be deallocated by simply calling av_free(). + * + * @return An AVCodecContext filled with default values or NULL on failure. + * @see avcodec_get_context_defaults + * + * @deprecated use avcodec_alloc_context3() + */ +attribute_deprecated +AVCodecContext *avcodec_alloc_context(void); + +/** THIS FUNCTION IS NOT YET PART OF THE PUBLIC API! + * we WILL change its arguments and name a few times! */ +attribute_deprecated +AVCodecContext *avcodec_alloc_context2(enum AVMediaType); +#endif + +/** + * Allocate an AVCodecContext and set its fields to default values. The + * resulting struct can be deallocated by simply calling av_free(). + * + * @param codec if non-NULL, allocate private data and initialize defaults + * for the given codec. It is illegal to then call avcodec_open2() + * with a different codec. + * + * @return An AVCodecContext filled with default values or NULL on failure. + * @see avcodec_get_context_defaults + */ +AVCodecContext *avcodec_alloc_context3(AVCodec *codec); + +/** + * Copy the settings of the source AVCodecContext into the destination + * AVCodecContext. The resulting destination codec context will be + * unopened, i.e. you are required to call avcodec_open2() before you + * can use this AVCodecContext to decode/encode video/audio data. + * + * @param dest target codec context, should be initialized with + * avcodec_alloc_context3(), but otherwise uninitialized + * @param src source codec context + * @return AVERROR() on error (e.g. memory allocation error), 0 on success + */ +int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src); + +/** + * Set the fields of the given AVFrame to default values. + * + * @param pic The AVFrame of which the fields should be set to default values. + */ +void avcodec_get_frame_defaults(AVFrame *pic); + +/** + * Allocate an AVFrame and set its fields to default values. The resulting + * struct can be deallocated by simply calling av_free(). + * + * @return An AVFrame filled with default values or NULL on failure. + * @see avcodec_get_frame_defaults + */ +AVFrame *avcodec_alloc_frame(void); + +int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic); +void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic); +int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic); + +/** + * Return the amount of padding in pixels which the get_buffer callback must + * provide around the edge of the image for codecs which do not have the + * CODEC_FLAG_EMU_EDGE flag. + * + * @return Required padding in pixels. + */ +unsigned avcodec_get_edge_width(void); +/** + * Modify width and height values so that they will result in a memory + * buffer that is acceptable for the codec if you do not use any horizontal + * padding. + * + * May only be used if a codec with CODEC_CAP_DR1 has been opened. + * If CODEC_FLAG_EMU_EDGE is not set, the dimensions must have been increased + * according to avcodec_get_edge_width() before. + */ +void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height); +/** + * Modify width and height values so that they will result in a memory + * buffer that is acceptable for the codec if you also ensure that all + * line sizes are a multiple of the respective linesize_align[i]. + * + * May only be used if a codec with CODEC_CAP_DR1 has been opened. + * If CODEC_FLAG_EMU_EDGE is not set, the dimensions must have been increased + * according to avcodec_get_edge_width() before. + */ +void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, + int linesize_align[AV_NUM_DATA_POINTERS]); + +enum PixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum PixelFormat * fmt); + +#if FF_API_THREAD_INIT +/** + * @deprecated Set s->thread_count before calling avcodec_open2() instead of calling this. + */ +attribute_deprecated +int avcodec_thread_init(AVCodecContext *s, int thread_count); +#endif + +int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2),void *arg, int *ret, int count, int size); +int avcodec_default_execute2(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2, int, int),void *arg, int *ret, int count); +//FIXME func typedef + +#if FF_API_AVCODEC_OPEN +/** + * Initialize the AVCodecContext to use the given AVCodec. Prior to using this + * function the context has to be allocated. + * + * The functions avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(), + * avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for + * retrieving a codec. + * + * @warning This function is not thread safe! + * + * @code + * avcodec_register_all(); + * codec = avcodec_find_decoder(CODEC_ID_H264); + * if (!codec) + * exit(1); + * + * context = avcodec_alloc_context3(codec); + * + * if (avcodec_open(context, codec) < 0) + * exit(1); + * @endcode + * + * @param avctx The context which will be set up to use the given codec. + * @param codec The codec to use within the context. + * @return zero on success, a negative value on error + * @see avcodec_alloc_context3, avcodec_find_decoder, avcodec_find_encoder, avcodec_close + * + * @deprecated use avcodec_open2 + */ +attribute_deprecated +int avcodec_open(AVCodecContext *avctx, AVCodec *codec); +#endif + +/** + * Initialize the AVCodecContext to use the given AVCodec. Prior to using this + * function the context has to be allocated with avcodec_alloc_context3(). + * + * The functions avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(), + * avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for + * retrieving a codec. + * + * @warning This function is not thread safe! + * + * @code + * avcodec_register_all(); + * av_dict_set(&opts, "b", "2.5M", 0); + * codec = avcodec_find_decoder(CODEC_ID_H264); + * if (!codec) + * exit(1); + * + * context = avcodec_alloc_context3(codec); + * + * if (avcodec_open2(context, codec, opts) < 0) + * exit(1); + * @endcode + * + * @param avctx The context to initialize. + * @param options A dictionary filled with AVCodecContext and codec-private options. + * On return this object will be filled with options that were not found. + * + * @return zero on success, a negative value on error + * @see avcodec_alloc_context3(), avcodec_find_decoder(), avcodec_find_encoder(), + * av_dict_set(), av_opt_find(). + */ +int avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVDictionary **options); + +#if FF_API_OLD_DECODE_AUDIO +/** + * Wrapper function which calls avcodec_decode_audio4. + * + * @deprecated Use avcodec_decode_audio4 instead. + * + * Decode the audio frame of size avpkt->size from avpkt->data into samples. + * Some decoders may support multiple frames in a single AVPacket, such + * decoders would then just decode the first frame. In this case, + * avcodec_decode_audio3 has to be called again with an AVPacket that contains + * the remaining data in order to decode the second frame etc. + * If no frame + * could be outputted, frame_size_ptr is zero. Otherwise, it is the + * decompressed frame size in bytes. + * + * @warning You must set frame_size_ptr to the allocated size of the + * output buffer before calling avcodec_decode_audio3(). + * + * @warning The input buffer must be FF_INPUT_BUFFER_PADDING_SIZE larger than + * the actual read bytes because some optimized bitstream readers read 32 or 64 + * bits at once and could read over the end. + * + * @warning The end of the input buffer avpkt->data should be set to 0 to ensure that + * no overreading happens for damaged MPEG streams. + * + * @warning You must not provide a custom get_buffer() when using + * avcodec_decode_audio3(). Doing so will override it with + * avcodec_default_get_buffer. Use avcodec_decode_audio4() instead, + * which does allow the application to provide a custom get_buffer(). + * + * @note You might have to align the input buffer avpkt->data and output buffer + * samples. The alignment requirements depend on the CPU: On some CPUs it isn't + * necessary at all, on others it won't work at all if not aligned and on others + * it will work but it will have an impact on performance. + * + * In practice, avpkt->data should have 4 byte alignment at minimum and + * samples should be 16 byte aligned unless the CPU doesn't need it + * (AltiVec and SSE do). + * + * @note Codecs which have the CODEC_CAP_DELAY capability set have a delay + * between input and output, these need to be fed with avpkt->data=NULL, + * avpkt->size=0 at the end to return the remaining frames. + * + * @param avctx the codec context + * @param[out] samples the output buffer, sample type in avctx->sample_fmt + * If the sample format is planar, each channel plane will + * be the same size, with no padding between channels. + * @param[in,out] frame_size_ptr the output buffer size in bytes + * @param[in] avpkt The input AVPacket containing the input buffer. + * You can create such packet with av_init_packet() and by then setting + * data and size, some decoders might in addition need other fields. + * All decoders are designed to use the least fields possible though. + * @return On error a negative value is returned, otherwise the number of bytes + * used or zero if no frame data was decompressed (used) from the input AVPacket. + */ +attribute_deprecated int avcodec_decode_audio3(AVCodecContext *avctx, int16_t *samples, + int *frame_size_ptr, + AVPacket *avpkt); +#endif + +/** + * Decode the audio frame of size avpkt->size from avpkt->data into frame. + * + * Some decoders may support multiple frames in a single AVPacket. Such + * decoders would then just decode the first frame. In this case, + * avcodec_decode_audio4 has to be called again with an AVPacket containing + * the remaining data in order to decode the second frame, etc... + * Even if no frames are returned, the packet needs to be fed to the decoder + * with remaining data until it is completely consumed or an error occurs. + * + * @warning The input buffer, avpkt->data must be FF_INPUT_BUFFER_PADDING_SIZE + * larger than the actual read bytes because some optimized bitstream + * readers read 32 or 64 bits at once and could read over the end. + * + * @note You might have to align the input buffer. The alignment requirements + * depend on the CPU and the decoder. + * + * @param avctx the codec context + * @param[out] frame The AVFrame in which to store decoded audio samples. + * Decoders request a buffer of a particular size by setting + * AVFrame.nb_samples prior to calling get_buffer(). The + * decoder may, however, only utilize part of the buffer by + * setting AVFrame.nb_samples to a smaller value in the + * output frame. + * @param[out] got_frame_ptr Zero if no frame could be decoded, otherwise it is + * non-zero. + * @param[in] avpkt The input AVPacket containing the input buffer. + * At least avpkt->data and avpkt->size should be set. Some + * decoders might also require additional fields to be set. + * @return A negative error code is returned if an error occurred during + * decoding, otherwise the number of bytes consumed from the input + * AVPacket is returned. + */ +int avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame, + int *got_frame_ptr, AVPacket *avpkt); + +/** + * Decode the video frame of size avpkt->size from avpkt->data into picture. + * Some decoders may support multiple frames in a single AVPacket, such + * decoders would then just decode the first frame. + * + * @warning The input buffer must be FF_INPUT_BUFFER_PADDING_SIZE larger than + * the actual read bytes because some optimized bitstream readers read 32 or 64 + * bits at once and could read over the end. + * + * @warning The end of the input buffer buf should be set to 0 to ensure that + * no overreading happens for damaged MPEG streams. + * + * @note You might have to align the input buffer avpkt->data. + * The alignment requirements depend on the CPU: on some CPUs it isn't + * necessary at all, on others it won't work at all if not aligned and on others + * it will work but it will have an impact on performance. + * + * In practice, avpkt->data should have 4 byte alignment at minimum. + * + * @note Codecs which have the CODEC_CAP_DELAY capability set have a delay + * between input and output, these need to be fed with avpkt->data=NULL, + * avpkt->size=0 at the end to return the remaining frames. + * + * @param avctx the codec context + * @param[out] picture The AVFrame in which the decoded video frame will be stored. + * Use avcodec_alloc_frame to get an AVFrame, the codec will + * allocate memory for the actual bitmap. + * with default get/release_buffer(), the decoder frees/reuses the bitmap as it sees fit. + * with overridden get/release_buffer() (needs CODEC_CAP_DR1) the user decides into what buffer the decoder + * decodes and the decoder tells the user once it does not need the data anymore, + * the user app can at this point free/reuse/keep the memory as it sees fit. + * + * @param[in] avpkt The input AVpacket containing the input buffer. + * You can create such packet with av_init_packet() and by then setting + * data and size, some decoders might in addition need other fields like + * flags&AV_PKT_FLAG_KEY. All decoders are designed to use the least + * fields possible. + * @param[in,out] got_picture_ptr Zero if no frame could be decompressed, otherwise, it is nonzero. + * @return On error a negative value is returned, otherwise the number of bytes + * used or zero if no frame could be decompressed. + */ +int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, + int *got_picture_ptr, + const AVPacket *avpkt); + +/** + * Decode a subtitle message. + * Return a negative value on error, otherwise return the number of bytes used. + * If no subtitle could be decompressed, got_sub_ptr is zero. + * Otherwise, the subtitle is stored in *sub. + * Note that CODEC_CAP_DR1 is not available for subtitle codecs. This is for + * simplicity, because the performance difference is expect to be negligible + * and reusing a get_buffer written for video codecs would probably perform badly + * due to a potentially very different allocation pattern. + * + * @param avctx the codec context + * @param[out] sub The AVSubtitle in which the decoded subtitle will be stored, must be + freed with avsubtitle_free if *got_sub_ptr is set. + * @param[in,out] got_sub_ptr Zero if no subtitle could be decompressed, otherwise, it is nonzero. + * @param[in] avpkt The input AVPacket containing the input buffer. + */ +int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, + AVPacket *avpkt); + +/** + * Free all allocated data in the given subtitle struct. + * + * @param sub AVSubtitle to free. + */ +void avsubtitle_free(AVSubtitle *sub); + +#if FF_API_OLD_ENCODE_AUDIO +/** + * Encode an audio frame from samples into buf. + * + * @deprecated Use avcodec_encode_audio2 instead. + * + * @note The output buffer should be at least FF_MIN_BUFFER_SIZE bytes large. + * However, for codecs with avctx->frame_size equal to 0 (e.g. PCM) the user + * will know how much space is needed because it depends on the value passed + * in buf_size as described below. In that case a lower value can be used. + * + * @param avctx the codec context + * @param[out] buf the output buffer + * @param[in] buf_size the output buffer size + * @param[in] samples the input buffer containing the samples + * The number of samples read from this buffer is frame_size*channels, + * both of which are defined in avctx. + * For codecs which have avctx->frame_size equal to 0 (e.g. PCM) the number of + * samples read from samples is equal to: + * buf_size * 8 / (avctx->channels * av_get_bits_per_sample(avctx->codec_id)) + * This also implies that av_get_bits_per_sample() must not return 0 for these + * codecs. + * @return On error a negative value is returned, on success zero or the number + * of bytes used to encode the data read from the input buffer. + */ +int attribute_deprecated avcodec_encode_audio(AVCodecContext *avctx, + uint8_t *buf, int buf_size, + const short *samples); +#endif + +/** + * Encode a frame of audio. + * + * Takes input samples from frame and writes the next output packet, if + * available, to avpkt. The output packet does not necessarily contain data for + * the most recent frame, as encoders can delay, split, and combine input frames + * internally as needed. + * + * @param avctx codec context + * @param avpkt output AVPacket. + * The user can supply an output buffer by setting + * avpkt->data and avpkt->size prior to calling the + * function, but if the size of the user-provided data is not + * large enough, encoding will fail. All other AVPacket fields + * will be reset by the encoder using av_init_packet(). If + * avpkt->data is NULL, the encoder will allocate it. + * The encoder will set avpkt->size to the size of the + * output packet. + * @param[in] frame AVFrame containing the raw audio data to be encoded. + * May be NULL when flushing an encoder that has the + * CODEC_CAP_DELAY capability set. + * There are 2 codec capabilities that affect the allowed + * values of frame->nb_samples. + * If CODEC_CAP_SMALL_LAST_FRAME is set, then only the final + * frame may be smaller than avctx->frame_size, and all other + * frames must be equal to avctx->frame_size. + * If CODEC_CAP_VARIABLE_FRAME_SIZE is set, then each frame + * can have any number of samples. + * If neither is set, frame->nb_samples must be equal to + * avctx->frame_size for all frames. + * @param[out] got_packet_ptr This field is set to 1 by libavcodec if the + * output packet is non-empty, and to 0 if it is + * empty. If the function returns an error, the + * packet can be assumed to be invalid, and the + * value of got_packet_ptr is undefined and should + * not be used. + * @return 0 on success, negative error code on failure + */ +int avcodec_encode_audio2(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr); + +/** + * Fill audio frame data and linesize. + * AVFrame extended_data channel pointers are allocated if necessary for + * planar audio. + * + * @param frame the AVFrame + * frame->nb_samples must be set prior to calling the + * function. This function fills in frame->data, + * frame->extended_data, frame->linesize[0]. + * @param nb_channels channel count + * @param sample_fmt sample format + * @param buf buffer to use for frame data + * @param buf_size size of buffer + * @param align plane size sample alignment + * @return 0 on success, negative error code on failure + */ +int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels, + enum AVSampleFormat sample_fmt, const uint8_t *buf, + int buf_size, int align); + +/** + * Encode a video frame from pict into buf. + * The input picture should be + * stored using a specific format, namely avctx.pix_fmt. + * + * @param avctx the codec context + * @param[out] buf the output buffer for the bitstream of encoded frame + * @param[in] buf_size the size of the output buffer in bytes + * @param[in] pict the input picture to encode + * @return On error a negative value is returned, on success zero or the number + * of bytes used from the output buffer. + */ +int avcodec_encode_video(AVCodecContext *avctx, uint8_t *buf, int buf_size, + const AVFrame *pict); +int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, + const AVSubtitle *sub); + +int avcodec_close(AVCodecContext *avctx); + +/** + * Register all the codecs, parsers and bitstream filters which were enabled at + * configuration time. If you do not call this function you can select exactly + * which formats you want to support, by using the individual registration + * functions. + * + * @see avcodec_register + * @see av_register_codec_parser + * @see av_register_bitstream_filter + */ +void avcodec_register_all(void); + +/** + * Flush buffers, should be called when seeking or when switching to a different stream. + */ +void avcodec_flush_buffers(AVCodecContext *avctx); + +void avcodec_default_free_buffers(AVCodecContext *s); + +/* misc useful functions */ + +#if FF_API_OLD_FF_PICT_TYPES +/** + * Return a single letter to describe the given picture type pict_type. + * + * @param[in] pict_type the picture type + * @return A single character representing the picture type. + * @deprecated Use av_get_picture_type_char() instead. + */ +attribute_deprecated +char av_get_pict_type_char(int pict_type); +#endif + +/** + * Return codec bits per sample. + * + * @param[in] codec_id the codec + * @return Number of bits per sample or zero if unknown for the given codec. + */ +int av_get_bits_per_sample(enum CodecID codec_id); + +#if FF_API_OLD_SAMPLE_FMT +/** + * @deprecated Use av_get_bytes_per_sample() instead. + */ +attribute_deprecated +int av_get_bits_per_sample_format(enum AVSampleFormat sample_fmt); +#endif + +/* frame parsing */ +typedef struct AVCodecParserContext { + void *priv_data; + struct AVCodecParser *parser; + int64_t frame_offset; /* offset of the current frame */ + int64_t cur_offset; /* current offset + (incremented by each av_parser_parse()) */ + int64_t next_frame_offset; /* offset of the next frame */ + /* video info */ + int pict_type; /* XXX: Put it back in AVCodecContext. */ + /** + * This field is used for proper frame duration computation in lavf. + * It signals, how much longer the frame duration of the current frame + * is compared to normal frame duration. + * + * frame_duration = (1 + repeat_pict) * time_base + * + * It is used by codecs like H.264 to display telecined material. + */ + int repeat_pict; /* XXX: Put it back in AVCodecContext. */ + int64_t pts; /* pts of the current frame */ + int64_t dts; /* dts of the current frame */ + + /* private data */ + int64_t last_pts; + int64_t last_dts; + int fetch_timestamp; + +#define AV_PARSER_PTS_NB 4 + int cur_frame_start_index; + int64_t cur_frame_offset[AV_PARSER_PTS_NB]; + int64_t cur_frame_pts[AV_PARSER_PTS_NB]; + int64_t cur_frame_dts[AV_PARSER_PTS_NB]; + + int flags; +#define PARSER_FLAG_COMPLETE_FRAMES 0x0001 +#define PARSER_FLAG_ONCE 0x0002 +/// Set if the parser has a valid file offset +#define PARSER_FLAG_FETCHED_OFFSET 0x0004 + + int64_t offset; ///< byte offset from starting packet start + int64_t cur_frame_end[AV_PARSER_PTS_NB]; + + /** + * Set by parser to 1 for key frames and 0 for non-key frames. + * It is initialized to -1, so if the parser doesn't set this flag, + * old-style fallback using AV_PICTURE_TYPE_I picture type as key frames + * will be used. + */ + int key_frame; + + /** + * Time difference in stream time base units from the pts of this + * packet to the point at which the output from the decoder has converged + * independent from the availability of previous frames. That is, the + * frames are virtually identical no matter if decoding started from + * the very first frame or from this keyframe. + * Is AV_NOPTS_VALUE if unknown. + * This field is not the display duration of the current frame. + * This field has no meaning if the packet does not have AV_PKT_FLAG_KEY + * set. + * + * The purpose of this field is to allow seeking in streams that have no + * keyframes in the conventional sense. It corresponds to the + * recovery point SEI in H.264 and match_time_delta in NUT. It is also + * essential for some types of subtitle streams to ensure that all + * subtitles are correctly displayed after seeking. + */ + int64_t convergence_duration; + + // Timestamp generation support: + /** + * Synchronization point for start of timestamp generation. + * + * Set to >0 for sync point, 0 for no sync point and <0 for undefined + * (default). + * + * For example, this corresponds to presence of H.264 buffering period + * SEI message. + */ + int dts_sync_point; + + /** + * Offset of the current timestamp against last timestamp sync point in + * units of AVCodecContext.time_base. + * + * Set to INT_MIN when dts_sync_point unused. Otherwise, it must + * contain a valid timestamp offset. + * + * Note that the timestamp of sync point has usually a nonzero + * dts_ref_dts_delta, which refers to the previous sync point. Offset of + * the next frame after timestamp sync point will be usually 1. + * + * For example, this corresponds to H.264 cpb_removal_delay. + */ + int dts_ref_dts_delta; + + /** + * Presentation delay of current frame in units of AVCodecContext.time_base. + * + * Set to INT_MIN when dts_sync_point unused. Otherwise, it must + * contain valid non-negative timestamp delta (presentation time of a frame + * must not lie in the past). + * + * This delay represents the difference between decoding and presentation + * time of the frame. + * + * For example, this corresponds to H.264 dpb_output_delay. + */ + int pts_dts_delta; + + /** + * Position of the packet in file. + * + * Analogous to cur_frame_pts/dts + */ + int64_t cur_frame_pos[AV_PARSER_PTS_NB]; + + /** + * Byte position of currently parsed frame in stream. + */ + int64_t pos; + + /** + * Previous frame byte position. + */ + int64_t last_pos; +} AVCodecParserContext; + +typedef struct AVCodecParser { + int codec_ids[5]; /* several codec IDs are permitted */ + int priv_data_size; + int (*parser_init)(AVCodecParserContext *s); + int (*parser_parse)(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size); + void (*parser_close)(AVCodecParserContext *s); + int (*split)(AVCodecContext *avctx, const uint8_t *buf, int buf_size); + struct AVCodecParser *next; +} AVCodecParser; + +AVCodecParser *av_parser_next(AVCodecParser *c); + +void av_register_codec_parser(AVCodecParser *parser); +AVCodecParserContext *av_parser_init(int codec_id); + +/** + * Parse a packet. + * + * @param s parser context. + * @param avctx codec context. + * @param poutbuf set to pointer to parsed buffer or NULL if not yet finished. + * @param poutbuf_size set to size of parsed buffer or zero if not yet finished. + * @param buf input buffer. + * @param buf_size input length, to signal EOF, this should be 0 (so that the last frame can be output). + * @param pts input presentation timestamp. + * @param dts input decoding timestamp. + * @param pos input byte position in stream. + * @return the number of bytes of the input bitstream used. + * + * Example: + * @code + * while(in_len){ + * len = av_parser_parse2(myparser, AVCodecContext, &data, &size, + * in_data, in_len, + * pts, dts, pos); + * in_data += len; + * in_len -= len; + * + * if(size) + * decode_frame(data, size); + * } + * @endcode + */ +int av_parser_parse2(AVCodecParserContext *s, + AVCodecContext *avctx, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, + int64_t pts, int64_t dts, + int64_t pos); + +int av_parser_change(AVCodecParserContext *s, + AVCodecContext *avctx, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, int keyframe); +void av_parser_close(AVCodecParserContext *s); + + +typedef struct AVBitStreamFilterContext { + void *priv_data; + struct AVBitStreamFilter *filter; + AVCodecParserContext *parser; + struct AVBitStreamFilterContext *next; +} AVBitStreamFilterContext; + + +typedef struct AVBitStreamFilter { + const char *name; + int priv_data_size; + int (*filter)(AVBitStreamFilterContext *bsfc, + AVCodecContext *avctx, const char *args, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, int keyframe); + void (*close)(AVBitStreamFilterContext *bsfc); + struct AVBitStreamFilter *next; +} AVBitStreamFilter; + +void av_register_bitstream_filter(AVBitStreamFilter *bsf); +AVBitStreamFilterContext *av_bitstream_filter_init(const char *name); +int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc, + AVCodecContext *avctx, const char *args, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, int keyframe); +void av_bitstream_filter_close(AVBitStreamFilterContext *bsf); + +AVBitStreamFilter *av_bitstream_filter_next(AVBitStreamFilter *f); + +/* memory */ + +/** + * Reallocate the given block if it is not large enough, otherwise do nothing. + * + * @see av_realloc + */ +void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size); + +/** + * Allocate a buffer, reusing the given one if large enough. + * + * Contrary to av_fast_realloc the current buffer contents might not be + * preserved and on error the old buffer is freed, thus no special + * handling to avoid memleaks is necessary. + * + * @param ptr pointer to pointer to already allocated buffer, overwritten with pointer to new buffer + * @param size size of the buffer *ptr points to + * @param min_size minimum size of *ptr buffer after returning, *ptr will be NULL and + * *size 0 if an error occurred. + */ +void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size); + +/** + * Same behaviour av_fast_malloc but the buffer has additional + * FF_INPUT_PADDING_SIZE at the end which will will always be 0. + * + * In addition the whole buffer will initially and after resizes + * be 0-initialized so that no uninitialized data will ever appear. + */ +void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size); + +/** + * Copy image src to dst. Wraps av_picture_data_copy() above. + */ +void av_picture_copy(AVPicture *dst, const AVPicture *src, + enum PixelFormat pix_fmt, int width, int height); + +/** + * Crop image top and left side. + */ +int av_picture_crop(AVPicture *dst, const AVPicture *src, + enum PixelFormat pix_fmt, int top_band, int left_band); + +/** + * Pad image. + */ +int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width, enum PixelFormat pix_fmt, + int padtop, int padbottom, int padleft, int padright, int *color); + +/** + * Encode extradata length to a buffer. Used by xiph codecs. + * + * @param s buffer to write to; must be at least (v/255+1) bytes long + * @param v size of extradata in bytes + * @return number of bytes written to the buffer. + */ +unsigned int av_xiphlacing(unsigned char *s, unsigned int v); + +/** + * Log a generic warning message about a missing feature. This function is + * intended to be used internally by FFmpeg (libavcodec, libavformat, etc.) + * only, and would normally not be used by applications. + * @param[in] avc a pointer to an arbitrary struct of which the first field is + * a pointer to an AVClass struct + * @param[in] feature string containing the name of the missing feature + * @param[in] want_sample indicates if samples are wanted which exhibit this feature. + * If want_sample is non-zero, additional verbage will be added to the log + * message which tells the user how to report samples to the development + * mailing list. + */ +void av_log_missing_feature(void *avc, const char *feature, int want_sample); + +/** + * Log a generic warning message asking for a sample. This function is + * intended to be used internally by FFmpeg (libavcodec, libavformat, etc.) + * only, and would normally not be used by applications. + * @param[in] avc a pointer to an arbitrary struct of which the first field is + * a pointer to an AVClass struct + * @param[in] msg string containing an optional message, or NULL if no message + */ +void av_log_ask_for_sample(void *avc, const char *msg, ...) av_printf_format(2, 3); + +/** + * Register the hardware accelerator hwaccel. + */ +void av_register_hwaccel(AVHWAccel *hwaccel); + +/** + * If hwaccel is NULL, returns the first registered hardware accelerator, + * if hwaccel is non-NULL, returns the next registered hardware accelerator + * after hwaccel, or NULL if hwaccel is the last one. + */ +AVHWAccel *av_hwaccel_next(AVHWAccel *hwaccel); + + +/** + * Lock operation used by lockmgr + */ +enum AVLockOp { + AV_LOCK_CREATE, ///< Create a mutex + AV_LOCK_OBTAIN, ///< Lock the mutex + AV_LOCK_RELEASE, ///< Unlock the mutex + AV_LOCK_DESTROY, ///< Free mutex resources +}; + +/** + * Register a user provided lock manager supporting the operations + * specified by AVLockOp. mutex points to a (void *) where the + * lockmgr should store/get a pointer to a user allocated mutex. It's + * NULL upon AV_LOCK_CREATE and != NULL for all other ops. + * + * @param cb User defined callback. Note: FFmpeg may invoke calls to this + * callback during the call to av_lockmgr_register(). + * Thus, the application must be prepared to handle that. + * If cb is set to NULL the lockmgr will be unregistered. + * Also note that during unregistration the previously registered + * lockmgr callback may also be invoked. + */ +int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op)); + +/** + * Get the type of the given codec. + */ +enum AVMediaType avcodec_get_type(enum CodecID codec_id); + +/** + * Get the AVClass for AVCodecContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *avcodec_get_class(void); + +/** + * Get the AVClass for AVFrame. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *avcodec_get_frame_class(void); + +#endif /* AVCODEC_AVCODEC_H */ diff --git a/Externals/ffmpeg/include/libavcodec/avfft.h b/Externals/ffmpeg/include/libavcodec/avfft.h new file mode 100644 index 0000000000..be2d9c7e1 --- /dev/null +++ b/Externals/ffmpeg/include/libavcodec/avfft.h @@ -0,0 +1,99 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_AVFFT_H +#define AVCODEC_AVFFT_H + +typedef float FFTSample; + +typedef struct FFTComplex { + FFTSample re, im; +} FFTComplex; + +typedef struct FFTContext FFTContext; + +/** + * Set up a complex FFT. + * @param nbits log2 of the length of the input array + * @param inverse if 0 perform the forward transform, if 1 perform the inverse + */ +FFTContext *av_fft_init(int nbits, int inverse); + +/** + * Do the permutation needed BEFORE calling ff_fft_calc(). + */ +void av_fft_permute(FFTContext *s, FFTComplex *z); + +/** + * Do a complex FFT with the parameters defined in av_fft_init(). The + * input data must be permuted before. No 1.0/sqrt(n) normalization is done. + */ +void av_fft_calc(FFTContext *s, FFTComplex *z); + +void av_fft_end(FFTContext *s); + +FFTContext *av_mdct_init(int nbits, int inverse, double scale); +void av_imdct_calc(FFTContext *s, FFTSample *output, const FFTSample *input); +void av_imdct_half(FFTContext *s, FFTSample *output, const FFTSample *input); +void av_mdct_calc(FFTContext *s, FFTSample *output, const FFTSample *input); +void av_mdct_end(FFTContext *s); + +/* Real Discrete Fourier Transform */ + +enum RDFTransformType { + DFT_R2C, + IDFT_C2R, + IDFT_R2C, + DFT_C2R, +}; + +typedef struct RDFTContext RDFTContext; + +/** + * Set up a real FFT. + * @param nbits log2 of the length of the input array + * @param trans the type of transform + */ +RDFTContext *av_rdft_init(int nbits, enum RDFTransformType trans); +void av_rdft_calc(RDFTContext *s, FFTSample *data); +void av_rdft_end(RDFTContext *s); + +/* Discrete Cosine Transform */ + +typedef struct DCTContext DCTContext; + +enum DCTTransformType { + DCT_II = 0, + DCT_III, + DCT_I, + DST_I, +}; + +/** + * Set up DCT. + * @param nbits size of the input array: + * (1 << nbits) for DCT-II, DCT-III and DST-I + * (1 << nbits) + 1 for DCT-I + * + * @note the first element of the input of DST-I is ignored + */ +DCTContext *av_dct_init(int nbits, enum DCTTransformType type); +void av_dct_calc(DCTContext *s, FFTSample *data); +void av_dct_end (DCTContext *s); + +#endif /* AVCODEC_AVFFT_H */ diff --git a/Externals/ffmpeg/include/libavcodec/dxva2.h b/Externals/ffmpeg/include/libavcodec/dxva2.h new file mode 100644 index 0000000000..fc9956083 --- /dev/null +++ b/Externals/ffmpeg/include/libavcodec/dxva2.h @@ -0,0 +1,71 @@ +/* + * DXVA2 HW acceleration + * + * copyright (c) 2009 Laurent Aimar + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_DXVA_H +#define AVCODEC_DXVA_H + +#include + +#include +#include + +#define FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG 1 ///< Work around for DXVA2 and old UVD/UVD+ ATI video cards + +/** + * This structure is used to provides the necessary configurations and data + * to the DXVA2 FFmpeg HWAccel implementation. + * + * The application must make it available as AVCodecContext.hwaccel_context. + */ +struct dxva_context { + /** + * DXVA2 decoder object + */ + IDirectXVideoDecoder *decoder; + + /** + * DXVA2 configuration used to create the decoder + */ + const DXVA2_ConfigPictureDecode *cfg; + + /** + * The number of surface in the surface array + */ + unsigned surface_count; + + /** + * The array of Direct3D surfaces used to create the decoder + */ + LPDIRECT3DSURFACE9 *surface; + + /** + * A bit field configuring the workarounds needed for using the decoder + */ + uint64_t workaround; + + /** + * Private to the FFmpeg AVHWAccel implementation + */ + unsigned report_id; +}; + +#endif /* AVCODEC_DXVA_H */ diff --git a/Externals/ffmpeg/include/libavcodec/opt.h b/Externals/ffmpeg/include/libavcodec/opt.h new file mode 100644 index 0000000000..2380e7433 --- /dev/null +++ b/Externals/ffmpeg/include/libavcodec/opt.h @@ -0,0 +1,34 @@ +/* + * This file is part of Libav. + * + * Libav 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. + * + * Libav 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 Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * This header is provided for compatibility only and will be removed + * on next major bump + */ + +#ifndef AVCODEC_OPT_H +#define AVCODEC_OPT_H + +#include "libavcodec/version.h" + +#if FF_API_OPT_H +#include "libavutil/opt.h" +#endif + +#endif /* AVCODEC_OPT_H */ diff --git a/Externals/ffmpeg/include/libavcodec/vaapi.h b/Externals/ffmpeg/include/libavcodec/vaapi.h new file mode 100644 index 0000000000..4c3bb9bb5 --- /dev/null +++ b/Externals/ffmpeg/include/libavcodec/vaapi.h @@ -0,0 +1,167 @@ +/* + * Video Acceleration API (shared data between FFmpeg and the video player) + * HW decode acceleration for MPEG-2, MPEG-4, H.264 and VC-1 + * + * Copyright (C) 2008-2009 Splitted-Desktop Systems + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_VAAPI_H +#define AVCODEC_VAAPI_H + +#include + +/** + * @defgroup VAAPI_Decoding VA API Decoding + * @ingroup Decoder + * @{ + */ + +/** + * This structure is used to share data between the FFmpeg library and + * the client video application. + * This shall be zero-allocated and available as + * AVCodecContext.hwaccel_context. All user members can be set once + * during initialization or through each AVCodecContext.get_buffer() + * function call. In any case, they must be valid prior to calling + * decoding functions. + */ +struct vaapi_context { + /** + * Window system dependent data + * + * - encoding: unused + * - decoding: Set by user + */ + void *display; + + /** + * Configuration ID + * + * - encoding: unused + * - decoding: Set by user + */ + uint32_t config_id; + + /** + * Context ID (video decode pipeline) + * + * - encoding: unused + * - decoding: Set by user + */ + uint32_t context_id; + + /** + * VAPictureParameterBuffer ID + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + uint32_t pic_param_buf_id; + + /** + * VAIQMatrixBuffer ID + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + uint32_t iq_matrix_buf_id; + + /** + * VABitPlaneBuffer ID (for VC-1 decoding) + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + uint32_t bitplane_buf_id; + + /** + * Slice parameter/data buffer IDs + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + uint32_t *slice_buf_ids; + + /** + * Number of effective slice buffer IDs to send to the HW + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + unsigned int n_slice_buf_ids; + + /** + * Size of pre-allocated slice_buf_ids + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + unsigned int slice_buf_ids_alloc; + + /** + * Pointer to VASliceParameterBuffers + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + void *slice_params; + + /** + * Size of a VASliceParameterBuffer element + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + unsigned int slice_param_size; + + /** + * Size of pre-allocated slice_params + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + unsigned int slice_params_alloc; + + /** + * Number of slices currently filled in + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + unsigned int slice_count; + + /** + * Pointer to slice data buffer base + * - encoding: unused + * - decoding: Set by libavcodec + */ + const uint8_t *slice_data; + + /** + * Current size of slice data + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + uint32_t slice_data_size; +}; + +/* @} */ + +#endif /* AVCODEC_VAAPI_H */ diff --git a/Externals/ffmpeg/include/libavcodec/vda.h b/Externals/ffmpeg/include/libavcodec/vda.h new file mode 100644 index 0000000000..6e9de9cd0 --- /dev/null +++ b/Externals/ffmpeg/include/libavcodec/vda.h @@ -0,0 +1,168 @@ +/* + * VDA HW acceleration + * + * copyright (c) 2011 Sebastien Zwickert + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_VDA_H +#define AVCODEC_VDA_H + +#include +#include + +// emmintrin.h is unable to compile with -std=c99 -Werror=missing-prototypes +// http://openradar.appspot.com/8026390 +#undef __GNUC_STDC_INLINE__ + +#define Picture QuickdrawPicture +#include +#undef Picture + +/** + * This structure is used to store a decoded frame information and data. + */ +typedef struct { + /** + * The PTS of the frame. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + int64_t pts; + + /** + * The CoreVideo buffer that contains the decoded data. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + CVPixelBufferRef cv_buffer; + + /** + * A pointer to the next frame. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + struct vda_frame *next_frame; +} vda_frame; + +/** + * This structure is used to provide the necessary configurations and data + * to the VDA FFmpeg HWAccel implementation. + * + * The application must make it available as AVCodecContext.hwaccel_context. + */ +struct vda_context { + /** + * VDA decoder object. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + VDADecoder decoder; + + /** + * VDA frames queue ordered by presentation timestamp. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + vda_frame *queue; + + /** + * Mutex for locking queue operations. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + pthread_mutex_t queue_mutex; + + /** + * The frame width. + * + * - encoding: unused + * - decoding: Set/Unset by user. + */ + int width; + + /** + * The frame height. + * + * - encoding: unused + * - decoding: Set/Unset by user. + */ + int height; + + /** + * The frame format. + * + * - encoding: unused + * - decoding: Set/Unset by user. + */ + int format; + + /** + * The pixel format for output image buffers. + * + * - encoding: unused + * - decoding: Set/Unset by user. + */ + OSType cv_pix_fmt_type; + + /** + * The current bitstream buffer. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + uint8_t *bitstream; + + /** + * The current size of the bitstream. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + int bitstream_size; + + /** + * The reference size used for fast reallocation. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + int ref_size; +}; + +/** Create the video decoder. */ +int ff_vda_create_decoder(struct vda_context *vda_ctx, + uint8_t *extradata, + int extradata_size); + +/** Destroy the video decoder. */ +int ff_vda_destroy_decoder(struct vda_context *vda_ctx); + +/** Return the top frame of the queue. */ +vda_frame *ff_vda_queue_pop(struct vda_context *vda_ctx); + +/** Release the given frame. */ +void ff_vda_release_vda_frame(vda_frame *frame); + +#endif /* AVCODEC_VDA_H */ diff --git a/Externals/ffmpeg/include/libavcodec/vdpau.h b/Externals/ffmpeg/include/libavcodec/vdpau.h new file mode 100644 index 0000000000..f3a547184 --- /dev/null +++ b/Externals/ffmpeg/include/libavcodec/vdpau.h @@ -0,0 +1,88 @@ +/* + * The Video Decode and Presentation API for UNIX (VDPAU) is used for + * hardware-accelerated decoding of MPEG-1/2, H.264 and VC-1. + * + * Copyright (C) 2008 NVIDIA + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_VDPAU_H +#define AVCODEC_VDPAU_H + +/** + * @defgroup Decoder VDPAU Decoder and Renderer + * + * VDPAU hardware acceleration has two modules + * - VDPAU decoding + * - VDPAU presentation + * + * The VDPAU decoding module parses all headers using FFmpeg + * parsing mechanisms and uses VDPAU for the actual decoding. + * + * As per the current implementation, the actual decoding + * and rendering (API calls) are done as part of the VDPAU + * presentation (vo_vdpau.c) module. + * + * @defgroup VDPAU_Decoding VDPAU Decoding + * @ingroup Decoder + * @{ + */ + +#include +#include + +/** @brief The videoSurface is used for rendering. */ +#define FF_VDPAU_STATE_USED_FOR_RENDER 1 + +/** + * @brief The videoSurface is needed for reference/prediction. + * The codec manipulates this. + */ +#define FF_VDPAU_STATE_USED_FOR_REFERENCE 2 + +/** + * @brief This structure is used as a callback between the FFmpeg + * decoder (vd_) and presentation (vo_) module. + * This is used for defining a video frame containing surface, + * picture parameter, bitstream information etc which are passed + * between the FFmpeg decoder and its clients. + */ +struct vdpau_render_state { + VdpVideoSurface surface; ///< Used as rendered surface, never changed. + + int state; ///< Holds FF_VDPAU_STATE_* values. + + /** Describe size/location of the compressed video data. + Set to 0 when freeing bitstream_buffers. */ + int bitstream_buffers_allocated; + int bitstream_buffers_used; + /** The user is responsible for freeing this buffer using av_freep(). */ + VdpBitstreamBuffer *bitstream_buffers; + + /** picture parameter information for all supported codecs */ + union VdpPictureInfo { + VdpPictureInfoH264 h264; + VdpPictureInfoMPEG1Or2 mpeg; + VdpPictureInfoVC1 vc1; + VdpPictureInfoMPEG4Part2 mpeg4; + } info; +}; + +/* @}*/ + +#endif /* AVCODEC_VDPAU_H */ diff --git a/Externals/ffmpeg/include/libavcodec/version.h b/Externals/ffmpeg/include/libavcodec/version.h new file mode 100644 index 0000000000..d67ad2f5d --- /dev/null +++ b/Externals/ffmpeg/include/libavcodec/version.h @@ -0,0 +1,130 @@ +/* + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_VERSION_H +#define AVCODEC_VERSION_H + +#define LIBAVCODEC_VERSION_MAJOR 53 +#define LIBAVCODEC_VERSION_MINOR 60 +#define LIBAVCODEC_VERSION_MICRO 100 + +#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ + LIBAVCODEC_VERSION_MINOR, \ + LIBAVCODEC_VERSION_MICRO) +#define LIBAVCODEC_VERSION AV_VERSION(LIBAVCODEC_VERSION_MAJOR, \ + LIBAVCODEC_VERSION_MINOR, \ + LIBAVCODEC_VERSION_MICRO) +#define LIBAVCODEC_BUILD LIBAVCODEC_VERSION_INT + +#define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION) + +/** + * Those FF_API_* defines are not part of public API. + * They may change, break or disappear at any time. + */ +#ifndef FF_API_PALETTE_CONTROL +#define FF_API_PALETTE_CONTROL (LIBAVCODEC_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_OLD_SAMPLE_FMT +#define FF_API_OLD_SAMPLE_FMT (LIBAVCODEC_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_OLD_AUDIOCONVERT +#define FF_API_OLD_AUDIOCONVERT (LIBAVCODEC_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_ANTIALIAS_ALGO +#define FF_API_ANTIALIAS_ALGO (LIBAVCODEC_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_REQUEST_CHANNELS +#define FF_API_REQUEST_CHANNELS (LIBAVCODEC_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_OPT_H +#define FF_API_OPT_H (LIBAVCODEC_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_THREAD_INIT +#define FF_API_THREAD_INIT (LIBAVCODEC_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_OLD_FF_PICT_TYPES +#define FF_API_OLD_FF_PICT_TYPES (LIBAVCODEC_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_FLAC_GLOBAL_OPTS +#define FF_API_FLAC_GLOBAL_OPTS (LIBAVCODEC_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_GET_PIX_FMT_NAME +#define FF_API_GET_PIX_FMT_NAME (LIBAVCODEC_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_ALLOC_CONTEXT +#define FF_API_ALLOC_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_AVCODEC_OPEN +#define FF_API_AVCODEC_OPEN (LIBAVCODEC_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_DRC_SCALE +#define FF_API_DRC_SCALE (LIBAVCODEC_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_ER +#define FF_API_ER (LIBAVCODEC_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_AVCODEC_INIT +#define FF_API_AVCODEC_INIT (LIBAVCODEC_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_X264_GLOBAL_OPTS +#define FF_API_X264_GLOBAL_OPTS (LIBAVCODEC_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_MPEGVIDEO_GLOBAL_OPTS +#define FF_API_MPEGVIDEO_GLOBAL_OPTS (LIBAVCODEC_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_LAME_GLOBAL_OPTS +#define FF_API_LAME_GLOBAL_OPTS (LIBAVCODEC_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_SNOW_GLOBAL_OPTS +#define FF_API_SNOW_GLOBAL_OPTS (LIBAVCODEC_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_MJPEG_GLOBAL_OPTS +#define FF_API_MJPEG_GLOBAL_OPTS (LIBAVCODEC_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_GET_ALPHA_INFO +#define FF_API_GET_ALPHA_INFO (LIBAVCODEC_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_PARSE_FRAME +#define FF_API_PARSE_FRAME (LIBAVCODEC_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_INTERNAL_CONTEXT +#define FF_API_INTERNAL_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_TIFFENC_COMPLEVEL +#define FF_API_TIFFENC_COMPLEVEL (LIBAVCODEC_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_DATA_POINTERS +#define FF_API_DATA_POINTERS (LIBAVCODEC_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_OLD_DECODE_AUDIO +#define FF_API_OLD_DECODE_AUDIO (LIBAVCODEC_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_OLD_TIMECODE +#define FF_API_OLD_TIMECODE (LIBAVCODEC_VERSION_MAJOR < 54) +#endif + +#ifndef FF_API_AVFRAME_AGE +#define FF_API_AVFRAME_AGE (LIBAVCODEC_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_OLD_ENCODE_AUDIO +#define FF_API_OLD_ENCODE_AUDIO (LIBAVCODEC_VERSION_MAJOR < 55) +#endif + +#endif /* AVCODEC_VERSION_H */ diff --git a/Externals/ffmpeg/include/libavcodec/xvmc.h b/Externals/ffmpeg/include/libavcodec/xvmc.h new file mode 100644 index 0000000000..93ad8bb9a --- /dev/null +++ b/Externals/ffmpeg/include/libavcodec/xvmc.h @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2003 Ivan Kalvachev + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_XVMC_H +#define AVCODEC_XVMC_H + +#include + +#include "avcodec.h" + +#define AV_XVMC_ID 0x1DC711C0 /**< special value to ensure that regular pixel routines haven't corrupted the struct + the number is 1337 speak for the letters IDCT MCo (motion compensation) */ + +struct xvmc_pix_fmt { + /** The field contains the special constant value AV_XVMC_ID. + It is used as a test that the application correctly uses the API, + and that there is no corruption caused by pixel routines. + - application - set during initialization + - libavcodec - unchanged + */ + int xvmc_id; + + /** Pointer to the block array allocated by XvMCCreateBlocks(). + The array has to be freed by XvMCDestroyBlocks(). + Each group of 64 values represents one data block of differential + pixel information (in MoCo mode) or coefficients for IDCT. + - application - set the pointer during initialization + - libavcodec - fills coefficients/pixel data into the array + */ + short* data_blocks; + + /** Pointer to the macroblock description array allocated by + XvMCCreateMacroBlocks() and freed by XvMCDestroyMacroBlocks(). + - application - set the pointer during initialization + - libavcodec - fills description data into the array + */ + XvMCMacroBlock* mv_blocks; + + /** Number of macroblock descriptions that can be stored in the mv_blocks + array. + - application - set during initialization + - libavcodec - unchanged + */ + int allocated_mv_blocks; + + /** Number of blocks that can be stored at once in the data_blocks array. + - application - set during initialization + - libavcodec - unchanged + */ + int allocated_data_blocks; + + /** Indicate that the hardware would interpret data_blocks as IDCT + coefficients and perform IDCT on them. + - application - set during initialization + - libavcodec - unchanged + */ + int idct; + + /** In MoCo mode it indicates that intra macroblocks are assumed to be in + unsigned format; same as the XVMC_INTRA_UNSIGNED flag. + - application - set during initialization + - libavcodec - unchanged + */ + int unsigned_intra; + + /** Pointer to the surface allocated by XvMCCreateSurface(). + It has to be freed by XvMCDestroySurface() on application exit. + It identifies the frame and its state on the video hardware. + - application - set during initialization + - libavcodec - unchanged + */ + XvMCSurface* p_surface; + +/** Set by the decoder before calling ff_draw_horiz_band(), + needed by the XvMCRenderSurface function. */ +//@{ + /** Pointer to the surface used as past reference + - application - unchanged + - libavcodec - set + */ + XvMCSurface* p_past_surface; + + /** Pointer to the surface used as future reference + - application - unchanged + - libavcodec - set + */ + XvMCSurface* p_future_surface; + + /** top/bottom field or frame + - application - unchanged + - libavcodec - set + */ + unsigned int picture_structure; + + /** XVMC_SECOND_FIELD - 1st or 2nd field in the sequence + - application - unchanged + - libavcodec - set + */ + unsigned int flags; +//}@ + + /** Number of macroblock descriptions in the mv_blocks array + that have already been passed to the hardware. + - application - zeroes it on get_buffer(). + A successful ff_draw_horiz_band() may increment it + with filled_mb_block_num or zero both. + - libavcodec - unchanged + */ + int start_mv_blocks_num; + + /** Number of new macroblock descriptions in the mv_blocks array (after + start_mv_blocks_num) that are filled by libavcodec and have to be + passed to the hardware. + - application - zeroes it on get_buffer() or after successful + ff_draw_horiz_band(). + - libavcodec - increment with one of each stored MB + */ + int filled_mv_blocks_num; + + /** Number of the the next free data block; one data block consists of + 64 short values in the data_blocks array. + All blocks before this one have already been claimed by placing their + position into the corresponding block description structure field, + that are part of the mv_blocks array. + - application - zeroes it on get_buffer(). + A successful ff_draw_horiz_band() may zero it together + with start_mb_blocks_num. + - libavcodec - each decoded macroblock increases it by the number + of coded blocks it contains. + */ + int next_free_data_block_num; +}; + +#endif /* AVCODEC_XVMC_H */ diff --git a/Externals/ffmpeg/include/libavdevice/avdevice.h b/Externals/ffmpeg/include/libavdevice/avdevice.h new file mode 100644 index 0000000000..5abf9f523 --- /dev/null +++ b/Externals/ffmpeg/include/libavdevice/avdevice.h @@ -0,0 +1,81 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVDEVICE_AVDEVICE_H +#define AVDEVICE_AVDEVICE_H + +/** + * @file + * @ingroup lavd + * Main libavdevice API header + */ + +/** + * @defgroup lavd Special devices muxing/demuxing library + * @{ + * Libavdevice is a complementary library to @ref libavf "libavformat". It + * provides various "special" platform-specific muxers and demuxers, e.g. for + * grabbing devices, audio capture and playback etc. As a consequence, the + * (de)muxers in libavdevice are of the AVFMT_NOFILE type (they use their own + * I/O functions). The filename passed to avformat_open_input() often does not + * refer to an actually existing file, but has some special device-specific + * meaning - e.g. for the x11grab device it is the display name. + * + * To use libavdevice, simply call avdevice_register_all() to register all + * compiled muxers and demuxers. They all use standard libavformat API. + * @} + */ + +#include "libavutil/avutil.h" +#include "libavformat/avformat.h" + +#define LIBAVDEVICE_VERSION_MAJOR 53 +#define LIBAVDEVICE_VERSION_MINOR 4 +#define LIBAVDEVICE_VERSION_MICRO 100 + +#define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ + LIBAVDEVICE_VERSION_MINOR, \ + LIBAVDEVICE_VERSION_MICRO) +#define LIBAVDEVICE_VERSION AV_VERSION(LIBAVDEVICE_VERSION_MAJOR, \ + LIBAVDEVICE_VERSION_MINOR, \ + LIBAVDEVICE_VERSION_MICRO) +#define LIBAVDEVICE_BUILD LIBAVDEVICE_VERSION_INT + +/** + * Return the LIBAVDEVICE_VERSION_INT constant. + */ +unsigned avdevice_version(void); + +/** + * Return the libavdevice build-time configuration. + */ +const char *avdevice_configuration(void); + +/** + * Return the libavdevice license. + */ +const char *avdevice_license(void); + +/** + * Initialize libavdevice and register all the input and output devices. + * @warning This function is not thread safe. + */ +void avdevice_register_all(void); + +#endif /* AVDEVICE_AVDEVICE_H */ + diff --git a/Externals/ffmpeg/include/libavfilter/avcodec.h b/Externals/ffmpeg/include/libavfilter/avcodec.h new file mode 100644 index 0000000000..22dd1a263 --- /dev/null +++ b/Externals/ffmpeg/include/libavfilter/avcodec.h @@ -0,0 +1,71 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFILTER_AVCODEC_H +#define AVFILTER_AVCODEC_H + +/** + * @file + * libavcodec/libavfilter gluing utilities + * + * This should be included in an application ONLY if the installed + * libavfilter has been compiled with libavcodec support, otherwise + * symbols defined below will not be available. + */ + +#include "libavcodec/avcodec.h" // AVFrame +#include "avfilter.h" +#include "vsrc_buffer.h" + +/** + * Copy the frame properties of src to dst, without copying the actual + * image data. + */ +int avfilter_copy_frame_props(AVFilterBufferRef *dst, const AVFrame *src); + +/** + * Create and return a picref reference from the data and properties + * contained in frame. + * + * @param perms permissions to assign to the new buffer reference + */ +AVFilterBufferRef *avfilter_get_video_buffer_ref_from_frame(const AVFrame *frame, int perms); + +/** + * Fill an AVFrame with the information stored in picref. + * + * @param frame an already allocated AVFrame + * @param picref a video buffer reference + * @return 0 in case of success, a negative AVERROR code in case of + * failure + */ +int avfilter_fill_frame_from_video_buffer_ref(AVFrame *frame, + const AVFilterBufferRef *picref); + +/** + * Add frame data to buffer_src. + * + * @param buffer_src pointer to a buffer source context + * @param flags a combination of AV_VSRC_BUF_FLAG_* flags + * @return >= 0 in case of success, a negative AVERROR code in case of + * failure + */ +int av_vsrc_buffer_add_frame(AVFilterContext *buffer_src, + const AVFrame *frame, int flags); + +#endif /* AVFILTER_AVCODEC_H */ diff --git a/Externals/ffmpeg/include/libavfilter/avfilter.h b/Externals/ffmpeg/include/libavfilter/avfilter.h new file mode 100644 index 0000000000..9c7a2e5bb --- /dev/null +++ b/Externals/ffmpeg/include/libavfilter/avfilter.h @@ -0,0 +1,948 @@ +/* + * filter layer + * Copyright (c) 2007 Bobby Bingham + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFILTER_AVFILTER_H +#define AVFILTER_AVFILTER_H + +#include "libavutil/avutil.h" +#include "libavutil/log.h" +#include "libavutil/samplefmt.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" +#include "libavcodec/avcodec.h" + + +#ifndef FF_API_OLD_VSINK_API +#define FF_API_OLD_VSINK_API (LIBAVFILTER_VERSION_MAJOR < 3) +#endif +#ifndef FF_API_OLD_ALL_FORMATS_API +#define FF_API_OLD_ALL_FORMATS_API (LIBAVFILTER_VERSION_MAJOR < 3) +#endif + +#include + +#include "libavfilter/version.h" + +/** + * Return the LIBAVFILTER_VERSION_INT constant. + */ +unsigned avfilter_version(void); + +/** + * Return the libavfilter build-time configuration. + */ +const char *avfilter_configuration(void); + +/** + * Return the libavfilter license. + */ +const char *avfilter_license(void); + + +typedef struct AVFilterContext AVFilterContext; +typedef struct AVFilterLink AVFilterLink; +typedef struct AVFilterPad AVFilterPad; + +/** + * A reference-counted buffer data type used by the filter system. Filters + * should not store pointers to this structure directly, but instead use the + * AVFilterBufferRef structure below. + */ +typedef struct AVFilterBuffer { + uint8_t *data[8]; ///< buffer data for each plane/channel + int linesize[8]; ///< number of bytes per line + + unsigned refcount; ///< number of references to this buffer + + /** private data to be used by a custom free function */ + void *priv; + /** + * A pointer to the function to deallocate this buffer if the default + * function is not sufficient. This could, for example, add the memory + * back into a memory pool to be reused later without the overhead of + * reallocating it from scratch. + */ + void (*free)(struct AVFilterBuffer *buf); + + int format; ///< media format + int w, h; ///< width and height of the allocated buffer +} AVFilterBuffer; + +#define AV_PERM_READ 0x01 ///< can read from the buffer +#define AV_PERM_WRITE 0x02 ///< can write to the buffer +#define AV_PERM_PRESERVE 0x04 ///< nobody else can overwrite the buffer +#define AV_PERM_REUSE 0x08 ///< can output the buffer multiple times, with the same contents each time +#define AV_PERM_REUSE2 0x10 ///< can output the buffer multiple times, modified each time +#define AV_PERM_NEG_LINESIZES 0x20 ///< the buffer requested can have negative linesizes +#define AV_PERM_ALIGN 0x40 ///< the buffer must be aligned + +#define AVFILTER_ALIGN 16 //not part of ABI + +/** + * Audio specific properties in a reference to an AVFilterBuffer. Since + * AVFilterBufferRef is common to different media formats, audio specific + * per reference properties must be separated out. + */ +typedef struct AVFilterBufferRefAudioProps { + uint64_t channel_layout; ///< channel layout of audio buffer + int nb_samples; ///< number of audio samples per channel + int sample_rate; ///< audio buffer sample rate + int planar; ///< audio buffer - planar or packed +} AVFilterBufferRefAudioProps; + +/** + * Video specific properties in a reference to an AVFilterBuffer. Since + * AVFilterBufferRef is common to different media formats, video specific + * per reference properties must be separated out. + */ +typedef struct AVFilterBufferRefVideoProps { + int w; ///< image width + int h; ///< image height + AVRational sample_aspect_ratio; ///< sample aspect ratio + int interlaced; ///< is frame interlaced + int top_field_first; ///< field order + enum AVPictureType pict_type; ///< picture type of the frame + int key_frame; ///< 1 -> keyframe, 0-> not +} AVFilterBufferRefVideoProps; + +/** + * A reference to an AVFilterBuffer. Since filters can manipulate the origin of + * a buffer to, for example, crop image without any memcpy, the buffer origin + * and dimensions are per-reference properties. Linesize is also useful for + * image flipping, frame to field filters, etc, and so is also per-reference. + * + * TODO: add anything necessary for frame reordering + */ +typedef struct AVFilterBufferRef { + AVFilterBuffer *buf; ///< the buffer that this is a reference to + uint8_t *data[8]; ///< picture/audio data for each plane + int linesize[8]; ///< number of bytes per line + int format; ///< media format + + /** + * presentation timestamp. The time unit may change during + * filtering, as it is specified in the link and the filter code + * may need to rescale the PTS accordingly. + */ + int64_t pts; + int64_t pos; ///< byte position in stream, -1 if unknown + + int perms; ///< permissions, see the AV_PERM_* flags + + enum AVMediaType type; ///< media type of buffer data + AVFilterBufferRefVideoProps *video; ///< video buffer specific properties + AVFilterBufferRefAudioProps *audio; ///< audio buffer specific properties +} AVFilterBufferRef; + +/** + * Copy properties of src to dst, without copying the actual data + */ +static inline void avfilter_copy_buffer_ref_props(AVFilterBufferRef *dst, AVFilterBufferRef *src) +{ + // copy common properties + dst->pts = src->pts; + dst->pos = src->pos; + + switch (src->type) { + case AVMEDIA_TYPE_VIDEO: *dst->video = *src->video; break; + case AVMEDIA_TYPE_AUDIO: *dst->audio = *src->audio; break; + default: break; + } +} + +/** + * Add a new reference to a buffer. + * + * @param ref an existing reference to the buffer + * @param pmask a bitmask containing the allowable permissions in the new + * reference + * @return a new reference to the buffer with the same properties as the + * old, excluding any permissions denied by pmask + */ +AVFilterBufferRef *avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask); + +/** + * Remove a reference to a buffer. If this is the last reference to the + * buffer, the buffer itself is also automatically freed. + * + * @param ref reference to the buffer, may be NULL + */ +void avfilter_unref_buffer(AVFilterBufferRef *ref); + +/** + * A list of supported formats for one end of a filter link. This is used + * during the format negotiation process to try to pick the best format to + * use to minimize the number of necessary conversions. Each filter gives a + * list of the formats supported by each input and output pad. The list + * given for each pad need not be distinct - they may be references to the + * same list of formats, as is often the case when a filter supports multiple + * formats, but will always output the same format as it is given in input. + * + * In this way, a list of possible input formats and a list of possible + * output formats are associated with each link. When a set of formats is + * negotiated over a link, the input and output lists are merged to form a + * new list containing only the common elements of each list. In the case + * that there were no common elements, a format conversion is necessary. + * Otherwise, the lists are merged, and all other links which reference + * either of the format lists involved in the merge are also affected. + * + * For example, consider the filter chain: + * filter (a) --> (b) filter (b) --> (c) filter + * + * where the letters in parenthesis indicate a list of formats supported on + * the input or output of the link. Suppose the lists are as follows: + * (a) = {A, B} + * (b) = {A, B, C} + * (c) = {B, C} + * + * First, the first link's lists are merged, yielding: + * filter (a) --> (a) filter (a) --> (c) filter + * + * Notice that format list (b) now refers to the same list as filter list (a). + * Next, the lists for the second link are merged, yielding: + * filter (a) --> (a) filter (a) --> (a) filter + * + * where (a) = {B}. + * + * Unfortunately, when the format lists at the two ends of a link are merged, + * we must ensure that all links which reference either pre-merge format list + * get updated as well. Therefore, we have the format list structure store a + * pointer to each of the pointers to itself. + */ +typedef struct AVFilterFormats { + unsigned format_count; ///< number of formats + int64_t *formats; ///< list of media formats + + unsigned refcount; ///< number of references to this list + struct AVFilterFormats ***refs; ///< references to this list +} AVFilterFormats; + +/** + * Create a list of supported formats. This is intended for use in + * AVFilter->query_formats(). + * + * @param fmts list of media formats, terminated by -1. If NULL an + * empty list is created. + * @return the format list, with no existing references + */ +AVFilterFormats *avfilter_make_format_list(const int *fmts); +AVFilterFormats *avfilter_make_format64_list(const int64_t *fmts); + +/** + * Add fmt to the list of media formats contained in *avff. + * If *avff is NULL the function allocates the filter formats struct + * and puts its pointer in *avff. + * + * @return a non negative value in case of success, or a negative + * value corresponding to an AVERROR code in case of error + */ +int avfilter_add_format(AVFilterFormats **avff, int64_t fmt); + +#if FF_API_OLD_ALL_FORMATS_API +/** + * @deprecated Use avfilter_make_all_formats() instead. + */ +attribute_deprecated +AVFilterFormats *avfilter_all_formats(enum AVMediaType type); +#endif + +/** + * Return a list of all formats supported by FFmpeg for the given media type. + */ +AVFilterFormats *avfilter_make_all_formats(enum AVMediaType type); + +/** + * A list of all channel layouts supported by libavfilter. + */ +extern const int64_t avfilter_all_channel_layouts[]; + +/** + * Return a list of all channel layouts supported by FFmpeg. + */ +AVFilterFormats *avfilter_make_all_channel_layouts(void); + +/** + * Return a list of all audio packing formats. + */ +AVFilterFormats *avfilter_make_all_packing_formats(void); + +/** + * Return a format list which contains the intersection of the formats of + * a and b. Also, all the references of a, all the references of b, and + * a and b themselves will be deallocated. + * + * If a and b do not share any common formats, neither is modified, and NULL + * is returned. + */ +AVFilterFormats *avfilter_merge_formats(AVFilterFormats *a, AVFilterFormats *b); + +/** + * Add *ref as a new reference to formats. + * That is the pointers will point like in the ASCII art below: + * ________ + * |formats |<--------. + * | ____ | ____|___________________ + * | |refs| | | __|_ + * | |* * | | | | | | AVFilterLink + * | |* *--------->|*ref| + * | |____| | | |____| + * |________| |________________________ + */ +void avfilter_formats_ref(AVFilterFormats *formats, AVFilterFormats **ref); + +/** + * If *ref is non-NULL, remove *ref as a reference to the format list + * it currently points to, deallocates that list if this was the last + * reference, and sets *ref to NULL. + * + * Before After + * ________ ________ NULL + * |formats |<--------. |formats | ^ + * | ____ | ____|________________ | ____ | ____|________________ + * | |refs| | | __|_ | |refs| | | __|_ + * | |* * | | | | | | AVFilterLink | |* * | | | | | | AVFilterLink + * | |* *--------->|*ref| | |* | | | |*ref| + * | |____| | | |____| | |____| | | |____| + * |________| |_____________________ |________| |_____________________ + */ +void avfilter_formats_unref(AVFilterFormats **ref); + +/** + * + * Before After + * ________ ________ + * |formats |<---------. |formats |<---------. + * | ____ | ___|___ | ____ | ___|___ + * | |refs| | | | | | |refs| | | | | NULL + * | |* *--------->|*oldref| | |* *--------->|*newref| ^ + * | |* * | | |_______| | |* * | | |_______| ___|___ + * | |____| | | |____| | | | | + * |________| |________| |*oldref| + * |_______| + */ +void avfilter_formats_changeref(AVFilterFormats **oldref, + AVFilterFormats **newref); + +/** + * A filter pad used for either input or output. + */ +struct AVFilterPad { + /** + * Pad name. The name is unique among inputs and among outputs, but an + * input may have the same name as an output. This may be NULL if this + * pad has no need to ever be referenced by name. + */ + const char *name; + + /** + * AVFilterPad type. Can be AVMEDIA_TYPE_VIDEO or AVMEDIA_TYPE_AUDIO. + */ + enum AVMediaType type; + + /** + * Minimum required permissions on incoming buffers. Any buffer with + * insufficient permissions will be automatically copied by the filter + * system to a new buffer which provides the needed access permissions. + * + * Input pads only. + */ + int min_perms; + + /** + * Permissions which are not accepted on incoming buffers. Any buffer + * which has any of these permissions set will be automatically copied + * by the filter system to a new buffer which does not have those + * permissions. This can be used to easily disallow buffers with + * AV_PERM_REUSE. + * + * Input pads only. + */ + int rej_perms; + + /** + * Callback called before passing the first slice of a new frame. If + * NULL, the filter layer will default to storing a reference to the + * picture inside the link structure. + * + * Input video pads only. + */ + void (*start_frame)(AVFilterLink *link, AVFilterBufferRef *picref); + + /** + * Callback function to get a video buffer. If NULL, the filter system will + * use avfilter_default_get_video_buffer(). + * + * Input video pads only. + */ + AVFilterBufferRef *(*get_video_buffer)(AVFilterLink *link, int perms, int w, int h); + + /** + * Callback function to get an audio buffer. If NULL, the filter system will + * use avfilter_default_get_audio_buffer(). + * + * Input audio pads only. + */ + AVFilterBufferRef *(*get_audio_buffer)(AVFilterLink *link, int perms, int nb_samples); + + /** + * Callback called after the slices of a frame are completely sent. If + * NULL, the filter layer will default to releasing the reference stored + * in the link structure during start_frame(). + * + * Input video pads only. + */ + void (*end_frame)(AVFilterLink *link); + + /** + * Slice drawing callback. This is where a filter receives video data + * and should do its processing. + * + * Input video pads only. + */ + void (*draw_slice)(AVFilterLink *link, int y, int height, int slice_dir); + + /** + * Samples filtering callback. This is where a filter receives audio data + * and should do its processing. + * + * Input audio pads only. + */ + void (*filter_samples)(AVFilterLink *link, AVFilterBufferRef *samplesref); + + /** + * Frame poll callback. This returns the number of immediately available + * samples. It should return a positive value if the next request_frame() + * is guaranteed to return one frame (with no delay). + * + * Defaults to just calling the source poll_frame() method. + * + * Output video pads only. + */ + int (*poll_frame)(AVFilterLink *link); + + /** + * Frame request callback. A call to this should result in at least one + * frame being output over the given link. This should return zero on + * success, and another value on error. + * + * Output video pads only. + */ + int (*request_frame)(AVFilterLink *link); + + /** + * Link configuration callback. + * + * For output pads, this should set the following link properties: + * video: width, height, sample_aspect_ratio, time_base + * audio: sample_rate. + * + * This should NOT set properties such as format, channel_layout, etc which + * are negotiated between filters by the filter system using the + * query_formats() callback before this function is called. + * + * For input pads, this should check the properties of the link, and update + * the filter's internal state as necessary. + * + * For both input and output pads, this should return zero on success, + * and another value on error. + */ + int (*config_props)(AVFilterLink *link); +}; + +/** default handler for start_frame() for video inputs */ +void avfilter_default_start_frame(AVFilterLink *link, AVFilterBufferRef *picref); + +/** default handler for draw_slice() for video inputs */ +void avfilter_default_draw_slice(AVFilterLink *link, int y, int h, int slice_dir); + +/** default handler for end_frame() for video inputs */ +void avfilter_default_end_frame(AVFilterLink *link); + +/** default handler for filter_samples() for audio inputs */ +void avfilter_default_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref); + +/** default handler for get_video_buffer() for video inputs */ +AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link, + int perms, int w, int h); + +/** default handler for get_audio_buffer() for audio inputs */ +AVFilterBufferRef *avfilter_default_get_audio_buffer(AVFilterLink *link, + int perms, int nb_samples); + +/** + * Helpers for query_formats() which set all links to the same list of + * formats/layouts. If there are no links hooked to this filter, the list + * of formats is freed. + */ +void avfilter_set_common_pixel_formats(AVFilterContext *ctx, AVFilterFormats *formats); +void avfilter_set_common_sample_formats(AVFilterContext *ctx, AVFilterFormats *formats); +void avfilter_set_common_channel_layouts(AVFilterContext *ctx, AVFilterFormats *formats); +void avfilter_set_common_packing_formats(AVFilterContext *ctx, AVFilterFormats *formats); + +/** Default handler for query_formats() */ +int avfilter_default_query_formats(AVFilterContext *ctx); + +/** start_frame() handler for filters which simply pass video along */ +void avfilter_null_start_frame(AVFilterLink *link, AVFilterBufferRef *picref); + +/** draw_slice() handler for filters which simply pass video along */ +void avfilter_null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir); + +/** end_frame() handler for filters which simply pass video along */ +void avfilter_null_end_frame(AVFilterLink *link); + +/** filter_samples() handler for filters which simply pass audio along */ +void avfilter_null_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref); + +/** get_video_buffer() handler for filters which simply pass video along */ +AVFilterBufferRef *avfilter_null_get_video_buffer(AVFilterLink *link, + int perms, int w, int h); + +/** get_audio_buffer() handler for filters which simply pass audio along */ +AVFilterBufferRef *avfilter_null_get_audio_buffer(AVFilterLink *link, + int perms, int nb_samples); + +/** + * Filter definition. This defines the pads a filter contains, and all the + * callback functions used to interact with the filter. + */ +typedef struct AVFilter { + const char *name; ///< filter name + + int priv_size; ///< size of private data to allocate for the filter + + /** + * Filter initialization function. Args contains the user-supplied + * parameters. FIXME: maybe an AVOption-based system would be better? + * opaque is data provided by the code requesting creation of the filter, + * and is used to pass data to the filter. + */ + int (*init)(AVFilterContext *ctx, const char *args, void *opaque); + + /** + * Filter uninitialization function. Should deallocate any memory held + * by the filter, release any buffer references, etc. This does not need + * to deallocate the AVFilterContext->priv memory itself. + */ + void (*uninit)(AVFilterContext *ctx); + + /** + * Queries formats/layouts supported by the filter and its pads, and sets + * the in_formats/in_chlayouts for links connected to its output pads, + * and out_formats/out_chlayouts for links connected to its input pads. + * + * @return zero on success, a negative value corresponding to an + * AVERROR code otherwise + */ + int (*query_formats)(AVFilterContext *); + + const AVFilterPad *inputs; ///< NULL terminated list of inputs. NULL if none + const AVFilterPad *outputs; ///< NULL terminated list of outputs. NULL if none + + /** + * A description for the filter. You should use the + * NULL_IF_CONFIG_SMALL() macro to define it. + */ + const char *description; + + /** + * Make the filter instance process a command. + * + * @param cmd the command to process, for handling simplicity all commands must be alphanumeric only + * @param arg the argument for the command + * @param res a buffer with size res_size where the filter(s) can return a response. This must not change when the command is not supported. + * @param flags if AVFILTER_CMD_FLAG_FAST is set and the command would be + * time consuming then a filter should treat it like an unsupported command + * + * @returns >=0 on success otherwise an error code. + * AVERROR(ENOSYS) on unsupported commands + */ + int (*process_command)(AVFilterContext *, const char *cmd, const char *arg, char *res, int res_len, int flags); +} AVFilter; + +/** An instance of a filter */ +struct AVFilterContext { + const AVClass *av_class; ///< needed for av_log() + + AVFilter *filter; ///< the AVFilter of which this is an instance + + char *name; ///< name of this filter instance + + unsigned input_count; ///< number of input pads + AVFilterPad *input_pads; ///< array of input pads + AVFilterLink **inputs; ///< array of pointers to input links + + unsigned output_count; ///< number of output pads + AVFilterPad *output_pads; ///< array of output pads + AVFilterLink **outputs; ///< array of pointers to output links + + void *priv; ///< private data for use by the filter + + struct AVFilterCommand *command_queue; +}; + +enum AVFilterPacking { + AVFILTER_PACKED = 0, + AVFILTER_PLANAR, +}; + +/** + * A link between two filters. This contains pointers to the source and + * destination filters between which this link exists, and the indexes of + * the pads involved. In addition, this link also contains the parameters + * which have been negotiated and agreed upon between the filter, such as + * image dimensions, format, etc. + */ +struct AVFilterLink { + AVFilterContext *src; ///< source filter + AVFilterPad *srcpad; ///< output pad on the source filter + + AVFilterContext *dst; ///< dest filter + AVFilterPad *dstpad; ///< input pad on the dest filter + + /** stage of the initialization of the link properties (dimensions, etc) */ + enum { + AVLINK_UNINIT = 0, ///< not started + AVLINK_STARTINIT, ///< started, but incomplete + AVLINK_INIT ///< complete + } init_state; + + enum AVMediaType type; ///< filter media type + + /* These parameters apply only to video */ + int w; ///< agreed upon image width + int h; ///< agreed upon image height + AVRational sample_aspect_ratio; ///< agreed upon sample aspect ratio + /* These parameters apply only to audio */ + uint64_t channel_layout; ///< channel layout of current buffer (see libavutil/audioconvert.h) +#if LIBAVFILTER_VERSION_MAJOR < 3 + int64_t sample_rate; ///< samples per second +#else + int sample_rate; ///< samples per second +#endif + int planar; ///< agreed upon packing mode of audio buffers. true if planar. + + int format; ///< agreed upon media format + + /** + * Lists of formats and channel layouts supported by the input and output + * filters respectively. These lists are used for negotiating the format + * to actually be used, which will be loaded into the format and + * channel_layout members, above, when chosen. + * + */ + AVFilterFormats *in_formats; + AVFilterFormats *out_formats; + + AVFilterFormats *in_chlayouts; + AVFilterFormats *out_chlayouts; + AVFilterFormats *in_packing; + AVFilterFormats *out_packing; + + /** + * The buffer reference currently being sent across the link by the source + * filter. This is used internally by the filter system to allow + * automatic copying of buffers which do not have sufficient permissions + * for the destination. This should not be accessed directly by the + * filters. + */ + AVFilterBufferRef *src_buf; + + AVFilterBufferRef *cur_buf; + AVFilterBufferRef *out_buf; + + /** + * Define the time base used by the PTS of the frames/samples + * which will pass through this link. + * During the configuration stage, each filter is supposed to + * change only the output timebase, while the timebase of the + * input link is assumed to be an unchangeable property. + */ + AVRational time_base; + + struct AVFilterPool *pool; +}; + +/** + * Link two filters together. + * + * @param src the source filter + * @param srcpad index of the output pad on the source filter + * @param dst the destination filter + * @param dstpad index of the input pad on the destination filter + * @return zero on success + */ +int avfilter_link(AVFilterContext *src, unsigned srcpad, + AVFilterContext *dst, unsigned dstpad); + +/** + * Free the link in *link, and set its pointer to NULL. + */ +void avfilter_link_free(AVFilterLink **link); + +/** + * Negotiate the media format, dimensions, etc of all inputs to a filter. + * + * @param filter the filter to negotiate the properties for its inputs + * @return zero on successful negotiation + */ +int avfilter_config_links(AVFilterContext *filter); + +/** + * Request a picture buffer with a specific set of permissions. + * + * @param link the output link to the filter from which the buffer will + * be requested + * @param perms the required access permissions + * @param w the minimum width of the buffer to allocate + * @param h the minimum height of the buffer to allocate + * @return A reference to the buffer. This must be unreferenced with + * avfilter_unref_buffer when you are finished with it. + */ +AVFilterBufferRef *avfilter_get_video_buffer(AVFilterLink *link, int perms, + int w, int h); + +/** + * Create a buffer reference wrapped around an already allocated image + * buffer. + * + * @param data pointers to the planes of the image to reference + * @param linesize linesizes for the planes of the image to reference + * @param perms the required access permissions + * @param w the width of the image specified by the data and linesize arrays + * @param h the height of the image specified by the data and linesize arrays + * @param format the pixel format of the image specified by the data and linesize arrays + */ +AVFilterBufferRef * +avfilter_get_video_buffer_ref_from_arrays(uint8_t * const data[4], const int linesize[4], int perms, + int w, int h, enum PixelFormat format); + +/** + * Request an audio samples buffer with a specific set of permissions. + * + * @param link the output link to the filter from which the buffer will + * be requested + * @param perms the required access permissions + * @param nb_samples the number of samples per channel + * @return A reference to the samples. This must be unreferenced with + * avfilter_unref_buffer when you are finished with it. + */ +AVFilterBufferRef *avfilter_get_audio_buffer(AVFilterLink *link, int perms, + int nb_samples); + +/** + * Create an audio buffer reference wrapped around an already + * allocated samples buffer. + * + * @param data pointers to the samples plane buffers + * @param linesize linesize for the samples plane buffers + * @param perms the required access permissions + * @param nb_samples number of samples per channel + * @param sample_fmt the format of each sample in the buffer to allocate + * @param channel_layout the channel layout of the buffer + * @param planar audio data layout - planar or packed + */ +AVFilterBufferRef * +avfilter_get_audio_buffer_ref_from_arrays(uint8_t *data[8], int linesize[8], int perms, + int nb_samples, enum AVSampleFormat sample_fmt, + uint64_t channel_layout, int planar); +/** + * Request an input frame from the filter at the other end of the link. + * + * @param link the input link + * @return zero on success + */ +int avfilter_request_frame(AVFilterLink *link); + +/** + * Poll a frame from the filter chain. + * + * @param link the input link + * @return the number of immediately available frames, a negative + * number in case of error + */ +int avfilter_poll_frame(AVFilterLink *link); + +/** + * Notify the next filter of the start of a frame. + * + * @param link the output link the frame will be sent over + * @param picref A reference to the frame about to be sent. The data for this + * frame need only be valid once draw_slice() is called for that + * portion. The receiving filter will free this reference when + * it no longer needs it. + */ +void avfilter_start_frame(AVFilterLink *link, AVFilterBufferRef *picref); + +/** + * Notify the next filter that the current frame has finished. + * + * @param link the output link the frame was sent over + */ +void avfilter_end_frame(AVFilterLink *link); + +/** + * Send a slice to the next filter. + * + * Slices have to be provided in sequential order, either in + * top-bottom or bottom-top order. If slices are provided in + * non-sequential order the behavior of the function is undefined. + * + * @param link the output link over which the frame is being sent + * @param y offset in pixels from the top of the image for this slice + * @param h height of this slice in pixels + * @param slice_dir the assumed direction for sending slices, + * from the top slice to the bottom slice if the value is 1, + * from the bottom slice to the top slice if the value is -1, + * for other values the behavior of the function is undefined. + */ +void avfilter_draw_slice(AVFilterLink *link, int y, int h, int slice_dir); + +#define AVFILTER_CMD_FLAG_ONE 1 ///< Stop once a filter understood the command (for target=all for example), fast filters are favored automatically +#define AVFILTER_CMD_FLAG_FAST 2 ///< Only execute command when its fast (like a video out that supports contrast adjustment in hw) + +/** + * Make the filter instance process a command. + * It is recommended to use avfilter_graph_send_command(). + */ +int avfilter_process_command(AVFilterContext *filter, const char *cmd, const char *arg, char *res, int res_len, int flags); + +/** + * Send a buffer of audio samples to the next filter. + * + * @param link the output link over which the audio samples are being sent + * @param samplesref a reference to the buffer of audio samples being sent. The + * receiving filter will free this reference when it no longer + * needs it or pass it on to the next filter. + */ +void avfilter_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref); + +/** Initialize the filter system. Register all built-in filters. */ +void avfilter_register_all(void); + +/** Uninitialize the filter system. Unregister all filters. */ +void avfilter_uninit(void); + +/** + * Register a filter. This is only needed if you plan to use + * avfilter_get_by_name later to lookup the AVFilter structure by name. A + * filter can still by instantiated with avfilter_open even if it is not + * registered. + * + * @param filter the filter to register + * @return 0 if the registration was successful, a negative value + * otherwise + */ +int avfilter_register(AVFilter *filter); + +/** + * Get a filter definition matching the given name. + * + * @param name the filter name to find + * @return the filter definition, if any matching one is registered. + * NULL if none found. + */ +AVFilter *avfilter_get_by_name(const char *name); + +/** + * If filter is NULL, returns a pointer to the first registered filter pointer, + * if filter is non-NULL, returns the next pointer after filter. + * If the returned pointer points to NULL, the last registered filter + * was already reached. + */ +AVFilter **av_filter_next(AVFilter **filter); + +/** + * Create a filter instance. + * + * @param filter_ctx put here a pointer to the created filter context + * on success, NULL on failure + * @param filter the filter to create an instance of + * @param inst_name Name to give to the new instance. Can be NULL for none. + * @return >= 0 in case of success, a negative error code otherwise + */ +int avfilter_open(AVFilterContext **filter_ctx, AVFilter *filter, const char *inst_name); + +/** + * Initialize a filter. + * + * @param filter the filter to initialize + * @param args A string of parameters to use when initializing the filter. + * The format and meaning of this string varies by filter. + * @param opaque Any extra non-string data needed by the filter. The meaning + * of this parameter varies by filter. + * @return zero on success + */ +int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque); + +/** + * Free a filter context. + * + * @param filter the filter to free + */ +void avfilter_free(AVFilterContext *filter); + +/** + * Insert a filter in the middle of an existing link. + * + * @param link the link into which the filter should be inserted + * @param filt the filter to be inserted + * @param filt_srcpad_idx the input pad on the filter to connect + * @param filt_dstpad_idx the output pad on the filter to connect + * @return zero on success + */ +int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt, + unsigned filt_srcpad_idx, unsigned filt_dstpad_idx); + +/** + * Insert a new pad. + * + * @param idx Insertion point. Pad is inserted at the end if this point + * is beyond the end of the list of pads. + * @param count Pointer to the number of pads in the list + * @param padidx_off Offset within an AVFilterLink structure to the element + * to increment when inserting a new pad causes link + * numbering to change + * @param pads Pointer to the pointer to the beginning of the list of pads + * @param links Pointer to the pointer to the beginning of the list of links + * @param newpad The new pad to add. A copy is made when adding. + */ +void avfilter_insert_pad(unsigned idx, unsigned *count, size_t padidx_off, + AVFilterPad **pads, AVFilterLink ***links, + AVFilterPad *newpad); + +/** Insert a new input pad for the filter. */ +static inline void avfilter_insert_inpad(AVFilterContext *f, unsigned index, + AVFilterPad *p) +{ + avfilter_insert_pad(index, &f->input_count, offsetof(AVFilterLink, dstpad), + &f->input_pads, &f->inputs, p); +} + +/** Insert a new output pad for the filter. */ +static inline void avfilter_insert_outpad(AVFilterContext *f, unsigned index, + AVFilterPad *p) +{ + avfilter_insert_pad(index, &f->output_count, offsetof(AVFilterLink, srcpad), + &f->output_pads, &f->outputs, p); +} + +#endif /* AVFILTER_AVFILTER_H */ diff --git a/Externals/ffmpeg/include/libavfilter/avfiltergraph.h b/Externals/ffmpeg/include/libavfilter/avfiltergraph.h new file mode 100644 index 0000000000..375ab8efb --- /dev/null +++ b/Externals/ffmpeg/include/libavfilter/avfiltergraph.h @@ -0,0 +1,184 @@ +/* + * Filter graphs + * copyright (c) 2007 Bobby Bingham + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFILTER_AVFILTERGRAPH_H +#define AVFILTER_AVFILTERGRAPH_H + +#include "avfilter.h" + +typedef struct AVFilterGraph { + unsigned filter_count; + AVFilterContext **filters; + + char *scale_sws_opts; ///< sws options to use for the auto-inserted scale filters +} AVFilterGraph; + +/** + * Allocate a filter graph. + */ +AVFilterGraph *avfilter_graph_alloc(void); + +/** + * Get a filter instance with name name from graph. + * + * @return the pointer to the found filter instance or NULL if it + * cannot be found. + */ +AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, char *name); + +/** + * Add an existing filter instance to a filter graph. + * + * @param graphctx the filter graph + * @param filter the filter to be added + */ +int avfilter_graph_add_filter(AVFilterGraph *graphctx, AVFilterContext *filter); + +/** + * Create and add a filter instance into an existing graph. + * The filter instance is created from the filter filt and inited + * with the parameters args and opaque. + * + * In case of success put in *filt_ctx the pointer to the created + * filter instance, otherwise set *filt_ctx to NULL. + * + * @param name the instance name to give to the created filter instance + * @param graph_ctx the filter graph + * @return a negative AVERROR error code in case of failure, a non + * negative value otherwise + */ +int avfilter_graph_create_filter(AVFilterContext **filt_ctx, AVFilter *filt, + const char *name, const char *args, void *opaque, + AVFilterGraph *graph_ctx); + +/** + * Check validity and configure all the links and formats in the graph. + * + * @param graphctx the filter graph + * @param log_ctx context used for logging + * @return 0 in case of success, a negative AVERROR code otherwise + */ +int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx); + +/** + * Free a graph, destroy its links, and set *graph to NULL. + * If *graph is NULL, do nothing. + */ +void avfilter_graph_free(AVFilterGraph **graph); + +/** + * A linked-list of the inputs/outputs of the filter chain. + * + * This is mainly useful for avfilter_graph_parse(), since this + * function may accept a description of a graph with not connected + * input/output pads. This struct specifies, per each not connected + * pad contained in the graph, the filter context and the pad index + * required for establishing a link. + */ +typedef struct AVFilterInOut { + /** unique name for this input/output in the list */ + char *name; + + /** filter context associated to this input/output */ + AVFilterContext *filter_ctx; + + /** index of the filt_ctx pad to use for linking */ + int pad_idx; + + /** next input/input in the list, NULL if this is the last */ + struct AVFilterInOut *next; +} AVFilterInOut; + +/** + * Create an AVFilterInOut. + * Must be free with avfilter_inout_free(). + */ +AVFilterInOut *avfilter_inout_alloc(void); + +/** + * Free the AVFilterInOut in *inout, and set its pointer to NULL. + * If *inout is NULL, do nothing. + */ +void avfilter_inout_free(AVFilterInOut **inout); + +/** + * Add a graph described by a string to a graph. + * + * @param graph the filter graph where to link the parsed graph context + * @param filters string to be parsed + * @param inputs pointer to a linked list to the inputs of the graph, may be NULL. + * If non-NULL, *inputs is updated to contain the list of open inputs + * after the parsing, should be freed with avfilter_inout_free(). + * @param outputs pointer to a linked list to the outputs of the graph, may be NULL. + * If non-NULL, *outputs is updated to contain the list of open outputs + * after the parsing, should be freed with avfilter_inout_free(). + * @return non negative on success, a negative AVERROR code on error + */ +int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, + AVFilterInOut **inputs, AVFilterInOut **outputs, + void *log_ctx); + +/** + * Send a command to one or more filter instances. + * + * @param graph the filter graph + * @param target the filter(s) to which the command should be sent + * "all" sends to all filters + * otherwise it can be a filter or filter instance name + * which will send the command to all matching filters. + * @param cmd the command to sent, for handling simplicity all commands must be alphanumeric only + * @param arg the argument for the command + * @param res a buffer with size res_size where the filter(s) can return a response. + * + * @returns >=0 on success otherwise an error code. + * AVERROR(ENOSYS) on unsupported commands + */ +int avfilter_graph_send_command(AVFilterGraph *graph, const char *target, const char *cmd, const char *arg, char *res, int res_len, int flags); + +/** + * Queue a command for one or more filter instances. + * + * @param graph the filter graph + * @param target the filter(s) to which the command should be sent + * "all" sends to all filters + * otherwise it can be a filter or filter instance name + * which will send the command to all matching filters. + * @param cmd the command to sent, for handling simplicity all commands must be alphanummeric only + * @param arg the argument for the command + * @param ts time at which the command should be sent to the filter + * + * @note As this executes commands after this function returns, no return code + * from the filter is provided, also AVFILTER_CMD_FLAG_ONE is not supported. + */ +int avfilter_graph_queue_command(AVFilterGraph *graph, const char *target, const char *cmd, const char *arg, int flags, double ts); + + +/** + * Dump a graph into a human-readable string representation. + * + * @param graph the graph to dump + * @param options formatting options; currently ignored + * @return a string, or NULL in case of memory allocation failure; + * the string must be freed using av_free + */ +char *avfilter_graph_dump(AVFilterGraph *graph, const char *options); + +#endif /* AVFILTER_AVFILTERGRAPH_H */ diff --git a/Externals/ffmpeg/include/libavfilter/buffersink.h b/Externals/ffmpeg/include/libavfilter/buffersink.h new file mode 100644 index 0000000000..73926a453 --- /dev/null +++ b/Externals/ffmpeg/include/libavfilter/buffersink.h @@ -0,0 +1,94 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFILTER_VSINK_BUFFER_H +#define AVFILTER_VSINK_BUFFER_H + +/** + * @file + * memory buffer sink API for audio and video + */ + +#include "avfilter.h" + +/** + * Struct to use for initializing a buffersink context. + */ +typedef struct { + const enum PixelFormat *pixel_fmts; ///< list of allowed pixel formats, terminated by PIX_FMT_NONE +} AVBufferSinkParams; + +/** + * Create an AVBufferSinkParams structure. + * + * Must be freed with av_free(). + */ +AVBufferSinkParams *av_buffersink_params_alloc(void); + +/** + * Struct to use for initializing an abuffersink context. + */ +typedef struct { + const enum AVSampleFormat *sample_fmts; ///< list of allowed sample formats, terminated by AV_SAMPLE_FMT_NONE + const int64_t *channel_layouts; ///< list of allowed channel layouts, terminated by -1 + const int *packing_fmts; ///< list of allowed packing formats +} AVABufferSinkParams; + +/** + * Create an AVABufferSinkParams structure. + * + * Must be freed with av_free(). + */ +AVABufferSinkParams *av_abuffersink_params_alloc(void); + +/** + * Tell av_buffersink_get_buffer_ref() to read video/samples buffer + * reference, but not remove it from the buffer. This is useful if you + * need only to read a video/samples buffer, without to fetch it. + */ +#define AV_BUFFERSINK_FLAG_PEEK 1 + +/** + * Get an audio/video buffer data from buffer_sink and put it in bufref. + * + * This function works with both audio and video buffer sinks. + * + * @param buffer_sink pointer to a buffersink or abuffersink context + * @param flags a combination of AV_BUFFERSINK_FLAG_* flags + * @return >= 0 in case of success, a negative AVERROR code in case of + * failure + */ +int av_buffersink_get_buffer_ref(AVFilterContext *buffer_sink, + AVFilterBufferRef **bufref, int flags); + + +/** + * Get the number of immediately available frames. + */ +int av_buffersink_poll_frame(AVFilterContext *ctx); + +#if FF_API_OLD_VSINK_API +/** + * @deprecated Use av_buffersink_get_buffer_ref() instead. + */ +attribute_deprecated +int av_vsink_buffer_get_video_buffer_ref(AVFilterContext *buffer_sink, + AVFilterBufferRef **picref, int flags); +#endif + +#endif /* AVFILTER_VSINK_BUFFER_H */ diff --git a/Externals/ffmpeg/include/libavfilter/version.h b/Externals/ffmpeg/include/libavfilter/version.h new file mode 100644 index 0000000000..60e496dcc --- /dev/null +++ b/Externals/ffmpeg/include/libavfilter/version.h @@ -0,0 +1,43 @@ +/* + * Version macros. + * + * This file is part of Libav. + * + * Libav 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. + * + * Libav 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 Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFILTER_VERSION_H +#define AVFILTER_VERSION_H + +/** + * @file + * Libavfilter version macros + */ + +#include "libavutil/avutil.h" + +#define LIBAVFILTER_VERSION_MAJOR 2 +#define LIBAVFILTER_VERSION_MINOR 60 +#define LIBAVFILTER_VERSION_MICRO 100 + +#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ + LIBAVFILTER_VERSION_MINOR, \ + LIBAVFILTER_VERSION_MICRO) +#define LIBAVFILTER_VERSION AV_VERSION(LIBAVFILTER_VERSION_MAJOR, \ + LIBAVFILTER_VERSION_MINOR, \ + LIBAVFILTER_VERSION_MICRO) +#define LIBAVFILTER_BUILD LIBAVFILTER_VERSION_INT + +#endif // AVFILTER_VERSION_H diff --git a/Externals/ffmpeg/include/libavfilter/vsrc_buffer.h b/Externals/ffmpeg/include/libavfilter/vsrc_buffer.h new file mode 100644 index 0000000000..b661d414e --- /dev/null +++ b/Externals/ffmpeg/include/libavfilter/vsrc_buffer.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2008 Vitor Sessak + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFILTER_VSRC_BUFFER_H +#define AVFILTER_VSRC_BUFFER_H + +/** + * @file + * memory buffer source API for video + */ + +#include "avfilter.h" + +/** + * Tell av_vsrc_buffer_add_video_buffer_ref() to overwrite the already + * cached video buffer with the new added one, otherwise the function + * will complain and exit. + */ +#define AV_VSRC_BUF_FLAG_OVERWRITE 1 + +/** + * Add video buffer data in picref to buffer_src. + * + * @param buffer_src pointer to a buffer source context + * @param flags a combination of AV_VSRC_BUF_FLAG_* flags + * @return >= 0 in case of success, a negative AVERROR code in case of + * failure + */ +int av_vsrc_buffer_add_video_buffer_ref(AVFilterContext *buffer_src, + AVFilterBufferRef *picref, int flags); + +#endif /* AVFILTER_VSRC_BUFFER_H */ diff --git a/Externals/ffmpeg/include/libavformat/avformat.h b/Externals/ffmpeg/include/libavformat/avformat.h new file mode 100644 index 0000000000..c28d1ddb2 --- /dev/null +++ b/Externals/ffmpeg/include/libavformat/avformat.h @@ -0,0 +1,2154 @@ +/* + * copyright (c) 2001 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_AVFORMAT_H +#define AVFORMAT_AVFORMAT_H + +/** + * @file + * @ingroup libavf + * Main libavformat public API header + */ + +/** + * @defgroup libavf I/O and Muxing/Demuxing Library + * @{ + * + * Libavformat (lavf) is a library for dealing with various media container + * formats. Its main two purposes are demuxing - i.e. splitting a media file + * into component streams, and the reverse process of muxing - writing supplied + * data in a specified container format. It also has an @ref lavf_io + * "I/O module" which supports a number of protocols for accessing the data (e.g. + * file, tcp, http and others). Before using lavf, you need to call + * av_register_all() to register all compiled muxers, demuxers and protocols. + * Unless you are absolutely sure you won't use libavformat's network + * capabilities, you should also call avformat_network_init(). + * + * A supported input format is described by an AVInputFormat struct, conversely + * an output format is described by AVOutputFormat. You can iterate over all + * registered input/output formats using the av_iformat_next() / + * av_oformat_next() functions. The protocols layer is not part of the public + * API, so you can only get the names of supported protocols with the + * avio_enum_protocols() function. + * + * Main lavf structure used for both muxing and demuxing is AVFormatContext, + * which exports all information about the file being read or written. As with + * most Libav structures, its size is not part of public ABI, so it cannot be + * allocated on stack or directly with av_malloc(). To create an + * AVFormatContext, use avformat_alloc_context() (some functions, like + * avformat_open_input() might do that for you). + * + * Most importantly an AVFormatContext contains: + * @li the @ref AVFormatContext.iformat "input" or @ref AVFormatContext.oformat + * "output" format. It is either autodetected or set by user for input; + * always set by user for output. + * @li an @ref AVFormatContext.streams "array" of AVStreams, which describe all + * elementary streams stored in the file. AVStreams are typically referred to + * using their index in this array. + * @li an @ref AVFormatContext.pb "I/O context". It is either opened by lavf or + * set by user for input, always set by user for output (unless you are dealing + * with an AVFMT_NOFILE format). + * + * @defgroup lavf_decoding Demuxing + * @{ + * Demuxers read a media file and split it into chunks of data (@em packets). A + * @ref AVPacket "packet" contains one or more frames which belong a single + * elementary stream. In lavf API this process is represented by the + * avformat_open_input() function for opening a file, av_read_frame() for + * reading a single packet and finally avformat_close_input(), which does the + * cleanup. + * + * @section lavf_decoding_open Opening a media file + * The minimum information required to open a file is its URL or filename, which + * is passed to avformat_open_input(), as in the following code: + * @code + * const char *url = "in.mp3"; + * AVFormatContext *s = NULL; + * int ret = avformat_open_input(&s, url, NULL, NULL); + * if (ret < 0) + * abort(); + * @endcode + * The above code attempts to allocate an AVFormatContext, open the + * specified file (autodetecting the format) and read the header, exporting the + * information stored there into s. Some formats do not have a header or do not + * store enough information there, so it is recommended that you call the + * avformat_find_stream_info() function which tries to read and decode a few + * frames to find missing information. + * + * In some cases you might want to preallocate an AVFormatContext yourself with + * avformat_alloc_context() and do some tweaking on it before passing it to + * avformat_open_input(). One such case is when you want to use custom functions + * for reading input data instead of lavf internal I/O layer. + * To do that, create your own AVIOContext with avio_alloc_context(), passing + * your reading callbacks to it. Then set the @em pb field of your + * AVFormatContext to newly created AVIOContext. + * + * After you have finished reading the file, you must close it with + * avformat_close_input(). It will free everything associated with the file. + * + * @section lavf_decoding_read Reading from an opened file + * + * @section lavf_decoding_seek Seeking + * @} + * + * @defgroup lavf_encoding Muxing + * @{ + * @} + * + * @defgroup lavf_io I/O Read/Write + * @{ + * @} + * + * @defgroup lavf_codec Demuxers + * @{ + * @defgroup lavf_codec_native Native Demuxers + * @{ + * @} + * @defgroup lavf_codec_wrappers External library wrappers + * @{ + * @} + * @} + * @defgroup lavf_protos I/O Protocols + * @{ + * @} + * @defgroup lavf_internal Internal + * @{ + * @} + * @} + * + */ + +#include +#include /* FILE */ +#include "libavcodec/avcodec.h" +#include "libavutil/dict.h" +#include "libavutil/log.h" + +#include "avio.h" +#include "libavformat/version.h" + +struct AVFormatContext; + + +/** + * @defgroup metadata_api Public Metadata API + * @{ + * @ingroup libavf + * The metadata API allows libavformat to export metadata tags to a client + * application when demuxing. Conversely it allows a client application to + * set metadata when muxing. + * + * Metadata is exported or set as pairs of key/value strings in the 'metadata' + * fields of the AVFormatContext, AVStream, AVChapter and AVProgram structs + * using the @ref lavu_dict "AVDictionary" API. Like all strings in FFmpeg, + * metadata is assumed to be UTF-8 encoded Unicode. Note that metadata + * exported by demuxers isn't checked to be valid UTF-8 in most cases. + * + * Important concepts to keep in mind: + * - Keys are unique; there can never be 2 tags with the same key. This is + * also meant semantically, i.e., a demuxer should not knowingly produce + * several keys that are literally different but semantically identical. + * E.g., key=Author5, key=Author6. In this example, all authors must be + * placed in the same tag. + * - Metadata is flat, not hierarchical; there are no subtags. If you + * want to store, e.g., the email address of the child of producer Alice + * and actor Bob, that could have key=alice_and_bobs_childs_email_address. + * - Several modifiers can be applied to the tag name. This is done by + * appending a dash character ('-') and the modifier name in the order + * they appear in the list below -- e.g. foo-eng-sort, not foo-sort-eng. + * - language -- a tag whose value is localized for a particular language + * is appended with the ISO 639-2/B 3-letter language code. + * For example: Author-ger=Michael, Author-eng=Mike + * The original/default language is in the unqualified "Author" tag. + * A demuxer should set a default if it sets any translated tag. + * - sorting -- a modified version of a tag that should be used for + * sorting will have '-sort' appended. E.g. artist="The Beatles", + * artist-sort="Beatles, The". + * + * - Demuxers attempt to export metadata in a generic format, however tags + * with no generic equivalents are left as they are stored in the container. + * Follows a list of generic tag names: + * + @verbatim + album -- name of the set this work belongs to + album_artist -- main creator of the set/album, if different from artist. + e.g. "Various Artists" for compilation albums. + artist -- main creator of the work + comment -- any additional description of the file. + composer -- who composed the work, if different from artist. + copyright -- name of copyright holder. + creation_time-- date when the file was created, preferably in ISO 8601. + date -- date when the work was created, preferably in ISO 8601. + disc -- number of a subset, e.g. disc in a multi-disc collection. + encoder -- name/settings of the software/hardware that produced the file. + encoded_by -- person/group who created the file. + filename -- original name of the file. + genre -- . + language -- main language in which the work is performed, preferably + in ISO 639-2 format. Multiple languages can be specified by + separating them with commas. + performer -- artist who performed the work, if different from artist. + E.g for "Also sprach Zarathustra", artist would be "Richard + Strauss" and performer "London Philharmonic Orchestra". + publisher -- name of the label/publisher. + service_name -- name of the service in broadcasting (channel name). + service_provider -- name of the service provider in broadcasting. + title -- name of the work. + track -- number of this work in the set, can be in form current/total. + variant_bitrate -- the total bitrate of the bitrate variant that the current stream is part of + @endverbatim + * + * Look in the examples section for an application example how to use the Metadata API. + * + * @} + */ + +#if FF_API_OLD_METADATA2 +/** + * @defgroup old_metadata Old metadata API + * The following functions are deprecated, use + * their equivalents from libavutil/dict.h instead. + * @{ + */ + +#define AV_METADATA_MATCH_CASE AV_DICT_MATCH_CASE +#define AV_METADATA_IGNORE_SUFFIX AV_DICT_IGNORE_SUFFIX +#define AV_METADATA_DONT_STRDUP_KEY AV_DICT_DONT_STRDUP_KEY +#define AV_METADATA_DONT_STRDUP_VAL AV_DICT_DONT_STRDUP_VAL +#define AV_METADATA_DONT_OVERWRITE AV_DICT_DONT_OVERWRITE + +typedef attribute_deprecated AVDictionary AVMetadata; +typedef attribute_deprecated AVDictionaryEntry AVMetadataTag; + +typedef struct AVMetadataConv AVMetadataConv; + +/** + * Get a metadata element with matching key. + * + * @param prev Set to the previous matching element to find the next. + * If set to NULL the first matching element is returned. + * @param flags Allows case as well as suffix-insensitive comparisons. + * @return Found tag or NULL, changing key or value leads to undefined behavior. + */ +attribute_deprecated AVDictionaryEntry * +av_metadata_get(AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags); + +/** + * Set the given tag in *pm, overwriting an existing tag. + * + * @param pm pointer to a pointer to a metadata struct. If *pm is NULL + * a metadata struct is allocated and put in *pm. + * @param key tag key to add to *pm (will be av_strduped depending on flags) + * @param value tag value to add to *pm (will be av_strduped depending on flags). + * Passing a NULL value will cause an existing tag to be deleted. + * @return >= 0 on success otherwise an error code <0 + */ +attribute_deprecated int av_metadata_set2(AVDictionary **pm, const char *key, const char *value, int flags); + +/** + * This function is provided for compatibility reason and currently does nothing. + */ +attribute_deprecated void av_metadata_conv(struct AVFormatContext *ctx, const AVMetadataConv *d_conv, + const AVMetadataConv *s_conv); + +/** + * Copy metadata from one AVDictionary struct into another. + * @param dst pointer to a pointer to a AVDictionary struct. If *dst is NULL, + * this function will allocate a struct for you and put it in *dst + * @param src pointer to source AVDictionary struct + * @param flags flags to use when setting metadata in *dst + * @note metadata is read using the AV_DICT_IGNORE_SUFFIX flag + */ +attribute_deprecated void av_metadata_copy(AVDictionary **dst, AVDictionary *src, int flags); + +/** + * Free all the memory allocated for an AVDictionary struct. + */ +attribute_deprecated void av_metadata_free(AVDictionary **m); +/** + * @} + */ +#endif + + +/* packet functions */ + + +/** + * Allocate and read the payload of a packet and initialize its + * fields with default values. + * + * @param pkt packet + * @param size desired payload size + * @return >0 (read size) if OK, AVERROR_xxx otherwise + */ +int av_get_packet(AVIOContext *s, AVPacket *pkt, int size); + + +/** + * Read data and append it to the current content of the AVPacket. + * If pkt->size is 0 this is identical to av_get_packet. + * Note that this uses av_grow_packet and thus involves a realloc + * which is inefficient. Thus this function should only be used + * when there is no reasonable way to know (an upper bound of) + * the final size. + * + * @param pkt packet + * @param size amount of data to read + * @return >0 (read size) if OK, AVERROR_xxx otherwise, previous data + * will not be lost even if an error occurs. + */ +int av_append_packet(AVIOContext *s, AVPacket *pkt, int size); + +/*************************************************/ +/* fractional numbers for exact pts handling */ + +/** + * The exact value of the fractional number is: 'val + num / den'. + * num is assumed to be 0 <= num < den. + */ +typedef struct AVFrac { + int64_t val, num, den; +} AVFrac; + +/*************************************************/ +/* input/output formats */ + +struct AVCodecTag; + +/** + * This structure contains the data a format has to probe a file. + */ +typedef struct AVProbeData { + const char *filename; + unsigned char *buf; /**< Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero. */ + int buf_size; /**< Size of buf except extra allocated bytes */ +} AVProbeData; + +#define AVPROBE_SCORE_MAX 100 ///< maximum score, half of that is used for file-extension-based detection +#define AVPROBE_PADDING_SIZE 32 ///< extra allocated bytes at the end of the probe buffer + +typedef struct AVFormatParameters { +#if FF_API_FORMAT_PARAMETERS + attribute_deprecated AVRational time_base; + attribute_deprecated int sample_rate; + attribute_deprecated int channels; + attribute_deprecated int width; + attribute_deprecated int height; + attribute_deprecated enum PixelFormat pix_fmt; + attribute_deprecated int channel; /**< Used to select DV channel. */ + attribute_deprecated const char *standard; /**< deprecated, use demuxer-specific options instead. */ + attribute_deprecated unsigned int mpeg2ts_raw:1; /**< deprecated, use mpegtsraw demuxer */ + /**< deprecated, use mpegtsraw demuxer-specific options instead */ + attribute_deprecated unsigned int mpeg2ts_compute_pcr:1; + attribute_deprecated unsigned int initial_pause:1; /**< Do not begin to play the stream + immediately (RTSP only). */ + attribute_deprecated unsigned int prealloced_context:1; +#endif +} AVFormatParameters; + +/// Demuxer will use avio_open, no opened file should be provided by the caller. +#define AVFMT_NOFILE 0x0001 +#define AVFMT_NEEDNUMBER 0x0002 /**< Needs '%d' in filename. */ +#define AVFMT_SHOW_IDS 0x0008 /**< Show format stream IDs numbers. */ +#define AVFMT_RAWPICTURE 0x0020 /**< Format wants AVPicture structure for + raw picture data. */ +#define AVFMT_GLOBALHEADER 0x0040 /**< Format wants global header. */ +#define AVFMT_NOTIMESTAMPS 0x0080 /**< Format does not need / have any timestamps. */ +#define AVFMT_GENERIC_INDEX 0x0100 /**< Use generic index building code. */ +#define AVFMT_TS_DISCONT 0x0200 /**< Format allows timestamp discontinuities. Note, muxers always require valid (monotone) timestamps */ +#define AVFMT_VARIABLE_FPS 0x0400 /**< Format allows variable fps. */ +#define AVFMT_NODIMENSIONS 0x0800 /**< Format does not need width/height */ +#define AVFMT_NOSTREAMS 0x1000 /**< Format does not require any streams */ +#define AVFMT_NOBINSEARCH 0x2000 /**< Format does not allow to fallback to binary search via read_timestamp */ +#define AVFMT_NOGENSEARCH 0x4000 /**< Format does not allow to fallback to generic search */ +#define AVFMT_NO_BYTE_SEEK 0x8000 /**< Format does not allow seeking by bytes */ +#define AVFMT_ALLOW_FLUSH 0x10000 /**< Format allows flushing. If not set, the muxer will not receive a NULL packet in the write_packet function. */ +#define AVFMT_TS_NONSTRICT 0x8000000 /**< Format does not require strictly + increasing timestamps, but they must + still be monotonic */ + +/** + * @addtogroup lavf_encoding + * @{ + */ +typedef struct AVOutputFormat { + const char *name; + /** + * Descriptive name for the format, meant to be more human-readable + * than name. You should use the NULL_IF_CONFIG_SMALL() macro + * to define it. + */ + const char *long_name; + const char *mime_type; + const char *extensions; /**< comma-separated filename extensions */ + /** + * size of private data so that it can be allocated in the wrapper + */ + int priv_data_size; + /* output support */ + enum CodecID audio_codec; /**< default audio codec */ + enum CodecID video_codec; /**< default video codec */ + int (*write_header)(struct AVFormatContext *); + /** + * Write a packet. If AVFMT_ALLOW_FLUSH is set in flags, + * pkt can be NULL in order to flush data buffered in the muxer. + * When flushing, return 0 if there still is more data to flush, + * or 1 if everything was flushed and there is no more buffered + * data. + */ + int (*write_packet)(struct AVFormatContext *, AVPacket *pkt); + int (*write_trailer)(struct AVFormatContext *); + /** + * can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_RAWPICTURE, + * AVFMT_GLOBALHEADER, AVFMT_NOTIMESTAMPS, AVFMT_VARIABLE_FPS, + * AVFMT_NODIMENSIONS, AVFMT_NOSTREAMS, AVFMT_ALLOW_FLUSH + */ + int flags; + + void *dummy; + + int (*interleave_packet)(struct AVFormatContext *, AVPacket *out, + AVPacket *in, int flush); + + /** + * List of supported codec_id-codec_tag pairs, ordered by "better + * choice first". The arrays are all terminated by CODEC_ID_NONE. + */ + const struct AVCodecTag * const *codec_tag; + + enum CodecID subtitle_codec; /**< default subtitle codec */ + +#if FF_API_OLD_METADATA2 + const AVMetadataConv *metadata_conv; +#endif + + const AVClass *priv_class; ///< AVClass for the private context + + /** + * Test if the given codec can be stored in this container. + * + * @return 1 if the codec is supported, 0 if it is not. + * A negative number if unknown. + */ + int (*query_codec)(enum CodecID id, int std_compliance); + + void (*get_output_timestamp)(struct AVFormatContext *s, int stream, + int64_t *dts, int64_t *wall); + + /* private fields */ + struct AVOutputFormat *next; +} AVOutputFormat; +/** + * @} + */ + +/** + * @addtogroup lavf_decoding + * @{ + */ +typedef struct AVInputFormat { + /** + * A comma separated list of short names for the format. New names + * may be appended with a minor bump. + */ + const char *name; + + /** + * Descriptive name for the format, meant to be more human-readable + * than name. You should use the NULL_IF_CONFIG_SMALL() macro + * to define it. + */ + const char *long_name; + + /** + * Size of private data so that it can be allocated in the wrapper. + */ + int priv_data_size; + + /** + * Tell if a given file has a chance of being parsed as this format. + * The buffer provided is guaranteed to be AVPROBE_PADDING_SIZE bytes + * big so you do not have to check for that unless you need more. + */ + int (*read_probe)(AVProbeData *); + + /** + * Read the format header and initialize the AVFormatContext + * structure. Return 0 if OK. 'ap' if non-NULL contains + * additional parameters. Only used in raw format right + * now. 'av_new_stream' should be called to create new streams. + */ + int (*read_header)(struct AVFormatContext *, + AVFormatParameters *ap); + + /** + * Read one packet and put it in 'pkt'. pts and flags are also + * set. 'av_new_stream' can be called only if the flag + * AVFMTCTX_NOHEADER is used and only in the calling thread (not in a + * background thread). + * @return 0 on success, < 0 on error. + * When returning an error, pkt must not have been allocated + * or must be freed before returning + */ + int (*read_packet)(struct AVFormatContext *, AVPacket *pkt); + + /** + * Close the stream. The AVFormatContext and AVStreams are not + * freed by this function + */ + int (*read_close)(struct AVFormatContext *); + + /** + * Seek to a given timestamp relative to the frames in + * stream component stream_index. + * @param stream_index Must not be -1. + * @param flags Selects which direction should be preferred if no exact + * match is available. + * @return >= 0 on success (but not necessarily the new offset) + */ + int (*read_seek)(struct AVFormatContext *, + int stream_index, int64_t timestamp, int flags); + + /** + * Get the next timestamp in stream[stream_index].time_base units. + * @return the timestamp or AV_NOPTS_VALUE if an error occurred + */ + int64_t (*read_timestamp)(struct AVFormatContext *s, int stream_index, + int64_t *pos, int64_t pos_limit); + + /** + * Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_SHOW_IDS, + * AVFMT_GENERIC_INDEX, AVFMT_TS_DISCONT, AVFMT_NOBINSEARCH, + * AVFMT_NOGENSEARCH, AVFMT_NO_BYTE_SEEK. + */ + int flags; + + /** + * If extensions are defined, then no probe is done. You should + * usually not use extension format guessing because it is not + * reliable enough + */ + const char *extensions; + + /** + * General purpose read-only value that the format can use. + */ + int value; + + /** + * Start/resume playing - only meaningful if using a network-based format + * (RTSP). + */ + int (*read_play)(struct AVFormatContext *); + + /** + * Pause playing - only meaningful if using a network-based format + * (RTSP). + */ + int (*read_pause)(struct AVFormatContext *); + + const struct AVCodecTag * const *codec_tag; + + /** + * Seek to timestamp ts. + * Seeking will be done so that the point from which all active streams + * can be presented successfully will be closest to ts and within min/max_ts. + * Active streams are all streams that have AVStream.discard < AVDISCARD_ALL. + */ + int (*read_seek2)(struct AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags); + +#if FF_API_OLD_METADATA2 + const AVMetadataConv *metadata_conv; +#endif + + const AVClass *priv_class; ///< AVClass for the private context + + /* private fields */ + struct AVInputFormat *next; +} AVInputFormat; +/** + * @} + */ + +enum AVStreamParseType { + AVSTREAM_PARSE_NONE, + AVSTREAM_PARSE_FULL, /**< full parsing and repack */ + AVSTREAM_PARSE_HEADERS, /**< Only parse headers, do not repack. */ + AVSTREAM_PARSE_TIMESTAMPS, /**< full parsing and interpolation of timestamps for frames not starting on a packet boundary */ + AVSTREAM_PARSE_FULL_ONCE, /**< full parsing and repack of the first frame only, only implemented for H.264 currently */ +}; + +typedef struct AVIndexEntry { + int64_t pos; + int64_t timestamp; /**< + * Timestamp in AVStream.time_base units, preferably the time from which on correctly decoded frames are available + * when seeking to this entry. That means preferable PTS on keyframe based formats. + * But demuxers can choose to store a different timestamp, if it is more convenient for the implementation or nothing better + * is known + */ +#define AVINDEX_KEYFRAME 0x0001 + int flags:2; + int size:30; //Yeah, trying to keep the size of this small to reduce memory requirements (it is 24 vs. 32 bytes due to possible 8-byte alignment). + int min_distance; /**< Minimum distance between this and the previous keyframe, used to avoid unneeded searching. */ +} AVIndexEntry; + +#define AV_DISPOSITION_DEFAULT 0x0001 +#define AV_DISPOSITION_DUB 0x0002 +#define AV_DISPOSITION_ORIGINAL 0x0004 +#define AV_DISPOSITION_COMMENT 0x0008 +#define AV_DISPOSITION_LYRICS 0x0010 +#define AV_DISPOSITION_KARAOKE 0x0020 + +/** + * Track should be used during playback by default. + * Useful for subtitle track that should be displayed + * even when user did not explicitly ask for subtitles. + */ +#define AV_DISPOSITION_FORCED 0x0040 +#define AV_DISPOSITION_HEARING_IMPAIRED 0x0080 /**< stream for hearing impaired audiences */ +#define AV_DISPOSITION_VISUAL_IMPAIRED 0x0100 /**< stream for visual impaired audiences */ +#define AV_DISPOSITION_CLEAN_EFFECTS 0x0200 /**< stream without voice */ + +/** + * Stream structure. + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * sizeof(AVStream) must not be used outside libav*. + */ +typedef struct AVStream { + int index; /**< stream index in AVFormatContext */ + int id; /**< format-specific stream ID */ + AVCodecContext *codec; /**< codec context */ + /** + * Real base framerate of the stream. + * This is the lowest framerate with which all timestamps can be + * represented accurately (it is the least common multiple of all + * framerates in the stream). Note, this value is just a guess! + * For example, if the time base is 1/90000 and all frames have either + * approximately 3600 or 1800 timer ticks, then r_frame_rate will be 50/1. + */ + AVRational r_frame_rate; + void *priv_data; + +#if FF_API_REORDER_PRIVATE + /* internal data used in av_find_stream_info() */ + int64_t first_dts; +#endif + + /** + * encoding: pts generation when outputting stream + */ + struct AVFrac pts; + + /** + * This is the fundamental unit of time (in seconds) in terms + * of which frame timestamps are represented. For fixed-fps content, + * time base should be 1/framerate and timestamp increments should be 1. + * decoding: set by libavformat + * encoding: set by libavformat in av_write_header + */ + AVRational time_base; +#if FF_API_REORDER_PRIVATE + int pts_wrap_bits; /**< number of bits in pts (used for wrapping control) */ +#endif +#if FF_API_STREAM_COPY + /* ffmpeg.c private use */ + attribute_deprecated int stream_copy; /**< If set, just copy stream. */ +#endif + enum AVDiscard discard; ///< Selects which packets can be discarded at will and do not need to be demuxed. + +#if FF_API_AVSTREAM_QUALITY + //FIXME move stuff to a flags field? + /** + * Quality, as it has been removed from AVCodecContext and put in AVVideoFrame. + * MN: dunno if that is the right place for it + */ + attribute_deprecated float quality; +#endif + + /** + * Decoding: pts of the first frame of the stream in presentation order, in stream time base. + * Only set this if you are absolutely 100% sure that the value you set + * it to really is the pts of the first frame. + * This may be undefined (AV_NOPTS_VALUE). + * @note The ASF header does NOT contain a correct start_time the ASF + * demuxer must NOT set this. + */ + int64_t start_time; + + /** + * Decoding: duration of the stream, in stream time base. + * If a source file does not specify a duration, but does specify + * a bitrate, this value will be estimated from bitrate and file size. + */ + int64_t duration; + +#if FF_API_REORDER_PRIVATE + /* av_read_frame() support */ + enum AVStreamParseType need_parsing; + struct AVCodecParserContext *parser; + + int64_t cur_dts; + int last_IP_duration; + int64_t last_IP_pts; + /* av_seek_frame() support */ + AVIndexEntry *index_entries; /**< Only used if the format does not + support seeking natively. */ + int nb_index_entries; + unsigned int index_entries_allocated_size; +#endif + + int64_t nb_frames; ///< number of frames in this stream if known or 0 + + int disposition; /**< AV_DISPOSITION_* bit field */ + +#if FF_API_REORDER_PRIVATE + AVProbeData probe_data; +#define MAX_REORDER_DELAY 16 + int64_t pts_buffer[MAX_REORDER_DELAY+1]; +#endif + + /** + * sample aspect ratio (0 if unknown) + * - encoding: Set by user. + * - decoding: Set by libavformat. + */ + AVRational sample_aspect_ratio; + + AVDictionary *metadata; + +#if FF_API_REORDER_PRIVATE + /* Intended mostly for av_read_frame() support. Not supposed to be used by */ + /* external applications; try to use something else if at all possible. */ + const uint8_t *cur_ptr; + int cur_len; + AVPacket cur_pkt; + + // Timestamp generation support: + /** + * Timestamp corresponding to the last dts sync point. + * + * Initialized when AVCodecParserContext.dts_sync_point >= 0 and + * a DTS is received from the underlying container. Otherwise set to + * AV_NOPTS_VALUE by default. + */ + int64_t reference_dts; + + /** + * Number of packets to buffer for codec probing + * NOT PART OF PUBLIC API + */ +#define MAX_PROBE_PACKETS 2500 + int probe_packets; + + /** + * last packet in packet_buffer for this stream when muxing. + * Used internally, NOT PART OF PUBLIC API, do not read or + * write from outside of libav* + */ + struct AVPacketList *last_in_packet_buffer; +#endif + + /** + * Average framerate + */ + AVRational avg_frame_rate; + + /***************************************************************** + * All fields below this line are not part of the public API. They + * may not be used outside of libavformat and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ + + /** + * Number of frames that have been demuxed during av_find_stream_info() + */ + int codec_info_nb_frames; + + /** + * Stream Identifier + * This is the MPEG-TS stream identifier +1 + * 0 means unknown + */ + int stream_identifier; + + int64_t interleaver_chunk_size; + int64_t interleaver_chunk_duration; + + /** + * Stream information used internally by av_find_stream_info() + */ +#define MAX_STD_TIMEBASES (60*12+5) + struct { + int64_t last_dts; + int64_t duration_gcd; + int duration_count; + double duration_error[2][2][MAX_STD_TIMEBASES]; + int64_t codec_info_duration; + int nb_decoded_frames; + } *info; + + /** + * flag to indicate that probing is requested + * NOT PART OF PUBLIC API + */ + int request_probe; +#if !FF_API_REORDER_PRIVATE + const uint8_t *cur_ptr; + int cur_len; + AVPacket cur_pkt; + + // Timestamp generation support: + /** + * Timestamp corresponding to the last dts sync point. + * + * Initialized when AVCodecParserContext.dts_sync_point >= 0 and + * a DTS is received from the underlying container. Otherwise set to + * AV_NOPTS_VALUE by default. + */ + int64_t reference_dts; + int64_t first_dts; + int64_t cur_dts; + int last_IP_duration; + int64_t last_IP_pts; + + /** + * Number of packets to buffer for codec probing + */ +#define MAX_PROBE_PACKETS 2500 + int probe_packets; + + /** + * last packet in packet_buffer for this stream when muxing. + */ + struct AVPacketList *last_in_packet_buffer; + AVProbeData probe_data; +#define MAX_REORDER_DELAY 16 + int64_t pts_buffer[MAX_REORDER_DELAY+1]; + /* av_read_frame() support */ + enum AVStreamParseType need_parsing; + struct AVCodecParserContext *parser; + + AVIndexEntry *index_entries; /**< Only used if the format does not + support seeking natively. */ + int nb_index_entries; + unsigned int index_entries_allocated_size; + + int pts_wrap_bits; /**< number of bits in pts (used for wrapping control) */ +#endif +} AVStream; + +#define AV_PROGRAM_RUNNING 1 + +/** + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * sizeof(AVProgram) must not be used outside libav*. + */ +typedef struct AVProgram { + int id; + int flags; + enum AVDiscard discard; ///< selects which program to discard and which to feed to the caller + unsigned int *stream_index; + unsigned int nb_stream_indexes; + AVDictionary *metadata; + + int program_num; + int pmt_pid; + int pcr_pid; +} AVProgram; + +#define AVFMTCTX_NOHEADER 0x0001 /**< signal that no header is present + (streams are added dynamically) */ + +typedef struct AVChapter { + int id; ///< unique ID to identify the chapter + AVRational time_base; ///< time base in which the start/end timestamps are specified + int64_t start, end; ///< chapter start/end time in time_base units + AVDictionary *metadata; +} AVChapter; + +/** + * Format I/O context. + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * sizeof(AVFormatContext) must not be used outside libav*, use + * avformat_alloc_context() to create an AVFormatContext. + */ +typedef struct AVFormatContext { + /** + * A class for logging and AVOptions. Set by avformat_alloc_context(). + * Exports (de)muxer private options if they exist. + */ + const AVClass *av_class; + + /** + * Can only be iformat or oformat, not both at the same time. + * + * decoding: set by avformat_open_input(). + * encoding: set by the user. + */ + struct AVInputFormat *iformat; + struct AVOutputFormat *oformat; + + /** + * Format private data. This is an AVOptions-enabled struct + * if and only if iformat/oformat.priv_class is not NULL. + */ + void *priv_data; + + /* + * I/O context. + * + * decoding: either set by the user before avformat_open_input() (then + * the user must close it manually) or set by avformat_open_input(). + * encoding: set by the user. + * + * Do NOT set this field if AVFMT_NOFILE flag is set in + * iformat/oformat.flags. In such a case, the (de)muxer will handle + * I/O in some other way and this field will be NULL. + */ + AVIOContext *pb; + + /** + * A list of all streams in the file. New streams are created with + * avformat_new_stream(). + * + * decoding: streams are created by libavformat in avformat_open_input(). + * If AVFMTCTX_NOHEADER is set in ctx_flags, then new streams may also + * appear in av_read_frame(). + * encoding: streams are created by the user before avformat_write_header(). + */ + unsigned int nb_streams; + AVStream **streams; + + char filename[1024]; /**< input or output filename */ + /* stream info */ +#if FF_API_TIMESTAMP + /** + * @deprecated use 'creation_time' metadata tag instead + */ + attribute_deprecated int64_t timestamp; +#endif + + int ctx_flags; /**< Format-specific flags, see AVFMTCTX_xx */ +#if FF_API_REORDER_PRIVATE + /* private data for pts handling (do not modify directly). */ + /** + * This buffer is only needed when packets were already buffered but + * not decoded, for example to get the codec parameters in MPEG + * streams. + */ + struct AVPacketList *packet_buffer; +#endif + + /** + * Decoding: position of the first frame of the component, in + * AV_TIME_BASE fractional seconds. NEVER set this value directly: + * It is deduced from the AVStream values. + */ + int64_t start_time; + + /** + * Decoding: duration of the stream, in AV_TIME_BASE fractional + * seconds. Only set this value if you know none of the individual stream + * durations and also do not set any of them. This is deduced from the + * AVStream values if not set. + */ + int64_t duration; + +#if FF_API_FILESIZE + /** + * decoding: total file size, 0 if unknown + */ + attribute_deprecated int64_t file_size; +#endif + + /** + * Decoding: total stream bitrate in bit/s, 0 if not + * available. Never set it directly if the file_size and the + * duration are known as FFmpeg can compute it automatically. + */ + int bit_rate; + +#if FF_API_REORDER_PRIVATE + /* av_read_frame() support */ + AVStream *cur_st; + + /* av_seek_frame() support */ + int64_t data_offset; /**< offset of the first packet */ +#endif + +#if FF_API_MUXRATE + /** + * use mpeg muxer private options instead + */ + attribute_deprecated int mux_rate; +#endif + unsigned int packet_size; +#if FF_API_PRELOAD + attribute_deprecated int preload; +#endif + int max_delay; + +#if FF_API_LOOP_OUTPUT +#define AVFMT_NOOUTPUTLOOP -1 +#define AVFMT_INFINITEOUTPUTLOOP 0 + /** + * number of times to loop output in formats that support it + * + * @deprecated use the 'loop' private option in the gif muxer. + */ + attribute_deprecated int loop_output; +#endif + + int flags; +#define AVFMT_FLAG_GENPTS 0x0001 ///< Generate missing pts even if it requires parsing future frames. +#define AVFMT_FLAG_IGNIDX 0x0002 ///< Ignore index. +#define AVFMT_FLAG_NONBLOCK 0x0004 ///< Do not block when reading packets from input. +#define AVFMT_FLAG_IGNDTS 0x0008 ///< Ignore DTS on frames that contain both DTS & PTS +#define AVFMT_FLAG_NOFILLIN 0x0010 ///< Do not infer any values from other values, just return what is stored in the container +#define AVFMT_FLAG_NOPARSE 0x0020 ///< Do not use AVParsers, you also must set AVFMT_FLAG_NOFILLIN as the fillin code works on frames and no parsing -> no frames. Also seeking to frames can not work if parsing to find frame boundaries has been disabled +#if FF_API_FLAG_RTP_HINT +#define AVFMT_FLAG_RTP_HINT 0x0040 ///< Deprecated, use the -movflags rtphint muxer specific AVOption instead +#endif +#define AVFMT_FLAG_CUSTOM_IO 0x0080 ///< The caller has supplied a custom AVIOContext, don't avio_close() it. +#define AVFMT_FLAG_DISCARD_CORRUPT 0x0100 ///< Discard frames marked corrupted +#define AVFMT_FLAG_MP4A_LATM 0x8000 ///< Enable RTP MP4A-LATM payload +#define AVFMT_FLAG_SORT_DTS 0x10000 ///< try to interleave outputted packets by dts (using this flag can slow demuxing down) +#define AVFMT_FLAG_PRIV_OPT 0x20000 ///< Enable use of private options by delaying codec open (this could be made default once all code is converted) +#define AVFMT_FLAG_KEEP_SIDE_DATA 0x40000 ///< Dont merge side data but keep it seperate. + +#if FF_API_LOOP_INPUT + /** + * @deprecated, use the 'loop' img2 demuxer private option. + */ + attribute_deprecated int loop_input; +#endif + + /** + * decoding: size of data to probe; encoding: unused. + */ + unsigned int probesize; + + /** + * decoding: maximum time (in AV_TIME_BASE units) during which the input should + * be analyzed in avformat_find_stream_info(). + */ + int max_analyze_duration; + + const uint8_t *key; + int keylen; + + unsigned int nb_programs; + AVProgram **programs; + + /** + * Forced video codec_id. + * Demuxing: Set by user. + */ + enum CodecID video_codec_id; + + /** + * Forced audio codec_id. + * Demuxing: Set by user. + */ + enum CodecID audio_codec_id; + + /** + * Forced subtitle codec_id. + * Demuxing: Set by user. + */ + enum CodecID subtitle_codec_id; + + /** + * Maximum amount of memory in bytes to use for the index of each stream. + * If the index exceeds this size, entries will be discarded as + * needed to maintain a smaller size. This can lead to slower or less + * accurate seeking (depends on demuxer). + * Demuxers for which a full in-memory index is mandatory will ignore + * this. + * muxing : unused + * demuxing: set by user + */ + unsigned int max_index_size; + + /** + * Maximum amount of memory in bytes to use for buffering frames + * obtained from realtime capture devices. + */ + unsigned int max_picture_buffer; + + unsigned int nb_chapters; + AVChapter **chapters; + + /** + * Flags to enable debugging. + */ + int debug; +#define FF_FDEBUG_TS 0x0001 + +#if FF_API_REORDER_PRIVATE + /** + * Raw packets from the demuxer, prior to parsing and decoding. + * This buffer is used for buffering packets until the codec can + * be identified, as parsing cannot be done without knowing the + * codec. + */ + struct AVPacketList *raw_packet_buffer; + struct AVPacketList *raw_packet_buffer_end; + + struct AVPacketList *packet_buffer_end; +#endif + + AVDictionary *metadata; + +#if FF_API_REORDER_PRIVATE + /** + * Remaining size available for raw_packet_buffer, in bytes. + * NOT PART OF PUBLIC API + */ +#define RAW_PACKET_BUFFER_SIZE 2500000 + int raw_packet_buffer_remaining_size; +#endif + + /** + * Start time of the stream in real world time, in microseconds + * since the unix epoch (00:00 1st January 1970). That is, pts=0 + * in the stream was captured at this real world time. + * - encoding: Set by user. + * - decoding: Unused. + */ + int64_t start_time_realtime; + + /** + * decoding: number of frames used to probe fps + */ + int fps_probe_size; + + /** + * Error recognition; higher values will detect more errors but may + * misdetect some more or less valid parts as errors. + * - encoding: unused + * - decoding: Set by user. + */ + int error_recognition; + + /** + * Custom interrupt callbacks for the I/O layer. + * + * decoding: set by the user before avformat_open_input(). + * encoding: set by the user before avformat_write_header() + * (mainly useful for AVFMT_NOFILE formats). The callback + * should also be passed to avio_open2() if it's used to + * open the file. + */ + AVIOInterruptCB interrupt_callback; + + /** + * Transport stream id. + * This will be moved into demuxer private options. Thus no API/ABI compatibility + */ + int ts_id; + + /** + * Audio preload in microseconds. + * Note, not all formats support this and unpredictable things may happen if it is used when not supported. + * - encoding: Set by user via AVOptions (NO direct access) + * - decoding: unused + */ + int audio_preload; + + /** + * Max chunk time in microseconds. + * Note, not all formats support this and unpredictable things may happen if it is used when not supported. + * - encoding: Set by user via AVOptions (NO direct access) + * - decoding: unused + */ + int max_chunk_duration; + + /** + * Max chunk size in bytes + * Note, not all formats support this and unpredictable things may happen if it is used when not supported. + * - encoding: Set by user via AVOptions (NO direct access) + * - decoding: unused + */ + int max_chunk_size; + + /***************************************************************** + * All fields below this line are not part of the public API. They + * may not be used outside of libavformat and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ +#if !FF_API_REORDER_PRIVATE + /** + * Raw packets from the demuxer, prior to parsing and decoding. + * This buffer is used for buffering packets until the codec can + * be identified, as parsing cannot be done without knowing the + * codec. + */ + struct AVPacketList *raw_packet_buffer; + struct AVPacketList *raw_packet_buffer_end; + /** + * Remaining size available for raw_packet_buffer, in bytes. + */ +#define RAW_PACKET_BUFFER_SIZE 2500000 + int raw_packet_buffer_remaining_size; + + /** + * This buffer is only needed when packets were already buffered but + * not decoded, for example to get the codec parameters in MPEG + * streams. + */ + struct AVPacketList *packet_buffer; + struct AVPacketList *packet_buffer_end; + + /* av_read_frame() support */ + AVStream *cur_st; + + /* av_seek_frame() support */ + int64_t data_offset; /**< offset of the first packet */ +#endif +} AVFormatContext; + +typedef struct AVPacketList { + AVPacket pkt; + struct AVPacketList *next; +} AVPacketList; + + +/** + * @defgroup lavf_core Core functions + * @ingroup libavf + * + * Functions for querying libavformat capabilities, allocating core structures, + * etc. + * @{ + */ + +/** + * Return the LIBAVFORMAT_VERSION_INT constant. + */ +unsigned avformat_version(void); + +/** + * Return the libavformat build-time configuration. + */ +const char *avformat_configuration(void); + +/** + * Return the libavformat license. + */ +const char *avformat_license(void); + +/** + * Initialize libavformat and register all the muxers, demuxers and + * protocols. If you do not call this function, then you can select + * exactly which formats you want to support. + * + * @see av_register_input_format() + * @see av_register_output_format() + * @see av_register_protocol() + */ +void av_register_all(void); + +void av_register_input_format(AVInputFormat *format); +void av_register_output_format(AVOutputFormat *format); + +/** + * Do global initialization of network components. This is optional, + * but recommended, since it avoids the overhead of implicitly + * doing the setup for each session. + * + * Calling this function will become mandatory if using network + * protocols at some major version bump. + */ +int avformat_network_init(void); + +/** + * Undo the initialization done by avformat_network_init. + */ +int avformat_network_deinit(void); + +/** + * If f is NULL, returns the first registered input format, + * if f is non-NULL, returns the next registered input format after f + * or NULL if f is the last one. + */ +AVInputFormat *av_iformat_next(AVInputFormat *f); + +/** + * If f is NULL, returns the first registered output format, + * if f is non-NULL, returns the next registered output format after f + * or NULL if f is the last one. + */ +AVOutputFormat *av_oformat_next(AVOutputFormat *f); + +/** + * Allocate an AVFormatContext. + * avformat_free_context() can be used to free the context and everything + * allocated by the framework within it. + */ +AVFormatContext *avformat_alloc_context(void); + +/** + * Free an AVFormatContext and all its streams. + * @param s context to free + */ +void avformat_free_context(AVFormatContext *s); + +/** + * Get the AVClass for AVFormatContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *avformat_get_class(void); + +/** + * Add a new stream to a media file. + * + * When demuxing, it is called by the demuxer in read_header(). If the + * flag AVFMTCTX_NOHEADER is set in s.ctx_flags, then it may also + * be called in read_packet(). + * + * When muxing, should be called by the user before avformat_write_header(). + * + * @param c If non-NULL, the AVCodecContext corresponding to the new stream + * will be initialized to use this codec. This is needed for e.g. codec-specific + * defaults to be set, so codec should be provided if it is known. + * + * @return newly created stream or NULL on error. + */ +AVStream *avformat_new_stream(AVFormatContext *s, AVCodec *c); + +AVProgram *av_new_program(AVFormatContext *s, int id); + +/** + * @} + */ + + +#if FF_API_GUESS_IMG2_CODEC +attribute_deprecated enum CodecID av_guess_image2_codec(const char *filename); +#endif + +#if FF_API_PKT_DUMP +attribute_deprecated void av_pkt_dump(FILE *f, AVPacket *pkt, int dump_payload); +attribute_deprecated void av_pkt_dump_log(void *avcl, int level, AVPacket *pkt, + int dump_payload); +#endif + + +#if FF_API_ALLOC_OUTPUT_CONTEXT +/** + * @deprecated deprecated in favor of avformat_alloc_output_context2() + */ +attribute_deprecated +AVFormatContext *avformat_alloc_output_context(const char *format, + AVOutputFormat *oformat, + const char *filename); +#endif + +/** + * Allocate an AVFormatContext for an output format. + * avformat_free_context() can be used to free the context and + * everything allocated by the framework within it. + * + * @param *ctx is set to the created format context, or to NULL in + * case of failure + * @param oformat format to use for allocating the context, if NULL + * format_name and filename are used instead + * @param format_name the name of output format to use for allocating the + * context, if NULL filename is used instead + * @param filename the name of the filename to use for allocating the + * context, may be NULL + * @return >= 0 in case of success, a negative AVERROR code in case of + * failure + */ +int avformat_alloc_output_context2(AVFormatContext **ctx, AVOutputFormat *oformat, + const char *format_name, const char *filename); + +/** + * @addtogroup lavf_decoding + * @{ + */ + +/** + * Find AVInputFormat based on the short name of the input format. + */ +AVInputFormat *av_find_input_format(const char *short_name); + +/** + * Guess the file format. + * + * @param is_opened Whether the file is already opened; determines whether + * demuxers with or without AVFMT_NOFILE are probed. + */ +AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened); + +/** + * Guess the file format. + * + * @param is_opened Whether the file is already opened; determines whether + * demuxers with or without AVFMT_NOFILE are probed. + * @param score_max A probe score larger that this is required to accept a + * detection, the variable is set to the actual detection + * score afterwards. + * If the score is <= AVPROBE_SCORE_MAX / 4 it is recommended + * to retry with a larger probe buffer. + */ +AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, int *score_max); + +/** + * Guess the file format. + * + * @param is_opened Whether the file is already opened; determines whether + * demuxers with or without AVFMT_NOFILE are probed. + * @param score_ret The score of the best detection. + */ +AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened, int *score_ret); + +/** + * Probe a bytestream to determine the input format. Each time a probe returns + * with a score that is too low, the probe buffer size is increased and another + * attempt is made. When the maximum probe size is reached, the input format + * with the highest score is returned. + * + * @param pb the bytestream to probe + * @param fmt the input format is put here + * @param filename the filename of the stream + * @param logctx the log context + * @param offset the offset within the bytestream to probe from + * @param max_probe_size the maximum probe buffer size (zero for default) + * @return 0 in case of success, a negative value corresponding to an + * AVERROR code otherwise + */ +int av_probe_input_buffer(AVIOContext *pb, AVInputFormat **fmt, + const char *filename, void *logctx, + unsigned int offset, unsigned int max_probe_size); + +#if FF_API_FORMAT_PARAMETERS +/** + * Allocate all the structures needed to read an input stream. + * This does not open the needed codecs for decoding the stream[s]. + * @deprecated use avformat_open_input instead. + */ +attribute_deprecated int av_open_input_stream(AVFormatContext **ic_ptr, + AVIOContext *pb, const char *filename, + AVInputFormat *fmt, AVFormatParameters *ap); + +/** + * Open a media file as input. The codecs are not opened. Only the file + * header (if present) is read. + * + * @param ic_ptr The opened media file handle is put here. + * @param filename filename to open + * @param fmt If non-NULL, force the file format to use. + * @param buf_size optional buffer size (zero if default is OK) + * @param ap Additional parameters needed when opening the file + * (NULL if default). + * @return 0 if OK, AVERROR_xxx otherwise + * + * @deprecated use avformat_open_input instead. + */ +attribute_deprecated int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, + AVInputFormat *fmt, + int buf_size, + AVFormatParameters *ap); +#endif + +/** + * Open an input stream and read the header. The codecs are not opened. + * The stream must be closed with av_close_input_file(). + * + * @param ps Pointer to user-supplied AVFormatContext (allocated by avformat_alloc_context). + * May be a pointer to NULL, in which case an AVFormatContext is allocated by this + * function and written into ps. + * Note that a user-supplied AVFormatContext will be freed on failure. + * @param filename Name of the stream to open. + * @param fmt If non-NULL, this parameter forces a specific input format. + * Otherwise the format is autodetected. + * @param options A dictionary filled with AVFormatContext and demuxer-private options. + * On return this parameter will be destroyed and replaced with a dict containing + * options that were not found. May be NULL. + * + * @return 0 on success, a negative AVERROR on failure. + * + * @note If you want to use custom IO, preallocate the format context and set its pb field. + */ +int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options); + +int av_demuxer_open(AVFormatContext *ic, AVFormatParameters *ap); + +#if FF_API_FORMAT_PARAMETERS +/** + * Read packets of a media file to get stream information. This + * is useful for file formats with no headers such as MPEG. This + * function also computes the real framerate in case of MPEG-2 repeat + * frame mode. + * The logical file position is not changed by this function; + * examined packets may be buffered for later processing. + * + * @param ic media file handle + * @return >=0 if OK, AVERROR_xxx on error + * @todo Let the user decide somehow what information is needed so that + * we do not waste time getting stuff the user does not need. + * + * @deprecated use avformat_find_stream_info. + */ +attribute_deprecated +int av_find_stream_info(AVFormatContext *ic); +#endif + +/** + * Read packets of a media file to get stream information. This + * is useful for file formats with no headers such as MPEG. This + * function also computes the real framerate in case of MPEG-2 repeat + * frame mode. + * The logical file position is not changed by this function; + * examined packets may be buffered for later processing. + * + * @param ic media file handle + * @param options If non-NULL, an ic.nb_streams long array of pointers to + * dictionaries, where i-th member contains options for + * codec corresponding to i-th stream. + * On return each dictionary will be filled with options that were not found. + * @return >=0 if OK, AVERROR_xxx on error + * + * @note this function isn't guaranteed to open all the codecs, so + * options being non-empty at return is a perfectly normal behavior. + * + * @todo Let the user decide somehow what information is needed so that + * we do not waste time getting stuff the user does not need. + */ +int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options); + +/** + * Find the programs which belong to a given stream. + * + * @param ic media file handle + * @param last the last found program, the search will start after this + * program, or from the beginning if it is NULL + * @param s stream index + * @return the next program which belongs to s, NULL if no program is found or + * the last program is not among the programs of ic. + */ +AVProgram *av_find_program_from_stream(AVFormatContext *ic, AVProgram *last, int s); + +/** + * Find the "best" stream in the file. + * The best stream is determined according to various heuristics as the most + * likely to be what the user expects. + * If the decoder parameter is non-NULL, av_find_best_stream will find the + * default decoder for the stream's codec; streams for which no decoder can + * be found are ignored. + * + * @param ic media file handle + * @param type stream type: video, audio, subtitles, etc. + * @param wanted_stream_nb user-requested stream number, + * or -1 for automatic selection + * @param related_stream try to find a stream related (eg. in the same + * program) to this one, or -1 if none + * @param decoder_ret if non-NULL, returns the decoder for the + * selected stream + * @param flags flags; none are currently defined + * @return the non-negative stream number in case of success, + * AVERROR_STREAM_NOT_FOUND if no stream with the requested type + * could be found, + * AVERROR_DECODER_NOT_FOUND if streams were found but no decoder + * @note If av_find_best_stream returns successfully and decoder_ret is not + * NULL, then *decoder_ret is guaranteed to be set to a valid AVCodec. + */ +int av_find_best_stream(AVFormatContext *ic, + enum AVMediaType type, + int wanted_stream_nb, + int related_stream, + AVCodec **decoder_ret, + int flags); + +/** + * Read a transport packet from a media file. + * + * This function is obsolete and should never be used. + * Use av_read_frame() instead. + * + * @param s media file handle + * @param pkt is filled + * @return 0 if OK, AVERROR_xxx on error + */ +int av_read_packet(AVFormatContext *s, AVPacket *pkt); + +/** + * Return the next frame of a stream. + * This function returns what is stored in the file, and does not validate + * that what is there are valid frames for the decoder. It will split what is + * stored in the file into frames and return one for each call. It will not + * omit invalid data between valid frames so as to give the decoder the maximum + * information possible for decoding. + * + * The returned packet is valid + * until the next av_read_frame() or until av_close_input_file() and + * must be freed with av_free_packet. For video, the packet contains + * exactly one frame. For audio, it contains an integer number of + * frames if each frame has a known fixed size (e.g. PCM or ADPCM + * data). If the audio frames have a variable size (e.g. MPEG audio), + * then it contains one frame. + * + * pkt->pts, pkt->dts and pkt->duration are always set to correct + * values in AVStream.time_base units (and guessed if the format cannot + * provide them). pkt->pts can be AV_NOPTS_VALUE if the video format + * has B-frames, so it is better to rely on pkt->dts if you do not + * decompress the payload. + * + * @return 0 if OK, < 0 on error or end of file + */ +int av_read_frame(AVFormatContext *s, AVPacket *pkt); + +/** + * Seek to the keyframe at timestamp. + * 'timestamp' in 'stream_index'. + * @param stream_index If stream_index is (-1), a default + * stream is selected, and timestamp is automatically converted + * from AV_TIME_BASE units to the stream specific time_base. + * @param timestamp Timestamp in AVStream.time_base units + * or, if no stream is specified, in AV_TIME_BASE units. + * @param flags flags which select direction and seeking mode + * @return >= 0 on success + */ +int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, + int flags); + +/** + * Seek to timestamp ts. + * Seeking will be done so that the point from which all active streams + * can be presented successfully will be closest to ts and within min/max_ts. + * Active streams are all streams that have AVStream.discard < AVDISCARD_ALL. + * + * If flags contain AVSEEK_FLAG_BYTE, then all timestamps are in bytes and + * are the file position (this may not be supported by all demuxers). + * If flags contain AVSEEK_FLAG_FRAME, then all timestamps are in frames + * in the stream with stream_index (this may not be supported by all demuxers). + * Otherwise all timestamps are in units of the stream selected by stream_index + * or if stream_index is -1, in AV_TIME_BASE units. + * If flags contain AVSEEK_FLAG_ANY, then non-keyframes are treated as + * keyframes (this may not be supported by all demuxers). + * + * @param stream_index index of the stream which is used as time base reference + * @param min_ts smallest acceptable timestamp + * @param ts target timestamp + * @param max_ts largest acceptable timestamp + * @param flags flags + * @return >=0 on success, error code otherwise + * + * @note This is part of the new seek API which is still under construction. + * Thus do not use this yet. It may change at any time, do not expect + * ABI compatibility yet! + */ +int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags); + +/** + * Start playing a network-based stream (e.g. RTSP stream) at the + * current position. + */ +int av_read_play(AVFormatContext *s); + +/** + * Pause a network-based stream (e.g. RTSP stream). + * + * Use av_read_play() to resume it. + */ +int av_read_pause(AVFormatContext *s); + +#if FF_API_FORMAT_PARAMETERS +/** + * Free a AVFormatContext allocated by av_open_input_stream. + * @param s context to free + * @deprecated use av_close_input_file() + */ +attribute_deprecated +void av_close_input_stream(AVFormatContext *s); +#endif + +#if FF_API_CLOSE_INPUT_FILE +/** + * @deprecated use avformat_close_input() + * Close a media file (but not its codecs). + * + * @param s media file handle + */ +attribute_deprecated +void av_close_input_file(AVFormatContext *s); +#endif + +/** + * Close an opened input AVFormatContext. Free it and all its contents + * and set *s to NULL. + */ +void avformat_close_input(AVFormatContext **s); +/** + * @} + */ + +#if FF_API_NEW_STREAM +/** + * Add a new stream to a media file. + * + * Can only be called in the read_header() function. If the flag + * AVFMTCTX_NOHEADER is in the format context, then new streams + * can be added in read_packet too. + * + * @param s media file handle + * @param id file-format-dependent stream ID + */ +attribute_deprecated +AVStream *av_new_stream(AVFormatContext *s, int id); +#endif + +#if FF_API_SET_PTS_INFO +/** + * @deprecated this function is not supposed to be called outside of lavf + */ +attribute_deprecated +void av_set_pts_info(AVStream *s, int pts_wrap_bits, + unsigned int pts_num, unsigned int pts_den); +#endif + +#define AVSEEK_FLAG_BACKWARD 1 ///< seek backward +#define AVSEEK_FLAG_BYTE 2 ///< seeking based on position in bytes +#define AVSEEK_FLAG_ANY 4 ///< seek to any frame, even non-keyframes +#define AVSEEK_FLAG_FRAME 8 ///< seeking based on frame number + +#if FF_API_SEEK_PUBLIC +attribute_deprecated +int av_seek_frame_binary(AVFormatContext *s, int stream_index, + int64_t target_ts, int flags); +attribute_deprecated +void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp); +attribute_deprecated +int64_t av_gen_search(AVFormatContext *s, int stream_index, + int64_t target_ts, int64_t pos_min, + int64_t pos_max, int64_t pos_limit, + int64_t ts_min, int64_t ts_max, + int flags, int64_t *ts_ret, + int64_t (*read_timestamp)(struct AVFormatContext *, int , int64_t *, int64_t )); +#endif + +#if FF_API_FORMAT_PARAMETERS +/** + * @deprecated pass the options to avformat_write_header directly. + */ +attribute_deprecated int av_set_parameters(AVFormatContext *s, AVFormatParameters *ap); +#endif + +/** + * @addtogroup lavf_encoding + * @{ + */ +/** + * Allocate the stream private data and write the stream header to + * an output media file. + * + * @param s Media file handle, must be allocated with avformat_alloc_context(). + * Its oformat field must be set to the desired output format; + * Its pb field must be set to an already openened AVIOContext. + * @param options An AVDictionary filled with AVFormatContext and muxer-private options. + * On return this parameter will be destroyed and replaced with a dict containing + * options that were not found. May be NULL. + * + * @return 0 on success, negative AVERROR on failure. + * + * @see av_opt_find, av_dict_set, avio_open, av_oformat_next. + */ +int avformat_write_header(AVFormatContext *s, AVDictionary **options); + +#if FF_API_FORMAT_PARAMETERS +/** + * Allocate the stream private data and write the stream header to an + * output media file. + * @note: this sets stream time-bases, if possible to stream->codec->time_base + * but for some formats it might also be some other time base + * + * @param s media file handle + * @return 0 if OK, AVERROR_xxx on error + * + * @deprecated use avformat_write_header. + */ +attribute_deprecated int av_write_header(AVFormatContext *s); +#endif + +/** + * Write a packet to an output media file. + * + * The packet shall contain one audio or video frame. + * The packet must be correctly interleaved according to the container + * specification, if not then av_interleaved_write_frame must be used. + * + * @param s media file handle + * @param pkt The packet, which contains the stream_index, buf/buf_size, + * dts/pts, ... + * This can be NULL (at any time, not just at the end), in + * order to immediately flush data buffered within the muxer, + * for muxers that buffer up data internally before writing it + * to the output. + * @return < 0 on error, = 0 if OK, 1 if flushed and there is no more data to flush + */ +int av_write_frame(AVFormatContext *s, AVPacket *pkt); + +/** + * Write a packet to an output media file ensuring correct interleaving. + * + * The packet must contain one audio or video frame. + * If the packets are already correctly interleaved, the application should + * call av_write_frame() instead as it is slightly faster. It is also important + * to keep in mind that completely non-interleaved input will need huge amounts + * of memory to interleave with this, so it is preferable to interleave at the + * demuxer level. + * + * @param s media file handle + * @param pkt The packet containing the data to be written. Libavformat takes + * ownership of the data and will free it when it sees fit using the packet's + * @ref AVPacket.destruct "destruct" field. The caller must not access the data + * after this function returns, as it may already be freed. + * Packet's @ref AVPacket.stream_index "stream_index" field must be set to the + * index of the corresponding stream in @ref AVFormatContext.streams + * "s.streams". + * It is very strongly recommended that timing information (@ref AVPacket.pts + * "pts", @ref AVPacket.dts "dts" @ref AVPacket.duration "duration") is set to + * correct values. + * + * @return 0 on success, a negative AVERROR on error. + */ +int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt); + +/** + * Interleave a packet per dts in an output media file. + * + * Packets with pkt->destruct == av_destruct_packet will be freed inside this + * function, so they cannot be used after it. Note that calling av_free_packet() + * on them is still safe. + * + * @param s media file handle + * @param out the interleaved packet will be output here + * @param pkt the input packet + * @param flush 1 if no further packets are available as input and all + * remaining packets should be output + * @return 1 if a packet was output, 0 if no packet could be output, + * < 0 if an error occurred + */ +int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, + AVPacket *pkt, int flush); + +/** + * Write the stream trailer to an output media file and free the + * file private data. + * + * May only be called after a successful call to av_write_header. + * + * @param s media file handle + * @return 0 if OK, AVERROR_xxx on error + */ +int av_write_trailer(AVFormatContext *s); + +/** + * Return the output format in the list of registered output formats + * which best matches the provided parameters, or return NULL if + * there is no match. + * + * @param short_name if non-NULL checks if short_name matches with the + * names of the registered formats + * @param filename if non-NULL checks if filename terminates with the + * extensions of the registered formats + * @param mime_type if non-NULL checks if mime_type matches with the + * MIME type of the registered formats + */ +AVOutputFormat *av_guess_format(const char *short_name, + const char *filename, + const char *mime_type); + +/** + * Guess the codec ID based upon muxer and filename. + */ +enum CodecID av_guess_codec(AVOutputFormat *fmt, const char *short_name, + const char *filename, const char *mime_type, + enum AVMediaType type); + +/** + * Get timing information for the data currently output. + * The exact meaning of "currently output" depends on the format. + * It is mostly relevant for devices that have an internal buffer and/or + * work in real time. + * @param s media file handle + * @param stream stream in the media file + * @param dts[out] DTS of the last packet output for the stream, in stream + * time_base units + * @param wall[out] absolute time when that packet whas output, + * in microsecond + * @return 0 if OK, AVERROR(ENOSYS) if the format does not support it + * Note: some formats or devices may not allow to measure dts and wall + * atomically. + */ +int av_get_output_timestamp(struct AVFormatContext *s, int stream, + int64_t *dts, int64_t *wall); + + +/** + * @} + */ + + +/** + * @defgroup lavf_misc Utility functions + * @ingroup libavf + * @{ + * + * Miscelaneous utility functions related to both muxing and demuxing + * (or neither). + */ + +/** + * Send a nice hexadecimal dump of a buffer to the specified file stream. + * + * @param f The file stream pointer where the dump should be sent to. + * @param buf buffer + * @param size buffer size + * + * @see av_hex_dump_log, av_pkt_dump2, av_pkt_dump_log2 + */ +void av_hex_dump(FILE *f, uint8_t *buf, int size); + +/** + * Send a nice hexadecimal dump of a buffer to the log. + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct. + * @param level The importance level of the message, lower values signifying + * higher importance. + * @param buf buffer + * @param size buffer size + * + * @see av_hex_dump, av_pkt_dump2, av_pkt_dump_log2 + */ +void av_hex_dump_log(void *avcl, int level, uint8_t *buf, int size); + +/** + * Send a nice dump of a packet to the specified file stream. + * + * @param f The file stream pointer where the dump should be sent to. + * @param pkt packet to dump + * @param dump_payload True if the payload must be displayed, too. + * @param st AVStream that the packet belongs to + */ +void av_pkt_dump2(FILE *f, AVPacket *pkt, int dump_payload, AVStream *st); + + +/** + * Send a nice dump of a packet to the log. + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct. + * @param level The importance level of the message, lower values signifying + * higher importance. + * @param pkt packet to dump + * @param dump_payload True if the payload must be displayed, too. + * @param st AVStream that the packet belongs to + */ +void av_pkt_dump_log2(void *avcl, int level, AVPacket *pkt, int dump_payload, + AVStream *st); + +/** + * Get the CodecID for the given codec tag tag. + * If no codec id is found returns CODEC_ID_NONE. + * + * @param tags list of supported codec_id-codec_tag pairs, as stored + * in AVInputFormat.codec_tag and AVOutputFormat.codec_tag + */ +enum CodecID av_codec_get_id(const struct AVCodecTag * const *tags, unsigned int tag); + +/** + * Get the codec tag for the given codec id id. + * If no codec tag is found returns 0. + * + * @param tags list of supported codec_id-codec_tag pairs, as stored + * in AVInputFormat.codec_tag and AVOutputFormat.codec_tag + */ +unsigned int av_codec_get_tag(const struct AVCodecTag * const *tags, enum CodecID id); + +int av_find_default_stream_index(AVFormatContext *s); + +/** + * Get the index for a specific timestamp. + * @param flags if AVSEEK_FLAG_BACKWARD then the returned index will correspond + * to the timestamp which is <= the requested one, if backward + * is 0, then it will be >= + * if AVSEEK_FLAG_ANY seek to any frame, only keyframes otherwise + * @return < 0 if no such timestamp could be found + */ +int av_index_search_timestamp(AVStream *st, int64_t timestamp, int flags); + +/** + * Add an index entry into a sorted list. Update the entry if the list + * already contains it. + * + * @param timestamp timestamp in the time base of the given stream + */ +int av_add_index_entry(AVStream *st, int64_t pos, int64_t timestamp, + int size, int distance, int flags); + + +/** + * Split a URL string into components. + * + * The pointers to buffers for storing individual components may be null, + * in order to ignore that component. Buffers for components not found are + * set to empty strings. If the port is not found, it is set to a negative + * value. + * + * @param proto the buffer for the protocol + * @param proto_size the size of the proto buffer + * @param authorization the buffer for the authorization + * @param authorization_size the size of the authorization buffer + * @param hostname the buffer for the host name + * @param hostname_size the size of the hostname buffer + * @param port_ptr a pointer to store the port number in + * @param path the buffer for the path + * @param path_size the size of the path buffer + * @param url the URL to split + */ +void av_url_split(char *proto, int proto_size, + char *authorization, int authorization_size, + char *hostname, int hostname_size, + int *port_ptr, + char *path, int path_size, + const char *url); + +#if FF_API_DUMP_FORMAT +/** + * @deprecated Deprecated in favor of av_dump_format(). + */ +attribute_deprecated void dump_format(AVFormatContext *ic, + int index, + const char *url, + int is_output); +#endif + +void av_dump_format(AVFormatContext *ic, + int index, + const char *url, + int is_output); + +#if FF_API_PARSE_DATE +/** + * Parse datestr and return a corresponding number of microseconds. + * + * @param datestr String representing a date or a duration. + * See av_parse_time() for the syntax of the provided string. + * @deprecated in favor of av_parse_time() + */ +attribute_deprecated +int64_t parse_date(const char *datestr, int duration); +#endif + +/** + * Get the current time in microseconds. + */ +int64_t av_gettime(void); + +#if FF_API_FIND_INFO_TAG +/** + * @deprecated use av_find_info_tag in libavutil instead. + */ +attribute_deprecated int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info); +#endif + +/** + * Return in 'buf' the path with '%d' replaced by a number. + * + * Also handles the '%0nd' format where 'n' is the total number + * of digits and '%%'. + * + * @param buf destination buffer + * @param buf_size destination buffer size + * @param path numbered sequence string + * @param number frame number + * @return 0 if OK, -1 on format error + */ +int av_get_frame_filename(char *buf, int buf_size, + const char *path, int number); + +/** + * Check whether filename actually is a numbered sequence generator. + * + * @param filename possible numbered sequence string + * @return 1 if a valid numbered sequence string, 0 otherwise + */ +int av_filename_number_test(const char *filename); + +/** + * Generate an SDP for an RTP session. + * + * @param ac array of AVFormatContexts describing the RTP streams. If the + * array is composed by only one context, such context can contain + * multiple AVStreams (one AVStream per RTP stream). Otherwise, + * all the contexts in the array (an AVCodecContext per RTP stream) + * must contain only one AVStream. + * @param n_files number of AVCodecContexts contained in ac + * @param buf buffer where the SDP will be stored (must be allocated by + * the caller) + * @param size the size of the buffer + * @return 0 if OK, AVERROR_xxx on error + */ +int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size); + +#if FF_API_SDP_CREATE +attribute_deprecated int avf_sdp_create(AVFormatContext *ac[], int n_files, char *buff, int size); +#endif + +/** + * Return a positive value if the given filename has one of the given + * extensions, 0 otherwise. + * + * @param extensions a comma-separated list of filename extensions + */ +int av_match_ext(const char *filename, const char *extensions); + +/** + * Test if the given container can store a codec. + * + * @param std_compliance standards compliance level, one of FF_COMPLIANCE_* + * + * @return 1 if codec with ID codec_id can be stored in ofmt, 0 if it cannot. + * A negative number if this information is not available. + */ +int avformat_query_codec(AVOutputFormat *ofmt, enum CodecID codec_id, int std_compliance); + +/** + * @} + */ + +#endif /* AVFORMAT_AVFORMAT_H */ diff --git a/Externals/ffmpeg/include/libavformat/avio.h b/Externals/ffmpeg/include/libavformat/avio.h new file mode 100644 index 0000000000..a8698a841 --- /dev/null +++ b/Externals/ffmpeg/include/libavformat/avio.h @@ -0,0 +1,695 @@ +/* + * copyright (c) 2001 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef AVFORMAT_AVIO_H +#define AVFORMAT_AVIO_H + +/** + * @file + * @ingroup lavf_io + * Buffered I/O operations + */ + +#include + +#include "libavutil/common.h" +#include "libavutil/dict.h" +#include "libavutil/log.h" + +#include "libavformat/version.h" + + +#define AVIO_SEEKABLE_NORMAL 0x0001 /**< Seeking works like for a local file */ + +/** + * Callback for checking whether to abort blocking functions. + * AVERROR_EXIT is returned in this case by the interrupted + * function. During blocking operations, callback is called with + * opaque as parameter. If the callback returns 1, the + * blocking operation will be aborted. + * + * No members can be added to this struct without a major bump, if + * new elements have been added after this struct in AVFormatContext + * or AVIOContext. + */ +typedef struct { + int (*callback)(void*); + void *opaque; +} AVIOInterruptCB; + +/** + * Bytestream IO Context. + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * sizeof(AVIOContext) must not be used outside libav*. + * + * @note None of the function pointers in AVIOContext should be called + * directly, they should only be set by the client application + * when implementing custom I/O. Normally these are set to the + * function pointers specified in avio_alloc_context() + */ +typedef struct { +#if !FF_API_OLD_AVIO + /** + * A class for private options. + * + * If this AVIOContext is created by avio_open2(), av_class is set and + * passes the options down to protocols. + * + * If this AVIOContext is manually allocated, then av_class may be set by + * the caller. + * + * warning -- this field can be NULL, be sure to not pass this AVIOContext + * to any av_opt_* functions in that case. + */ + AVClass *av_class; +#endif + unsigned char *buffer; /**< Start of the buffer. */ + int buffer_size; /**< Maximum buffer size */ + unsigned char *buf_ptr; /**< Current position in the buffer */ + unsigned char *buf_end; /**< End of the data, may be less than + buffer+buffer_size if the read function returned + less data than requested, e.g. for streams where + no more data has been received yet. */ + void *opaque; /**< A private pointer, passed to the read/write/seek/... + functions. */ + int (*read_packet)(void *opaque, uint8_t *buf, int buf_size); + int (*write_packet)(void *opaque, uint8_t *buf, int buf_size); + int64_t (*seek)(void *opaque, int64_t offset, int whence); + int64_t pos; /**< position in the file of the current buffer */ + int must_flush; /**< true if the next seek should flush */ + int eof_reached; /**< true if eof reached */ + int write_flag; /**< true if open for writing */ +#if FF_API_OLD_AVIO + attribute_deprecated int is_streamed; +#endif + int max_packet_size; + unsigned long checksum; + unsigned char *checksum_ptr; + unsigned long (*update_checksum)(unsigned long checksum, const uint8_t *buf, unsigned int size); + int error; /**< contains the error code or 0 if no error happened */ + /** + * Pause or resume playback for network streaming protocols - e.g. MMS. + */ + int (*read_pause)(void *opaque, int pause); + /** + * Seek to a given timestamp in stream with the specified stream_index. + * Needed for some network streaming protocols which don't support seeking + * to byte position. + */ + int64_t (*read_seek)(void *opaque, int stream_index, + int64_t timestamp, int flags); + /** + * A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable. + */ + int seekable; + + /** + * max filesize, used to limit allocations + * This field is internal to libavformat and access from outside is not allowed. + */ + int64_t maxsize; +} AVIOContext; + +/* unbuffered I/O */ + +#if FF_API_OLD_AVIO +/** + * URL Context. + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * sizeof(URLContext) must not be used outside libav*. + * @deprecated This struct will be made private + */ +typedef struct URLContext { + const AVClass *av_class; ///< information for av_log(). Set by url_open(). + struct URLProtocol *prot; + int flags; + int is_streamed; /**< true if streamed (no seek possible), default = false */ + int max_packet_size; /**< if non zero, the stream is packetized with this max packet size */ + void *priv_data; + char *filename; /**< specified URL */ + int is_connected; + AVIOInterruptCB interrupt_callback; +} URLContext; + +#define URL_PROTOCOL_FLAG_NESTED_SCHEME 1 /*< The protocol name can be the first part of a nested protocol scheme */ +#define URL_PROTOCOL_FLAG_NETWORK 2 /*< The protocol uses network */ + +/** + * @deprecated This struct is to be made private. Use the higher-level + * AVIOContext-based API instead. + */ +typedef struct URLProtocol { + const char *name; + int (*url_open)(URLContext *h, const char *url, int flags); + int (*url_read)(URLContext *h, unsigned char *buf, int size); + int (*url_write)(URLContext *h, const unsigned char *buf, int size); + int64_t (*url_seek)(URLContext *h, int64_t pos, int whence); + int (*url_close)(URLContext *h); + struct URLProtocol *next; + int (*url_read_pause)(URLContext *h, int pause); + int64_t (*url_read_seek)(URLContext *h, int stream_index, + int64_t timestamp, int flags); + int (*url_get_file_handle)(URLContext *h); + int priv_data_size; + const AVClass *priv_data_class; + int flags; + int (*url_check)(URLContext *h, int mask); +} URLProtocol; + +typedef struct URLPollEntry { + URLContext *handle; + int events; + int revents; +} URLPollEntry; + +/* not implemented */ +attribute_deprecated int url_poll(URLPollEntry *poll_table, int n, int timeout); + +/** + * @name URL open modes + * The flags argument to url_open and cosins must be one of the following + * constants, optionally ORed with other flags. + * @{ + */ +#define URL_RDONLY 1 /**< read-only */ +#define URL_WRONLY 2 /**< write-only */ +#define URL_RDWR (URL_RDONLY|URL_WRONLY) /**< read-write */ +/** + * @} + */ + +/** + * Use non-blocking mode. + * If this flag is set, operations on the context will return + * AVERROR(EAGAIN) if they can not be performed immediately. + * If this flag is not set, operations on the context will never return + * AVERROR(EAGAIN). + * Note that this flag does not affect the opening/connecting of the + * context. Connecting a protocol will always block if necessary (e.g. on + * network protocols) but never hang (e.g. on busy devices). + * Warning: non-blocking protocols is work-in-progress; this flag may be + * silently ignored. + */ +#define URL_FLAG_NONBLOCK 8 + +typedef int URLInterruptCB(void); +extern URLInterruptCB *url_interrupt_cb; + +/** + * @defgroup old_url_funcs Old url_* functions + * The following functions are deprecated. Use the buffered API based on #AVIOContext instead. + * @{ + * @ingroup lavf_io + */ +attribute_deprecated int url_open_protocol (URLContext **puc, struct URLProtocol *up, + const char *url, int flags); +attribute_deprecated int url_alloc(URLContext **h, const char *url, int flags); +attribute_deprecated int url_connect(URLContext *h); +attribute_deprecated int url_open(URLContext **h, const char *url, int flags); +attribute_deprecated int url_read(URLContext *h, unsigned char *buf, int size); +attribute_deprecated int url_read_complete(URLContext *h, unsigned char *buf, int size); +attribute_deprecated int url_write(URLContext *h, const unsigned char *buf, int size); +attribute_deprecated int64_t url_seek(URLContext *h, int64_t pos, int whence); +attribute_deprecated int url_close(URLContext *h); +attribute_deprecated int64_t url_filesize(URLContext *h); +attribute_deprecated int url_get_file_handle(URLContext *h); +attribute_deprecated int url_get_max_packet_size(URLContext *h); +attribute_deprecated void url_get_filename(URLContext *h, char *buf, int buf_size); +attribute_deprecated int av_url_read_pause(URLContext *h, int pause); +attribute_deprecated int64_t av_url_read_seek(URLContext *h, int stream_index, + int64_t timestamp, int flags); +attribute_deprecated void url_set_interrupt_cb(int (*interrupt_cb)(void)); + +/** + * returns the next registered protocol after the given protocol (the first if + * NULL is given), or NULL if protocol is the last one. + */ +URLProtocol *av_protocol_next(URLProtocol *p); + +/** + * Register the URLProtocol protocol. + * + * @param size the size of the URLProtocol struct referenced + */ +attribute_deprecated int av_register_protocol2(URLProtocol *protocol, int size); +/** + * @} + */ + + +typedef attribute_deprecated AVIOContext ByteIOContext; + +attribute_deprecated int init_put_byte(AVIOContext *s, + unsigned char *buffer, + int buffer_size, + int write_flag, + void *opaque, + int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), + int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), + int64_t (*seek)(void *opaque, int64_t offset, int whence)); +attribute_deprecated AVIOContext *av_alloc_put_byte( + unsigned char *buffer, + int buffer_size, + int write_flag, + void *opaque, + int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), + int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), + int64_t (*seek)(void *opaque, int64_t offset, int whence)); + +/** + * @defgroup old_avio_funcs Old put_/get_*() functions + * The following functions are deprecated. Use the "avio_"-prefixed functions instead. + * @{ + * @ingroup lavf_io + */ +attribute_deprecated int get_buffer(AVIOContext *s, unsigned char *buf, int size); +attribute_deprecated int get_partial_buffer(AVIOContext *s, unsigned char *buf, int size); +attribute_deprecated int get_byte(AVIOContext *s); +attribute_deprecated unsigned int get_le16(AVIOContext *s); +attribute_deprecated unsigned int get_le24(AVIOContext *s); +attribute_deprecated unsigned int get_le32(AVIOContext *s); +attribute_deprecated uint64_t get_le64(AVIOContext *s); +attribute_deprecated unsigned int get_be16(AVIOContext *s); +attribute_deprecated unsigned int get_be24(AVIOContext *s); +attribute_deprecated unsigned int get_be32(AVIOContext *s); +attribute_deprecated uint64_t get_be64(AVIOContext *s); + +attribute_deprecated void put_byte(AVIOContext *s, int b); +attribute_deprecated void put_nbyte(AVIOContext *s, int b, int count); +attribute_deprecated void put_buffer(AVIOContext *s, const unsigned char *buf, int size); +attribute_deprecated void put_le64(AVIOContext *s, uint64_t val); +attribute_deprecated void put_be64(AVIOContext *s, uint64_t val); +attribute_deprecated void put_le32(AVIOContext *s, unsigned int val); +attribute_deprecated void put_be32(AVIOContext *s, unsigned int val); +attribute_deprecated void put_le24(AVIOContext *s, unsigned int val); +attribute_deprecated void put_be24(AVIOContext *s, unsigned int val); +attribute_deprecated void put_le16(AVIOContext *s, unsigned int val); +attribute_deprecated void put_be16(AVIOContext *s, unsigned int val); +attribute_deprecated void put_tag(AVIOContext *s, const char *tag); +/** + * @} + */ + +attribute_deprecated int av_url_read_fpause(AVIOContext *h, int pause); +attribute_deprecated int64_t av_url_read_fseek (AVIOContext *h, int stream_index, + int64_t timestamp, int flags); + +/** + * @defgroup old_url_f_funcs Old url_f* functions + * The following functions are deprecated, use the "avio_"-prefixed functions instead. + * @{ + * @ingroup lavf_io + */ +attribute_deprecated int url_fopen( AVIOContext **s, const char *url, int flags); +attribute_deprecated int url_fclose(AVIOContext *s); +attribute_deprecated int64_t url_fseek(AVIOContext *s, int64_t offset, int whence); +attribute_deprecated int url_fskip(AVIOContext *s, int64_t offset); +attribute_deprecated int64_t url_ftell(AVIOContext *s); +attribute_deprecated int64_t url_fsize(AVIOContext *s); +#define URL_EOF (-1) +attribute_deprecated int url_fgetc(AVIOContext *s); +attribute_deprecated int url_setbufsize(AVIOContext *s, int buf_size); +attribute_deprecated int url_fprintf(AVIOContext *s, const char *fmt, ...) av_printf_format(2, 3); +attribute_deprecated void put_flush_packet(AVIOContext *s); +attribute_deprecated int url_open_dyn_buf(AVIOContext **s); +attribute_deprecated int url_open_dyn_packet_buf(AVIOContext **s, int max_packet_size); +attribute_deprecated int url_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer); +attribute_deprecated int url_fdopen(AVIOContext **s, URLContext *h); +/** + * @} + */ + +attribute_deprecated int url_ferror(AVIOContext *s); + +attribute_deprecated int udp_set_remote_url(URLContext *h, const char *uri); +attribute_deprecated int udp_get_local_port(URLContext *h); + +attribute_deprecated void init_checksum(AVIOContext *s, + unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), + unsigned long checksum); +attribute_deprecated unsigned long get_checksum(AVIOContext *s); +attribute_deprecated void put_strz(AVIOContext *s, const char *buf); +/** @note unlike fgets, the EOL character is not returned and a whole + line is parsed. return NULL if first char read was EOF */ +attribute_deprecated char *url_fgets(AVIOContext *s, char *buf, int buf_size); +/** + * @deprecated use avio_get_str instead + */ +attribute_deprecated char *get_strz(AVIOContext *s, char *buf, int maxlen); +/** + * @deprecated Use AVIOContext.seekable field directly. + */ +attribute_deprecated static inline int url_is_streamed(AVIOContext *s) +{ + return !s->seekable; +} +attribute_deprecated URLContext *url_fileno(AVIOContext *s); + +/** + * @deprecated use AVIOContext.max_packet_size directly. + */ +attribute_deprecated int url_fget_max_packet_size(AVIOContext *s); + +attribute_deprecated int url_open_buf(AVIOContext **s, uint8_t *buf, int buf_size, int flags); + +/** return the written or read size */ +attribute_deprecated int url_close_buf(AVIOContext *s); + +/** + * Return a non-zero value if the resource indicated by url + * exists, 0 otherwise. + * @deprecated Use avio_check instead. + */ +attribute_deprecated int url_exist(const char *url); +#endif // FF_API_OLD_AVIO + +/** + * Return AVIO_FLAG_* access flags corresponding to the access permissions + * of the resource in url, or a negative value corresponding to an + * AVERROR code in case of failure. The returned access flags are + * masked by the value in flags. + * + * @note This function is intrinsically unsafe, in the sense that the + * checked resource may change its existence or permission status from + * one call to another. Thus you should not trust the returned value, + * unless you are sure that no other processes are accessing the + * checked resource. + */ +int avio_check(const char *url, int flags); + +#if FF_API_OLD_INTERRUPT_CB +/** + * The callback is called in blocking functions to test regulary if + * asynchronous interruption is needed. AVERROR_EXIT is returned + * in this case by the interrupted function. 'NULL' means no interrupt + * callback is given. + * @deprecated Use interrupt_callback in AVFormatContext/avio_open2 + * instead. + */ +attribute_deprecated void avio_set_interrupt_cb(int (*interrupt_cb)(void)); +#endif + +/** + * Allocate and initialize an AVIOContext for buffered I/O. It must be later + * freed with av_free(). + * + * @param buffer Memory block for input/output operations via AVIOContext. + * The buffer must be allocated with av_malloc() and friends. + * @param buffer_size The buffer size is very important for performance. + * For protocols with fixed blocksize it should be set to this blocksize. + * For others a typical size is a cache page, e.g. 4kb. + * @param write_flag Set to 1 if the buffer should be writable, 0 otherwise. + * @param opaque An opaque pointer to user-specific data. + * @param read_packet A function for refilling the buffer, may be NULL. + * @param write_packet A function for writing the buffer contents, may be NULL. + * @param seek A function for seeking to specified byte position, may be NULL. + * + * @return Allocated AVIOContext or NULL on failure. + */ +AVIOContext *avio_alloc_context( + unsigned char *buffer, + int buffer_size, + int write_flag, + void *opaque, + int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), + int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), + int64_t (*seek)(void *opaque, int64_t offset, int whence)); + +void avio_w8(AVIOContext *s, int b); +void avio_write(AVIOContext *s, const unsigned char *buf, int size); +void avio_wl64(AVIOContext *s, uint64_t val); +void avio_wb64(AVIOContext *s, uint64_t val); +void avio_wl32(AVIOContext *s, unsigned int val); +void avio_wb32(AVIOContext *s, unsigned int val); +void avio_wl24(AVIOContext *s, unsigned int val); +void avio_wb24(AVIOContext *s, unsigned int val); +void avio_wl16(AVIOContext *s, unsigned int val); +void avio_wb16(AVIOContext *s, unsigned int val); + +/** + * Write a NULL-terminated string. + * @return number of bytes written. + */ +int avio_put_str(AVIOContext *s, const char *str); + +/** + * Convert an UTF-8 string to UTF-16LE and write it. + * @return number of bytes written. + */ +int avio_put_str16le(AVIOContext *s, const char *str); + +/** + * Passing this as the "whence" parameter to a seek function causes it to + * return the filesize without seeking anywhere. Supporting this is optional. + * If it is not supported then the seek function will return <0. + */ +#define AVSEEK_SIZE 0x10000 + +/** + * Oring this flag as into the "whence" parameter to a seek function causes it to + * seek by any means (like reopening and linear reading) or other normally unreasonble + * means that can be extreemly slow. + * This may be ignored by the seek code. + */ +#define AVSEEK_FORCE 0x20000 + +/** + * fseek() equivalent for AVIOContext. + * @return new position or AVERROR. + */ +int64_t avio_seek(AVIOContext *s, int64_t offset, int whence); + +/** + * Skip given number of bytes forward + * @return new position or AVERROR. + */ +int64_t avio_skip(AVIOContext *s, int64_t offset); + +/** + * ftell() equivalent for AVIOContext. + * @return position or AVERROR. + */ +static av_always_inline int64_t avio_tell(AVIOContext *s) +{ + return avio_seek(s, 0, SEEK_CUR); +} + +/** + * Get the filesize. + * @return filesize or AVERROR + */ +int64_t avio_size(AVIOContext *s); + +/** + * feof() equivalent for AVIOContext. + * @return non zero if and only if end of file + */ +int url_feof(AVIOContext *s); + +/** @warning currently size is limited */ +int avio_printf(AVIOContext *s, const char *fmt, ...) av_printf_format(2, 3); + +void avio_flush(AVIOContext *s); + + +/** + * Read size bytes from AVIOContext into buf. + * @return number of bytes read or AVERROR + */ +int avio_read(AVIOContext *s, unsigned char *buf, int size); + +/** + * @name Functions for reading from AVIOContext + * @{ + * + * @note return 0 if EOF, so you cannot use it if EOF handling is + * necessary + */ +int avio_r8 (AVIOContext *s); +unsigned int avio_rl16(AVIOContext *s); +unsigned int avio_rl24(AVIOContext *s); +unsigned int avio_rl32(AVIOContext *s); +uint64_t avio_rl64(AVIOContext *s); +unsigned int avio_rb16(AVIOContext *s); +unsigned int avio_rb24(AVIOContext *s); +unsigned int avio_rb32(AVIOContext *s); +uint64_t avio_rb64(AVIOContext *s); +/** + * @} + */ + +/** + * Read a string from pb into buf. The reading will terminate when either + * a NULL character was encountered, maxlen bytes have been read, or nothing + * more can be read from pb. The result is guaranteed to be NULL-terminated, it + * will be truncated if buf is too small. + * Note that the string is not interpreted or validated in any way, it + * might get truncated in the middle of a sequence for multi-byte encodings. + * + * @return number of bytes read (is always <= maxlen). + * If reading ends on EOF or error, the return value will be one more than + * bytes actually read. + */ +int avio_get_str(AVIOContext *pb, int maxlen, char *buf, int buflen); + +/** + * Read a UTF-16 string from pb and convert it to UTF-8. + * The reading will terminate when either a null or invalid character was + * encountered or maxlen bytes have been read. + * @return number of bytes read (is always <= maxlen) + */ +int avio_get_str16le(AVIOContext *pb, int maxlen, char *buf, int buflen); +int avio_get_str16be(AVIOContext *pb, int maxlen, char *buf, int buflen); + + +/** + * @name URL open modes + * The flags argument to avio_open must be one of the following + * constants, optionally ORed with other flags. + * @{ + */ +#define AVIO_FLAG_READ 1 /**< read-only */ +#define AVIO_FLAG_WRITE 2 /**< write-only */ +#define AVIO_FLAG_READ_WRITE (AVIO_FLAG_READ|AVIO_FLAG_WRITE) /**< read-write pseudo flag */ +/** + * @} + */ + +/** + * Use non-blocking mode. + * If this flag is set, operations on the context will return + * AVERROR(EAGAIN) if they can not be performed immediately. + * If this flag is not set, operations on the context will never return + * AVERROR(EAGAIN). + * Note that this flag does not affect the opening/connecting of the + * context. Connecting a protocol will always block if necessary (e.g. on + * network protocols) but never hang (e.g. on busy devices). + * Warning: non-blocking protocols is work-in-progress; this flag may be + * silently ignored. + */ +#define AVIO_FLAG_NONBLOCK 8 + +/** + * Create and initialize a AVIOContext for accessing the + * resource indicated by url. + * @note When the resource indicated by url has been opened in + * read+write mode, the AVIOContext can be used only for writing. + * + * @param s Used to return the pointer to the created AVIOContext. + * In case of failure the pointed to value is set to NULL. + * @param flags flags which control how the resource indicated by url + * is to be opened + * @return 0 in case of success, a negative value corresponding to an + * AVERROR code in case of failure + */ +int avio_open(AVIOContext **s, const char *url, int flags); + +/** + * Create and initialize a AVIOContext for accessing the + * resource indicated by url. + * @note When the resource indicated by url has been opened in + * read+write mode, the AVIOContext can be used only for writing. + * + * @param s Used to return the pointer to the created AVIOContext. + * In case of failure the pointed to value is set to NULL. + * @param flags flags which control how the resource indicated by url + * is to be opened + * @param int_cb an interrupt callback to be used at the protocols level + * @param options A dictionary filled with protocol-private options. On return + * this parameter will be destroyed and replaced with a dict containing options + * that were not found. May be NULL. + * @return 0 in case of success, a negative value corresponding to an + * AVERROR code in case of failure + */ +int avio_open2(AVIOContext **s, const char *url, int flags, + const AVIOInterruptCB *int_cb, AVDictionary **options); + +/** + * Close the resource accessed by the AVIOContext s and free it. + * This function can only be used if s was opened by avio_open(). + * + * @return 0 on success, an AVERROR < 0 on error. + */ +int avio_close(AVIOContext *s); + +/** + * Open a write only memory stream. + * + * @param s new IO context + * @return zero if no error. + */ +int avio_open_dyn_buf(AVIOContext **s); + +/** + * Return the written size and a pointer to the buffer. The buffer + * must be freed with av_free(). + * Padding of FF_INPUT_BUFFER_PADDING_SIZE is added to the buffer. + * + * @param s IO context + * @param pbuffer pointer to a byte buffer + * @return the length of the byte buffer + */ +int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer); + +/** + * Iterate through names of available protocols. + * @note it is recommanded to use av_protocol_next() instead of this + * + * @param opaque A private pointer representing current protocol. + * It must be a pointer to NULL on first iteration and will + * be updated by successive calls to avio_enum_protocols. + * @param output If set to 1, iterate over output protocols, + * otherwise over input protocols. + * + * @return A static string containing the name of current protocol or NULL + */ +const char *avio_enum_protocols(void **opaque, int output); + +/** + * Pause and resume playing - only meaningful if using a network streaming + * protocol (e.g. MMS). + * @param pause 1 for pause, 0 for resume + */ +int avio_pause(AVIOContext *h, int pause); + +/** + * Seek to a given timestamp relative to some component stream. + * Only meaningful if using a network streaming protocol (e.g. MMS.). + * @param stream_index The stream index that the timestamp is relative to. + * If stream_index is (-1) the timestamp should be in AV_TIME_BASE + * units from the beginning of the presentation. + * If a stream_index >= 0 is used and the protocol does not support + * seeking based on component streams, the call will fail. + * @param timestamp timestamp in AVStream.time_base units + * or if there is no stream specified then in AV_TIME_BASE units. + * @param flags Optional combination of AVSEEK_FLAG_BACKWARD, AVSEEK_FLAG_BYTE + * and AVSEEK_FLAG_ANY. The protocol may silently ignore + * AVSEEK_FLAG_BACKWARD and AVSEEK_FLAG_ANY, but AVSEEK_FLAG_BYTE will + * fail if used and not supported. + * @return >= 0 on success + * @see AVInputFormat::read_seek + */ +int64_t avio_seek_time(AVIOContext *h, int stream_index, + int64_t timestamp, int flags); + +#endif /* AVFORMAT_AVIO_H */ diff --git a/Externals/ffmpeg/include/libavformat/version.h b/Externals/ffmpeg/include/libavformat/version.h new file mode 100644 index 0000000000..f3848da6b --- /dev/null +++ b/Externals/ffmpeg/include/libavformat/version.h @@ -0,0 +1,129 @@ +/* + * Version macros. + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_VERSION_H +#define AVFORMAT_VERSION_H + +/** + * @file + * @ingroup libavf + * Libavformat version macros + */ + +#include "libavutil/avutil.h" + +#define LIBAVFORMAT_VERSION_MAJOR 53 +#define LIBAVFORMAT_VERSION_MINOR 31 +#define LIBAVFORMAT_VERSION_MICRO 100 + +#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ + LIBAVFORMAT_VERSION_MINOR, \ + LIBAVFORMAT_VERSION_MICRO) +#define LIBAVFORMAT_VERSION AV_VERSION(LIBAVFORMAT_VERSION_MAJOR, \ + LIBAVFORMAT_VERSION_MINOR, \ + LIBAVFORMAT_VERSION_MICRO) +#define LIBAVFORMAT_BUILD LIBAVFORMAT_VERSION_INT + +#define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION) + +/** + * Those FF_API_* defines are not part of public API. + * They may change, break or disappear at any time. + */ +#ifndef FF_API_OLD_METADATA2 +#define FF_API_OLD_METADATA2 (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_OLD_AVIO +#define FF_API_OLD_AVIO (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_DUMP_FORMAT +#define FF_API_DUMP_FORMAT (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_PARSE_DATE +#define FF_API_PARSE_DATE (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_FIND_INFO_TAG +#define FF_API_FIND_INFO_TAG (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_PKT_DUMP +#define FF_API_PKT_DUMP (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_GUESS_IMG2_CODEC +#define FF_API_GUESS_IMG2_CODEC (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_SDP_CREATE +#define FF_API_SDP_CREATE (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_ALLOC_OUTPUT_CONTEXT +#define FF_API_ALLOC_OUTPUT_CONTEXT (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_FORMAT_PARAMETERS +#define FF_API_FORMAT_PARAMETERS (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_FLAG_RTP_HINT +#define FF_API_FLAG_RTP_HINT (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_AVSTREAM_QUALITY +#define FF_API_AVSTREAM_QUALITY (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_LOOP_INPUT +#define FF_API_LOOP_INPUT (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_LOOP_OUTPUT +#define FF_API_LOOP_OUTPUT (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_TIMESTAMP +#define FF_API_TIMESTAMP (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_FILESIZE +#define FF_API_FILESIZE (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_MUXRATE +#define FF_API_MUXRATE (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_RTSP_URL_OPTIONS +#define FF_API_RTSP_URL_OPTIONS (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_NEW_STREAM +#define FF_API_NEW_STREAM (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_PRELOAD +#define FF_API_PRELOAD (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_STREAM_COPY +#define FF_API_STREAM_COPY (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_SEEK_PUBLIC +#define FF_API_SEEK_PUBLIC (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_REORDER_PRIVATE +#define FF_API_REORDER_PRIVATE (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_OLD_INTERRUPT_CB +#define FF_API_OLD_INTERRUPT_CB (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_SET_PTS_INFO +#define FF_API_SET_PTS_INFO (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_CLOSE_INPUT_FILE +#define FF_API_CLOSE_INPUT_FILE (LIBAVFORMAT_VERSION_MAJOR < 55) +#endif + +#endif /* AVFORMAT_VERSION_H */ diff --git a/Externals/ffmpeg/include/libavutil/adler32.h b/Externals/ffmpeg/include/libavutil/adler32.h new file mode 100644 index 0000000000..e926ef6cc --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/adler32.h @@ -0,0 +1,43 @@ +/* + * copyright (c) 2006 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_ADLER32_H +#define AVUTIL_ADLER32_H + +#include +#include "attributes.h" + +/** + * @ingroup lavu_crypto + * Calculate the Adler32 checksum of a buffer. + * + * Passing the return value to a subsequent av_adler32_update() call + * allows the checksum of multiple buffers to be calculated as though + * they were concatenated. + * + * @param adler initial checksum value + * @param buf pointer to input buffer + * @param len size of input buffer + * @return updated checksum + */ +unsigned long av_adler32_update(unsigned long adler, const uint8_t *buf, + unsigned int len) av_pure; + +#endif /* AVUTIL_ADLER32_H */ diff --git a/Externals/ffmpeg/include/libavutil/aes.h b/Externals/ffmpeg/include/libavutil/aes.h new file mode 100644 index 0000000000..bafa4cc3c --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/aes.h @@ -0,0 +1,57 @@ +/* + * copyright (c) 2007 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_AES_H +#define AVUTIL_AES_H + +#include + +/** + * @defgroup lavu_aes AES + * @ingroup lavu_crypto + * @{ + */ + +extern const int av_aes_size; + +struct AVAES; + +/** + * Initialize an AVAES context. + * @param key_bits 128, 192 or 256 + * @param decrypt 0 for encryption, 1 for decryption + */ +int av_aes_init(struct AVAES *a, const uint8_t *key, int key_bits, int decrypt); + +/** + * Encrypt or decrypt a buffer using a previously initialized context. + * @param count number of 16 byte blocks + * @param dst destination array, can be equal to src + * @param src source array, can be equal to dst + * @param iv initialization vector for CBC mode, if NULL then ECB will be used + * @param decrypt 0 for encryption, 1 for decryption + */ +void av_aes_crypt(struct AVAES *a, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt); + +/** + * @} + */ + +#endif /* AVUTIL_AES_H */ diff --git a/Externals/ffmpeg/include/libavutil/attributes.h b/Externals/ffmpeg/include/libavutil/attributes.h new file mode 100644 index 0000000000..0a6fda172 --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/attributes.h @@ -0,0 +1,162 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Macro definitions for various function/variable attributes + */ + +#ifndef AVUTIL_ATTRIBUTES_H +#define AVUTIL_ATTRIBUTES_H + +#ifdef __GNUC__ +# define AV_GCC_VERSION_AT_LEAST(x,y) (__GNUC__ > x || __GNUC__ == x && __GNUC_MINOR__ >= y) +#else +# define AV_GCC_VERSION_AT_LEAST(x,y) 0 +#endif + +#ifndef av_always_inline +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define av_always_inline __attribute__((always_inline)) inline +#else +# define av_always_inline inline +#endif +#endif + +#ifndef av_noreturn +#if AV_GCC_VERSION_AT_LEAST(2,5) +# define av_noreturn __attribute__((noreturn)) +#else +# define av_noreturn +#endif +#endif + +#ifndef av_noinline +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define av_noinline __attribute__((noinline)) +#else +# define av_noinline +#endif +#endif + +#ifndef av_pure +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define av_pure __attribute__((pure)) +#else +# define av_pure +#endif +#endif + +#ifndef av_const +#if AV_GCC_VERSION_AT_LEAST(2,6) +# define av_const __attribute__((const)) +#else +# define av_const +#endif +#endif + +#ifndef av_cold +#if AV_GCC_VERSION_AT_LEAST(4,3) +# define av_cold __attribute__((cold)) +#else +# define av_cold +#endif +#endif + +#ifndef av_flatten +#if AV_GCC_VERSION_AT_LEAST(4,1) +# define av_flatten __attribute__((flatten)) +#else +# define av_flatten +#endif +#endif + +#ifndef attribute_deprecated +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define attribute_deprecated __attribute__((deprecated)) +#else +# define attribute_deprecated +#endif +#endif + +/** + * Disable warnings about deprecated features + * This is useful for sections of code kept for backward compatibility and + * scheduled for removal. + */ +#ifndef AV_NOWARN_DEPRECATED +#if AV_GCC_VERSION_AT_LEAST(4,6) +# define AV_NOWARN_DEPRECATED(code) \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") \ + code \ + _Pragma("GCC diagnostic pop") +#else +# define AV_NOWARN_DEPRECATED(code) code +#endif +#endif + + +#ifndef av_unused +#if defined(__GNUC__) +# define av_unused __attribute__((unused)) +#else +# define av_unused +#endif +#endif + +/** + * Mark a variable as used and prevent the compiler from optimizing it + * away. This is useful for variables accessed only from inline + * assembler without the compiler being aware. + */ +#ifndef av_used +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define av_used __attribute__((used)) +#else +# define av_used +#endif +#endif + +#ifndef av_alias +#if AV_GCC_VERSION_AT_LEAST(3,3) +# define av_alias __attribute__((may_alias)) +#else +# define av_alias +#endif +#endif + +#ifndef av_uninit +#if defined(__GNUC__) && !defined(__INTEL_COMPILER) +# define av_uninit(x) x=x +#else +# define av_uninit(x) x +#endif +#endif + +#ifdef __GNUC__ +# define av_builtin_constant_p __builtin_constant_p +# define av_printf_format(fmtpos, attrpos) __attribute__((__format__(__printf__, fmtpos, attrpos))) +#else +# define av_builtin_constant_p(x) 0 +# define av_printf_format(fmtpos, attrpos) +#endif + +#endif /* AVUTIL_ATTRIBUTES_H */ diff --git a/Externals/ffmpeg/include/libavutil/audioconvert.h b/Externals/ffmpeg/include/libavutil/audioconvert.h new file mode 100644 index 0000000000..29ec1cbc0 --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/audioconvert.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2006 Michael Niedermayer + * Copyright (c) 2008 Peter Ross + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_AUDIOCONVERT_H +#define AVUTIL_AUDIOCONVERT_H + +#include + +/** + * @file + * audio conversion routines + */ + +/** + * @addtogroup lavu_audio + * @{ + */ + +/** + * @defgroup channel_masks Audio channel masks + * @{ + */ +#define AV_CH_FRONT_LEFT 0x00000001 +#define AV_CH_FRONT_RIGHT 0x00000002 +#define AV_CH_FRONT_CENTER 0x00000004 +#define AV_CH_LOW_FREQUENCY 0x00000008 +#define AV_CH_BACK_LEFT 0x00000010 +#define AV_CH_BACK_RIGHT 0x00000020 +#define AV_CH_FRONT_LEFT_OF_CENTER 0x00000040 +#define AV_CH_FRONT_RIGHT_OF_CENTER 0x00000080 +#define AV_CH_BACK_CENTER 0x00000100 +#define AV_CH_SIDE_LEFT 0x00000200 +#define AV_CH_SIDE_RIGHT 0x00000400 +#define AV_CH_TOP_CENTER 0x00000800 +#define AV_CH_TOP_FRONT_LEFT 0x00001000 +#define AV_CH_TOP_FRONT_CENTER 0x00002000 +#define AV_CH_TOP_FRONT_RIGHT 0x00004000 +#define AV_CH_TOP_BACK_LEFT 0x00008000 +#define AV_CH_TOP_BACK_CENTER 0x00010000 +#define AV_CH_TOP_BACK_RIGHT 0x00020000 +#define AV_CH_STEREO_LEFT 0x20000000 ///< Stereo downmix. +#define AV_CH_STEREO_RIGHT 0x40000000 ///< See AV_CH_STEREO_LEFT. +#define AV_CH_WIDE_LEFT 0x0000000080000000ULL +#define AV_CH_WIDE_RIGHT 0x0000000100000000ULL +#define AV_CH_SURROUND_DIRECT_LEFT 0x0000000200000000ULL +#define AV_CH_SURROUND_DIRECT_RIGHT 0x0000000400000000ULL + +/** Channel mask value used for AVCodecContext.request_channel_layout + to indicate that the user requests the channel order of the decoder output + to be the native codec channel order. */ +#define AV_CH_LAYOUT_NATIVE 0x8000000000000000ULL + +/** + * @} + * @defgroup channel_mask_c Audio channel convenience macros + * @{ + * */ +#define AV_CH_LAYOUT_MONO (AV_CH_FRONT_CENTER) +#define AV_CH_LAYOUT_STEREO (AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT) +#define AV_CH_LAYOUT_2POINT1 (AV_CH_LAYOUT_STEREO|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_2_1 (AV_CH_LAYOUT_STEREO|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_SURROUND (AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER) +#define AV_CH_LAYOUT_3POINT1 (AV_CH_LAYOUT_SURROUND|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_4POINT0 (AV_CH_LAYOUT_SURROUND|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_4POINT1 (AV_CH_LAYOUT_4POINT0|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_2_2 (AV_CH_LAYOUT_STEREO|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT) +#define AV_CH_LAYOUT_QUAD (AV_CH_LAYOUT_STEREO|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_5POINT0 (AV_CH_LAYOUT_SURROUND|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT) +#define AV_CH_LAYOUT_5POINT1 (AV_CH_LAYOUT_5POINT0|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_5POINT0_BACK (AV_CH_LAYOUT_SURROUND|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_5POINT1_BACK (AV_CH_LAYOUT_5POINT0_BACK|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_6POINT0 (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT0_FRONT (AV_CH_LAYOUT_2_2|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_HEXAGONAL (AV_CH_LAYOUT_5POINT0_BACK|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT1 (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT1_BACK (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT1_FRONT (AV_CH_LAYOUT_6POINT0_FRONT|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_7POINT0 (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_7POINT0_FRONT (AV_CH_LAYOUT_5POINT0|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_7POINT1 (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_7POINT1_WIDE (AV_CH_LAYOUT_5POINT1|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_OCTAGONAL (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_CENTER|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_STEREO_DOWNMIX (AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT) + +/** + * @} + */ + +/** + * Return a channel layout id that matches name, 0 if no match. + * name can be one or several of the following notations, + * separated by '+' or '|': + * - the name of an usual channel layout (mono, stereo, 4.0, quad, 5.0, + * 5.0(side), 5.1, 5.1(side), 7.1, 7.1(wide), downmix); + * - the name of a single channel (FL, FR, FC, LFE, BL, BR, FLC, FRC, BC, + * SL, SR, TC, TFL, TFC, TFR, TBL, TBC, TBR, DL, DR); + * - a number of channels, in decimal, optionnally followed by 'c', yielding + * the default channel layout for that number of channels (@see + * av_get_default_channel_layout); + * - a channel layout mask, in hexadecimal starting with "0x" (see the + * AV_CH_* macros). + + Example: "stereo+FC" = "2+FC" = "2c+1c" = "0x7" + */ +uint64_t av_get_channel_layout(const char *name); + +/** + * Return a description of a channel layout. + * If nb_channels is <= 0, it is guessed from the channel_layout. + * + * @param buf put here the string containing the channel layout + * @param buf_size size in bytes of the buffer + */ +void av_get_channel_layout_string(char *buf, int buf_size, int nb_channels, uint64_t channel_layout); + +/** + * Return the number of channels in the channel layout. + */ +int av_get_channel_layout_nb_channels(uint64_t channel_layout); + +/** + * Return default channel layout for a given number of channels. + */ +int64_t av_get_default_channel_layout(int nb_channels); + +/** + * @} + */ + +#endif /* AVUTIL_AUDIOCONVERT_H */ diff --git a/Externals/ffmpeg/include/libavutil/avassert.h b/Externals/ffmpeg/include/libavutil/avassert.h new file mode 100644 index 0000000000..e100d0bfd --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/avassert.h @@ -0,0 +1,66 @@ +/* + * copyright (c) 2010 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * simple assert() macros that are a bit more flexible than ISO C assert(). + * @author Michael Niedermayer + */ + +#ifndef AVUTIL_AVASSERT_H +#define AVUTIL_AVASSERT_H + +#include +#include "avutil.h" +#include "log.h" + +/** + * assert() equivalent, that is always enabled. + */ +#define av_assert0(cond) do { \ + if (!(cond)) { \ + av_log(NULL, AV_LOG_FATAL, "Assertion %s failed at %s:%d\n", \ + AV_STRINGIFY(cond), __FILE__, __LINE__); \ + abort(); \ + } \ +} while (0) + + +/** + * assert() equivalent, that does not lie in speed critical code. + * These asserts() thus can be enabled without fearing speedloss. + */ +#if defined(ASSERT_LEVEL) && ASSERT_LEVEL > 0 +#define av_assert1(cond) av_assert0(cond) +#else +#define av_assert1(cond) ((void)0) +#endif + + +/** + * assert() equivalent, that does lie in speed critical code. + */ +#if defined(ASSERT_LEVEL) && ASSERT_LEVEL > 1 +#define av_assert2(cond) av_assert0(cond) +#else +#define av_assert2(cond) ((void)0) +#endif + +#endif /* AVUTIL_AVASSERT_H */ diff --git a/Externals/ffmpeg/include/libavutil/avconfig.h b/Externals/ffmpeg/include/libavutil/avconfig.h new file mode 100644 index 0000000000..f10aa6186 --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/avconfig.h @@ -0,0 +1,6 @@ +/* Generated by ffconf */ +#ifndef AVUTIL_AVCONFIG_H +#define AVUTIL_AVCONFIG_H +#define AV_HAVE_BIGENDIAN 0 +#define AV_HAVE_FAST_UNALIGNED 1 +#endif /* AVUTIL_AVCONFIG_H */ diff --git a/Externals/ffmpeg/include/libavutil/avstring.h b/Externals/ffmpeg/include/libavutil/avstring.h new file mode 100644 index 0000000000..f73d6e742 --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/avstring.h @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2007 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_AVSTRING_H +#define AVUTIL_AVSTRING_H + +#include +#include "attributes.h" + +/** + * @addtogroup lavu_string + * @{ + */ + +/** + * Return non-zero if pfx is a prefix of str. If it is, *ptr is set to + * the address of the first character in str after the prefix. + * + * @param str input string + * @param pfx prefix to test + * @param ptr updated if the prefix is matched inside str + * @return non-zero if the prefix matches, zero otherwise + */ +int av_strstart(const char *str, const char *pfx, const char **ptr); + +/** + * Return non-zero if pfx is a prefix of str independent of case. If + * it is, *ptr is set to the address of the first character in str + * after the prefix. + * + * @param str input string + * @param pfx prefix to test + * @param ptr updated if the prefix is matched inside str + * @return non-zero if the prefix matches, zero otherwise + */ +int av_stristart(const char *str, const char *pfx, const char **ptr); + +/** + * Locate the first case-independent occurrence in the string haystack + * of the string needle. A zero-length string needle is considered to + * match at the start of haystack. + * + * This function is a case-insensitive version of the standard strstr(). + * + * @param haystack string to search in + * @param needle string to search for + * @return pointer to the located match within haystack + * or a null pointer if no match + */ +char *av_stristr(const char *haystack, const char *needle); + +/** + * Copy the string src to dst, but no more than size - 1 bytes, and + * null-terminate dst. + * + * This function is the same as BSD strlcpy(). + * + * @param dst destination buffer + * @param src source string + * @param size size of destination buffer + * @return the length of src + * + * @warning since the return value is the length of src, src absolutely + * _must_ be a properly 0-terminated string, otherwise this will read beyond + * the end of the buffer and possibly crash. + */ +size_t av_strlcpy(char *dst, const char *src, size_t size); + +/** + * Append the string src to the string dst, but to a total length of + * no more than size - 1 bytes, and null-terminate dst. + * + * This function is similar to BSD strlcat(), but differs when + * size <= strlen(dst). + * + * @param dst destination buffer + * @param src source string + * @param size size of destination buffer + * @return the total length of src and dst + * + * @warning since the return value use the length of src and dst, these + * absolutely _must_ be a properly 0-terminated strings, otherwise this + * will read beyond the end of the buffer and possibly crash. + */ +size_t av_strlcat(char *dst, const char *src, size_t size); + +/** + * Append output to a string, according to a format. Never write out of + * the destination buffer, and always put a terminating 0 within + * the buffer. + * @param dst destination buffer (string to which the output is + * appended) + * @param size total size of the destination buffer + * @param fmt printf-compatible format string, specifying how the + * following parameters are used + * @return the length of the string that would have been generated + * if enough space had been available + */ +size_t av_strlcatf(char *dst, size_t size, const char *fmt, ...) av_printf_format(3, 4); + +/** + * Print arguments following specified format into a large enough auto + * allocated buffer. It is similar to GNU asprintf(). + * @param fmt printf-compatible format string, specifying how the + * following parameters are used. + * @return the allocated string + * @note You have to free the string yourself with av_free(). + */ +char *av_asprintf(const char *fmt, ...) av_printf_format(1, 2); + +/** + * Convert a number to a av_malloced string. + */ +char *av_d2str(double d); + +/** + * Unescape the given string until a non escaped terminating char, + * and return the token corresponding to the unescaped string. + * + * The normal \ and ' escaping is supported. Leading and trailing + * whitespaces are removed, unless they are escaped with '\' or are + * enclosed between ''. + * + * @param buf the buffer to parse, buf will be updated to point to the + * terminating char + * @param term a 0-terminated list of terminating chars + * @return the malloced unescaped string, which must be av_freed by + * the user, NULL in case of allocation failure + */ +char *av_get_token(const char **buf, const char *term); + +/** + * Split the string into several tokens which can be accessed by + * successive calls to av_strtok(). + * + * A token is defined as a sequence of characters not belonging to the + * set specified in delim. + * + * On the first call to av_strtok(), s should point to the string to + * parse, and the value of saveptr is ignored. In subsequent calls, s + * should be NULL, and saveptr should be unchanged since the previous + * call. + * + * This function is similar to strtok_r() defined in POSIX.1. + * + * @param s the string to parse, may be NULL + * @param delim 0-terminated list of token delimiters, must be non-NULL + * @param saveptr user-provided pointer which points to stored + * information necessary for av_strtok() to continue scanning the same + * string. saveptr is updated to point to the next character after the + * first delimiter found, or to NULL if the string was terminated + * @return the found token, or NULL when no token is found + */ +char *av_strtok(char *s, const char *delim, char **saveptr); + +/** + * Locale-independent conversion of ASCII characters to uppercase. + */ +static inline int av_toupper(int c) +{ + if (c >= 'a' && c <= 'z') + c ^= 0x20; + return c; +} + +/** + * Locale-independent conversion of ASCII characters to lowercase. + */ +static inline int av_tolower(int c) +{ + if (c >= 'A' && c <= 'Z') + c ^= 0x20; + return c; +} + +/** + * Locale-independent case-insensitive compare. + * @note This means only ASCII-range characters are case-insensitive + */ +int av_strcasecmp(const char *a, const char *b); + +/** + * Locale-independent case-insensitive compare. + * @note This means only ASCII-range characters are case-insensitive + */ +int av_strncasecmp(const char *a, const char *b, size_t n); + +/** + * @} + */ + +#endif /* AVUTIL_AVSTRING_H */ diff --git a/Externals/ffmpeg/include/libavutil/avutil.h b/Externals/ffmpeg/include/libavutil/avutil.h new file mode 100644 index 0000000000..3f772621e --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/avutil.h @@ -0,0 +1,349 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_AVUTIL_H +#define AVUTIL_AVUTIL_H + +/** + * @file + * external API header + */ + +/** + * @mainpage + * + * @section libav_intro Introduction + * + * This document describe the usage of the different libraries + * provided by FFmpeg. + * + * @li @ref libavc "libavcodec" encoding/decoding library + * @li @subpage libavfilter graph based frame editing library + * @li @ref libavf "libavformat" I/O and muxing/demuxing library + * @li @ref lavd "libavdevice" special devices muxing/demuxing library + * @li @ref lavu "libavutil" common utility library + * @li @subpage libpostproc post processing library + * @li @subpage libswscale color conversion and scaling library + * + */ + +/** + * @defgroup lavu Common utility functions + * + * @brief + * libavutil contains the code shared across all the other FFmpeg + * libraries + * + * @note In order to use the functions provided by avutil you must include + * the specific header. + * + * @{ + * + * @defgroup lavu_crypto Crypto and Hashing + * + * @{ + * @} + * + * @defgroup lavu_math Maths + * @{ + * + * @} + * + * @defgroup lavu_string String Manipulation + * + * @{ + * + * @} + * + * @defgroup lavu_mem Memory Management + * + * @{ + * + * @} + * + * @defgroup lavu_data Data Structures + * @{ + * + * @} + * + * @defgroup lavu_audio Audio related + * + * @{ + * + * @} + * + * @defgroup lavu_error Error Codes + * + * @{ + * + * @} + * + * @defgroup lavu_misc Other + * + * @{ + * + * @defgroup lavu_internal Internal + * + * Not exported functions, for internal usage only + * + * @{ + * + * @} + */ + + +/** + * @defgroup preproc_misc Preprocessor String Macros + * + * String manipulation macros + * + * @{ + */ + +#define AV_STRINGIFY(s) AV_TOSTRING(s) +#define AV_TOSTRING(s) #s + +#define AV_GLUE(a, b) a ## b +#define AV_JOIN(a, b) AV_GLUE(a, b) + +#define AV_PRAGMA(s) _Pragma(#s) + +/** + * @} + */ + +/** + * @defgroup version_utils Library Version Macros + * + * Useful to check and match library version in order to maintain + * backward compatibility. + * + * @{ + */ + +#define AV_VERSION_INT(a, b, c) (a<<16 | b<<8 | c) +#define AV_VERSION_DOT(a, b, c) a ##.## b ##.## c +#define AV_VERSION(a, b, c) AV_VERSION_DOT(a, b, c) + +/** + * @} + * + * @defgroup lavu_ver Version and Build diagnostics + * + * Macros and function useful to check at compiletime and at runtime + * which version of libavutil is in use. + * + * @{ + */ + +#define LIBAVUTIL_VERSION_MAJOR 51 +#define LIBAVUTIL_VERSION_MINOR 34 +#define LIBAVUTIL_VERSION_MICRO 101 + +#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ + LIBAVUTIL_VERSION_MINOR, \ + LIBAVUTIL_VERSION_MICRO) +#define LIBAVUTIL_VERSION AV_VERSION(LIBAVUTIL_VERSION_MAJOR, \ + LIBAVUTIL_VERSION_MINOR, \ + LIBAVUTIL_VERSION_MICRO) +#define LIBAVUTIL_BUILD LIBAVUTIL_VERSION_INT + +#define LIBAVUTIL_IDENT "Lavu" AV_STRINGIFY(LIBAVUTIL_VERSION) + +/** + * @} + * + * @defgroup depr_guards Deprecation guards + * Those FF_API_* defines are not part of public API. + * They may change, break or disappear at any time. + * + * They are used mostly internally to mark code that will be removed + * on the next major version. + * + * @{ + */ +#ifndef FF_API_OLD_EVAL_NAMES +#define FF_API_OLD_EVAL_NAMES (LIBAVUTIL_VERSION_MAJOR < 52) +#endif +#ifndef FF_API_GET_BITS_PER_SAMPLE_FMT +#define FF_API_GET_BITS_PER_SAMPLE_FMT (LIBAVUTIL_VERSION_MAJOR < 52) +#endif +#ifndef FF_API_FIND_OPT +#define FF_API_FIND_OPT (LIBAVUTIL_VERSION_MAJOR < 52) +#endif +#ifndef FF_API_AV_FIFO_PEEK +#define FF_API_AV_FIFO_PEEK (LIBAVUTIL_VERSION_MAJOR < 52) +#endif +#ifndef FF_API_OLD_AVOPTIONS +#define FF_API_OLD_AVOPTIONS (LIBAVUTIL_VERSION_MAJOR < 52) +#endif + +/** + * @} + */ + +/** + * @addtogroup lavu_ver + * @{ + */ + +/** + * Return the LIBAVUTIL_VERSION_INT constant. + */ +unsigned avutil_version(void); + +/** + * Return the libavutil build-time configuration. + */ +const char *avutil_configuration(void); + +/** + * Return the libavutil license. + */ +const char *avutil_license(void); + +/** + * @} + */ + +/** + * @addtogroup lavu_media Media Type + * @brief Media Type + */ + +enum AVMediaType { + AVMEDIA_TYPE_UNKNOWN = -1, ///< Usually treated as AVMEDIA_TYPE_DATA + AVMEDIA_TYPE_VIDEO, + AVMEDIA_TYPE_AUDIO, + AVMEDIA_TYPE_DATA, ///< Opaque data information usually continuous + AVMEDIA_TYPE_SUBTITLE, + AVMEDIA_TYPE_ATTACHMENT, ///< Opaque data information usually sparse + AVMEDIA_TYPE_NB +}; + +/** + * Return a string describing the media_type enum, NULL if media_type + * is unknown. + */ +const char *av_get_media_type_string(enum AVMediaType media_type); + +/** + * @defgroup lavu_const Constants + * @{ + * + * @defgroup lavu_enc Encoding specific + * + * @note those definition should move to avcodec + * @{ + */ + +#define FF_LAMBDA_SHIFT 7 +#define FF_LAMBDA_SCALE (1< + +/** + * @defgroup lavu_base64 Base64 + * @ingroup lavu_crypto + * @{ + */ + + +/** + * Decode a base64-encoded string. + * + * @param out buffer for decoded data + * @param in null-terminated input string + * @param out_size size in bytes of the out buffer, must be at + * least 3/4 of the length of in + * @return number of bytes written, or a negative value in case of + * invalid input + */ +int av_base64_decode(uint8_t *out, const char *in, int out_size); + +/** + * Encode data to base64 and null-terminate. + * + * @param out buffer for encoded data + * @param out_size size in bytes of the output buffer, must be at + * least AV_BASE64_SIZE(in_size) + * @param in_size size in bytes of the 'in' buffer + * @return 'out' or NULL in case of error + */ +char *av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size); + +/** + * Calculate the output size needed to base64-encode x bytes. + */ +#define AV_BASE64_SIZE(x) (((x)+2) / 3 * 4 + 1) + + /** + * @} + */ + +#endif /* AVUTIL_BASE64_H */ diff --git a/Externals/ffmpeg/include/libavutil/bswap.h b/Externals/ffmpeg/include/libavutil/bswap.h new file mode 100644 index 0000000000..06f654816 --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/bswap.h @@ -0,0 +1,109 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * byte swapping routines + */ + +#ifndef AVUTIL_BSWAP_H +#define AVUTIL_BSWAP_H + +#include +#include "libavutil/avconfig.h" +#include "attributes.h" + +#ifdef HAVE_AV_CONFIG_H + +#include "config.h" + +#if ARCH_ARM +# include "arm/bswap.h" +#elif ARCH_AVR32 +# include "avr32/bswap.h" +#elif ARCH_BFIN +# include "bfin/bswap.h" +#elif ARCH_SH4 +# include "sh4/bswap.h" +#elif ARCH_X86 +# include "x86/bswap.h" +#endif + +#endif /* HAVE_AV_CONFIG_H */ + +#define AV_BSWAP16C(x) (((x) << 8 & 0xff00) | ((x) >> 8 & 0x00ff)) +#define AV_BSWAP32C(x) (AV_BSWAP16C(x) << 16 | AV_BSWAP16C((x) >> 16)) +#define AV_BSWAP64C(x) (AV_BSWAP32C(x) << 32 | AV_BSWAP32C((x) >> 32)) + +#define AV_BSWAPC(s, x) AV_BSWAP##s##C(x) + +#ifndef av_bswap16 +static av_always_inline av_const uint16_t av_bswap16(uint16_t x) +{ + x= (x>>8) | (x<<8); + return x; +} +#endif + +#ifndef av_bswap32 +static av_always_inline av_const uint32_t av_bswap32(uint32_t x) +{ + return AV_BSWAP32C(x); +} +#endif + +#ifndef av_bswap64 +static inline uint64_t av_const av_bswap64(uint64_t x) +{ + return (uint64_t)av_bswap32(x) << 32 | av_bswap32(x >> 32); +} +#endif + +// be2ne ... big-endian to native-endian +// le2ne ... little-endian to native-endian + +#if AV_HAVE_BIGENDIAN +#define av_be2ne16(x) (x) +#define av_be2ne32(x) (x) +#define av_be2ne64(x) (x) +#define av_le2ne16(x) av_bswap16(x) +#define av_le2ne32(x) av_bswap32(x) +#define av_le2ne64(x) av_bswap64(x) +#define AV_BE2NEC(s, x) (x) +#define AV_LE2NEC(s, x) AV_BSWAPC(s, x) +#else +#define av_be2ne16(x) av_bswap16(x) +#define av_be2ne32(x) av_bswap32(x) +#define av_be2ne64(x) av_bswap64(x) +#define av_le2ne16(x) (x) +#define av_le2ne32(x) (x) +#define av_le2ne64(x) (x) +#define AV_BE2NEC(s, x) AV_BSWAPC(s, x) +#define AV_LE2NEC(s, x) (x) +#endif + +#define AV_BE2NE16C(x) AV_BE2NEC(16, x) +#define AV_BE2NE32C(x) AV_BE2NEC(32, x) +#define AV_BE2NE64C(x) AV_BE2NEC(64, x) +#define AV_LE2NE16C(x) AV_LE2NEC(16, x) +#define AV_LE2NE32C(x) AV_LE2NEC(32, x) +#define AV_LE2NE64C(x) AV_LE2NEC(64, x) + +#endif /* AVUTIL_BSWAP_H */ diff --git a/Externals/ffmpeg/include/libavutil/common.h b/Externals/ffmpeg/include/libavutil/common.h new file mode 100644 index 0000000000..84290c636 --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/common.h @@ -0,0 +1,400 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * common internal and external API header + */ + +#ifndef AVUTIL_COMMON_H +#define AVUTIL_COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include "attributes.h" +#include "libavutil/avconfig.h" + +#if AV_HAVE_BIGENDIAN +# define AV_NE(be, le) (be) +#else +# define AV_NE(be, le) (le) +#endif + +//rounded division & shift +#define RSHIFT(a,b) ((a) > 0 ? ((a) + ((1<<(b))>>1))>>(b) : ((a) + ((1<<(b))>>1)-1)>>(b)) +/* assume b>0 */ +#define ROUNDED_DIV(a,b) (((a)>0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b)) +#define FFUDIV(a,b) (((a)>0 ?(a):(a)-(b)+1) / (b)) +#define FFUMOD(a,b) ((a)-(b)*FFUDIV(a,b)) +#define FFABS(a) ((a) >= 0 ? (a) : (-(a))) +#define FFSIGN(a) ((a) > 0 ? 1 : -1) + +#define FFMAX(a,b) ((a) > (b) ? (a) : (b)) +#define FFMAX3(a,b,c) FFMAX(FFMAX(a,b),c) +#define FFMIN(a,b) ((a) > (b) ? (b) : (a)) +#define FFMIN3(a,b,c) FFMIN(FFMIN(a,b),c) + +#define FFSWAP(type,a,b) do{type SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0) +#define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0])) +#define FFALIGN(x, a) (((x)+(a)-1)&~((a)-1)) + +/* misc math functions */ +extern const uint8_t ff_log2_tab[256]; + +extern const uint8_t av_reverse[256]; + +static av_always_inline av_const int av_log2_c(unsigned int v) +{ + int n = 0; + if (v & 0xffff0000) { + v >>= 16; + n += 16; + } + if (v & 0xff00) { + v >>= 8; + n += 8; + } + n += ff_log2_tab[v]; + + return n; +} + +static av_always_inline av_const int av_log2_16bit_c(unsigned int v) +{ + int n = 0; + if (v & 0xff00) { + v >>= 8; + n += 8; + } + n += ff_log2_tab[v]; + + return n; +} + +#ifdef HAVE_AV_CONFIG_H +# include "config.h" +# include "intmath.h" +#endif + +/* Pull in unguarded fallback defines at the end of this file. */ +#include "common.h" + +/** + * Clip a signed integer value into the amin-amax range. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ +static av_always_inline av_const int av_clip_c(int a, int amin, int amax) +{ + if (a < amin) return amin; + else if (a > amax) return amax; + else return a; +} + +/** + * Clip a signed integer value into the 0-255 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const uint8_t av_clip_uint8_c(int a) +{ + if (a&(~0xFF)) return (-a)>>31; + else return a; +} + +/** + * Clip a signed integer value into the -128,127 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const int8_t av_clip_int8_c(int a) +{ + if ((a+0x80) & ~0xFF) return (a>>31) ^ 0x7F; + else return a; +} + +/** + * Clip a signed integer value into the 0-65535 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const uint16_t av_clip_uint16_c(int a) +{ + if (a&(~0xFFFF)) return (-a)>>31; + else return a; +} + +/** + * Clip a signed integer value into the -32768,32767 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const int16_t av_clip_int16_c(int a) +{ + if ((a+0x8000) & ~0xFFFF) return (a>>31) ^ 0x7FFF; + else return a; +} + +/** + * Clip a signed 64-bit integer value into the -2147483648,2147483647 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const int32_t av_clipl_int32_c(int64_t a) +{ + if ((a+0x80000000u) & ~UINT64_C(0xFFFFFFFF)) return (a>>63) ^ 0x7FFFFFFF; + else return a; +} + +/** + * Clip a signed integer to an unsigned power of two range. + * @param a value to clip + * @param p bit position to clip at + * @return clipped value + */ +static av_always_inline av_const unsigned av_clip_uintp2_c(int a, int p) +{ + if (a & ~((1<> 31 & ((1< amax) return amax; + else return a; +} + +/** Compute ceil(log2(x)). + * @param x value used to compute ceil(log2(x)) + * @return computed ceiling of log2(x) + */ +static av_always_inline av_const int av_ceil_log2_c(int x) +{ + return av_log2((x - 1) << 1); +} + +/** + * Count number of bits set to one in x + * @param x value to count bits of + * @return the number of bits set to one in x + */ +static av_always_inline av_const int av_popcount_c(uint32_t x) +{ + x -= (x >> 1) & 0x55555555; + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + x = (x + (x >> 4)) & 0x0F0F0F0F; + x += x >> 8; + return (x + (x >> 16)) & 0x3F; +} + +/** + * Count number of bits set to one in x + * @param x value to count bits of + * @return the number of bits set to one in x + */ +static av_always_inline av_const int av_popcount64_c(uint64_t x) +{ + return av_popcount(x) + av_popcount(x >> 32); +} + +#define MKTAG(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((unsigned)(d) << 24)) +#define MKBETAG(a,b,c,d) ((d) | ((c) << 8) | ((b) << 16) | ((unsigned)(a) << 24)) + +/** + * Convert a UTF-8 character (up to 4 bytes) to its 32-bit UCS-4 encoded form. + * + * @param val Output value, must be an lvalue of type uint32_t. + * @param GET_BYTE Expression reading one byte from the input. + * Evaluated up to 7 times (4 for the currently + * assigned Unicode range). With a memory buffer + * input, this could be *ptr++. + * @param ERROR Expression to be evaluated on invalid input, + * typically a goto statement. + */ +#define GET_UTF8(val, GET_BYTE, ERROR)\ + val= GET_BYTE;\ + {\ + int ones= 7 - av_log2(val ^ 255);\ + if(ones==1)\ + ERROR\ + val&= 127>>ones;\ + while(--ones > 0){\ + int tmp= GET_BYTE - 128;\ + if(tmp>>6)\ + ERROR\ + val= (val<<6) + tmp;\ + }\ + } + +/** + * Convert a UTF-16 character (2 or 4 bytes) to its 32-bit UCS-4 encoded form. + * + * @param val Output value, must be an lvalue of type uint32_t. + * @param GET_16BIT Expression returning two bytes of UTF-16 data converted + * to native byte order. Evaluated one or two times. + * @param ERROR Expression to be evaluated on invalid input, + * typically a goto statement. + */ +#define GET_UTF16(val, GET_16BIT, ERROR)\ + val = GET_16BIT;\ + {\ + unsigned int hi = val - 0xD800;\ + if (hi < 0x800) {\ + val = GET_16BIT - 0xDC00;\ + if (val > 0x3FFU || hi > 0x3FFU)\ + ERROR\ + val += (hi<<10) + 0x10000;\ + }\ + }\ + +/** + * @def PUT_UTF8(val, tmp, PUT_BYTE) + * Convert a 32-bit Unicode character to its UTF-8 encoded form (up to 4 bytes long). + * @param val is an input-only argument and should be of type uint32_t. It holds + * a UCS-4 encoded Unicode character that is to be converted to UTF-8. If + * val is given as a function it is executed only once. + * @param tmp is a temporary variable and should be of type uint8_t. It + * represents an intermediate value during conversion that is to be + * output by PUT_BYTE. + * @param PUT_BYTE writes the converted UTF-8 bytes to any proper destination. + * It could be a function or a statement, and uses tmp as the input byte. + * For example, PUT_BYTE could be "*output++ = tmp;" PUT_BYTE will be + * executed up to 4 times for values in the valid UTF-8 range and up to + * 7 times in the general case, depending on the length of the converted + * Unicode character. + */ +#define PUT_UTF8(val, tmp, PUT_BYTE)\ + {\ + int bytes, shift;\ + uint32_t in = val;\ + if (in < 0x80) {\ + tmp = in;\ + PUT_BYTE\ + } else {\ + bytes = (av_log2(in) + 4) / 5;\ + shift = (bytes - 1) * 6;\ + tmp = (256 - (256 >> bytes)) | (in >> shift);\ + PUT_BYTE\ + while (shift >= 6) {\ + shift -= 6;\ + tmp = 0x80 | ((in >> shift) & 0x3f);\ + PUT_BYTE\ + }\ + }\ + } + +/** + * @def PUT_UTF16(val, tmp, PUT_16BIT) + * Convert a 32-bit Unicode character to its UTF-16 encoded form (2 or 4 bytes). + * @param val is an input-only argument and should be of type uint32_t. It holds + * a UCS-4 encoded Unicode character that is to be converted to UTF-16. If + * val is given as a function it is executed only once. + * @param tmp is a temporary variable and should be of type uint16_t. It + * represents an intermediate value during conversion that is to be + * output by PUT_16BIT. + * @param PUT_16BIT writes the converted UTF-16 data to any proper destination + * in desired endianness. It could be a function or a statement, and uses tmp + * as the input byte. For example, PUT_BYTE could be "*output++ = tmp;" + * PUT_BYTE will be executed 1 or 2 times depending on input character. + */ +#define PUT_UTF16(val, tmp, PUT_16BIT)\ + {\ + uint32_t in = val;\ + if (in < 0x10000) {\ + tmp = in;\ + PUT_16BIT\ + } else {\ + tmp = 0xD800 | ((in - 0x10000) >> 10);\ + PUT_16BIT\ + tmp = 0xDC00 | ((in - 0x10000) & 0x3FF);\ + PUT_16BIT\ + }\ + }\ + + + +#include "mem.h" + +#ifdef HAVE_AV_CONFIG_H +# include "internal.h" +#endif /* HAVE_AV_CONFIG_H */ + +#endif /* AVUTIL_COMMON_H */ + +/* + * The following definitions are outside the multiple inclusion guard + * to ensure they are immediately available in intmath.h. + */ + +#ifndef av_log2 +# define av_log2 av_log2_c +#endif +#ifndef av_log2_16bit +# define av_log2_16bit av_log2_16bit_c +#endif +#ifndef av_ceil_log2 +# define av_ceil_log2 av_ceil_log2_c +#endif +#ifndef av_clip +# define av_clip av_clip_c +#endif +#ifndef av_clip_uint8 +# define av_clip_uint8 av_clip_uint8_c +#endif +#ifndef av_clip_int8 +# define av_clip_int8 av_clip_int8_c +#endif +#ifndef av_clip_uint16 +# define av_clip_uint16 av_clip_uint16_c +#endif +#ifndef av_clip_int16 +# define av_clip_int16 av_clip_int16_c +#endif +#ifndef av_clipl_int32 +# define av_clipl_int32 av_clipl_int32_c +#endif +#ifndef av_clip_uintp2 +# define av_clip_uintp2 av_clip_uintp2_c +#endif +#ifndef av_clipf +# define av_clipf av_clipf_c +#endif +#ifndef av_popcount +# define av_popcount av_popcount_c +#endif +#ifndef av_popcount64 +# define av_popcount64 av_popcount64_c +#endif diff --git a/Externals/ffmpeg/include/libavutil/cpu.h b/Externals/ffmpeg/include/libavutil/cpu.h new file mode 100644 index 0000000000..5f7eed2b6 --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/cpu.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2000, 2001, 2002 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_CPU_H +#define AVUTIL_CPU_H + +#define AV_CPU_FLAG_FORCE 0x80000000 /* force usage of selected flags (OR) */ + + /* lower 16 bits - CPU features */ +#define AV_CPU_FLAG_MMX 0x0001 ///< standard MMX +#define AV_CPU_FLAG_MMX2 0x0002 ///< SSE integer functions or AMD MMX ext +#define AV_CPU_FLAG_3DNOW 0x0004 ///< AMD 3DNOW +#define AV_CPU_FLAG_SSE 0x0008 ///< SSE functions +#define AV_CPU_FLAG_SSE2 0x0010 ///< PIV SSE2 functions +#define AV_CPU_FLAG_SSE2SLOW 0x40000000 ///< SSE2 supported, but usually not faster +#define AV_CPU_FLAG_3DNOWEXT 0x0020 ///< AMD 3DNowExt +#define AV_CPU_FLAG_SSE3 0x0040 ///< Prescott SSE3 functions +#define AV_CPU_FLAG_SSE3SLOW 0x20000000 ///< SSE3 supported, but usually not faster +#define AV_CPU_FLAG_SSSE3 0x0080 ///< Conroe SSSE3 functions +#define AV_CPU_FLAG_ATOM 0x10000000 ///< Atom processor, some SSSE3 instructions are slower +#define AV_CPU_FLAG_SSE4 0x0100 ///< Penryn SSE4.1 functions +#define AV_CPU_FLAG_SSE42 0x0200 ///< Nehalem SSE4.2 functions +#define AV_CPU_FLAG_AVX 0x4000 ///< AVX functions: requires OS support even if YMM registers aren't used +#define AV_CPU_FLAG_XOP 0x0400 ///< Bulldozer XOP functions +#define AV_CPU_FLAG_FMA4 0x0800 ///< Bulldozer FMA4 functions +#define AV_CPU_FLAG_IWMMXT 0x0100 ///< XScale IWMMXT +#define AV_CPU_FLAG_ALTIVEC 0x0001 ///< standard + +/** + * Return the flags which specify extensions supported by the CPU. + */ +int av_get_cpu_flags(void); + + +/** + * Disables cpu detection and forces the specified flags. + */ +void av_force_cpu_flags(int flags); + + +/* The following CPU-specific functions shall not be called directly. */ +int ff_get_cpu_flags_arm(void); +int ff_get_cpu_flags_ppc(void); +int ff_get_cpu_flags_x86(void); + +#endif /* AVUTIL_CPU_H */ diff --git a/Externals/ffmpeg/include/libavutil/crc.h b/Externals/ffmpeg/include/libavutil/crc.h new file mode 100644 index 0000000000..6c0baab5a --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/crc.h @@ -0,0 +1,44 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_CRC_H +#define AVUTIL_CRC_H + +#include +#include +#include "attributes.h" + +typedef uint32_t AVCRC; + +typedef enum { + AV_CRC_8_ATM, + AV_CRC_16_ANSI, + AV_CRC_16_CCITT, + AV_CRC_32_IEEE, + AV_CRC_32_IEEE_LE, /*< reversed bitorder version of AV_CRC_32_IEEE */ + AV_CRC_MAX, /*< Not part of public API! Do not use outside libavutil. */ +}AVCRCId; + +int av_crc_init(AVCRC *ctx, int le, int bits, uint32_t poly, int ctx_size); +const AVCRC *av_crc_get_table(AVCRCId crc_id); +uint32_t av_crc(const AVCRC *ctx, uint32_t start_crc, const uint8_t *buffer, size_t length) av_pure; + +#endif /* AVUTIL_CRC_H */ + diff --git a/Externals/ffmpeg/include/libavutil/dict.h b/Externals/ffmpeg/include/libavutil/dict.h new file mode 100644 index 0000000000..2adf28c12 --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/dict.h @@ -0,0 +1,127 @@ +/* + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Public dictionary API. + * @deprecated + * AVDictionary is provided for compatibility with libav. It is both in + * implementation as well as API inefficient. It does not scale and is + * extremely slow with large dictionaries. + * It is recommended that new code uses our tree container from tree.c/h + * where applicable, which uses AVL trees to achieve O(log n) performance. + */ + +#ifndef AVUTIL_DICT_H +#define AVUTIL_DICT_H + +/** + * @addtogroup lavu_dict AVDictionary + * @ingroup lavu_data + * + * @brief Simple key:value store + * + * @{ + * Dictionaries are used for storing key:value pairs. To create + * an AVDictionary, simply pass an address of a NULL pointer to + * av_dict_set(). NULL can be used as an empty dictionary wherever + * a pointer to an AVDictionary is required. + * Use av_dict_get() to retrieve an entry or iterate over all + * entries and finally av_dict_free() to free the dictionary + * and all its contents. + * + * @code + * AVDictionary *d = NULL; // "create" an empty dictionary + * av_dict_set(&d, "foo", "bar", 0); // add an entry + * + * char *k = av_strdup("key"); // if your strings are already allocated, + * char *v = av_strdup("value"); // you can avoid copying them like this + * av_dict_set(&d, k, v, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL); + * + * AVDictionaryEntry *t = NULL; + * while (t = av_dict_get(d, "", t, AV_DICT_IGNORE_SUFFIX)) { + * <....> // iterate over all entries in d + * } + * + * av_dict_free(&d); + * @endcode + * + */ + +#define AV_DICT_MATCH_CASE 1 +#define AV_DICT_IGNORE_SUFFIX 2 +#define AV_DICT_DONT_STRDUP_KEY 4 /**< Take ownership of a key that's been + allocated with av_malloc() and children. */ +#define AV_DICT_DONT_STRDUP_VAL 8 /**< Take ownership of a value that's been + allocated with av_malloc() and chilren. */ +#define AV_DICT_DONT_OVERWRITE 16 ///< Don't overwrite existing entries. +#define AV_DICT_APPEND 32 /**< If the entry already exists, append to it. Note that no + delimiter is added, the strings are simply concatenated. */ + +typedef struct { + char *key; + char *value; +} AVDictionaryEntry; + +typedef struct AVDictionary AVDictionary; + +/** + * Get a dictionary entry with matching key. + * + * @param prev Set to the previous matching element to find the next. + * If set to NULL the first matching element is returned. + * @param flags Allows case as well as suffix-insensitive comparisons. + * @return Found entry or NULL, changing key or value leads to undefined behavior. + */ +AVDictionaryEntry * +av_dict_get(AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags); + +/** + * Set the given entry in *pm, overwriting an existing entry. + * + * @param pm pointer to a pointer to a dictionary struct. If *pm is NULL + * a dictionary struct is allocated and put in *pm. + * @param key entry key to add to *pm (will be av_strduped depending on flags) + * @param value entry value to add to *pm (will be av_strduped depending on flags). + * Passing a NULL value will cause an existing tag to be deleted. + * @return >= 0 on success otherwise an error code <0 + */ +int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags); + +/** + * Copy entries from one AVDictionary struct into another. + * @param dst pointer to a pointer to a AVDictionary struct. If *dst is NULL, + * this function will allocate a struct for you and put it in *dst + * @param src pointer to source AVDictionary struct + * @param flags flags to use when setting entries in *dst + * @note metadata is read using the AV_DICT_IGNORE_SUFFIX flag + */ +void av_dict_copy(AVDictionary **dst, AVDictionary *src, int flags); + +/** + * Free all the memory allocated for an AVDictionary struct + * and all keys and values. + */ +void av_dict_free(AVDictionary **m); + +/** + * @} + */ + +#endif // AVUTIL_DICT_H diff --git a/Externals/ffmpeg/include/libavutil/error.h b/Externals/ffmpeg/include/libavutil/error.h new file mode 100644 index 0000000000..40e54f1ed --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/error.h @@ -0,0 +1,86 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * error code definitions + */ + +#ifndef AVUTIL_ERROR_H +#define AVUTIL_ERROR_H + +#include +#include "avutil.h" + +/** + * @addtogroup lavu_error + * + * @{ + */ + + +/* error handling */ +#if EDOM > 0 +#define AVERROR(e) (-(e)) ///< Returns a negative error code from a POSIX error code, to return from library functions. +#define AVUNERROR(e) (-(e)) ///< Returns a POSIX error code from a library function error return value. +#else +/* Some platforms have E* and errno already negated. */ +#define AVERROR(e) (e) +#define AVUNERROR(e) (e) +#endif + +#define AVERROR_BSF_NOT_FOUND (-MKTAG(0xF8,'B','S','F')) ///< Bitstream filter not found +#define AVERROR_BUG (-MKTAG( 'B','U','G','!')) ///< Internal bug, also see AVERROR_BUG2 +#define AVERROR_DECODER_NOT_FOUND (-MKTAG(0xF8,'D','E','C')) ///< Decoder not found +#define AVERROR_DEMUXER_NOT_FOUND (-MKTAG(0xF8,'D','E','M')) ///< Demuxer not found +#define AVERROR_ENCODER_NOT_FOUND (-MKTAG(0xF8,'E','N','C')) ///< Encoder not found +#define AVERROR_EOF (-MKTAG( 'E','O','F',' ')) ///< End of file +#define AVERROR_EXIT (-MKTAG( 'E','X','I','T')) ///< Immediate exit was requested; the called function should not be restarted +#define AVERROR_FILTER_NOT_FOUND (-MKTAG(0xF8,'F','I','L')) ///< Filter not found +#define AVERROR_INVALIDDATA (-MKTAG( 'I','N','D','A')) ///< Invalid data found when processing input +#define AVERROR_MUXER_NOT_FOUND (-MKTAG(0xF8,'M','U','X')) ///< Muxer not found +#define AVERROR_OPTION_NOT_FOUND (-MKTAG(0xF8,'O','P','T')) ///< Option not found +#define AVERROR_PATCHWELCOME (-MKTAG( 'P','A','W','E')) ///< Not yet implemented in FFmpeg, patches welcome +#define AVERROR_PROTOCOL_NOT_FOUND (-MKTAG(0xF8,'P','R','O')) ///< Protocol not found +#define AVERROR_STREAM_NOT_FOUND (-MKTAG(0xF8,'S','T','R')) ///< Stream not found + +/** + * This is semantically identical to AVERROR_BUG + * it has been introduced in Libav after our AVERROR_BUG and with a modified value. + */ +#define AVERROR_BUG2 (-MKTAG( 'B','U','G',' ')) + +/** + * Put a description of the AVERROR code errnum in errbuf. + * In case of failure the global variable errno is set to indicate the + * error. Even in case of failure av_strerror() will print a generic + * error message indicating the errnum provided to errbuf. + * + * @param errnum error code to describe + * @param errbuf buffer to which description is written + * @param errbuf_size the size in bytes of errbuf + * @return 0 on success, a negative value if a description for errnum + * cannot be found + */ +int av_strerror(int errnum, char *errbuf, size_t errbuf_size); + +/** + * @} + */ + +#endif /* AVUTIL_ERROR_H */ diff --git a/Externals/ffmpeg/include/libavutil/eval.h b/Externals/ffmpeg/include/libavutil/eval.h new file mode 100644 index 0000000000..22fa12112 --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/eval.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2002 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * simple arithmetic expression evaluator + */ + +#ifndef AVUTIL_EVAL_H +#define AVUTIL_EVAL_H + +#include "avutil.h" + +typedef struct AVExpr AVExpr; + +/** + * Parse and evaluate an expression. + * Note, this is significantly slower than av_expr_eval(). + * + * @param res a pointer to a double where is put the result value of + * the expression, or NAN in case of error + * @param s expression as a zero terminated string, for example "1+2^3+5*5+sin(2/3)" + * @param const_names NULL terminated array of zero terminated strings of constant identifiers, for example {"PI", "E", 0} + * @param const_values a zero terminated array of values for the identifiers from const_names + * @param func1_names NULL terminated array of zero terminated strings of funcs1 identifiers + * @param funcs1 NULL terminated array of function pointers for functions which take 1 argument + * @param func2_names NULL terminated array of zero terminated strings of funcs2 identifiers + * @param funcs2 NULL terminated array of function pointers for functions which take 2 arguments + * @param opaque a pointer which will be passed to all functions from funcs1 and funcs2 + * @param log_ctx parent logging context + * @return 0 in case of success, a negative value corresponding to an + * AVERROR code otherwise + */ +int av_expr_parse_and_eval(double *res, const char *s, + const char * const *const_names, const double *const_values, + const char * const *func1_names, double (* const *funcs1)(void *, double), + const char * const *func2_names, double (* const *funcs2)(void *, double, double), + void *opaque, int log_offset, void *log_ctx); + +/** + * Parse an expression. + * + * @param expr a pointer where is put an AVExpr containing the parsed + * value in case of successful parsing, or NULL otherwise. + * The pointed to AVExpr must be freed with av_expr_free() by the user + * when it is not needed anymore. + * @param s expression as a zero terminated string, for example "1+2^3+5*5+sin(2/3)" + * @param const_names NULL terminated array of zero terminated strings of constant identifiers, for example {"PI", "E", 0} + * @param func1_names NULL terminated array of zero terminated strings of funcs1 identifiers + * @param funcs1 NULL terminated array of function pointers for functions which take 1 argument + * @param func2_names NULL terminated array of zero terminated strings of funcs2 identifiers + * @param funcs2 NULL terminated array of function pointers for functions which take 2 arguments + * @param log_ctx parent logging context + * @return 0 in case of success, a negative value corresponding to an + * AVERROR code otherwise + */ +int av_expr_parse(AVExpr **expr, const char *s, + const char * const *const_names, + const char * const *func1_names, double (* const *funcs1)(void *, double), + const char * const *func2_names, double (* const *funcs2)(void *, double, double), + int log_offset, void *log_ctx); + +/** + * Evaluate a previously parsed expression. + * + * @param const_values a zero terminated array of values for the identifiers from av_expr_parse() const_names + * @param opaque a pointer which will be passed to all functions from funcs1 and funcs2 + * @return the value of the expression + */ +double av_expr_eval(AVExpr *e, const double *const_values, void *opaque); + +/** + * Free a parsed expression previously created with av_expr_parse(). + */ +void av_expr_free(AVExpr *e); + +#if FF_API_OLD_EVAL_NAMES +/** + * @deprecated Deprecated in favor of av_expr_parse_and_eval(). + */ +attribute_deprecated +int av_parse_and_eval_expr(double *res, const char *s, + const char * const *const_names, const double *const_values, + const char * const *func1_names, double (* const *funcs1)(void *, double), + const char * const *func2_names, double (* const *funcs2)(void *, double, double), + void *opaque, int log_offset, void *log_ctx); + +/** + * @deprecated Deprecated in favor of av_expr_parse(). + */ +attribute_deprecated +int av_parse_expr(AVExpr **expr, const char *s, + const char * const *const_names, + const char * const *func1_names, double (* const *funcs1)(void *, double), + const char * const *func2_names, double (* const *funcs2)(void *, double, double), + int log_offset, void *log_ctx); +/** + * @deprecated Deprecated in favor of av_expr_eval(). + */ +attribute_deprecated +double av_eval_expr(AVExpr *e, const double *const_values, void *opaque); + +/** + * @deprecated Deprecated in favor of av_expr_free(). + */ +attribute_deprecated +void av_free_expr(AVExpr *e); +#endif /* FF_API_OLD_EVAL_NAMES */ + +/** + * Parse the string in numstr and return its value as a double. If + * the string is empty, contains only whitespaces, or does not contain + * an initial substring that has the expected syntax for a + * floating-point number, no conversion is performed. In this case, + * returns a value of zero and the value returned in tail is the value + * of numstr. + * + * @param numstr a string representing a number, may contain one of + * the International System number postfixes, for example 'K', 'M', + * 'G'. If 'i' is appended after the postfix, powers of 2 are used + * instead of powers of 10. The 'B' postfix multiplies the value for + * 8, and can be appended after another postfix or used alone. This + * allows using for example 'KB', 'MiB', 'G' and 'B' as postfix. + * @param tail if non-NULL puts here the pointer to the char next + * after the last parsed character + */ +double av_strtod(const char *numstr, char **tail); + +#endif /* AVUTIL_EVAL_H */ diff --git a/Externals/ffmpeg/include/libavutil/fifo.h b/Externals/ffmpeg/include/libavutil/fifo.h new file mode 100644 index 0000000000..22a9aa5d1 --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/fifo.h @@ -0,0 +1,143 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * a very simple circular buffer FIFO implementation + */ + +#ifndef AVUTIL_FIFO_H +#define AVUTIL_FIFO_H + +#include +#include "avutil.h" + +typedef struct AVFifoBuffer { + uint8_t *buffer; + uint8_t *rptr, *wptr, *end; + uint32_t rndx, wndx; +} AVFifoBuffer; + +/** + * Initialize an AVFifoBuffer. + * @param size of FIFO + * @return AVFifoBuffer or NULL in case of memory allocation failure + */ +AVFifoBuffer *av_fifo_alloc(unsigned int size); + +/** + * Free an AVFifoBuffer. + * @param f AVFifoBuffer to free + */ +void av_fifo_free(AVFifoBuffer *f); + +/** + * Reset the AVFifoBuffer to the state right after av_fifo_alloc, in particular it is emptied. + * @param f AVFifoBuffer to reset + */ +void av_fifo_reset(AVFifoBuffer *f); + +/** + * Return the amount of data in bytes in the AVFifoBuffer, that is the + * amount of data you can read from it. + * @param f AVFifoBuffer to read from + * @return size + */ +int av_fifo_size(AVFifoBuffer *f); + +/** + * Return the amount of space in bytes in the AVFifoBuffer, that is the + * amount of data you can write into it. + * @param f AVFifoBuffer to write into + * @return size + */ +int av_fifo_space(AVFifoBuffer *f); + +/** + * Feed data from an AVFifoBuffer to a user-supplied callback. + * @param f AVFifoBuffer to read from + * @param buf_size number of bytes to read + * @param func generic read function + * @param dest data destination + */ +int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void*, void*, int)); + +/** + * Feed data from a user-supplied callback to an AVFifoBuffer. + * @param f AVFifoBuffer to write to + * @param src data source; non-const since it may be used as a + * modifiable context by the function defined in func + * @param size number of bytes to write + * @param func generic write function; the first parameter is src, + * the second is dest_buf, the third is dest_buf_size. + * func must return the number of bytes written to dest_buf, or <= 0 to + * indicate no more data available to write. + * If func is NULL, src is interpreted as a simple byte array for source data. + * @return the number of bytes written to the FIFO + */ +int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, int (*func)(void*, void*, int)); + +/** + * Resize an AVFifoBuffer. + * In case of reallocation failure, the old FIFO is kept unchanged. + * + * @param f AVFifoBuffer to resize + * @param size new AVFifoBuffer size in bytes + * @return <0 for failure, >=0 otherwise + */ +int av_fifo_realloc2(AVFifoBuffer *f, unsigned int size); + +/** + * Read and discard the specified amount of data from an AVFifoBuffer. + * @param f AVFifoBuffer to read from + * @param size amount of data to read in bytes + */ +void av_fifo_drain(AVFifoBuffer *f, int size); + +/** + * Return a pointer to the data stored in a FIFO buffer at a certain offset. + * The FIFO buffer is not modified. + * + * @param f AVFifoBuffer to peek at, f must be non-NULL + * @param offs an offset in bytes, its absolute value must be less + * than the used buffer size or the returned pointer will + * point outside to the buffer data. + * The used buffer size can be checked with av_fifo_size(). + */ +static inline uint8_t *av_fifo_peek2(const AVFifoBuffer *f, int offs) +{ + uint8_t *ptr = f->rptr + offs; + if (ptr >= f->end) + ptr = f->buffer + (ptr - f->end); + else if (ptr < f->buffer) + ptr = f->end - (f->buffer - ptr); + return ptr; +} + +#if FF_API_AV_FIFO_PEEK +/** + * @deprecated Use av_fifo_peek2() instead. + */ +attribute_deprecated +static inline uint8_t av_fifo_peek(AVFifoBuffer *f, int offs) +{ + return *av_fifo_peek2(f, offs); +} +#endif + +#endif /* AVUTIL_FIFO_H */ diff --git a/Externals/ffmpeg/include/libavutil/file.h b/Externals/ffmpeg/include/libavutil/file.h new file mode 100644 index 0000000000..f3af9ef7e --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/file.h @@ -0,0 +1,61 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_FILE_H +#define AVUTIL_FILE_H + +#include "avutil.h" + +/** + * @file + * Misc file utilities. + */ + +/** + * Read the file with name filename, and put its content in a newly + * allocated buffer or map it with mmap() when available. + * In case of success set *bufptr to the read or mmapped buffer, and + * *size to the size in bytes of the buffer in *bufptr. + * The returned buffer must be released with av_file_unmap(). + * + * @param log_offset loglevel offset used for logging + * @param log_ctx context used for logging + * @return a non negative number in case of success, a negative value + * corresponding to an AVERROR error code in case of failure + */ +int av_file_map(const char *filename, uint8_t **bufptr, size_t *size, + int log_offset, void *log_ctx); + +/** + * Unmap or free the buffer bufptr created by av_file_map(). + * + * @param size size in bytes of bufptr, must be the same as returned + * by av_file_map() + */ +void av_file_unmap(uint8_t *bufptr, size_t size); + +/** + * Wrapper to work around the lack of mkstemp() on mingw. + * Also, tries to create file in /tmp first, if possible. + * *prefix can be a character constant; *filename will be allocated internally. + * @return file descriptor of opened file (or -1 on error) + * and opened file name in **filename. + */ +int av_tempfile(const char *prefix, char **filename, int log_offset, void *log_ctx); + +#endif /* AVUTIL_FILE_H */ diff --git a/Externals/ffmpeg/include/libavutil/imgutils.h b/Externals/ffmpeg/include/libavutil/imgutils.h new file mode 100644 index 0000000000..9b53815fb --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/imgutils.h @@ -0,0 +1,138 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_IMGUTILS_H +#define AVUTIL_IMGUTILS_H + +/** + * @file + * misc image utilities + * + * @addtogroup lavu_picture + * @{ + */ + +#include "avutil.h" +#include "pixdesc.h" + +/** + * Compute the max pixel step for each plane of an image with a + * format described by pixdesc. + * + * The pixel step is the distance in bytes between the first byte of + * the group of bytes which describe a pixel component and the first + * byte of the successive group in the same plane for the same + * component. + * + * @param max_pixsteps an array which is filled with the max pixel step + * for each plane. Since a plane may contain different pixel + * components, the computed max_pixsteps[plane] is relative to the + * component in the plane with the max pixel step. + * @param max_pixstep_comps an array which is filled with the component + * for each plane which has the max pixel step. May be NULL. + */ +void av_image_fill_max_pixsteps(int max_pixsteps[4], int max_pixstep_comps[4], + const AVPixFmtDescriptor *pixdesc); + +/** + * Compute the size of an image line with format pix_fmt and width + * width for the plane plane. + * + * @return the computed size in bytes + */ +int av_image_get_linesize(enum PixelFormat pix_fmt, int width, int plane); + +/** + * Fill plane linesizes for an image with pixel format pix_fmt and + * width width. + * + * @param linesizes array to be filled with the linesize for each plane + * @return >= 0 in case of success, a negative error code otherwise + */ +int av_image_fill_linesizes(int linesizes[4], enum PixelFormat pix_fmt, int width); + +/** + * Fill plane data pointers for an image with pixel format pix_fmt and + * height height. + * + * @param data pointers array to be filled with the pointer for each image plane + * @param ptr the pointer to a buffer which will contain the image + * @param linesizes the array containing the linesize for each + * plane, should be filled by av_image_fill_linesizes() + * @return the size in bytes required for the image buffer, a negative + * error code in case of failure + */ +int av_image_fill_pointers(uint8_t *data[4], enum PixelFormat pix_fmt, int height, + uint8_t *ptr, const int linesizes[4]); + +/** + * Allocate an image with size w and h and pixel format pix_fmt, and + * fill pointers and linesizes accordingly. + * The allocated image buffer has to be freed by using + * av_freep(&pointers[0]). + * + * @param align the value to use for buffer size alignment + * @return the size in bytes required for the image buffer, a negative + * error code in case of failure + */ +int av_image_alloc(uint8_t *pointers[4], int linesizes[4], + int w, int h, enum PixelFormat pix_fmt, int align); + +/** + * Copy image plane from src to dst. + * That is, copy "height" number of lines of "bytewidth" bytes each. + * The first byte of each successive line is separated by *_linesize + * bytes. + * + * @param dst_linesize linesize for the image plane in dst + * @param src_linesize linesize for the image plane in src + */ +void av_image_copy_plane(uint8_t *dst, int dst_linesize, + const uint8_t *src, int src_linesize, + int bytewidth, int height); + +/** + * Copy image in src_data to dst_data. + * + * @param dst_linesizes linesizes for the image in dst_data + * @param src_linesizes linesizes for the image in src_data + */ +void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4], + const uint8_t *src_data[4], const int src_linesizes[4], + enum PixelFormat pix_fmt, int width, int height); + +/** + * Check if the given dimension of an image is valid, meaning that all + * bytes of the image can be addressed with a signed int. + * + * @param w the width of the picture + * @param h the height of the picture + * @param log_offset the offset to sum to the log level for logging with log_ctx + * @param log_ctx the parent logging context, it may be NULL + * @return >= 0 if valid, a negative error code otherwise + */ +int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx); + +int ff_set_systematic_pal2(uint32_t pal[256], enum PixelFormat pix_fmt); + +/** + * @} + */ + + +#endif /* AVUTIL_IMGUTILS_H */ diff --git a/Externals/ffmpeg/include/libavutil/intfloat_readwrite.h b/Externals/ffmpeg/include/libavutil/intfloat_readwrite.h new file mode 100644 index 0000000000..9709f4dae --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/intfloat_readwrite.h @@ -0,0 +1,40 @@ +/* + * copyright (c) 2005 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_INTFLOAT_READWRITE_H +#define AVUTIL_INTFLOAT_READWRITE_H + +#include +#include "attributes.h" + +/* IEEE 80 bits extended float */ +typedef struct AVExtFloat { + uint8_t exponent[2]; + uint8_t mantissa[8]; +} AVExtFloat; + +attribute_deprecated double av_int2dbl(int64_t v) av_const; +attribute_deprecated float av_int2flt(int32_t v) av_const; +attribute_deprecated double av_ext2dbl(const AVExtFloat ext) av_const; +attribute_deprecated int64_t av_dbl2int(double d) av_const; +attribute_deprecated int32_t av_flt2int(float d) av_const; +attribute_deprecated AVExtFloat av_dbl2ext(double d) av_const; + +#endif /* AVUTIL_INTFLOAT_READWRITE_H */ diff --git a/Externals/ffmpeg/include/libavutil/intreadwrite.h b/Externals/ffmpeg/include/libavutil/intreadwrite.h new file mode 100644 index 0000000000..09d796c8b --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/intreadwrite.h @@ -0,0 +1,522 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_INTREADWRITE_H +#define AVUTIL_INTREADWRITE_H + +#include +#include "libavutil/avconfig.h" +#include "attributes.h" +#include "bswap.h" + +typedef union { + uint64_t u64; + uint32_t u32[2]; + uint16_t u16[4]; + uint8_t u8 [8]; + double f64; + float f32[2]; +} av_alias av_alias64; + +typedef union { + uint32_t u32; + uint16_t u16[2]; + uint8_t u8 [4]; + float f32; +} av_alias av_alias32; + +typedef union { + uint16_t u16; + uint8_t u8 [2]; +} av_alias av_alias16; + +/* + * Arch-specific headers can provide any combination of + * AV_[RW][BLN](16|24|32|64) and AV_(COPY|SWAP|ZERO)(64|128) macros. + * Preprocessor symbols must be defined, even if these are implemented + * as inline functions. + */ + +#ifdef HAVE_AV_CONFIG_H + +#include "config.h" + +#if ARCH_ARM +# include "arm/intreadwrite.h" +#elif ARCH_AVR32 +# include "avr32/intreadwrite.h" +#elif ARCH_MIPS +# include "mips/intreadwrite.h" +#elif ARCH_PPC +# include "ppc/intreadwrite.h" +#elif ARCH_TOMI +# include "tomi/intreadwrite.h" +#elif ARCH_X86 +# include "x86/intreadwrite.h" +#endif + +#endif /* HAVE_AV_CONFIG_H */ + +/* + * Map AV_RNXX <-> AV_R[BL]XX for all variants provided by per-arch headers. + */ + +#if AV_HAVE_BIGENDIAN + +# if defined(AV_RN16) && !defined(AV_RB16) +# define AV_RB16(p) AV_RN16(p) +# elif !defined(AV_RN16) && defined(AV_RB16) +# define AV_RN16(p) AV_RB16(p) +# endif + +# if defined(AV_WN16) && !defined(AV_WB16) +# define AV_WB16(p, v) AV_WN16(p, v) +# elif !defined(AV_WN16) && defined(AV_WB16) +# define AV_WN16(p, v) AV_WB16(p, v) +# endif + +# if defined(AV_RN24) && !defined(AV_RB24) +# define AV_RB24(p) AV_RN24(p) +# elif !defined(AV_RN24) && defined(AV_RB24) +# define AV_RN24(p) AV_RB24(p) +# endif + +# if defined(AV_WN24) && !defined(AV_WB24) +# define AV_WB24(p, v) AV_WN24(p, v) +# elif !defined(AV_WN24) && defined(AV_WB24) +# define AV_WN24(p, v) AV_WB24(p, v) +# endif + +# if defined(AV_RN32) && !defined(AV_RB32) +# define AV_RB32(p) AV_RN32(p) +# elif !defined(AV_RN32) && defined(AV_RB32) +# define AV_RN32(p) AV_RB32(p) +# endif + +# if defined(AV_WN32) && !defined(AV_WB32) +# define AV_WB32(p, v) AV_WN32(p, v) +# elif !defined(AV_WN32) && defined(AV_WB32) +# define AV_WN32(p, v) AV_WB32(p, v) +# endif + +# if defined(AV_RN64) && !defined(AV_RB64) +# define AV_RB64(p) AV_RN64(p) +# elif !defined(AV_RN64) && defined(AV_RB64) +# define AV_RN64(p) AV_RB64(p) +# endif + +# if defined(AV_WN64) && !defined(AV_WB64) +# define AV_WB64(p, v) AV_WN64(p, v) +# elif !defined(AV_WN64) && defined(AV_WB64) +# define AV_WN64(p, v) AV_WB64(p, v) +# endif + +#else /* AV_HAVE_BIGENDIAN */ + +# if defined(AV_RN16) && !defined(AV_RL16) +# define AV_RL16(p) AV_RN16(p) +# elif !defined(AV_RN16) && defined(AV_RL16) +# define AV_RN16(p) AV_RL16(p) +# endif + +# if defined(AV_WN16) && !defined(AV_WL16) +# define AV_WL16(p, v) AV_WN16(p, v) +# elif !defined(AV_WN16) && defined(AV_WL16) +# define AV_WN16(p, v) AV_WL16(p, v) +# endif + +# if defined(AV_RN24) && !defined(AV_RL24) +# define AV_RL24(p) AV_RN24(p) +# elif !defined(AV_RN24) && defined(AV_RL24) +# define AV_RN24(p) AV_RL24(p) +# endif + +# if defined(AV_WN24) && !defined(AV_WL24) +# define AV_WL24(p, v) AV_WN24(p, v) +# elif !defined(AV_WN24) && defined(AV_WL24) +# define AV_WN24(p, v) AV_WL24(p, v) +# endif + +# if defined(AV_RN32) && !defined(AV_RL32) +# define AV_RL32(p) AV_RN32(p) +# elif !defined(AV_RN32) && defined(AV_RL32) +# define AV_RN32(p) AV_RL32(p) +# endif + +# if defined(AV_WN32) && !defined(AV_WL32) +# define AV_WL32(p, v) AV_WN32(p, v) +# elif !defined(AV_WN32) && defined(AV_WL32) +# define AV_WN32(p, v) AV_WL32(p, v) +# endif + +# if defined(AV_RN64) && !defined(AV_RL64) +# define AV_RL64(p) AV_RN64(p) +# elif !defined(AV_RN64) && defined(AV_RL64) +# define AV_RN64(p) AV_RL64(p) +# endif + +# if defined(AV_WN64) && !defined(AV_WL64) +# define AV_WL64(p, v) AV_WN64(p, v) +# elif !defined(AV_WN64) && defined(AV_WL64) +# define AV_WN64(p, v) AV_WL64(p, v) +# endif + +#endif /* !AV_HAVE_BIGENDIAN */ + +/* + * Define AV_[RW]N helper macros to simplify definitions not provided + * by per-arch headers. + */ + +#if defined(__GNUC__) && !defined(__TI_COMPILER_VERSION__) + +union unaligned_64 { uint64_t l; } __attribute__((packed)) av_alias; +union unaligned_32 { uint32_t l; } __attribute__((packed)) av_alias; +union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias; + +# define AV_RN(s, p) (((const union unaligned_##s *) (p))->l) +# define AV_WN(s, p, v) ((((union unaligned_##s *) (p))->l) = (v)) + +#elif defined(__DECC) + +# define AV_RN(s, p) (*((const __unaligned uint##s##_t*)(p))) +# define AV_WN(s, p, v) (*((__unaligned uint##s##_t*)(p)) = (v)) + +#elif AV_HAVE_FAST_UNALIGNED + +# define AV_RN(s, p) (((const av_alias##s*)(p))->u##s) +# define AV_WN(s, p, v) (((av_alias##s*)(p))->u##s = (v)) + +#else + +#ifndef AV_RB16 +# define AV_RB16(x) \ + ((((const uint8_t*)(x))[0] << 8) | \ + ((const uint8_t*)(x))[1]) +#endif +#ifndef AV_WB16 +# define AV_WB16(p, d) do { \ + ((uint8_t*)(p))[1] = (d); \ + ((uint8_t*)(p))[0] = (d)>>8; \ + } while(0) +#endif + +#ifndef AV_RL16 +# define AV_RL16(x) \ + ((((const uint8_t*)(x))[1] << 8) | \ + ((const uint8_t*)(x))[0]) +#endif +#ifndef AV_WL16 +# define AV_WL16(p, d) do { \ + ((uint8_t*)(p))[0] = (d); \ + ((uint8_t*)(p))[1] = (d)>>8; \ + } while(0) +#endif + +#ifndef AV_RB32 +# define AV_RB32(x) \ + (((uint32_t)((const uint8_t*)(x))[0] << 24) | \ + (((const uint8_t*)(x))[1] << 16) | \ + (((const uint8_t*)(x))[2] << 8) | \ + ((const uint8_t*)(x))[3]) +#endif +#ifndef AV_WB32 +# define AV_WB32(p, d) do { \ + ((uint8_t*)(p))[3] = (d); \ + ((uint8_t*)(p))[2] = (d)>>8; \ + ((uint8_t*)(p))[1] = (d)>>16; \ + ((uint8_t*)(p))[0] = (d)>>24; \ + } while(0) +#endif + +#ifndef AV_RL32 +# define AV_RL32(x) \ + (((uint32_t)((const uint8_t*)(x))[3] << 24) | \ + (((const uint8_t*)(x))[2] << 16) | \ + (((const uint8_t*)(x))[1] << 8) | \ + ((const uint8_t*)(x))[0]) +#endif +#ifndef AV_WL32 +# define AV_WL32(p, d) do { \ + ((uint8_t*)(p))[0] = (d); \ + ((uint8_t*)(p))[1] = (d)>>8; \ + ((uint8_t*)(p))[2] = (d)>>16; \ + ((uint8_t*)(p))[3] = (d)>>24; \ + } while(0) +#endif + +#ifndef AV_RB64 +# define AV_RB64(x) \ + (((uint64_t)((const uint8_t*)(x))[0] << 56) | \ + ((uint64_t)((const uint8_t*)(x))[1] << 48) | \ + ((uint64_t)((const uint8_t*)(x))[2] << 40) | \ + ((uint64_t)((const uint8_t*)(x))[3] << 32) | \ + ((uint64_t)((const uint8_t*)(x))[4] << 24) | \ + ((uint64_t)((const uint8_t*)(x))[5] << 16) | \ + ((uint64_t)((const uint8_t*)(x))[6] << 8) | \ + (uint64_t)((const uint8_t*)(x))[7]) +#endif +#ifndef AV_WB64 +# define AV_WB64(p, d) do { \ + ((uint8_t*)(p))[7] = (d); \ + ((uint8_t*)(p))[6] = (d)>>8; \ + ((uint8_t*)(p))[5] = (d)>>16; \ + ((uint8_t*)(p))[4] = (d)>>24; \ + ((uint8_t*)(p))[3] = (d)>>32; \ + ((uint8_t*)(p))[2] = (d)>>40; \ + ((uint8_t*)(p))[1] = (d)>>48; \ + ((uint8_t*)(p))[0] = (d)>>56; \ + } while(0) +#endif + +#ifndef AV_RL64 +# define AV_RL64(x) \ + (((uint64_t)((const uint8_t*)(x))[7] << 56) | \ + ((uint64_t)((const uint8_t*)(x))[6] << 48) | \ + ((uint64_t)((const uint8_t*)(x))[5] << 40) | \ + ((uint64_t)((const uint8_t*)(x))[4] << 32) | \ + ((uint64_t)((const uint8_t*)(x))[3] << 24) | \ + ((uint64_t)((const uint8_t*)(x))[2] << 16) | \ + ((uint64_t)((const uint8_t*)(x))[1] << 8) | \ + (uint64_t)((const uint8_t*)(x))[0]) +#endif +#ifndef AV_WL64 +# define AV_WL64(p, d) do { \ + ((uint8_t*)(p))[0] = (d); \ + ((uint8_t*)(p))[1] = (d)>>8; \ + ((uint8_t*)(p))[2] = (d)>>16; \ + ((uint8_t*)(p))[3] = (d)>>24; \ + ((uint8_t*)(p))[4] = (d)>>32; \ + ((uint8_t*)(p))[5] = (d)>>40; \ + ((uint8_t*)(p))[6] = (d)>>48; \ + ((uint8_t*)(p))[7] = (d)>>56; \ + } while(0) +#endif + +#if AV_HAVE_BIGENDIAN +# define AV_RN(s, p) AV_RB##s(p) +# define AV_WN(s, p, v) AV_WB##s(p, v) +#else +# define AV_RN(s, p) AV_RL##s(p) +# define AV_WN(s, p, v) AV_WL##s(p, v) +#endif + +#endif /* HAVE_FAST_UNALIGNED */ + +#ifndef AV_RN16 +# define AV_RN16(p) AV_RN(16, p) +#endif + +#ifndef AV_RN32 +# define AV_RN32(p) AV_RN(32, p) +#endif + +#ifndef AV_RN64 +# define AV_RN64(p) AV_RN(64, p) +#endif + +#ifndef AV_WN16 +# define AV_WN16(p, v) AV_WN(16, p, v) +#endif + +#ifndef AV_WN32 +# define AV_WN32(p, v) AV_WN(32, p, v) +#endif + +#ifndef AV_WN64 +# define AV_WN64(p, v) AV_WN(64, p, v) +#endif + +#if AV_HAVE_BIGENDIAN +# define AV_RB(s, p) AV_RN##s(p) +# define AV_WB(s, p, v) AV_WN##s(p, v) +# define AV_RL(s, p) av_bswap##s(AV_RN##s(p)) +# define AV_WL(s, p, v) AV_WN##s(p, av_bswap##s(v)) +#else +# define AV_RB(s, p) av_bswap##s(AV_RN##s(p)) +# define AV_WB(s, p, v) AV_WN##s(p, av_bswap##s(v)) +# define AV_RL(s, p) AV_RN##s(p) +# define AV_WL(s, p, v) AV_WN##s(p, v) +#endif + +#define AV_RB8(x) (((const uint8_t*)(x))[0]) +#define AV_WB8(p, d) do { ((uint8_t*)(p))[0] = (d); } while(0) + +#define AV_RL8(x) AV_RB8(x) +#define AV_WL8(p, d) AV_WB8(p, d) + +#ifndef AV_RB16 +# define AV_RB16(p) AV_RB(16, p) +#endif +#ifndef AV_WB16 +# define AV_WB16(p, v) AV_WB(16, p, v) +#endif + +#ifndef AV_RL16 +# define AV_RL16(p) AV_RL(16, p) +#endif +#ifndef AV_WL16 +# define AV_WL16(p, v) AV_WL(16, p, v) +#endif + +#ifndef AV_RB32 +# define AV_RB32(p) AV_RB(32, p) +#endif +#ifndef AV_WB32 +# define AV_WB32(p, v) AV_WB(32, p, v) +#endif + +#ifndef AV_RL32 +# define AV_RL32(p) AV_RL(32, p) +#endif +#ifndef AV_WL32 +# define AV_WL32(p, v) AV_WL(32, p, v) +#endif + +#ifndef AV_RB64 +# define AV_RB64(p) AV_RB(64, p) +#endif +#ifndef AV_WB64 +# define AV_WB64(p, v) AV_WB(64, p, v) +#endif + +#ifndef AV_RL64 +# define AV_RL64(p) AV_RL(64, p) +#endif +#ifndef AV_WL64 +# define AV_WL64(p, v) AV_WL(64, p, v) +#endif + +#ifndef AV_RB24 +# define AV_RB24(x) \ + ((((const uint8_t*)(x))[0] << 16) | \ + (((const uint8_t*)(x))[1] << 8) | \ + ((const uint8_t*)(x))[2]) +#endif +#ifndef AV_WB24 +# define AV_WB24(p, d) do { \ + ((uint8_t*)(p))[2] = (d); \ + ((uint8_t*)(p))[1] = (d)>>8; \ + ((uint8_t*)(p))[0] = (d)>>16; \ + } while(0) +#endif + +#ifndef AV_RL24 +# define AV_RL24(x) \ + ((((const uint8_t*)(x))[2] << 16) | \ + (((const uint8_t*)(x))[1] << 8) | \ + ((const uint8_t*)(x))[0]) +#endif +#ifndef AV_WL24 +# define AV_WL24(p, d) do { \ + ((uint8_t*)(p))[0] = (d); \ + ((uint8_t*)(p))[1] = (d)>>8; \ + ((uint8_t*)(p))[2] = (d)>>16; \ + } while(0) +#endif + +/* + * The AV_[RW]NA macros access naturally aligned data + * in a type-safe way. + */ + +#define AV_RNA(s, p) (((const av_alias##s*)(p))->u##s) +#define AV_WNA(s, p, v) (((av_alias##s*)(p))->u##s = (v)) + +#ifndef AV_RN16A +# define AV_RN16A(p) AV_RNA(16, p) +#endif + +#ifndef AV_RN32A +# define AV_RN32A(p) AV_RNA(32, p) +#endif + +#ifndef AV_RN64A +# define AV_RN64A(p) AV_RNA(64, p) +#endif + +#ifndef AV_WN16A +# define AV_WN16A(p, v) AV_WNA(16, p, v) +#endif + +#ifndef AV_WN32A +# define AV_WN32A(p, v) AV_WNA(32, p, v) +#endif + +#ifndef AV_WN64A +# define AV_WN64A(p, v) AV_WNA(64, p, v) +#endif + +/* Parameters for AV_COPY*, AV_SWAP*, AV_ZERO* must be + * naturally aligned. They may be implemented using MMX, + * so emms_c() must be called before using any float code + * afterwards. + */ + +#define AV_COPY(n, d, s) \ + (((av_alias##n*)(d))->u##n = ((const av_alias##n*)(s))->u##n) + +#ifndef AV_COPY16 +# define AV_COPY16(d, s) AV_COPY(16, d, s) +#endif + +#ifndef AV_COPY32 +# define AV_COPY32(d, s) AV_COPY(32, d, s) +#endif + +#ifndef AV_COPY64 +# define AV_COPY64(d, s) AV_COPY(64, d, s) +#endif + +#ifndef AV_COPY128 +# define AV_COPY128(d, s) \ + do { \ + AV_COPY64(d, s); \ + AV_COPY64((char*)(d)+8, (char*)(s)+8); \ + } while(0) +#endif + +#define AV_SWAP(n, a, b) FFSWAP(av_alias##n, *(av_alias##n*)(a), *(av_alias##n*)(b)) + +#ifndef AV_SWAP64 +# define AV_SWAP64(a, b) AV_SWAP(64, a, b) +#endif + +#define AV_ZERO(n, d) (((av_alias##n*)(d))->u##n = 0) + +#ifndef AV_ZERO16 +# define AV_ZERO16(d) AV_ZERO(16, d) +#endif + +#ifndef AV_ZERO32 +# define AV_ZERO32(d) AV_ZERO(32, d) +#endif + +#ifndef AV_ZERO64 +# define AV_ZERO64(d) AV_ZERO(64, d) +#endif + +#ifndef AV_ZERO128 +# define AV_ZERO128(d) \ + do { \ + AV_ZERO64(d); \ + AV_ZERO64((char*)(d)+8); \ + } while(0) +#endif + +#endif /* AVUTIL_INTREADWRITE_H */ diff --git a/Externals/ffmpeg/include/libavutil/lfg.h b/Externals/ffmpeg/include/libavutil/lfg.h new file mode 100644 index 0000000000..854ffce73 --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/lfg.h @@ -0,0 +1,62 @@ +/* + * Lagged Fibonacci PRNG + * Copyright (c) 2008 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_LFG_H +#define AVUTIL_LFG_H + +typedef struct { + unsigned int state[64]; + int index; +} AVLFG; + +void av_lfg_init(AVLFG *c, unsigned int seed); + +/** + * Get the next random unsigned 32-bit number using an ALFG. + * + * Please also consider a simple LCG like state= state*1664525+1013904223, + * it may be good enough and faster for your specific use case. + */ +static inline unsigned int av_lfg_get(AVLFG *c){ + c->state[c->index & 63] = c->state[(c->index-24) & 63] + c->state[(c->index-55) & 63]; + return c->state[c->index++ & 63]; +} + +/** + * Get the next random unsigned 32-bit number using a MLFG. + * + * Please also consider av_lfg_get() above, it is faster. + */ +static inline unsigned int av_mlfg_get(AVLFG *c){ + unsigned int a= c->state[(c->index-55) & 63]; + unsigned int b= c->state[(c->index-24) & 63]; + return c->state[c->index++ & 63] = 2*a*b+a+b; +} + +/** + * Get the next two numbers generated by a Box-Muller Gaussian + * generator using the random numbers issued by lfg. + * + * @param out array where the two generated numbers are placed + */ +void av_bmg_get(AVLFG *lfg, double out[2]); + +#endif /* AVUTIL_LFG_H */ diff --git a/Externals/ffmpeg/include/libavutil/log.h b/Externals/ffmpeg/include/libavutil/log.h new file mode 100644 index 0000000000..02a0e1ac8 --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/log.h @@ -0,0 +1,182 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_LOG_H +#define AVUTIL_LOG_H + +#include +#include "avutil.h" +#include "attributes.h" + +/** + * Describe the class of an AVClass context structure. That is an + * arbitrary struct of which the first field is a pointer to an + * AVClass struct (e.g. AVCodecContext, AVFormatContext etc.). + */ +typedef struct AVClass { + /** + * The name of the class; usually it is the same name as the + * context structure type to which the AVClass is associated. + */ + const char* class_name; + + /** + * A pointer to a function which returns the name of a context + * instance ctx associated with the class. + */ + const char* (*item_name)(void* ctx); + + /** + * a pointer to the first option specified in the class if any or NULL + * + * @see av_set_default_options() + */ + const struct AVOption *option; + + /** + * LIBAVUTIL_VERSION with which this structure was created. + * This is used to allow fields to be added without requiring major + * version bumps everywhere. + */ + + int version; + + /** + * Offset in the structure where log_level_offset is stored. + * 0 means there is no such variable + */ + int log_level_offset_offset; + + /** + * Offset in the structure where a pointer to the parent context for loging is stored. + * for example a decoder that uses eval.c could pass its AVCodecContext to eval as such + * parent context. And a av_log() implementation could then display the parent context + * can be NULL of course + */ + int parent_log_context_offset; + + /** + * Return next AVOptions-enabled child or NULL + */ + void* (*child_next)(void *obj, void *prev); + + /** + * Return an AVClass corresponding to next potential + * AVOptions-enabled child. + * + * The difference between child_next and this is that + * child_next iterates over _already existing_ objects, while + * child_class_next iterates over _all possible_ children. + */ + const struct AVClass* (*child_class_next)(const struct AVClass *prev); +} AVClass; + +/* av_log API */ + +#define AV_LOG_QUIET -8 + +/** + * Something went really wrong and we will crash now. + */ +#define AV_LOG_PANIC 0 + +/** + * Something went wrong and recovery is not possible. + * For example, no header was found for a format which depends + * on headers or an illegal combination of parameters is used. + */ +#define AV_LOG_FATAL 8 + +/** + * Something went wrong and cannot losslessly be recovered. + * However, not all future data is affected. + */ +#define AV_LOG_ERROR 16 + +/** + * Something somehow does not look correct. This may or may not + * lead to problems. An example would be the use of '-vstrict -2'. + */ +#define AV_LOG_WARNING 24 + +#define AV_LOG_INFO 32 +#define AV_LOG_VERBOSE 40 + +/** + * Stuff which is only useful for libav* developers. + */ +#define AV_LOG_DEBUG 48 + +/** + * Send the specified message to the log if the level is less than or equal + * to the current av_log_level. By default, all logging messages are sent to + * stderr. This behavior can be altered by setting a different av_vlog callback + * function. + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct. + * @param level The importance level of the message, lower values signifying + * higher importance. + * @param fmt The format string (printf-compatible) that specifies how + * subsequent arguments are converted to output. + * @see av_vlog + */ +void av_log(void *avcl, int level, const char *fmt, ...) av_printf_format(3, 4); + +void av_vlog(void *avcl, int level, const char *fmt, va_list); +int av_log_get_level(void); +void av_log_set_level(int); +void av_log_set_callback(void (*)(void*, int, const char*, va_list)); +void av_log_default_callback(void* ptr, int level, const char* fmt, va_list vl); +const char* av_default_item_name(void* ctx); + +/** + * Format a line of log the same way as the default callback. + * @param line buffer to receive the formated line + * @param line_size size of the buffer + * @param print_prefix used to store whether the prefix must be printed; + * must point to a persistent integer initially set to 1 + */ +void av_log_format_line(void *ptr, int level, const char *fmt, va_list vl, + char *line, int line_size, int *print_prefix); + +/** + * av_dlog macros + * Useful to print debug messages that shouldn't get compiled in normally. + */ + +#ifdef DEBUG +# define av_dlog(pctx, ...) av_log(pctx, AV_LOG_DEBUG, __VA_ARGS__) +#else +# define av_dlog(pctx, ...) do { if (0) av_log(pctx, AV_LOG_DEBUG, __VA_ARGS__); } while (0) +#endif + +/** + * Skip repeated messages, this requires the user app to use av_log() instead of + * (f)printf as the 2 would otherwise interfere and lead to + * "Last message repeated x times" messages below (f)printf messages with some + * bad luck. + * Also to receive the last, "last repeated" line if any, the user app must + * call av_log(NULL, AV_LOG_QUIET, "%s", ""); at the end + */ +#define AV_LOG_SKIP_REPEATED 1 +void av_log_set_flags(int arg); + +#endif /* AVUTIL_LOG_H */ diff --git a/Externals/ffmpeg/include/libavutil/lzo.h b/Externals/ffmpeg/include/libavutil/lzo.h new file mode 100644 index 0000000000..060b5c9d7 --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/lzo.h @@ -0,0 +1,77 @@ +/* + * LZO 1x decompression + * copyright (c) 2006 Reimar Doeffinger + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_LZO_H +#define AVUTIL_LZO_H + +/** + * @defgroup lavu_lzo LZO + * @ingroup lavu_crypto + * + * @{ + */ + +#include + +/** @name Error flags returned by av_lzo1x_decode + * @{ */ +/// end of the input buffer reached before decoding finished +#define AV_LZO_INPUT_DEPLETED 1 +/// decoded data did not fit into output buffer +#define AV_LZO_OUTPUT_FULL 2 +/// a reference to previously decoded data was wrong +#define AV_LZO_INVALID_BACKPTR 4 +/// a non-specific error in the compressed bitstream +#define AV_LZO_ERROR 8 +/** @} */ + +#define AV_LZO_INPUT_PADDING 8 +#define AV_LZO_OUTPUT_PADDING 12 + +/** + * @brief Decodes LZO 1x compressed data. + * @param out output buffer + * @param outlen size of output buffer, number of bytes left are returned here + * @param in input buffer + * @param inlen size of input buffer, number of bytes left are returned here + * @return 0 on success, otherwise a combination of the error flags above + * + * Make sure all buffers are appropriately padded, in must provide + * AV_LZO_INPUT_PADDING, out must provide AV_LZO_OUTPUT_PADDING additional bytes. + */ +int av_lzo1x_decode(void *out, int *outlen, const void *in, int *inlen); + +/** + * @brief deliberately overlapping memcpy implementation + * @param dst destination buffer; must be padded with 12 additional bytes + * @param back how many bytes back we start (the initial size of the overlapping window), must be > 0 + * @param cnt number of bytes to copy, must be >= 0 + * + * cnt > back is valid, this will copy the bytes we just copied, + * thus creating a repeating pattern with a period length of back. + */ +void av_memcpy_backptr(uint8_t *dst, int back, int cnt); + +/** + * @} + */ + +#endif /* AVUTIL_LZO_H */ diff --git a/Externals/ffmpeg/include/libavutil/mathematics.h b/Externals/ffmpeg/include/libavutil/mathematics.h new file mode 100644 index 0000000000..ad39e263c --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/mathematics.h @@ -0,0 +1,122 @@ +/* + * copyright (c) 2005 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_MATHEMATICS_H +#define AVUTIL_MATHEMATICS_H + +#include +#include +#include "attributes.h" +#include "rational.h" + +#ifndef M_E +#define M_E 2.7182818284590452354 /* e */ +#endif +#ifndef M_LN2 +#define M_LN2 0.69314718055994530942 /* log_e 2 */ +#endif +#ifndef M_LN10 +#define M_LN10 2.30258509299404568402 /* log_e 10 */ +#endif +#ifndef M_LOG2_10 +#define M_LOG2_10 3.32192809488736234787 /* log_2 10 */ +#endif +#ifndef M_PHI +#define M_PHI 1.61803398874989484820 /* phi / golden ratio */ +#endif +#ifndef M_PI +#define M_PI 3.14159265358979323846 /* pi */ +#endif +#ifndef M_SQRT1_2 +#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ +#endif +#ifndef M_SQRT2 +#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ +#endif +#ifndef NAN +#define NAN (0.0/0.0) +#endif +#ifndef INFINITY +#define INFINITY (1.0/0.0) +#endif + +/** + * @addtogroup lavu_math + * @{ + */ + + +enum AVRounding { + AV_ROUND_ZERO = 0, ///< Round toward zero. + AV_ROUND_INF = 1, ///< Round away from zero. + AV_ROUND_DOWN = 2, ///< Round toward -infinity. + AV_ROUND_UP = 3, ///< Round toward +infinity. + AV_ROUND_NEAR_INF = 5, ///< Round to nearest and halfway cases away from zero. +}; + +/** + * Return the greatest common divisor of a and b. + * If both a and b are 0 or either or both are <0 then behavior is + * undefined. + */ +int64_t av_const av_gcd(int64_t a, int64_t b); + +/** + * Rescale a 64-bit integer with rounding to nearest. + * A simple a*b/c isn't possible as it can overflow. + */ +int64_t av_rescale(int64_t a, int64_t b, int64_t c) av_const; + +/** + * Rescale a 64-bit integer with specified rounding. + * A simple a*b/c isn't possible as it can overflow. + */ +int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding) av_const; + +/** + * Rescale a 64-bit integer by 2 rational numbers. + */ +int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq) av_const; + +/** + * Compare 2 timestamps each in its own timebases. + * The result of the function is undefined if one of the timestamps + * is outside the int64_t range when represented in the others timebase. + * @return -1 if ts_a is before ts_b, 1 if ts_a is after ts_b or 0 if they represent the same position + */ +int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b); + +/** + * Compare 2 integers modulo mod. + * That is we compare integers a and b for which only the least + * significant log2(mod) bits are known. + * + * @param mod must be a power of 2 + * @return a negative value if a is smaller than b + * a positive value if a is greater than b + * 0 if a equals b + */ +int64_t av_compare_mod(uint64_t a, uint64_t b, uint64_t mod); + +/** + * @} + */ + +#endif /* AVUTIL_MATHEMATICS_H */ diff --git a/Externals/ffmpeg/include/libavutil/md5.h b/Externals/ffmpeg/include/libavutil/md5.h new file mode 100644 index 0000000000..1333ab2dd --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/md5.h @@ -0,0 +1,46 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_MD5_H +#define AVUTIL_MD5_H + +#include + +/** + * @defgroup lavu_md5 MD5 + * @ingroup lavu_crypto + * @{ + */ + +extern const int av_md5_size; + +struct AVMD5; + +void av_md5_init(struct AVMD5 *ctx); +void av_md5_update(struct AVMD5 *ctx, const uint8_t *src, const int len); +void av_md5_final(struct AVMD5 *ctx, uint8_t *dst); +void av_md5_sum(uint8_t *dst, const uint8_t *src, const int len); + +/** + * @} + */ + +#endif /* AVUTIL_MD5_H */ + diff --git a/Externals/ffmpeg/include/libavutil/mem.h b/Externals/ffmpeg/include/libavutil/mem.h new file mode 100644 index 0000000000..c6c907ea0 --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/mem.h @@ -0,0 +1,188 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * memory handling functions + */ + +#ifndef AVUTIL_MEM_H +#define AVUTIL_MEM_H + +#include "attributes.h" +#include "error.h" +#include "avutil.h" + +/** + * @addtogroup lavu_mem + * @{ + */ + + +#if defined(__INTEL_COMPILER) && __INTEL_COMPILER < 1110 || defined(__SUNPRO_C) + #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v + #define DECLARE_ASM_CONST(n,t,v) const t __attribute__ ((aligned (n))) v +#elif defined(__TI_COMPILER_VERSION__) + #define DECLARE_ALIGNED(n,t,v) \ + AV_PRAGMA(DATA_ALIGN(v,n)) \ + t __attribute__((aligned(n))) v + #define DECLARE_ASM_CONST(n,t,v) \ + AV_PRAGMA(DATA_ALIGN(v,n)) \ + static const t __attribute__((aligned(n))) v +#elif defined(__GNUC__) + #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v + #define DECLARE_ASM_CONST(n,t,v) static const t av_used __attribute__ ((aligned (n))) v +#elif defined(_MSC_VER) + #define DECLARE_ALIGNED(n,t,v) __declspec(align(n)) t v + #define DECLARE_ASM_CONST(n,t,v) __declspec(align(n)) static const t v +#else + #define DECLARE_ALIGNED(n,t,v) t v + #define DECLARE_ASM_CONST(n,t,v) static const t v +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,1) + #define av_malloc_attrib __attribute__((__malloc__)) +#else + #define av_malloc_attrib +#endif + +#if AV_GCC_VERSION_AT_LEAST(4,3) + #define av_alloc_size(n) __attribute__((alloc_size(n))) +#else + #define av_alloc_size(n) +#endif + +/** + * Allocate a block of size bytes with alignment suitable for all + * memory accesses (including vectors if available on the CPU). + * @param size Size in bytes for the memory block to be allocated. + * @return Pointer to the allocated block, NULL if the block cannot + * be allocated. + * @see av_mallocz() + */ +void *av_malloc(size_t size) av_malloc_attrib av_alloc_size(1); + +/** + * Allocate or reallocate a block of memory. + * If ptr is NULL and size > 0, allocate a new block. If + * size is zero, free the memory block pointed to by ptr. + * @param ptr Pointer to a memory block already allocated with + * av_malloc(z)() or av_realloc() or NULL. + * @param size Size in bytes for the memory block to be allocated or + * reallocated. + * @return Pointer to a newly reallocated block or NULL if the block + * cannot be reallocated or the function is used to free the memory block. + * @see av_fast_realloc() + */ +void *av_realloc(void *ptr, size_t size) av_alloc_size(2); + +/** + * Allocate or reallocate a block of memory. + * This function does the same thing as av_realloc, except: + * - It takes two arguments and checks the result of the multiplication for + * integer overflow. + * - It frees the input block in case of failure, thus avoiding the memory + * leak with the classic "buf = realloc(buf); if (!buf) return -1;". + */ +void *av_realloc_f(void *ptr, size_t nelem, size_t elsize); + +/** + * Free a memory block which has been allocated with av_malloc(z)() or + * av_realloc(). + * @param ptr Pointer to the memory block which should be freed. + * @note ptr = NULL is explicitly allowed. + * @note It is recommended that you use av_freep() instead. + * @see av_freep() + */ +void av_free(void *ptr); + +/** + * Allocate a block of size bytes with alignment suitable for all + * memory accesses (including vectors if available on the CPU) and + * zero all the bytes of the block. + * @param size Size in bytes for the memory block to be allocated. + * @return Pointer to the allocated block, NULL if it cannot be allocated. + * @see av_malloc() + */ +void *av_mallocz(size_t size) av_malloc_attrib av_alloc_size(1); + +/** + * Allocate a block of nmemb * size bytes with alignment suitable for all + * memory accesses (including vectors if available on the CPU) and + * zero all the bytes of the block. + * The allocation will fail if nmemb * size is greater than or equal + * to INT_MAX. + * @param nmemb + * @param size + * @return Pointer to the allocated block, NULL if it cannot be allocated. + */ +void *av_calloc(size_t nmemb, size_t size) av_malloc_attrib; + +/** + * Duplicate the string s. + * @param s string to be duplicated + * @return Pointer to a newly allocated string containing a + * copy of s or NULL if the string cannot be allocated. + */ +char *av_strdup(const char *s) av_malloc_attrib; + +/** + * Free a memory block which has been allocated with av_malloc(z)() or + * av_realloc() and set the pointer pointing to it to NULL. + * @param ptr Pointer to the pointer to the memory block which should + * be freed. + * @see av_free() + */ +void av_freep(void *ptr); + +/** + * Add an element to a dynamic array. + * + * @param tab_ptr Pointer to the array. + * @param nb_ptr Pointer to the number of elements in the array. + * @param elem Element to be added. + */ +void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem); + +/** + * Multiply two size_t values checking for overflow. + * @return 0 if success, AVERROR(EINVAL) if overflow. + */ +static inline int av_size_mult(size_t a, size_t b, size_t *r) +{ + size_t t = a * b; + /* Hack inspired from glibc: only try the division if nelem and elsize + * are both greater than sqrt(SIZE_MAX). */ + if ((a | b) >= ((size_t)1 << (sizeof(size_t) * 4)) && a && t / a != b) + return AVERROR(EINVAL); + *r = t; + return 0; +} + +/** + * Set the maximum size that may me allocated in one block. + */ +void av_max_alloc(size_t max); + +/** + * @} + */ + +#endif /* AVUTIL_MEM_H */ diff --git a/Externals/ffmpeg/include/libavutil/opt.h b/Externals/ffmpeg/include/libavutil/opt.h new file mode 100644 index 0000000000..0196056d6 --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/opt.h @@ -0,0 +1,603 @@ +/* + * AVOptions + * copyright (c) 2005 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_OPT_H +#define AVUTIL_OPT_H + +/** + * @file + * AVOptions + */ + +#include "rational.h" +#include "avutil.h" +#include "dict.h" +#include "log.h" + +/** + * @defgroup avoptions AVOptions + * @ingroup lavu_data + * @{ + * AVOptions provide a generic system to declare options on arbitrary structs + * ("objects"). An option can have a help text, a type and a range of possible + * values. Options may then be enumerated, read and written to. + * + * @section avoptions_implement Implementing AVOptions + * This section describes how to add AVOptions capabilities to a struct. + * + * All AVOptions-related information is stored in an AVClass. Therefore + * the first member of the struct must be a pointer to an AVClass describing it. + * The option field of the AVClass must be set to a NULL-terminated static array + * of AVOptions. Each AVOption must have a non-empty name, a type, a default + * value and for number-type AVOptions also a range of allowed values. It must + * also declare an offset in bytes from the start of the struct, where the field + * associated with this AVOption is located. Other fields in the AVOption struct + * should also be set when applicable, but are not required. + * + * The following example illustrates an AVOptions-enabled struct: + * @code + * typedef struct test_struct { + * AVClass *class; + * int int_opt; + * char *str_opt; + * uint8_t *bin_opt; + * int bin_len; + * } test_struct; + * + * static const AVOption options[] = { + * { "test_int", "This is a test option of int type.", offsetof(test_struct, int_opt), + * AV_OPT_TYPE_INT, { -1 }, INT_MIN, INT_MAX }, + * { "test_str", "This is a test option of string type.", offsetof(test_struct, str_opt), + * AV_OPT_TYPE_STRING }, + * { "test_bin", "This is a test option of binary type.", offsetof(test_struct, bin_opt), + * AV_OPT_TYPE_BINARY }, + * { NULL }, + * }; + * + * static const AVClass test_class = { + * .class_name = "test class", + * .item_name = av_default_item_name, + * .option = options, + * .version = LIBAVUTIL_VERSION_INT, + * }; + * @endcode + * + * Next, when allocating your struct, you must ensure that the AVClass pointer + * is set to the correct value. Then, av_opt_set_defaults() must be called to + * initialize defaults. After that the struct is ready to be used with the + * AVOptions API. + * + * When cleaning up, you may use the av_opt_free() function to automatically + * free all the allocated string and binary options. + * + * Continuing with the above example: + * + * @code + * test_struct *alloc_test_struct(void) + * { + * test_struct *ret = av_malloc(sizeof(*ret)); + * ret->class = &test_class; + * av_opt_set_defaults(ret); + * return ret; + * } + * void free_test_struct(test_struct **foo) + * { + * av_opt_free(*foo); + * av_freep(foo); + * } + * @endcode + * + * @subsection avoptions_implement_nesting Nesting + * It may happen that an AVOptions-enabled struct contains another + * AVOptions-enabled struct as a member (e.g. AVCodecContext in + * libavcodec exports generic options, while its priv_data field exports + * codec-specific options). In such a case, it is possible to set up the + * parent struct to export a child's options. To do that, simply + * implement AVClass.child_next() and AVClass.child_class_next() in the + * parent struct's AVClass. + * Assuming that the test_struct from above now also contains a + * child_struct field: + * + * @code + * typedef struct child_struct { + * AVClass *class; + * int flags_opt; + * } child_struct; + * static const AVOption child_opts[] = { + * { "test_flags", "This is a test option of flags type.", + * offsetof(child_struct, flags_opt), AV_OPT_TYPE_FLAGS, { 0 }, INT_MIN, INT_MAX }, + * { NULL }, + * }; + * static const AVClass child_class = { + * .class_name = "child class", + * .item_name = av_default_item_name, + * .option = child_opts, + * .version = LIBAVUTIL_VERSION_INT, + * }; + * + * void *child_next(void *obj, void *prev) + * { + * test_struct *t = obj; + * if (!prev && t->child_struct) + * return t->child_struct; + * return NULL + * } + * const AVClass child_class_next(const AVClass *prev) + * { + * return prev ? NULL : &child_class; + * } + * @endcode + * Putting child_next() and child_class_next() as defined above into + * test_class will now make child_struct's options accessible through + * test_struct (again, proper setup as described above needs to be done on + * child_struct right after it is created). + * + * From the above example it might not be clear why both child_next() + * and child_class_next() are needed. The distinction is that child_next() + * iterates over actually existing objects, while child_class_next() + * iterates over all possible child classes. E.g. if an AVCodecContext + * was initialized to use a codec which has private options, then its + * child_next() will return AVCodecContext.priv_data and finish + * iterating. OTOH child_class_next() on AVCodecContext.av_class will + * iterate over all available codecs with private options. + * + * @subsection avoptions_implement_named_constants Named constants + * It is possible to create named constants for options. Simply set the unit + * field of the option the constants should apply to to a string and + * create the constants themselves as options of type AV_OPT_TYPE_CONST + * with their unit field set to the same string. + * Their default_val field should contain the value of the named + * constant. + * For example, to add some named constants for the test_flags option + * above, put the following into the child_opts array: + * @code + * { "test_flags", "This is a test option of flags type.", + * offsetof(child_struct, flags_opt), AV_OPT_TYPE_FLAGS, { 0 }, INT_MIN, INT_MAX, "test_unit" }, + * { "flag1", "This is a flag with value 16", 0, AV_OPT_TYPE_CONST, { 16 }, 0, 0, "test_unit" }, + * @endcode + * + * @section avoptions_use Using AVOptions + * This section deals with accessing options in an AVOptions-enabled struct. + * Such structs in FFmpeg are e.g. AVCodecContext in libavcodec or + * AVFormatContext in libavformat. + * + * @subsection avoptions_use_examine Examining AVOptions + * The basic functions for examining options are av_opt_next(), which iterates + * over all options defined for one object, and av_opt_find(), which searches + * for an option with the given name. + * + * The situation is more complicated with nesting. An AVOptions-enabled struct + * may have AVOptions-enabled children. Passing the AV_OPT_SEARCH_CHILDREN flag + * to av_opt_find() will make the function search children recursively. + * + * For enumerating there are basically two cases. The first is when you want to + * get all options that may potentially exist on the struct and its children + * (e.g. when constructing documentation). In that case you should call + * av_opt_child_class_next() recursively on the parent struct's AVClass. The + * second case is when you have an already initialized struct with all its + * children and you want to get all options that can be actually written or read + * from it. In that case you should call av_opt_child_next() recursively (and + * av_opt_next() on each result). + * + * @subsection avoptions_use_get_set Reading and writing AVOptions + * When setting options, you often have a string read directly from the + * user. In such a case, simply passing it to av_opt_set() is enough. For + * non-string type options, av_opt_set() will parse the string according to the + * option type. + * + * Similarly av_opt_get() will read any option type and convert it to a string + * which will be returned. Do not forget that the string is allocated, so you + * have to free it with av_free(). + * + * In some cases it may be more convenient to put all options into an + * AVDictionary and call av_opt_set_dict() on it. A specific case of this + * are the format/codec open functions in lavf/lavc which take a dictionary + * filled with option as a parameter. This allows to set some options + * that cannot be set otherwise, since e.g. the input file format is not known + * before the file is actually opened. + */ + +enum AVOptionType{ + AV_OPT_TYPE_FLAGS, + AV_OPT_TYPE_INT, + AV_OPT_TYPE_INT64, + AV_OPT_TYPE_DOUBLE, + AV_OPT_TYPE_FLOAT, + AV_OPT_TYPE_STRING, + AV_OPT_TYPE_RATIONAL, + AV_OPT_TYPE_BINARY, ///< offset must point to a pointer immediately followed by an int for the length + AV_OPT_TYPE_CONST = 128, +#if FF_API_OLD_AVOPTIONS + FF_OPT_TYPE_FLAGS = 0, + FF_OPT_TYPE_INT, + FF_OPT_TYPE_INT64, + FF_OPT_TYPE_DOUBLE, + FF_OPT_TYPE_FLOAT, + FF_OPT_TYPE_STRING, + FF_OPT_TYPE_RATIONAL, + FF_OPT_TYPE_BINARY, ///< offset must point to a pointer immediately followed by an int for the length + FF_OPT_TYPE_CONST=128, +#endif +}; + +/** + * AVOption + */ +typedef struct AVOption { + const char *name; + + /** + * short English help text + * @todo What about other languages? + */ + const char *help; + + /** + * The offset relative to the context structure where the option + * value is stored. It should be 0 for named constants. + */ + int offset; + enum AVOptionType type; + + /** + * the default value for scalar options + */ + union { + double dbl; + const char *str; + /* TODO those are unused now */ + int64_t i64; + AVRational q; + } default_val; + double min; ///< minimum valid value for the option + double max; ///< maximum valid value for the option + + int flags; +#define AV_OPT_FLAG_ENCODING_PARAM 1 ///< a generic parameter which can be set by the user for muxing or encoding +#define AV_OPT_FLAG_DECODING_PARAM 2 ///< a generic parameter which can be set by the user for demuxing or decoding +#define AV_OPT_FLAG_METADATA 4 ///< some data extracted or inserted into the file like title, comment, ... +#define AV_OPT_FLAG_AUDIO_PARAM 8 +#define AV_OPT_FLAG_VIDEO_PARAM 16 +#define AV_OPT_FLAG_SUBTITLE_PARAM 32 +//FIXME think about enc-audio, ... style flags + + /** + * The logical unit to which the option belongs. Non-constant + * options and corresponding named constants share the same + * unit. May be NULL. + */ + const char *unit; +} AVOption; + +#if FF_API_FIND_OPT +/** + * Look for an option in obj. Look only for the options which + * have the flags set as specified in mask and flags (that is, + * for which it is the case that opt->flags & mask == flags). + * + * @param[in] obj a pointer to a struct whose first element is a + * pointer to an AVClass + * @param[in] name the name of the option to look for + * @param[in] unit the unit of the option to look for, or any if NULL + * @return a pointer to the option found, or NULL if no option + * has been found + * + * @deprecated use av_opt_find. + */ +attribute_deprecated +const AVOption *av_find_opt(void *obj, const char *name, const char *unit, int mask, int flags); +#endif + +#if FF_API_OLD_AVOPTIONS +/** + * Set the field of obj with the given name to value. + * + * @param[in] obj A struct whose first element is a pointer to an + * AVClass. + * @param[in] name the name of the field to set + * @param[in] val The value to set. If the field is not of a string + * type, then the given string is parsed. + * SI postfixes and some named scalars are supported. + * If the field is of a numeric type, it has to be a numeric or named + * scalar. Behavior with more than one scalar and +- infix operators + * is undefined. + * If the field is of a flags type, it has to be a sequence of numeric + * scalars or named flags separated by '+' or '-'. Prefixing a flag + * with '+' causes it to be set without affecting the other flags; + * similarly, '-' unsets a flag. + * @param[out] o_out if non-NULL put here a pointer to the AVOption + * found + * @param alloc this parameter is currently ignored + * @return 0 if the value has been set, or an AVERROR code in case of + * error: + * AVERROR_OPTION_NOT_FOUND if no matching option exists + * AVERROR(ERANGE) if the value is out of range + * AVERROR(EINVAL) if the value is not valid + * @deprecated use av_opt_set() + */ +attribute_deprecated +int av_set_string3(void *obj, const char *name, const char *val, int alloc, const AVOption **o_out); + +attribute_deprecated const AVOption *av_set_double(void *obj, const char *name, double n); +attribute_deprecated const AVOption *av_set_q(void *obj, const char *name, AVRational n); +attribute_deprecated const AVOption *av_set_int(void *obj, const char *name, int64_t n); + +double av_get_double(void *obj, const char *name, const AVOption **o_out); +AVRational av_get_q(void *obj, const char *name, const AVOption **o_out); +int64_t av_get_int(void *obj, const char *name, const AVOption **o_out); +attribute_deprecated const char *av_get_string(void *obj, const char *name, const AVOption **o_out, char *buf, int buf_len); +attribute_deprecated const AVOption *av_next_option(void *obj, const AVOption *last); +#endif + +/** + * Show the obj options. + * + * @param req_flags requested flags for the options to show. Show only the + * options for which it is opt->flags & req_flags. + * @param rej_flags rejected flags for the options to show. Show only the + * options for which it is !(opt->flags & req_flags). + * @param av_log_obj log context to use for showing the options + */ +int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags); + +/** + * Set the values of all AVOption fields to their default values. + * + * @param s an AVOption-enabled struct (its first member must be a pointer to AVClass) + */ +void av_opt_set_defaults(void *s); + +#if FF_API_OLD_AVOPTIONS +attribute_deprecated +void av_opt_set_defaults2(void *s, int mask, int flags); +#endif + +/** + * Parse the key/value pairs list in opts. For each key/value pair + * found, stores the value in the field in ctx that is named like the + * key. ctx must be an AVClass context, storing is done using + * AVOptions. + * + * @param opts options string to parse, may be NULL + * @param key_val_sep a 0-terminated list of characters used to + * separate key from value + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other + * @return the number of successfully set key/value pairs, or a negative + * value corresponding to an AVERROR code in case of error: + * AVERROR(EINVAL) if opts cannot be parsed, + * the error code issued by av_set_string3() if a key/value pair + * cannot be set + */ +int av_set_options_string(void *ctx, const char *opts, + const char *key_val_sep, const char *pairs_sep); + +/** + * Free all string and binary options in obj. + */ +void av_opt_free(void *obj); + +/** + * Check whether a particular flag is set in a flags field. + * + * @param field_name the name of the flag field option + * @param flag_name the name of the flag to check + * @return non-zero if the flag is set, zero if the flag isn't set, + * isn't of the right type, or the flags field doesn't exist. + */ +int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name); + +/* + * Set all the options from a given dictionary on an object. + * + * @param obj a struct whose first element is a pointer to AVClass + * @param options options to process. This dictionary will be freed and replaced + * by a new one containing all options not found in obj. + * Of course this new dictionary needs to be freed by caller + * with av_dict_free(). + * + * @return 0 on success, a negative AVERROR if some option was found in obj, + * but could not be set. + * + * @see av_dict_copy() + */ +int av_opt_set_dict(void *obj, struct AVDictionary **options); + +/** + * @defgroup opt_eval_funcs Evaluating option strings + * @{ + * This group of functions can be used to evaluate option strings + * and get numbers out of them. They do the same thing as av_opt_set(), + * except the result is written into the caller-supplied pointer. + * + * @param obj a struct whose first element is a pointer to AVClass. + * @param o an option for which the string is to be evaluated. + * @param val string to be evaluated. + * @param *_out value of the string will be written here. + * + * @return 0 on success, a negative number on failure. + */ +int av_opt_eval_flags (void *obj, const AVOption *o, const char *val, int *flags_out); +int av_opt_eval_int (void *obj, const AVOption *o, const char *val, int *int_out); +int av_opt_eval_int64 (void *obj, const AVOption *o, const char *val, int64_t *int64_out); +int av_opt_eval_float (void *obj, const AVOption *o, const char *val, float *float_out); +int av_opt_eval_double(void *obj, const AVOption *o, const char *val, double *double_out); +int av_opt_eval_q (void *obj, const AVOption *o, const char *val, AVRational *q_out); +/** + * @} + */ + +#define AV_OPT_SEARCH_CHILDREN 0x0001 /**< Search in possible children of the + given object first. */ +/** + * The obj passed to av_opt_find() is fake -- only a double pointer to AVClass + * instead of a required pointer to a struct containing AVClass. This is + * useful for searching for options without needing to allocate the corresponding + * object. + */ +#define AV_OPT_SEARCH_FAKE_OBJ 0x0002 + +/** + * Look for an option in an object. Consider only options which + * have all the specified flags set. + * + * @param[in] obj A pointer to a struct whose first element is a + * pointer to an AVClass. + * Alternatively a double pointer to an AVClass, if + * AV_OPT_SEARCH_FAKE_OBJ search flag is set. + * @param[in] name The name of the option to look for. + * @param[in] unit When searching for named constants, name of the unit + * it belongs to. + * @param opt_flags Find only options with all the specified flags set (AV_OPT_FLAG). + * @param search_flags A combination of AV_OPT_SEARCH_*. + * + * @return A pointer to the option found, or NULL if no option + * was found. + * + * @note Options found with AV_OPT_SEARCH_CHILDREN flag may not be settable + * directly with av_set_string3(). Use special calls which take an options + * AVDictionary (e.g. avformat_open_input()) to set options found with this + * flag. + */ +const AVOption *av_opt_find(void *obj, const char *name, const char *unit, + int opt_flags, int search_flags); + +/** + * Look for an option in an object. Consider only options which + * have all the specified flags set. + * + * @param[in] obj A pointer to a struct whose first element is a + * pointer to an AVClass. + * Alternatively a double pointer to an AVClass, if + * AV_OPT_SEARCH_FAKE_OBJ search flag is set. + * @param[in] name The name of the option to look for. + * @param[in] unit When searching for named constants, name of the unit + * it belongs to. + * @param opt_flags Find only options with all the specified flags set (AV_OPT_FLAG). + * @param search_flags A combination of AV_OPT_SEARCH_*. + * @param[out] target_obj if non-NULL, an object to which the option belongs will be + * written here. It may be different from obj if AV_OPT_SEARCH_CHILDREN is present + * in search_flags. This parameter is ignored if search_flags contain + * AV_OPT_SEARCH_FAKE_OBJ. + * + * @return A pointer to the option found, or NULL if no option + * was found. + */ +const AVOption *av_opt_find2(void *obj, const char *name, const char *unit, + int opt_flags, int search_flags, void **target_obj); + +/** + * Iterate over all AVOptions belonging to obj. + * + * @param obj an AVOptions-enabled struct or a double pointer to an + * AVClass describing it. + * @param prev result of the previous call to av_opt_next() on this object + * or NULL + * @return next AVOption or NULL + */ +const AVOption *av_opt_next(void *obj, const AVOption *prev); + +/** + * Iterate over AVOptions-enabled children of obj. + * + * @param prev result of a previous call to this function or NULL + * @return next AVOptions-enabled child or NULL + */ +void *av_opt_child_next(void *obj, void *prev); + +/** + * Iterate over potential AVOptions-enabled children of parent. + * + * @param prev result of a previous call to this function or NULL + * @return AVClass corresponding to next potential child or NULL + */ +const AVClass *av_opt_child_class_next(const AVClass *parent, const AVClass *prev); + +/** + * @defgroup opt_set_funcs Option setting functions + * @{ + * Those functions set the field of obj with the given name to value. + * + * @param[in] obj A struct whose first element is a pointer to an AVClass. + * @param[in] name the name of the field to set + * @param[in] val The value to set. In case of av_opt_set() if the field is not + * of a string type, then the given string is parsed. + * SI postfixes and some named scalars are supported. + * If the field is of a numeric type, it has to be a numeric or named + * scalar. Behavior with more than one scalar and +- infix operators + * is undefined. + * If the field is of a flags type, it has to be a sequence of numeric + * scalars or named flags separated by '+' or '-'. Prefixing a flag + * with '+' causes it to be set without affecting the other flags; + * similarly, '-' unsets a flag. + * @param search_flags flags passed to av_opt_find2. I.e. if AV_OPT_SEARCH_CHILDREN + * is passed here, then the option may be set on a child of obj. + * + * @return 0 if the value has been set, or an AVERROR code in case of + * error: + * AVERROR_OPTION_NOT_FOUND if no matching option exists + * AVERROR(ERANGE) if the value is out of range + * AVERROR(EINVAL) if the value is not valid + */ +int av_opt_set (void *obj, const char *name, const char *val, int search_flags); +int av_opt_set_int (void *obj, const char *name, int64_t val, int search_flags); +int av_opt_set_double(void *obj, const char *name, double val, int search_flags); +int av_opt_set_q (void *obj, const char *name, AVRational val, int search_flags); +/** + * @} + */ + +/** + * @defgroup opt_get_funcs Option getting functions + * @{ + * Those functions get a value of the option with the given name from an object. + * + * @param[in] obj a struct whose first element is a pointer to an AVClass. + * @param[in] name name of the option to get. + * @param[in] search_flags flags passed to av_opt_find2. I.e. if AV_OPT_SEARCH_CHILDREN + * is passed here, then the option may be found in a child of obj. + * @param[out] out_val value of the option will be written here + * @return 0 on success, a negative error code otherwise + */ +/** + * @note the returned string will av_malloc()ed and must be av_free()ed by the caller + */ +int av_opt_get (void *obj, const char *name, int search_flags, uint8_t **out_val); +int av_opt_get_int (void *obj, const char *name, int search_flags, int64_t *out_val); +int av_opt_get_double(void *obj, const char *name, int search_flags, double *out_val); +int av_opt_get_q (void *obj, const char *name, int search_flags, AVRational *out_val); +/** + * @} + */ +/** + * Gets a pointer to the requested field in a struct. + * This function allows accessing a struct even when its fields are moved or + * renamed since the application making the access has been compiled, + * + * @returns a pointer to the field, it can be cast to the correct type and read + * or written to. + */ +void *av_opt_ptr(const AVClass *avclass, void *obj, const char *name); +/** + * @} + */ + +#endif /* AVUTIL_OPT_H */ diff --git a/Externals/ffmpeg/include/libavutil/parseutils.h b/Externals/ffmpeg/include/libavutil/parseutils.h new file mode 100644 index 0000000000..2a74a060f --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/parseutils.h @@ -0,0 +1,124 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_PARSEUTILS_H +#define AVUTIL_PARSEUTILS_H + +#include + +#include "rational.h" + +/** + * @file + * misc parsing utilities + */ + +/** + * Parse str and put in width_ptr and height_ptr the detected values. + * + * @param[in,out] width_ptr pointer to the variable which will contain the detected + * width value + * @param[in,out] height_ptr pointer to the variable which will contain the detected + * height value + * @param[in] str the string to parse: it has to be a string in the format + * width x height or a valid video size abbreviation. + * @return >= 0 on success, a negative error code otherwise + */ +int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str); + +/** + * Parse str and store the detected values in *rate. + * + * @param[in,out] rate pointer to the AVRational which will contain the detected + * frame rate + * @param[in] str the string to parse: it has to be a string in the format + * rate_num / rate_den, a float number or a valid video rate abbreviation + * @return >= 0 on success, a negative error code otherwise + */ +int av_parse_video_rate(AVRational *rate, const char *str); + +/** + * Put the RGBA values that correspond to color_string in rgba_color. + * + * @param color_string a string specifying a color. It can be the name of + * a color (case insensitive match) or a [0x|#]RRGGBB[AA] sequence, + * possibly followed by "@" and a string representing the alpha + * component. + * The alpha component may be a string composed by "0x" followed by an + * hexadecimal number or a decimal number between 0.0 and 1.0, which + * represents the opacity value (0x00/0.0 means completely transparent, + * 0xff/1.0 completely opaque). + * If the alpha component is not specified then 0xff is assumed. + * The string "random" will result in a random color. + * @param slen length of the initial part of color_string containing the + * color. It can be set to -1 if color_string is a null terminated string + * containing nothing else than the color. + * @return >= 0 in case of success, a negative value in case of + * failure (for example if color_string cannot be parsed). + */ +int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen, + void *log_ctx); + +/** + * Parse timestr and return in *time a corresponding number of + * microseconds. + * + * @param timeval puts here the number of microseconds corresponding + * to the string in timestr. If the string represents a duration, it + * is the number of microseconds contained in the time interval. If + * the string is a date, is the number of microseconds since 1st of + * January, 1970 up to the time of the parsed date. If timestr cannot + * be successfully parsed, set *time to INT64_MIN. + + * @param timestr a string representing a date or a duration. + * - If a date the syntax is: + * @code + * [{YYYY-MM-DD|YYYYMMDD}[T|t| ]]{{HH[:MM[:SS[.m...]]]}|{HH[MM[SS[.m...]]]}}[Z] + * now + * @endcode + * If the value is "now" it takes the current time. + * Time is local time unless Z is appended, in which case it is + * interpreted as UTC. + * If the year-month-day part is not specified it takes the current + * year-month-day. + * - If a duration the syntax is: + * @code + * [-]HH[:MM[:SS[.m...]]] + * [-]S+[.m...] + * @endcode + * @param duration flag which tells how to interpret timestr, if not + * zero timestr is interpreted as a duration, otherwise as a date + * @return 0 in case of success, a negative value corresponding to an + * AVERROR code otherwise + */ +int av_parse_time(int64_t *timeval, const char *timestr, int duration); + +/** + * Attempt to find a specific tag in a URL. + * + * syntax: '?tag1=val1&tag2=val2...'. Little URL decoding is done. + * Return 1 if found. + */ +int av_find_info_tag(char *arg, int arg_size, const char *tag1, const char *info); + +/** + * Convert the decomposed UTC time in tm to a time_t value. + */ +time_t av_timegm(struct tm *tm); + +#endif /* AVUTIL_PARSEUTILS_H */ diff --git a/Externals/ffmpeg/include/libavutil/pixdesc.h b/Externals/ffmpeg/include/libavutil/pixdesc.h new file mode 100644 index 0000000000..217524678 --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/pixdesc.h @@ -0,0 +1,177 @@ +/* + * pixel format descriptor + * Copyright (c) 2009 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_PIXDESC_H +#define AVUTIL_PIXDESC_H + +#include +#include "pixfmt.h" + +typedef struct AVComponentDescriptor{ + uint16_t plane :2; ///< which of the 4 planes contains the component + + /** + * Number of elements between 2 horizontally consecutive pixels minus 1. + * Elements are bits for bitstream formats, bytes otherwise. + */ + uint16_t step_minus1 :3; + + /** + * Number of elements before the component of the first pixel plus 1. + * Elements are bits for bitstream formats, bytes otherwise. + */ + uint16_t offset_plus1 :3; + uint16_t shift :3; ///< number of least significant bits that must be shifted away to get the value + uint16_t depth_minus1 :4; ///< number of bits in the component minus 1 +}AVComponentDescriptor; + +/** + * Descriptor that unambiguously describes how the bits of a pixel are + * stored in the up to 4 data planes of an image. It also stores the + * subsampling factors and number of components. + * + * @note This is separate of the colorspace (RGB, YCbCr, YPbPr, JPEG-style YUV + * and all the YUV variants) AVPixFmtDescriptor just stores how values + * are stored not what these values represent. + */ +typedef struct AVPixFmtDescriptor{ + const char *name; + uint8_t nb_components; ///< The number of components each pixel has, (1-4) + + /** + * Amount to shift the luma width right to find the chroma width. + * For YV12 this is 1 for example. + * chroma_width = -((-luma_width) >> log2_chroma_w) + * The note above is needed to ensure rounding up. + * This value only refers to the chroma components. + */ + uint8_t log2_chroma_w; ///< chroma_width = -((-luma_width )>>log2_chroma_w) + + /** + * Amount to shift the luma height right to find the chroma height. + * For YV12 this is 1 for example. + * chroma_height= -((-luma_height) >> log2_chroma_h) + * The note above is needed to ensure rounding up. + * This value only refers to the chroma components. + */ + uint8_t log2_chroma_h; + uint8_t flags; + + /** + * Parameters that describe how pixels are packed. If the format + * has chroma components, they must be stored in comp[1] and + * comp[2]. + */ + AVComponentDescriptor comp[4]; +}AVPixFmtDescriptor; + +#define PIX_FMT_BE 1 ///< Pixel format is big-endian. +#define PIX_FMT_PAL 2 ///< Pixel format has a palette in data[1], values are indexes in this palette. +#define PIX_FMT_BITSTREAM 4 ///< All values of a component are bit-wise packed end to end. +#define PIX_FMT_HWACCEL 8 ///< Pixel format is an HW accelerated format. +#define PIX_FMT_PLANAR 16 ///< At least one pixel component is not in the first data plane +#define PIX_FMT_RGB 32 ///< The pixel format contains RGB-like data (as opposed to YUV/grayscale) + +/** + * The array of all the pixel format descriptors. + */ +extern const AVPixFmtDescriptor av_pix_fmt_descriptors[]; + +/** + * Read a line from an image, and write the values of the + * pixel format component c to dst. + * + * @param data the array containing the pointers to the planes of the image + * @param linesize the array containing the linesizes of the image + * @param desc the pixel format descriptor for the image + * @param x the horizontal coordinate of the first pixel to read + * @param y the vertical coordinate of the first pixel to read + * @param w the width of the line to read, that is the number of + * values to write to dst + * @param read_pal_component if not zero and the format is a paletted + * format writes the values corresponding to the palette + * component c in data[1] to dst, rather than the palette indexes in + * data[0]. The behavior is undefined if the format is not paletted. + */ +void av_read_image_line(uint16_t *dst, const uint8_t *data[4], const int linesize[4], + const AVPixFmtDescriptor *desc, int x, int y, int c, int w, int read_pal_component); + +/** + * Write the values from src to the pixel format component c of an + * image line. + * + * @param src array containing the values to write + * @param data the array containing the pointers to the planes of the + * image to write into. It is supposed to be zeroed. + * @param linesize the array containing the linesizes of the image + * @param desc the pixel format descriptor for the image + * @param x the horizontal coordinate of the first pixel to write + * @param y the vertical coordinate of the first pixel to write + * @param w the width of the line to write, that is the number of + * values to write to the image line + */ +void av_write_image_line(const uint16_t *src, uint8_t *data[4], const int linesize[4], + const AVPixFmtDescriptor *desc, int x, int y, int c, int w); + +/** + * Return the pixel format corresponding to name. + * + * If there is no pixel format with name name, then looks for a + * pixel format with the name corresponding to the native endian + * format of name. + * For example in a little-endian system, first looks for "gray16", + * then for "gray16le". + * + * Finally if no pixel format has been found, returns PIX_FMT_NONE. + */ +enum PixelFormat av_get_pix_fmt(const char *name); + +/** + * Return the short name for a pixel format, NULL in case pix_fmt is + * unknown. + * + * @see av_get_pix_fmt(), av_get_pix_fmt_string() + */ +const char *av_get_pix_fmt_name(enum PixelFormat pix_fmt); + +/** + * Print in buf the string corresponding to the pixel format with + * number pix_fmt, or an header if pix_fmt is negative. + * + * @param buf the buffer where to write the string + * @param buf_size the size of buf + * @param pix_fmt the number of the pixel format to print the + * corresponding info string, or a negative value to print the + * corresponding header. + */ +char *av_get_pix_fmt_string (char *buf, int buf_size, enum PixelFormat pix_fmt); + +/** + * Return the number of bits per pixel used by the pixel format + * described by pixdesc. + * + * The returned number of bits refers to the number of bits actually + * used for storing the pixel information, that is padding bits are + * not counted. + */ +int av_get_bits_per_pixel(const AVPixFmtDescriptor *pixdesc); + +#endif /* AVUTIL_PIXDESC_H */ diff --git a/Externals/ffmpeg/include/libavutil/pixfmt.h b/Externals/ffmpeg/include/libavutil/pixfmt.h new file mode 100644 index 0000000000..f0d9c019a --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/pixfmt.h @@ -0,0 +1,227 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_PIXFMT_H +#define AVUTIL_PIXFMT_H + +/** + * @file + * pixel format definitions + * + */ + +#include "libavutil/avconfig.h" + +/** + * Pixel format. + * + * @note + * PIX_FMT_RGB32 is handled in an endian-specific manner. An RGBA + * color is put together as: + * (A << 24) | (R << 16) | (G << 8) | B + * This is stored as BGRA on little-endian CPU architectures and ARGB on + * big-endian CPUs. + * + * @par + * When the pixel format is palettized RGB (PIX_FMT_PAL8), the palettized + * image data is stored in AVFrame.data[0]. The palette is transported in + * AVFrame.data[1], is 1024 bytes long (256 4-byte entries) and is + * formatted the same as in PIX_FMT_RGB32 described above (i.e., it is + * also endian-specific). Note also that the individual RGB palette + * components stored in AVFrame.data[1] should be in the range 0..255. + * This is important as many custom PAL8 video codecs that were designed + * to run on the IBM VGA graphics adapter use 6-bit palette components. + * + * @par + * For all the 8bit per pixel formats, an RGB32 palette is in data[1] like + * for pal8. This palette is filled in automatically by the function + * allocating the picture. + * + * @note + * make sure that all newly added big endian formats have pix_fmt&1==1 + * and that all newly added little endian formats have pix_fmt&1==0 + * this allows simpler detection of big vs little endian. + */ +enum PixelFormat { + PIX_FMT_NONE= -1, + PIX_FMT_YUV420P, ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples) + PIX_FMT_YUYV422, ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr + PIX_FMT_RGB24, ///< packed RGB 8:8:8, 24bpp, RGBRGB... + PIX_FMT_BGR24, ///< packed RGB 8:8:8, 24bpp, BGRBGR... + PIX_FMT_YUV422P, ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples) + PIX_FMT_YUV444P, ///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples) + PIX_FMT_YUV410P, ///< planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples) + PIX_FMT_YUV411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) + PIX_FMT_GRAY8, ///< Y , 8bpp + PIX_FMT_MONOWHITE, ///< Y , 1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb + PIX_FMT_MONOBLACK, ///< Y , 1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb + PIX_FMT_PAL8, ///< 8 bit with PIX_FMT_RGB32 palette + PIX_FMT_YUVJ420P, ///< planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV420P and setting color_range + PIX_FMT_YUVJ422P, ///< planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV422P and setting color_range + PIX_FMT_YUVJ444P, ///< planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV444P and setting color_range + PIX_FMT_XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing + PIX_FMT_XVMC_MPEG2_IDCT, + PIX_FMT_UYVY422, ///< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1 + PIX_FMT_UYYVYY411, ///< packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3 + PIX_FMT_BGR8, ///< packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb) + PIX_FMT_BGR4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1B 2G 1R(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits + PIX_FMT_BGR4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1B 2G 1R(lsb) + PIX_FMT_RGB8, ///< packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb) + PIX_FMT_RGB4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1R 2G 1B(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits + PIX_FMT_RGB4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1R 2G 1B(lsb) + PIX_FMT_NV12, ///< planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V) + PIX_FMT_NV21, ///< as above, but U and V bytes are swapped + + PIX_FMT_ARGB, ///< packed ARGB 8:8:8:8, 32bpp, ARGBARGB... + PIX_FMT_RGBA, ///< packed RGBA 8:8:8:8, 32bpp, RGBARGBA... + PIX_FMT_ABGR, ///< packed ABGR 8:8:8:8, 32bpp, ABGRABGR... + PIX_FMT_BGRA, ///< packed BGRA 8:8:8:8, 32bpp, BGRABGRA... + + PIX_FMT_GRAY16BE, ///< Y , 16bpp, big-endian + PIX_FMT_GRAY16LE, ///< Y , 16bpp, little-endian + PIX_FMT_YUV440P, ///< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples) + PIX_FMT_YUVJ440P, ///< planar YUV 4:4:0 full scale (JPEG), deprecated in favor of PIX_FMT_YUV440P and setting color_range + PIX_FMT_YUVA420P, ///< planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples) + PIX_FMT_VDPAU_H264,///< H.264 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers + PIX_FMT_VDPAU_MPEG1,///< MPEG-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers + PIX_FMT_VDPAU_MPEG2,///< MPEG-2 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers + PIX_FMT_VDPAU_WMV3,///< WMV3 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers + PIX_FMT_VDPAU_VC1, ///< VC-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers + PIX_FMT_RGB48BE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as big-endian + PIX_FMT_RGB48LE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as little-endian + + PIX_FMT_RGB565BE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian + PIX_FMT_RGB565LE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian + PIX_FMT_RGB555BE, ///< packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), big-endian, most significant bit to 0 + PIX_FMT_RGB555LE, ///< packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), little-endian, most significant bit to 0 + + PIX_FMT_BGR565BE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), big-endian + PIX_FMT_BGR565LE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), little-endian + PIX_FMT_BGR555BE, ///< packed BGR 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), big-endian, most significant bit to 1 + PIX_FMT_BGR555LE, ///< packed BGR 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), little-endian, most significant bit to 1 + + PIX_FMT_VAAPI_MOCO, ///< HW acceleration through VA API at motion compensation entry-point, Picture.data[3] contains a vaapi_render_state struct which contains macroblocks as well as various fields extracted from headers + PIX_FMT_VAAPI_IDCT, ///< HW acceleration through VA API at IDCT entry-point, Picture.data[3] contains a vaapi_render_state struct which contains fields extracted from headers + PIX_FMT_VAAPI_VLD, ///< HW decoding through VA API, Picture.data[3] contains a vaapi_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers + + PIX_FMT_YUV420P16LE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + PIX_FMT_YUV420P16BE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + PIX_FMT_YUV422P16LE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + PIX_FMT_YUV422P16BE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + PIX_FMT_YUV444P16LE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + PIX_FMT_YUV444P16BE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + PIX_FMT_VDPAU_MPEG4, ///< MPEG4 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers + PIX_FMT_DXVA2_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer + + PIX_FMT_RGB444LE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), little-endian, most significant bits to 0 + PIX_FMT_RGB444BE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), big-endian, most significant bits to 0 + PIX_FMT_BGR444LE, ///< packed BGR 4:4:4, 16bpp, (msb)4A 4B 4G 4R(lsb), little-endian, most significant bits to 1 + PIX_FMT_BGR444BE, ///< packed BGR 4:4:4, 16bpp, (msb)4A 4B 4G 4R(lsb), big-endian, most significant bits to 1 + PIX_FMT_GRAY8A, ///< 8bit gray, 8bit alpha + PIX_FMT_BGR48BE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as big-endian + PIX_FMT_BGR48LE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as little-endian + + //the following 10 formats have the disadvantage of needing 1 format for each bit depth, thus + //If you want to support multiple bit depths, then using PIX_FMT_YUV420P16* with the bpp stored seperately + //is better + PIX_FMT_YUV420P9BE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + PIX_FMT_YUV420P9LE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + PIX_FMT_YUV420P10BE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + PIX_FMT_YUV420P10LE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + PIX_FMT_YUV422P10BE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + PIX_FMT_YUV422P10LE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + PIX_FMT_YUV444P9BE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + PIX_FMT_YUV444P9LE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + PIX_FMT_YUV444P10BE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + PIX_FMT_YUV444P10LE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + PIX_FMT_YUV422P9BE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + PIX_FMT_YUV422P9LE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + PIX_FMT_VDA_VLD, ///< hardware decoding through VDA + +#ifdef AV_PIX_FMT_ABI_GIT_MASTER + PIX_FMT_RGBA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + PIX_FMT_RGBA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + PIX_FMT_BGRA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + PIX_FMT_BGRA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian +#endif + PIX_FMT_GBRP, ///< planar GBR 4:4:4 24bpp + PIX_FMT_GBRP9BE, ///< planar GBR 4:4:4 27bpp, big endian + PIX_FMT_GBRP9LE, ///< planar GBR 4:4:4 27bpp, little endian + PIX_FMT_GBRP10BE, ///< planar GBR 4:4:4 30bpp, big endian + PIX_FMT_GBRP10LE, ///< planar GBR 4:4:4 30bpp, little endian + PIX_FMT_GBRP16BE, ///< planar GBR 4:4:4 48bpp, big endian + PIX_FMT_GBRP16LE, ///< planar GBR 4:4:4 48bpp, little endian + +#ifndef AV_PIX_FMT_ABI_GIT_MASTER + PIX_FMT_RGBA64BE=0x123, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + PIX_FMT_RGBA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + PIX_FMT_BGRA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + PIX_FMT_BGRA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian +#endif + PIX_FMT_0RGB=0x123+4, ///< packed RGB 8:8:8, 32bpp, 0RGB0RGB... + PIX_FMT_RGB0, ///< packed RGB 8:8:8, 32bpp, RGB0RGB0... + PIX_FMT_0BGR, ///< packed BGR 8:8:8, 32bpp, 0BGR0BGR... + PIX_FMT_BGR0, ///< packed BGR 8:8:8, 32bpp, BGR0BGR0... + PIX_FMT_NB, ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions +}; + +#define PIX_FMT_Y400A PIX_FMT_GRAY8A +#define PIX_FMT_GBR24P PIX_FMT_GBRP + +#if AV_HAVE_BIGENDIAN +# define PIX_FMT_NE(be, le) PIX_FMT_##be +#else +# define PIX_FMT_NE(be, le) PIX_FMT_##le +#endif + +#define PIX_FMT_RGB32 PIX_FMT_NE(ARGB, BGRA) +#define PIX_FMT_RGB32_1 PIX_FMT_NE(RGBA, ABGR) +#define PIX_FMT_BGR32 PIX_FMT_NE(ABGR, RGBA) +#define PIX_FMT_BGR32_1 PIX_FMT_NE(BGRA, ARGB) +#define PIX_FMT_0RGB32 PIX_FMT_NE(0RGB, BGR0) +#define PIX_FMT_0BGR32 PIX_FMT_NE(0BGR, RGB0) + +#define PIX_FMT_GRAY16 PIX_FMT_NE(GRAY16BE, GRAY16LE) +#define PIX_FMT_RGB48 PIX_FMT_NE(RGB48BE, RGB48LE) +#define PIX_FMT_RGB565 PIX_FMT_NE(RGB565BE, RGB565LE) +#define PIX_FMT_RGB555 PIX_FMT_NE(RGB555BE, RGB555LE) +#define PIX_FMT_RGB444 PIX_FMT_NE(RGB444BE, RGB444LE) +#define PIX_FMT_BGR48 PIX_FMT_NE(BGR48BE, BGR48LE) +#define PIX_FMT_BGR565 PIX_FMT_NE(BGR565BE, BGR565LE) +#define PIX_FMT_BGR555 PIX_FMT_NE(BGR555BE, BGR555LE) +#define PIX_FMT_BGR444 PIX_FMT_NE(BGR444BE, BGR444LE) + +#define PIX_FMT_YUV420P9 PIX_FMT_NE(YUV420P9BE , YUV420P9LE) +#define PIX_FMT_YUV422P9 PIX_FMT_NE(YUV422P9BE , YUV422P9LE) +#define PIX_FMT_YUV444P9 PIX_FMT_NE(YUV444P9BE , YUV444P9LE) +#define PIX_FMT_YUV420P10 PIX_FMT_NE(YUV420P10BE, YUV420P10LE) +#define PIX_FMT_YUV422P10 PIX_FMT_NE(YUV422P10BE, YUV422P10LE) +#define PIX_FMT_YUV444P10 PIX_FMT_NE(YUV444P10BE, YUV444P10LE) +#define PIX_FMT_YUV420P16 PIX_FMT_NE(YUV420P16BE, YUV420P16LE) +#define PIX_FMT_YUV422P16 PIX_FMT_NE(YUV422P16BE, YUV422P16LE) +#define PIX_FMT_YUV444P16 PIX_FMT_NE(YUV444P16BE, YUV444P16LE) + +#define PIX_FMT_RGBA64 PIX_FMT_NE(RGBA64BE, RGBA64LE) +#define PIX_FMT_BGRA64 PIX_FMT_NE(BGRA64BE, BGRA64LE) +#define PIX_FMT_GBRP9 PIX_FMT_NE(GBRP9BE , GBRP9LE) +#define PIX_FMT_GBRP10 PIX_FMT_NE(GBRP10BE, GBRP10LE) +#define PIX_FMT_GBRP16 PIX_FMT_NE(GBRP16BE, GBRP16LE) + +#endif /* AVUTIL_PIXFMT_H */ diff --git a/Externals/ffmpeg/include/libavutil/random_seed.h b/Externals/ffmpeg/include/libavutil/random_seed.h new file mode 100644 index 0000000000..0462a048e --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/random_seed.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2009 Baptiste Coudurier + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_RANDOM_SEED_H +#define AVUTIL_RANDOM_SEED_H + +#include +/** + * @addtogroup lavu_crypto + * @{ + */ + +/** + * Get a seed to use in conjunction with random functions. + * This function tries to provide a good seed at a best effort bases. + * Its possible to call this function multiple times if more bits are needed. + * It can be quite slow, which is why it should only be used as seed for a faster + * PRNG. The quality of the seed depends on the platform. + */ +uint32_t av_get_random_seed(void); + +/** + * @} + */ + +#endif /* AVUTIL_RANDOM_SEED_H */ diff --git a/Externals/ffmpeg/include/libavutil/rational.h b/Externals/ffmpeg/include/libavutil/rational.h new file mode 100644 index 0000000000..8c2bdb552 --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/rational.h @@ -0,0 +1,144 @@ +/* + * rational numbers + * Copyright (c) 2003 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * rational numbers + * @author Michael Niedermayer + */ + +#ifndef AVUTIL_RATIONAL_H +#define AVUTIL_RATIONAL_H + +#include +#include +#include "attributes.h" + +/** + * @addtogroup lavu_math + * @{ + */ + +/** + * rational number numerator/denominator + */ +typedef struct AVRational{ + int num; ///< numerator + int den; ///< denominator +} AVRational; + +/** + * Compare two rationals. + * @param a first rational + * @param b second rational + * @return 0 if a==b, 1 if a>b, -1 if a>63)|1; + else if(b.den && a.den) return 0; + else if(a.num && b.num) return (a.num>>31) - (b.num>>31); + else return INT_MIN; +} + +/** + * Convert rational to double. + * @param a rational to convert + * @return (double) a + */ +static inline double av_q2d(AVRational a){ + return a.num / (double) a.den; +} + +/** + * Reduce a fraction. + * This is useful for framerate calculations. + * @param dst_num destination numerator + * @param dst_den destination denominator + * @param num source numerator + * @param den source denominator + * @param max the maximum allowed for dst_num & dst_den + * @return 1 if exact, 0 otherwise + */ +int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max); + +/** + * Multiply two rationals. + * @param b first rational + * @param c second rational + * @return b*c + */ +AVRational av_mul_q(AVRational b, AVRational c) av_const; + +/** + * Divide one rational by another. + * @param b first rational + * @param c second rational + * @return b/c + */ +AVRational av_div_q(AVRational b, AVRational c) av_const; + +/** + * Add two rationals. + * @param b first rational + * @param c second rational + * @return b+c + */ +AVRational av_add_q(AVRational b, AVRational c) av_const; + +/** + * Subtract one rational from another. + * @param b first rational + * @param c second rational + * @return b-c + */ +AVRational av_sub_q(AVRational b, AVRational c) av_const; + +/** + * Convert a double precision floating point number to a rational. + * inf is expressed as {1,0} or {-1,0} depending on the sign. + * + * @param d double to convert + * @param max the maximum allowed numerator and denominator + * @return (AVRational) d + */ +AVRational av_d2q(double d, int max) av_const; + +/** + * @return 1 if q1 is nearer to q than q2, -1 if q2 is nearer + * than q1, 0 if they have the same distance. + */ +int av_nearer_q(AVRational q, AVRational q1, AVRational q2); + +/** + * Find the nearest value in q_list to q. + * @param q_list an array of rationals terminated by {0, 0} + * @return the index of the nearest value found in the array + */ +int av_find_nearest_q_idx(AVRational q, const AVRational* q_list); + +/** + * @} + */ + +#endif /* AVUTIL_RATIONAL_H */ diff --git a/Externals/ffmpeg/include/libavutil/samplefmt.h b/Externals/ffmpeg/include/libavutil/samplefmt.h new file mode 100644 index 0000000000..855cffd83 --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/samplefmt.h @@ -0,0 +1,156 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_SAMPLEFMT_H +#define AVUTIL_SAMPLEFMT_H + +#include "avutil.h" + +/** + * all in native-endian format + */ +enum AVSampleFormat { + AV_SAMPLE_FMT_NONE = -1, + AV_SAMPLE_FMT_U8, ///< unsigned 8 bits + AV_SAMPLE_FMT_S16, ///< signed 16 bits + AV_SAMPLE_FMT_S32, ///< signed 32 bits + AV_SAMPLE_FMT_FLT, ///< float + AV_SAMPLE_FMT_DBL, ///< double + + AV_SAMPLE_FMT_U8P, ///< unsigned 8 bits, planar + AV_SAMPLE_FMT_S16P, ///< signed 16 bits, planar + AV_SAMPLE_FMT_S32P, ///< signed 32 bits, planar + AV_SAMPLE_FMT_FLTP, ///< float, planar + AV_SAMPLE_FMT_DBLP, ///< double, planar + + AV_SAMPLE_FMT_NB ///< Number of sample formats. DO NOT USE if linking dynamically +}; + +/** + * Return the name of sample_fmt, or NULL if sample_fmt is not + * recognized. + */ +const char *av_get_sample_fmt_name(enum AVSampleFormat sample_fmt); + +/** + * Return a sample format corresponding to name, or AV_SAMPLE_FMT_NONE + * on error. + */ +enum AVSampleFormat av_get_sample_fmt(const char *name); + +/** + * Return the planar<->packed alternative form of the given sample format, or + * AV_SAMPLE_FMT_NONE on error. If the passed sample_fmt is already in the + * requested planar/packed format, the format returned is the same as the + * input. + */ +enum AVSampleFormat av_get_alt_sample_fmt(enum AVSampleFormat sample_fmt, int planar); + +/** + * Generate a string corresponding to the sample format with + * sample_fmt, or a header if sample_fmt is negative. + * + * @param buf the buffer where to write the string + * @param buf_size the size of buf + * @param sample_fmt the number of the sample format to print the + * corresponding info string, or a negative value to print the + * corresponding header. + * @return the pointer to the filled buffer or NULL if sample_fmt is + * unknown or in case of other errors + */ +char *av_get_sample_fmt_string(char *buf, int buf_size, enum AVSampleFormat sample_fmt); + +#if FF_API_GET_BITS_PER_SAMPLE_FMT +/** + * @deprecated Use av_get_bytes_per_sample() instead. + */ +attribute_deprecated +int av_get_bits_per_sample_fmt(enum AVSampleFormat sample_fmt); +#endif + +/** + * Return number of bytes per sample. + * + * @param sample_fmt the sample format + * @return number of bytes per sample or zero if unknown for the given + * sample format + */ +int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt); + +/** + * Check if the sample format is planar. + * + * @param sample_fmt the sample format to inspect + * @return 1 if the sample format is planar, 0 if it is interleaved + */ +int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt); + +/** + * Get the required buffer size for the given audio parameters. + * + * @param[out] linesize calculated linesize, may be NULL + * @param nb_channels the number of channels + * @param nb_samples the number of samples in a single channel + * @param sample_fmt the sample format + * @return required buffer size, or negative error code on failure + */ +int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples, + enum AVSampleFormat sample_fmt, int align); + +/** + * Fill channel data pointers and linesize for samples with sample + * format sample_fmt. + * + * The pointers array is filled with the pointers to the samples data: + * for planar, set the start point of each channel's data within the buffer, + * for packed, set the start point of the entire buffer only. + * + * The linesize array is filled with the aligned size of each channel's data + * buffer for planar layout, or the aligned size of the buffer for all channels + * for packed layout. + * + * @param[out] audio_data array to be filled with the pointer for each channel + * @param[out] linesize calculated linesize + * @param buf the pointer to a buffer containing the samples + * @param nb_channels the number of channels + * @param nb_samples the number of samples in a single channel + * @param sample_fmt the sample format + * @param align buffer size alignment (1 = no alignment required) + * @return 0 on success or a negative error code on failure + */ +int av_samples_fill_arrays(uint8_t **audio_data, int *linesize, uint8_t *buf, + int nb_channels, int nb_samples, + enum AVSampleFormat sample_fmt, int align); + +/** + * Allocate a samples buffer for nb_samples samples, and fill data pointers and + * linesize accordingly. + * The allocated samples buffer can be freed by using av_freep(&audio_data[0]) + * + * @param[out] audio_data array to be filled with the pointer for each channel + * @param[out] linesize aligned size for audio buffer(s) + * @param nb_channels number of audio channels + * @param nb_samples number of samples per channel + * @param align buffer size alignment (1 = no alignment required) + * @return 0 on success or a negative error code on failure + * @see av_samples_fill_arrays() + */ +int av_samples_alloc(uint8_t **audio_data, int *linesize, int nb_channels, + int nb_samples, enum AVSampleFormat sample_fmt, int align); + +#endif /* AVUTIL_SAMPLEFMT_H */ diff --git a/Externals/ffmpeg/include/libavutil/sha.h b/Externals/ffmpeg/include/libavutil/sha.h new file mode 100644 index 0000000000..d891cae87 --- /dev/null +++ b/Externals/ffmpeg/include/libavutil/sha.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2007 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_SHA_H +#define AVUTIL_SHA_H + +#include + +/** + * @defgroup lavu_sha SHA + * @ingroup lavu_crypto + * @{ + */ + +extern const int av_sha_size; + +struct AVSHA; + +/** + * Initialize SHA-1 or SHA-2 hashing. + * + * @param context pointer to the function context (of size av_sha_size) + * @param bits number of bits in digest (SHA-1 - 160 bits, SHA-2 224 or 256 bits) + * @return zero if initialization succeeded, -1 otherwise + */ +int av_sha_init(struct AVSHA* context, int bits); + +/** + * Update hash value. + * + * @param context hash function context + * @param data input data to update hash with + * @param len input data length + */ +void av_sha_update(struct AVSHA* context, const uint8_t* data, unsigned int len); + +/** + * Finish hashing and output digest value. + * + * @param context hash function context + * @param digest buffer where output digest value is stored + */ +void av_sha_final(struct AVSHA* context, uint8_t *digest); + +/** + * @} + */ + +#endif /* AVUTIL_SHA_H */ diff --git a/Externals/ffmpeg/include/libpostproc/postprocess.h b/Externals/ffmpeg/include/libpostproc/postprocess.h new file mode 100644 index 0000000000..c2c5c7324 --- /dev/null +++ b/Externals/ffmpeg/include/libpostproc/postprocess.h @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2001-2003 Michael Niedermayer (michaelni@gmx.at) + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * FFmpeg 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef POSTPROC_POSTPROCESS_H +#define POSTPROC_POSTPROCESS_H + +/** + * @file + * @brief + * external postprocessing API + */ + +#include "libavutil/avutil.h" + +#ifndef LIBPOSTPROC_VERSION_MAJOR +#define LIBPOSTPROC_VERSION_MAJOR 52 +#define LIBPOSTPROC_VERSION_MINOR 0 +#define LIBPOSTPROC_VERSION_MICRO 100 +#endif + +#define LIBPOSTPROC_VERSION_INT AV_VERSION_INT(LIBPOSTPROC_VERSION_MAJOR, \ + LIBPOSTPROC_VERSION_MINOR, \ + LIBPOSTPROC_VERSION_MICRO) +#define LIBPOSTPROC_VERSION AV_VERSION(LIBPOSTPROC_VERSION_MAJOR, \ + LIBPOSTPROC_VERSION_MINOR, \ + LIBPOSTPROC_VERSION_MICRO) +#define LIBPOSTPROC_BUILD LIBPOSTPROC_VERSION_INT + +#define LIBPOSTPROC_IDENT "postproc" AV_STRINGIFY(LIBPOSTPROC_VERSION) + +/** + * Return the LIBPOSTPROC_VERSION_INT constant. + */ +unsigned postproc_version(void); + +/** + * Return the libpostproc build-time configuration. + */ +const char *postproc_configuration(void); + +/** + * Return the libpostproc license. + */ +const char *postproc_license(void); + +#define PP_QUALITY_MAX 6 + +#define QP_STORE_T int8_t + +#include + +typedef void pp_context; +typedef void pp_mode; + +#if LIBPOSTPROC_VERSION_INT < (52<<16) +typedef pp_context pp_context_t; +typedef pp_mode pp_mode_t; +extern const char *const pp_help; ///< a simple help text +#else +extern const char pp_help[]; ///< a simple help text +#endif + +void pp_postprocess(const uint8_t * src[3], const int srcStride[3], + uint8_t * dst[3], const int dstStride[3], + int horizontalSize, int verticalSize, + const QP_STORE_T *QP_store, int QP_stride, + pp_mode *mode, pp_context *ppContext, int pict_type); + + +/** + * Return a pp_mode or NULL if an error occurred. + * + * @param name the string after "-pp" on the command line + * @param quality a number from 0 to PP_QUALITY_MAX + */ +pp_mode *pp_get_mode_by_name_and_quality(const char *name, int quality); +void pp_free_mode(pp_mode *mode); + +pp_context *pp_get_context(int width, int height, int flags); +void pp_free_context(pp_context *ppContext); + +#define PP_CPU_CAPS_MMX 0x80000000 +#define PP_CPU_CAPS_MMX2 0x20000000 +#define PP_CPU_CAPS_3DNOW 0x40000000 +#define PP_CPU_CAPS_ALTIVEC 0x10000000 + +#define PP_FORMAT 0x00000008 +#define PP_FORMAT_420 (0x00000011|PP_FORMAT) +#define PP_FORMAT_422 (0x00000001|PP_FORMAT) +#define PP_FORMAT_411 (0x00000002|PP_FORMAT) +#define PP_FORMAT_444 (0x00000000|PP_FORMAT) + +#define PP_PICT_TYPE_QP2 0x00000010 ///< MPEG2 style QScale + +#endif /* POSTPROC_POSTPROCESS_H */ diff --git a/Externals/ffmpeg/include/libswresample/swresample.h b/Externals/ffmpeg/include/libswresample/swresample.h new file mode 100644 index 0000000000..8dc4e1f34 --- /dev/null +++ b/Externals/ffmpeg/include/libswresample/swresample.h @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2011 Michael Niedermayer (michaelni@gmx.at) + * + * This file is part of libswresample + * + * libswresample 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. + * + * libswresample 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 libswresample; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * libswresample public header + */ + +#ifndef SWR_H +#define SWR_H + +#include +#include "libavutil/samplefmt.h" + +#define LIBSWRESAMPLE_VERSION_MAJOR 0 +#define LIBSWRESAMPLE_VERSION_MINOR 6 +#define LIBSWRESAMPLE_VERSION_MICRO 100 + +#define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \ + LIBSWRESAMPLE_VERSION_MINOR, \ + LIBSWRESAMPLE_VERSION_MICRO) + +#define SWR_CH_MAX 16 ///< Maximum number of channels + +#define SWR_FLAG_RESAMPLE 1 ///< Force resampling even if equal sample rate +//TODO use int resample ? +//long term TODO can we enable this dynamically? + + +struct SwrContext; + +/** + * Allocate SwrContext. + * + * If you use this function you will need to set the parameters (manually or + * with swr_alloc_set_opts()) before calling swr_init(). + * + * @see swr_alloc_set_opts(), swr_init(), swr_free() + * @return NULL on error, allocated context otherwise + */ +struct SwrContext *swr_alloc(void); + +/** + * Initialize context after user parameters have been set. + * + * @return AVERROR error code in case of failure. + */ +int swr_init(struct SwrContext *s); + +/** + * Allocate SwrContext if needed and set/reset common parameters. + * + * This function does not require s to be allocated with swr_alloc(). On the + * other hand, swr_alloc() can use swr_alloc_set_opts() to set the parameters + * on the allocated context. + * + * @param s Swr context, can be NULL + * @param out_ch_layout output channel layout (AV_CH_LAYOUT_*) + * @param out_sample_fmt output sample format (AV_SAMPLE_FMT_*). + * @param out_sample_rate output sample rate (frequency in Hz) + * @param in_ch_layout input channel layout (AV_CH_LAYOUT_*) + * @param in_sample_fmt input sample format (AV_SAMPLE_FMT_*). + * @param in_sample_rate input sample rate (frequency in Hz) + * @param log_offset logging level offset + * @param log_ctx parent logging context, can be NULL + * + * @see swr_init(), swr_free() + * @return NULL on error, allocated context otherwise + */ +struct SwrContext *swr_alloc_set_opts(struct SwrContext *s, + int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate, + int64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, + int log_offset, void *log_ctx); + +/** + * Free the given SwrContext and set the pointer to NULL. + */ +void swr_free(struct SwrContext **s); + +/** + * Convert audio. + * + * in and in_count can be set to 0 to flush the last few samples out at the + * end. + * + * @param s allocated Swr context, with parameters set + * @param out output buffers, only the first one need be set in case of packed audio + * @param out_count amount of space available for output in samples per channel + * @param in input buffers, only the first one need to be set in case of packed audio + * @param in_count number of input samples available in one channel + * + * @return number of samples output per channel + */ +int swr_convert(struct SwrContext *s, uint8_t *out[SWR_CH_MAX], int out_count, + const uint8_t *in [SWR_CH_MAX], int in_count); + +/** + * Activate resampling compensation. + */ +int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensation_distance); + +/** + * Set a customized input channel mapping. + * + * @param s allocated Swr context, not yet initialized + * @param channel_map customized input channel mapping (array of channel + * indexes, -1 for a muted channel) + * @return AVERROR error code in case of failure. + */ +int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map); + +/** + * Return the LIBSWRESAMPLE_VERSION_INT constant. + */ +unsigned swresample_version(void); + +/** + * Return the swr build-time configuration. + */ +const char *swresample_configuration(void); + +/** + * Return the swr license. + */ +const char *swresample_license(void); + +#endif diff --git a/Externals/ffmpeg/include/libswscale/swscale.h b/Externals/ffmpeg/include/libswscale/swscale.h new file mode 100644 index 0000000000..fa7100c41 --- /dev/null +++ b/Externals/ffmpeg/include/libswscale/swscale.h @@ -0,0 +1,363 @@ +/* + * Copyright (C) 2001-2011 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWSCALE_SWSCALE_H +#define SWSCALE_SWSCALE_H + +/** + * @file + * @brief + * external api for the swscale stuff + */ + +#include "libavutil/avutil.h" +#include "libavutil/log.h" +#include "libavutil/pixfmt.h" + +#define LIBSWSCALE_VERSION_MAJOR 2 +#define LIBSWSCALE_VERSION_MINOR 1 +#define LIBSWSCALE_VERSION_MICRO 100 + +#define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \ + LIBSWSCALE_VERSION_MINOR, \ + LIBSWSCALE_VERSION_MICRO) +#define LIBSWSCALE_VERSION AV_VERSION(LIBSWSCALE_VERSION_MAJOR, \ + LIBSWSCALE_VERSION_MINOR, \ + LIBSWSCALE_VERSION_MICRO) +#define LIBSWSCALE_BUILD LIBSWSCALE_VERSION_INT + +#define LIBSWSCALE_IDENT "SwS" AV_STRINGIFY(LIBSWSCALE_VERSION) + +/** + * Those FF_API_* defines are not part of public API. + * They may change, break or disappear at any time. + */ +#ifndef FF_API_SWS_GETCONTEXT +#define FF_API_SWS_GETCONTEXT (LIBSWSCALE_VERSION_MAJOR < 3) +#endif +#ifndef FF_API_SWS_CPU_CAPS +#define FF_API_SWS_CPU_CAPS (LIBSWSCALE_VERSION_MAJOR < 3) +#endif +#ifndef FF_API_SWS_FORMAT_NAME +#define FF_API_SWS_FORMAT_NAME (LIBSWSCALE_VERSION_MAJOR < 3) +#endif + +/** + * Return the LIBSWSCALE_VERSION_INT constant. + */ +unsigned swscale_version(void); + +/** + * Return the libswscale build-time configuration. + */ +const char *swscale_configuration(void); + +/** + * Return the libswscale license. + */ +const char *swscale_license(void); + +/* values for the flags, the stuff on the command line is different */ +#define SWS_FAST_BILINEAR 1 +#define SWS_BILINEAR 2 +#define SWS_BICUBIC 4 +#define SWS_X 8 +#define SWS_POINT 0x10 +#define SWS_AREA 0x20 +#define SWS_BICUBLIN 0x40 +#define SWS_GAUSS 0x80 +#define SWS_SINC 0x100 +#define SWS_LANCZOS 0x200 +#define SWS_SPLINE 0x400 + +#define SWS_SRC_V_CHR_DROP_MASK 0x30000 +#define SWS_SRC_V_CHR_DROP_SHIFT 16 + +#define SWS_PARAM_DEFAULT 123456 + +#define SWS_PRINT_INFO 0x1000 + +//the following 3 flags are not completely implemented +//internal chrominace subsampling info +#define SWS_FULL_CHR_H_INT 0x2000 +//input subsampling info +#define SWS_FULL_CHR_H_INP 0x4000 +#define SWS_DIRECT_BGR 0x8000 +#define SWS_ACCURATE_RND 0x40000 +#define SWS_BITEXACT 0x80000 + +#if FF_API_SWS_CPU_CAPS +/** + * CPU caps are autodetected now, those flags + * are only provided for API compatibility. + */ +#define SWS_CPU_CAPS_MMX 0x80000000 +#define SWS_CPU_CAPS_MMX2 0x20000000 +#define SWS_CPU_CAPS_3DNOW 0x40000000 +#define SWS_CPU_CAPS_ALTIVEC 0x10000000 +#define SWS_CPU_CAPS_BFIN 0x01000000 +#define SWS_CPU_CAPS_SSE2 0x02000000 +#endif + +#define SWS_MAX_REDUCE_CUTOFF 0.002 + +#define SWS_CS_ITU709 1 +#define SWS_CS_FCC 4 +#define SWS_CS_ITU601 5 +#define SWS_CS_ITU624 5 +#define SWS_CS_SMPTE170M 5 +#define SWS_CS_SMPTE240M 7 +#define SWS_CS_DEFAULT 5 + +/** + * Return a pointer to yuv<->rgb coefficients for the given colorspace + * suitable for sws_setColorspaceDetails(). + * + * @param colorspace One of the SWS_CS_* macros. If invalid, + * SWS_CS_DEFAULT is used. + */ +const int *sws_getCoefficients(int colorspace); + +// when used for filters they must have an odd number of elements +// coeffs cannot be shared between vectors +typedef struct { + double *coeff; ///< pointer to the list of coefficients + int length; ///< number of coefficients in the vector +} SwsVector; + +// vectors can be shared +typedef struct { + SwsVector *lumH; + SwsVector *lumV; + SwsVector *chrH; + SwsVector *chrV; +} SwsFilter; + +struct SwsContext; + +/** + * Return a positive value if pix_fmt is a supported input format, 0 + * otherwise. + */ +int sws_isSupportedInput(enum PixelFormat pix_fmt); + +/** + * Return a positive value if pix_fmt is a supported output format, 0 + * otherwise. + */ +int sws_isSupportedOutput(enum PixelFormat pix_fmt); + +/** + * Allocate an empty SwsContext. This must be filled and passed to + * sws_init_context(). For filling see AVOptions, options.c and + * sws_setColorspaceDetails(). + */ +struct SwsContext *sws_alloc_context(void); + +/** + * Initialize the swscaler context sws_context. + * + * @return zero or positive value on success, a negative value on + * error + */ +int sws_init_context(struct SwsContext *sws_context, SwsFilter *srcFilter, SwsFilter *dstFilter); + +/** + * Free the swscaler context swsContext. + * If swsContext is NULL, then does nothing. + */ +void sws_freeContext(struct SwsContext *swsContext); + +#if FF_API_SWS_GETCONTEXT +/** + * Allocate and return an SwsContext. You need it to perform + * scaling/conversion operations using sws_scale(). + * + * @param srcW the width of the source image + * @param srcH the height of the source image + * @param srcFormat the source image format + * @param dstW the width of the destination image + * @param dstH the height of the destination image + * @param dstFormat the destination image format + * @param flags specify which algorithm and options to use for rescaling + * @return a pointer to an allocated context, or NULL in case of error + * @note this function is to be removed after a saner alternative is + * written + * @deprecated Use sws_getCachedContext() instead. + */ +struct SwsContext *sws_getContext(int srcW, int srcH, enum PixelFormat srcFormat, + int dstW, int dstH, enum PixelFormat dstFormat, + int flags, SwsFilter *srcFilter, + SwsFilter *dstFilter, const double *param); +#endif + +/** + * Scale the image slice in srcSlice and put the resulting scaled + * slice in the image in dst. A slice is a sequence of consecutive + * rows in an image. + * + * Slices have to be provided in sequential order, either in + * top-bottom or bottom-top order. If slices are provided in + * non-sequential order the behavior of the function is undefined. + * + * @param c the scaling context previously created with + * sws_getContext() + * @param srcSlice the array containing the pointers to the planes of + * the source slice + * @param srcStride the array containing the strides for each plane of + * the source image + * @param srcSliceY the position in the source image of the slice to + * process, that is the number (counted starting from + * zero) in the image of the first row of the slice + * @param srcSliceH the height of the source slice, that is the number + * of rows in the slice + * @param dst the array containing the pointers to the planes of + * the destination image + * @param dstStride the array containing the strides for each plane of + * the destination image + * @return the height of the output slice + */ +int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[], + const int srcStride[], int srcSliceY, int srcSliceH, + uint8_t *const dst[], const int dstStride[]); + +/** + * @param inv_table the yuv2rgb coefficients, normally ff_yuv2rgb_coeffs[x] + * @return -1 if not supported + */ +int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4], + int srcRange, const int table[4], int dstRange, + int brightness, int contrast, int saturation); + +/** + * @return -1 if not supported + */ +int sws_getColorspaceDetails(struct SwsContext *c, int **inv_table, + int *srcRange, int **table, int *dstRange, + int *brightness, int *contrast, int *saturation); + +/** + * Allocate and return an uninitialized vector with length coefficients. + */ +SwsVector *sws_allocVec(int length); + +/** + * Return a normalized Gaussian curve used to filter stuff + * quality = 3 is high quality, lower is lower quality. + */ +SwsVector *sws_getGaussianVec(double variance, double quality); + +/** + * Allocate and return a vector with length coefficients, all + * with the same value c. + */ +SwsVector *sws_getConstVec(double c, int length); + +/** + * Allocate and return a vector with just one coefficient, with + * value 1.0. + */ +SwsVector *sws_getIdentityVec(void); + +/** + * Scale all the coefficients of a by the scalar value. + */ +void sws_scaleVec(SwsVector *a, double scalar); + +/** + * Scale all the coefficients of a so that their sum equals height. + */ +void sws_normalizeVec(SwsVector *a, double height); +void sws_convVec(SwsVector *a, SwsVector *b); +void sws_addVec(SwsVector *a, SwsVector *b); +void sws_subVec(SwsVector *a, SwsVector *b); +void sws_shiftVec(SwsVector *a, int shift); + +/** + * Allocate and return a clone of the vector a, that is a vector + * with the same coefficients as a. + */ +SwsVector *sws_cloneVec(SwsVector *a); + +/** + * Print with av_log() a textual representation of the vector a + * if log_level <= av_log_level. + */ +void sws_printVec2(SwsVector *a, AVClass *log_ctx, int log_level); + +void sws_freeVec(SwsVector *a); + +SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur, + float lumaSharpen, float chromaSharpen, + float chromaHShift, float chromaVShift, + int verbose); +void sws_freeFilter(SwsFilter *filter); + +/** + * Check if context can be reused, otherwise reallocate a new one. + * + * If context is NULL, just calls sws_getContext() to get a new + * context. Otherwise, checks if the parameters are the ones already + * saved in context. If that is the case, returns the current + * context. Otherwise, frees context and gets a new context with + * the new parameters. + * + * Be warned that srcFilter and dstFilter are not checked, they + * are assumed to remain the same. + */ +struct SwsContext *sws_getCachedContext(struct SwsContext *context, + int srcW, int srcH, enum PixelFormat srcFormat, + int dstW, int dstH, enum PixelFormat dstFormat, + int flags, SwsFilter *srcFilter, + SwsFilter *dstFilter, const double *param); + +/** + * Convert an 8-bit paletted frame into a frame with a color depth of 32 bits. + * + * The output frame will have the same packed format as the palette. + * + * @param src source frame buffer + * @param dst destination frame buffer + * @param num_pixels number of pixels to convert + * @param palette array with [256] entries, which must match color arrangement (RGB or BGR) of src + */ +void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette); + +/** + * Convert an 8-bit paletted frame into a frame with a color depth of 24 bits. + * + * With the palette format "ABCD", the destination frame ends up with the format "ABC". + * + * @param src source frame buffer + * @param dst destination frame buffer + * @param num_pixels number of pixels to convert + * @param palette array with [256] entries, which must match color arrangement (RGB or BGR) of src + */ +void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette); + +/** + * Get the AVClass for swsContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *sws_get_class(void); + +#endif /* SWSCALE_SWSCALE_H */ diff --git a/Externals/ffmpeg/lib/avcodec.lib b/Externals/ffmpeg/lib/avcodec.lib new file mode 100644 index 0000000000..53ecaeb2d Binary files /dev/null and b/Externals/ffmpeg/lib/avcodec.lib differ diff --git a/Externals/ffmpeg/lib/avdevice.lib b/Externals/ffmpeg/lib/avdevice.lib new file mode 100644 index 0000000000..c78323821 Binary files /dev/null and b/Externals/ffmpeg/lib/avdevice.lib differ diff --git a/Externals/ffmpeg/lib/avfilter.lib b/Externals/ffmpeg/lib/avfilter.lib new file mode 100644 index 0000000000..9d6633e31 Binary files /dev/null and b/Externals/ffmpeg/lib/avfilter.lib differ diff --git a/Externals/ffmpeg/lib/avformat.lib b/Externals/ffmpeg/lib/avformat.lib new file mode 100644 index 0000000000..19b2292f4 Binary files /dev/null and b/Externals/ffmpeg/lib/avformat.lib differ diff --git a/Externals/ffmpeg/lib/avutil.lib b/Externals/ffmpeg/lib/avutil.lib new file mode 100644 index 0000000000..2e0854be8 Binary files /dev/null and b/Externals/ffmpeg/lib/avutil.lib differ diff --git a/Externals/ffmpeg/lib/postproc.lib b/Externals/ffmpeg/lib/postproc.lib new file mode 100644 index 0000000000..420101090 Binary files /dev/null and b/Externals/ffmpeg/lib/postproc.lib differ diff --git a/Externals/ffmpeg/lib/swresample.lib b/Externals/ffmpeg/lib/swresample.lib new file mode 100644 index 0000000000..e85e552cb Binary files /dev/null and b/Externals/ffmpeg/lib/swresample.lib differ diff --git a/Externals/ffmpeg/lib/swscale.lib b/Externals/ffmpeg/lib/swscale.lib new file mode 100644 index 0000000000..7b42d2c21 Binary files /dev/null and b/Externals/ffmpeg/lib/swscale.lib differ diff --git a/Externals/ffmpeg/licenses/bzip2.txt b/Externals/ffmpeg/licenses/bzip2.txt new file mode 100644 index 0000000000..cc614178c --- /dev/null +++ b/Externals/ffmpeg/licenses/bzip2.txt @@ -0,0 +1,42 @@ + +-------------------------------------------------------------------------- + +This program, "bzip2", the associated library "libbzip2", and all +documentation, are copyright (C) 1996-2010 Julian R Seward. All +rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + +3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + +4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Julian Seward, jseward@bzip.org +bzip2/libbzip2 version 1.0.6 of 6 September 2010 + +-------------------------------------------------------------------------- diff --git a/Externals/ffmpeg/licenses/ffmpeg.txt b/Externals/ffmpeg/licenses/ffmpeg.txt new file mode 100644 index 0000000000..94a9ed024 --- /dev/null +++ b/Externals/ffmpeg/licenses/ffmpeg.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/Externals/ffmpeg/licenses/freetype.txt b/Externals/ffmpeg/licenses/freetype.txt new file mode 100644 index 0000000000..b2fe7b6af --- /dev/null +++ b/Externals/ffmpeg/licenses/freetype.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Externals/ffmpeg/licenses/frei0r.txt b/Externals/ffmpeg/licenses/frei0r.txt new file mode 100644 index 0000000000..2ac66a73f --- /dev/null +++ b/Externals/ffmpeg/licenses/frei0r.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. \ No newline at end of file diff --git a/Externals/ffmpeg/licenses/gsm.txt b/Externals/ffmpeg/licenses/gsm.txt new file mode 100644 index 0000000000..bebe86fae --- /dev/null +++ b/Externals/ffmpeg/licenses/gsm.txt @@ -0,0 +1,35 @@ +Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann, +Technische Universitaet Berlin + +Any use of this software is permitted provided that this notice is not +removed and that neither the authors nor the Technische Universitaet Berlin +are deemed to have made any representations as to the suitability of this +software for any purpose nor are held responsible for any defects of +this software. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + +As a matter of courtesy, the authors request to be informed about uses +this software has found, about bugs in this software, and about any +improvements that may be of general interest. + +Berlin, 28.11.1994 +Jutta Degener +Carsten Bormann + + oOo + +Since the original terms of 15 years ago maybe do not make our +intentions completely clear given today's refined usage of the legal +terms, we append this additional permission: + + Permission to use, copy, modify, and distribute this software + for any purpose with or without fee is hereby granted, + provided that this notice is not removed and that neither + the authors nor the Technische Universitaet Berlin are + deemed to have made any representations as to the suitability + of this software for any purpose nor are held responsible + for any defects of this software. THERE IS ABSOLUTELY NO + WARRANTY FOR THIS SOFTWARE. + +Berkeley/Bremen, 05.04.2009 +Jutta Degener +Carsten Bormann \ No newline at end of file diff --git a/Externals/ffmpeg/licenses/lame.txt b/Externals/ffmpeg/licenses/lame.txt new file mode 100644 index 0000000000..ec33109fe --- /dev/null +++ b/Externals/ffmpeg/licenses/lame.txt @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! \ No newline at end of file diff --git a/Externals/ffmpeg/licenses/libvpx.txt b/Externals/ffmpeg/licenses/libvpx.txt new file mode 100644 index 0000000000..83e4e6f6d --- /dev/null +++ b/Externals/ffmpeg/licenses/libvpx.txt @@ -0,0 +1,29 @@ +Copyright (c) 2010, Google Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Google nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Externals/ffmpeg/licenses/opencore-amr.txt b/Externals/ffmpeg/licenses/opencore-amr.txt new file mode 100644 index 0000000000..3e4ce883b --- /dev/null +++ b/Externals/ffmpeg/licenses/opencore-amr.txt @@ -0,0 +1,191 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the +copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other +entities that control, are controlled by, or are under common control with +that entity. For the purposes of this definition, "control" means (i) the +power, direct or indirect, to cause the direction or management of such +entity, whether by contract or otherwise, or (ii) ownership of fifty +percent (50%) or more of the outstanding shares, or (iii) beneficial +ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, +including but not limited to software source code, documentation source, +and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation +or translation of a Source form, including but not limited to compiled +object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, +made available under the License, as indicated by a copyright notice that +is included in or attached to the work (an example is provided in the +Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, +that is based on (or derived from) the Work and for which the editorial +revisions, annotations, elaborations, or other modifications represent, as +a whole, an original work of authorship. For the purposes of this License, +Derivative Works shall not include works that remain separable from, or +merely link (or bind by name) to the interfaces of, the Work and Derivative +Works thereof. + +"Contribution" shall mean any work of authorship, including the original +version of the Work and any modifications or additions to that Work or +Derivative Works thereof, that is intentionally submitted to Licensor for +inclusion in the Work by the copyright owner or by an individual or Legal +Entity authorized to submit on behalf of the copyright owner. For the +purposes of this definition, "submitted" means any form of electronic, +verbal, or written communication sent to the Licensor or its +representatives, including but not limited to communication on electronic +mailing lists, source code control systems, and issue tracking systems that +are managed by, or on behalf of, the Licensor for the purpose of discussing +and improving the Work, but excluding communication that is conspicuously +marked or otherwise designated in writing by the copyright owner as "Not a +Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on +behalf of whom a Contribution has been received by Licensor and +subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this +License, each Contributor hereby grants to You a perpetual, worldwide, +non-exclusive, no-charge, royalty-free, irrevocable copyright license to +reproduce, prepare Derivative Works of, publicly display, publicly perform, +sublicense, and distribute the Work and such Derivative Works in Source or +Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this +License, each Contributor hereby grants to You a perpetual, worldwide, +non-exclusive, no-charge, royalty-free, irrevocable (except as stated in +this section) patent license to make, have made, use, offer to sell, sell, +import, and otherwise transfer the Work, where such license applies only to +those patent claims licensable by such Contributor that are necessarily +infringed by their Contribution(s) alone or by combination of their +Contribution(s) with the Work to which such Contribution(s) was submitted. +If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or +contributory patent infringement, then any patent licenses granted to You +under this License for that Work shall terminate as of the date such +litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or +Derivative Works thereof in any medium, with or without modifications, and +in Source or Object form, provided that You meet the following conditions: + + 1. You must give any other recipients of the Work or Derivative Works a +copy of this License; and + + 2. You must cause any modified files to carry prominent notices stating +that You changed the files; and + + 3. You must retain, in the Source form of any Derivative Works that You +distribute, all copyright, patent, trademark, and attribution notices from +the Source form of the Work, excluding those notices that do not pertain to +any part of the Derivative Works; and + + 4. If the Work includes a "NOTICE" text file as part of its +distribution, then any Derivative Works that You distribute must include a +readable copy of the attribution notices contained within such NOTICE file, +excluding those notices that do not pertain to any part of the Derivative +Works, in at least one of the following places: within a NOTICE text file +distributed as part of the Derivative Works; within the Source form or +documentation, if provided along with the Derivative Works; or, within a +display generated by the Derivative Works, if and wherever such third-party +notices normally appear. The contents of the NOTICE file are for +informational purposes only and do not modify the License. You may add Your +own attribution notices within Derivative Works that You distribute, +alongside or as an addendum to the NOTICE text from the Work, provided that +such additional attribution notices cannot be construed as modifying the +License. + +You may add Your own copyright statement to Your modifications and may +provide additional or different license terms and conditions for use, +reproduction, or distribution of Your modifications, or for any such +Derivative Works as a whole, provided Your use, reproduction, and +distribution of the Work otherwise complies with the conditions stated in +this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any +Contribution intentionally submitted for inclusion in the Work by You to +the Licensor shall be under the terms and conditions of this License, +without any additional terms or conditions. Notwithstanding the above, +nothing herein shall supersede or modify the terms of any separate license +agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade +names, trademarks, service marks, or product names of the Licensor, except +as required for reasonable and customary use in describing the origin of +the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to +in writing, Licensor provides the Work (and each Contributor provides its +Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied, including, without limitation, any +warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or +FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for +determining the appropriateness of using or redistributing the Work and +assume any risks associated with Your exercise of permissions under this +License. + +8. Limitation of Liability. In no event and under no legal theory, whether +in tort (including negligence), contract, or otherwise, unless required by +applicable law (such as deliberate and grossly negligent acts) or agreed to +in writing, shall any Contributor be liable to You for damages, including +any direct, indirect, special, incidental, or consequential damages of any +character arising as a result of this License or out of the use or +inability to use the Work (including but not limited to damages for loss of +goodwill, work stoppage, computer failure or malfunction, or any and all +other commercial damages or losses), even if such Contributor has been +advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the +Work or Derivative Works thereof, You may choose to offer, and charge a fee +for, acceptance of support, warranty, indemnity, or other liability +obligations and/or rights consistent with this License. However, in +accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if +You agree to indemnify, defend, and hold each Contributor harmless for any +liability incurred by, or claims asserted against, such Contributor by +reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "[]" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included +on the same "printed page" as the copyright notice for easier +identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); you may + not use this file except in compliance with the License. You may obtain a + copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable + law or agreed to in writing, software distributed under the License is + distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the specific language + governing permissions and limitations under the License. \ No newline at end of file diff --git a/Externals/ffmpeg/licenses/openjpeg.txt b/Externals/ffmpeg/licenses/openjpeg.txt new file mode 100644 index 0000000000..d1e5b6a53 --- /dev/null +++ b/Externals/ffmpeg/licenses/openjpeg.txt @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ \ No newline at end of file diff --git a/Externals/ffmpeg/licenses/rtmp.txt b/Externals/ffmpeg/licenses/rtmp.txt new file mode 100644 index 0000000000..bf28f6ff4 --- /dev/null +++ b/Externals/ffmpeg/licenses/rtmp.txt @@ -0,0 +1,503 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + diff --git a/Externals/ffmpeg/licenses/schroedinger.txt b/Externals/ffmpeg/licenses/schroedinger.txt new file mode 100644 index 0000000000..d6b542f99 --- /dev/null +++ b/Externals/ffmpeg/licenses/schroedinger.txt @@ -0,0 +1,278 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. \ No newline at end of file diff --git a/Externals/ffmpeg/licenses/sdl.txt b/Externals/ffmpeg/licenses/sdl.txt new file mode 100644 index 0000000000..2cba2ac74 --- /dev/null +++ b/Externals/ffmpeg/licenses/sdl.txt @@ -0,0 +1,458 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/Externals/ffmpeg/licenses/speex.txt b/Externals/ffmpeg/licenses/speex.txt new file mode 100644 index 0000000000..26284642b --- /dev/null +++ b/Externals/ffmpeg/licenses/speex.txt @@ -0,0 +1,35 @@ +Copyright 2002-2008 Xiph.org Foundation +Copyright 2002-2008 Jean-Marc Valin +Copyright 2005-2007 Analog Devices Inc. +Copyright 2005-2008 Commonwealth Scientific and Industrial Research + Organisation (CSIRO) +Copyright 1993, 2002, 2006 David Rowe +Copyright 2003 EpicGames +Copyright 1992-1994 Jutta Degener, Carsten Bormann + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +- Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +- Neither the name of the Xiph.org Foundation nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/Externals/ffmpeg/licenses/theora.txt b/Externals/ffmpeg/licenses/theora.txt new file mode 100644 index 0000000000..f71b538a5 --- /dev/null +++ b/Externals/ffmpeg/licenses/theora.txt @@ -0,0 +1,28 @@ +Copyright (C) 2002-2009 Xiph.org Foundation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +- Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +- Neither the name of the Xiph.org Foundation nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/Externals/ffmpeg/licenses/vo-aacenc.txt b/Externals/ffmpeg/licenses/vo-aacenc.txt new file mode 100644 index 0000000000..5ec4bf01e --- /dev/null +++ b/Externals/ffmpeg/licenses/vo-aacenc.txt @@ -0,0 +1,191 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the +copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other +entities that control, are controlled by, or are under common control with +that entity. For the purposes of this definition, "control" means (i) the +power, direct or indirect, to cause the direction or management of such +entity, whether by contract or otherwise, or (ii) ownership of fifty +percent (50%) or more of the outstanding shares, or (iii) beneficial +ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, +including but not limited to software source code, documentation source, +and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation +or translation of a Source form, including but not limited to compiled +object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, +made available under the License, as indicated by a copyright notice that +is included in or attached to the work (an example is provided in the +Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, +that is based on (or derived from) the Work and for which the editorial +revisions, annotations, elaborations, or other modifications represent, as +a whole, an original work of authorship. For the purposes of this License, +Derivative Works shall not include works that remain separable from, or +merely link (or bind by name) to the interfaces of, the Work and Derivative +Works thereof. + +"Contribution" shall mean any work of authorship, including the original +version of the Work and any modifications or additions to that Work or +Derivative Works thereof, that is intentionally submitted to Licensor for +inclusion in the Work by the copyright owner or by an individual or Legal +Entity authorized to submit on behalf of the copyright owner. For the +purposes of this definition, "submitted" means any form of electronic, +verbal, or written communication sent to the Licensor or its +representatives, including but not limited to communication on electronic +mailing lists, source code control systems, and issue tracking systems that +are managed by, or on behalf of, the Licensor for the purpose of discussing +and improving the Work, but excluding communication that is conspicuously +marked or otherwise designated in writing by the copyright owner as "Not a +Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on +behalf of whom a Contribution has been received by Licensor and +subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this +License, each Contributor hereby grants to You a perpetual, worldwide, +non-exclusive, no-charge, royalty-free, irrevocable copyright license to +reproduce, prepare Derivative Works of, publicly display, publicly perform, +sublicense, and distribute the Work and such Derivative Works in Source or +Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this +License, each Contributor hereby grants to You a perpetual, worldwide, +non-exclusive, no-charge, royalty-free, irrevocable (except as stated in +this section) patent license to make, have made, use, offer to sell, sell, +import, and otherwise transfer the Work, where such license applies only to +those patent claims licensable by such Contributor that are necessarily +infringed by their Contribution(s) alone or by combination of their +Contribution(s) with the Work to which such Contribution(s) was submitted. +If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or +contributory patent infringement, then any patent licenses granted to You +under this License for that Work shall terminate as of the date such +litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or +Derivative Works thereof in any medium, with or without modifications, and +in Source or Object form, provided that You meet the following conditions: + + 1. You must give any other recipients of the Work or Derivative Works a +copy of this License; and + + 2. You must cause any modified files to carry prominent notices stating +that You changed the files; and + + 3. You must retain, in the Source form of any Derivative Works that You +distribute, all copyright, patent, trademark, and attribution notices from +the Source form of the Work, excluding those notices that do not pertain to +any part of the Derivative Works; and + + 4. If the Work includes a "NOTICE" text file as part of its +distribution, then any Derivative Works that You distribute must include a +readable copy of the attribution notices contained within such NOTICE file, +excluding those notices that do not pertain to any part of the Derivative +Works, in at least one of the following places: within a NOTICE text file +distributed as part of the Derivative Works; within the Source form or +documentation, if provided along with the Derivative Works; or, within a +display generated by the Derivative Works, if and wherever such third-party +notices normally appear. The contents of the NOTICE file are for +informational purposes only and do not modify the License. You may add Your +own attribution notices within Derivative Works that You distribute, +alongside or as an addendum to the NOTICE text from the Work, provided that +such additional attribution notices cannot be construed as modifying the +License. + +You may add Your own copyright statement to Your modifications and may +provide additional or different license terms and conditions for use, +reproduction, or distribution of Your modifications, or for any such +Derivative Works as a whole, provided Your use, reproduction, and +distribution of the Work otherwise complies with the conditions stated in +this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any +Contribution intentionally submitted for inclusion in the Work by You to +the Licensor shall be under the terms and conditions of this License, +without any additional terms or conditions. Notwithstanding the above, +nothing herein shall supersede or modify the terms of any separate license +agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade +names, trademarks, service marks, or product names of the Licensor, except +as required for reasonable and customary use in describing the origin of +the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to +in writing, Licensor provides the Work (and each Contributor provides its +Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied, including, without limitation, any +warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or +FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for +determining the appropriateness of using or redistributing the Work and +assume any risks associated with Your exercise of permissions under this +License. + +8. Limitation of Liability. In no event and under no legal theory, whether +in tort (including negligence), contract, or otherwise, unless required by +applicable law (such as deliberate and grossly negligent acts) or agreed to +in writing, shall any Contributor be liable to You for damages, including +any direct, indirect, special, incidental, or consequential damages of any +character arising as a result of this License or out of the use or +inability to use the Work (including but not limited to damages for loss of +goodwill, work stoppage, computer failure or malfunction, or any and all +other commercial damages or losses), even if such Contributor has been +advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the +Work or Derivative Works thereof, You may choose to offer, and charge a fee +for, acceptance of support, warranty, indemnity, or other liability +obligations and/or rights consistent with this License. However, in +accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if +You agree to indemnify, defend, and hold each Contributor harmless for any +liability incurred by, or claims asserted against, such Contributor by +reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "[]" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included +on the same "printed page" as the copyright notice for easier +identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); you may + not use this file except in compliance with the License. You may obtain a + copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable + law or agreed to in writing, software distributed under the License is + distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the specific language + governing permissions and limitations under the License. diff --git a/Externals/ffmpeg/licenses/vo-amrwbenc.txt b/Externals/ffmpeg/licenses/vo-amrwbenc.txt new file mode 100644 index 0000000000..5ec4bf01e --- /dev/null +++ b/Externals/ffmpeg/licenses/vo-amrwbenc.txt @@ -0,0 +1,191 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the +copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other +entities that control, are controlled by, or are under common control with +that entity. For the purposes of this definition, "control" means (i) the +power, direct or indirect, to cause the direction or management of such +entity, whether by contract or otherwise, or (ii) ownership of fifty +percent (50%) or more of the outstanding shares, or (iii) beneficial +ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, +including but not limited to software source code, documentation source, +and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation +or translation of a Source form, including but not limited to compiled +object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, +made available under the License, as indicated by a copyright notice that +is included in or attached to the work (an example is provided in the +Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, +that is based on (or derived from) the Work and for which the editorial +revisions, annotations, elaborations, or other modifications represent, as +a whole, an original work of authorship. For the purposes of this License, +Derivative Works shall not include works that remain separable from, or +merely link (or bind by name) to the interfaces of, the Work and Derivative +Works thereof. + +"Contribution" shall mean any work of authorship, including the original +version of the Work and any modifications or additions to that Work or +Derivative Works thereof, that is intentionally submitted to Licensor for +inclusion in the Work by the copyright owner or by an individual or Legal +Entity authorized to submit on behalf of the copyright owner. For the +purposes of this definition, "submitted" means any form of electronic, +verbal, or written communication sent to the Licensor or its +representatives, including but not limited to communication on electronic +mailing lists, source code control systems, and issue tracking systems that +are managed by, or on behalf of, the Licensor for the purpose of discussing +and improving the Work, but excluding communication that is conspicuously +marked or otherwise designated in writing by the copyright owner as "Not a +Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on +behalf of whom a Contribution has been received by Licensor and +subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this +License, each Contributor hereby grants to You a perpetual, worldwide, +non-exclusive, no-charge, royalty-free, irrevocable copyright license to +reproduce, prepare Derivative Works of, publicly display, publicly perform, +sublicense, and distribute the Work and such Derivative Works in Source or +Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this +License, each Contributor hereby grants to You a perpetual, worldwide, +non-exclusive, no-charge, royalty-free, irrevocable (except as stated in +this section) patent license to make, have made, use, offer to sell, sell, +import, and otherwise transfer the Work, where such license applies only to +those patent claims licensable by such Contributor that are necessarily +infringed by their Contribution(s) alone or by combination of their +Contribution(s) with the Work to which such Contribution(s) was submitted. +If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or +contributory patent infringement, then any patent licenses granted to You +under this License for that Work shall terminate as of the date such +litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or +Derivative Works thereof in any medium, with or without modifications, and +in Source or Object form, provided that You meet the following conditions: + + 1. You must give any other recipients of the Work or Derivative Works a +copy of this License; and + + 2. You must cause any modified files to carry prominent notices stating +that You changed the files; and + + 3. You must retain, in the Source form of any Derivative Works that You +distribute, all copyright, patent, trademark, and attribution notices from +the Source form of the Work, excluding those notices that do not pertain to +any part of the Derivative Works; and + + 4. If the Work includes a "NOTICE" text file as part of its +distribution, then any Derivative Works that You distribute must include a +readable copy of the attribution notices contained within such NOTICE file, +excluding those notices that do not pertain to any part of the Derivative +Works, in at least one of the following places: within a NOTICE text file +distributed as part of the Derivative Works; within the Source form or +documentation, if provided along with the Derivative Works; or, within a +display generated by the Derivative Works, if and wherever such third-party +notices normally appear. The contents of the NOTICE file are for +informational purposes only and do not modify the License. You may add Your +own attribution notices within Derivative Works that You distribute, +alongside or as an addendum to the NOTICE text from the Work, provided that +such additional attribution notices cannot be construed as modifying the +License. + +You may add Your own copyright statement to Your modifications and may +provide additional or different license terms and conditions for use, +reproduction, or distribution of Your modifications, or for any such +Derivative Works as a whole, provided Your use, reproduction, and +distribution of the Work otherwise complies with the conditions stated in +this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any +Contribution intentionally submitted for inclusion in the Work by You to +the Licensor shall be under the terms and conditions of this License, +without any additional terms or conditions. Notwithstanding the above, +nothing herein shall supersede or modify the terms of any separate license +agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade +names, trademarks, service marks, or product names of the Licensor, except +as required for reasonable and customary use in describing the origin of +the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to +in writing, Licensor provides the Work (and each Contributor provides its +Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied, including, without limitation, any +warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or +FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for +determining the appropriateness of using or redistributing the Work and +assume any risks associated with Your exercise of permissions under this +License. + +8. Limitation of Liability. In no event and under no legal theory, whether +in tort (including negligence), contract, or otherwise, unless required by +applicable law (such as deliberate and grossly negligent acts) or agreed to +in writing, shall any Contributor be liable to You for damages, including +any direct, indirect, special, incidental, or consequential damages of any +character arising as a result of this License or out of the use or +inability to use the Work (including but not limited to damages for loss of +goodwill, work stoppage, computer failure or malfunction, or any and all +other commercial damages or losses), even if such Contributor has been +advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the +Work or Derivative Works thereof, You may choose to offer, and charge a fee +for, acceptance of support, warranty, indemnity, or other liability +obligations and/or rights consistent with this License. However, in +accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if +You agree to indemnify, defend, and hold each Contributor harmless for any +liability incurred by, or claims asserted against, such Contributor by +reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "[]" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included +on the same "printed page" as the copyright notice for easier +identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); you may + not use this file except in compliance with the License. You may obtain a + copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable + law or agreed to in writing, software distributed under the License is + distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the specific language + governing permissions and limitations under the License. diff --git a/Externals/ffmpeg/licenses/vorbis.txt b/Externals/ffmpeg/licenses/vorbis.txt new file mode 100644 index 0000000000..2f9af4165 --- /dev/null +++ b/Externals/ffmpeg/licenses/vorbis.txt @@ -0,0 +1,28 @@ +Copyright (c) 2002-2008 Xiph.org Foundation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +- Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +- Neither the name of the Xiph.org Foundation nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/Externals/ffmpeg/licenses/x264.txt b/Externals/ffmpeg/licenses/x264.txt new file mode 100644 index 0000000000..0f70665a7 --- /dev/null +++ b/Externals/ffmpeg/licenses/x264.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. \ No newline at end of file diff --git a/Externals/ffmpeg/licenses/xavs.txt b/Externals/ffmpeg/licenses/xavs.txt new file mode 100644 index 0000000000..94a9ed024 --- /dev/null +++ b/Externals/ffmpeg/licenses/xavs.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/Externals/ffmpeg/licenses/xvid.txt b/Externals/ffmpeg/licenses/xvid.txt new file mode 100644 index 0000000000..16101eeb9 --- /dev/null +++ b/Externals/ffmpeg/licenses/xvid.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. \ No newline at end of file diff --git a/Externals/ffmpeg/licenses/zlib.txt b/Externals/ffmpeg/licenses/zlib.txt new file mode 100644 index 0000000000..530fd8385 --- /dev/null +++ b/Externals/ffmpeg/licenses/zlib.txt @@ -0,0 +1,23 @@ + zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.5, April 19th, 2010 + + Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly + Mark Adler diff --git a/Externals/libfreenect/AForge ReadMe.txt b/Externals/libfreenect/AForge ReadMe.txt new file mode 100644 index 0000000000..c65560ed8 --- /dev/null +++ b/Externals/libfreenect/AForge ReadMe.txt @@ -0,0 +1,9 @@ +Libraries in this folder are part of the OpenKinect project and were built from its sources: +http://openkinect.org/ +Sources from git's master branch was used. Last updated and built on February 20, 2012. + +The libraries were built using VS.NET 2010. Configuration done with CMake. + +See installation/build notes here: +http://openkinect.org/wiki/Getting_Started#Windows + diff --git a/Externals/libfreenect/APACHE20 b/Externals/libfreenect/APACHE20 new file mode 100644 index 0000000000..d64569567 --- /dev/null +++ b/Externals/libfreenect/APACHE20 @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Samples/Vision/Kinect/freenect.dll b/Externals/libfreenect/freenect.dll similarity index 100% rename from Samples/Vision/Kinect/freenect.dll rename to Externals/libfreenect/freenect.dll diff --git a/Externals/msinttypes/AForge ReadMe.txt b/Externals/msinttypes/AForge ReadMe.txt new file mode 100644 index 0000000000..ef1bfe8f4 --- /dev/null +++ b/Externals/msinttypes/AForge ReadMe.txt @@ -0,0 +1,2 @@ +The folder contains files from "msinttypes" project, which allow compiling C99 compliant projects in MSVC. +http://code.google.com/p/msinttypes/ diff --git a/Externals/msinttypes/changelog.txt b/Externals/msinttypes/changelog.txt new file mode 100644 index 0000000000..e13b87e5c --- /dev/null +++ b/Externals/msinttypes/changelog.txt @@ -0,0 +1,138 @@ +------------------------------------------------------------------------ +r26 | 2009-10-02 13:36:47 +0400 | 2 lines + +[Issue 5] Change to "stdint.h" to let compiler search for it in local directory. + +------------------------------------------------------------------------ +r25 | 2009-09-17 23:46:49 +0400 | 2 lines + +[Issue 4] Fix incorrect int8_t behaviour if compiled with /J flag. + +------------------------------------------------------------------------ +r24 | 2009-05-13 14:53:48 +0400 | 2 lines + +Forgot about #ifdef __cplusplus guard around 'extern "C"', so inclusion to C files has been broken. + +------------------------------------------------------------------------ +r23 | 2009-05-12 01:27:45 +0400 | 3 lines + +[Issue 2] Always wrap is included. + +------------------------------------------------------------------------ +r19 | 2007-07-04 02:14:40 +0400 | 3 lines + +Explicitly cast to appropriate type INT8_MIN, INT16_MIN, INT32_MIN and INT64_MIN constants. +Due to their unusual definition in Visual Studio headers (-_Ix_MAX-1) they are propagated to int and thus do not have expected type, causing VS6 strict compiler to claim about type inconsistency. + +------------------------------------------------------------------------ +r18 | 2007-06-26 16:53:23 +0400 | 2 lines + +Better handling of (U)INTx_C macros - now they generate constants of exact width. + +------------------------------------------------------------------------ +r17 | 2007-03-29 20:16:14 +0400 | 2 lines + +Fix typo: Miscrosoft -> Microsoft. + +------------------------------------------------------------------------ +r16 | 2007-02-24 17:32:58 +0300 | 4 lines + +Remove include, as it is not present in Visual Studio 2005 Epxress Edition and required only for INT_PTR and UINT_PTR types. + +'intptr_t' and 'uintptr_t' types now defined explicitly with #ifdef _WIN64. + +------------------------------------------------------------------------ +r15 | 2007-02-11 20:53:05 +0300 | 2 lines + +More correct fix for compilation under VS6. + +------------------------------------------------------------------------ +r14 | 2007-02-11 20:04:32 +0300 | 2 lines + +Bugfix: fix compiling under VS6, when stdint.h enclosed in 'extern "C" {}'. + +------------------------------------------------------------------------ +r13 | 2006-12-13 16:53:11 +0300 | 2 lines + +Make _inline modifier for imaxdiv default option. Use STATIC_IMAXDIV to make it static. + +------------------------------------------------------------------------ +r12 | 2006-12-13 16:42:24 +0300 | 2 lines + +Error message changed: VC6 supported from now. + +------------------------------------------------------------------------ +r11 | 2006-12-13 16:39:33 +0300 | 2 lines + +All (U)INT* types changed to (unsigned) __int*. This should make stdint.h compatible with VC6. + +------------------------------------------------------------------------ +r10 | 2006-12-13 16:20:57 +0300 | 3 lines + +Added INLINE_IMAXDIV define switch. +If INLINE_IMAXDIV is defined imaxdiv() have static modifier. If not - it is _inline. + +------------------------------------------------------------------------ +r9 | 2006-12-13 15:53:52 +0300 | 2 lines + +Error message for non-MSC compiler changed. + +------------------------------------------------------------------------ +r8 | 2006-12-13 12:47:48 +0300 | 2 lines + +Added #ifndef for SIZE_MAX (it is defined in limits.h on MSVSC 8). + +------------------------------------------------------------------------ +r7 | 2006-12-13 01:08:02 +0300 | 2 lines + +License chaged to BSD-derivative. + +------------------------------------------------------------------------ +r6 | 2006-12-13 00:53:20 +0300 | 2 lines + +Added include to avoid warnings when it is included after stdint.h. + +------------------------------------------------------------------------ +r5 | 2006-12-12 00:58:05 +0300 | 2 lines + +BUGFIX: Definitions of INTPTR_MIN, INTPTR_MAX and UINTPTR_MAX for WIN32 and WIN64 was mixed up. + +------------------------------------------------------------------------ +r4 | 2006-12-12 00:51:55 +0300 | 2 lines + +Rise #error if _MSC_VER is not defined. I.e. compiler other then Microsoft Visual C++ is used. + +------------------------------------------------------------------------ +r3 | 2006-12-11 22:54:14 +0300 | 2 lines + +Added include to stdint.h. + +------------------------------------------------------------------------ +r2 | 2006-12-11 21:39:27 +0300 | 2 lines + +Initial check in. + +------------------------------------------------------------------------ +r1 | 2006-12-11 21:30:23 +0300 | 1 line + +Initial directory structure. +------------------------------------------------------------------------ diff --git a/Externals/msinttypes/inttypes.h b/Externals/msinttypes/inttypes.h new file mode 100644 index 0000000000..4b3828a21 --- /dev/null +++ b/Externals/msinttypes/inttypes.h @@ -0,0 +1,305 @@ +// ISO C9x compliant inttypes.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_INTTYPES_H_ // [ +#define _MSC_INTTYPES_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include "stdint.h" + +// 7.8 Format conversion of integer types + +typedef struct { + intmax_t quot; + intmax_t rem; +} imaxdiv_t; + +// 7.8.1 Macros for format specifiers + +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 + +// The fprintf macros for signed integers are: +#define PRId8 "d" +#define PRIi8 "i" +#define PRIdLEAST8 "d" +#define PRIiLEAST8 "i" +#define PRIdFAST8 "d" +#define PRIiFAST8 "i" + +#define PRId16 "hd" +#define PRIi16 "hi" +#define PRIdLEAST16 "hd" +#define PRIiLEAST16 "hi" +#define PRIdFAST16 "hd" +#define PRIiFAST16 "hi" + +#define PRId32 "I32d" +#define PRIi32 "I32i" +#define PRIdLEAST32 "I32d" +#define PRIiLEAST32 "I32i" +#define PRIdFAST32 "I32d" +#define PRIiFAST32 "I32i" + +#define PRId64 "I64d" +#define PRIi64 "I64i" +#define PRIdLEAST64 "I64d" +#define PRIiLEAST64 "I64i" +#define PRIdFAST64 "I64d" +#define PRIiFAST64 "I64i" + +#define PRIdMAX "I64d" +#define PRIiMAX "I64i" + +#define PRIdPTR "Id" +#define PRIiPTR "Ii" + +// The fprintf macros for unsigned integers are: +#define PRIo8 "o" +#define PRIu8 "u" +#define PRIx8 "x" +#define PRIX8 "X" +#define PRIoLEAST8 "o" +#define PRIuLEAST8 "u" +#define PRIxLEAST8 "x" +#define PRIXLEAST8 "X" +#define PRIoFAST8 "o" +#define PRIuFAST8 "u" +#define PRIxFAST8 "x" +#define PRIXFAST8 "X" + +#define PRIo16 "ho" +#define PRIu16 "hu" +#define PRIx16 "hx" +#define PRIX16 "hX" +#define PRIoLEAST16 "ho" +#define PRIuLEAST16 "hu" +#define PRIxLEAST16 "hx" +#define PRIXLEAST16 "hX" +#define PRIoFAST16 "ho" +#define PRIuFAST16 "hu" +#define PRIxFAST16 "hx" +#define PRIXFAST16 "hX" + +#define PRIo32 "I32o" +#define PRIu32 "I32u" +#define PRIx32 "I32x" +#define PRIX32 "I32X" +#define PRIoLEAST32 "I32o" +#define PRIuLEAST32 "I32u" +#define PRIxLEAST32 "I32x" +#define PRIXLEAST32 "I32X" +#define PRIoFAST32 "I32o" +#define PRIuFAST32 "I32u" +#define PRIxFAST32 "I32x" +#define PRIXFAST32 "I32X" + +#define PRIo64 "I64o" +#define PRIu64 "I64u" +#define PRIx64 "I64x" +#define PRIX64 "I64X" +#define PRIoLEAST64 "I64o" +#define PRIuLEAST64 "I64u" +#define PRIxLEAST64 "I64x" +#define PRIXLEAST64 "I64X" +#define PRIoFAST64 "I64o" +#define PRIuFAST64 "I64u" +#define PRIxFAST64 "I64x" +#define PRIXFAST64 "I64X" + +#define PRIoMAX "I64o" +#define PRIuMAX "I64u" +#define PRIxMAX "I64x" +#define PRIXMAX "I64X" + +#define PRIoPTR "Io" +#define PRIuPTR "Iu" +#define PRIxPTR "Ix" +#define PRIXPTR "IX" + +// The fscanf macros for signed integers are: +#define SCNd8 "d" +#define SCNi8 "i" +#define SCNdLEAST8 "d" +#define SCNiLEAST8 "i" +#define SCNdFAST8 "d" +#define SCNiFAST8 "i" + +#define SCNd16 "hd" +#define SCNi16 "hi" +#define SCNdLEAST16 "hd" +#define SCNiLEAST16 "hi" +#define SCNdFAST16 "hd" +#define SCNiFAST16 "hi" + +#define SCNd32 "ld" +#define SCNi32 "li" +#define SCNdLEAST32 "ld" +#define SCNiLEAST32 "li" +#define SCNdFAST32 "ld" +#define SCNiFAST32 "li" + +#define SCNd64 "I64d" +#define SCNi64 "I64i" +#define SCNdLEAST64 "I64d" +#define SCNiLEAST64 "I64i" +#define SCNdFAST64 "I64d" +#define SCNiFAST64 "I64i" + +#define SCNdMAX "I64d" +#define SCNiMAX "I64i" + +#ifdef _WIN64 // [ +# define SCNdPTR "I64d" +# define SCNiPTR "I64i" +#else // _WIN64 ][ +# define SCNdPTR "ld" +# define SCNiPTR "li" +#endif // _WIN64 ] + +// The fscanf macros for unsigned integers are: +#define SCNo8 "o" +#define SCNu8 "u" +#define SCNx8 "x" +#define SCNX8 "X" +#define SCNoLEAST8 "o" +#define SCNuLEAST8 "u" +#define SCNxLEAST8 "x" +#define SCNXLEAST8 "X" +#define SCNoFAST8 "o" +#define SCNuFAST8 "u" +#define SCNxFAST8 "x" +#define SCNXFAST8 "X" + +#define SCNo16 "ho" +#define SCNu16 "hu" +#define SCNx16 "hx" +#define SCNX16 "hX" +#define SCNoLEAST16 "ho" +#define SCNuLEAST16 "hu" +#define SCNxLEAST16 "hx" +#define SCNXLEAST16 "hX" +#define SCNoFAST16 "ho" +#define SCNuFAST16 "hu" +#define SCNxFAST16 "hx" +#define SCNXFAST16 "hX" + +#define SCNo32 "lo" +#define SCNu32 "lu" +#define SCNx32 "lx" +#define SCNX32 "lX" +#define SCNoLEAST32 "lo" +#define SCNuLEAST32 "lu" +#define SCNxLEAST32 "lx" +#define SCNXLEAST32 "lX" +#define SCNoFAST32 "lo" +#define SCNuFAST32 "lu" +#define SCNxFAST32 "lx" +#define SCNXFAST32 "lX" + +#define SCNo64 "I64o" +#define SCNu64 "I64u" +#define SCNx64 "I64x" +#define SCNX64 "I64X" +#define SCNoLEAST64 "I64o" +#define SCNuLEAST64 "I64u" +#define SCNxLEAST64 "I64x" +#define SCNXLEAST64 "I64X" +#define SCNoFAST64 "I64o" +#define SCNuFAST64 "I64u" +#define SCNxFAST64 "I64x" +#define SCNXFAST64 "I64X" + +#define SCNoMAX "I64o" +#define SCNuMAX "I64u" +#define SCNxMAX "I64x" +#define SCNXMAX "I64X" + +#ifdef _WIN64 // [ +# define SCNoPTR "I64o" +# define SCNuPTR "I64u" +# define SCNxPTR "I64x" +# define SCNXPTR "I64X" +#else // _WIN64 ][ +# define SCNoPTR "lo" +# define SCNuPTR "lu" +# define SCNxPTR "lx" +# define SCNXPTR "lX" +#endif // _WIN64 ] + +#endif // __STDC_FORMAT_MACROS ] + +// 7.8.2 Functions for greatest-width integer types + +// 7.8.2.1 The imaxabs function +#define imaxabs _abs64 + +// 7.8.2.2 The imaxdiv function + +// This is modified version of div() function from Microsoft's div.c found +// in %MSVC.NET%\crt\src\div.c +#ifdef STATIC_IMAXDIV // [ +static +#else // STATIC_IMAXDIV ][ +_inline +#endif // STATIC_IMAXDIV ] +imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) +{ + imaxdiv_t result; + + result.quot = numer / denom; + result.rem = numer % denom; + + if (numer < 0 && result.rem > 0) { + // did division wrong; must fix up + ++result.quot; + result.rem -= denom; + } + + return result; +} + +// 7.8.2.3 The strtoimax and strtoumax functions +#define strtoimax _strtoi64 +#define strtoumax _strtoui64 + +// 7.8.2.4 The wcstoimax and wcstoumax functions +#define wcstoimax _wcstoi64 +#define wcstoumax _wcstoui64 + + +#endif // _MSC_INTTYPES_H_ ] diff --git a/Externals/msinttypes/stdint.h b/Externals/msinttypes/stdint.h new file mode 100644 index 0000000000..d02608a59 --- /dev/null +++ b/Externals/msinttypes/stdint.h @@ -0,0 +1,247 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2008 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include + +// For Visual Studio 6 in C++ mode and for many Visual Studio versions when +// compiling for ARM we should wrap include with 'extern "C++" {}' +// or compiler give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#ifdef __cplusplus +extern "C" { +#endif +# include +#ifdef __cplusplus +} +#endif + +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types + +// Visual Studio 6 and Embedded Visual C++ 4 doesn't +// realize that, e.g. char has the same size as __int8 +// so we give up on __intX for them. +#if (_MSC_VER < 1300) + typedef signed char int8_t; + typedef signed short int16_t; + typedef signed int int32_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; +#else + typedef signed __int8 int8_t; + typedef signed __int16 int16_t; + typedef signed __int32 int32_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; +#endif +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; + + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef signed __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 signed int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +#define INTMAX_C INT64_C +#define UINTMAX_C UINT64_C + +#endif // __STDC_CONSTANT_MACROS ] + + +#endif // _MSC_STDINT_H_ ] diff --git a/License.txt b/License.txt index f771439a1..e4b8d0b8b 100644 --- a/License.txt +++ b/License.txt @@ -1,6 +1,6 @@ The Accord.NET Framework -Copyright (c) 2009-2014, Csar Roberto de Souza +Copyright (c) 2009-2015, Accord.NET Authors 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 diff --git a/Release notes.txt b/Release notes.txt index 764f77796..d07f82ebd 100644 --- a/Release notes.txt +++ b/Release notes.txt @@ -1,3 +1,31 @@ +Accord.NET Framework 3.0.0 release notes +----------------------------------------- +16.08.2015. + +Version updates and fixes: + - GC-70: Merge with AForge.NET. + - GC-90: Convert unit test projects to NUnit + - GH-114: GeneralizedBetaDistribution's calls Random with wrong parameter order + +* General + - This release marks a milestone in the Accord.NET Framework. Starting from this + release, the AForge.NET Framework has been incorporated directly in the project, + meaning that we are now free to fix, maintain, transform and improve AForge.NET + directly. + + - This release provides most of the AForge.NET namespaces unchanged. This means + that this specific version of Accord.NET Framework can be used as drop-in + replacement in any project currently using the AForge.NET Framework and that + is willing to upgrade to Accord.NET sometime in the future. + + - This release is mostly a transition release to help projects using the AForge.NET + framework make the transition to Accord.NET more easily. Further releases will be + aimed at improving the interaction between the two codebases and streamlining the + provided functionality. + + + + Accord.NET Framework 2.15.0 release notes ----------------------------------------- 01.05.2015. diff --git a/Samples/Audio/Beat detection/AboutBox.Designer.cs b/Samples/Audio/Beat detection/AboutBox.Designer.cs index 4307253ef..f6d7e7190 100644 --- a/Samples/Audio/Beat detection/AboutBox.Designer.cs +++ b/Samples/Audio/Beat detection/AboutBox.Designer.cs @@ -1,4 +1,4 @@ -namespace BeatDetector +namespace SampleApp { partial class AboutBox { diff --git a/Samples/Audio/Beat detection/AboutBox.cs b/Samples/Audio/Beat detection/AboutBox.cs index 42befda87..bcc2b0acb 100644 --- a/Samples/Audio/Beat detection/AboutBox.cs +++ b/Samples/Audio/Beat detection/AboutBox.cs @@ -1,8 +1,8 @@ using System; using System.Reflection; -using System.Windows.Forms; - -namespace BeatDetector +using System.Windows.Forms; + +namespace SampleApp { partial class AboutBox : Form { diff --git a/Samples/Audio/Beat detection/Accord.dll.config b/Samples/Audio/Beat detection/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Audio/Beat detection/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Audio/Beat detection/Beat detection.csproj b/Samples/Audio/Beat detection/Beat detection.csproj index 26da9d664..0ae02837c 100644 --- a/Samples/Audio/Beat detection/Beat detection.csproj +++ b/Samples/Audio/Beat detection/Beat detection.csproj @@ -1,153 +1,141 @@ - - - - {01BA7F4B-6C29-48D1-ADB5-087B8DCF8AC3} - Debug - AnyCPU - WinExe - BeatDetector - Beat detection - v4.0 - Properties - BeatDetector.Program - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - - true - bin\x86\Debug\ - DEBUG;TRACE - true - Full - x86 - true - GlobalSuppressions.cs - AllRules.ruleset - - - bin\x86\Release\ - TRACE - true - None - x86 - true - GlobalSuppressions.cs - AllRules.ruleset - - - framework.ico - - - - - False - ..\..\..\Release\net40\Accord.dll - - - False - ..\..\..\Release\net40\Accord.Audio.dll - - - False - ..\..\..\Release\net40\Accord.Audio.Formats.dll - - - False - ..\..\..\Release\net40\Accord.Audition.dll - - - False - ..\..\..\Release\net40\Accord.DirectSound.dll - - - False - ..\..\..\Release\net40\Accord.Math.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Controls.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Math.dll - - - ..\..\..\Externals\SharpDX\net40\SharpDX.dll - - - ..\..\..\Externals\SharpDX\net40\SharpDX.DirectSound.dll - - - - 3.5 - - - - - - - - Form - - - AboutBox.cs - - - Form - - - MainForm.cs - - - - - AboutBox.cs - - - MainForm.cs - Designer - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - - - + + + + {01BA7F4B-6C29-48D1-ADB5-087B8DCF8AC3} + Debug + AnyCPU + WinExe + SampleApp + Beat detection + v4.0 + Properties + SampleApp.Program + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + bin\x86\Debug\ + DEBUG;TRACE + true + Full + x86 + true + GlobalSuppressions.cs + AllRules.ruleset + + + bin\x86\Release\ + TRACE + true + None + x86 + true + GlobalSuppressions.cs + AllRules.ruleset + + + framework.ico + + + + + False + ..\..\..\Release\net40\Accord.dll + + + False + ..\..\..\Release\net40\Accord.Audio.dll + + + ..\..\..\Release\net40\Accord.Audio.DirectSound.dll + + + False + ..\..\..\Release\net40\Accord.Audition.dll + + + False + ..\..\..\Release\net40\Accord.Math.dll + + + ..\..\..\Externals\SharpDX\net40\SharpDX.dll + + + ..\..\..\Externals\SharpDX\net40\SharpDX.DirectSound.dll + + + + 3.5 + + + + + + + + Form + + + AboutBox.cs + + + Form + + + MainForm.cs + + + + + AboutBox.cs + + + MainForm.cs + Designer + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + + PreserveNewest + + \ No newline at end of file diff --git a/Samples/Audio/Beat detection/MainForm.Designer.cs b/Samples/Audio/Beat detection/MainForm.Designer.cs index 34bd7219f..f5aaa98fa 100644 --- a/Samples/Audio/Beat detection/MainForm.Designer.cs +++ b/Samples/Audio/Beat detection/MainForm.Designer.cs @@ -1,35 +1,35 @@ -namespace BeatDetector -{ - partial class MainForm - { - /// - /// Designer variable used to keep track of non-visual components. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Disposes resources used by the form. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing) - { - if (components != null) - { - components.Dispose(); - } - } - base.Dispose(disposing); - } - - /// - /// This method is required for Signals Forms designer support. - /// Do not change the method contents inside the source code editor. The Forms designer might - /// not be able to load this method if it was changed manually. - /// - private void InitializeComponent() - { +namespace SampleApp +{ + partial class MainForm + { + /// + /// Designer variable used to keep track of non-visual components. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Disposes resources used by the form. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (components != null) + { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + /// + /// This method is required for Signals Forms designer support. + /// Do not change the method contents inside the source code editor. The Forms designer might + /// not be able to load this method if it was changed manually. + /// + private void InitializeComponent() + { this.components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog(); @@ -228,24 +228,24 @@ private void InitializeComponent() this.ResumeLayout(false); this.PerformLayout(); - } - private System.Windows.Forms.Label label1; - private System.Windows.Forms.Label lbAutoTempo; - private System.Windows.Forms.Label lbManualTempo; - private System.Windows.Forms.Label lbStatus; - private System.Windows.Forms.Button button4; - private System.Windows.Forms.Button button3; - private System.Windows.Forms.ComboBox comboBox1; - private System.Windows.Forms.Button button2; - private System.Windows.Forms.Button button1; - private System.Windows.Forms.OpenFileDialog openFileDialog1; - private System.Windows.Forms.Button button5; - private System.Windows.Forms.Timer timer1; - private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem closeToolStripMenuItem; - private System.Windows.Forms.MenuStrip menuStrip1; - private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem1; - - } -} + } + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label lbAutoTempo; + private System.Windows.Forms.Label lbManualTempo; + private System.Windows.Forms.Label lbStatus; + private System.Windows.Forms.Button button4; + private System.Windows.Forms.Button button3; + private System.Windows.Forms.ComboBox comboBox1; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.OpenFileDialog openFileDialog1; + private System.Windows.Forms.Button button5; + private System.Windows.Forms.Timer timer1; + private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem closeToolStripMenuItem; + private System.Windows.Forms.MenuStrip menuStrip1; + private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem1; + + } +} diff --git a/Samples/Audio/Beat detection/MainForm.cs b/Samples/Audio/Beat detection/MainForm.cs index a9b0147a5..548740500 100644 --- a/Samples/Audio/Beat detection/MainForm.cs +++ b/Samples/Audio/Beat detection/MainForm.cs @@ -36,10 +36,11 @@ using System.Windows.Forms; using Accord.Audio; using Accord.Audition.Beat; -using Accord.DirectSound; - -namespace BeatDetector +using Accord.DirectSound; + +namespace SampleApp { + /// /// Beat detector sample application. /// diff --git a/Samples/Audio/Beat detection/Program.cs b/Samples/Audio/Beat detection/Program.cs index 86df352f5..450caab6f 100644 --- a/Samples/Audio/Beat detection/Program.cs +++ b/Samples/Audio/Beat detection/Program.cs @@ -1,7 +1,7 @@ using System; using System.Windows.Forms; -namespace BeatDetector +namespace SampleApp { class Program { diff --git a/Samples/Audio/Fourier (FFT)/AboutBox.Designer.cs b/Samples/Audio/Fourier (FFT)/AboutBox.Designer.cs index 155bd6a59..195aa8480 100644 --- a/Samples/Audio/Fourier (FFT)/AboutBox.Designer.cs +++ b/Samples/Audio/Fourier (FFT)/AboutBox.Designer.cs @@ -1,4 +1,4 @@ -namespace Fourier +namespace SampleApp { partial class AboutBox { diff --git a/Samples/Audio/Fourier (FFT)/AboutBox.cs b/Samples/Audio/Fourier (FFT)/AboutBox.cs index 6d7007b05..bcc2b0acb 100644 --- a/Samples/Audio/Fourier (FFT)/AboutBox.cs +++ b/Samples/Audio/Fourier (FFT)/AboutBox.cs @@ -1,8 +1,8 @@ using System; using System.Reflection; -using System.Windows.Forms; - -namespace Fourier +using System.Windows.Forms; + +namespace SampleApp { partial class AboutBox : Form { diff --git a/Samples/Audio/Fourier (FFT)/Accord.dll.config b/Samples/Audio/Fourier (FFT)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Audio/Fourier (FFT)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Audio/Fourier (FFT)/Fourier (FFT).csproj b/Samples/Audio/Fourier (FFT)/Fourier (FFT).csproj index 0607ff91d..eef42c959 100644 --- a/Samples/Audio/Fourier (FFT)/Fourier (FFT).csproj +++ b/Samples/Audio/Fourier (FFT)/Fourier (FFT).csproj @@ -1,155 +1,144 @@ - - - - {18DDB224-5488-4833-A4F0-AA98F37F9864} - Debug - AnyCPU - WinExe - Fourier - Fourier %28FFT%29 - v4.0 - Properties - C:\Documents and Settings\Caio\Dados de aplicativos\ICSharpCode/SharpDevelop3.0\Settings.SourceAnalysis - Fourier.Program - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - - true - bin\x86\Debug\ - DEBUG;TRACE - true - Full - x86 - true - GlobalSuppressions.cs - AllRules.ruleset - - - bin\x86\Release\ - TRACE - true - None - x86 - true - GlobalSuppressions.cs - AllRules.ruleset - - - framework.ico - - - - - False - ..\..\..\Release\net40\Accord.dll - - - False - ..\..\..\Release\net40\Accord.Audio.dll - - - False - ..\..\..\Release\net40\Accord.Audio.Formats.dll - - - False - ..\..\..\Release\net40\Accord.Controls.Audio.dll - - - False - ..\..\..\Release\net40\Accord.DirectSound.dll - - - False - ..\..\..\Release\net40\Accord.Math.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Controls.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Math.dll - - - ..\..\..\Externals\SharpDX\net40\SharpDX.dll - - - ..\..\..\Externals\SharpDX\net40\SharpDX.DirectSound.dll - - - - 3.5 - - - - - - - - - Form - - - AboutBox.cs - - - Form - - - MainForm.cs - - - - - AboutBox.cs - - - MainForm.cs - Designer - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - - - + + + + {18DDB224-5488-4833-A4F0-AA98F37F9864} + Debug + AnyCPU + WinExe + SampleApp + Fourier %28FFT%29 + v4.0 + Properties + C:\Documents and Settings\Caio\Dados de aplicativos\ICSharpCode/SharpDevelop3.0\Settings.SourceAnalysis + SampleApp.Program + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + bin\x86\Debug\ + DEBUG;TRACE + true + Full + x86 + true + GlobalSuppressions.cs + AllRules.ruleset + + + bin\x86\Release\ + TRACE + true + None + x86 + true + GlobalSuppressions.cs + AllRules.ruleset + + + framework.ico + + + + + False + ..\..\..\Release\net40\Accord.dll + + + False + ..\..\..\Release\net40\Accord.Audio.dll + + + ..\..\..\Release\net40\Accord.Audio.DirectSound.dll + + + False + ..\..\..\Release\net40\Accord.Controls.Audio.dll + + + False + ..\..\..\Release\net40\Accord.Math.dll + + + ..\..\..\Externals\SharpDX\net40\SharpDX.dll + + + ..\..\..\Externals\SharpDX\net40\SharpDX.DirectSound.dll + + + + 3.5 + + + + + + + + + + Form + + + AboutBox.cs + + + Form + + + MainForm.cs + + + + + AboutBox.cs + + + MainForm.cs + Designer + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + + PreserveNewest + + \ No newline at end of file diff --git a/Samples/Audio/Fourier (FFT)/MainForm.Designer.cs b/Samples/Audio/Fourier (FFT)/MainForm.Designer.cs index f06e9cd4d..8ddb9abb5 100644 --- a/Samples/Audio/Fourier (FFT)/MainForm.Designer.cs +++ b/Samples/Audio/Fourier (FFT)/MainForm.Designer.cs @@ -1,33 +1,35 @@ -namespace Fourier -{ - partial class MainForm - { - /// - /// Designer variable used to keep track of non-visual components. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Disposes resources used by the form. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing) { - if (components != null) { - components.Dispose(); - } - } - base.Dispose(disposing); - } - - /// - /// This method is required for Signals Forms designer support. - /// Do not change the method contents inside the source code editor. The Forms designer might - /// not be able to load this method if it was changed manually. - /// - private void InitializeComponent() - { +namespace SampleApp +{ + partial class MainForm + { + /// + /// Designer variable used to keep track of non-visual components. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Disposes resources used by the form. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (components != null) + { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + /// + /// This method is required for Signals Forms designer support. + /// Do not change the method contents inside the source code editor. The Forms designer might + /// not be able to load this method if it was changed manually. + /// + private void InitializeComponent() + { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); this.menuStrip1 = new System.Windows.Forms.MenuStrip(); this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -187,7 +189,7 @@ private void InitializeComponent() // // comboBox1 // - this.comboBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + this.comboBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox1.FormattingEnabled = true; @@ -198,14 +200,12 @@ private void InitializeComponent() // // chart1 // - this.chart1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) + this.chart1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.chart1.BackColor = System.Drawing.Color.White; this.chart1.Location = new System.Drawing.Point(12, 27); this.chart1.Name = "chart1"; - this.chart1.RangeX = ((AForge.DoubleRange)(resources.GetObject("chart1.RangeX"))); - this.chart1.RangeY = ((AForge.DoubleRange)(resources.GetObject("chart1.RangeY"))); this.chart1.SimpleMode = false; this.chart1.Size = new System.Drawing.Size(684, 367); this.chart1.TabIndex = 6; @@ -213,7 +213,7 @@ private void InitializeComponent() // // vScrollBar1 // - this.vScrollBar1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + this.vScrollBar1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Right))); this.vScrollBar1.LargeChange = 1; this.vScrollBar1.Location = new System.Drawing.Point(698, 27); @@ -225,7 +225,7 @@ private void InitializeComponent() // // hScrollBar1 // - this.hScrollBar1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + this.hScrollBar1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.hScrollBar1.LargeChange = 5; this.hScrollBar1.Location = new System.Drawing.Point(12, 397); @@ -257,26 +257,26 @@ private void InitializeComponent() this.ResumeLayout(false); this.PerformLayout(); - } - private System.Windows.Forms.ToolStripMenuItem hammingWindowToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem optionsToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem closeToolStripMenuItem; - private Accord.Controls.Wavechart chart1; - private System.Windows.Forms.ComboBox comboBox1; - private System.Windows.Forms.Button button2; - private System.Windows.Forms.Button btnStart; - private System.Windows.Forms.OpenFileDialog openFileDialog1; - private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; - private System.Windows.Forms.MenuStrip menuStrip1; - private System.Windows.Forms.VScrollBar vScrollBar1; - private System.Windows.Forms.HScrollBar hScrollBar1; - private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem hannWindowToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem blackmanWindowToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem noneToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem startToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem stopToolStripMenuItem; - private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; - } -} + } + private System.Windows.Forms.ToolStripMenuItem hammingWindowToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem optionsToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem closeToolStripMenuItem; + private Accord.Controls.Wavechart chart1; + private System.Windows.Forms.ComboBox comboBox1; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.Button btnStart; + private System.Windows.Forms.OpenFileDialog openFileDialog1; + private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; + private System.Windows.Forms.MenuStrip menuStrip1; + private System.Windows.Forms.VScrollBar vScrollBar1; + private System.Windows.Forms.HScrollBar hScrollBar1; + private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem hannWindowToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem blackmanWindowToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem noneToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem startToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem stopToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + } +} diff --git a/Samples/Audio/Fourier (FFT)/MainForm.cs b/Samples/Audio/Fourier (FFT)/MainForm.cs index c5253a98e..a11de531e 100644 --- a/Samples/Audio/Fourier (FFT)/MainForm.cs +++ b/Samples/Audio/Fourier (FFT)/MainForm.cs @@ -1,234 +1,234 @@ -// Accord.NET Sample Applications -// http://accord-framework.net -// -// Copyright © 2009-2014, César Souza -// All rights reserved. 3-BSD License: -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// * Neither the name of the Accord.NET Framework authors nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -using Accord.Audio; -using Accord.Audio.Windows; -using Accord.DirectSound; -using AForge; -using AForge.Math; -using System; -using System.Drawing; -using System.Windows.Forms; - -namespace Fourier -{ - public partial class MainForm : Form - { - private IAudioSource source; - private IWindow window; - - public MainForm() - { - InitializeComponent(); - } - - - /// - /// Starts capturing from the chosen audio input interface - /// - /// - void btnStart_Click(object sender, EventArgs e) - { - // Get the device currently selected in the combobox - AudioDeviceInfo info = comboBox1.SelectedItem as AudioDeviceInfo; - - if (info == null) - { - MessageBox.Show("No audio devices available."); - return; - } - - // Create a new audio capture device - source = new AudioCaptureDevice(info) - { - // Capture at 22050 Hz - DesiredFrameSize = 2048, - SampleRate = 22050 - }; - - // Wire up some notification events - source.NewFrame += source_NewFrame; - source.AudioSourceError += source_AudioSourceError; - - - // Start it! - source.Start(); - } - - /// - /// Stops capturing - /// - /// - void btnStop_Click(object sender, EventArgs e) - { - // Stop capturing - if (source != null) - source.SignalToStop(); - } - - - /// - /// This method will be called whenever there is a new audio - /// frame to be processed. - /// - /// - void source_NewFrame(object sender, NewFrameEventArgs eventArgs) - { - // We can start by converting the audio frame to a complex signal - ComplexSignal signal = ComplexSignal.FromSignal(eventArgs.Signal); - - // If its needed, - if (window != null) - { - // Apply the chosen audio window - signal = window.Apply(signal, 0); - } - - // Transform to the complex domain - signal.ForwardFourierTransform(); - - // Now we can get the power spectrum output and its - // related frequency vector to plot our spectrometer. - - Complex[] channel = signal.GetChannel(0); - double[] power = Accord.Audio.Tools.GetPowerSpectrum(channel); - double[] freqv = Accord.Audio.Tools.GetFrequencyVector(signal.Length, signal.SampleRate); - - power[0] = 0; // zero DC - float[] g = new float[power.Length]; - for (int i = 0; i < power.Length; i++) - g[i] = (float)power[i]; - - // Adjust the zoom according to the horizontal and vertical scrollbars. - chart1.RangeX = new DoubleRange(freqv[0], freqv[freqv.Length - 1] / hScrollBar1.Value); - chart1.RangeY = new DoubleRange(0f, Math.Pow(10, -vScrollBar1.Value)); - - chart1.UpdateWaveform("fft", g); - } - - /// - /// This callback will be called when there is some error with the audio - /// source. It can be used to route exceptions so they don't compromise - /// the audio processing pipeline. - /// - /// - void source_AudioSourceError(object sender, AudioSourceErrorEventArgs e) - { - throw new Exception(e.Description); - } - - protected override void OnLoad(EventArgs e) - { - base.OnLoad(e); - - // Configure the wave chart to display the FFT - chart1.AddWaveform("fft", Color.Black, 1, false); - - // Enumerate audio devices and add all devices to combo - AudioDeviceCollection audioDevices = new AudioDeviceCollection(AudioDeviceCategory.Capture); - - foreach (AudioDeviceInfo device in audioDevices) - comboBox1.Items.Add(device); - - // Set a message if there is none - if (comboBox1.Items.Count == 0) - { - comboBox1.Items.Add("No local capture devices"); - comboBox1.Enabled = false; - } - - comboBox1.SelectedIndex = 0; - } - - - - void hammingWindowToolStripMenuItemClick(object sender, EventArgs e) - { - window = RaisedCosineWindow.Hamming(2048); - - reset(); - hammingWindowToolStripMenuItem.Checked = true; - } - - void hannWindowToolStripMenuItemClick(object sender, EventArgs e) - { - window = RaisedCosineWindow.Hann(2048); - - reset(); - hannWindowToolStripMenuItem.Checked = true; - } - - void blackmanWindowToolStripMenuItemClick(object sender, EventArgs e) - { - window = new BlackmanWindow(2048); - - reset(); - blackmanWindowToolStripMenuItem.Checked = true; - } - - private void noneToolStripMenuItem_Click(object sender, EventArgs e) - { - window = null; - - reset(); - noneToolStripMenuItem.Checked = true; - } - - private void reset() - { - hannWindowToolStripMenuItem.Checked = false; - hammingWindowToolStripMenuItem.Checked = false; - blackmanWindowToolStripMenuItem.Checked = false; - noneToolStripMenuItem.Checked = false; - } - - protected override void OnClosed(EventArgs e) - { - base.OnClosed(e); - - if (source != null) - source.SignalToStop(); - } - - private void aboutToolStripMenuItem_Click(object sender, EventArgs e) - { - new AboutBox().ShowDialog(this); - } - - private void closeToolStripMenuItem_Click(object sender, EventArgs e) - { - Close(); - } - - - } -} +// Accord.NET Sample Applications +// http://accord-framework.net +// +// Copyright © 2009-2014, César Souza +// All rights reserved. 3-BSD License: +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of the Accord.NET Framework authors nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +using Accord.Audio; +using Accord.Audio.Windows; +using Accord.DirectSound; +using AForge; +using AForge.Math; +using System; +using System.Drawing; +using System.Numerics; +using System.Windows.Forms; + +namespace SampleApp +{ + public partial class MainForm : Form + { + private IAudioSource source; + private IWindow window; + + public MainForm() + { + InitializeComponent(); + } + + + /// + /// Starts capturing from the chosen audio input interface + /// + /// + void btnStart_Click(object sender, EventArgs e) + { + // Get the device currently selected in the combobox + AudioDeviceInfo info = comboBox1.SelectedItem as AudioDeviceInfo; + + if (info == null) + { + MessageBox.Show("No audio devices available."); + return; + } + + // Create a new audio capture device + source = new AudioCaptureDevice(info) + { + // Capture at 22050 Hz + DesiredFrameSize = 2048, + SampleRate = 22050 + }; + + // Wire up some notification events + source.NewFrame += source_NewFrame; + source.AudioSourceError += source_AudioSourceError; + + // Start it! + source.Start(); + } + + /// + /// Stops capturing + /// + /// + void btnStop_Click(object sender, EventArgs e) + { + // Stop capturing + if (source != null) + source.SignalToStop(); + } + + + /// + /// This method will be called whenever there is a new audio + /// frame to be processed. + /// + /// + void source_NewFrame(object sender, NewFrameEventArgs eventArgs) + { + // We can start by converting the audio frame to a complex signal + ComplexSignal signal = ComplexSignal.FromSignal(eventArgs.Signal); + + // If its needed, + if (window != null) + { + // Apply the chosen audio window + signal = window.Apply(signal, 0); + } + + // Transform to the complex domain + signal.ForwardFourierTransform(); + + // Now we can get the power spectrum output and its + // related frequency vector to plot our spectrometer. + + Complex[] channel = signal.GetChannel(0); + double[] power = Accord.Audio.Tools.GetPowerSpectrum(channel); + double[] freqv = Accord.Audio.Tools.GetFrequencyVector(signal.Length, signal.SampleRate); + + power[0] = 0; // zero DC + float[] g = new float[power.Length]; + for (int i = 0; i < power.Length; i++) + g[i] = (float)power[i]; + + // Adjust the zoom according to the horizontal and vertical scrollbars. + chart1.RangeX = new DoubleRange(freqv[0], freqv[freqv.Length - 1] / hScrollBar1.Value); + chart1.RangeY = new DoubleRange(0f, Math.Pow(10, -vScrollBar1.Value)); + + chart1.UpdateWaveform("fft", g); + } + + /// + /// This callback will be called when there is some error with the audio + /// source. It can be used to route exceptions so they don't compromise + /// the audio processing pipeline. + /// + /// + void source_AudioSourceError(object sender, AudioSourceErrorEventArgs e) + { + throw new Exception(e.Description); + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + // Configure the wave chart to display the FFT + chart1.AddWaveform("fft", Color.Black, 1, false); + + // Enumerate audio devices and add all devices to combo + AudioDeviceCollection audioDevices = new AudioDeviceCollection(AudioDeviceCategory.Capture); + + foreach (AudioDeviceInfo device in audioDevices) + comboBox1.Items.Add(device); + + // Set a message if there is none + if (comboBox1.Items.Count == 0) + { + comboBox1.Items.Add("No local capture devices"); + comboBox1.Enabled = false; + } + + comboBox1.SelectedIndex = 0; + } + + + + void hammingWindowToolStripMenuItemClick(object sender, EventArgs e) + { + window = RaisedCosineWindow.Hamming(2048); + + reset(); + hammingWindowToolStripMenuItem.Checked = true; + } + + void hannWindowToolStripMenuItemClick(object sender, EventArgs e) + { + window = RaisedCosineWindow.Hann(2048); + + reset(); + hannWindowToolStripMenuItem.Checked = true; + } + + void blackmanWindowToolStripMenuItemClick(object sender, EventArgs e) + { + window = new BlackmanWindow(2048); + + reset(); + blackmanWindowToolStripMenuItem.Checked = true; + } + + private void noneToolStripMenuItem_Click(object sender, EventArgs e) + { + window = null; + + reset(); + noneToolStripMenuItem.Checked = true; + } + + private void reset() + { + hannWindowToolStripMenuItem.Checked = false; + hammingWindowToolStripMenuItem.Checked = false; + blackmanWindowToolStripMenuItem.Checked = false; + noneToolStripMenuItem.Checked = false; + } + + protected override void OnClosed(EventArgs e) + { + base.OnClosed(e); + + if (source != null) + source.SignalToStop(); + } + + private void aboutToolStripMenuItem_Click(object sender, EventArgs e) + { + new AboutBox().ShowDialog(this); + } + + private void closeToolStripMenuItem_Click(object sender, EventArgs e) + { + Close(); + } + + + } +} diff --git a/Samples/Audio/Fourier (FFT)/MainForm.resx b/Samples/Audio/Fourier (FFT)/MainForm.resx index fecf175af..e76596b50 100644 --- a/Samples/Audio/Fourier (FFT)/MainForm.resx +++ b/Samples/Audio/Fourier (FFT)/MainForm.resx @@ -123,278 +123,264 @@ 126, 17 - - - AAEAAAD/////AQAAAAAAAAAMAgAAAElBRm9yZ2UsIFZlcnNpb249Mi4yLjUuMCwgQ3VsdHVyZT1uZXV0 - cmFsLCBQdWJsaWNLZXlUb2tlbj1jMWRiNmZmNGVhYTA2YWViBQEAAAASQUZvcmdlLkRvdWJsZVJhbmdl - AgAAAANtaW4DbWF4AAAGBgIAAAAAAAAAAAAAAAAAAAAAAPA/Cw== - - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAElBRm9yZ2UsIFZlcnNpb249Mi4yLjUuMCwgQ3VsdHVyZT1uZXV0 - cmFsLCBQdWJsaWNLZXlUb2tlbj1jMWRiNmZmNGVhYTA2YWViBQEAAAASQUZvcmdlLkRvdWJsZVJhbmdl - AgAAAANtaW4DbWF4AAAGBgIAAAAAAAAAAAAAAAAAAAAAAPA/Cw== - - 51 - AAABAAMAEBAAAAAAIABoBAAANgAAACAgAAAAACAAqBAAAJ4EAAAwMAAAAAAgAKglAABGFQAAKAAAABAA - AAAgAAAAAQAgAAAAAABABAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wEAAAA7AAAAVQAA - AF0AAAAJ////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAtwAA - ADkAAAA/AAAAff///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ABEAAAADAAAACQAAANcAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAADVAAAAJf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAvQAAAEn///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAGwAAAM0AAACrAAAANf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAGQAAAJcAAACtAAAAlwAAAIEAAAA/////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAGUAAAAxAAAAfwAAAJ8AAAALAAAAi////wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAABlAAAAMQAAAGMAAAC7AAAADQAAAIn///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAFwAAAJkAAABtAAAA2wAAAIEAAAA9////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAZAAAAgQAAAPMAAAAx////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAAAkAAADvAAAADf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAA2wAA - AB3///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - AK8AAAAzAAAAAwAAABP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAABTAAAAaQAAADEAAADD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAAwAAAFcAAABVAAAAPf///wH///8B////Af///wEAAP//AAD//wAA//8AAP//AAD//wAA - //8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//KAAAACAAAABAAAAAAQAgAAAA - AACAEAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ABcAAABRAAAAYQAAAEcAAAAL////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAvAAAApwAAAF8AAABBAAAAfwAAAKMAAAAh////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAAI8AAAD5AAAAcwAAAAMAAAAHAAAApQAAAKkAAAAL////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAdwAAAOEAAABrAAAAA////wEAAABNAAAA5wAAAFv///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAPAAAAMQAAAA3///8B////AQAAAB0AAADhAAAAsf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ANMAAAD5AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAtwAAAP8AAAAz////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAACdAAAA/wAAAF3///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAIcAAAD/AAAAh////wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAcQAAAP8AAACdAAAAA////wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABfAAAA/wAAALsAAAAf////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAYwAAANcAAAD/AAAA9QAA - AN0AAAClAAAAK////wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACQAAAIMAAADRAAAAjQAA - AP8AAADjAAAAYwAAAKcAAADFAAAAMf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABXAAAA2QAA - AC0AAAA1AAAA8wAAAOsAAAAv////AQAAAJUAAADDAAAABf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ALcAAAB7////AQAAACsAAADjAAAA/QAAADv///8BAAAAJwAAAMsAAABB////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAA3QAAAEP///8BAAAAHwAAAM8AAAD/AAAASf///wEAAAAFAAAAsQAAAHH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAADfAAAARf///wEAAAAVAAAAvwAAAP8AAABp////AQAAAAUAAACxAAAAbf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAALcAAAB9////AQAAAAsAAACtAAAA/wAAAIH///8BAAAAKwAA - AM0AAAA5////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAATwAAANsAAAAzAAAAAwAAAKEAAAD/AAAAmwAA - AAUAAACXAAAAvwAAAAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAewAAANkAAABrAAAApQAA - AP8AAADRAAAApwAAAL8AAAAt////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAWwAA - AMUAAADrAAAA/wAAAPUAAACVAAAAJ////wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAAwAAAE8AAAD/AAAA2QAAAAX///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAHwAAAP8AAADdAAAAEf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAFAAAA/wAAAOEAAAAd////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAADfAAAA5wAAAC3///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAALcAAADtAAAAQf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAhQAA - APUAAABX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAABPAAAA7wAAAHP///8B////AQAAAA0AAAA3AAAAE////wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAABkAAADPAAAAmwAAAAf///8BAAAAZQAAAOcAAACL////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAGMAAADjAAAAH////wEAAABdAAAA9QAAAKn///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAACwAAAIEAAAChAAAAUwAAAF8AAACpAAAAN/// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAADkAAABXAAAATQAA - ABf///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAwAAAAYAAAAAEA - IAAAAAAAgCUAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAAcAAAAPAAAAEwAAABMAAAARAAAACQAAAAP///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAADAAAAHQAAAGMAAACvAAAA0QAAANUAAAC7AAAAdQAA - ACkAAAAF////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAATAAAApQAAANcAAABXAAAACQAA - AA0AAABTAAAAwwAAALsAAAA/AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABHAAAA/wAA - APEAAACNAAAAC////wH///8BAAAATQAAANcAAADBAAAAKQAAAAP///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAABtAAAA/wAAAP8AAAC/AAAAG////wH///8BAAAABwAAAKEAAAD5AAAAhQAAAAn///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAAA5AAAAxQAAANUAAACBAAAADf///wH///8B////AQAAAGcAAADnAAAA6QAA - ACf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAFAAAAPQAAAEsAAAAb////Af///wH///8B////AQAA - ADUAAADVAAAA/wAAAHX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAAA8AAADJAAAA/wAAANH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAC7AAAA/QAAAPsAAAAL////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACjAAAA+QAAAP8AAABB////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA8wAA - AP8AAABp////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAB3AAAA7wAAAP8AAACb////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAABnAAAA7QAAAP8AAAC/////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAABNAAAA5wAAAP8AAADf////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAA/AAAA5QAAAP8AAADtAAAAB/// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAxAAAA4QAA - AP8AAADxAAAANQAAAAn///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - AB0AAABjAAAA6QAAAP8AAAD5AAAAowAAAG8AAABBAAAAFf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAFAAAAPQAAAJUAAADfAAAA/QAAAP8AAAD9AAAA5wAAAOcAAADRAAAAgwAAACv///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAAAUAAABNAAAAwwAAANkAAACRAAAA6wAAAP8AAAD5AAAArQAAAGsAAACtAAAA5QAA - AKMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAADkAAAC/AAAA1wAAAGkAAAAVAAAA0QAAAP8AAAD5AAAAmQAA - AAUAAAApAAAAiwAAAOMAAACXAAAAIf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAEwAAAIUAAADjAAAAcwAAAA////8BAAAAtwAA - APsAAAD7AAAAs////wH///8BAAAAHQAAAJkAAADnAAAAWwAAAAX///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAOQAAAMUAAACrAAAAJ/// - /wH///8BAAAAoQAAAPsAAAD/AAAA0f///wH///8BAAAAAwAAAEcAAADNAAAAnQAAAB////8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAA - AOsAAAB1AAAABf///wH///8BAAAAhwAAAPcAAAD/AAAA1////wH///8B////AQAAABcAAACfAAAAzwAA - ADf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAZwAAAPUAAAD/AAAA3QAAABn///8B////AQAA - AAMAAACLAAAA6QAAAEP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAVQAAAPMAAAD/AAAA4wAA - ADf///8B////AQAAAAMAAACLAAAA5wAAAEP///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAAAPEAAAB7AAAABf///wH///8BAAAANwAA - APEAAAD/AAAA5QAAAEX///8B////AQAAABcAAAChAAAAxQAAADP///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAANwAAAMMAAACtAAAAKf// - /wH///8BAAAAGwAAAO0AAAD/AAAA6wAAAF////8BAAAAAwAAAE8AAADVAAAAlQAAABv///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAADwAA - AH0AAADnAAAAeQAAABH///8BAAAACwAAAO0AAAD/AAAA7wAAAHEAAAADAAAAIQAAAJ0AAADpAAAAWQAA - AAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAADUAAAC1AAAA2wAAAHUAAAAdAAAAAwAAAN8AAAD/AAAA9QAAAJMAAAArAAAAkQAA - AN8AAACPAAAAHf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAAUAAABJAAAAuwAAAOMAAACdAAAAZQAAANsAAAD/AAAA+wAA - ANEAAACtAAAA4QAAAJsAAAAr////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAFAAAAOQAAAIsAAADVAAAA5wAA - APcAAAD/AAAA/wAAAPcAAADDAAAAdQAAACf///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ABcAAABFAAAAaQAAALkAAAD/AAAA/wAAANUAAAA5AAAADf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAABQAAAGMAAAD/AAAA/wAAAMcAAAAJ////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////AQAAADcAAAD/AAAA/wAAAMsAAAAV////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAABUAAAD/AAAA/wAA - AM8AAAAh////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - AAMAAAD/AAAA/wAAANMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAADdAAAA/wAAANkAAAA9////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAACtAAAA/wAAAOEAAABV////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA/wAAAOUAAABl////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABTAAAA/wAA - AO8AAAB9////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAnAAAA8wAAAPcAAACX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAAAPAAAAwQAAAP0AAACtAAAABf///wH///8B////AQAAABsAAABTAAAASwAA - AAf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAHAAAAbQAAAP8AAADBAAAAIf///wH///8BAAAABwAA - AH0AAADbAAAA0wAAAEv///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAADAAAAKwAAANcAAADbAAAAVf// - /wH///8BAAAACwAAALUAAAD/AAAA/wAAAJX///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACwAA - AGkAAADvAAAAmwAAABP///8BAAAABQAAAHEAAADpAAAA/wAAAGv///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAABcAAACDAAAA4QAAAIcAAAAtAAAAGwAAAFMAAADTAAAAsQAAAB3///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAAMAAAAVAAAAWwAAAKkAAADFAAAAxwAAAKsAAABjAAAAHwAA - AAP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAAA0AAAATAAAAEwAA - AA8AAAAH////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8= - + AAABAAMAEBAAAAAAIABoBAAANgAAACAgAAAAACAAqBAAAJ4EAAAwMAAAAAAgAKglAABGFQAAKAAAABAA + AAAgAAAAAQAgAAAAAABABAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wEAAAA7AAAAVQAA + AF0AAAAJ////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAtwAA + ADkAAAA/AAAAff///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABEAAAADAAAACQAAANcAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADVAAAAJf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAvQAAAEn///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAGwAAAM0AAACrAAAANf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAGQAAAJcAAACtAAAAlwAAAIEAAAA/////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAGUAAAAxAAAAfwAAAJ8AAAALAAAAi////wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAABlAAAAMQAAAGMAAAC7AAAADQAAAIn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAFwAAAJkAAABtAAAA2wAAAIEAAAA9////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAZAAAAgQAAAPMAAAAx////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAAAkAAADvAAAADf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAA2wAA + AB3///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AK8AAAAzAAAAAwAAABP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABTAAAAaQAAADEAAADD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAAwAAAFcAAABVAAAAPf///wH///8B////Af///wEAAP//AAD//wAA//8AAP//AAD//wAA + //8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//KAAAACAAAABAAAAAAQAgAAAA + AACAEAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABcAAABRAAAAYQAAAEcAAAAL////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAvAAAApwAAAF8AAABBAAAAfwAAAKMAAAAh////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAI8AAAD5AAAAcwAAAAMAAAAHAAAApQAAAKkAAAAL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAdwAAAOEAAABrAAAAA////wEAAABNAAAA5wAAAFv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAPAAAAMQAAAA3///8B////AQAAAB0AAADhAAAAsf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ANMAAAD5AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAtwAAAP8AAAAz////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAACdAAAA/wAAAF3///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAIcAAAD/AAAAh////wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAcQAAAP8AAACdAAAAA////wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABfAAAA/wAAALsAAAAf////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAYwAAANcAAAD/AAAA9QAA + AN0AAAClAAAAK////wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACQAAAIMAAADRAAAAjQAA + AP8AAADjAAAAYwAAAKcAAADFAAAAMf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABXAAAA2QAA + AC0AAAA1AAAA8wAAAOsAAAAv////AQAAAJUAAADDAAAABf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ALcAAAB7////AQAAACsAAADjAAAA/QAAADv///8BAAAAJwAAAMsAAABB////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAA3QAAAEP///8BAAAAHwAAAM8AAAD/AAAASf///wEAAAAFAAAAsQAAAHH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADfAAAARf///wEAAAAVAAAAvwAAAP8AAABp////AQAAAAUAAACxAAAAbf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAALcAAAB9////AQAAAAsAAACtAAAA/wAAAIH///8BAAAAKwAA + AM0AAAA5////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAATwAAANsAAAAzAAAAAwAAAKEAAAD/AAAAmwAA + AAUAAACXAAAAvwAAAAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAewAAANkAAABrAAAApQAA + AP8AAADRAAAApwAAAL8AAAAt////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAWwAA + AMUAAADrAAAA/wAAAPUAAACVAAAAJ////wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAAwAAAE8AAAD/AAAA2QAAAAX///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAHwAAAP8AAADdAAAAEf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAFAAAA/wAAAOEAAAAd////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAADfAAAA5wAAAC3///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAALcAAADtAAAAQf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAhQAA + APUAAABX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABPAAAA7wAAAHP///8B////AQAAAA0AAAA3AAAAE////wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAABkAAADPAAAAmwAAAAf///8BAAAAZQAAAOcAAACL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAGMAAADjAAAAH////wEAAABdAAAA9QAAAKn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAACwAAAIEAAAChAAAAUwAAAF8AAACpAAAAN/// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAADkAAABXAAAATQAA + ABf///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAwAAAAYAAAAAEA + IAAAAAAAgCUAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAcAAAAPAAAAEwAAABMAAAARAAAACQAAAAP///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAADAAAAHQAAAGMAAACvAAAA0QAAANUAAAC7AAAAdQAA + ACkAAAAF////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAATAAAApQAAANcAAABXAAAACQAA + AA0AAABTAAAAwwAAALsAAAA/AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABHAAAA/wAA + APEAAACNAAAAC////wH///8BAAAATQAAANcAAADBAAAAKQAAAAP///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABtAAAA/wAAAP8AAAC/AAAAG////wH///8BAAAABwAAAKEAAAD5AAAAhQAAAAn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAAA5AAAAxQAAANUAAACBAAAADf///wH///8B////AQAAAGcAAADnAAAA6QAA + ACf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAFAAAAPQAAAEsAAAAb////Af///wH///8B////AQAA + ADUAAADVAAAA/wAAAHX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAA8AAADJAAAA/wAAANH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAC7AAAA/QAAAPsAAAAL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACjAAAA+QAAAP8AAABB////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA8wAA + AP8AAABp////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAB3AAAA7wAAAP8AAACb////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAABnAAAA7QAAAP8AAAC/////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAABNAAAA5wAAAP8AAADf////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAA/AAAA5QAAAP8AAADtAAAAB/// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAxAAAA4QAA + AP8AAADxAAAANQAAAAn///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AB0AAABjAAAA6QAAAP8AAAD5AAAAowAAAG8AAABBAAAAFf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAFAAAAPQAAAJUAAADfAAAA/QAAAP8AAAD9AAAA5wAAAOcAAADRAAAAgwAAACv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAAUAAABNAAAAwwAAANkAAACRAAAA6wAAAP8AAAD5AAAArQAAAGsAAACtAAAA5QAA + AKMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAADkAAAC/AAAA1wAAAGkAAAAVAAAA0QAAAP8AAAD5AAAAmQAA + AAUAAAApAAAAiwAAAOMAAACXAAAAIf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAEwAAAIUAAADjAAAAcwAAAA////8BAAAAtwAA + APsAAAD7AAAAs////wH///8BAAAAHQAAAJkAAADnAAAAWwAAAAX///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAOQAAAMUAAACrAAAAJ/// + /wH///8BAAAAoQAAAPsAAAD/AAAA0f///wH///8BAAAAAwAAAEcAAADNAAAAnQAAAB////8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAA + AOsAAAB1AAAABf///wH///8BAAAAhwAAAPcAAAD/AAAA1////wH///8B////AQAAABcAAACfAAAAzwAA + ADf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAZwAAAPUAAAD/AAAA3QAAABn///8B////AQAA + AAMAAACLAAAA6QAAAEP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAVQAAAPMAAAD/AAAA4wAA + ADf///8B////AQAAAAMAAACLAAAA5wAAAEP///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAAAPEAAAB7AAAABf///wH///8BAAAANwAA + APEAAAD/AAAA5QAAAEX///8B////AQAAABcAAAChAAAAxQAAADP///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAANwAAAMMAAACtAAAAKf// + /wH///8BAAAAGwAAAO0AAAD/AAAA6wAAAF////8BAAAAAwAAAE8AAADVAAAAlQAAABv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAADwAA + AH0AAADnAAAAeQAAABH///8BAAAACwAAAO0AAAD/AAAA7wAAAHEAAAADAAAAIQAAAJ0AAADpAAAAWQAA + AAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAADUAAAC1AAAA2wAAAHUAAAAdAAAAAwAAAN8AAAD/AAAA9QAAAJMAAAArAAAAkQAA + AN8AAACPAAAAHf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAUAAABJAAAAuwAAAOMAAACdAAAAZQAAANsAAAD/AAAA+wAA + ANEAAACtAAAA4QAAAJsAAAAr////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAFAAAAOQAAAIsAAADVAAAA5wAA + APcAAAD/AAAA/wAAAPcAAADDAAAAdQAAACf///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABcAAABFAAAAaQAAALkAAAD/AAAA/wAAANUAAAA5AAAADf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAABQAAAGMAAAD/AAAA/wAAAMcAAAAJ////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////AQAAADcAAAD/AAAA/wAAAMsAAAAV////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAABUAAAD/AAAA/wAA + AM8AAAAh////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AAMAAAD/AAAA/wAAANMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADdAAAA/wAAANkAAAA9////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAACtAAAA/wAAAOEAAABV////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA/wAAAOUAAABl////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABTAAAA/wAA + AO8AAAB9////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAnAAAA8wAAAPcAAACX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAAAPAAAAwQAAAP0AAACtAAAABf///wH///8B////AQAAABsAAABTAAAASwAA + AAf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAHAAAAbQAAAP8AAADBAAAAIf///wH///8BAAAABwAA + AH0AAADbAAAA0wAAAEv///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAADAAAAKwAAANcAAADbAAAAVf// + /wH///8BAAAACwAAALUAAAD/AAAA/wAAAJX///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACwAA + AGkAAADvAAAAmwAAABP///8BAAAABQAAAHEAAADpAAAA/wAAAGv///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAABcAAACDAAAA4QAAAIcAAAAtAAAAGwAAAFMAAADTAAAAsQAAAB3///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAMAAAAVAAAAWwAAAKkAAADFAAAAxwAAAKsAAABjAAAAHwAA + AAP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAAA0AAAATAAAAEwAA + AA8AAAAH////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8= + \ No newline at end of file diff --git a/Samples/Audio/Fourier (FFT)/Program.cs b/Samples/Audio/Fourier (FFT)/Program.cs index e042487d1..8f50c6b1e 100644 --- a/Samples/Audio/Fourier (FFT)/Program.cs +++ b/Samples/Audio/Fourier (FFT)/Program.cs @@ -1,7 +1,7 @@ using System; using System.Windows.Forms; -namespace Fourier +namespace SampleApp { internal sealed class Program diff --git a/Samples/Audio/Recorder/AboutBox.Designer.cs b/Samples/Audio/Recorder/AboutBox.Designer.cs index 0972a0a01..f6d7e7190 100644 --- a/Samples/Audio/Recorder/AboutBox.Designer.cs +++ b/Samples/Audio/Recorder/AboutBox.Designer.cs @@ -1,32 +1,32 @@ -namespace Recorder -{ - partial class AboutBox - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { +namespace SampleApp +{ + partial class AboutBox + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AboutBox)); this.tableLayoutPanel = new System.Windows.Forms.TableLayoutPanel(); this.logoPictureBox = new System.Windows.Forms.PictureBox(); @@ -174,17 +174,17 @@ private void InitializeComponent() ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).EndInit(); this.ResumeLayout(false); - } - - #endregion - - private System.Windows.Forms.TableLayoutPanel tableLayoutPanel; - private System.Windows.Forms.PictureBox logoPictureBox; - private System.Windows.Forms.Label labelProductName; - private System.Windows.Forms.Label labelVersion; - private System.Windows.Forms.Label labelCopyright; - private System.Windows.Forms.Label labelCompanyName; - private System.Windows.Forms.TextBox textBoxDescription; - private System.Windows.Forms.Button okButton; - } -} + } + + #endregion + + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel; + private System.Windows.Forms.PictureBox logoPictureBox; + private System.Windows.Forms.Label labelProductName; + private System.Windows.Forms.Label labelVersion; + private System.Windows.Forms.Label labelCopyright; + private System.Windows.Forms.Label labelCompanyName; + private System.Windows.Forms.TextBox textBoxDescription; + private System.Windows.Forms.Button okButton; + } +} diff --git a/Samples/Audio/Recorder/AboutBox.cs b/Samples/Audio/Recorder/AboutBox.cs index 598b4f427..c1446f400 100644 --- a/Samples/Audio/Recorder/AboutBox.cs +++ b/Samples/Audio/Recorder/AboutBox.cs @@ -4,9 +4,9 @@ using System.Drawing; using System.Linq; using System.Reflection; -using System.Windows.Forms; - -namespace Recorder +using System.Windows.Forms; + +namespace SampleApp { partial class AboutBox : Form { diff --git a/Samples/Audio/Recorder/Accord.dll.config b/Samples/Audio/Recorder/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Audio/Recorder/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Audio/Recorder/MainForm.Designer.cs b/Samples/Audio/Recorder/MainForm.Designer.cs index 793d392dd..b00d40042 100644 --- a/Samples/Audio/Recorder/MainForm.Designer.cs +++ b/Samples/Audio/Recorder/MainForm.Designer.cs @@ -1,35 +1,35 @@ -namespace Recorder -{ - partial class MainForm - { - /// - /// Designer variable used to keep track of non-visual components. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Disposes resources used by the form. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing) - { - if (components != null) - { - components.Dispose(); - } - } - base.Dispose(disposing); - } - - /// - /// This method is required for Signals Forms designer support. - /// Do not change the method contents inside the source code editor. The Forms designer might - /// not be able to load this method if it was changed manually. - /// - private void InitializeComponent() - { +namespace SampleApp +{ + partial class MainForm + { + /// + /// Designer variable used to keep track of non-visual components. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Disposes resources used by the form. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (components != null) + { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + /// + /// This method is required for Signals Forms designer support. + /// Do not change the method contents inside the source code editor. The Forms designer might + /// not be able to load this method if it was changed manually. + /// + private void InitializeComponent() + { this.components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); this.menuStrip1 = new System.Windows.Forms.MenuStrip(); @@ -289,29 +289,29 @@ private void InitializeComponent() this.ResumeLayout(false); this.PerformLayout(); - } - private System.Windows.Forms.ToolStripMenuItem optionsToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem closeToolStripMenuItem; - private Accord.Controls.Wavechart chart; - private System.Windows.Forms.Button btnRecord; - private System.Windows.Forms.Button btnStop; - private System.Windows.Forms.OpenFileDialog openFileDialog1; - private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; - private System.Windows.Forms.MenuStrip menuStrip1; - private System.Windows.Forms.ToolStripMenuItem effectsToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem; - private System.Windows.Forms.Label lbPosition; - private System.Windows.Forms.Label lbLength; - private System.Windows.Forms.Button btnBwd; - private System.Windows.Forms.Button btnPlay; - private System.Windows.Forms.Button btnFwd; - private System.Windows.Forms.TrackBar trackBar1; - private System.Windows.Forms.ToolStripMenuItem saveToolStripMenuItem; - private System.Windows.Forms.SaveFileDialog saveFileDialog1; - private System.Windows.Forms.Timer timer1; - private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem; - private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; - private System.Windows.Forms.ToolStripMenuItem btnIncreaseVolume; - private System.Windows.Forms.ToolStripMenuItem btnDecreaseVolume; - } -} + } + private System.Windows.Forms.ToolStripMenuItem optionsToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem closeToolStripMenuItem; + private Accord.Controls.Wavechart chart; + private System.Windows.Forms.Button btnRecord; + private System.Windows.Forms.Button btnStop; + private System.Windows.Forms.OpenFileDialog openFileDialog1; + private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; + private System.Windows.Forms.MenuStrip menuStrip1; + private System.Windows.Forms.ToolStripMenuItem effectsToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem; + private System.Windows.Forms.Label lbPosition; + private System.Windows.Forms.Label lbLength; + private System.Windows.Forms.Button btnBwd; + private System.Windows.Forms.Button btnPlay; + private System.Windows.Forms.Button btnFwd; + private System.Windows.Forms.TrackBar trackBar1; + private System.Windows.Forms.ToolStripMenuItem saveToolStripMenuItem; + private System.Windows.Forms.SaveFileDialog saveFileDialog1; + private System.Windows.Forms.Timer timer1; + private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripMenuItem btnIncreaseVolume; + private System.Windows.Forms.ToolStripMenuItem btnDecreaseVolume; + } +} diff --git a/Samples/Audio/Recorder/MainForm.cs b/Samples/Audio/Recorder/MainForm.cs index 9cbe831ae..7965c7aaf 100644 --- a/Samples/Audio/Recorder/MainForm.cs +++ b/Samples/Audio/Recorder/MainForm.cs @@ -37,9 +37,9 @@ using Accord.Audio; using Accord.Audio.Formats; using Accord.DirectSound; -using Accord.Audio.Filters; - -namespace Recorder +using Accord.Audio.Filters; + +namespace SampleApp { /// /// Audio recorder sample application. diff --git a/Samples/Audio/Recorder/MainForm.resx b/Samples/Audio/Recorder/MainForm.resx index b2db0d884..a3b85cbec 100644 --- a/Samples/Audio/Recorder/MainForm.resx +++ b/Samples/Audio/Recorder/MainForm.resx @@ -123,20 +123,6 @@ 17, 17 - - - AAEAAAD/////AQAAAAAAAAAMAgAAAElBRm9yZ2UsIFZlcnNpb249Mi4yLjUuMCwgQ3VsdHVyZT1uZXV0 - cmFsLCBQdWJsaWNLZXlUb2tlbj1jMWRiNmZmNGVhYTA2YWViBQEAAAASQUZvcmdlLkRvdWJsZVJhbmdl - AgAAAANtaW4DbWF4AAAGBgIAAAAAAAAAAAAAAAAAAAAAAPA/Cw== - - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAElBRm9yZ2UsIFZlcnNpb249Mi4yLjUuMCwgQ3VsdHVyZT1uZXV0 - cmFsLCBQdWJsaWNLZXlUb2tlbj1jMWRiNmZmNGVhYTA2YWViBQEAAAASQUZvcmdlLkRvdWJsZVJhbmdl - AgAAAANtaW4DbWF4AAAGBgIAAAAAAAAAAAAAAAAAAAAAAPA/Cw== - - 272, 17 @@ -146,258 +132,258 @@ - AAABAAMAEBAAAAAAIABoBAAANgAAACAgAAAAACAAqBAAAJ4EAAAwMAAAAAAgAKglAABGFQAAKAAAABAA - AAAgAAAAAQAgAAAAAABABAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wEAAAA7AAAAVQAA - AF0AAAAJ////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAtwAA - ADkAAAA/AAAAff///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ABEAAAADAAAACQAAANcAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAADVAAAAJf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAvQAAAEn///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAGwAAAM0AAACrAAAANf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAGQAAAJcAAACtAAAAlwAAAIEAAAA/////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAGUAAAAxAAAAfwAAAJ8AAAALAAAAi////wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAABlAAAAMQAAAGMAAAC7AAAADQAAAIn///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAFwAAAJkAAABtAAAA2wAAAIEAAAA9////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAZAAAAgQAAAPMAAAAx////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAAAkAAADvAAAADf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAA2wAA - AB3///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - AK8AAAAzAAAAAwAAABP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAABTAAAAaQAAADEAAADD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAAwAAAFcAAABVAAAAPf///wH///8B////Af///wEAAP//AAD//wAA//8AAP//AAD//wAA - //8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//KAAAACAAAABAAAAAAQAgAAAA - AACAEAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ABcAAABRAAAAYQAAAEcAAAAL////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAvAAAApwAAAF8AAABBAAAAfwAAAKMAAAAh////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAAI8AAAD5AAAAcwAAAAMAAAAHAAAApQAAAKkAAAAL////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAdwAAAOEAAABrAAAAA////wEAAABNAAAA5wAAAFv///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAPAAAAMQAAAA3///8B////AQAAAB0AAADhAAAAsf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ANMAAAD5AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAtwAAAP8AAAAz////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAACdAAAA/wAAAF3///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAIcAAAD/AAAAh////wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAcQAAAP8AAACdAAAAA////wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABfAAAA/wAAALsAAAAf////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAYwAAANcAAAD/AAAA9QAA - AN0AAAClAAAAK////wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACQAAAIMAAADRAAAAjQAA - AP8AAADjAAAAYwAAAKcAAADFAAAAMf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABXAAAA2QAA - AC0AAAA1AAAA8wAAAOsAAAAv////AQAAAJUAAADDAAAABf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ALcAAAB7////AQAAACsAAADjAAAA/QAAADv///8BAAAAJwAAAMsAAABB////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAA3QAAAEP///8BAAAAHwAAAM8AAAD/AAAASf///wEAAAAFAAAAsQAAAHH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAADfAAAARf///wEAAAAVAAAAvwAAAP8AAABp////AQAAAAUAAACxAAAAbf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAALcAAAB9////AQAAAAsAAACtAAAA/wAAAIH///8BAAAAKwAA - AM0AAAA5////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAATwAAANsAAAAzAAAAAwAAAKEAAAD/AAAAmwAA - AAUAAACXAAAAvwAAAAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAewAAANkAAABrAAAApQAA - AP8AAADRAAAApwAAAL8AAAAt////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAWwAA - AMUAAADrAAAA/wAAAPUAAACVAAAAJ////wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAAwAAAE8AAAD/AAAA2QAAAAX///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAHwAAAP8AAADdAAAAEf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAFAAAA/wAAAOEAAAAd////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAADfAAAA5wAAAC3///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAALcAAADtAAAAQf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAhQAA - APUAAABX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAABPAAAA7wAAAHP///8B////AQAAAA0AAAA3AAAAE////wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAABkAAADPAAAAmwAAAAf///8BAAAAZQAAAOcAAACL////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAGMAAADjAAAAH////wEAAABdAAAA9QAAAKn///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAACwAAAIEAAAChAAAAUwAAAF8AAACpAAAAN/// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAADkAAABXAAAATQAA - ABf///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAwAAAAYAAAAAEA - IAAAAAAAgCUAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAAcAAAAPAAAAEwAAABMAAAARAAAACQAAAAP///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAADAAAAHQAAAGMAAACvAAAA0QAAANUAAAC7AAAAdQAA - ACkAAAAF////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAATAAAApQAAANcAAABXAAAACQAA - AA0AAABTAAAAwwAAALsAAAA/AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABHAAAA/wAA - APEAAACNAAAAC////wH///8BAAAATQAAANcAAADBAAAAKQAAAAP///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAABtAAAA/wAAAP8AAAC/AAAAG////wH///8BAAAABwAAAKEAAAD5AAAAhQAAAAn///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAAA5AAAAxQAAANUAAACBAAAADf///wH///8B////AQAAAGcAAADnAAAA6QAA - ACf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAFAAAAPQAAAEsAAAAb////Af///wH///8B////AQAA - ADUAAADVAAAA/wAAAHX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAAA8AAADJAAAA/wAAANH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAC7AAAA/QAAAPsAAAAL////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACjAAAA+QAAAP8AAABB////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA8wAA - AP8AAABp////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAB3AAAA7wAAAP8AAACb////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAABnAAAA7QAAAP8AAAC/////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAABNAAAA5wAAAP8AAADf////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAA/AAAA5QAAAP8AAADtAAAAB/// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAxAAAA4QAA - AP8AAADxAAAANQAAAAn///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - AB0AAABjAAAA6QAAAP8AAAD5AAAAowAAAG8AAABBAAAAFf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAFAAAAPQAAAJUAAADfAAAA/QAAAP8AAAD9AAAA5wAAAOcAAADRAAAAgwAAACv///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAAAUAAABNAAAAwwAAANkAAACRAAAA6wAAAP8AAAD5AAAArQAAAGsAAACtAAAA5QAA - AKMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAADkAAAC/AAAA1wAAAGkAAAAVAAAA0QAAAP8AAAD5AAAAmQAA - AAUAAAApAAAAiwAAAOMAAACXAAAAIf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAEwAAAIUAAADjAAAAcwAAAA////8BAAAAtwAA - APsAAAD7AAAAs////wH///8BAAAAHQAAAJkAAADnAAAAWwAAAAX///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAOQAAAMUAAACrAAAAJ/// - /wH///8BAAAAoQAAAPsAAAD/AAAA0f///wH///8BAAAAAwAAAEcAAADNAAAAnQAAAB////8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAA - AOsAAAB1AAAABf///wH///8BAAAAhwAAAPcAAAD/AAAA1////wH///8B////AQAAABcAAACfAAAAzwAA - ADf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAZwAAAPUAAAD/AAAA3QAAABn///8B////AQAA - AAMAAACLAAAA6QAAAEP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAVQAAAPMAAAD/AAAA4wAA - ADf///8B////AQAAAAMAAACLAAAA5wAAAEP///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAAAPEAAAB7AAAABf///wH///8BAAAANwAA - APEAAAD/AAAA5QAAAEX///8B////AQAAABcAAAChAAAAxQAAADP///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAANwAAAMMAAACtAAAAKf// - /wH///8BAAAAGwAAAO0AAAD/AAAA6wAAAF////8BAAAAAwAAAE8AAADVAAAAlQAAABv///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAADwAA - AH0AAADnAAAAeQAAABH///8BAAAACwAAAO0AAAD/AAAA7wAAAHEAAAADAAAAIQAAAJ0AAADpAAAAWQAA - AAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAADUAAAC1AAAA2wAAAHUAAAAdAAAAAwAAAN8AAAD/AAAA9QAAAJMAAAArAAAAkQAA - AN8AAACPAAAAHf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAAUAAABJAAAAuwAAAOMAAACdAAAAZQAAANsAAAD/AAAA+wAA - ANEAAACtAAAA4QAAAJsAAAAr////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAFAAAAOQAAAIsAAADVAAAA5wAA - APcAAAD/AAAA/wAAAPcAAADDAAAAdQAAACf///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ABcAAABFAAAAaQAAALkAAAD/AAAA/wAAANUAAAA5AAAADf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAABQAAAGMAAAD/AAAA/wAAAMcAAAAJ////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////AQAAADcAAAD/AAAA/wAAAMsAAAAV////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAABUAAAD/AAAA/wAA - AM8AAAAh////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - AAMAAAD/AAAA/wAAANMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAADdAAAA/wAAANkAAAA9////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAACtAAAA/wAAAOEAAABV////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA/wAAAOUAAABl////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABTAAAA/wAA - AO8AAAB9////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAnAAAA8wAAAPcAAACX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAAAPAAAAwQAAAP0AAACtAAAABf///wH///8B////AQAAABsAAABTAAAASwAA - AAf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAHAAAAbQAAAP8AAADBAAAAIf///wH///8BAAAABwAA - AH0AAADbAAAA0wAAAEv///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAADAAAAKwAAANcAAADbAAAAVf// - /wH///8BAAAACwAAALUAAAD/AAAA/wAAAJX///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACwAA - AGkAAADvAAAAmwAAABP///8BAAAABQAAAHEAAADpAAAA/wAAAGv///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAABcAAACDAAAA4QAAAIcAAAAtAAAAGwAAAFMAAADTAAAAsQAAAB3///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAAMAAAAVAAAAWwAAAKkAAADFAAAAxwAAAKsAAABjAAAAHwAA - AAP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAAA0AAAATAAAAEwAA - AA8AAAAH////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8= - + AAABAAMAEBAAAAAAIABoBAAANgAAACAgAAAAACAAqBAAAJ4EAAAwMAAAAAAgAKglAABGFQAAKAAAABAA + AAAgAAAAAQAgAAAAAABABAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wEAAAA7AAAAVQAA + AF0AAAAJ////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAtwAA + ADkAAAA/AAAAff///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABEAAAADAAAACQAAANcAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADVAAAAJf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAvQAAAEn///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAGwAAAM0AAACrAAAANf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAGQAAAJcAAACtAAAAlwAAAIEAAAA/////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAGUAAAAxAAAAfwAAAJ8AAAALAAAAi////wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAABlAAAAMQAAAGMAAAC7AAAADQAAAIn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAFwAAAJkAAABtAAAA2wAAAIEAAAA9////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAZAAAAgQAAAPMAAAAx////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAAAkAAADvAAAADf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAA2wAA + AB3///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AK8AAAAzAAAAAwAAABP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABTAAAAaQAAADEAAADD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAAwAAAFcAAABVAAAAPf///wH///8B////Af///wEAAP//AAD//wAA//8AAP//AAD//wAA + //8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//KAAAACAAAABAAAAAAQAgAAAA + AACAEAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABcAAABRAAAAYQAAAEcAAAAL////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAvAAAApwAAAF8AAABBAAAAfwAAAKMAAAAh////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAI8AAAD5AAAAcwAAAAMAAAAHAAAApQAAAKkAAAAL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAdwAAAOEAAABrAAAAA////wEAAABNAAAA5wAAAFv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAPAAAAMQAAAA3///8B////AQAAAB0AAADhAAAAsf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ANMAAAD5AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAtwAAAP8AAAAz////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAACdAAAA/wAAAF3///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAIcAAAD/AAAAh////wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAcQAAAP8AAACdAAAAA////wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABfAAAA/wAAALsAAAAf////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAYwAAANcAAAD/AAAA9QAA + AN0AAAClAAAAK////wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACQAAAIMAAADRAAAAjQAA + AP8AAADjAAAAYwAAAKcAAADFAAAAMf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABXAAAA2QAA + AC0AAAA1AAAA8wAAAOsAAAAv////AQAAAJUAAADDAAAABf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ALcAAAB7////AQAAACsAAADjAAAA/QAAADv///8BAAAAJwAAAMsAAABB////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAA3QAAAEP///8BAAAAHwAAAM8AAAD/AAAASf///wEAAAAFAAAAsQAAAHH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADfAAAARf///wEAAAAVAAAAvwAAAP8AAABp////AQAAAAUAAACxAAAAbf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAALcAAAB9////AQAAAAsAAACtAAAA/wAAAIH///8BAAAAKwAA + AM0AAAA5////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAATwAAANsAAAAzAAAAAwAAAKEAAAD/AAAAmwAA + AAUAAACXAAAAvwAAAAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAewAAANkAAABrAAAApQAA + AP8AAADRAAAApwAAAL8AAAAt////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAWwAA + AMUAAADrAAAA/wAAAPUAAACVAAAAJ////wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAAwAAAE8AAAD/AAAA2QAAAAX///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAHwAAAP8AAADdAAAAEf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAFAAAA/wAAAOEAAAAd////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAADfAAAA5wAAAC3///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAALcAAADtAAAAQf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAhQAA + APUAAABX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABPAAAA7wAAAHP///8B////AQAAAA0AAAA3AAAAE////wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAABkAAADPAAAAmwAAAAf///8BAAAAZQAAAOcAAACL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAGMAAADjAAAAH////wEAAABdAAAA9QAAAKn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAACwAAAIEAAAChAAAAUwAAAF8AAACpAAAAN/// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAADkAAABXAAAATQAA + ABf///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAwAAAAYAAAAAEA + IAAAAAAAgCUAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAcAAAAPAAAAEwAAABMAAAARAAAACQAAAAP///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAADAAAAHQAAAGMAAACvAAAA0QAAANUAAAC7AAAAdQAA + ACkAAAAF////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAATAAAApQAAANcAAABXAAAACQAA + AA0AAABTAAAAwwAAALsAAAA/AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABHAAAA/wAA + APEAAACNAAAAC////wH///8BAAAATQAAANcAAADBAAAAKQAAAAP///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABtAAAA/wAAAP8AAAC/AAAAG////wH///8BAAAABwAAAKEAAAD5AAAAhQAAAAn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAAA5AAAAxQAAANUAAACBAAAADf///wH///8B////AQAAAGcAAADnAAAA6QAA + ACf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAFAAAAPQAAAEsAAAAb////Af///wH///8B////AQAA + ADUAAADVAAAA/wAAAHX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAA8AAADJAAAA/wAAANH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAC7AAAA/QAAAPsAAAAL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACjAAAA+QAAAP8AAABB////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA8wAA + AP8AAABp////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAB3AAAA7wAAAP8AAACb////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAABnAAAA7QAAAP8AAAC/////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAABNAAAA5wAAAP8AAADf////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAA/AAAA5QAAAP8AAADtAAAAB/// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAxAAAA4QAA + AP8AAADxAAAANQAAAAn///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AB0AAABjAAAA6QAAAP8AAAD5AAAAowAAAG8AAABBAAAAFf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAFAAAAPQAAAJUAAADfAAAA/QAAAP8AAAD9AAAA5wAAAOcAAADRAAAAgwAAACv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAAUAAABNAAAAwwAAANkAAACRAAAA6wAAAP8AAAD5AAAArQAAAGsAAACtAAAA5QAA + AKMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAADkAAAC/AAAA1wAAAGkAAAAVAAAA0QAAAP8AAAD5AAAAmQAA + AAUAAAApAAAAiwAAAOMAAACXAAAAIf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAEwAAAIUAAADjAAAAcwAAAA////8BAAAAtwAA + APsAAAD7AAAAs////wH///8BAAAAHQAAAJkAAADnAAAAWwAAAAX///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAOQAAAMUAAACrAAAAJ/// + /wH///8BAAAAoQAAAPsAAAD/AAAA0f///wH///8BAAAAAwAAAEcAAADNAAAAnQAAAB////8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAA + AOsAAAB1AAAABf///wH///8BAAAAhwAAAPcAAAD/AAAA1////wH///8B////AQAAABcAAACfAAAAzwAA + ADf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAZwAAAPUAAAD/AAAA3QAAABn///8B////AQAA + AAMAAACLAAAA6QAAAEP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAVQAAAPMAAAD/AAAA4wAA + ADf///8B////AQAAAAMAAACLAAAA5wAAAEP///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAAAPEAAAB7AAAABf///wH///8BAAAANwAA + APEAAAD/AAAA5QAAAEX///8B////AQAAABcAAAChAAAAxQAAADP///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAANwAAAMMAAACtAAAAKf// + /wH///8BAAAAGwAAAO0AAAD/AAAA6wAAAF////8BAAAAAwAAAE8AAADVAAAAlQAAABv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAADwAA + AH0AAADnAAAAeQAAABH///8BAAAACwAAAO0AAAD/AAAA7wAAAHEAAAADAAAAIQAAAJ0AAADpAAAAWQAA + AAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAADUAAAC1AAAA2wAAAHUAAAAdAAAAAwAAAN8AAAD/AAAA9QAAAJMAAAArAAAAkQAA + AN8AAACPAAAAHf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAUAAABJAAAAuwAAAOMAAACdAAAAZQAAANsAAAD/AAAA+wAA + ANEAAACtAAAA4QAAAJsAAAAr////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAFAAAAOQAAAIsAAADVAAAA5wAA + APcAAAD/AAAA/wAAAPcAAADDAAAAdQAAACf///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABcAAABFAAAAaQAAALkAAAD/AAAA/wAAANUAAAA5AAAADf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAABQAAAGMAAAD/AAAA/wAAAMcAAAAJ////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////AQAAADcAAAD/AAAA/wAAAMsAAAAV////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAABUAAAD/AAAA/wAA + AM8AAAAh////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AAMAAAD/AAAA/wAAANMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADdAAAA/wAAANkAAAA9////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAACtAAAA/wAAAOEAAABV////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA/wAAAOUAAABl////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABTAAAA/wAA + AO8AAAB9////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAnAAAA8wAAAPcAAACX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAAAPAAAAwQAAAP0AAACtAAAABf///wH///8B////AQAAABsAAABTAAAASwAA + AAf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAHAAAAbQAAAP8AAADBAAAAIf///wH///8BAAAABwAA + AH0AAADbAAAA0wAAAEv///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAADAAAAKwAAANcAAADbAAAAVf// + /wH///8BAAAACwAAALUAAAD/AAAA/wAAAJX///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACwAA + AGkAAADvAAAAmwAAABP///8BAAAABQAAAHEAAADpAAAA/wAAAGv///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAABcAAACDAAAA4QAAAIcAAAAtAAAAGwAAAFMAAADTAAAAsQAAAB3///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAMAAAAVAAAAWwAAAKkAAADFAAAAxwAAAKsAAABjAAAAHwAA + AAP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAAA0AAAATAAAAEwAA + AA8AAAAH////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8= + \ No newline at end of file diff --git a/Samples/Audio/Recorder/Program.cs b/Samples/Audio/Recorder/Program.cs index 9ca868bf6..316268492 100644 --- a/Samples/Audio/Recorder/Program.cs +++ b/Samples/Audio/Recorder/Program.cs @@ -1,7 +1,7 @@ using System; using System.Windows.Forms; -namespace Recorder +namespace SampleApp { static class Program { diff --git a/Samples/Audio/Recorder/Recorder.csproj b/Samples/Audio/Recorder/Recorder.csproj index b3eb2e38a..2ae1d0d05 100644 --- a/Samples/Audio/Recorder/Recorder.csproj +++ b/Samples/Audio/Recorder/Recorder.csproj @@ -1,141 +1,132 @@ - - - - Debug - x86 - 8.0.30703 - 2.0 - {A3C56C4A-57FC-48A4-A45A-DA12304D06A9} - WinExe - Properties - Recorder - Recorder - v4.0 - Client - 512 - - - x86 - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - x86 - pdbonly - true - bin\x86\Release\ - TRACE - prompt - 4 - - - framework.ico - - - - False - ..\..\..\Release\net40\Accord.dll - - - False - ..\..\..\Release\net40\Accord.Audio.dll - - - False - ..\..\..\Release\net40\Accord.Audio.Formats.dll - - - False - ..\..\..\Release\net40\Accord.Controls.Audio.dll - - - False - ..\..\..\Release\net40\Accord.DirectSound.dll - - - False - ..\..\..\Release\net40\Accord.Math.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Math.dll - - - ..\..\..\Externals\SharpDX\net40\SharpDX.dll - - - ..\..\..\Externals\SharpDX\net40\SharpDX.DirectSound.dll - - - - - - - - - - - - - - - Form - - - AboutBox.cs - - - Form - - - MainForm.cs - - - - - AboutBox.cs - - - MainForm.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - + + + + Debug + x86 + 8.0.30703 + 2.0 + {A3C56C4A-57FC-48A4-A45A-DA12304D06A9} + WinExe + Properties + Recorder + Recorder + v4.0 + Client + 512 + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + bin\x86\Release\ + TRACE + prompt + 4 + + + framework.ico + + + SampleApp.Program + + + + False + ..\..\..\Release\net40\Accord.dll + + + False + ..\..\..\Release\net40\Accord.Audio.dll + + + ..\..\..\Release\net40\Accord.Audio.DirectSound.dll + + + False + ..\..\..\Release\net40\Accord.Controls.Audio.dll + + + False + ..\..\..\Release\net40\Accord.Math.dll + + + ..\..\..\Externals\SharpDX\net40\SharpDX.dll + + + ..\..\..\Externals\SharpDX\net40\SharpDX.DirectSound.dll + + + + + + + + + + + + + Form + + + AboutBox.cs + + + Form + + + MainForm.cs + + + + + AboutBox.cs + + + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + --> \ No newline at end of file diff --git a/Samples/Fuzzy/Robot (Inference)/AboutForm.Designer.cs b/Samples/Fuzzy/Robot (Inference)/AboutForm.Designer.cs new file mode 100644 index 0000000000..0e1fac1ff --- /dev/null +++ b/Samples/Fuzzy/Robot (Inference)/AboutForm.Designer.cs @@ -0,0 +1,120 @@ +namespace SampleApp +{ + partial class AboutForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.emailLabel = new System.Windows.Forms.LinkLabel(); + this.label3 = new System.Windows.Forms.Label(); + this.aforgeFrameworkLabel = new System.Windows.Forms.LinkLabel(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // emailLabel + // + this.emailLabel.AutoSize = true; + this.emailLabel.Location = new System.Drawing.Point(80, 99); + this.emailLabel.Name = "emailLabel"; + this.emailLabel.Size = new System.Drawing.Size(135, 13); + this.emailLabel.TabIndex = 12; + this.emailLabel.TabStop = true; + this.emailLabel.Text = "fabio.caversan@gmail.com"; + this.emailLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkClicked); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(56, 84); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(182, 13); + this.label3.TabIndex = 11; + this.label3.Text = "Copyright © 2009, Fabio L. Caversan"; + // + // aforgeFrameworkLabel + // + this.aforgeFrameworkLabel.AutoSize = true; + this.aforgeFrameworkLabel.Location = new System.Drawing.Point(51, 59); + this.aforgeFrameworkLabel.Name = "aforgeFrameworkLabel"; + this.aforgeFrameworkLabel.Size = new System.Drawing.Size(192, 13); + this.aforgeFrameworkLabel.TabIndex = 10; + this.aforgeFrameworkLabel.TabStop = true; + this.aforgeFrameworkLabel.Text = "http://www.aforgenet.com/framework/"; + this.aforgeFrameworkLabel.VisitedLinkColor = System.Drawing.Color.Blue; + this.aforgeFrameworkLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkClicked); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(29, 44); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(236, 13); + this.label2.TabIndex = 9; + this.label2.Text = "Sample application from AForge.NET Framework"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204))); + this.label1.Location = new System.Drawing.Point(68, 14); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(159, 13); + this.label1.TabIndex = 8; + this.label1.Text = "Fuzzy Auto Guided Vehicle"; + // + // AboutForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(294, 126); + this.Controls.Add(this.emailLabel); + this.Controls.Add(this.label3); + this.Controls.Add(this.aforgeFrameworkLabel); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "AboutForm"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "About ..."; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.LinkLabel emailLabel; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.LinkLabel aforgeFrameworkLabel; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + } +} \ No newline at end of file diff --git a/Samples/Fuzzy/Robot (Inference)/AboutForm.cs b/Samples/Fuzzy/Robot (Inference)/AboutForm.cs new file mode 100644 index 0000000000..37498b511 --- /dev/null +++ b/Samples/Fuzzy/Robot (Inference)/AboutForm.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace SampleApp +{ + public partial class AboutForm : Form + { + public AboutForm( ) + { + InitializeComponent( ); + + // initialize links + emailLabel.Links.Add( 0, emailLabel.Text.Length, "mailto:" + emailLabel.Text ); + aforgeFrameworkLabel.Links.Add( 0, aforgeFrameworkLabel.Text.Length, aforgeFrameworkLabel.Text ); + } + + private void LinkClicked( object sender, LinkLabelLinkClickedEventArgs e ) + { + System.Diagnostics.Process.Start( e.Link.LinkData.ToString( ) ); + } + } +} diff --git a/Samples/Fuzzy/Robot (Inference)/AboutForm.resx b/Samples/Fuzzy/Robot (Inference)/AboutForm.resx new file mode 100644 index 0000000000..19dc0dd8b --- /dev/null +++ b/Samples/Fuzzy/Robot (Inference)/AboutForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Fuzzy/Robot (Inference)/Accord.dll.config b/Samples/Fuzzy/Robot (Inference)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Fuzzy/Robot (Inference)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Fuzzy/Robot (Inference)/AssemblyInfo.cs b/Samples/Fuzzy/Robot (Inference)/AssemblyInfo.cs new file mode 100644 index 0000000000..6e7180d0a --- /dev/null +++ b/Samples/Fuzzy/Robot (Inference)/AssemblyInfo.cs @@ -0,0 +1,58 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle( "Fuzzy Auto Guided Vehicle" )] +[assembly: AssemblyDescription( "Fuzzy Auto Guided Vehicle sample" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "AForge" )] +[assembly: AssemblyProduct( "AForge.NET" )] +[assembly: AssemblyCopyright( "AForge 2009" )] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion( "2.0.0.0" )] + +// +// In order to sign your assembly you must specify a key to use. Refer to the +// Microsoft .NET Framework documentation for more information on assembly signing. +// +// Use the attributes below to control which key is used for signing. +// +// Notes: +// (*) If no key is specified, the assembly is not signed. +// (*) KeyName refers to a key that has been installed in the Crypto Service +// Provider (CSP) on your machine. KeyFile refers to a file which contains +// a key. +// (*) If the KeyFile and the KeyName values are both specified, the +// following processing occurs: +// (1) If the KeyName can be found in the CSP, that key is used. +// (2) If the KeyName does not exist and the KeyFile does exist, the key +// in the KeyFile is installed into the CSP and used. +// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. +// When specifying the KeyFile, the location of the KeyFile should be +// relative to the project output directory which is +// %Project Directory%\obj\. For example, if your KeyFile is +// located in the project directory, you would specify the AssemblyKeyFile +// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] +// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework +// documentation for more information on this. +// +[assembly: AssemblyDelaySign( false )] +[assembly: AssemblyKeyFile( "" )] +[assembly: AssemblyKeyName( "" )] diff --git a/Samples/Fuzzy/Robot (Inference)/FuzzyAGV.sln b/Samples/Fuzzy/Robot (Inference)/FuzzyAGV.sln new file mode 100644 index 0000000000..00bf5d013 --- /dev/null +++ b/Samples/Fuzzy/Robot (Inference)/FuzzyAGV.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C# Express 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FuzzyAGV", "FuzzyAGV.csproj", "{BCC446EF-0F10-4FBB-AB37-9A9E0B1CDBAB}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BCC446EF-0F10-4FBB-AB37-9A9E0B1CDBAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BCC446EF-0F10-4FBB-AB37-9A9E0B1CDBAB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BCC446EF-0F10-4FBB-AB37-9A9E0B1CDBAB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BCC446EF-0F10-4FBB-AB37-9A9E0B1CDBAB}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/Fuzzy/Robot (Inference)/MainForm.cs b/Samples/Fuzzy/Robot (Inference)/MainForm.cs new file mode 100644 index 0000000000..25f4f5103 --- /dev/null +++ b/Samples/Fuzzy/Robot (Inference)/MainForm.cs @@ -0,0 +1,772 @@ +// Fuzzy Auto Guided Vehicle Sample +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +using System; +using System.Drawing; +using System.Drawing.Imaging; +using System.Collections; +using System.ComponentModel; +using System.Windows.Forms; +using System.Data; +using System.Threading; +using System.Diagnostics; +using AForge.Fuzzy; + +namespace SampleApp +{ + public class MainForm : System.Windows.Forms.Form + { + #region Private members + private string RunLabel; + private Point InitialPos; + private bool FirstInference; + private int LastX; + private int LastY; + private double Angle; + private Bitmap OriginalMap, InitialMap; + private InferenceSystem IS; + private Thread thMovement; + + /// + /// Required designer variable. + /// + private System.Windows.Forms.PictureBox pbTerrain; + private System.Windows.Forms.Button btnRun; + private System.Windows.Forms.TextBox txtInterval; + private System.Windows.Forms.CheckBox cbLasers; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Label txtRight; + private System.Windows.Forms.Label txtLeft; + private System.Windows.Forms.Label txtFront; + private System.Windows.Forms.Label lbl; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label txtAngle; + private System.Windows.Forms.Button btnStep; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.PictureBox pbRobot; + private System.Windows.Forms.Button btnReset; + private System.Windows.Forms.GroupBox gbComandos; + private System.ComponentModel.Container components = null; + private GroupBox groupBox3; + private Label label5; + private Button aboutButton; + private System.Windows.Forms.CheckBox cbTrajeto; + #endregion + + #region Class constructor, destructor and Main method + + /// + /// The main entry point for the application. + /// + [STAThread] + public static void Main() + { + Application.Run(new MainForm()); + } + + + public MainForm() + { + InitializeComponent(); + Angle = 0; + OriginalMap = new Bitmap(pbTerrain.Image); + InitialMap = new Bitmap(pbTerrain.Image); + + InitFuzzyEngine(); + FirstInference = true; + pbRobot.Top = pbTerrain.Bottom - 50; + pbRobot.Left = pbTerrain.Left + 60; + InitialPos = pbRobot.Location; + RunLabel = btnRun.Text; + } + + /// + /// Stoping the movement thread + /// + protected override void Dispose(bool disposing) + { + StopMovement(); + if (disposing) + { + if (components != null) + { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + + #endregion + + #region Windows Form Designer generated code + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); + this.pbTerrain = new System.Windows.Forms.PictureBox(); + this.btnStep = new System.Windows.Forms.Button(); + this.btnRun = new System.Windows.Forms.Button(); + this.txtInterval = new System.Windows.Forms.TextBox(); + this.cbLasers = new System.Windows.Forms.CheckBox(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.txtRight = new System.Windows.Forms.Label(); + this.txtLeft = new System.Windows.Forms.Label(); + this.txtFront = new System.Windows.Forms.Label(); + this.lbl = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.label3 = new System.Windows.Forms.Label(); + this.txtAngle = new System.Windows.Forms.Label(); + this.gbComandos = new System.Windows.Forms.GroupBox(); + this.cbTrajeto = new System.Windows.Forms.CheckBox(); + this.btnReset = new System.Windows.Forms.Button(); + this.label4 = new System.Windows.Forms.Label(); + this.pbRobot = new System.Windows.Forms.PictureBox(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.label5 = new System.Windows.Forms.Label(); + this.aboutButton = new System.Windows.Forms.Button(); + ((System.ComponentModel.ISupportInitialize)(this.pbTerrain)).BeginInit(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.gbComandos.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pbRobot)).BeginInit(); + this.groupBox3.SuspendLayout(); + this.SuspendLayout(); + // + // pbTerrain + // + this.pbTerrain.BackColor = System.Drawing.SystemColors.ControlText; + this.pbTerrain.ErrorImage = null; + this.pbTerrain.Image = ((System.Drawing.Image)(resources.GetObject("pbTerrain.Image"))); + this.pbTerrain.InitialImage = null; + this.pbTerrain.Location = new System.Drawing.Point(256, 12); + this.pbTerrain.Name = "pbTerrain"; + this.pbTerrain.Size = new System.Drawing.Size(500, 500); + this.pbTerrain.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pbTerrain.TabIndex = 10; + this.pbTerrain.TabStop = false; + this.pbTerrain.MouseDown += new System.Windows.Forms.MouseEventHandler(this.pbTerrain_MouseDown); + this.pbTerrain.MouseMove += new System.Windows.Forms.MouseEventHandler(this.pbTerrain_MouseMove); + // + // btnStep + // + this.btnStep.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.btnStep.Location = new System.Drawing.Point(10, 159); + this.btnStep.Name = "btnStep"; + this.btnStep.Size = new System.Drawing.Size(120, 34); + this.btnStep.TabIndex = 14; + this.btnStep.Text = "&One Step"; + this.btnStep.Click += new System.EventHandler(this.button3_Click); + // + // btnRun + // + this.btnRun.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.btnRun.Location = new System.Drawing.Point(10, 202); + this.btnRun.Name = "btnRun"; + this.btnRun.Size = new System.Drawing.Size(120, 33); + this.btnRun.TabIndex = 15; + this.btnRun.Text = "&Run"; + this.btnRun.Click += new System.EventHandler(this.btnRun_Click); + // + // txtInterval + // + this.txtInterval.Location = new System.Drawing.Point(10, 121); + this.txtInterval.Name = "txtInterval"; + this.txtInterval.Size = new System.Drawing.Size(115, 26); + this.txtInterval.TabIndex = 16; + this.txtInterval.Text = "10"; + this.txtInterval.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; + // + // cbLasers + // + this.cbLasers.Checked = true; + this.cbLasers.CheckState = System.Windows.Forms.CheckState.Checked; + this.cbLasers.Location = new System.Drawing.Point(13, 58); + this.cbLasers.Name = "cbLasers"; + this.cbLasers.Size = new System.Drawing.Size(192, 36); + this.cbLasers.TabIndex = 17; + this.cbLasers.Text = "&Show Beams"; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.txtRight); + this.groupBox1.Controls.Add(this.txtLeft); + this.groupBox1.Controls.Add(this.txtFront); + this.groupBox1.Controls.Add(this.lbl); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Location = new System.Drawing.Point(13, 12); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(230, 105); + this.groupBox1.TabIndex = 24; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Sensor readings::"; + // + // txtRight + // + this.txtRight.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.txtRight.Location = new System.Drawing.Point(166, 70); + this.txtRight.Name = "txtRight"; + this.txtRight.RightToLeft = System.Windows.Forms.RightToLeft.Yes; + this.txtRight.Size = new System.Drawing.Size(52, 24); + this.txtRight.TabIndex = 29; + this.txtRight.Text = "0"; + this.txtRight.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // txtLeft + // + this.txtLeft.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.txtLeft.Location = new System.Drawing.Point(166, 47); + this.txtLeft.Name = "txtLeft"; + this.txtLeft.RightToLeft = System.Windows.Forms.RightToLeft.Yes; + this.txtLeft.Size = new System.Drawing.Size(52, 23); + this.txtLeft.TabIndex = 28; + this.txtLeft.Text = "0"; + this.txtLeft.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // txtFront + // + this.txtFront.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.txtFront.Location = new System.Drawing.Point(166, 23); + this.txtFront.Name = "txtFront"; + this.txtFront.RightToLeft = System.Windows.Forms.RightToLeft.Yes; + this.txtFront.Size = new System.Drawing.Size(52, 24); + this.txtFront.TabIndex = 27; + this.txtFront.Text = "0"; + this.txtFront.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // lbl + // + this.lbl.Location = new System.Drawing.Point(13, 70); + this.lbl.Name = "lbl"; + this.lbl.Size = new System.Drawing.Size(160, 24); + this.lbl.TabIndex = 26; + this.lbl.Text = "Right (pixels):"; + // + // label2 + // + this.label2.Location = new System.Drawing.Point(13, 47); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(160, 23); + this.label2.TabIndex = 25; + this.label2.Text = "Left (pixels):"; + // + // label1 + // + this.label1.Location = new System.Drawing.Point(13, 23); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(141, 24); + this.label1.TabIndex = 24; + this.label1.Text = "Frontal (pixels):"; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.label3); + this.groupBox2.Controls.Add(this.txtAngle); + this.groupBox2.Location = new System.Drawing.Point(13, 129); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(230, 58); + this.groupBox2.TabIndex = 25; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Output:"; + // + // label3 + // + this.label3.Location = new System.Drawing.Point(13, 23); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(141, 24); + this.label3.TabIndex = 10; + this.label3.Text = "Angle (degrees):"; + // + // txtAngle + // + this.txtAngle.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.txtAngle.Location = new System.Drawing.Point(154, 23); + this.txtAngle.Name = "txtAngle"; + this.txtAngle.Size = new System.Drawing.Size(64, 24); + this.txtAngle.TabIndex = 29; + this.txtAngle.Text = "0,00"; + this.txtAngle.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // gbComandos + // + this.gbComandos.Controls.Add(this.cbTrajeto); + this.gbComandos.Controls.Add(this.btnReset); + this.gbComandos.Controls.Add(this.label4); + this.gbComandos.Controls.Add(this.btnStep); + this.gbComandos.Controls.Add(this.cbLasers); + this.gbComandos.Controls.Add(this.btnRun); + this.gbComandos.Controls.Add(this.txtInterval); + this.gbComandos.Location = new System.Drawing.Point(13, 199); + this.gbComandos.Name = "gbComandos"; + this.gbComandos.Size = new System.Drawing.Size(230, 292); + this.gbComandos.TabIndex = 26; + this.gbComandos.TabStop = false; + this.gbComandos.Text = "Tools:"; + // + // cbTrajeto + // + this.cbTrajeto.Location = new System.Drawing.Point(13, 23); + this.cbTrajeto.Name = "cbTrajeto"; + this.cbTrajeto.Size = new System.Drawing.Size(192, 35); + this.cbTrajeto.TabIndex = 19; + this.cbTrajeto.Text = "&Track Path"; + // + // btnReset + // + this.btnReset.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.btnReset.Location = new System.Drawing.Point(10, 244); + this.btnReset.Name = "btnReset"; + this.btnReset.Size = new System.Drawing.Size(120, 34); + this.btnReset.TabIndex = 0; + this.btnReset.Text = "Rest&art"; + this.btnReset.Click += new System.EventHandler(this.btnReset_Click); + // + // label4 + // + this.label4.Location = new System.Drawing.Point(10, 98); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(200, 19); + this.label4.TabIndex = 18; + this.label4.Text = "Move Interval (ms):"; + // + // pbRobot + // + this.pbRobot.BackColor = System.Drawing.Color.Transparent; + this.pbRobot.Image = ((System.Drawing.Image)(resources.GetObject("pbRobot.Image"))); + this.pbRobot.Location = new System.Drawing.Point(346, 690); + this.pbRobot.Name = "pbRobot"; + this.pbRobot.Size = new System.Drawing.Size(16, 14); + this.pbRobot.TabIndex = 11; + this.pbRobot.TabStop = false; + // + // groupBox3 + // + this.groupBox3.Controls.Add(this.label5); + this.groupBox3.Location = new System.Drawing.Point(13, 500); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Size = new System.Drawing.Size(230, 174); + this.groupBox3.TabIndex = 27; + this.groupBox3.TabStop = false; + this.groupBox3.Text = "Hints:"; + // + // label5 + // + this.label5.Location = new System.Drawing.Point(13, 23); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(200, 129); + this.label5.TabIndex = 10; + this.label5.Text = "Left click the image to draw passages (white), right click the image to draw wall" + + "s (black)."; + // + // aboutButton + // + this.aboutButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.aboutButton.Location = new System.Drawing.Point(66, 691); + this.aboutButton.Name = "aboutButton"; + this.aboutButton.Size = new System.Drawing.Size(120, 34); + this.aboutButton.TabIndex = 28; + this.aboutButton.Text = "About"; + this.aboutButton.UseVisualStyleBackColor = true; + this.aboutButton.Click += new System.EventHandler(this.aboutButton_Click); + // + // MainForm + // + this.AutoScaleBaseSize = new System.Drawing.Size(8, 19); + this.ClientSize = new System.Drawing.Size(981, 733); + this.Controls.Add(this.aboutButton); + this.Controls.Add(this.groupBox3); + this.Controls.Add(this.gbComandos); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.pbRobot); + this.Controls.Add(this.pbTerrain); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D; + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MaximizeBox = false; + this.Name = "MainForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Fuzzy Auto Guided Vehicle Sample"; + ((System.ComponentModel.ISupportInitialize)(this.pbTerrain)).EndInit(); + this.groupBox1.ResumeLayout(false); + this.groupBox2.ResumeLayout(false); + this.gbComandos.ResumeLayout(false); + this.gbComandos.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pbRobot)).EndInit(); + this.groupBox3.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + #endregion + + // Hardcode initializing the Fuzzy Inference System + void InitFuzzyEngine() + { + + // Linguistic labels (fuzzy sets) that compose the distances + FuzzySet fsNear = new FuzzySet("Near", new TrapezoidalFunction(15, 50, TrapezoidalFunction.EdgeType.Right)); + FuzzySet fsMedium = new FuzzySet("Medium", new TrapezoidalFunction(15, 50, 60, 100)); + FuzzySet fsFar = new FuzzySet("Far", new TrapezoidalFunction(60, 100, TrapezoidalFunction.EdgeType.Left)); + + // Right Distance (Input) + LinguisticVariable lvRight = new LinguisticVariable("RightDistance", 0, 120); + lvRight.AddLabel(fsNear); + lvRight.AddLabel(fsMedium); + lvRight.AddLabel(fsFar); + + // Left Distance (Input) + LinguisticVariable lvLeft = new LinguisticVariable("LeftDistance", 0, 120); + lvLeft.AddLabel(fsNear); + lvLeft.AddLabel(fsMedium); + lvLeft.AddLabel(fsFar); + + // Front Distance (Input) + LinguisticVariable lvFront = new LinguisticVariable("FrontalDistance", 0, 120); + lvFront.AddLabel(fsNear); + lvFront.AddLabel(fsMedium); + lvFront.AddLabel(fsFar); + + // Linguistic labels (fuzzy sets) that compose the angle + FuzzySet fsVN = new FuzzySet("VeryNegative", new TrapezoidalFunction(-40, -35, TrapezoidalFunction.EdgeType.Right)); + FuzzySet fsN = new FuzzySet("Negative", new TrapezoidalFunction(-40, -35, -25, -20)); + FuzzySet fsLN = new FuzzySet("LittleNegative", new TrapezoidalFunction(-25, -20, -10, -5)); + FuzzySet fsZero = new FuzzySet("Zero", new TrapezoidalFunction(-10, 5, 5, 10)); + FuzzySet fsLP = new FuzzySet("LittlePositive", new TrapezoidalFunction(5, 10, 20, 25)); + FuzzySet fsP = new FuzzySet("Positive", new TrapezoidalFunction(20, 25, 35, 40)); + FuzzySet fsVP = new FuzzySet("VeryPositive", new TrapezoidalFunction(35, 40, TrapezoidalFunction.EdgeType.Left)); + + // Angle + LinguisticVariable lvAngle = new LinguisticVariable("Angle", -50, 50); + lvAngle.AddLabel(fsVN); + lvAngle.AddLabel(fsN); + lvAngle.AddLabel(fsLN); + lvAngle.AddLabel(fsZero); + lvAngle.AddLabel(fsLP); + lvAngle.AddLabel(fsP); + lvAngle.AddLabel(fsVP); + + // The database + Database fuzzyDB = new Database(); + fuzzyDB.AddVariable(lvFront); + fuzzyDB.AddVariable(lvLeft); + fuzzyDB.AddVariable(lvRight); + fuzzyDB.AddVariable(lvAngle); + + // Creating the inference system + IS = new InferenceSystem(fuzzyDB, new CentroidDefuzzifier(1000)); + + // Going Straight + IS.NewRule("Rule 1", "IF FrontalDistance IS Far THEN Angle IS Zero"); + // Going Straight (if can go anywhere) + IS.NewRule("Rule 2", "IF FrontalDistance IS Far AND RightDistance IS Far AND LeftDistance IS Far THEN Angle IS Zero"); + // Near right wall + IS.NewRule("Rule 3", "IF RightDistance IS Near AND LeftDistance IS Not Near THEN Angle IS LittleNegative"); + // Near left wall + IS.NewRule("Rule 4", "IF RightDistance IS Not Near AND LeftDistance IS Near THEN Angle IS LittlePositive"); + // Near front wall - room at right + IS.NewRule("Rule 5", "IF RightDistance IS Far AND FrontalDistance IS Near THEN Angle IS Positive"); + // Near front wall - room at left + IS.NewRule("Rule 6", "IF LeftDistance IS Far AND FrontalDistance IS Near THEN Angle IS Negative"); + // Near front wall - room at both sides - go right + IS.NewRule("Rule 7", "IF RightDistance IS Far AND LeftDistance IS Far AND FrontalDistance IS Near THEN Angle IS Positive"); + } + + // Run one epoch of the Fuzzy Inference System + private void DoInference() + { + // Setting inputs + IS.SetInput("RightDistance", Convert.ToSingle(txtRight.Text)); + IS.SetInput("LeftDistance", Convert.ToSingle(txtLeft.Text)); + IS.SetInput("FrontalDistance", Convert.ToSingle(txtFront.Text)); + + // Setting outputs + try + { + double NewAngle = IS.Evaluate("Angle"); + txtAngle.Text = NewAngle.ToString("##0.#0"); + Angle += NewAngle; + } + catch (Exception) + { + } + } + + // AGV's terrain drawing + private void pbTerrain_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) + { + pbTerrain.Image = CopyImage(OriginalMap); + LastX = e.X; + LastY = e.Y; + } + + // AGV's terrain drawing + private void pbTerrain_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) + { + Graphics g = Graphics.FromImage(pbTerrain.Image); + + Color c = Color.Yellow; + + if (e.Button == MouseButtons.Left) + c = Color.White; + else if (e.Button == MouseButtons.Right) + c = Color.Black; + + if (c != Color.Yellow) + { + g.FillRectangle(new SolidBrush(c), e.X - 40, e.Y - 40, 80, 80); + + LastX = e.X; + LastY = e.Y; + + g.DrawImage(pbTerrain.Image, 0, 0); + OriginalMap = CopyImage(pbTerrain.Image as Bitmap); + pbTerrain.Refresh(); + g.Dispose(); + } + + } + + // Getting sensors measures + private void GetMeasures() + { + // Getting AGV's position + pbTerrain.Image = CopyImage(OriginalMap); + Bitmap b = pbTerrain.Image as Bitmap; + Point pPos = new Point(pbRobot.Left - pbTerrain.Left + 5, pbRobot.Top - pbTerrain.Top + 5); + + // AGV on the wall + if ((b.GetPixel(pPos.X, pPos.Y).R == 0) && (b.GetPixel(pPos.X, pPos.Y).G == 0) && (b.GetPixel(pPos.X, pPos.Y).B == 0)) + { + if (btnRun.Text != RunLabel) + { + btnRun_Click(btnRun, null); + } + string Msg = "The vehicle is on the solid area!"; + MessageBox.Show(Msg, "Error!"); + throw new Exception(Msg); + } + + // Getting distances + Point pFrontObstacle = GetObstacle(pPos, b, -1, 0); + Point pLeftObstacle = GetObstacle(pPos, b, 1, 90); + Point pRightObstacle = GetObstacle(pPos, b, 1, -90); + + // Showing beams + Graphics g = Graphics.FromImage(b); + if (cbLasers.Checked) + { + g.DrawLine(new Pen(Color.Green, 1), pFrontObstacle, pPos); + g.DrawLine(new Pen(Color.Red, 1), pLeftObstacle, pPos); + g.DrawLine(new Pen(Color.Red, 1), pRightObstacle, pPos); + } + + // Drawing AGV + if (btnRun.Text != RunLabel) + { + g.FillEllipse(new SolidBrush(Color.Navy), pPos.X - 5, pPos.Y - 5, 10, 10); + } + + g.DrawImage(b, 0, 0); + g.Dispose(); + + pbTerrain.Refresh(); + + // Updating distances texts + txtFront.Text = GetDistance(pPos, pFrontObstacle).ToString(); + txtLeft.Text = GetDistance(pPos, pLeftObstacle).ToString(); + txtRight.Text = GetDistance(pPos, pRightObstacle).ToString(); + + } + + // Calculating distances + private int GetDistance(Point p1, Point p2) + { + return (Convert.ToInt32(Math.Sqrt(Math.Pow(p1.X - p2.X, 2) + Math.Pow(p1.Y - p2.Y, 2)))); + } + + // Finding obstacles + private Point GetObstacle(Point Start, Bitmap Map, int Inc, int AngleOffset) + { + Point p = new Point(Start.X, Start.Y); + + double rad = ((Angle + 90 + AngleOffset) * Math.PI) / 180; + int IncX = 0; + int IncY = 0; + int Offset = 0; + + while ((p.X + IncX >= 0) && (p.X + IncX < Map.Width) && (p.Y + IncY >= 0) && (p.Y + IncY < Map.Height)) + { + if ((Map.GetPixel(p.X + IncX, p.Y + IncY).R == 0) && (Map.GetPixel(p.X + IncX, p.Y + IncY).G == 0) && (Map.GetPixel(p.X + IncX, p.Y + IncY).B == 0)) + break; + Offset += Inc; + IncX = Convert.ToInt32(Offset * Math.Cos(rad)); + IncY = Convert.ToInt32(Offset * Math.Sin(rad)); + } + p.X += IncX; + p.Y += IncY; + + return p; + } + + // Copying bitmaps + private Bitmap CopyImage(Bitmap Src) + { + return new Bitmap(Src); + } + + + // Restarting the AGVs simulation + private void btnReset_Click(object sender, System.EventArgs e) + { + Angle = 0; + pbTerrain.Image = new Bitmap(InitialMap); + OriginalMap = new Bitmap(InitialMap); + FirstInference = true; + pbRobot.Location = InitialPos; + txtFront.Text = "0"; + txtLeft.Text = "0"; + txtRight.Text = "0"; + txtAngle.Text = "0,00"; + } + + // Moving the AGV + private void MoveAGV() + { + double rad = ((Angle + 90) * Math.PI) / 180; + int Offset = 0; + int Inc = -4; + + Offset += Inc; + int IncX = Convert.ToInt32(Offset * Math.Cos(rad)); + int IncY = Convert.ToInt32(Offset * Math.Sin(rad)); + + // Leaving the track + if (cbTrajeto.Checked) + { + Graphics g = Graphics.FromImage(OriginalMap); + Point p1 = new Point(pbRobot.Left - pbTerrain.Left + pbRobot.Width / 2, pbRobot.Top - pbTerrain.Top + pbRobot.Height / 2); + Point p2 = new Point(p1.X + IncX, p1.Y + IncY); + g.DrawLine(new Pen(new SolidBrush(Color.Blue)), p1, p2); + g.DrawImage(OriginalMap, 0, 0); + g.Dispose(); + } + + pbRobot.Top = pbRobot.Top + IncY; + pbRobot.Left = pbRobot.Left + IncX; + } + + // Starting and stopping the AGV's moviment a + private void btnRun_Click(object sender, System.EventArgs e) + { + Button b = (sender as Button); + + if (b.Text == RunLabel) + { + b.Text = "&Stop"; + btnStep.Enabled = false; + btnReset.Enabled = false; + txtInterval.Enabled = false; + cbLasers.Enabled = false; + cbTrajeto.Enabled = false; + pbRobot.Hide(); + StartMovement(); + } + else + { + StopMovement(); + b.Text = RunLabel; + btnReset.Enabled = true; + btnStep.Enabled = true; + txtInterval.Enabled = true; + cbLasers.Enabled = true; + cbTrajeto.Enabled = true; + pbRobot.Show(); + pbTerrain.Image = CopyImage(OriginalMap); + pbTerrain.Refresh(); + } + } + + // One step of the AGV + private void button3_Click(object sender, System.EventArgs e) + { + pbRobot.Hide(); + AGVStep(); + pbRobot.Show(); + } + + // Thread for the AGVs movement + private void StartMovement() + { + thMovement = new Thread(new ThreadStart(MoveCycle)); + thMovement.IsBackground = true; + thMovement.Priority = ThreadPriority.AboveNormal; + thMovement.Start(); + } + + // Thread main cycle + private void MoveCycle() + { + try + { + while (Thread.CurrentThread.IsAlive) + { + MethodInvoker mi = new MethodInvoker(AGVStep); + this.BeginInvoke(mi); + Thread.Sleep(Convert.ToInt32(txtInterval.Text)); + } + } + catch (ThreadInterruptedException) + { + } + } + + // One step of the AGV + private void AGVStep() + { + if (FirstInference) GetMeasures(); + + try + { + DoInference(); + MoveAGV(); + GetMeasures(); + } + catch (Exception ex) + { + Debug.WriteLine(ex); + } + } + + // Stop background thread + private void StopMovement() + { + if (thMovement != null) + { + thMovement.Interrupt(); + thMovement = null; + } + } + + // Show About dialog + private void aboutButton_Click(object sender, EventArgs e) + { + AboutForm form = new AboutForm(); + + form.ShowDialog(); + } + } +} diff --git a/Samples/Fuzzy/Robot (Inference)/MainForm.resx b/Samples/Fuzzy/Robot (Inference)/MainForm.resx new file mode 100644 index 0000000000..cc2fd5f21 --- /dev/null +++ b/Samples/Fuzzy/Robot (Inference)/MainForm.resx @@ -0,0 +1,16824 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + Qk12Qg8AAAAAADYAAAAoAAAA9AEAAPQBAAABACAAAAAAAAAAAADEDgAAxA4AAAAAAAAAAAAAAAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA//////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA//////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/w== + + + + + Qk12AQAAAAAAADYAAAAoAAAACgAAAAoAAAABABgAAAAAAAAAAADEDgAAxA4AAAAAAAAAAAAA//////// + ////////gAAAgAAA////////////////AAD///////+AAACAAACAAACAAACAAACAAAD///////8AAP// + /4AAAIAAAIAAAIAAAIAAAIAAAIAAAIAAAP///wAA////gAAAgAAAgAAAgAAAgAAAgAAAgAAAgAAA//// + AACAAACAAACAAACAAACAAACAAACAAACAAACAAACAAAAAAIAAAIAAAIAAAIAAAIAAAIAAAIAAAIAAAIAA + AIAAAAAA////gAAAgAAAgAAAgAAAgAAAgAAAgAAAgAAA////AAD///+AAACAAACAAACAAACAAACAAACA + AACAAAD///8AAP///////4AAAIAAAIAAAIAAAIAAAIAAAP///////wAA////////////////gAAAgAAA + ////////////////AAA= + + + + 64 + + + + AAABAAEAICAQAAEABADoAgAAFgAAACgAAAAgAAAAQAAAAAEABAAAAAAAgAIAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAACAAACAAAAAgIAAgAAAAIAAgACAgAAAwMDAAICAgAAAAP8AAP8AAAD//wD/AAAA/wD/AP// + AAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAO7u4AAAAAAAAAD7 + AAswAA7gAO4AAAAAAAAAs7OzsAAOAAwOAAAAAAAACzs7OzsA7gAADuAAAAAAA7OzAAOzsw4AAA4AAAAA + AA87MABgOzsO4ADuAAAAAABgswAABgOwwO7u4AAAAAAAADsAAAALMAwA4AAAAAAAAACzAAAAA7BgDAAA + AAAAAAALOzAAADs7AAAAAAAAAAAAD7OzAAOzvwAAAAAAAAAAAGALOzs7OwAAAAAAAAAAAAAAYLOzs7Dz + AAOwAAAAAAAAAAD7AA8AOzs7MAAAAAAAAAAGAABgA7Ozs7MAAAAAAAAAAAAADzs7AAs7OwAAAAAAAAAA + AAOzsABgs7MAAAAAAAAAAABgOwAABgswAAAAAAAAAAAAALMAAAADsAAAAAAAAADgAAA7AAAACzAAAAAA + AADu7uADs7AAALOzAAAAAAAO4ADuDzs7AAs7PwAAAAAADgAMDgADs7OzswAAAAAAAO4AAA7gYDs7OzAA + AAAAAAwOAAAOAADzAAPwAAAAAAAADuAA7gAGAABgAAAAAAAAAMDu7uAAAAAAAAAAAAAAAAAMAOAAAAAA + AAAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///9////8H//OeA//gDAH/wAgB/4A + AYP8AAGH+AAAB/gcAA/8HgAf/B4AP/wOBv/4AAf/+AAOf/wAAD//AAA//wAAD/+cAAf/+AAH//gcD//c + Hg//BB4P/gAOB/wAAAf4AAAP+GAAH/BhAD/4AQB/+AOc//wH///+D////7///w== + + + \ No newline at end of file diff --git a/Samples/Fuzzy/Robot (Inference)/Program.cs b/Samples/Fuzzy/Robot (Inference)/Program.cs new file mode 100644 index 0000000000..ef737e5ed --- /dev/null +++ b/Samples/Fuzzy/Robot (Inference)/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Windows.Forms; + +namespace SampleApp +{ + static class Program + { + [STAThread] + static void Main() + { + // if (Environment.OSVersion.Version.Major >= 6) + // SetProcessDPIAware(); + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + + [System.Runtime.InteropServices.DllImport("user32.dll")] + private static extern bool SetProcessDPIAware(); + } +} diff --git a/Samples/Fuzzy/Robot (Inference)/Properties/Resources.Designer.cs b/Samples/Fuzzy/Robot (Inference)/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..7b58e53ee --- /dev/null +++ b/Samples/Fuzzy/Robot (Inference)/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Samples/Fuzzy/Robot (Inference)/Properties/Resources.resx b/Samples/Fuzzy/Robot (Inference)/Properties/Resources.resx new file mode 100644 index 0000000000..7080a7d11 --- /dev/null +++ b/Samples/Fuzzy/Robot (Inference)/Properties/Resources.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Fuzzy/Robot (Inference)/Properties/app.manifest b/Samples/Fuzzy/Robot (Inference)/Properties/app.manifest new file mode 100644 index 0000000000..e4aecf49a --- /dev/null +++ b/Samples/Fuzzy/Robot (Inference)/Properties/app.manifest @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/Fuzzy/Robot (Inference)/Robot (Inference).csproj b/Samples/Fuzzy/Robot (Inference)/Robot (Inference).csproj new file mode 100644 index 0000000000..a12d92063 --- /dev/null +++ b/Samples/Fuzzy/Robot (Inference)/Robot (Inference).csproj @@ -0,0 +1,160 @@ + + + + Local + 9.0.30729 + 2.0 + {BCC446EF-0F10-4FBB-AB37-9A9E0B1CDBAB} + Debug + AnyCPU + + + + + Robot %28Fuzzy Inference%29 + + + JScript + Grid + IE50 + false + WinExe + SampleApp + OnBuildSuccess + SampleApp.Program + + + + + 3.5 + v4.0 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + bin\x86\Debug\ + DEBUG;TRACE + 285212672 + 4096 + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + 285212672 + true + 4096 + x86 + prompt + MinimumRecommendedRules.ruleset + + + + ..\..\..\Release\net40\Accord.dll + + + ..\..\..\Release\net40\Accord.Fuzzy.dll + + + System + + + System.Data + + + System.Drawing + + + System.Windows.Forms + + + System.XML + + + + + + Form + + + AboutForm.cs + + + Code + + + Form + + + + True + True + Resources.resx + + + AboutForm.cs + + + MainForm.cs + Designer + + + Designer + ResXFileCodeGenerator + Resources.Designer.cs + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + PreserveNewest + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/Fuzzy/Robot (Inference)/app.config b/Samples/Fuzzy/Robot (Inference)/app.config new file mode 100644 index 0000000000..57c0f2cbc --- /dev/null +++ b/Samples/Fuzzy/Robot (Inference)/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/Accord.dll.config b/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/FuzzySetSample.sln b/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/FuzzySetSample.sln new file mode 100644 index 0000000000..9580a93d9 --- /dev/null +++ b/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/FuzzySetSample.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C# Express 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FuzzySetSample", "FuzzySetSample.csproj", "{2C079A0D-8F90-4B4E-85AA-CAD45F7E0CAC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2C079A0D-8F90-4B4E-85AA-CAD45F7E0CAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2C079A0D-8F90-4B4E-85AA-CAD45F7E0CAC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2C079A0D-8F90-4B4E-85AA-CAD45F7E0CAC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2C079A0D-8F90-4B4E-85AA-CAD45F7E0CAC}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/MainForm.Designer.cs b/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/MainForm.Designer.cs new file mode 100644 index 0000000000..a7ca9190f --- /dev/null +++ b/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/MainForm.Designer.cs @@ -0,0 +1,146 @@ +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.runFuzzySetTestButton = new System.Windows.Forms.Button(); + this.chart = new AForge.Controls.Chart(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.runLingVarTestButton = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // runFuzzySetTestButton + // + this.runFuzzySetTestButton.Location = new System.Drawing.Point(10, 12); + this.runFuzzySetTestButton.Name = "runFuzzySetTestButton"; + this.runFuzzySetTestButton.Size = new System.Drawing.Size(125, 23); + this.runFuzzySetTestButton.TabIndex = 0; + this.runFuzzySetTestButton.Text = "Run Fuzzy Set Test"; + this.runFuzzySetTestButton.UseVisualStyleBackColor = true; + this.runFuzzySetTestButton.Click += new System.EventHandler(this.runFuzzySetTestButton_Click); + // + // chart + // + this.chart.Location = new System.Drawing.Point(10, 41); + this.chart.Name = "chart"; + this.chart.Size = new System.Drawing.Size(418, 250); + this.chart.TabIndex = 1; + // + // label1 + // + this.label1.BackColor = System.Drawing.Color.LightBlue; + this.label1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Location = new System.Drawing.Point(116, 299); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(100, 23); + this.label1.TabIndex = 2; + this.label1.Text = "Cool"; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // label2 + // + this.label2.BackColor = System.Drawing.Color.LightCoral; + this.label2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.label2.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label2.Location = new System.Drawing.Point(222, 299); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(100, 23); + this.label2.TabIndex = 3; + this.label2.Text = "Warm"; + this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // label3 + // + this.label3.BackColor = System.Drawing.Color.CornflowerBlue; + this.label3.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.label3.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label3.Location = new System.Drawing.Point(10, 299); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(100, 23); + this.label3.TabIndex = 4; + this.label3.Text = "Cold"; + this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // label4 + // + this.label4.BackColor = System.Drawing.Color.Firebrick; + this.label4.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.label4.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label4.Location = new System.Drawing.Point(328, 299); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(100, 23); + this.label4.TabIndex = 5; + this.label4.Text = "Hot"; + this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // runLingVarTestButton + // + this.runLingVarTestButton.Location = new System.Drawing.Point(141, 12); + this.runLingVarTestButton.Name = "runLingVarTestButton"; + this.runLingVarTestButton.Size = new System.Drawing.Size(158, 23); + this.runLingVarTestButton.TabIndex = 6; + this.runLingVarTestButton.Text = "Run Linguistic Variable Test"; + this.runLingVarTestButton.UseVisualStyleBackColor = true; + this.runLingVarTestButton.Click += new System.EventHandler(this.runLingVarTestButton_Click); + // + // Sample + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(435, 332); + this.Controls.Add(this.runLingVarTestButton); + this.Controls.Add(this.label4); + this.Controls.Add(this.label3); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.Controls.Add(this.chart); + this.Controls.Add(this.runFuzzySetTestButton); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.Name = "Sample"; + this.Text = "Fuzzy Sets Sample"; + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button runFuzzySetTestButton; + private AForge.Controls.Chart chart; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Button runLingVarTestButton; + } +} + diff --git a/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/MainForm.cs b/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/MainForm.cs new file mode 100644 index 0000000000..03690dbcd --- /dev/null +++ b/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/MainForm.cs @@ -0,0 +1,127 @@ +// Fyzzy Set sample application +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +using AForge.Fuzzy; +using AForge.Controls; +using AForge; + +namespace SampleApp +{ + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + + chart.RangeX = new Range(0, 50); + chart.AddDataSeries("COLD", Color.CornflowerBlue, Chart.SeriesType.Line, 3, true); + chart.AddDataSeries("COOL", Color.LightBlue, Chart.SeriesType.Line, 3, true); + chart.AddDataSeries("WARM", Color.LightCoral, Chart.SeriesType.Line, 3, true); + chart.AddDataSeries("HOT", Color.Firebrick, Chart.SeriesType.Line, 3, true); + } + + // Testing basic functionality of fuzzy sets + private void runFuzzySetTestButton_Click(object sender, EventArgs e) + { + ClearDataSeries(); + + // create 2 fuzzy sets to represent the Cool and Warm temperatures + FuzzySet fsCool = new FuzzySet("Cool", new TrapezoidalFunction(13, 18, 23, 28)); + FuzzySet fsWarm = new FuzzySet("Warm", new TrapezoidalFunction(23, 28, 33, 38)); + + // get membership of some points to the cool fuzzy set + double[,] coolValues = new double[20, 2]; + for (int i = 10; i < 30; i++) + { + coolValues[i - 10, 0] = i; + coolValues[i - 10, 1] = fsCool.GetMembership(i); + } + + // getting memberships of some points to the warm fuzzy set + double[,] warmValues = new double[20, 2]; + for (int i = 20; i < 40; i++) + { + warmValues[i - 20, 0] = i; + warmValues[i - 20, 1] = fsWarm.GetMembership(i); + } + + // plot membership to a chart + chart.UpdateDataSeries("COOL", coolValues); + chart.UpdateDataSeries("WARM", warmValues); + } + + + // Testing basic functionality of linguistic variables + private void runLingVarTestButton_Click(object sender, EventArgs e) + { + ClearDataSeries(); + + // create a linguistic variable to represent temperature + LinguisticVariable lvTemperature = new LinguisticVariable("Temperature", 0, 80); + + // create the linguistic labels (fuzzy sets) that compose the temperature + FuzzySet fsCold = new FuzzySet("Cold", new TrapezoidalFunction(10, 15, TrapezoidalFunction.EdgeType.Right)); + FuzzySet fsCool = new FuzzySet("Cool", new TrapezoidalFunction(10, 15, 20, 25)); + FuzzySet fsWarm = new FuzzySet("Warm", new TrapezoidalFunction(20, 25, 30, 35)); + FuzzySet fsHot = new FuzzySet("Hot", new TrapezoidalFunction(30, 35, TrapezoidalFunction.EdgeType.Left)); + + // adding labels to the variable + lvTemperature.AddLabel(fsCold); + lvTemperature.AddLabel(fsCool); + lvTemperature.AddLabel(fsWarm); + lvTemperature.AddLabel(fsHot); + + // get membership of some points to the cool fuzzy set + double[][,] chartValues = new double[4][,]; + for (int i = 0; i < 4; i++) + chartValues[i] = new double[160, 2]; + + // showing the shape of the linguistic variable - the shape of its labels memberships from start to end + int j = 0; + for (float x = 0; x < 80; x += 0.5f, j++) + { + double y1 = lvTemperature.GetLabelMembership("Cold", x); + double y2 = lvTemperature.GetLabelMembership("Cool", x); + double y3 = lvTemperature.GetLabelMembership("Warm", x); + double y4 = lvTemperature.GetLabelMembership("Hot", x); + + chartValues[0][j, 0] = x; + chartValues[0][j, 1] = y1; + chartValues[1][j, 0] = x; + chartValues[1][j, 1] = y2; + chartValues[2][j, 0] = x; + chartValues[2][j, 1] = y3; + chartValues[3][j, 0] = x; + chartValues[3][j, 1] = y4; + } + + // plot membership to a chart + chart.UpdateDataSeries("COLD", chartValues[0]); + chart.UpdateDataSeries("COOL", chartValues[1]); + chart.UpdateDataSeries("WARM", chartValues[2]); + chart.UpdateDataSeries("HOT", chartValues[3]); + } + + // Clear all data series data + private void ClearDataSeries() + { + chart.UpdateDataSeries("COLD", null); + chart.UpdateDataSeries("COOL", null); + chart.UpdateDataSeries("WARM", null); + chart.UpdateDataSeries("HOT", null); + } + } +} \ No newline at end of file diff --git a/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/MainForm.resx b/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/MainForm.resx new file mode 100644 index 0000000000..19dc0dd8b --- /dev/null +++ b/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/MainForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/Program.cs b/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/Program.cs new file mode 100644 index 0000000000..d9b26e676 --- /dev/null +++ b/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Windows.Forms; + +namespace SampleApp +{ + static class Program + { + [STAThread] + static void Main() + { + if (Environment.OSVersion.Version.Major >= 6) + SetProcessDPIAware(); + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + + [System.Runtime.InteropServices.DllImport("user32.dll")] + private static extern bool SetProcessDPIAware(); + } +} \ No newline at end of file diff --git a/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/Properties/AssemblyInfo.cs b/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..9729b31c1 --- /dev/null +++ b/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle( "Fuzzy Set Sample" )] +[assembly: AssemblyDescription( "AForge Fuzzy Set Sample" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "AForge" )] +[assembly: AssemblyProduct( "AForge.NET" )] +[assembly: AssemblyCopyright( "AForge © 2008" )] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible( false )] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid( "6a9ab600-5d56-4e13-a8bf-b540838ddba3" )] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion( "1.0.0.0" )] +[assembly: AssemblyFileVersion( "1.0.0.0" )] diff --git a/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/Properties/Resources.Designer.cs b/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..7b58e53ee --- /dev/null +++ b/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Samples/Statistics/Tabular filters/Properties/Resources.resx b/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/Properties/Resources.resx similarity index 100% rename from Samples/Statistics/Tabular filters/Properties/Resources.resx rename to Samples/Fuzzy/Sets (Fuzzy, Linguistic)/Properties/Resources.resx diff --git a/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/Properties/Settings.Designer.cs b/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/Properties/Settings.Designer.cs new file mode 100644 index 0000000000..dbc9e5d22 --- /dev/null +++ b/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Samples/Statistics/Tabular filters/Properties/Settings.settings b/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/Properties/Settings.settings similarity index 100% rename from Samples/Statistics/Tabular filters/Properties/Settings.settings rename to Samples/Fuzzy/Sets (Fuzzy, Linguistic)/Properties/Settings.settings diff --git a/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/Sets (Fuzzy, Linguistic).csproj b/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/Sets (Fuzzy, Linguistic).csproj new file mode 100644 index 0000000000..c9fa4752c --- /dev/null +++ b/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/Sets (Fuzzy, Linguistic).csproj @@ -0,0 +1,143 @@ + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {2C079A0D-8F90-4B4E-85AA-CAD45F7E0CAC} + WinExe + Properties + SampleApp + Sets %28Fuzzy-Linguistic%29 + + + 3.5 + v4.0 + + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + SampleApp.Program + + + + ..\..\..\Release\net40\Accord.dll + + + ..\..\..\Release\net40\Accord.Controls.dll + + + ..\..\..\Release\net40\Accord.Controls.Imaging.dll + + + ..\..\..\Release\net40\Accord.Fuzzy.dll + + + + + + + + + + Form + + + MainForm.cs + + + + + Designer + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + \ No newline at end of file diff --git a/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/app.config b/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/app.config new file mode 100644 index 0000000000..57c0f2cbc --- /dev/null +++ b/Samples/Fuzzy/Sets (Fuzzy, Linguistic)/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Samples/Genetic/Genetic Programming/Accord.dll.config b/Samples/Genetic/Genetic Programming/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Genetic/Genetic Programming/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Genetic/Genetic Programming/Applications/Approximation.cs b/Samples/Genetic/Genetic Programming/Applications/Approximation.cs new file mode 100644 index 0000000000..b27173524 --- /dev/null +++ b/Samples/Genetic/Genetic Programming/Applications/Approximation.cs @@ -0,0 +1,710 @@ +// Approximation (Symbolic Regression) using Genetic Programming and Gene Expression Programming +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +using System; +using System.Drawing; +using System.Collections; +using System.ComponentModel; +using System.Windows.Forms; +using System.Data; +using System.IO; +using System.Threading; + +using AForge; +using AForge.Genetic; +using AForge.Controls; + +namespace SampleApp +{ + + public class Approximation : System.Windows.Forms.Form + { + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.ListView dataList; + private System.Windows.Forms.ColumnHeader xColumnHeader; + private System.Windows.Forms.ColumnHeader yColumnHeader; + private System.Windows.Forms.Button loadDataButton; + private System.Windows.Forms.OpenFileDialog openFileDialog; + /// + /// Required designer variable. + /// + private System.ComponentModel.Container components = null; + private System.Windows.Forms.GroupBox groupBox2; + private AForge.Controls.Chart chart; + private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox populationSizeBox; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.ComboBox selectionBox; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox iterationsBox; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Button startButton; + private System.Windows.Forms.Button stopButton; + private System.Windows.Forms.GroupBox groupBox4; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.TextBox currentIterationBox; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.TextBox currentErrorBox; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.ComboBox functionsSetBox; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.ComboBox geneticMethodBox; + private System.Windows.Forms.GroupBox groupBox5; + private System.Windows.Forms.TextBox solutionBox; + + private double[,] data = null; + + private int populationSize = 100; + private int iterations = 1000; + private int selectionMethod = 0; + private int functionsSet = 0; + private int geneticMethod = 0; + + private Thread workerThread = null; + private volatile bool needToStop = false; + + public Approximation() + { + InitializeComponent(); + + chart.AddDataSeries("data", Color.Red, Chart.SeriesType.Dots, 5); + chart.AddDataSeries("solution", Color.Blue, Chart.SeriesType.Line, 1); + + selectionBox.SelectedIndex = selectionMethod; + functionsSetBox.SelectedIndex = functionsSet; + geneticMethodBox.SelectedIndex = geneticMethod; + UpdateSettings(); + + openFileDialog.InitialDirectory = Path.Combine(Application.StartupPath, "Sample data (approximation)"); + } + + /// + /// Clean up any resources being used. + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (components != null) + { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.dataList = new System.Windows.Forms.ListView(); + this.xColumnHeader = new System.Windows.Forms.ColumnHeader(); + this.yColumnHeader = new System.Windows.Forms.ColumnHeader(); + this.loadDataButton = new System.Windows.Forms.Button(); + this.openFileDialog = new System.Windows.Forms.OpenFileDialog(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.chart = new AForge.Controls.Chart(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.geneticMethodBox = new System.Windows.Forms.ComboBox(); + this.label8 = new System.Windows.Forms.Label(); + this.functionsSetBox = new System.Windows.Forms.ComboBox(); + this.label7 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.iterationsBox = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.selectionBox = new System.Windows.Forms.ComboBox(); + this.label2 = new System.Windows.Forms.Label(); + this.populationSizeBox = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.startButton = new System.Windows.Forms.Button(); + this.stopButton = new System.Windows.Forms.Button(); + this.groupBox4 = new System.Windows.Forms.GroupBox(); + this.currentErrorBox = new System.Windows.Forms.TextBox(); + this.label6 = new System.Windows.Forms.Label(); + this.currentIterationBox = new System.Windows.Forms.TextBox(); + this.label5 = new System.Windows.Forms.Label(); + this.groupBox5 = new System.Windows.Forms.GroupBox(); + this.solutionBox = new System.Windows.Forms.TextBox(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.groupBox3.SuspendLayout(); + this.groupBox4.SuspendLayout(); + this.groupBox5.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.dataList); + this.groupBox1.Controls.Add(this.loadDataButton); + this.groupBox1.Location = new System.Drawing.Point(10, 10); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(180, 310); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Data"; + // + // dataList + // + this.dataList.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.xColumnHeader, + this.yColumnHeader}); + this.dataList.FullRowSelect = true; + this.dataList.GridLines = true; + this.dataList.Location = new System.Drawing.Point(10, 20); + this.dataList.Name = "dataList"; + this.dataList.Size = new System.Drawing.Size(160, 255); + this.dataList.TabIndex = 0; + this.dataList.View = System.Windows.Forms.View.Details; + // + // xColumnHeader + // + this.xColumnHeader.Text = "X"; + // + // yColumnHeader + // + this.yColumnHeader.Text = "Y"; + // + // loadDataButton + // + this.loadDataButton.Location = new System.Drawing.Point(10, 280); + this.loadDataButton.Name = "loadDataButton"; + this.loadDataButton.TabIndex = 1; + this.loadDataButton.Text = "&Load"; + this.loadDataButton.Click += new System.EventHandler(this.loadDataButton_Click); + // + // openFileDialog + // + this.openFileDialog.Filter = "CSV (Comma delimited) (*.csv)|*.csv"; + this.openFileDialog.Title = "Select data file"; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.chart); + this.groupBox2.Location = new System.Drawing.Point(200, 10); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(300, 310); + this.groupBox2.TabIndex = 1; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Function"; + // + // chart + // + this.chart.Location = new System.Drawing.Point(10, 20); + this.chart.Name = "chart"; + this.chart.Size = new System.Drawing.Size(280, 280); + this.chart.TabIndex = 0; + // + // groupBox3 + // + this.groupBox3.Controls.Add(this.geneticMethodBox); + this.groupBox3.Controls.Add(this.label8); + this.groupBox3.Controls.Add(this.functionsSetBox); + this.groupBox3.Controls.Add(this.label7); + this.groupBox3.Controls.Add(this.label4); + this.groupBox3.Controls.Add(this.iterationsBox); + this.groupBox3.Controls.Add(this.label3); + this.groupBox3.Controls.Add(this.selectionBox); + this.groupBox3.Controls.Add(this.label2); + this.groupBox3.Controls.Add(this.populationSizeBox); + this.groupBox3.Controls.Add(this.label1); + this.groupBox3.Location = new System.Drawing.Point(510, 10); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Size = new System.Drawing.Size(185, 198); + this.groupBox3.TabIndex = 2; + this.groupBox3.TabStop = false; + this.groupBox3.Text = "Settings"; + // + // geneticMethodBox + // + this.geneticMethodBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.geneticMethodBox.Items.AddRange(new object[] { + "GP", + "GEP"}); + this.geneticMethodBox.Location = new System.Drawing.Point(110, 95); + this.geneticMethodBox.Name = "geneticMethodBox"; + this.geneticMethodBox.Size = new System.Drawing.Size(65, 21); + this.geneticMethodBox.TabIndex = 7; + // + // label8 + // + this.label8.Location = new System.Drawing.Point(10, 97); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(88, 16); + this.label8.TabIndex = 6; + this.label8.Text = "Genetic method:"; + // + // functionsSetBox + // + this.functionsSetBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.functionsSetBox.Items.AddRange(new object[] { + "Simple", + "Extended"}); + this.functionsSetBox.Location = new System.Drawing.Point(110, 70); + this.functionsSetBox.Name = "functionsSetBox"; + this.functionsSetBox.Size = new System.Drawing.Size(65, 21); + this.functionsSetBox.TabIndex = 5; + // + // label7 + // + this.label7.Location = new System.Drawing.Point(10, 72); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(80, 16); + this.label7.TabIndex = 4; + this.label7.Text = "Functions set:"; + // + // label4 + // + this.label4.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(204))); + this.label4.Location = new System.Drawing.Point(125, 175); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(56, 15); + this.label4.TabIndex = 10; + this.label4.Text = "( 0 - inifinity )"; + // + // iterationsBox + // + this.iterationsBox.Location = new System.Drawing.Point(125, 155); + this.iterationsBox.Name = "iterationsBox"; + this.iterationsBox.Size = new System.Drawing.Size(50, 20); + this.iterationsBox.TabIndex = 9; + this.iterationsBox.Text = ""; + // + // label3 + // + this.label3.Location = new System.Drawing.Point(10, 157); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(60, 16); + this.label3.TabIndex = 8; + this.label3.Text = "Iterations:"; + // + // selectionBox + // + this.selectionBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.selectionBox.Items.AddRange(new object[] { + "Elite", + "Rank", + "Roulette"}); + this.selectionBox.Location = new System.Drawing.Point(110, 45); + this.selectionBox.Name = "selectionBox"; + this.selectionBox.Size = new System.Drawing.Size(65, 21); + this.selectionBox.TabIndex = 3; + // + // label2 + // + this.label2.Location = new System.Drawing.Point(10, 47); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(100, 16); + this.label2.TabIndex = 2; + this.label2.Text = "Selection method:"; + // + // populationSizeBox + // + this.populationSizeBox.Location = new System.Drawing.Point(125, 20); + this.populationSizeBox.Name = "populationSizeBox"; + this.populationSizeBox.Size = new System.Drawing.Size(50, 20); + this.populationSizeBox.TabIndex = 1; + this.populationSizeBox.Text = ""; + // + // label1 + // + this.label1.Location = new System.Drawing.Point(10, 22); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(85, 16); + this.label1.TabIndex = 0; + this.label1.Text = "Population size:"; + // + // startButton + // + this.startButton.Enabled = false; + this.startButton.Location = new System.Drawing.Point(530, 297); + this.startButton.Name = "startButton"; + this.startButton.TabIndex = 3; + this.startButton.Text = "&Start"; + this.startButton.Click += new System.EventHandler(this.startButton_Click); + // + // stopButton + // + this.stopButton.Enabled = false; + this.stopButton.Location = new System.Drawing.Point(620, 297); + this.stopButton.Name = "stopButton"; + this.stopButton.TabIndex = 4; + this.stopButton.Text = "S&top"; + this.stopButton.Click += new System.EventHandler(this.stopButton_Click); + // + // groupBox4 + // + this.groupBox4.Controls.Add(this.currentErrorBox); + this.groupBox4.Controls.Add(this.label6); + this.groupBox4.Controls.Add(this.currentIterationBox); + this.groupBox4.Controls.Add(this.label5); + this.groupBox4.Location = new System.Drawing.Point(510, 216); + this.groupBox4.Name = "groupBox4"; + this.groupBox4.Size = new System.Drawing.Size(185, 75); + this.groupBox4.TabIndex = 5; + this.groupBox4.TabStop = false; + this.groupBox4.Text = "Current iteration"; + // + // currentErrorBox + // + this.currentErrorBox.Location = new System.Drawing.Point(125, 45); + this.currentErrorBox.Name = "currentErrorBox"; + this.currentErrorBox.ReadOnly = true; + this.currentErrorBox.Size = new System.Drawing.Size(50, 20); + this.currentErrorBox.TabIndex = 3; + this.currentErrorBox.Text = ""; + // + // label6 + // + this.label6.Location = new System.Drawing.Point(10, 47); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(70, 16); + this.label6.TabIndex = 2; + this.label6.Text = "Error:"; + // + // currentIterationBox + // + this.currentIterationBox.Location = new System.Drawing.Point(125, 20); + this.currentIterationBox.Name = "currentIterationBox"; + this.currentIterationBox.ReadOnly = true; + this.currentIterationBox.Size = new System.Drawing.Size(50, 20); + this.currentIterationBox.TabIndex = 1; + this.currentIterationBox.Text = ""; + // + // label5 + // + this.label5.Location = new System.Drawing.Point(10, 22); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(70, 16); + this.label5.TabIndex = 0; + this.label5.Text = "Iteration:"; + // + // groupBox5 + // + this.groupBox5.Controls.Add(this.solutionBox); + this.groupBox5.Location = new System.Drawing.Point(10, 330); + this.groupBox5.Name = "groupBox5"; + this.groupBox5.Size = new System.Drawing.Size(685, 50); + this.groupBox5.TabIndex = 6; + this.groupBox5.TabStop = false; + this.groupBox5.Text = "Solution:"; + // + // solutionBox + // + this.solutionBox.Location = new System.Drawing.Point(10, 20); + this.solutionBox.Name = "solutionBox"; + this.solutionBox.ReadOnly = true; + this.solutionBox.Size = new System.Drawing.Size(665, 20); + this.solutionBox.TabIndex = 0; + this.solutionBox.Text = ""; + // + // MainForm + // + this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); + this.ClientSize = new System.Drawing.Size(704, 390); + this.Controls.Add(this.groupBox5); + this.Controls.Add(this.groupBox4); + this.Controls.Add(this.stopButton); + this.Controls.Add(this.startButton); + this.Controls.Add(this.groupBox3); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.Name = "MainForm"; + this.Text = "Approximation (Symbolic Regression) using Genetic Programming and Gene Expression" + + " Programming"; + this.Closing += new System.ComponentModel.CancelEventHandler(this.MainForm_Closing); + this.groupBox1.ResumeLayout(false); + this.groupBox2.ResumeLayout(false); + this.groupBox3.ResumeLayout(false); + this.groupBox4.ResumeLayout(false); + this.groupBox5.ResumeLayout(false); + this.ResumeLayout(false); + + } + #endregion + + + + // Delegates to enable async calls for setting controls properties + private delegate void SetTextCallback(System.Windows.Forms.Control control, string text); + + // Thread safe updating of control's text property + private void SetText(System.Windows.Forms.Control control, string text) + { + if (control.InvokeRequired) + { + SetTextCallback d = new SetTextCallback(SetText); + Invoke(d, new object[] { control, text }); + } + else + { + control.Text = text; + } + } + + // On main form closing + private void MainForm_Closing(object sender, System.ComponentModel.CancelEventArgs e) + { + // check if worker thread is running + if ((workerThread != null) && (workerThread.IsAlive)) + { + needToStop = true; + while (!workerThread.Join(100)) + Application.DoEvents(); + } + } + + // Update settings controls + private void UpdateSettings() + { + populationSizeBox.Text = populationSize.ToString(); + iterationsBox.Text = iterations.ToString(); + } + + // Load data + private void loadDataButton_Click(object sender, System.EventArgs e) + { + // show file selection dialog + if (openFileDialog.ShowDialog() == DialogResult.OK) + { + StreamReader reader = null; + // read maximum 50 points + float[,] tempData = new float[50, 2]; + float minX = float.MaxValue; + float maxX = float.MinValue; + + try + { + // open selected file + reader = File.OpenText(openFileDialog.FileName); + string str = null; + int i = 0; + + // read the data + while ((i < 50) && ((str = reader.ReadLine()) != null)) + { + string[] strs = str.Split(';'); + if (strs.Length == 1) + strs = str.Split(','); + // parse X + tempData[i, 0] = float.Parse(strs[0]); + tempData[i, 1] = float.Parse(strs[1]); + + // search for min value + if (tempData[i, 0] < minX) + minX = tempData[i, 0]; + // search for max value + if (tempData[i, 0] > maxX) + maxX = tempData[i, 0]; + + i++; + } + + // allocate and set data + data = new double[i, 2]; + Array.Copy(tempData, 0, data, 0, i * 2); + } + catch (Exception) + { + MessageBox.Show("Failed reading the file", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + finally + { + // close file + if (reader != null) + reader.Close(); + } + + // update list and chart + UpdateDataListView(); + chart.RangeX = new Range(minX, maxX); + chart.UpdateDataSeries("data", data); + chart.UpdateDataSeries("solution", null); + // enable "Start" button + startButton.Enabled = true; + } + } + + // Update data in list view + private void UpdateDataListView() + { + // remove all current records + dataList.Items.Clear(); + // add new records + for (int i = 0, n = data.GetLength(0); i < n; i++) + { + dataList.Items.Add(data[i, 0].ToString()); + dataList.Items[i].SubItems.Add(data[i, 1].ToString()); + } + } + + // Delegates to enable async calls for setting controls properties + private delegate void EnableCallback(bool enable); + + // Enable/disale controls (safe for threading) + private void EnableControls(bool enable) + { + if (InvokeRequired) + { + EnableCallback d = new EnableCallback(EnableControls); + Invoke(d, new object[] { enable }); + } + else + { + loadDataButton.Enabled = enable; + populationSizeBox.Enabled = enable; + iterationsBox.Enabled = enable; + selectionBox.Enabled = enable; + functionsSetBox.Enabled = enable; + geneticMethodBox.Enabled = enable; + + startButton.Enabled = enable; + stopButton.Enabled = !enable; + } + } + + // On button "Start" + private void startButton_Click(object sender, System.EventArgs e) + { + solutionBox.Text = string.Empty; + + // get population size + try + { + populationSize = Math.Max(10, Math.Min(100, int.Parse(populationSizeBox.Text))); + } + catch + { + populationSize = 40; + } + // iterations + try + { + iterations = Math.Max(0, int.Parse(iterationsBox.Text)); + } + catch + { + iterations = 100; + } + // update settings controls + UpdateSettings(); + + selectionMethod = selectionBox.SelectedIndex; + functionsSet = functionsSetBox.SelectedIndex; + geneticMethod = geneticMethodBox.SelectedIndex; + + // disable all settings controls except "Stop" button + EnableControls(false); + + // run worker thread + needToStop = false; + workerThread = new Thread(new ThreadStart(SearchSolution)); + + workerThread.Start(); + } + + // On button "Stop" + private void stopButton_Click(object sender, System.EventArgs e) + { + // stop worker thread + needToStop = true; + while (!workerThread.Join(100)) + Application.DoEvents(); + workerThread = null; + } + + // Worker thread + void SearchSolution() + { + // create fitness function + SymbolicRegressionFitness fitness = new SymbolicRegressionFitness(data, new double[] { 1, 2, 3, 5, 7 }); + // create gene function + IGPGene gene = (functionsSet == 0) ? + (IGPGene)new SimpleGeneFunction(6) : + (IGPGene)new ExtendedGeneFunction(6); + // create population + Population population = new Population(populationSize, + (geneticMethod == 0) ? + (IChromosome)new GPTreeChromosome(gene) : + (IChromosome)new GEPChromosome(gene, 15), + fitness, + (selectionMethod == 0) ? (ISelectionMethod)new EliteSelection() : + (selectionMethod == 1) ? (ISelectionMethod)new RankSelection() : + (ISelectionMethod)new RouletteWheelSelection() + ); + // iterations + int i = 1; + // solution array + double[,] solution = new double[50, 2]; + double[] input = new double[6] { 0, 1, 2, 3, 5, 7 }; + + // calculate X values to be used with solution function + for (int j = 0; j < 50; j++) + { + solution[j, 0] = chart.RangeX.Min + (double)j * chart.RangeX.Length / 49; + } + + // loop + while (!needToStop) + { + // run one epoch of genetic algorithm + population.RunEpoch(); + + try + { + // get best solution + string bestFunction = population.BestChromosome.ToString(); + + // calculate best function + for (int j = 0; j < 50; j++) + { + input[0] = solution[j, 0]; + solution[j, 1] = PolishExpression.Evaluate(bestFunction, input); + } + chart.UpdateDataSeries("solution", solution); + // calculate error + double error = 0.0; + for (int j = 0, k = data.GetLength(0); j < k; j++) + { + input[0] = data[j, 0]; + error += Math.Abs(data[j, 1] - PolishExpression.Evaluate(bestFunction, input)); + } + + // set current iteration's info + SetText(currentIterationBox, i.ToString()); + SetText(currentErrorBox, error.ToString("F3")); + } + catch + { + // remove any solutions from chart in case of any errors + chart.UpdateDataSeries("solution", null); + } + + // increase current iteration + i++; + + // + if ((iterations != 0) && (i > iterations)) + break; + } + + // show solution + SetText(solutionBox, population.BestChromosome.ToString()); + + // enable settings controls + EnableControls(true); + } + } +} diff --git a/Samples/Genetic/Genetic Programming/Applications/Approximation.resx b/Samples/Genetic/Genetic Programming/Applications/Approximation.resx new file mode 100644 index 0000000000..4d19d9d7b --- /dev/null +++ b/Samples/Genetic/Genetic Programming/Applications/Approximation.resx @@ -0,0 +1,430 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Private + + + 8, 8 + + + True + + + False + + + True + + + Private + + + False + + + Private + + + Private + + + Private + + + Private + + + Private + + + Private + + + False + + + Private + + + Private + + + Private + + + Private + + + 17, 17 + + + Private + + + 8, 8 + + + True + + + False + + + True + + + Private + + + Private + + + False + + + Private + + + Private + + + 8, 8 + + + True + + + False + + + True + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + False + + + Private + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + False + + + Private + + + Private + + + False + + + Private + + + Private + + + Private + + + 8, 8 + + + True + + + False + + + True + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + Private + + + 8, 8 + + + True + + + False + + + Private + + + True + + + Private + + + False + + + Private + + + False + + + False + + + False + + + 8, 8 + + + (Default) + + + True + + + 80 + + + MainForm + + + True + + + Private + + \ No newline at end of file diff --git a/Samples/Genetic/Genetic Programming/Applications/Optimization.cs b/Samples/Genetic/Genetic Programming/Applications/Optimization.cs new file mode 100644 index 0000000000..2daa5d86f --- /dev/null +++ b/Samples/Genetic/Genetic Programming/Applications/Optimization.cs @@ -0,0 +1,650 @@ +// 1D Optimization using Genetic Algorithms +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +using System; +using System.Drawing; +using System.Collections; +using System.ComponentModel; +using System.Windows.Forms; +using System.Data; +using System.Threading; + +using AForge; +using AForge.Genetic; +using AForge.Controls; + +namespace SampleApp +{ + + public class Optimization : System.Windows.Forms.Form + { + private AForge.Controls.Chart chart; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox minXBox; + private System.Windows.Forms.TextBox maxXBox; + private System.Windows.Forms.Label label2; + /// + /// Required designer variable. + /// + private System.ComponentModel.Container components = null; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox populationSizeBox; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.TextBox chromosomeLengthBox; + private System.Windows.Forms.CheckBox onlyBestCheck; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.TextBox iterationsBox; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Button startButton; + private System.Windows.Forms.Button stopButton; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.ComboBox selectionBox; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.ComboBox modeBox; + private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.TextBox currentIterationBox; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.TextBox currentValueBox; + + private UserFunction userFunction = new UserFunction(); + private int populationSize = 40; + private int chromosomeLength = 32; + private int iterations = 100; + private int selectionMethod = 0; + private int optimizationMode = 0; + private bool showOnlyBest = false; + + private Thread workerThread = null; + private volatile bool needToStop = false; + + public Optimization() + { + InitializeComponent(); + + // add data series to chart + chart.AddDataSeries("function", Color.Red, Chart.SeriesType.Line, 1); + chart.AddDataSeries("solution", Color.Blue, Chart.SeriesType.Dots, 5); + UpdateChart(); + + // update controls + minXBox.Text = userFunction.Range.Min.ToString(); + maxXBox.Text = userFunction.Range.Max.ToString(); + selectionBox.SelectedIndex = selectionMethod; + modeBox.SelectedIndex = optimizationMode; + UpdateSettings(); + } + + /// + /// Clean up any resources being used. + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (components != null) + { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.chart = new AForge.Controls.Chart(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.label1 = new System.Windows.Forms.Label(); + this.minXBox = new System.Windows.Forms.TextBox(); + this.maxXBox = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.modeBox = new System.Windows.Forms.ComboBox(); + this.label8 = new System.Windows.Forms.Label(); + this.selectionBox = new System.Windows.Forms.ComboBox(); + this.label7 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.iterationsBox = new System.Windows.Forms.TextBox(); + this.label5 = new System.Windows.Forms.Label(); + this.onlyBestCheck = new System.Windows.Forms.CheckBox(); + this.chromosomeLengthBox = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.populationSizeBox = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.startButton = new System.Windows.Forms.Button(); + this.stopButton = new System.Windows.Forms.Button(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.currentValueBox = new System.Windows.Forms.TextBox(); + this.label10 = new System.Windows.Forms.Label(); + this.currentIterationBox = new System.Windows.Forms.TextBox(); + this.label9 = new System.Windows.Forms.Label(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.groupBox3.SuspendLayout(); + this.SuspendLayout(); + // + // chart + // + this.chart.Location = new System.Drawing.Point(10, 20); + this.chart.Name = "chart"; + this.chart.Size = new System.Drawing.Size(280, 270); + this.chart.TabIndex = 0; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.chart); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.minXBox); + this.groupBox1.Controls.Add(this.maxXBox); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Location = new System.Drawing.Point(10, 10); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(300, 330); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Function"; + // + // label1 + // + this.label1.Location = new System.Drawing.Point(10, 297); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(41, 13); + this.label1.TabIndex = 3; + this.label1.Text = "Range:"; + // + // minXBox + // + this.minXBox.Location = new System.Drawing.Point(60, 295); + this.minXBox.Name = "minXBox"; + this.minXBox.Size = new System.Drawing.Size(50, 20); + this.minXBox.TabIndex = 3; + this.minXBox.Text = ""; + this.minXBox.TextChanged += new System.EventHandler(this.minXBox_TextChanged); + // + // maxXBox + // + this.maxXBox.Location = new System.Drawing.Point(130, 295); + this.maxXBox.Name = "maxXBox"; + this.maxXBox.Size = new System.Drawing.Size(50, 20); + this.maxXBox.TabIndex = 4; + this.maxXBox.Text = ""; + this.maxXBox.TextChanged += new System.EventHandler(this.maxXBox_TextChanged); + // + // label2 + // + this.label2.Location = new System.Drawing.Point(115, 297); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(8, 16); + this.label2.TabIndex = 3; + this.label2.Text = "-"; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.modeBox); + this.groupBox2.Controls.Add(this.label8); + this.groupBox2.Controls.Add(this.selectionBox); + this.groupBox2.Controls.Add(this.label7); + this.groupBox2.Controls.Add(this.label6); + this.groupBox2.Controls.Add(this.iterationsBox); + this.groupBox2.Controls.Add(this.label5); + this.groupBox2.Controls.Add(this.onlyBestCheck); + this.groupBox2.Controls.Add(this.chromosomeLengthBox); + this.groupBox2.Controls.Add(this.label4); + this.groupBox2.Controls.Add(this.populationSizeBox); + this.groupBox2.Controls.Add(this.label3); + this.groupBox2.Location = new System.Drawing.Point(320, 10); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(185, 222); + this.groupBox2.TabIndex = 1; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Settings"; + // + // modeBox + // + this.modeBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.modeBox.Items.AddRange(new object[] { + "Maximize", + "Minimize"}); + this.modeBox.Location = new System.Drawing.Point(110, 95); + this.modeBox.Name = "modeBox"; + this.modeBox.Size = new System.Drawing.Size(65, 21); + this.modeBox.TabIndex = 7; + // + // label8 + // + this.label8.Location = new System.Drawing.Point(10, 97); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(110, 17); + this.label8.TabIndex = 6; + this.label8.Text = "Optimization mode:"; + // + // selectionBox + // + this.selectionBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.selectionBox.Items.AddRange(new object[] { + "Elite", + "Rank", + "Roulette"}); + this.selectionBox.Location = new System.Drawing.Point(110, 70); + this.selectionBox.Name = "selectionBox"; + this.selectionBox.Size = new System.Drawing.Size(65, 21); + this.selectionBox.TabIndex = 5; + // + // label7 + // + this.label7.Location = new System.Drawing.Point(10, 72); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(100, 16); + this.label7.TabIndex = 4; + this.label7.Text = "Selection method:"; + // + // label6 + // + this.label6.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0))); + this.label6.Location = new System.Drawing.Point(125, 175); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(56, 16); + this.label6.TabIndex = 10; + this.label6.Text = "( 0 - inifinity )"; + // + // iterationsBox + // + this.iterationsBox.Location = new System.Drawing.Point(125, 155); + this.iterationsBox.Name = "iterationsBox"; + this.iterationsBox.Size = new System.Drawing.Size(50, 20); + this.iterationsBox.TabIndex = 9; + this.iterationsBox.Text = ""; + // + // label5 + // + this.label5.Location = new System.Drawing.Point(10, 157); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(64, 16); + this.label5.TabIndex = 8; + this.label5.Text = "Iterations:"; + // + // onlyBestCheck + // + this.onlyBestCheck.Location = new System.Drawing.Point(10, 195); + this.onlyBestCheck.Name = "onlyBestCheck"; + this.onlyBestCheck.Size = new System.Drawing.Size(144, 16); + this.onlyBestCheck.TabIndex = 11; + this.onlyBestCheck.Text = "Show only best solution"; + // + // chromosomeLengthBox + // + this.chromosomeLengthBox.Location = new System.Drawing.Point(125, 45); + this.chromosomeLengthBox.Name = "chromosomeLengthBox"; + this.chromosomeLengthBox.Size = new System.Drawing.Size(50, 20); + this.chromosomeLengthBox.TabIndex = 3; + this.chromosomeLengthBox.Text = ""; + // + // label4 + // + this.label4.Location = new System.Drawing.Point(10, 47); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(110, 12); + this.label4.TabIndex = 2; + this.label4.Text = "Chromosome length:"; + // + // populationSizeBox + // + this.populationSizeBox.Location = new System.Drawing.Point(125, 20); + this.populationSizeBox.Name = "populationSizeBox"; + this.populationSizeBox.Size = new System.Drawing.Size(50, 20); + this.populationSizeBox.TabIndex = 1; + this.populationSizeBox.Text = ""; + // + // label3 + // + this.label3.Location = new System.Drawing.Point(10, 22); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(85, 16); + this.label3.TabIndex = 0; + this.label3.Text = "Population size:"; + // + // startButton + // + this.startButton.Location = new System.Drawing.Point(340, 317); + this.startButton.Name = "startButton"; + this.startButton.TabIndex = 3; + this.startButton.Text = "&Start"; + this.startButton.Click += new System.EventHandler(this.startButton_Click); + // + // stopButton + // + this.stopButton.Enabled = false; + this.stopButton.Location = new System.Drawing.Point(430, 317); + this.stopButton.Name = "stopButton"; + this.stopButton.TabIndex = 4; + this.stopButton.Text = "S&top"; + this.stopButton.Click += new System.EventHandler(this.stopButton_Click); + // + // groupBox3 + // + this.groupBox3.Controls.Add(this.currentValueBox); + this.groupBox3.Controls.Add(this.label10); + this.groupBox3.Controls.Add(this.currentIterationBox); + this.groupBox3.Controls.Add(this.label9); + this.groupBox3.Location = new System.Drawing.Point(320, 235); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Size = new System.Drawing.Size(185, 75); + this.groupBox3.TabIndex = 2; + this.groupBox3.TabStop = false; + this.groupBox3.Text = "Current iteration"; + // + // currentValueBox + // + this.currentValueBox.Location = new System.Drawing.Point(125, 45); + this.currentValueBox.Name = "currentValueBox"; + this.currentValueBox.ReadOnly = true; + this.currentValueBox.Size = new System.Drawing.Size(50, 20); + this.currentValueBox.TabIndex = 3; + this.currentValueBox.Text = ""; + // + // label10 + // + this.label10.Location = new System.Drawing.Point(10, 47); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(60, 15); + this.label10.TabIndex = 2; + this.label10.Text = "Value:"; + // + // currentIterationBox + // + this.currentIterationBox.Location = new System.Drawing.Point(125, 20); + this.currentIterationBox.Name = "currentIterationBox"; + this.currentIterationBox.ReadOnly = true; + this.currentIterationBox.Size = new System.Drawing.Size(50, 20); + this.currentIterationBox.TabIndex = 1; + this.currentIterationBox.Text = ""; + // + // label9 + // + this.label9.Location = new System.Drawing.Point(10, 22); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(60, 16); + this.label9.TabIndex = 0; + this.label9.Text = "Iteration:"; + // + // MainForm + // + this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); + this.ClientSize = new System.Drawing.Size(514, 350); + this.Controls.Add(this.groupBox3); + this.Controls.Add(this.stopButton); + this.Controls.Add(this.startButton); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.Name = "MainForm"; + this.Text = "1D Optimization using Genetic Algorithms"; + this.Closing += new System.ComponentModel.CancelEventHandler(this.MainForm_Closing); + this.groupBox1.ResumeLayout(false); + this.groupBox2.ResumeLayout(false); + this.groupBox3.ResumeLayout(false); + this.ResumeLayout(false); + + } + #endregion + + + // Delegates to enable async calls for setting controls properties + private delegate void SetTextCallback(System.Windows.Forms.Control control, string text); + + // Thread safe updating of control's text property + private void SetText(System.Windows.Forms.Control control, string text) + { + if (control.InvokeRequired) + { + SetTextCallback d = new SetTextCallback(SetText); + Invoke(d, new object[] { control, text }); + } + else + { + control.Text = text; + } + } + + // On main form closing + private void MainForm_Closing(object sender, System.ComponentModel.CancelEventArgs e) + { + // check if worker thread is running + if ((workerThread != null) && (workerThread.IsAlive)) + { + needToStop = true; + while (!workerThread.Join(100)) + Application.DoEvents(); + } + } + + // Update settings controls + private void UpdateSettings() + { + populationSizeBox.Text = populationSize.ToString(); + chromosomeLengthBox.Text = chromosomeLength.ToString(); + iterationsBox.Text = iterations.ToString(); + } + + // Update chart + private void UpdateChart() + { + // update chart range + chart.RangeX = userFunction.Range; + + double[,] data = null; + + if (chart.RangeX.Length > 0) + { + // prepare data + data = new double[501, 2]; + + double minX = userFunction.Range.Min; + double length = userFunction.Range.Length; + + for (int i = 0; i <= 500; i++) + { + data[i, 0] = minX + length * i / 500; + data[i, 1] = userFunction.OptimizationFunction(data[i, 0]); + } + } + + // update chart series + chart.UpdateDataSeries("function", data); + } + + // Update min value + private void minXBox_TextChanged(object sender, System.EventArgs e) + { + try + { + userFunction.Range = new Range(float.Parse(minXBox.Text), userFunction.Range.Max); + UpdateChart(); + } + catch + { + } + } + + // Update max value + private void maxXBox_TextChanged(object sender, System.EventArgs e) + { + try + { + userFunction.Range = new Range(userFunction.Range.Min, float.Parse(maxXBox.Text)); + UpdateChart(); + } + catch + { + } + } + + // Delegates to enable async calls for setting controls properties + private delegate void EnableCallback(bool enable); + + // Enable/disale controls (safe for threading) + private void EnableControls(bool enable) + { + if (InvokeRequired) + { + EnableCallback d = new EnableCallback(EnableControls); + Invoke(d, new object[] { enable }); + } + else + { + minXBox.Enabled = enable; + maxXBox.Enabled = enable; + + populationSizeBox.Enabled = enable; + chromosomeLengthBox.Enabled = enable; + iterationsBox.Enabled = enable; + selectionBox.Enabled = enable; + modeBox.Enabled = enable; + onlyBestCheck.Enabled = enable; + + startButton.Enabled = enable; + stopButton.Enabled = !enable; + } + } + + // On "Start" button click + private void startButton_Click(object sender, System.EventArgs e) + { + // get population size + try + { + populationSize = Math.Max(10, Math.Min(100, int.Parse(populationSizeBox.Text))); + } + catch + { + populationSize = 40; + } + // get chromosome length + try + { + chromosomeLength = Math.Max(8, Math.Min(64, int.Parse(chromosomeLengthBox.Text))); + } + catch + { + chromosomeLength = 32; + } + // iterations + try + { + iterations = Math.Max(0, int.Parse(iterationsBox.Text)); + } + catch + { + iterations = 100; + } + // update settings controls + UpdateSettings(); + + selectionMethod = selectionBox.SelectedIndex; + optimizationMode = modeBox.SelectedIndex; + showOnlyBest = onlyBestCheck.Checked; + + // disable all settings controls except "Stop" button + EnableControls(false); + + // run worker thread + needToStop = false; + workerThread = new Thread(new ThreadStart(SearchSolution)); + workerThread.Start(); + } + + // On "Stop" button click + private void stopButton_Click(object sender, System.EventArgs e) + { + // stop worker thread + needToStop = true; + while (!workerThread.Join(100)) + Application.DoEvents(); + workerThread = null; + } + + + // Worker thread + void SearchSolution() + { + // create population + Population population = new Population(populationSize, + new BinaryChromosome(chromosomeLength), + userFunction, + (selectionMethod == 0) ? (ISelectionMethod)new EliteSelection() : + (selectionMethod == 1) ? (ISelectionMethod)new RankSelection() : + (ISelectionMethod)new RouletteWheelSelection() + ); + // set optimization mode + userFunction.Mode = (optimizationMode == 0) ? + OptimizationFunction1D.Modes.Maximization : + OptimizationFunction1D.Modes.Minimization; + // iterations + int i = 1; + // solution + double[,] data = new double[(showOnlyBest) ? 1 : populationSize, 2]; + + + // loop + while (!needToStop) + { + // run one epoch of genetic algorithm + population.RunEpoch(); + + // show current solution + if (showOnlyBest) + { + data[0, 0] = userFunction.Translate(population.BestChromosome); + data[0, 1] = userFunction.OptimizationFunction(data[0, 0]); + } + else + { + for (int j = 0; j < populationSize; j++) + { + data[j, 0] = userFunction.Translate(population[j]); + data[j, 1] = userFunction.OptimizationFunction(data[j, 0]); + } + } + chart.UpdateDataSeries("solution", data); + + // set current iteration's info + SetText(currentIterationBox, i.ToString()); + SetText(currentValueBox, userFunction.Translate(population.BestChromosome).ToString("F3")); + + // increase current iteration + i++; + + // + if ((iterations != 0) && (i > iterations)) + break; + } + + // enable settings controls + EnableControls(true); + } + } + + // Function to optimize + public class UserFunction : OptimizationFunction1D + { + public UserFunction() : base(new Range(0, 255)) { } + + public override double OptimizationFunction(double x) + { + return Math.Cos(x / 23) * Math.Sin(x / 50) + 2; + } + } +} diff --git a/Samples/Genetic/Genetic Programming/Applications/Optimization.resx b/Samples/Genetic/Genetic Programming/Applications/Optimization.resx new file mode 100644 index 0000000000..cd01cc397 --- /dev/null +++ b/Samples/Genetic/Genetic Programming/Applications/Optimization.resx @@ -0,0 +1,391 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Private + + + False + + + Private + + + Private + + + 8, 8 + + + True + + + False + + + True + + + Private + + + False + + + Private + + + Private + + + Private + + + False + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + Private + + + 8, 8 + + + True + + + False + + + True + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + False + + + Private + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + False + + + Private + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + False + + + Private + + + Private + + + False + + + Private + + + Private + + + Private + + + 8, 8 + + + True + + + False + + + True + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + False + + + (Default) + + + False + + + False + + + MainForm + + + 8, 8 + + + True + + + 80 + + + True + + + Private + + \ No newline at end of file diff --git a/Samples/Genetic/Genetic Programming/Applications/SettingsDialog.cs b/Samples/Genetic/Genetic Programming/Applications/SettingsDialog.cs new file mode 100644 index 0000000000..6747d9b6a --- /dev/null +++ b/Samples/Genetic/Genetic Programming/Applications/SettingsDialog.cs @@ -0,0 +1,258 @@ +// Time Series Prediction using Genetic Programming and Gene Expression Programming +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2006-2009 +// andrew.kirillov@aforgenet.com + +using System; +using System.Drawing; +using System.Collections; +using System.ComponentModel; +using System.Windows.Forms; + +namespace SampleApp +{ + + public class SettingsDialog : System.Windows.Forms.Form + { + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox maxInitialLevelBox; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox maxLevelBox; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox headLengthBox; + private System.Windows.Forms.Button okButton; + private System.Windows.Forms.Button cancelButton; + /// + /// Required designer variable. + /// + private System.ComponentModel.Container components = null; + + private int maxInitialTreeLevel = 3; + private int maxTreeLevel = 5; + private int headLength = 20; + + // Max initial tree level property + public int MaxInitialTreeLevel + { + get { return maxInitialTreeLevel; } + set { maxInitialTreeLevel = value; } + } + // Max tree level property + public int MaxTreeLevel + { + get { return maxTreeLevel; } + set { maxTreeLevel = value; } + } + // Head length property + public int HeadLength + { + get { return headLength; } + set { headLength = value; } + } + + + public SettingsDialog() + { + InitializeComponent(); + } + + /// + /// Clean up any resources being used. + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (components != null) + { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.maxLevelBox = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.maxInitialLevelBox = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.headLengthBox = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.okButton = new System.Windows.Forms.Button(); + this.cancelButton = new System.Windows.Forms.Button(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.AddRange(new System.Windows.Forms.Control[] { + this.maxLevelBox, + this.label2, + this.maxInitialLevelBox, + this.label1}); + this.groupBox1.Location = new System.Drawing.Point(10, 10); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(210, 80); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "GP Settings"; + // + // maxLevelBox + // + this.maxLevelBox.Location = new System.Drawing.Point(145, 50); + this.maxLevelBox.Name = "maxLevelBox"; + this.maxLevelBox.Size = new System.Drawing.Size(50, 20); + this.maxLevelBox.TabIndex = 3; + this.maxLevelBox.Text = ""; + // + // label2 + // + this.label2.Location = new System.Drawing.Point(10, 52); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(100, 16); + this.label2.TabIndex = 2; + this.label2.Text = "Max tree level:"; + // + // maxInitialLevelBox + // + this.maxInitialLevelBox.Location = new System.Drawing.Point(145, 20); + this.maxInitialLevelBox.Name = "maxInitialLevelBox"; + this.maxInitialLevelBox.Size = new System.Drawing.Size(50, 20); + this.maxInitialLevelBox.TabIndex = 1; + this.maxInitialLevelBox.Text = ""; + // + // label1 + // + this.label1.Location = new System.Drawing.Point(10, 22); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(135, 16); + this.label1.TabIndex = 0; + this.label1.Text = "Maximum initial tree level:"; + // + // groupBox2 + // + this.groupBox2.Controls.AddRange(new System.Windows.Forms.Control[] { + this.headLengthBox, + this.label3}); + this.groupBox2.Location = new System.Drawing.Point(10, 100); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(210, 50); + this.groupBox2.TabIndex = 1; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "GEP Settings"; + // + // headLengthBox + // + this.headLengthBox.Location = new System.Drawing.Point(145, 20); + this.headLengthBox.Name = "headLengthBox"; + this.headLengthBox.Size = new System.Drawing.Size(50, 20); + this.headLengthBox.TabIndex = 1; + this.headLengthBox.Text = ""; + // + // label3 + // + this.label3.Location = new System.Drawing.Point(10, 22); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(100, 16); + this.label3.TabIndex = 0; + this.label3.Text = "Head length:"; + // + // okButton + // + this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK; + this.okButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.okButton.Location = new System.Drawing.Point(60, 160); + this.okButton.Name = "okButton"; + this.okButton.TabIndex = 2; + this.okButton.Text = "&Ok"; + this.okButton.Click += new System.EventHandler(this.okButton_Click); + // + // cancelButton + // + this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.cancelButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.cancelButton.Location = new System.Drawing.Point(145, 160); + this.cancelButton.Name = "cancelButton"; + this.cancelButton.TabIndex = 3; + this.cancelButton.Text = "&Cancel"; + // + // ExSettingsDialog + // + this.AcceptButton = this.okButton; + this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); + this.CancelButton = this.cancelButton; + this.ClientSize = new System.Drawing.Size(234, 193); + this.Controls.AddRange(new System.Windows.Forms.Control[] { + this.cancelButton, + this.okButton, + this.groupBox2, + this.groupBox1}); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "ExSettingsDialog"; + this.Opacity = 0.800000011920929; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Extended Settings"; + this.Load += new System.EventHandler(this.ExSettingsDialog_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox2.ResumeLayout(false); + this.ResumeLayout(false); + + } + #endregion + + // On form load + private void ExSettingsDialog_Load(object sender, System.EventArgs e) + { + maxInitialLevelBox.Text = maxInitialTreeLevel.ToString(); + maxLevelBox.Text = maxTreeLevel.ToString(); + headLengthBox.Text = headLength.ToString(); + } + + // On "Ok" button click + private void okButton_Click(object sender, System.EventArgs e) + { + // max initial tree level + try + { + maxInitialTreeLevel = Math.Max(1, Math.Min(7, int.Parse(maxInitialLevelBox.Text))); + } + catch + { + maxInitialTreeLevel = 3; + } + // max tree level + try + { + maxTreeLevel = Math.Max(2, Math.Min(9, int.Parse(maxLevelBox.Text))); + } + catch + { + maxTreeLevel = 5; + } + // head length + try + { + headLength = Math.Max(3, Math.Min(50, int.Parse(headLengthBox.Text))); + } + catch + { + headLength = 20; + } + } + } +} diff --git a/Samples/Genetic/Genetic Programming/Applications/SettingsDialog.resx b/Samples/Genetic/Genetic Programming/Applications/SettingsDialog.resx new file mode 100644 index 0000000000..cb0936320 --- /dev/null +++ b/Samples/Genetic/Genetic Programming/Applications/SettingsDialog.resx @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ExSettingsDialog + + + False + + \ No newline at end of file diff --git a/Samples/Genetic/Genetic Programming/Applications/TimeSeries.cs b/Samples/Genetic/Genetic Programming/Applications/TimeSeries.cs new file mode 100644 index 0000000000..2d5eb4aff --- /dev/null +++ b/Samples/Genetic/Genetic Programming/Applications/TimeSeries.cs @@ -0,0 +1,972 @@ +// Time Series Prediction using Genetic Programming and Gene Expression Programming +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +using System; +using System.Drawing; +using System.Collections; +using System.ComponentModel; +using System.Windows.Forms; +using System.Data; +using System.IO; +using System.Threading; + +using AForge; +using AForge.Genetic; +using AForge.Controls; + +namespace SampleApp +{ + + public class TimeSeries : System.Windows.Forms.Form + { + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.ListView dataList; + private System.Windows.Forms.ColumnHeader yColumnHeader; + private System.Windows.Forms.Button loadDataButton; + private System.Windows.Forms.OpenFileDialog openFileDialog; + private System.ComponentModel.IContainer components; + private System.Windows.Forms.GroupBox groupBox2; + private AForge.Controls.Chart chart; + private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox populationSizeBox; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.ComboBox selectionBox; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.ComboBox functionsSetBox; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.ComboBox geneticMethodBox; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.TextBox windowSizeBox; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.TextBox predictionSizeBox; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.TextBox iterationsBox; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.Button startButton; + private System.Windows.Forms.Button stopButton; + private System.Windows.Forms.GroupBox groupBox4; + private System.Windows.Forms.Label label11; + private System.Windows.Forms.TextBox currentIterationBox; + private System.Windows.Forms.Label label12; + private System.Windows.Forms.TextBox currentLearningErrorBox; + private System.Windows.Forms.Label label13; + private System.Windows.Forms.TextBox currentPredictionErrorBox; + private System.Windows.Forms.GroupBox groupBox5; + private System.Windows.Forms.TextBox solutionBox; + private System.Windows.Forms.ColumnHeader estimatedYColumnHeader; + private System.Windows.Forms.Button moreSettingsButton; + private System.Windows.Forms.ToolTip toolTip; + + private double[] data = null; + private double[,] dataToShow = null; + + private int populationSize = 100; + private int iterations = 1000; + private int windowSize = 5; + private int predictionSize = 1; + private int selectionMethod = 0; + private int functionsSet = 0; + private int geneticMethod = 0; + + private int headLength = 20; + + private Thread workerThread = null; + private volatile bool needToStop = false; + + private double[,] windowDelimiter = new double[2, 2] { { 0, 0 }, { 0, 0 } }; + private double[,] predictionDelimiter = new double[2, 2] { { 0, 0 }, { 0, 0 } }; + + public TimeSeries() + { + InitializeComponent(); + + // + chart.AddDataSeries("data", Color.Red, Chart.SeriesType.Dots, 5); + chart.AddDataSeries("solution", Color.Blue, Chart.SeriesType.Line, 1); + chart.AddDataSeries("window", Color.LightGray, Chart.SeriesType.Line, 1, false); + chart.AddDataSeries("prediction", Color.Gray, Chart.SeriesType.Line, 1, false); + + selectionBox.SelectedIndex = selectionMethod; + functionsSetBox.SelectedIndex = functionsSet; + geneticMethodBox.SelectedIndex = geneticMethod; + UpdateSettings(); + + openFileDialog.InitialDirectory = Path.Combine(Application.StartupPath, "Sample data (time series)"); + } + + /// + /// Clean up any resources being used. + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (components != null) + { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.dataList = new System.Windows.Forms.ListView(); + this.yColumnHeader = new System.Windows.Forms.ColumnHeader(); + this.estimatedYColumnHeader = new System.Windows.Forms.ColumnHeader(); + this.loadDataButton = new System.Windows.Forms.Button(); + this.openFileDialog = new System.Windows.Forms.OpenFileDialog(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.chart = new AForge.Controls.Chart(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.moreSettingsButton = new System.Windows.Forms.Button(); + this.label10 = new System.Windows.Forms.Label(); + this.iterationsBox = new System.Windows.Forms.TextBox(); + this.label9 = new System.Windows.Forms.Label(); + this.label8 = new System.Windows.Forms.Label(); + this.predictionSizeBox = new System.Windows.Forms.TextBox(); + this.label7 = new System.Windows.Forms.Label(); + this.windowSizeBox = new System.Windows.Forms.TextBox(); + this.label6 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.geneticMethodBox = new System.Windows.Forms.ComboBox(); + this.label4 = new System.Windows.Forms.Label(); + this.functionsSetBox = new System.Windows.Forms.ComboBox(); + this.label3 = new System.Windows.Forms.Label(); + this.selectionBox = new System.Windows.Forms.ComboBox(); + this.label2 = new System.Windows.Forms.Label(); + this.populationSizeBox = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.startButton = new System.Windows.Forms.Button(); + this.stopButton = new System.Windows.Forms.Button(); + this.groupBox4 = new System.Windows.Forms.GroupBox(); + this.currentPredictionErrorBox = new System.Windows.Forms.TextBox(); + this.label13 = new System.Windows.Forms.Label(); + this.currentLearningErrorBox = new System.Windows.Forms.TextBox(); + this.label12 = new System.Windows.Forms.Label(); + this.currentIterationBox = new System.Windows.Forms.TextBox(); + this.label11 = new System.Windows.Forms.Label(); + this.groupBox5 = new System.Windows.Forms.GroupBox(); + this.solutionBox = new System.Windows.Forms.TextBox(); + this.toolTip = new System.Windows.Forms.ToolTip(this.components); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.groupBox3.SuspendLayout(); + this.groupBox4.SuspendLayout(); + this.groupBox5.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.dataList); + this.groupBox1.Controls.Add(this.loadDataButton); + this.groupBox1.Location = new System.Drawing.Point(10, 10); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(180, 380); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Data"; + // + // dataList + // + this.dataList.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.yColumnHeader, + this.estimatedYColumnHeader}); + this.dataList.FullRowSelect = true; + this.dataList.GridLines = true; + this.dataList.Location = new System.Drawing.Point(10, 20); + this.dataList.Name = "dataList"; + this.dataList.Size = new System.Drawing.Size(160, 315); + this.dataList.TabIndex = 1; + this.dataList.View = System.Windows.Forms.View.Details; + // + // yColumnHeader + // + this.yColumnHeader.Text = "Y:Real"; + this.yColumnHeader.Width = 70; + // + // estimatedYColumnHeader + // + this.estimatedYColumnHeader.Text = "Y:Estimated"; + this.estimatedYColumnHeader.Width = 70; + // + // loadDataButton + // + this.loadDataButton.Location = new System.Drawing.Point(10, 345); + this.loadDataButton.Name = "loadDataButton"; + this.loadDataButton.TabIndex = 1; + this.loadDataButton.Text = "&Load"; + this.loadDataButton.Click += new System.EventHandler(this.loadDataButton_Click); + // + // openFileDialog + // + this.openFileDialog.Filter = "CSV (Comma delimited) (*.csv)|*.csv"; + this.openFileDialog.Title = "Select data file"; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.chart); + this.groupBox2.Location = new System.Drawing.Point(200, 10); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(300, 380); + this.groupBox2.TabIndex = 1; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Function"; + // + // chart + // + this.chart.Location = new System.Drawing.Point(10, 20); + this.chart.Name = "chart"; + this.chart.Size = new System.Drawing.Size(280, 350); + this.chart.TabIndex = 0; + // + // groupBox3 + // + this.groupBox3.Controls.Add(this.moreSettingsButton); + this.groupBox3.Controls.Add(this.label10); + this.groupBox3.Controls.Add(this.iterationsBox); + this.groupBox3.Controls.Add(this.label9); + this.groupBox3.Controls.Add(this.label8); + this.groupBox3.Controls.Add(this.predictionSizeBox); + this.groupBox3.Controls.Add(this.label7); + this.groupBox3.Controls.Add(this.windowSizeBox); + this.groupBox3.Controls.Add(this.label6); + this.groupBox3.Controls.Add(this.label5); + this.groupBox3.Controls.Add(this.geneticMethodBox); + this.groupBox3.Controls.Add(this.label4); + this.groupBox3.Controls.Add(this.functionsSetBox); + this.groupBox3.Controls.Add(this.label3); + this.groupBox3.Controls.Add(this.selectionBox); + this.groupBox3.Controls.Add(this.label2); + this.groupBox3.Controls.Add(this.populationSizeBox); + this.groupBox3.Controls.Add(this.label1); + this.groupBox3.Location = new System.Drawing.Point(510, 10); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Size = new System.Drawing.Size(185, 240); + this.groupBox3.TabIndex = 2; + this.groupBox3.TabStop = false; + this.groupBox3.Text = "Settings"; + // + // moreSettingsButton + // + this.moreSettingsButton.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((System.Byte)(204))); + this.moreSettingsButton.ForeColor = System.Drawing.SystemColors.ControlText; + this.moreSettingsButton.Location = new System.Drawing.Point(10, 220); + this.moreSettingsButton.Name = "moreSettingsButton"; + this.moreSettingsButton.Size = new System.Drawing.Size(25, 15); + this.moreSettingsButton.TabIndex = 17; + this.moreSettingsButton.Text = ">>"; + this.toolTip.SetToolTip(this.moreSettingsButton, "More settings"); + this.moreSettingsButton.Click += new System.EventHandler(this.moreSettingsButton_Click); + // + // label10 + // + this.label10.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0))); + this.label10.Location = new System.Drawing.Point(125, 220); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(58, 14); + this.label10.TabIndex = 16; + this.label10.Text = "( 0 - inifinity )"; + // + // iterationsBox + // + this.iterationsBox.Location = new System.Drawing.Point(125, 200); + this.iterationsBox.Name = "iterationsBox"; + this.iterationsBox.Size = new System.Drawing.Size(50, 20); + this.iterationsBox.TabIndex = 15; + this.iterationsBox.Text = ""; + // + // label9 + // + this.label9.Location = new System.Drawing.Point(10, 202); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(70, 16); + this.label9.TabIndex = 14; + this.label9.Text = "Iterations:"; + // + // label8 + // + this.label8.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; + this.label8.Location = new System.Drawing.Point(10, 190); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(165, 2); + this.label8.TabIndex = 13; + // + // predictionSizeBox + // + this.predictionSizeBox.Location = new System.Drawing.Point(125, 160); + this.predictionSizeBox.Name = "predictionSizeBox"; + this.predictionSizeBox.Size = new System.Drawing.Size(50, 20); + this.predictionSizeBox.TabIndex = 12; + this.predictionSizeBox.Text = ""; + this.predictionSizeBox.TextChanged += new System.EventHandler(this.predictionSizeBox_TextChanged); + // + // label7 + // + this.label7.Location = new System.Drawing.Point(10, 162); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(90, 16); + this.label7.TabIndex = 11; + this.label7.Text = "Prediction size:"; + // + // windowSizeBox + // + this.windowSizeBox.Location = new System.Drawing.Point(125, 135); + this.windowSizeBox.Name = "windowSizeBox"; + this.windowSizeBox.Size = new System.Drawing.Size(50, 20); + this.windowSizeBox.TabIndex = 10; + this.windowSizeBox.Text = ""; + this.windowSizeBox.TextChanged += new System.EventHandler(this.windowSizeBox_TextChanged); + // + // label6 + // + this.label6.Location = new System.Drawing.Point(10, 137); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(80, 16); + this.label6.TabIndex = 9; + this.label6.Text = "Window size:"; + // + // label5 + // + this.label5.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; + this.label5.Location = new System.Drawing.Point(10, 125); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(165, 2); + this.label5.TabIndex = 8; + // + // geneticMethodBox + // + this.geneticMethodBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.geneticMethodBox.Items.AddRange(new object[] { + "GP", + "GEP"}); + this.geneticMethodBox.Location = new System.Drawing.Point(110, 95); + this.geneticMethodBox.Name = "geneticMethodBox"; + this.geneticMethodBox.Size = new System.Drawing.Size(65, 21); + this.geneticMethodBox.TabIndex = 7; + // + // label4 + // + this.label4.Location = new System.Drawing.Point(10, 97); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(100, 16); + this.label4.TabIndex = 6; + this.label4.Text = "Genetic method:"; + // + // functionsSetBox + // + this.functionsSetBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.functionsSetBox.Items.AddRange(new object[] { + "Simple", + "Extended"}); + this.functionsSetBox.Location = new System.Drawing.Point(110, 70); + this.functionsSetBox.Name = "functionsSetBox"; + this.functionsSetBox.Size = new System.Drawing.Size(65, 21); + this.functionsSetBox.TabIndex = 5; + // + // label3 + // + this.label3.Location = new System.Drawing.Point(10, 72); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(100, 16); + this.label3.TabIndex = 4; + this.label3.Text = "Function set:"; + // + // selectionBox + // + this.selectionBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.selectionBox.Items.AddRange(new object[] { + "Elite", + "Rank", + "Roulette"}); + this.selectionBox.Location = new System.Drawing.Point(110, 45); + this.selectionBox.Name = "selectionBox"; + this.selectionBox.Size = new System.Drawing.Size(65, 21); + this.selectionBox.TabIndex = 3; + // + // label2 + // + this.label2.Location = new System.Drawing.Point(10, 47); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(100, 16); + this.label2.TabIndex = 2; + this.label2.Text = "Selection method:"; + // + // populationSizeBox + // + this.populationSizeBox.Location = new System.Drawing.Point(125, 20); + this.populationSizeBox.Name = "populationSizeBox"; + this.populationSizeBox.Size = new System.Drawing.Size(50, 20); + this.populationSizeBox.TabIndex = 1; + this.populationSizeBox.Text = ""; + // + // label1 + // + this.label1.Location = new System.Drawing.Point(10, 22); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(100, 16); + this.label1.TabIndex = 0; + this.label1.Text = "Population size:"; + // + // startButton + // + this.startButton.Enabled = false; + this.startButton.Location = new System.Drawing.Point(535, 364); + this.startButton.Name = "startButton"; + this.startButton.TabIndex = 3; + this.startButton.Text = "&Start"; + this.startButton.Click += new System.EventHandler(this.startButton_Click); + // + // stopButton + // + this.stopButton.Enabled = false; + this.stopButton.Location = new System.Drawing.Point(620, 364); + this.stopButton.Name = "stopButton"; + this.stopButton.TabIndex = 4; + this.stopButton.Text = "S&top"; + this.stopButton.Click += new System.EventHandler(this.stopButton_Click); + // + // groupBox4 + // + this.groupBox4.Controls.Add(this.currentPredictionErrorBox); + this.groupBox4.Controls.Add(this.label13); + this.groupBox4.Controls.Add(this.currentLearningErrorBox); + this.groupBox4.Controls.Add(this.label12); + this.groupBox4.Controls.Add(this.currentIterationBox); + this.groupBox4.Controls.Add(this.label11); + this.groupBox4.Location = new System.Drawing.Point(510, 255); + this.groupBox4.Name = "groupBox4"; + this.groupBox4.Size = new System.Drawing.Size(185, 100); + this.groupBox4.TabIndex = 5; + this.groupBox4.TabStop = false; + this.groupBox4.Text = "Current iteration:"; + // + // currentPredictionErrorBox + // + this.currentPredictionErrorBox.Location = new System.Drawing.Point(125, 70); + this.currentPredictionErrorBox.Name = "currentPredictionErrorBox"; + this.currentPredictionErrorBox.ReadOnly = true; + this.currentPredictionErrorBox.Size = new System.Drawing.Size(50, 20); + this.currentPredictionErrorBox.TabIndex = 5; + this.currentPredictionErrorBox.Text = ""; + // + // label13 + // + this.label13.Location = new System.Drawing.Point(10, 72); + this.label13.Name = "label13"; + this.label13.Size = new System.Drawing.Size(100, 16); + this.label13.TabIndex = 4; + this.label13.Text = "Prediction error:"; + // + // currentLearningErrorBox + // + this.currentLearningErrorBox.Location = new System.Drawing.Point(125, 45); + this.currentLearningErrorBox.Name = "currentLearningErrorBox"; + this.currentLearningErrorBox.ReadOnly = true; + this.currentLearningErrorBox.Size = new System.Drawing.Size(50, 20); + this.currentLearningErrorBox.TabIndex = 3; + this.currentLearningErrorBox.Text = ""; + // + // label12 + // + this.label12.Location = new System.Drawing.Point(10, 47); + this.label12.Name = "label12"; + this.label12.Size = new System.Drawing.Size(80, 16); + this.label12.TabIndex = 2; + this.label12.Text = "Learning error:"; + // + // currentIterationBox + // + this.currentIterationBox.Location = new System.Drawing.Point(125, 20); + this.currentIterationBox.Name = "currentIterationBox"; + this.currentIterationBox.ReadOnly = true; + this.currentIterationBox.Size = new System.Drawing.Size(50, 20); + this.currentIterationBox.TabIndex = 1; + this.currentIterationBox.Text = ""; + // + // label11 + // + this.label11.Location = new System.Drawing.Point(10, 22); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(70, 16); + this.label11.TabIndex = 0; + this.label11.Text = "Iteration:"; + // + // groupBox5 + // + this.groupBox5.Controls.Add(this.solutionBox); + this.groupBox5.Location = new System.Drawing.Point(10, 395); + this.groupBox5.Name = "groupBox5"; + this.groupBox5.Size = new System.Drawing.Size(685, 50); + this.groupBox5.TabIndex = 6; + this.groupBox5.TabStop = false; + this.groupBox5.Text = "Solution"; + // + // solutionBox + // + this.solutionBox.Location = new System.Drawing.Point(10, 20); + this.solutionBox.Name = "solutionBox"; + this.solutionBox.ReadOnly = true; + this.solutionBox.Size = new System.Drawing.Size(665, 20); + this.solutionBox.TabIndex = 0; + this.solutionBox.Text = ""; + // + // MainForm + // + this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); + this.ClientSize = new System.Drawing.Size(704, 455); + this.Controls.Add(this.groupBox5); + this.Controls.Add(this.groupBox4); + this.Controls.Add(this.stopButton); + this.Controls.Add(this.startButton); + this.Controls.Add(this.groupBox3); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.Name = "MainForm"; + this.Text = "Time Series Prediction using Genetic Programming and Gene Expression Programming"; + this.Closing += new System.ComponentModel.CancelEventHandler(this.MainForm_Closing); + this.groupBox1.ResumeLayout(false); + this.groupBox2.ResumeLayout(false); + this.groupBox3.ResumeLayout(false); + this.groupBox4.ResumeLayout(false); + this.groupBox5.ResumeLayout(false); + this.ResumeLayout(false); + + } + #endregion + + + // Delegates to enable async calls for setting controls properties + private delegate void SetTextCallback(System.Windows.Forms.Control control, string text); + private delegate void AddSubItemCallback(System.Windows.Forms.ListView control, int item, string subitemText); + + // Thread safe updating of control's text property + private void SetText(System.Windows.Forms.Control control, string text) + { + if (control.InvokeRequired) + { + SetTextCallback d = new SetTextCallback(SetText); + Invoke(d, new object[] { control, text }); + } + else + { + control.Text = text; + } + } + + // Thread safe adding of subitem to list control + private void AddSubItem(System.Windows.Forms.ListView control, int item, string subitemText) + { + if (control.InvokeRequired) + { + AddSubItemCallback d = new AddSubItemCallback(AddSubItem); + Invoke(d, new object[] { control, item, subitemText }); + } + else + { + control.Items[item].SubItems.Add(subitemText); + } + } + + // On main form closing + private void MainForm_Closing(object sender, System.ComponentModel.CancelEventArgs e) + { + // check if worker thread is running + if ((workerThread != null) && (workerThread.IsAlive)) + { + needToStop = true; + while (!workerThread.Join(100)) + Application.DoEvents(); + } + } + + // Update settings controls + private void UpdateSettings() + { + populationSizeBox.Text = populationSize.ToString(); + iterationsBox.Text = iterations.ToString(); + windowSizeBox.Text = windowSize.ToString(); + predictionSizeBox.Text = predictionSize.ToString(); + } + + // Load data + private void loadDataButton_Click(object sender, System.EventArgs e) + { + // show file selection dialog + if (openFileDialog.ShowDialog() == DialogResult.OK) + { + StreamReader reader = null; + // read maximum 50 points + double[] tempData = new double[50]; + + try + { + // open selected file + reader = File.OpenText(openFileDialog.FileName); + string str = null; + int i = 0; + + // read the data + while ((i < 50) && ((str = reader.ReadLine()) != null)) + { + // parse the value + tempData[i] = double.Parse(str); + + i++; + } + + // allocate and set data + data = new double[i]; + dataToShow = new double[i, 2]; + Array.Copy(tempData, 0, data, 0, i); + for (int j = 0; j < i; j++) + { + dataToShow[j, 0] = j; + dataToShow[j, 1] = data[j]; + } + } + catch (Exception) + { + MessageBox.Show("Failed reading the file", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + finally + { + // close file + if (reader != null) + reader.Close(); + } + + // update list and chart + UpdateDataListView(); + chart.RangeX = new Range(0, data.Length - 1); + chart.UpdateDataSeries("data", dataToShow); + chart.UpdateDataSeries("solution", null); + // set delimiters + UpdateDelimiters(); + // enable "Start" button + startButton.Enabled = true; + } + } + + // Update delimiters on the chart + private void UpdateDelimiters() + { + // window delimiter + windowDelimiter[0, 0] = windowDelimiter[1, 0] = windowSize; + windowDelimiter[0, 1] = chart.RangeY.Min; + windowDelimiter[1, 1] = chart.RangeY.Max; + chart.UpdateDataSeries("window", windowDelimiter); + // prediction delimiter + predictionDelimiter[0, 0] = predictionDelimiter[1, 0] = data.Length - 1 - predictionSize; + predictionDelimiter[0, 1] = chart.RangeY.Min; + predictionDelimiter[1, 1] = chart.RangeY.Max; + chart.UpdateDataSeries("prediction", predictionDelimiter); + } + + // Update data in list view + private void UpdateDataListView() + { + // remove all current records + dataList.Items.Clear(); + // add new records + for (int i = 0, n = data.GetLength(0); i < n; i++) + { + dataList.Items.Add(data[i].ToString()); + } + } + + // Delegates to enable async calls for setting controls properties + private delegate void EnableCallback(bool enable); + + // Enable/disale controls (safe for threading) + private void EnableControls(bool enable) + { + if (InvokeRequired) + { + EnableCallback d = new EnableCallback(EnableControls); + Invoke(d, new object[] { enable }); + } + else + { + + loadDataButton.Enabled = enable; + populationSizeBox.Enabled = enable; + iterationsBox.Enabled = enable; + selectionBox.Enabled = enable; + functionsSetBox.Enabled = enable; + geneticMethodBox.Enabled = enable; + windowSizeBox.Enabled = enable; + predictionSizeBox.Enabled = enable; + + moreSettingsButton.Enabled = enable; + + startButton.Enabled = enable; + stopButton.Enabled = !enable; + } + } + + // On window size changed + private void windowSizeBox_TextChanged(object sender, System.EventArgs e) + { + UpdateWindowSize(); + } + + // On prediction changed + private void predictionSizeBox_TextChanged(object sender, System.EventArgs e) + { + UpdatePredictionSize(); + } + + // Update window size + private void UpdateWindowSize() + { + if (data != null) + { + // get new window size value + try + { + windowSize = Math.Max(1, Math.Min(15, int.Parse(windowSizeBox.Text))); + } + catch + { + windowSize = 5; + } + // check if we have too few data + if (windowSize >= data.Length) + windowSize = 1; + // update delimiters + UpdateDelimiters(); + } + } + + // Update prediction size + private void UpdatePredictionSize() + { + if (data != null) + { + // get new prediction size value + try + { + predictionSize = Math.Max(1, Math.Min(10, int.Parse(predictionSizeBox.Text))); + } + catch + { + predictionSize = 1; + } + // check if we have too few data + if (data.Length - predictionSize - 1 < windowSize) + predictionSize = 1; + // update delimiters + UpdateDelimiters(); + } + } + + // Clear current solution + private void ClearSolution() + { + // remove solution form chart + chart.UpdateDataSeries("solution", null); + // remove it from solution box + solutionBox.Text = string.Empty; + // remove it from data list view + for (int i = 0, n = dataList.Items.Count; i < n; i++) + { + if (dataList.Items[i].SubItems.Count > 1) + dataList.Items[i].SubItems.RemoveAt(1); + } + } + + // On button "Start" + private void startButton_Click(object sender, System.EventArgs e) + { + ClearSolution(); + + // get population size + try + { + populationSize = Math.Max(10, Math.Min(100, int.Parse(populationSizeBox.Text))); + } + catch + { + populationSize = 40; + } + // iterations + try + { + iterations = Math.Max(0, int.Parse(iterationsBox.Text)); + } + catch + { + iterations = 100; + } + // update settings controls + UpdateSettings(); + + selectionMethod = selectionBox.SelectedIndex; + functionsSet = functionsSetBox.SelectedIndex; + geneticMethod = geneticMethodBox.SelectedIndex; + + // disable all settings controls except "Stop" button + EnableControls(false); + + // run worker thread + needToStop = false; + workerThread = new Thread(new ThreadStart(SearchSolution)); + workerThread.Start(); + } + + // On button "Stop" + private void stopButton_Click(object sender, System.EventArgs e) + { + // stop worker thread + needToStop = true; + while (!workerThread.Join(100)) + Application.DoEvents(); + workerThread = null; + } + + // Worker thread + void SearchSolution() + { + // constants + double[] constants = new double[10] { 1, 2, 3, 5, 7, 11, 13, 17, 19, 23 }; + // create fitness function + TimeSeriesPredictionFitness fitness = new TimeSeriesPredictionFitness( + data, windowSize, predictionSize, constants); + // create gene function + IGPGene gene = (functionsSet == 0) ? + (IGPGene)new SimpleGeneFunction(windowSize + constants.Length) : + (IGPGene)new ExtendedGeneFunction(windowSize + constants.Length); + // create population + Population population = new Population(populationSize, + (geneticMethod == 0) ? + (IChromosome)new GPTreeChromosome(gene) : + (IChromosome)new GEPChromosome(gene, headLength), + fitness, + (selectionMethod == 0) ? (ISelectionMethod)new EliteSelection() : + (selectionMethod == 1) ? (ISelectionMethod)new RankSelection() : + (ISelectionMethod)new RouletteWheelSelection() + ); + // iterations + int i = 1; + // solution array + int solutionSize = data.Length - windowSize; + double[,] solution = new double[solutionSize, 2]; + double[] input = new double[windowSize + constants.Length]; + + // calculate X values to be used with solution function + for (int j = 0; j < solutionSize; j++) + { + solution[j, 0] = j + windowSize; + } + // prepare input + Array.Copy(constants, 0, input, windowSize, constants.Length); + + // loop + while (!needToStop) + { + // run one epoch of genetic algorithm + population.RunEpoch(); + + try + { + // get best solution + string bestFunction = population.BestChromosome.ToString(); + + // calculate best function and prediction error + double learningError = 0.0; + double predictionError = 0.0; + // go through all the data + for (int j = 0, n = data.Length - windowSize; j < n; j++) + { + // put values from current window as variables + for (int k = 0, b = j + windowSize - 1; k < windowSize; k++) + { + input[k] = data[b - k]; + } + + // evalue the function + solution[j, 1] = PolishExpression.Evaluate(bestFunction, input); + + // calculate prediction error + if (j >= n - predictionSize) + { + predictionError += Math.Abs(solution[j, 1] - data[windowSize + j]); + } + else + { + learningError += Math.Abs(solution[j, 1] - data[windowSize + j]); + } + } + // update solution on the chart + chart.UpdateDataSeries("solution", solution); + + // set current iteration's info + SetText(currentIterationBox, i.ToString()); + SetText(currentLearningErrorBox, learningError.ToString("F3")); + SetText(currentPredictionErrorBox, predictionError.ToString("F3")); + } + catch + { + // remove any solutions from chart in case of any errors + chart.UpdateDataSeries("solution", null); + } + + + // increase current iteration + i++; + + // + if ((iterations != 0) && (i > iterations)) + break; + } + + // show solution + SetText(solutionBox, population.BestChromosome.ToString()); + for (int j = windowSize, k = 0, n = data.Length; j < n; j++, k++) + { + AddSubItem(dataList, j, solution[k, 1].ToString()); + } + + // enable settings controls + EnableControls(true); + } + + // On "More settings" button click + private void moreSettingsButton_Click(object sender, System.EventArgs e) + { + var settingsDlg = new SettingsDialog(); + + // init the dialog + settingsDlg.MaxInitialTreeLevel = GPTreeChromosome.MaxInitialLevel; + settingsDlg.MaxTreeLevel = GPTreeChromosome.MaxLevel; + settingsDlg.HeadLength = headLength; + + // show the dialog + if (settingsDlg.ShowDialog() == DialogResult.OK) + { + GPTreeChromosome.MaxInitialLevel = settingsDlg.MaxInitialTreeLevel; + GPTreeChromosome.MaxLevel = settingsDlg.MaxTreeLevel; + headLength = settingsDlg.HeadLength; + } + } + } +} diff --git a/Samples/Genetic/Genetic Programming/Applications/TimeSeries.resx b/Samples/Genetic/Genetic Programming/Applications/TimeSeries.resx new file mode 100644 index 0000000000..ccc197687 --- /dev/null +++ b/Samples/Genetic/Genetic Programming/Applications/TimeSeries.resx @@ -0,0 +1,520 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Private + + + 8, 8 + + + False + + + False + + + True + + + Private + + + False + + + Private + + + Private + + + Private + + + Private + + + Private + + + Private + + + False + + + Private + + + Private + + + Private + + + Private + + + 17, 17 + + + Private + + + 8, 8 + + + False + + + False + + + True + + + Private + + + Private + + + False + + + Private + + + Private + + + 8, 8 + + + False + + + False + + + True + + + Private + + + False + + + Private + + + Private + + + False + + + Private + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + False + + + Private + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + False + + + Private + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + False + + + Private + + + Private + + + False + + + Private + + + Private + + + Private + + + 8, 8 + + + False + + + False + + + True + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + Private + + + Private + + + False + + + False + + + Private + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + Private + + + 8, 8 + + + False + + + False + + + True + + + Private + + + Private + + + Private + + + False + + + Private + + + 141, 17 + + + Private + + + False + + + (Default) + + + False + + + False + + + 8, 8 + + + True + + + 81 + + + False + + + MainForm + + + Private + + \ No newline at end of file diff --git a/Samples/Genetic/Genetic Programming/Genetic Programming.csproj b/Samples/Genetic/Genetic Programming/Genetic Programming.csproj new file mode 100644 index 0000000000..9d847c03c --- /dev/null +++ b/Samples/Genetic/Genetic Programming/Genetic Programming.csproj @@ -0,0 +1,217 @@ + + + + Local + 9.0.21022 + 2.0 + {2E6B9575-0C86-4034-8A8E-13C880B69A6F} + Debug + AnyCPU + framework.ico + + + Genetic Programming Samples + + + JScript + Grid + IE50 + false + WinExe + SampleApp + OnBuildSuccess + SampleApp.Program + + + + + 3.5 + v4.0 + false + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true + + + + true + bin\x86\Debug\ + DEBUG;TRACE + 285212672 + 4096 + full + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + bin\x86\Release\ + TRACE + 285212672 + true + 4096 + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + + False + ..\..\..\Release\net40\Accord.dll + + + ..\..\..\Release\net40\Accord.Controls.dll + + + ..\..\..\Release\net40\Accord.Genetic.dll + + + ..\..\..\Release\net40\Accord.IO.dll + + + False + ..\..\..\Release\net40\Accord.Math.dll + + + System + + + 3.5 + + + System.Data + + + System.Drawing + + + System.Windows.Forms + + + System.XML + + + + + Form + + + Form + + + + + Form + + + Form + + + MainForm.cs + + + Form + + + Approximation.cs + Designer + + + Optimization.cs + + + SettingsDialog.cs + + + MainForm.cs + + + TimeSeries.cs + Designer + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 2.0 %28x86%29 + false + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + true + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + PreserveNewest + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/Genetic/Genetic Programming/MainForm.Designer.cs b/Samples/Genetic/Genetic Programming/MainForm.Designer.cs new file mode 100644 index 0000000000..9de86ebf6 --- /dev/null +++ b/Samples/Genetic/Genetic Programming/MainForm.Designer.cs @@ -0,0 +1,92 @@ +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); + this.btnApproximation = new System.Windows.Forms.Button(); + this.btnTimeSeries = new System.Windows.Forms.Button(); + this.btnXOR = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // btnApproximation + // + this.btnApproximation.Location = new System.Drawing.Point(18, 18); + this.btnApproximation.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.btnApproximation.Name = "btnApproximation"; + this.btnApproximation.Size = new System.Drawing.Size(240, 120); + this.btnApproximation.TabIndex = 0; + this.btnApproximation.Text = "Approximation"; + this.btnApproximation.UseVisualStyleBackColor = true; + this.btnApproximation.Click += new System.EventHandler(this.btnApproximation_Click); + // + // btnTimeSeries + // + this.btnTimeSeries.Location = new System.Drawing.Point(267, 18); + this.btnTimeSeries.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.btnTimeSeries.Name = "btnTimeSeries"; + this.btnTimeSeries.Size = new System.Drawing.Size(240, 120); + this.btnTimeSeries.TabIndex = 0; + this.btnTimeSeries.Text = "Time-Series"; + this.btnTimeSeries.UseVisualStyleBackColor = true; + this.btnTimeSeries.Click += new System.EventHandler(this.btnTimeSeries_Click); + // + // btnXOR + // + this.btnXOR.Location = new System.Drawing.Point(516, 18); + this.btnXOR.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.btnXOR.Name = "btnXOR"; + this.btnXOR.Size = new System.Drawing.Size(240, 120); + this.btnXOR.TabIndex = 0; + this.btnXOR.Text = "Optimization"; + this.btnXOR.UseVisualStyleBackColor = true; + this.btnXOR.Click += new System.EventHandler(this.btnOptimization_Click); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(776, 154); + this.Controls.Add(this.btnXOR); + this.Controls.Add(this.btnTimeSeries); + this.Controls.Add(this.btnApproximation); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.Name = "MainForm"; + this.Text = "Genetic Programming sample applications"; + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button btnApproximation; + private System.Windows.Forms.Button btnTimeSeries; + private System.Windows.Forms.Button btnXOR; + } +} \ No newline at end of file diff --git a/Samples/Genetic/Genetic Programming/MainForm.cs b/Samples/Genetic/Genetic Programming/MainForm.cs new file mode 100644 index 0000000000..0b2ef5b75 --- /dev/null +++ b/Samples/Genetic/Genetic Programming/MainForm.cs @@ -0,0 +1,60 @@ +using System; +using System.Windows.Forms; + +namespace SampleApp +{ + /// + /// Genetic Programming multiple sample applications. + /// + /// + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + } + + + /// + /// Launches the approximation sample application. + /// + /// + private void btnApproximation_Click(object sender, EventArgs e) + { + launch(new Approximation()); + } + + /// + /// Launches the time-series sample application. + /// + /// + private void btnTimeSeries_Click(object sender, EventArgs e) + { + launch(new TimeSeries()); + } + + /// + /// Launches the optimization sample application. + /// + /// + private void btnOptimization_Click(object sender, EventArgs e) + { + launch(new Optimization()); + } + + + + + private void launch(Form form) + { + form.Show(); + form.FormClosed += new FormClosedEventHandler(form_FormClosed); + WindowState = FormWindowState.Minimized; + } + + void form_FormClosed(object sender, FormClosedEventArgs e) + { + WindowState = FormWindowState.Normal; + } + } +} diff --git a/Samples/Statistics/Tabular filters/MainForm.resx b/Samples/Genetic/Genetic Programming/MainForm.resx similarity index 76% rename from Samples/Statistics/Tabular filters/MainForm.resx rename to Samples/Genetic/Genetic Programming/MainForm.resx index 46c31b2e7..dc0a44401 100644 --- a/Samples/Statistics/Tabular filters/MainForm.resx +++ b/Samples/Genetic/Genetic Programming/MainForm.resx @@ -1,4 +1,4 @@ - + + + + + + diff --git a/Samples/Genetic/Travelling Salesman (GP)/App.ico b/Samples/Genetic/Travelling Salesman (GP)/App.ico new file mode 100644 index 0000000000..3a5525fd7 Binary files /dev/null and b/Samples/Genetic/Travelling Salesman (GP)/App.ico differ diff --git a/Samples/Genetic/Travelling Salesman (GP)/AssemblyInfo.cs b/Samples/Genetic/Travelling Salesman (GP)/AssemblyInfo.cs new file mode 100644 index 0000000000..817c0f7cc --- /dev/null +++ b/Samples/Genetic/Travelling Salesman (GP)/AssemblyInfo.cs @@ -0,0 +1,59 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle( "Genetic TSP" )] +[assembly: AssemblyDescription( "Genetic TSP sample" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "AForge" )] +[assembly: AssemblyProduct( "AForge.NET" )] +[assembly: AssemblyCopyright( "AForge 2008" )] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion( "2.0.0.0" )] +[assembly: AssemblyFileVersion( "2.0.0.0" )] + +// +// In order to sign your assembly you must specify a key to use. Refer to the +// Microsoft .NET Framework documentation for more information on assembly signing. +// +// Use the attributes below to control which key is used for signing. +// +// Notes: +// (*) If no key is specified, the assembly is not signed. +// (*) KeyName refers to a key that has been installed in the Crypto Service +// Provider (CSP) on your machine. KeyFile refers to a file which contains +// a key. +// (*) If the KeyFile and the KeyName values are both specified, the +// following processing occurs: +// (1) If the KeyName can be found in the CSP, that key is used. +// (2) If the KeyName does not exist and the KeyFile does exist, the key +// in the KeyFile is installed into the CSP and used. +// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. +// When specifying the KeyFile, the location of the KeyFile should be +// relative to the project output directory which is +// %Project Directory%\obj\. For example, if your KeyFile is +// located in the project directory, you would specify the AssemblyKeyFile +// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] +// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework +// documentation for more information on this. +// +[assembly: AssemblyDelaySign( false )] +[assembly: AssemblyKeyFile( "" )] +[assembly: AssemblyKeyName( "" )] diff --git a/Samples/Genetic/Travelling Salesman (GP)/MainForm.cs b/Samples/Genetic/Travelling Salesman (GP)/MainForm.cs new file mode 100644 index 0000000000..1ba9bcf11 --- /dev/null +++ b/Samples/Genetic/Travelling Salesman (GP)/MainForm.cs @@ -0,0 +1,558 @@ +// Traveling Salesman Problem using Genetic Algorithms +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +using System; +using System.Drawing; +using System.Collections; +using System.ComponentModel; +using System.Windows.Forms; +using System.Data; +using System.Threading; + +using AForge; +using AForge.Genetic; +using AForge.Controls; + +namespace SampleApp +{ + + public class MainForm : System.Windows.Forms.Form + { + private System.Windows.Forms.GroupBox groupBox1; + private AForge.Controls.Chart mapControl; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox citiesCountBox; + private System.Windows.Forms.Button generateMapButton; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox populationSizeBox; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.ComboBox selectionBox; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.TextBox iterationsBox; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.Button startButton; + private System.Windows.Forms.Button stopButton; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.TextBox currentIterationBox; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.TextBox pathLengthBox; + private System.Windows.Forms.CheckBox greedyCrossoverBox; + /// + /// Required designer variable. + /// + private System.ComponentModel.Container components = null; + + private int citiesCount = 20; + private int populationSize = 40; + private int iterations = 100; + private int selectionMethod = 0; + private bool greedyCrossover = true; + + private double[,] map = null; + + private Thread workerThread = null; + private volatile bool needToStop = false; + + // Constructor + public MainForm() + { + // + // Required for Windows Form Designer support + // + InitializeComponent(); + + // set up map control + mapControl.RangeX = new Range(0, 1000); + mapControl.RangeY = new Range(0, 1000); + mapControl.AddDataSeries("map", Color.Red, Chart.SeriesType.Dots, 5, false); + mapControl.AddDataSeries("path", Color.Blue, Chart.SeriesType.Line, 1, false); + + // + selectionBox.SelectedIndex = selectionMethod; + greedyCrossoverBox.Checked = greedyCrossover; + UpdateSettings(); + GenerateMap(); + } + + /// + /// Clean up any resources being used. + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (components != null) + { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.generateMapButton = new System.Windows.Forms.Button(); + this.citiesCountBox = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.mapControl = new AForge.Controls.Chart(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.greedyCrossoverBox = new System.Windows.Forms.CheckBox(); + this.label5 = new System.Windows.Forms.Label(); + this.iterationsBox = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.selectionBox = new System.Windows.Forms.ComboBox(); + this.label3 = new System.Windows.Forms.Label(); + this.populationSizeBox = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.pathLengthBox = new System.Windows.Forms.TextBox(); + this.label7 = new System.Windows.Forms.Label(); + this.currentIterationBox = new System.Windows.Forms.TextBox(); + this.label6 = new System.Windows.Forms.Label(); + this.startButton = new System.Windows.Forms.Button(); + this.stopButton = new System.Windows.Forms.Button(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.groupBox3.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.generateMapButton); + this.groupBox1.Controls.Add(this.citiesCountBox); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.mapControl); + this.groupBox1.Location = new System.Drawing.Point(16, 15); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(480, 497); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Map"; + // + // generateMapButton + // + this.generateMapButton.Location = new System.Drawing.Point(176, 452); + this.generateMapButton.Name = "generateMapButton"; + this.generateMapButton.Size = new System.Drawing.Size(120, 32); + this.generateMapButton.TabIndex = 3; + this.generateMapButton.Text = "&Generate"; + this.generateMapButton.Click += new System.EventHandler(this.generateMapButton_Click); + // + // citiesCountBox + // + this.citiesCountBox.Location = new System.Drawing.Point(80, 453); + this.citiesCountBox.Name = "citiesCountBox"; + this.citiesCountBox.Size = new System.Drawing.Size(80, 26); + this.citiesCountBox.TabIndex = 2; + // + // label1 + // + this.label1.Location = new System.Drawing.Point(16, 456); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(64, 23); + this.label1.TabIndex = 1; + this.label1.Text = "Cities:"; + // + // mapControl + // + this.mapControl.Location = new System.Drawing.Point(16, 29); + this.mapControl.Name = "mapControl"; + this.mapControl.RangeX = ((AForge.Range)(resources.GetObject("mapControl.RangeX"))); + this.mapControl.RangeY = ((AForge.Range)(resources.GetObject("mapControl.RangeY"))); + this.mapControl.Size = new System.Drawing.Size(448, 409); + this.mapControl.TabIndex = 0; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.greedyCrossoverBox); + this.groupBox2.Controls.Add(this.label5); + this.groupBox2.Controls.Add(this.iterationsBox); + this.groupBox2.Controls.Add(this.label4); + this.groupBox2.Controls.Add(this.selectionBox); + this.groupBox2.Controls.Add(this.label3); + this.groupBox2.Controls.Add(this.populationSizeBox); + this.groupBox2.Controls.Add(this.label2); + this.groupBox2.Location = new System.Drawing.Point(512, 15); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(296, 328); + this.groupBox2.TabIndex = 1; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Settings"; + // + // greedyCrossoverBox + // + this.greedyCrossoverBox.Location = new System.Drawing.Point(16, 102); + this.greedyCrossoverBox.Name = "greedyCrossoverBox"; + this.greedyCrossoverBox.Size = new System.Drawing.Size(192, 35); + this.greedyCrossoverBox.TabIndex = 7; + this.greedyCrossoverBox.Text = "Greedy crossover"; + // + // label5 + // + this.label5.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label5.Location = new System.Drawing.Point(200, 292); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(93, 22); + this.label5.TabIndex = 6; + this.label5.Text = "( 0 - inifinity )"; + // + // iterationsBox + // + this.iterationsBox.Location = new System.Drawing.Point(200, 263); + this.iterationsBox.Name = "iterationsBox"; + this.iterationsBox.Size = new System.Drawing.Size(80, 26); + this.iterationsBox.TabIndex = 5; + // + // label4 + // + this.label4.Location = new System.Drawing.Point(16, 266); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(96, 23); + this.label4.TabIndex = 4; + this.label4.Text = "Iterations:"; + // + // selectionBox + // + this.selectionBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.selectionBox.Items.AddRange(new object[] { + "Elite", + "Rank", + "Roulette"}); + this.selectionBox.Location = new System.Drawing.Point(176, 66); + this.selectionBox.Name = "selectionBox"; + this.selectionBox.Size = new System.Drawing.Size(104, 28); + this.selectionBox.TabIndex = 3; + // + // label3 + // + this.label3.Location = new System.Drawing.Point(16, 69); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(160, 23); + this.label3.TabIndex = 2; + this.label3.Text = "Selection method:"; + // + // populationSizeBox + // + this.populationSizeBox.Location = new System.Drawing.Point(200, 29); + this.populationSizeBox.Name = "populationSizeBox"; + this.populationSizeBox.Size = new System.Drawing.Size(80, 26); + this.populationSizeBox.TabIndex = 1; + // + // label2 + // + this.label2.Location = new System.Drawing.Point(16, 32); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(144, 24); + this.label2.TabIndex = 0; + this.label2.Text = "Population size:"; + // + // groupBox3 + // + this.groupBox3.Controls.Add(this.pathLengthBox); + this.groupBox3.Controls.Add(this.label7); + this.groupBox3.Controls.Add(this.currentIterationBox); + this.groupBox3.Controls.Add(this.label6); + this.groupBox3.Location = new System.Drawing.Point(512, 351); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Size = new System.Drawing.Size(296, 109); + this.groupBox3.TabIndex = 2; + this.groupBox3.TabStop = false; + this.groupBox3.Text = "Current iteration"; + // + // pathLengthBox + // + this.pathLengthBox.Location = new System.Drawing.Point(200, 66); + this.pathLengthBox.Name = "pathLengthBox"; + this.pathLengthBox.ReadOnly = true; + this.pathLengthBox.Size = new System.Drawing.Size(80, 26); + this.pathLengthBox.TabIndex = 3; + // + // label7 + // + this.label7.Location = new System.Drawing.Point(16, 69); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(128, 23); + this.label7.TabIndex = 2; + this.label7.Text = "Path length:"; + // + // currentIterationBox + // + this.currentIterationBox.Location = new System.Drawing.Point(200, 29); + this.currentIterationBox.Name = "currentIterationBox"; + this.currentIterationBox.ReadOnly = true; + this.currentIterationBox.Size = new System.Drawing.Size(80, 26); + this.currentIterationBox.TabIndex = 1; + // + // label6 + // + this.label6.Location = new System.Drawing.Point(16, 32); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(80, 24); + this.label6.TabIndex = 0; + this.label6.Text = "Iteration:"; + // + // startButton + // + this.startButton.Location = new System.Drawing.Point(544, 475); + this.startButton.Name = "startButton"; + this.startButton.Size = new System.Drawing.Size(120, 34); + this.startButton.TabIndex = 3; + this.startButton.Text = "&Start"; + this.startButton.Click += new System.EventHandler(this.startButton_Click); + // + // stopButton + // + this.stopButton.Enabled = false; + this.stopButton.Location = new System.Drawing.Point(688, 475); + this.stopButton.Name = "stopButton"; + this.stopButton.Size = new System.Drawing.Size(120, 34); + this.stopButton.TabIndex = 4; + this.stopButton.Text = "S&top"; + this.stopButton.Click += new System.EventHandler(this.stopButton_Click); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(824, 530); + this.Controls.Add(this.stopButton); + this.Controls.Add(this.startButton); + this.Controls.Add(this.groupBox3); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.Name = "MainForm"; + this.Text = "Traveling Salesman Problem using Genetic Algorithms"; + this.Closing += new System.ComponentModel.CancelEventHandler(this.MainForm_Closing); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.groupBox3.ResumeLayout(false); + this.groupBox3.PerformLayout(); + this.ResumeLayout(false); + + } + #endregion + + // Delegates to enable async calls for setting controls properties + private delegate void SetTextCallback(System.Windows.Forms.Control control, string text); + + // Thread safe updating of control's text property + private void SetText(System.Windows.Forms.Control control, string text) + { + if (control.InvokeRequired) + { + SetTextCallback d = new SetTextCallback(SetText); + Invoke(d, new object[] { control, text }); + } + else + { + control.Text = text; + } + } + + // On main form closing + private void MainForm_Closing(object sender, System.ComponentModel.CancelEventArgs e) + { + // check if worker thread is running + if ((workerThread != null) && (workerThread.IsAlive)) + { + needToStop = true; + while (!workerThread.Join(100)) + Application.DoEvents(); + } + } + + // Update settings controls + private void UpdateSettings() + { + citiesCountBox.Text = citiesCount.ToString(); + populationSizeBox.Text = populationSize.ToString(); + iterationsBox.Text = iterations.ToString(); + } + + // Delegates to enable async calls for setting controls properties + private delegate void EnableCallback(bool enable); + + // Enable/disale controls (safe for threading) + private void EnableControls(bool enable) + { + if (InvokeRequired) + { + EnableCallback d = new EnableCallback(EnableControls); + Invoke(d, new object[] { enable }); + } + else + { + citiesCountBox.Enabled = enable; + populationSizeBox.Enabled = enable; + iterationsBox.Enabled = enable; + selectionBox.Enabled = enable; + + generateMapButton.Enabled = enable; + + startButton.Enabled = enable; + stopButton.Enabled = !enable; + } + } + + // Generate new map for the Traivaling Salesman problem + private void GenerateMap() + { + Random rand = new Random((int)DateTime.Now.Ticks); + + // create coordinates array + map = new double[citiesCount, 2]; + + for (int i = 0; i < citiesCount; i++) + { + map[i, 0] = rand.Next(1001); + map[i, 1] = rand.Next(1001); + } + + // set the map + mapControl.UpdateDataSeries("map", map); + // erase path if it is + mapControl.UpdateDataSeries("path", null); + } + + // On "Generate" button click - generate map + private void generateMapButton_Click(object sender, System.EventArgs e) + { + // get cities count + try + { + citiesCount = Math.Max(5, Math.Min(50, int.Parse(citiesCountBox.Text))); + } + catch + { + citiesCount = 20; + } + citiesCountBox.Text = citiesCount.ToString(); + + // regenerate map + GenerateMap(); + } + + // On "Start" button click + private void startButton_Click(object sender, System.EventArgs e) + { + // get population size + try + { + populationSize = Math.Max(10, Math.Min(100, int.Parse(populationSizeBox.Text))); + } + catch + { + populationSize = 40; + } + // iterations + try + { + iterations = Math.Max(0, int.Parse(iterationsBox.Text)); + } + catch + { + iterations = 100; + } + // update settings controls + UpdateSettings(); + + selectionMethod = selectionBox.SelectedIndex; + greedyCrossover = greedyCrossoverBox.Checked; + + // disable all settings controls except "Stop" button + EnableControls(false); + + // run worker thread + needToStop = false; + workerThread = new Thread(new ThreadStart(SearchSolution)); + workerThread.Start(); + } + + // On "Stop" button click + private void stopButton_Click(object sender, System.EventArgs e) + { + // stop worker thread + if (workerThread != null) + { + needToStop = true; + while (!workerThread.Join(100)) + Application.DoEvents(); + workerThread = null; + } + } + + // Worker thread + void SearchSolution() + { + // create fitness function + TSPFitnessFunction fitnessFunction = new TSPFitnessFunction(map); + + // create population + Population population = new Population(populationSize, + (greedyCrossover) ? new TSPChromosome(map) : new PermutationChromosome(citiesCount), + fitnessFunction, + (selectionMethod == 0) ? (ISelectionMethod)new EliteSelection() : + (selectionMethod == 1) ? (ISelectionMethod)new RankSelection() : + (ISelectionMethod)new RouletteWheelSelection() + ); + + // iterations + int i = 1; + + // path + double[,] path = new double[citiesCount + 1, 2]; + + // loop + while (!needToStop) + { + // run one epoch of genetic algorithm + population.RunEpoch(); + + // display current path + ushort[] bestValue = ((PermutationChromosome)population.BestChromosome).Value; + + for (int j = 0; j < citiesCount; j++) + { + path[j, 0] = map[bestValue[j], 0]; + path[j, 1] = map[bestValue[j], 1]; + } + path[citiesCount, 0] = map[bestValue[0], 0]; + path[citiesCount, 1] = map[bestValue[0], 1]; + + mapControl.UpdateDataSeries("path", path); + + // set current iteration's info + SetText(currentIterationBox, i.ToString()); + SetText(pathLengthBox, fitnessFunction.PathLength(population.BestChromosome).ToString()); + + // increase current iteration + i++; + + // + if ((iterations != 0) && (i > iterations)) + break; + } + + // enable settings controls + EnableControls(true); + } + } +} diff --git a/Samples/Statistics/Tabular filters/TableSelectDialog.resx b/Samples/Genetic/Travelling Salesman (GP)/MainForm.resx similarity index 100% rename from Samples/Statistics/Tabular filters/TableSelectDialog.resx rename to Samples/Genetic/Travelling Salesman (GP)/MainForm.resx diff --git a/Samples/Genetic/Travelling Salesman (GP)/Program.cs b/Samples/Genetic/Travelling Salesman (GP)/Program.cs new file mode 100644 index 0000000000..316268492 --- /dev/null +++ b/Samples/Genetic/Travelling Salesman (GP)/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Windows.Forms; + +namespace SampleApp +{ + static class Program + { + [STAThread] + static void Main() + { + if (Environment.OSVersion.Version.Major >= 6) + SetProcessDPIAware(); + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + + [System.Runtime.InteropServices.DllImport("user32.dll")] + private static extern bool SetProcessDPIAware(); + } +} diff --git a/Samples/Genetic/Travelling Salesman (GP)/TSP.sln b/Samples/Genetic/Travelling Salesman (GP)/TSP.sln new file mode 100644 index 0000000000..6678dfaee --- /dev/null +++ b/Samples/Genetic/Travelling Salesman (GP)/TSP.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C# Express 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TSP", "TSP.csproj", "{DEC346FD-C496-4B3E-A0E9-60AE011E3C49}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {DEC346FD-C496-4B3E-A0E9-60AE011E3C49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DEC346FD-C496-4B3E-A0E9-60AE011E3C49}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DEC346FD-C496-4B3E-A0E9-60AE011E3C49}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DEC346FD-C496-4B3E-A0E9-60AE011E3C49}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/Genetic/Travelling Salesman (GP)/TSPChromosome.cs b/Samples/Genetic/Travelling Salesman (GP)/TSPChromosome.cs new file mode 100644 index 0000000000..6084cdcfd --- /dev/null +++ b/Samples/Genetic/Travelling Salesman (GP)/TSPChromosome.cs @@ -0,0 +1,160 @@ +// Traveling Salesman Problem using Genetic Algorithms +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +using System; +using AForge.Genetic; + +namespace SampleApp +{ + /// + /// The chromosome is to solve TSP task (Travailing Salesman Problem). + /// + public class TSPChromosome : PermutationChromosome + { + private double[,] map = null; + + /// + /// Constructor + /// + public TSPChromosome(double[,] map) + : base(map.GetLength(0)) + { + this.map = map; + } + + /// + /// Copy Constructor + /// + protected TSPChromosome(TSPChromosome source) + : base(source) + { + this.map = source.map; + } + + /// + /// Create new random chromosome (factory method) + /// + public override IChromosome CreateNew() + { + return new TSPChromosome(map); + } + + /// + /// Clone the chromosome + /// + public override IChromosome Clone() + { + return new TSPChromosome(this); + } + + /// + /// Crossover operator + /// + public override void Crossover(IChromosome pair) + { + TSPChromosome p = (TSPChromosome)pair; + + // check for correct pair + if ((p != null) && (p.length == length)) + { + ushort[] child1 = new ushort[length]; + ushort[] child2 = new ushort[length]; + + // create two children + CreateChildUsingCrossover(this.val, p.val, child1); + CreateChildUsingCrossover(p.val, this.val, child2); + + // replace parents with children + this.val = child1; + p.val = child2; + } + } + + // Produce new child applying crossover to two parents + private void CreateChildUsingCrossover(ushort[] parent1, ushort[] parent2, ushort[] child) + { + // temporary array to specify if certain gene already + // present in the child + bool[] geneIsBusy = new bool[length]; + // previous gene in the child and two next candidates + ushort prev, next1, next2; + // candidates validness - candidate is valid, if it is not + // yet in the child + bool valid1, valid2; + + int j, k = length - 1; + + // first gene of the child is taken from the second parent + prev = child[0] = parent2[0]; + geneIsBusy[prev] = true; + + // resolve all other genes of the child + for (int i = 1; i < length; i++) + { + // find the next gene after PREV in both parents + // 1 + for (j = 0; j < k; j++) + { + if (parent1[j] == prev) + break; + } + next1 = (j == k) ? parent1[0] : parent1[j + 1]; + // 2 + for (j = 0; j < k; j++) + { + if (parent2[j] == prev) + break; + } + next2 = (j == k) ? parent2[0] : parent2[j + 1]; + + // check candidate genes for validness + valid1 = !geneIsBusy[next1]; + valid2 = !geneIsBusy[next2]; + + // select gene + if (valid1 && valid2) + { + // both candidates are valid + // select one closest city + double dx1 = map[next1, 0] - map[prev, 0]; + double dy1 = map[next1, 1] - map[prev, 1]; + double dx2 = map[next2, 0] - map[prev, 0]; + double dy2 = map[next2, 1] - map[prev, 1]; + + prev = (Math.Sqrt(dx1 * dx1 + dy1 * dy1) < Math.Sqrt(dx2 * dx2 + dy2 * dy2)) ? next1 : next2; + } + else if (!(valid1 || valid2)) + { + // none of candidates is valid, so + // select random gene which is not in the child yet + int r = j = rand.Next(length); + + // go down first + while ((r < length) && (geneIsBusy[r] == true)) + r++; + if (r == length) + { + // not found, try to go up + r = j - 1; + while (geneIsBusy[r] == true) // && ( r >= 0 ) + r--; + } + prev = (ushort)r; + } + else + { + // one of candidates is valid + prev = (valid1) ? next1 : next2; + } + + child[i] = prev; + geneIsBusy[prev] = true; + } + } + } +} diff --git a/Samples/Genetic/Travelling Salesman (GP)/TSPFitnessFunction.cs b/Samples/Genetic/Travelling Salesman (GP)/TSPFitnessFunction.cs new file mode 100644 index 0000000000..a4a87d2c1 --- /dev/null +++ b/Samples/Genetic/Travelling Salesman (GP)/TSPFitnessFunction.cs @@ -0,0 +1,84 @@ +// AForge Framework +// Traveling Salesman Problem using Genetic Algorithms +// +// Copyright Andrew Kirillov, 2006-2008 +// andrew.kirillov@gmail.com +// + +using System; +using AForge.Genetic; + +namespace SampleApp +{ + /// + /// Fitness function for TSP task (Travaling Salasman Problem) + /// + public class TSPFitnessFunction : IFitnessFunction + { + // map + private double[,] map = null; + + // Constructor + public TSPFitnessFunction(double[,] map) + { + this.map = map; + } + + /// + /// Evaluate chromosome - calculates its fitness value + /// + public double Evaluate(IChromosome chromosome) + { + return 1 / (PathLength(chromosome) + 1); + } + + /// + /// Translate genotype to phenotype + /// + public object Translate(IChromosome chromosome) + { + return chromosome.ToString(); + } + + /// + /// Calculate path length represented by the specified chromosome + /// + public double PathLength(IChromosome chromosome) + { + // salesman path + ushort[] path = ((PermutationChromosome)chromosome).Value; + + // check path size + if (path.Length != map.GetLength(0)) + { + throw new ArgumentException("Invalid path specified - not all cities are visited"); + } + + // path length + int prev = path[0]; + int curr = path[path.Length - 1]; + + // calculate distance between the last and the first city + double dx = map[curr, 0] - map[prev, 0]; + double dy = map[curr, 1] - map[prev, 1]; + double pathLength = Math.Sqrt(dx * dx + dy * dy); + + // calculate the path length from the first city to the last + for (int i = 1, n = path.Length; i < n; i++) + { + // get current city + curr = path[i]; + + // calculate distance + dx = map[curr, 0] - map[prev, 0]; + dy = map[curr, 1] - map[prev, 1]; + pathLength += Math.Sqrt(dx * dx + dy * dy); + + // put current city as previous + prev = curr; + } + + return pathLength; + } + } +} diff --git a/Samples/Genetic/Travelling Salesman (GP)/Travelling Salesman (GP).csproj b/Samples/Genetic/Travelling Salesman (GP)/Travelling Salesman (GP).csproj new file mode 100644 index 0000000000..b174dd4cf --- /dev/null +++ b/Samples/Genetic/Travelling Salesman (GP)/Travelling Salesman (GP).csproj @@ -0,0 +1,206 @@ + + + + Local + 9.0.21022 + 2.0 + {DEC346FD-C496-4B3E-A0E9-60AE011E3C49} + Debug + AnyCPU + App.ico + + + Travelling Salesman %28GP%29 + + + JScript + Grid + IE50 + false + WinExe + SampleApp + OnBuildSuccess + + + + + + + 3.5 + v4.0 + false + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true + + + bin\Debug\ + false + 285212672 + false + + + DEBUG;TRACE + + + true + 4096 + false + + + false + false + false + false + 4 + full + prompt + + + bin\Release\ + false + 285212672 + false + + + TRACE + + + false + 4096 + false + + + true + false + false + false + 4 + none + prompt + + + true + bin\x86\Debug\ + DEBUG;TRACE + 285212672 + 4096 + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + 285212672 + true + 4096 + x86 + prompt + MinimumRecommendedRules.ruleset + + + + ..\..\..\Release\net40\Accord.dll + + + ..\..\..\Release\net40\Accord.Controls.dll + + + ..\..\..\Release\net40\Accord.Genetic.dll + + + System + + + System.Data + + + System.Drawing + + + + System.Windows.Forms + + + System.XML + + + + + + Code + + + Form + + + + Code + + + Code + + + MainForm.cs + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 2.0 %28x86%29 + false + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + true + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + PreserveNewest + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/Genetic/Travelling Salesman (GP)/app.config b/Samples/Genetic/Travelling Salesman (GP)/app.config new file mode 100644 index 0000000000..57c0f2cbc --- /dev/null +++ b/Samples/Genetic/Travelling Salesman (GP)/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Samples/Imaging/Classification (BoW)/AboutBox.Designer.cs b/Samples/Imaging/Classification (BoW)/AboutBox.Designer.cs index 425929e20..f6d7e7190 100644 --- a/Samples/Imaging/Classification (BoW)/AboutBox.Designer.cs +++ b/Samples/Imaging/Classification (BoW)/AboutBox.Designer.cs @@ -1,4 +1,4 @@ -namespace Classification.BoW +namespace SampleApp { partial class AboutBox { diff --git a/Samples/Imaging/Classification (BoW)/AboutBox.cs b/Samples/Imaging/Classification (BoW)/AboutBox.cs index 16ead4005..bcc2b0acb 100644 --- a/Samples/Imaging/Classification (BoW)/AboutBox.cs +++ b/Samples/Imaging/Classification (BoW)/AboutBox.cs @@ -1,8 +1,8 @@ using System; using System.Reflection; -using System.Windows.Forms; - -namespace Classification.BoW +using System.Windows.Forms; + +namespace SampleApp { partial class AboutBox : Form { diff --git a/Samples/Imaging/Classification (BoW)/Accord.dll.config b/Samples/Imaging/Classification (BoW)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Imaging/Classification (BoW)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Imaging/Classification (BoW)/Classification (BoW).csproj b/Samples/Imaging/Classification (BoW)/Classification (BoW).csproj index 05bc9a464..b5e9f81a1 100644 --- a/Samples/Imaging/Classification (BoW)/Classification (BoW).csproj +++ b/Samples/Imaging/Classification (BoW)/Classification (BoW).csproj @@ -8,7 +8,7 @@ {F6CFAC9E-A9AF-4DDF-9405-B4B3578E5154} WinExe Properties - Classification.BoW + SampleApp Classification %28BoW%29 v4.0 Client @@ -40,54 +40,35 @@ - ..\..\packages\Accord.2.14.5-alpha\lib\net40\Accord.dll + ..\..\..\Release\net40\Accord.dll - ..\..\packages\Accord.Controls.2.14.5-alpha\lib\net40\Accord.Controls.dll + ..\..\..\Release\net40\Accord.Controls.dll - ..\..\packages\Accord.Controls.Imaging.2.14.5-alpha\lib\net40\Accord.Controls.Imaging.dll + ..\..\..\Release\net40\Accord.Controls.Imaging.dll - ..\..\packages\Accord.Imaging.2.14.5-alpha\lib\net40\Accord.Imaging.dll + ..\..\..\Release\net40\Accord.Imaging.dll - ..\..\packages\Accord.MachineLearning.2.14.5-alpha\lib\net40\Accord.MachineLearning.dll + ..\..\..\Release\net40\Accord.MachineLearning.dll - ..\..\packages\Accord.Math.2.14.5-alpha\lib\net40\Accord.Math.dll + ..\..\..\Release\net40\Accord.Math.dll - ..\..\packages\Accord.Statistics.2.14.5-alpha\lib\net40\Accord.Statistics.dll - - - ..\..\packages\AForge.2.2.5\lib\AForge.dll - - - ..\..\packages\AForge.Controls.2.2.5\lib\AForge.Controls.dll - - - ..\..\packages\AForge.Imaging.2.2.5\lib\AForge.Imaging.dll - - - ..\..\packages\AForge.Math.2.2.5\lib\AForge.Math.dll - - - ..\..\packages\AForge.Video.2.2.5\lib\AForge.Video.dll + ..\..\..\Release\net40\Accord.Statistics.dll + - - - - ..\..\packages\ZedGraph.5.1.6\lib\net35-Client\ZedGraph.dll - @@ -120,8 +101,10 @@ Resources.resx True + + PreserveNewest + - SettingsSingleFileGenerator Settings.Designer.cs @@ -135,7 +118,6 @@ - Always @@ -805,13 +787,6 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + diff --git a/Samples/Imaging/Corners (FAST)/Corners (FAST).csproj b/Samples/Imaging/Corners (FAST)/Corners (FAST).csproj index 4f32571ee..bfd438451 100644 --- a/Samples/Imaging/Corners (FAST)/Corners (FAST).csproj +++ b/Samples/Imaging/Corners (FAST)/Corners (FAST).csproj @@ -1,153 +1,148 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {F7750412-9EA2-4FCF-A268-AC927188A009} - WinExe - Properties - Corners.FAST - Corners %28FAST%29 - v4.0 - 512 - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - - true - bin\x86\Debug\ - DEBUG;TRACE - full - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - bin\x86\Release\ - TRACE - true - pdbonly - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - framework.ico - - - - False - ..\..\..\Release\net40\Accord.dll - - - False - ..\..\..\Release\net40\Accord.Imaging.dll - - - False - ..\..\..\Release\net40\Accord.Math.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Imaging.dll - - - - 3.5 - - - - - - - Form - - - MainForm.cs - - - - - MainForm.cs - Designer - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {F7750412-9EA2-4FCF-A268-AC927188A009} + WinExe + Properties + SampleApp + Corners %28FAST%29 + v4.0 + 512 + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + framework.ico + + + + False + ..\..\..\Release\net40\Accord.dll + + + False + ..\..\..\Release\net40\Accord.Imaging.dll + + + False + ..\..\..\Release\net40\Accord.Math.dll + + + + 3.5 + + + + + + + Form + + + MainForm.cs + + + + + MainForm.cs + Designer + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + --> \ No newline at end of file diff --git a/Samples/Imaging/Corners (FAST)/MainForm.Designer.cs b/Samples/Imaging/Corners (FAST)/MainForm.Designer.cs index 8d2851980..389cd4145 100644 --- a/Samples/Imaging/Corners (FAST)/MainForm.Designer.cs +++ b/Samples/Imaging/Corners (FAST)/MainForm.Designer.cs @@ -1,33 +1,33 @@ -namespace Corners.FAST -{ - partial class MainForm - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); this.pictureBox1 = new System.Windows.Forms.PictureBox(); this.button1 = new System.Windows.Forms.Button(); @@ -39,10 +39,10 @@ private void InitializeComponent() // // pictureBox1 // - this.pictureBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) + this.pictureBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.pictureBox1.Image = global::Corners.FAST.Properties.Resources.lena512; + this.pictureBox1.Image = global::SampleApp.Properties.Resources.lena512; this.pictureBox1.Location = new System.Drawing.Point(12, 12); this.pictureBox1.Name = "pictureBox1"; this.pictureBox1.Size = new System.Drawing.Size(489, 477); @@ -111,14 +111,14 @@ private void InitializeComponent() this.ResumeLayout(false); this.PerformLayout(); - } - - #endregion - - private System.Windows.Forms.PictureBox pictureBox1; - private System.Windows.Forms.Button button1; - private System.Windows.Forms.Label label2; - private System.Windows.Forms.NumericUpDown numThreshold; - } -} - + } + + #endregion + + private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.NumericUpDown numThreshold; + } +} + diff --git a/Samples/Imaging/Corners (FAST)/MainForm.cs b/Samples/Imaging/Corners (FAST)/MainForm.cs index 39c980188..2dcb12f25 100644 --- a/Samples/Imaging/Corners (FAST)/MainForm.cs +++ b/Samples/Imaging/Corners (FAST)/MainForm.cs @@ -1,69 +1,68 @@ -// Accord.NET Sample Applications -// http://accord-framework.net -// -// Copyright © 2009-2014, César Souza -// All rights reserved. 3-BSD License: -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// * Neither the name of the Accord.NET Framework authors nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -using System; -using System.Drawing; -using System.Windows.Forms; -using Accord.Imaging; -using AForge.Imaging.Filters; -using Corners.FAST.Properties; - -namespace Corners.FAST -{ - public partial class MainForm : Form - { - public MainForm() - { - InitializeComponent(); - } - - - private void button1_Click(object sender, EventArgs e) - { - // Open a image - Bitmap lenna = Resources.lena512; - - // Create a new SURF Features Detector using the given parameters - FastCornersDetector fast = new FastCornersDetector() - { - Threshold = (int)numThreshold.Value, - Suppress = true - }; - - // Create a new AForge's Corner Marker Filter - CornersMarker corners = new CornersMarker(fast, Color.White); - - // Apply the filter and display it on a picturebox - pictureBox1.Image = corners.Apply(lenna); - } - } -} +// Accord.NET Sample Applications +// http://accord-framework.net +// +// Copyright © 2009-2014, César Souza +// All rights reserved. 3-BSD License: +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of the Accord.NET Framework authors nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +using System; +using System.Drawing; +using System.Windows.Forms; +using Accord.Imaging; +using AForge.Imaging.Filters; + +namespace SampleApp +{ + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + } + + + private void button1_Click(object sender, EventArgs e) + { + // Open a image + Bitmap lenna = Properties.Resources.lena512; + + // Create a new SURF Features Detector using the given parameters + FastCornersDetector fast = new FastCornersDetector() + { + Threshold = (int)numThreshold.Value, + Suppress = true + }; + + // Create a new AForge's Corner Marker Filter + CornersMarker corners = new CornersMarker(fast, Color.White); + + // Apply the filter and display it on a picturebox + pictureBox1.Image = corners.Apply(lenna); + } + } +} diff --git a/Samples/Imaging/Corners (FAST)/Program.cs b/Samples/Imaging/Corners (FAST)/Program.cs index c3b43028d..316268492 100644 --- a/Samples/Imaging/Corners (FAST)/Program.cs +++ b/Samples/Imaging/Corners (FAST)/Program.cs @@ -1,7 +1,7 @@ using System; using System.Windows.Forms; -namespace Corners.FAST +namespace SampleApp { static class Program { diff --git a/Samples/Imaging/Corners (FAST)/Properties/Resources.Designer.cs b/Samples/Imaging/Corners (FAST)/Properties/Resources.Designer.cs index be2dfc8f6..80ca087bc 100644 --- a/Samples/Imaging/Corners (FAST)/Properties/Resources.Designer.cs +++ b/Samples/Imaging/Corners (FAST)/Properties/Resources.Designer.cs @@ -1,73 +1,73 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.18052 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Corners.FAST.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Corners.FAST.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap lena512 { - get { - object obj = ResourceManager.GetObject("lena512", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap lena512 { + get { + object obj = ResourceManager.GetObject("lena512", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/Samples/Imaging/Corners (FAST)/Properties/Settings.Designer.cs b/Samples/Imaging/Corners (FAST)/Properties/Settings.Designer.cs index a5a77cb96..dbc9e5d22 100644 --- a/Samples/Imaging/Corners (FAST)/Properties/Settings.Designer.cs +++ b/Samples/Imaging/Corners (FAST)/Properties/Settings.Designer.cs @@ -1,26 +1,26 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.18052 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Corners.FAST.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Samples/Imaging/Corners (Harris)/Accord.dll.config b/Samples/Imaging/Corners (Harris)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Imaging/Corners (Harris)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Imaging/Corners (Harris)/Corners (Harris).csproj b/Samples/Imaging/Corners (Harris)/Corners (Harris).csproj index e576000c4..51d53b7f3 100644 --- a/Samples/Imaging/Corners (Harris)/Corners (Harris).csproj +++ b/Samples/Imaging/Corners (Harris)/Corners (Harris).csproj @@ -1,156 +1,151 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {316F5B16-E308-4ABE-B95D-EF64FFAEF028} - WinExe - Properties - Corners.Harris - Corners %28Harris%29 - v4.0 - 512 - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - - true - bin\x86\Debug\ - DEBUG;TRACE - full - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - bin\x86\Release\ - TRACE - true - pdbonly - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - framework.ico - - - - False - ..\..\..\Release\net40\Accord.dll - - - False - ..\..\..\Release\net40\Accord.Imaging.dll - - - False - ..\..\..\Release\net40\Accord.Math.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Imaging.dll - - - - 3.5 - - - - - - - Form - - - MainForm.cs - - - - - MainForm.cs - Designer - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - - - - + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {316F5B16-E308-4ABE-B95D-EF64FFAEF028} + WinExe + Properties + SampleApp + Corners %28Harris%29 + v4.0 + 512 + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + framework.ico + + + + False + ..\..\..\Release\net40\Accord.dll + + + False + ..\..\..\Release\net40\Accord.Imaging.dll + + + False + ..\..\..\Release\net40\Accord.Math.dll + + + + 3.5 + + + + + + + Form + + + MainForm.cs + + + + + MainForm.cs + Designer + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + --> \ No newline at end of file diff --git a/Samples/Imaging/Corners (Harris)/MainForm.Designer.cs b/Samples/Imaging/Corners (Harris)/MainForm.Designer.cs index cf2efdf07..5c474ad88 100644 --- a/Samples/Imaging/Corners (Harris)/MainForm.Designer.cs +++ b/Samples/Imaging/Corners (Harris)/MainForm.Designer.cs @@ -1,33 +1,33 @@ -namespace Corners.Harris -{ - partial class MainForm - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); this.pictureBox1 = new System.Windows.Forms.PictureBox(); this.button1 = new System.Windows.Forms.Button(); @@ -45,10 +45,10 @@ private void InitializeComponent() // // pictureBox1 // - this.pictureBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) + this.pictureBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.pictureBox1.Image = global::Corners.Harris.Properties.Resources.lena512; + this.pictureBox1.Image = global::SampleApp.Properties.Resources.lena512; this.pictureBox1.Location = new System.Drawing.Point(12, 12); this.pictureBox1.Name = "pictureBox1"; this.pictureBox1.Size = new System.Drawing.Size(489, 477); @@ -193,18 +193,18 @@ private void InitializeComponent() this.ResumeLayout(false); this.PerformLayout(); - } - - #endregion - - private System.Windows.Forms.PictureBox pictureBox1; - private System.Windows.Forms.Button button1; - private System.Windows.Forms.NumericUpDown numSigma; - private System.Windows.Forms.NumericUpDown numThreshold; - private System.Windows.Forms.NumericUpDown numK; - private System.Windows.Forms.Label label2; - private System.Windows.Forms.Label label3; - private System.Windows.Forms.CheckBox checkBox1; - } -} - + } + + #endregion + + private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.NumericUpDown numSigma; + private System.Windows.Forms.NumericUpDown numThreshold; + private System.Windows.Forms.NumericUpDown numK; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.CheckBox checkBox1; + } +} + diff --git a/Samples/Imaging/Corners (Harris)/MainForm.cs b/Samples/Imaging/Corners (Harris)/MainForm.cs index c39b5f581..88329a148 100644 --- a/Samples/Imaging/Corners (Harris)/MainForm.cs +++ b/Samples/Imaging/Corners (Harris)/MainForm.cs @@ -1,75 +1,75 @@ -// Accord.NET Sample Applications -// http://accord-framework.net -// -// Copyright © 2009-2014, César Souza -// All rights reserved. 3-BSD License: -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// * Neither the name of the Accord.NET Framework authors nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -using System; -using System.Drawing; -using System.Windows.Forms; -using Accord.Imaging; -using AForge.Imaging.Filters; - -namespace Corners.Harris -{ - public partial class MainForm : Form - { - public MainForm() - { - InitializeComponent(); - } - - - private void button1_Click(object sender, EventArgs e) - { - // Open a image - Bitmap lenna = Harris.Properties.Resources.lena512; - - double sigma = (double)numSigma.Value; - float k = (float)numK.Value; - float threshold = (float)numThreshold.Value; - - // Create a new Harris Corners Detector using the given parameters - HarrisCornersDetector harris = new HarrisCornersDetector(k) - { - Measure = checkBox1.Checked ? - HarrisCornerMeasure.Harris : HarrisCornerMeasure.Noble, - - Threshold = threshold, - Sigma = sigma - }; - - // Create a new AForge's Corner Marker Filter - CornersMarker corners = new CornersMarker(harris, Color.White); - - // Apply the filter and display it on a picturebox - pictureBox1.Image = corners.Apply(lenna); - } - } -} +// Accord.NET Sample Applications +// http://accord-framework.net +// +// Copyright © 2009-2014, César Souza +// All rights reserved. 3-BSD License: +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of the Accord.NET Framework authors nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +using System; +using System.Drawing; +using System.Windows.Forms; +using Accord.Imaging; +using AForge.Imaging.Filters; + +namespace SampleApp +{ + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + } + + + private void button1_Click(object sender, EventArgs e) + { + // Open a image + Bitmap lenna = Properties.Resources.lena512; + + double sigma = (double)numSigma.Value; + float k = (float)numK.Value; + float threshold = (float)numThreshold.Value; + + // Create a new Harris Corners Detector using the given parameters + HarrisCornersDetector harris = new HarrisCornersDetector(k) + { + Measure = checkBox1.Checked ? + HarrisCornerMeasure.Harris : HarrisCornerMeasure.Noble, + + Threshold = threshold, + Sigma = sigma + }; + + // Create a new AForge's Corner Marker Filter + CornersMarker corners = new CornersMarker(harris, Color.White); + + // Apply the filter and display it on a picturebox + pictureBox1.Image = corners.Apply(lenna); + } + } +} diff --git a/Samples/Imaging/Corners (Harris)/Program.cs b/Samples/Imaging/Corners (Harris)/Program.cs index 5ba6223d1..316268492 100644 --- a/Samples/Imaging/Corners (Harris)/Program.cs +++ b/Samples/Imaging/Corners (Harris)/Program.cs @@ -1,9 +1,7 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Windows.Forms; -namespace Corners.Harris +namespace SampleApp { static class Program { diff --git a/Samples/Imaging/Corners (Harris)/Properties/Resources.Designer.cs b/Samples/Imaging/Corners (Harris)/Properties/Resources.Designer.cs index 15115f2cd..80ca087bc 100644 --- a/Samples/Imaging/Corners (Harris)/Properties/Resources.Designer.cs +++ b/Samples/Imaging/Corners (Harris)/Properties/Resources.Designer.cs @@ -1,73 +1,73 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.18052 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Corners.Harris.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Corners.Harris.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap lena512 { - get { - object obj = ResourceManager.GetObject("lena512", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap lena512 { + get { + object obj = ResourceManager.GetObject("lena512", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/Samples/Imaging/Corners (Harris)/Properties/Settings.Designer.cs b/Samples/Imaging/Corners (Harris)/Properties/Settings.Designer.cs index 8452556f6..dbc9e5d22 100644 --- a/Samples/Imaging/Corners (Harris)/Properties/Settings.Designer.cs +++ b/Samples/Imaging/Corners (Harris)/Properties/Settings.Designer.cs @@ -1,26 +1,26 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.18052 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Corners.Harris.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Samples/Imaging/Corners (SURF)/Accord.dll.config b/Samples/Imaging/Corners (SURF)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Imaging/Corners (SURF)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Imaging/Corners (SURF)/Corners (SURF).csproj b/Samples/Imaging/Corners (SURF)/Corners (SURF).csproj index 6e3281336..8a2cfc4d1 100644 --- a/Samples/Imaging/Corners (SURF)/Corners (SURF).csproj +++ b/Samples/Imaging/Corners (SURF)/Corners (SURF).csproj @@ -1,153 +1,148 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {936F3B12-2B1A-468E-9830-51EC9EFB127E} - WinExe - Properties - Corners.SURF - Corners %28SURF%29 - v4.0 - 512 - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - - true - bin\x86\Debug\ - DEBUG;TRACE - full - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - bin\x86\Release\ - TRACE - true - pdbonly - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - framework.ico - - - - False - ..\..\..\Release\net40\Accord.dll - - - False - ..\..\..\Release\net40\Accord.Imaging.dll - - - False - ..\..\..\Release\net40\Accord.Math.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Imaging.dll - - - - 3.5 - - - - - - - Form - - - MainForm.cs - - - - - MainForm.cs - Designer - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {936F3B12-2B1A-468E-9830-51EC9EFB127E} + WinExe + Properties + SampleApp + Corners %28SURF%29 + v4.0 + 512 + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + framework.ico + + + + False + ..\..\..\Release\net40\Accord.dll + + + False + ..\..\..\Release\net40\Accord.Imaging.dll + + + False + ..\..\..\Release\net40\Accord.Math.dll + + + + 3.5 + + + + + + + Form + + + MainForm.cs + + + + + MainForm.cs + Designer + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + --> \ No newline at end of file diff --git a/Samples/Imaging/Corners (SURF)/MainForm.Designer.cs b/Samples/Imaging/Corners (SURF)/MainForm.Designer.cs index 46b5acee5..35d43a810 100644 --- a/Samples/Imaging/Corners (SURF)/MainForm.Designer.cs +++ b/Samples/Imaging/Corners (SURF)/MainForm.Designer.cs @@ -1,33 +1,33 @@ -namespace Corners.SURF -{ - partial class MainForm - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); this.pictureBox1 = new System.Windows.Forms.PictureBox(); this.button1 = new System.Windows.Forms.Button(); @@ -45,10 +45,10 @@ private void InitializeComponent() // // pictureBox1 // - this.pictureBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) + this.pictureBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.pictureBox1.Image = global::Corners.SURF.Properties.Resources.lena512; + this.pictureBox1.Image = global::SampleApp.Properties.Resources.lena512; this.pictureBox1.Location = new System.Drawing.Point(12, 12); this.pictureBox1.Name = "pictureBox1"; this.pictureBox1.Size = new System.Drawing.Size(489, 477); @@ -164,18 +164,18 @@ private void InitializeComponent() this.ResumeLayout(false); this.PerformLayout(); - } - - #endregion - - private System.Windows.Forms.PictureBox pictureBox1; - private System.Windows.Forms.Button button1; - private System.Windows.Forms.NumericUpDown numThreshold; - private System.Windows.Forms.Label label1; - private System.Windows.Forms.NumericUpDown numOctaves; - private System.Windows.Forms.NumericUpDown numInitial; - private System.Windows.Forms.Label label2; - private System.Windows.Forms.Label label3; - } -} - + } + + #endregion + + private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.NumericUpDown numThreshold; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.NumericUpDown numOctaves; + private System.Windows.Forms.NumericUpDown numInitial; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + } +} + diff --git a/Samples/Imaging/Corners (SURF)/MainForm.cs b/Samples/Imaging/Corners (SURF)/MainForm.cs index c30c20607..f26eb7563 100644 --- a/Samples/Imaging/Corners (SURF)/MainForm.cs +++ b/Samples/Imaging/Corners (SURF)/MainForm.cs @@ -1,73 +1,72 @@ -// Accord.NET Sample Applications -// http://accord-framework.net -// -// Copyright © 2009-2014, César Souza -// All rights reserved. 3-BSD License: -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// * Neither the name of the Accord.NET Framework authors nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Windows.Forms; -using Accord.Imaging; -using Accord.Imaging.Filters; -using Corners.SURF.Properties; - -namespace Corners.SURF -{ - public partial class MainForm : Form - { - public MainForm() - { - InitializeComponent(); - } - - - private void button1_Click(object sender, EventArgs e) - { - // Open a image - Bitmap lenna = Resources.lena512; - - float threshold = (float)numThreshold.Value; - int octaves = (int)numOctaves.Value; - int initial = (int)numInitial.Value; - - // Create a new SURF Features Detector using the given parameters - SpeededUpRobustFeaturesDetector surf = - new SpeededUpRobustFeaturesDetector(threshold, octaves, initial); - - List points = surf.ProcessImage(lenna); - - // Create a new AForge's Corner Marker Filter - FeaturesMarker features = new FeaturesMarker(points); - - // Apply the filter and display it on a picturebox - pictureBox1.Image = features.Apply(lenna); - } - } -} +// Accord.NET Sample Applications +// http://accord-framework.net +// +// Copyright © 2009-2014, César Souza +// All rights reserved. 3-BSD License: +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of the Accord.NET Framework authors nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Windows.Forms; +using Accord.Imaging; +using Accord.Imaging.Filters; + +namespace SampleApp +{ + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + } + + + private void button1_Click(object sender, EventArgs e) + { + // Open a image + Bitmap lenna = Properties.Resources.lena512; + + float threshold = (float)numThreshold.Value; + int octaves = (int)numOctaves.Value; + int initial = (int)numInitial.Value; + + // Create a new SURF Features Detector using the given parameters + SpeededUpRobustFeaturesDetector surf = + new SpeededUpRobustFeaturesDetector(threshold, octaves, initial); + + List points = surf.ProcessImage(lenna); + + // Create a new AForge's Corner Marker Filter + FeaturesMarker features = new FeaturesMarker(points); + + // Apply the filter and display it on a picturebox + pictureBox1.Image = features.Apply(lenna); + } + } +} diff --git a/Samples/Imaging/Corners (SURF)/Program.cs b/Samples/Imaging/Corners (SURF)/Program.cs index a1c30ff31..316268492 100644 --- a/Samples/Imaging/Corners (SURF)/Program.cs +++ b/Samples/Imaging/Corners (SURF)/Program.cs @@ -1,7 +1,7 @@ using System; using System.Windows.Forms; -namespace Corners.SURF +namespace SampleApp { static class Program { diff --git a/Samples/Imaging/Corners (SURF)/Properties/Resources.Designer.cs b/Samples/Imaging/Corners (SURF)/Properties/Resources.Designer.cs index dc79c1b17..80ca087bc 100644 --- a/Samples/Imaging/Corners (SURF)/Properties/Resources.Designer.cs +++ b/Samples/Imaging/Corners (SURF)/Properties/Resources.Designer.cs @@ -1,73 +1,73 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.18052 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Corners.SURF.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Corners.SURF.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap lena512 { - get { - object obj = ResourceManager.GetObject("lena512", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap lena512 { + get { + object obj = ResourceManager.GetObject("lena512", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/Samples/Imaging/Corners (SURF)/Properties/Settings.Designer.cs b/Samples/Imaging/Corners (SURF)/Properties/Settings.Designer.cs index 7fe9d73a3..dbc9e5d22 100644 --- a/Samples/Imaging/Corners (SURF)/Properties/Settings.Designer.cs +++ b/Samples/Imaging/Corners (SURF)/Properties/Settings.Designer.cs @@ -1,26 +1,26 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.18052 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Corners.SURF.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Samples/Imaging/Detection (Blobs)/AboutForm.Designer.cs b/Samples/Imaging/Detection (Blobs)/AboutForm.Designer.cs new file mode 100644 index 0000000000..6b0fabc47 --- /dev/null +++ b/Samples/Imaging/Detection (Blobs)/AboutForm.Designer.cs @@ -0,0 +1,130 @@ +namespace SampleApp +{ + partial class AboutForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.panel1 = new System.Windows.Forms.Panel(); + this.emailLabel = new System.Windows.Forms.LinkLabel(); + this.label3 = new System.Windows.Forms.Label(); + this.aforgeLabel = new System.Windows.Forms.LinkLabel(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.panel1.SuspendLayout(); + this.SuspendLayout(); + // + // panel1 + // + this.panel1.Controls.Add(this.emailLabel); + this.panel1.Controls.Add(this.label3); + this.panel1.Controls.Add(this.aforgeLabel); + this.panel1.Controls.Add(this.label2); + this.panel1.Controls.Add(this.label1); + this.panel1.Location = new System.Drawing.Point(13, 12); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(303, 139); + this.panel1.TabIndex = 4; + // + // emailLabel + // + this.emailLabel.AutoSize = true; + this.emailLabel.Location = new System.Drawing.Point(75, 108); + this.emailLabel.Name = "emailLabel"; + this.emailLabel.Size = new System.Drawing.Size(153, 13); + this.emailLabel.TabIndex = 5; + this.emailLabel.TabStop = true; + this.emailLabel.Text = "andrew.kirillov@aforgenet.com"; + this.emailLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkClicked); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(69, 93); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(165, 13); + this.label3.TabIndex = 4; + this.label3.Text = "Copyright © 2009, Andrew Kirillov"; + // + // aforgeLabel + // + this.aforgeLabel.AutoSize = true; + this.aforgeLabel.Location = new System.Drawing.Point(55, 58); + this.aforgeLabel.Name = "aforgeLabel"; + this.aforgeLabel.Size = new System.Drawing.Size(192, 13); + this.aforgeLabel.TabIndex = 3; + this.aforgeLabel.TabStop = true; + this.aforgeLabel.Text = "http://www.aforgenet.com/framework/"; + this.aforgeLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkClicked); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(39, 43); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(225, 13); + this.label2.TabIndex = 2; + this.label2.Text = "Sample application of AForge.NET framework:"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(101, 18); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(101, 13); + this.label1.TabIndex = 1; + this.label1.Text = "Blobs Explorer 1.0.0"; + // + // AboutForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(329, 162); + this.Controls.Add(this.panel1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "AboutForm"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "About"; + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.LinkLabel emailLabel; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.LinkLabel aforgeLabel; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + } +} \ No newline at end of file diff --git a/Samples/Imaging/Detection (Blobs)/AboutForm.cs b/Samples/Imaging/Detection (Blobs)/AboutForm.cs new file mode 100644 index 0000000000..7b0330ce2 --- /dev/null +++ b/Samples/Imaging/Detection (Blobs)/AboutForm.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace SampleApp +{ + public partial class AboutForm : Form + { + public AboutForm() + { + InitializeComponent(); + + // initialize links + emailLabel.Links.Add(0, emailLabel.Text.Length, "mailto:andrew.kirillov@aforgenet.com"); + aforgeLabel.Links.Add(0, aforgeLabel.Text.Length, "http://www.aforgenet.com/framework/"); + } + + private void LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + System.Diagnostics.Process.Start(e.Link.LinkData.ToString()); + } + } +} diff --git a/Samples/Imaging/Detection (Blobs)/AboutForm.resx b/Samples/Imaging/Detection (Blobs)/AboutForm.resx new file mode 100644 index 0000000000..19dc0dd8b --- /dev/null +++ b/Samples/Imaging/Detection (Blobs)/AboutForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Imaging/Detection (Blobs)/Accord.dll.config b/Samples/Imaging/Detection (Blobs)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Imaging/Detection (Blobs)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Imaging/Detection (Blobs)/BlobsBrowser.Designer.cs b/Samples/Imaging/Detection (Blobs)/BlobsBrowser.Designer.cs new file mode 100644 index 0000000000..1bcf4ef24 --- /dev/null +++ b/Samples/Imaging/Detection (Blobs)/BlobsBrowser.Designer.cs @@ -0,0 +1,45 @@ +namespace SampleApp +{ + partial class BlobsBrowser + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.SuspendLayout(); + // + // BlobsBrowser + // + this.Paint += new System.Windows.Forms.PaintEventHandler(this.BlobsBrowser_Paint); + this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.BlobsBrowser_MouseMove); + this.MouseClick += new System.Windows.Forms.MouseEventHandler(this.BlobsBrowser_MouseClick); + this.ParentChanged += new System.EventHandler(this.BlobsBrowser_ParentChanged); + this.ResumeLayout(false); + + } + + #endregion + } +} diff --git a/Samples/Imaging/Detection (Blobs)/BlobsBrowser.cs b/Samples/Imaging/Detection (Blobs)/BlobsBrowser.cs new file mode 100644 index 0000000000..ab7781c78 --- /dev/null +++ b/Samples/Imaging/Detection (Blobs)/BlobsBrowser.cs @@ -0,0 +1,341 @@ +// Blobs Browser sample application +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Drawing.Imaging; +using System.Data; +using System.Text; +using System.Windows.Forms; + +using AForge; +using AForge.Imaging; +using AForge.Math.Geometry; + +namespace SampleApp +{ + public delegate void BlobSelectionHandler(object sender, Blob blob); + + public partial class BlobsBrowser : Control + { + private Bitmap image = null; + private int imageWidth, imageHeight; + private Control parent = null; + + private BlobCounter blobCounter = new BlobCounter(); + private Blob[] blobs; + private int selectedBlobID; + + Dictionary> leftEdges = new Dictionary>(); + Dictionary> rightEdges = new Dictionary>(); + Dictionary> topEdges = new Dictionary>(); + Dictionary> bottomEdges = new Dictionary>(); + + Dictionary> hulls = new Dictionary>(); + Dictionary> quadrilaterals = new Dictionary>(); + + // Event to notify about selected blob + public event BlobSelectionHandler BlobSelected; + + // Blobs' highlight types enumeration + public enum HightlightType + { + ConvexHull, + LeftAndRightEdges, + TopAndBottomEdges, + Quadrilateral + } + + private HightlightType highlighting = HightlightType.Quadrilateral; + private bool showRectangleAroundSelection = false; + + // Blobs' highlight type + public HightlightType Highlighting + { + get { return highlighting; } + set + { + highlighting = value; + Invalidate(); + } + } + + // Show rectangle around selection or not + public bool ShowRectangleAroundSelection + { + get { return showRectangleAroundSelection; } + set + { + showRectangleAroundSelection = value; + Invalidate(); + } + } + + public BlobsBrowser() + { + InitializeComponent(); + + // update control style + SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | + ControlStyles.DoubleBuffer | ControlStyles.UserPaint, true); + } + + // Set image to display by the control + public int SetImage(Bitmap image) + { + leftEdges.Clear(); + rightEdges.Clear(); + topEdges.Clear(); + bottomEdges.Clear(); + hulls.Clear(); + quadrilaterals.Clear(); + + selectedBlobID = 0; + + this.image = AForge.Imaging.Image.Clone(image, PixelFormat.Format24bppRgb); + imageWidth = this.image.Width; + imageHeight = this.image.Height; + + blobCounter.ProcessImage(this.image); + blobs = blobCounter.GetObjectsInformation(); + + GrahamConvexHull grahamScan = new GrahamConvexHull(); + + foreach (Blob blob in blobs) + { + List leftEdge = new List(); + List rightEdge = new List(); + List topEdge = new List(); + List bottomEdge = new List(); + + // collect edge points + blobCounter.GetBlobsLeftAndRightEdges(blob, out leftEdge, out rightEdge); + blobCounter.GetBlobsTopAndBottomEdges(blob, out topEdge, out bottomEdge); + + leftEdges.Add(blob.ID, leftEdge); + rightEdges.Add(blob.ID, rightEdge); + topEdges.Add(blob.ID, topEdge); + bottomEdges.Add(blob.ID, bottomEdge); + + // find convex hull + List edgePoints = new List(); + edgePoints.AddRange(leftEdge); + edgePoints.AddRange(rightEdge); + + List hull = grahamScan.FindHull(edgePoints); + hulls.Add(blob.ID, hull); + + List quadrilateral = null; + + // find quadrilateral + if (hull.Count < 4) + { + quadrilateral = new List(hull); + } + else + { + quadrilateral = PointsCloud.FindQuadrilateralCorners(hull); + } + quadrilaterals.Add(blob.ID, quadrilateral); + + // shift all points for vizualization + IntPoint shift = new IntPoint(1, 1); + + PointsCloud.Shift(leftEdge, shift); + PointsCloud.Shift(rightEdge, shift); + PointsCloud.Shift(topEdge, shift); + PointsCloud.Shift(bottomEdge, shift); + PointsCloud.Shift(hull, shift); + PointsCloud.Shift(quadrilateral, shift); + } + + UpdatePosition(); + Invalidate(); + + return blobs.Length; + } + + // Paint the control + private void BlobsBrowser_Paint(object sender, PaintEventArgs e) + { + Graphics g = e.Graphics; + Rectangle rect = this.ClientRectangle; + + Pen borderPen = new Pen(Color.FromArgb(64, 64, 64), 1); + Pen highlightPen = new Pen(Color.Red); + Pen highlightPenBold = new Pen(Color.FromArgb(0, 255, 0), 3); + Pen rectPen = new Pen(Color.Blue); + + // draw rectangle + g.DrawRectangle(borderPen, rect.X, rect.Y, rect.Width - 1, rect.Height - 1); + + if (image != null) + { + g.DrawImage(image, rect.X + 1, rect.Y + 1, rect.Width - 2, rect.Height - 2); + + foreach (Blob blob in blobs) + { + Pen pen = (blob.ID == selectedBlobID) ? highlightPenBold : highlightPen; + + if ((showRectangleAroundSelection) && (blob.ID == selectedBlobID)) + { + g.DrawRectangle(rectPen, blob.Rectangle); + } + + switch (highlighting) + { + case HightlightType.ConvexHull: + g.DrawPolygon(pen, PointsListToArray(hulls[blob.ID])); + break; + case HightlightType.LeftAndRightEdges: + DrawEdge(g, pen, leftEdges[blob.ID]); + DrawEdge(g, pen, rightEdges[blob.ID]); + break; + case HightlightType.TopAndBottomEdges: + DrawEdge(g, pen, topEdges[blob.ID]); + DrawEdge(g, pen, bottomEdges[blob.ID]); + break; + case HightlightType.Quadrilateral: + g.DrawPolygon(pen, PointsListToArray(quadrilaterals[blob.ID])); + break; + } + } + } + else + { + g.FillRectangle(new SolidBrush(Color.FromArgb(128, 128, 128)), + rect.X + 1, rect.Y + 1, rect.Width - 2, rect.Height - 2); + } + } + + // Update controls size and position + private void UpdatePosition() + { + if (this.Parent != null) + { + Rectangle rc = this.Parent.ClientRectangle; + int width = 320; + int height = 240; + + if (image != null) + { + // get frame size + width = imageWidth; + height = imageHeight; + } + + // update controls size and location + this.SuspendLayout(); + this.Location = new System.Drawing.Point((rc.Width - width - 2) / 2, (rc.Height - height - 2) / 2); + this.Size = new Size(width + 2, height + 2); + this.ResumeLayout(); + } + } + + // Parent of the control has changed + private void BlobsBrowser_ParentChanged(object sender, EventArgs e) + { + if (parent != null) + { + parent.SizeChanged -= new EventHandler(parent_SizeChanged); + } + + parent = this.Parent; + + // set handler for Size Changed parent's event + if (parent != null) + { + parent.SizeChanged += new EventHandler(parent_SizeChanged); + } + } + + // Parent control has changed its size + private void parent_SizeChanged(object sender, EventArgs e) + { + UpdatePosition(); + } + + // On mouse moving - update cursor + private void BlobsBrowser_MouseMove(object sender, MouseEventArgs e) + { + int x = e.X - 1; + int y = e.Y - 1; + + if ((image != null) && (x >= 0) && (y >= 0) && + (x < imageWidth) && (y < imageHeight) && + (blobCounter.ObjectLabels[y * imageWidth + x] != 0)) + { + this.Cursor = Cursors.Hand; + } + else + { + this.Cursor = Cursors.Default; + } + } + + // On mouse click - notify user if blob was clicked + private void BlobsBrowser_MouseClick(object sender, MouseEventArgs e) + { + int x = e.X - 1; + int y = e.Y - 1; + + if ((image != null) && (x >= 0) && (y >= 0) && + (x < imageWidth) && (y < imageHeight)) + { + int blobID = blobCounter.ObjectLabels[y * imageWidth + x]; + + if (blobID != 0) + { + selectedBlobID = blobID; + Invalidate(); + + if (BlobSelected != null) + { + for (int i = 0; i < blobs.Length; i++) + { + if (blobs[i].ID == blobID) + { + BlobSelected(this, blobs[i]); + } + } + } + } + } + } + + // Convert list of AForge.NET's IntPoint to array of .NET's Point + private static System.Drawing.Point[] PointsListToArray(List list) + { + System.Drawing.Point[] array = new System.Drawing.Point[list.Count]; + + for (int i = 0, n = list.Count; i < n; i++) + { + array[i] = new System.Drawing.Point(list[i].X, list[i].Y); + } + + return array; + } + + // Draw object's edge + private static void DrawEdge(Graphics g, Pen pen, List edge) + { + System.Drawing.Point[] points = PointsListToArray(edge); + + if (points.Length > 1) + { + g.DrawLines(pen, points); + } + else + { + g.DrawLine(pen, points[0], points[0]); + } + } + } +} diff --git a/Samples/Imaging/Detection (Blobs)/BlobsBrowser.resx b/Samples/Imaging/Detection (Blobs)/BlobsBrowser.resx new file mode 100644 index 0000000000..52a9ad3e7 --- /dev/null +++ b/Samples/Imaging/Detection (Blobs)/BlobsBrowser.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + False + + \ No newline at end of file diff --git a/Samples/Imaging/Detection (Blobs)/BlobsExplorer.sln b/Samples/Imaging/Detection (Blobs)/BlobsExplorer.sln new file mode 100644 index 0000000000..0284dffe6 --- /dev/null +++ b/Samples/Imaging/Detection (Blobs)/BlobsExplorer.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C# Express 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlobsExplorer", "BlobsExplorer.csproj", "{742487A3-DD2E-4F47-9ABB-77E88653A1D3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {742487A3-DD2E-4F47-9ABB-77E88653A1D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {742487A3-DD2E-4F47-9ABB-77E88653A1D3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {742487A3-DD2E-4F47-9ABB-77E88653A1D3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {742487A3-DD2E-4F47-9ABB-77E88653A1D3}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/Imaging/Detection (Blobs)/Detection (Blobs).csproj b/Samples/Imaging/Detection (Blobs)/Detection (Blobs).csproj new file mode 100644 index 0000000000..52e95d2e7 --- /dev/null +++ b/Samples/Imaging/Detection (Blobs)/Detection (Blobs).csproj @@ -0,0 +1,157 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {742487A3-DD2E-4F47-9ABB-77E88653A1D3} + WinExe + Properties + SampleApp + Detection %28Blobs%29 + v4.0 + 512 + + + 3.5 + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + + ..\..\..\Release\net40\Accord.dll + + + ..\..\..\Release\net40\Accord.Imaging.dll + + + ..\..\..\Release\net40\Accord.Math.dll + + + + + + + + + + Form + + + AboutForm.cs + + + Component + + + BlobsBrowser.cs + + + Form + + + MainForm.cs + + + + + BlobsBrowser.cs + + + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + AboutForm.cs + + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + \ No newline at end of file diff --git a/Samples/Imaging/Detection (Blobs)/MainForm.Designer.cs b/Samples/Imaging/Detection (Blobs)/MainForm.Designer.cs new file mode 100644 index 0000000000..7ef5bc336 --- /dev/null +++ b/Samples/Imaging/Detection (Blobs)/MainForm.Designer.cs @@ -0,0 +1,292 @@ +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.mainMenu = new System.Windows.Forms.MenuStrip(); + this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.openToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.loaddemoImageToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator(); + this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.statusStrip = new System.Windows.Forms.StatusStrip(); + this.blobsCountLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.openFileDialog = new System.Windows.Forms.OpenFileDialog(); + this.splitContainer = new System.Windows.Forms.SplitContainer(); + this.blobsBrowser = new BlobsBrowser(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.showRectangleAroundSelectionCheck = new System.Windows.Forms.CheckBox(); + this.highlightTypeCombo = new System.Windows.Forms.ComboBox(); + this.propertyGrid = new System.Windows.Forms.PropertyGrid(); + this.mainMenu.SuspendLayout(); + this.statusStrip.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit(); + this.splitContainer.Panel1.SuspendLayout(); + this.splitContainer.Panel2.SuspendLayout(); + this.splitContainer.SuspendLayout(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // mainMenu + // + this.mainMenu.ImageScalingSize = new System.Drawing.Size(24, 24); + this.mainMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.fileToolStripMenuItem, + this.helpToolStripMenuItem}); + this.mainMenu.Location = new System.Drawing.Point(0, 0); + this.mainMenu.Name = "mainMenu"; + this.mainMenu.Padding = new System.Windows.Forms.Padding(9, 3, 0, 3); + this.mainMenu.Size = new System.Drawing.Size(1066, 35); + this.mainMenu.TabIndex = 0; + // + // fileToolStripMenuItem + // + this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.openToolStripMenuItem, + this.loaddemoImageToolStripMenuItem, + this.toolStripMenuItem1, + this.exitToolStripMenuItem}); + this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; + this.fileToolStripMenuItem.Size = new System.Drawing.Size(50, 29); + this.fileToolStripMenuItem.Text = "&File"; + // + // openToolStripMenuItem + // + this.openToolStripMenuItem.Name = "openToolStripMenuItem"; + this.openToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O))); + this.openToolStripMenuItem.Size = new System.Drawing.Size(229, 30); + this.openToolStripMenuItem.Text = "&Open"; + this.openToolStripMenuItem.Click += new System.EventHandler(this.openToolStripMenuItem_Click); + // + // loaddemoImageToolStripMenuItem + // + this.loaddemoImageToolStripMenuItem.Name = "loaddemoImageToolStripMenuItem"; + this.loaddemoImageToolStripMenuItem.Size = new System.Drawing.Size(229, 30); + this.loaddemoImageToolStripMenuItem.Text = "Load &demo image"; + this.loaddemoImageToolStripMenuItem.Click += new System.EventHandler(this.loaddemoImageToolStripMenuItem_Click); + // + // toolStripMenuItem1 + // + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + this.toolStripMenuItem1.Size = new System.Drawing.Size(226, 6); + // + // exitToolStripMenuItem + // + this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; + this.exitToolStripMenuItem.Size = new System.Drawing.Size(229, 30); + this.exitToolStripMenuItem.Text = "E&xit"; + this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click); + // + // helpToolStripMenuItem + // + this.helpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.aboutToolStripMenuItem}); + this.helpToolStripMenuItem.Name = "helpToolStripMenuItem"; + this.helpToolStripMenuItem.Size = new System.Drawing.Size(61, 29); + this.helpToolStripMenuItem.Text = "&Help"; + // + // aboutToolStripMenuItem + // + this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem"; + this.aboutToolStripMenuItem.Size = new System.Drawing.Size(134, 30); + this.aboutToolStripMenuItem.Text = "&About"; + this.aboutToolStripMenuItem.Click += new System.EventHandler(this.aboutToolStripMenuItem_Click); + // + // statusStrip + // + this.statusStrip.ImageScalingSize = new System.Drawing.Size(24, 24); + this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.blobsCountLabel}); + this.statusStrip.Location = new System.Drawing.Point(0, 649); + this.statusStrip.Name = "statusStrip"; + this.statusStrip.Padding = new System.Windows.Forms.Padding(2, 0, 21, 0); + this.statusStrip.Size = new System.Drawing.Size(1066, 22); + this.statusStrip.TabIndex = 1; + // + // blobsCountLabel + // + this.blobsCountLabel.AutoSize = false; + this.blobsCountLabel.BorderSides = ((System.Windows.Forms.ToolStripStatusLabelBorderSides)((((System.Windows.Forms.ToolStripStatusLabelBorderSides.Left | System.Windows.Forms.ToolStripStatusLabelBorderSides.Top) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Right) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Bottom))); + this.blobsCountLabel.BorderStyle = System.Windows.Forms.Border3DStyle.SunkenInner; + this.blobsCountLabel.Name = "blobsCountLabel"; + this.blobsCountLabel.Size = new System.Drawing.Size(1043, 17); + this.blobsCountLabel.Spring = true; + this.blobsCountLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // openFileDialog + // + this.openFileDialog.Filter = "Image files (*.jpg,*.png,*.tif,*.bmp,*.gif)|*.jpg;*.png;*.tif;*.bmp;*.gif|JPG fil" + + "es (*.jpg)|*.jpg|PNG files (*.png)|*.png|TIF files (*.tif)|*.tif|BMP files (*.bm" + + "p)|*.bmp|GIF files (*.gif)|*.gif"; + this.openFileDialog.Title = "Open image file"; + // + // splitContainer + // + this.splitContainer.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer.Location = new System.Drawing.Point(0, 35); + this.splitContainer.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.splitContainer.Name = "splitContainer"; + // + // splitContainer.Panel1 + // + this.splitContainer.Panel1.Controls.Add(this.blobsBrowser); + // + // splitContainer.Panel2 + // + this.splitContainer.Panel2.Controls.Add(this.groupBox1); + this.splitContainer.Panel2.Controls.Add(this.propertyGrid); + this.splitContainer.Panel2MinSize = 100; + this.splitContainer.Size = new System.Drawing.Size(1066, 614); + this.splitContainer.SplitterDistance = 746; + this.splitContainer.SplitterWidth = 6; + this.splitContainer.TabIndex = 2; + // + // blobsBrowser + // + this.blobsBrowser.Highlighting = BlobsBrowser.HightlightType.Quadrilateral; + this.blobsBrowser.Location = new System.Drawing.Point(212, 186); + this.blobsBrowser.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.blobsBrowser.Name = "blobsBrowser"; + this.blobsBrowser.ShowRectangleAroundSelection = false; + this.blobsBrowser.Size = new System.Drawing.Size(322, 242); + this.blobsBrowser.TabIndex = 0; + this.blobsBrowser.BlobSelected += new BlobSelectionHandler(this.blobsBrowser_BlobSelected); + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.showRectangleAroundSelectionCheck); + this.groupBox1.Controls.Add(this.highlightTypeCombo); + this.groupBox1.Location = new System.Drawing.Point(4, 5); + this.groupBox1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox1.Size = new System.Drawing.Size(298, 100); + this.groupBox1.TabIndex = 1; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Highlight Type"; + // + // showRectangleAroundSelectionCheck + // + this.showRectangleAroundSelectionCheck.AutoSize = true; + this.showRectangleAroundSelectionCheck.Location = new System.Drawing.Point(9, 69); + this.showRectangleAroundSelectionCheck.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.showRectangleAroundSelectionCheck.Name = "showRectangleAroundSelectionCheck"; + this.showRectangleAroundSelectionCheck.Size = new System.Drawing.Size(266, 24); + this.showRectangleAroundSelectionCheck.TabIndex = 1; + this.showRectangleAroundSelectionCheck.Text = "Show rectangle around selection"; + this.showRectangleAroundSelectionCheck.UseVisualStyleBackColor = true; + this.showRectangleAroundSelectionCheck.CheckedChanged += new System.EventHandler(this.showRectangleAroundSelectionCheck_CheckedChanged); + // + // highlightTypeCombo + // + this.highlightTypeCombo.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.highlightTypeCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.highlightTypeCombo.FormattingEnabled = true; + this.highlightTypeCombo.Items.AddRange(new object[] { + "Convex Hull", + "Left/Right Edges", + "Top/Bottom Edges", + "Quadrilateral"}); + this.highlightTypeCombo.Location = new System.Drawing.Point(9, 31); + this.highlightTypeCombo.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.highlightTypeCombo.Name = "highlightTypeCombo"; + this.highlightTypeCombo.Size = new System.Drawing.Size(278, 28); + this.highlightTypeCombo.TabIndex = 0; + this.highlightTypeCombo.SelectedIndexChanged += new System.EventHandler(this.highlightTypeCombo_SelectedIndexChanged); + // + // propertyGrid + // + this.propertyGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.propertyGrid.HelpVisible = false; + this.propertyGrid.Location = new System.Drawing.Point(0, 114); + this.propertyGrid.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.propertyGrid.Name = "propertyGrid"; + this.propertyGrid.Size = new System.Drawing.Size(312, 500); + this.propertyGrid.TabIndex = 0; + this.propertyGrid.ToolbarVisible = false; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(1066, 671); + this.Controls.Add(this.splitContainer); + this.Controls.Add(this.statusStrip); + this.Controls.Add(this.mainMenu); + this.MainMenuStrip = this.mainMenu; + this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.MinimumSize = new System.Drawing.Size(709, 524); + this.Name = "MainForm"; + this.Text = "Blobs Explorer"; + this.Load += new System.EventHandler(this.MainForm_Load); + this.mainMenu.ResumeLayout(false); + this.mainMenu.PerformLayout(); + this.statusStrip.ResumeLayout(false); + this.statusStrip.PerformLayout(); + this.splitContainer.Panel1.ResumeLayout(false); + this.splitContainer.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit(); + this.splitContainer.ResumeLayout(false); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.MenuStrip mainMenu; + private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; + private System.Windows.Forms.StatusStrip statusStrip; + private System.Windows.Forms.ToolStripMenuItem openToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1; + private System.Windows.Forms.OpenFileDialog openFileDialog; + private System.Windows.Forms.SplitContainer splitContainer; + private System.Windows.Forms.PropertyGrid propertyGrid; + private BlobsBrowser blobsBrowser; + private System.Windows.Forms.ToolStripStatusLabel blobsCountLabel; + private System.Windows.Forms.ToolStripMenuItem loaddemoImageToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.ComboBox highlightTypeCombo; + private System.Windows.Forms.CheckBox showRectangleAroundSelectionCheck; + } +} + diff --git a/Samples/Imaging/Detection (Blobs)/MainForm.cs b/Samples/Imaging/Detection (Blobs)/MainForm.cs new file mode 100644 index 0000000000..e10a2a3dc --- /dev/null +++ b/Samples/Imaging/Detection (Blobs)/MainForm.cs @@ -0,0 +1,111 @@ +// Blobs Browser sample application +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; +using System.Resources; +using System.Reflection; + +using AForge.Imaging; + +namespace SampleApp +{ + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + + highlightTypeCombo.SelectedIndex = 0; + showRectangleAroundSelectionCheck.Checked = blobsBrowser.ShowRectangleAroundSelection; + } + + // On loading of the form + private void MainForm_Load(object sender, EventArgs e) + { + LoadDemo(); + } + + // Exit from application + private void exitToolStripMenuItem_Click(object sender, EventArgs e) + { + this.Close(); + } + + // Open file + private void openToolStripMenuItem_Click(object sender, EventArgs e) + { + if (openFileDialog.ShowDialog() == DialogResult.OK) + { + try + { + ProcessImage((Bitmap)Bitmap.FromFile(openFileDialog.FileName)); + } + catch + { + MessageBox.Show("Failed loading selected image file.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } + + // Process image + private void ProcessImage(Bitmap image) + { + int foundBlobsCount = blobsBrowser.SetImage(image); + + blobsCountLabel.Text = string.Format("Found blobs' count: {0}", foundBlobsCount); + propertyGrid.SelectedObject = null; + } + + // Blob was selected - display its information + private void blobsBrowser_BlobSelected(object sender, Blob blob) + { + propertyGrid.SelectedObject = blob; + propertyGrid.ExpandAllGridItems(); + } + + // Load demo image + private void loaddemoImageToolStripMenuItem_Click(object sender, EventArgs e) + { + LoadDemo(); + } + + private void LoadDemo() + { + // load arrow bitmap + Assembly assembly = this.GetType().Assembly; + Bitmap image = new Bitmap(Properties.Resources.demo); + ProcessImage(image); + } + + // Show about form + private void aboutToolStripMenuItem_Click(object sender, EventArgs e) + { + AboutForm form = new AboutForm(); + + form.ShowDialog(); + } + + // Change type of blobs' highlighting + private void highlightTypeCombo_SelectedIndexChanged(object sender, EventArgs e) + { + blobsBrowser.Highlighting = (BlobsBrowser.HightlightType)highlightTypeCombo.SelectedIndex; + } + + // Toggle displaying of rectangle around selection + private void showRectangleAroundSelectionCheck_CheckedChanged(object sender, EventArgs e) + { + blobsBrowser.ShowRectangleAroundSelection = showRectangleAroundSelectionCheck.Checked; + } + } +} diff --git a/Samples/Imaging/Detection (Blobs)/MainForm.resx b/Samples/Imaging/Detection (Blobs)/MainForm.resx new file mode 100644 index 0000000000..819a00319 --- /dev/null +++ b/Samples/Imaging/Detection (Blobs)/MainForm.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 127, 17 + + + 236, 17 + + \ No newline at end of file diff --git a/Samples/Imaging/Detection (Blobs)/Program.cs b/Samples/Imaging/Detection (Blobs)/Program.cs new file mode 100644 index 0000000000..316268492 --- /dev/null +++ b/Samples/Imaging/Detection (Blobs)/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Windows.Forms; + +namespace SampleApp +{ + static class Program + { + [STAThread] + static void Main() + { + if (Environment.OSVersion.Version.Major >= 6) + SetProcessDPIAware(); + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + + [System.Runtime.InteropServices.DllImport("user32.dll")] + private static extern bool SetProcessDPIAware(); + } +} diff --git a/Samples/Imaging/Detection (Blobs)/Properties/AssemblyInfo.cs b/Samples/Imaging/Detection (Blobs)/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..f7b27093a --- /dev/null +++ b/Samples/Imaging/Detection (Blobs)/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Blobs Explorer")] +[assembly: AssemblyDescription("Blobs Explorer sample")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("AForge")] +[assembly: AssemblyProduct("AForge.NET")] +[assembly: AssemblyCopyright("AForge © 2009")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("ee0212a1-9013-46bf-b859-36a6ee62b4a6")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Samples/Imaging/Detection (Blobs)/Properties/Resources.Designer.cs b/Samples/Imaging/Detection (Blobs)/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..662cb028d --- /dev/null +++ b/Samples/Imaging/Detection (Blobs)/Properties/Resources.Designer.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap demo { + get { + object obj = ResourceManager.GetObject("demo", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/Samples/Imaging/Detection (Blobs)/Properties/Resources.resx b/Samples/Imaging/Detection (Blobs)/Properties/Resources.resx new file mode 100644 index 0000000000..42bd24156 --- /dev/null +++ b/Samples/Imaging/Detection (Blobs)/Properties/Resources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\demo.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/Samples/Imaging/Detection (Blobs)/Properties/Settings.Designer.cs b/Samples/Imaging/Detection (Blobs)/Properties/Settings.Designer.cs new file mode 100644 index 0000000000..dbc9e5d22 --- /dev/null +++ b/Samples/Imaging/Detection (Blobs)/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Samples/Imaging/Detection (Blobs)/Properties/Settings.settings b/Samples/Imaging/Detection (Blobs)/Properties/Settings.settings new file mode 100644 index 0000000000..39645652a --- /dev/null +++ b/Samples/Imaging/Detection (Blobs)/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Samples/Imaging/Detection (Blobs)/app.config b/Samples/Imaging/Detection (Blobs)/app.config new file mode 100644 index 0000000000..57c0f2cbc --- /dev/null +++ b/Samples/Imaging/Detection (Blobs)/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Samples/Imaging/Detection (Blobs)/demo.png b/Samples/Imaging/Detection (Blobs)/demo.png new file mode 100644 index 0000000000..1702b8aa8 Binary files /dev/null and b/Samples/Imaging/Detection (Blobs)/demo.png differ diff --git a/Samples/Imaging/Detection (Shape)/AboutForm.Designer.cs b/Samples/Imaging/Detection (Shape)/AboutForm.Designer.cs new file mode 100644 index 0000000000..249dc26e8 --- /dev/null +++ b/Samples/Imaging/Detection (Shape)/AboutForm.Designer.cs @@ -0,0 +1,130 @@ +namespace SampleApp +{ + partial class AboutForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.panel1 = new System.Windows.Forms.Panel( ); + this.emailLabel = new System.Windows.Forms.LinkLabel( ); + this.label3 = new System.Windows.Forms.Label( ); + this.aforgeLabel = new System.Windows.Forms.LinkLabel( ); + this.label2 = new System.Windows.Forms.Label( ); + this.label1 = new System.Windows.Forms.Label( ); + this.panel1.SuspendLayout( ); + this.SuspendLayout( ); + // + // panel1 + // + this.panel1.Controls.Add( this.emailLabel ); + this.panel1.Controls.Add( this.label3 ); + this.panel1.Controls.Add( this.aforgeLabel ); + this.panel1.Controls.Add( this.label2 ); + this.panel1.Controls.Add( this.label1 ); + this.panel1.Location = new System.Drawing.Point( 13, 12 ); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size( 303, 139 ); + this.panel1.TabIndex = 4; + // + // emailLabel + // + this.emailLabel.AutoSize = true; + this.emailLabel.Location = new System.Drawing.Point( 75, 108 ); + this.emailLabel.Name = "emailLabel"; + this.emailLabel.Size = new System.Drawing.Size( 153, 13 ); + this.emailLabel.TabIndex = 5; + this.emailLabel.TabStop = true; + this.emailLabel.Text = "andrew.kirillov@aforgenet.com"; + this.emailLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler( this.LinkClicked ); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point( 69, 93 ); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size( 165, 13 ); + this.label3.TabIndex = 4; + this.label3.Text = "Copyright © 2010, Andrew Kirillov"; + // + // aforgeLabel + // + this.aforgeLabel.AutoSize = true; + this.aforgeLabel.Location = new System.Drawing.Point( 55, 58 ); + this.aforgeLabel.Name = "aforgeLabel"; + this.aforgeLabel.Size = new System.Drawing.Size( 192, 13 ); + this.aforgeLabel.TabIndex = 3; + this.aforgeLabel.TabStop = true; + this.aforgeLabel.Text = "http://www.aforgenet.com/framework/"; + this.aforgeLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler( this.LinkClicked ); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point( 39, 43 ); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size( 225, 13 ); + this.label2.TabIndex = 2; + this.label2.Text = "Sample application of AForge.NET framework:"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point( 80, 18 ); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size( 142, 13 ); + this.label1.TabIndex = 1; + this.label1.Text = "Simple Shape Checker 1.0.0"; + // + // AboutForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 13F ); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size( 329, 162 ); + this.Controls.Add( this.panel1 ); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "AboutForm"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "About"; + this.panel1.ResumeLayout( false ); + this.panel1.PerformLayout( ); + this.ResumeLayout( false ); + + } + + #endregion + + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.LinkLabel emailLabel; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.LinkLabel aforgeLabel; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + } +} \ No newline at end of file diff --git a/Samples/Imaging/Detection (Shape)/AboutForm.cs b/Samples/Imaging/Detection (Shape)/AboutForm.cs new file mode 100644 index 0000000000..7b0330ce2 --- /dev/null +++ b/Samples/Imaging/Detection (Shape)/AboutForm.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace SampleApp +{ + public partial class AboutForm : Form + { + public AboutForm() + { + InitializeComponent(); + + // initialize links + emailLabel.Links.Add(0, emailLabel.Text.Length, "mailto:andrew.kirillov@aforgenet.com"); + aforgeLabel.Links.Add(0, aforgeLabel.Text.Length, "http://www.aforgenet.com/framework/"); + } + + private void LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + System.Diagnostics.Process.Start(e.Link.LinkData.ToString()); + } + } +} diff --git a/Samples/Imaging/Detection (Shape)/AboutForm.resx b/Samples/Imaging/Detection (Shape)/AboutForm.resx new file mode 100644 index 0000000000..19dc0dd8b --- /dev/null +++ b/Samples/Imaging/Detection (Shape)/AboutForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Imaging/Detection (Shape)/Detection (Shape).csproj b/Samples/Imaging/Detection (Shape)/Detection (Shape).csproj new file mode 100644 index 0000000000..d4f55f13e --- /dev/null +++ b/Samples/Imaging/Detection (Shape)/Detection (Shape).csproj @@ -0,0 +1,147 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {722FD1AB-4193-45B1-A94E-10B6E5C9AA05} + WinExe + Properties + SampleApp + Detection %28Shape%29 + v4.0 + 512 + + + 3.5 + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + + ..\..\..\Release\net40\Accord.dll + + + ..\..\..\Release\net40\Accord.Imaging.dll + + + ..\..\..\Release\net40\Accord.Math.dll + + + + + + + + + Form + + + AboutForm.cs + + + Form + + + MainForm.cs + + + + + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + AboutForm.cs + + + + + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + \ No newline at end of file diff --git a/Samples/Imaging/Detection (Shape)/MainForm.Designer.cs b/Samples/Imaging/Detection (Shape)/MainForm.Designer.cs new file mode 100644 index 0000000000..66ad596d4 --- /dev/null +++ b/Samples/Imaging/Detection (Shape)/MainForm.Designer.cs @@ -0,0 +1,369 @@ +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.components = new System.ComponentModel.Container( ); + this.pictureBox = new System.Windows.Forms.PictureBox( ); + this.menuStrip = new System.Windows.Forms.MenuStrip( ); + this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.openToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator( ); + this.loadDemoImage1ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.loadDemoImage2ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.loadDemoImage3ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.loadDemoImage4ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator( ); + this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.groupBox1 = new System.Windows.Forms.GroupBox( ); + this.label9 = new System.Windows.Forms.Label( ); + this.label10 = new System.Windows.Forms.Label( ); + this.label7 = new System.Windows.Forms.Label( ); + this.label8 = new System.Windows.Forms.Label( ); + this.label5 = new System.Windows.Forms.Label( ); + this.label6 = new System.Windows.Forms.Label( ); + this.label3 = new System.Windows.Forms.Label( ); + this.label4 = new System.Windows.Forms.Label( ); + this.label2 = new System.Windows.Forms.Label( ); + this.label1 = new System.Windows.Forms.Label( ); + this.openFileDialog = new System.Windows.Forms.OpenFileDialog( ); + this.splitContainer = new System.Windows.Forms.SplitContainer( ); + this.toolTip = new System.Windows.Forms.ToolTip( this.components ); + ( (System.ComponentModel.ISupportInitialize) ( this.pictureBox ) ).BeginInit( ); + this.menuStrip.SuspendLayout( ); + this.groupBox1.SuspendLayout( ); + this.splitContainer.Panel1.SuspendLayout( ); + this.splitContainer.Panel2.SuspendLayout( ); + this.splitContainer.SuspendLayout( ); + this.SuspendLayout( ); + // + // pictureBox + // + this.pictureBox.BackColor = System.Drawing.SystemColors.ControlDark; + this.pictureBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.pictureBox.Location = new System.Drawing.Point( 102, 32 ); + this.pictureBox.Name = "pictureBox"; + this.pictureBox.Size = new System.Drawing.Size( 320, 240 ); + this.pictureBox.TabIndex = 0; + this.pictureBox.TabStop = false; + // + // menuStrip + // + this.menuStrip.Items.AddRange( new System.Windows.Forms.ToolStripItem[] { + this.fileToolStripMenuItem, + this.helpToolStripMenuItem} ); + this.menuStrip.Location = new System.Drawing.Point( 0, 0 ); + this.menuStrip.Name = "menuStrip"; + this.menuStrip.Size = new System.Drawing.Size( 524, 24 ); + this.menuStrip.TabIndex = 0; + // + // fileToolStripMenuItem + // + this.fileToolStripMenuItem.DropDownItems.AddRange( new System.Windows.Forms.ToolStripItem[] { + this.openToolStripMenuItem, + this.toolStripMenuItem1, + this.loadDemoImage1ToolStripMenuItem, + this.loadDemoImage2ToolStripMenuItem, + this.loadDemoImage3ToolStripMenuItem, + this.loadDemoImage4ToolStripMenuItem, + this.toolStripMenuItem2, + this.exitToolStripMenuItem} ); + this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; + this.fileToolStripMenuItem.Size = new System.Drawing.Size( 37, 20 ); + this.fileToolStripMenuItem.Text = "&File"; + // + // openToolStripMenuItem + // + this.openToolStripMenuItem.Name = "openToolStripMenuItem"; + this.openToolStripMenuItem.ShortcutKeys = ( (System.Windows.Forms.Keys) ( ( System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O ) ) ); + this.openToolStripMenuItem.Size = new System.Drawing.Size( 179, 22 ); + this.openToolStripMenuItem.Text = "&Open"; + this.openToolStripMenuItem.Click += new System.EventHandler( this.openToolStripMenuItem_Click ); + // + // toolStripMenuItem1 + // + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + this.toolStripMenuItem1.Size = new System.Drawing.Size( 176, 6 ); + // + // loadDemoImage1ToolStripMenuItem + // + this.loadDemoImage1ToolStripMenuItem.Name = "loadDemoImage1ToolStripMenuItem"; + this.loadDemoImage1ToolStripMenuItem.Size = new System.Drawing.Size( 179, 22 ); + this.loadDemoImage1ToolStripMenuItem.Text = "Load demo image &1"; + this.loadDemoImage1ToolStripMenuItem.Click += new System.EventHandler( this.loadDemoImage1ToolStripMenuItem_Click ); + // + // loadDemoImage2ToolStripMenuItem + // + this.loadDemoImage2ToolStripMenuItem.Name = "loadDemoImage2ToolStripMenuItem"; + this.loadDemoImage2ToolStripMenuItem.Size = new System.Drawing.Size( 179, 22 ); + this.loadDemoImage2ToolStripMenuItem.Text = "Load demo image &2"; + this.loadDemoImage2ToolStripMenuItem.Click += new System.EventHandler( this.loadDemoImage2ToolStripMenuItem_Click ); + // + // loadDemoImage3ToolStripMenuItem + // + this.loadDemoImage3ToolStripMenuItem.Name = "loadDemoImage3ToolStripMenuItem"; + this.loadDemoImage3ToolStripMenuItem.Size = new System.Drawing.Size( 179, 22 ); + this.loadDemoImage3ToolStripMenuItem.Text = "Load demo image &3"; + this.loadDemoImage3ToolStripMenuItem.Click += new System.EventHandler( this.loadDemoImage3ToolStripMenuItem_Click ); + // + // loadDemoImage4ToolStripMenuItem + // + this.loadDemoImage4ToolStripMenuItem.Name = "loadDemoImage4ToolStripMenuItem"; + this.loadDemoImage4ToolStripMenuItem.Size = new System.Drawing.Size( 179, 22 ); + this.loadDemoImage4ToolStripMenuItem.Text = "Load demo image &4"; + this.loadDemoImage4ToolStripMenuItem.Click += new System.EventHandler( this.loadDemoImage4ToolStripMenuItem_Click ); + // + // toolStripMenuItem2 + // + this.toolStripMenuItem2.Name = "toolStripMenuItem2"; + this.toolStripMenuItem2.Size = new System.Drawing.Size( 176, 6 ); + // + // exitToolStripMenuItem + // + this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; + this.exitToolStripMenuItem.Size = new System.Drawing.Size( 179, 22 ); + this.exitToolStripMenuItem.Text = "E&xit"; + this.exitToolStripMenuItem.Click += new System.EventHandler( this.exitToolStripMenuItem_Click ); + // + // helpToolStripMenuItem + // + this.helpToolStripMenuItem.DropDownItems.AddRange( new System.Windows.Forms.ToolStripItem[] { + this.aboutToolStripMenuItem} ); + this.helpToolStripMenuItem.Name = "helpToolStripMenuItem"; + this.helpToolStripMenuItem.Size = new System.Drawing.Size( 44, 20 ); + this.helpToolStripMenuItem.Text = "&Help"; + // + // aboutToolStripMenuItem + // + this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem"; + this.aboutToolStripMenuItem.Size = new System.Drawing.Size( 107, 22 ); + this.aboutToolStripMenuItem.Text = "&About"; + this.aboutToolStripMenuItem.Click += new System.EventHandler( this.aboutToolStripMenuItem_Click ); + // + // groupBox1 + // + this.groupBox1.Anchor = ( (System.Windows.Forms.AnchorStyles) ( ( ( System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left ) + | System.Windows.Forms.AnchorStyles.Right ) ) ); + this.groupBox1.Controls.Add( this.label9 ); + this.groupBox1.Controls.Add( this.label10 ); + this.groupBox1.Controls.Add( this.label7 ); + this.groupBox1.Controls.Add( this.label8 ); + this.groupBox1.Controls.Add( this.label5 ); + this.groupBox1.Controls.Add( this.label6 ); + this.groupBox1.Controls.Add( this.label3 ); + this.groupBox1.Controls.Add( this.label4 ); + this.groupBox1.Controls.Add( this.label2 ); + this.groupBox1.Controls.Add( this.label1 ); + this.groupBox1.Location = new System.Drawing.Point( 10, 1 ); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size( 502, 45 ); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Legend"; + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Location = new System.Drawing.Point( 410, 22 ); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size( 82, 13 ); + this.label9.TabIndex = 9; + this.label9.Text = "Known triangles"; + this.toolTip.SetToolTip( this.label9, "Equilateral, Isosceles, Rectangled or Rectangled Isosceles Triangle" ); + // + // label10 + // + this.label10.BackColor = System.Drawing.Color.Green; + this.label10.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.label10.Location = new System.Drawing.Point( 390, 18 ); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size( 20, 20 ); + this.label10.TabIndex = 8; + this.toolTip.SetToolTip( this.label10, "Equilateral, Isosceles, Rectangled or Rectangled Isosceles Triangle" ); + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point( 330, 22 ); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size( 50, 13 ); + this.label7.TabIndex = 7; + this.label7.Text = "Triangles"; + // + // label8 + // + this.label8.BackColor = System.Drawing.Color.Blue; + this.label8.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.label8.Location = new System.Drawing.Point( 310, 18 ); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size( 20, 20 ); + this.label8.TabIndex = 6; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point( 200, 22 ); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size( 105, 13 ); + this.label5.TabIndex = 5; + this.label5.Text = "Known quadrilaterals"; + this.toolTip.SetToolTip( this.label5, "Trapezoid, Parallelogram, Rectangle, Rhombus or Square" ); + // + // label6 + // + this.label6.BackColor = System.Drawing.Color.Brown; + this.label6.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.label6.Location = new System.Drawing.Point( 180, 18 ); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size( 20, 20 ); + this.label6.TabIndex = 4; + this.toolTip.SetToolTip( this.label6, "Trapezoid, Parallelogram, Rectangle, Rhombus or Square" ); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point( 100, 22 ); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size( 71, 13 ); + this.label3.TabIndex = 3; + this.label3.Text = "Quadrilaterals"; + // + // label4 + // + this.label4.BackColor = System.Drawing.Color.Red; + this.label4.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.label4.Location = new System.Drawing.Point( 80, 18 ); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size( 20, 20 ); + this.label4.TabIndex = 2; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point( 30, 22 ); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size( 38, 13 ); + this.label2.TabIndex = 1; + this.label2.Text = "Circles"; + // + // label1 + // + this.label1.BackColor = System.Drawing.Color.Yellow; + this.label1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.label1.Location = new System.Drawing.Point( 10, 18 ); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size( 20, 20 ); + this.label1.TabIndex = 0; + // + // openFileDialog + // + this.openFileDialog.Filter = "Image files (*.jpg,*.png,*.tif,*.bmp,*.gif)|*.jpg;*.png;*.tif;*.bmp;*.gif|JPG fil" + + "es (*.jpg)|*.jpg|PNG files (*.png)|*.png|TIF files (*.tif)|*.tif|BMP files (*.bm" + + "p)|*.bmp|GIF files (*.gif)|*.gif"; + this.openFileDialog.Title = "Open image file"; + // + // splitContainer + // + this.splitContainer.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer.Location = new System.Drawing.Point( 0, 24 ); + this.splitContainer.Name = "splitContainer"; + this.splitContainer.Orientation = System.Windows.Forms.Orientation.Horizontal; + // + // splitContainer.Panel1 + // + this.splitContainer.Panel1.Controls.Add( this.groupBox1 ); + // + // splitContainer.Panel2 + // + this.splitContainer.Panel2.Controls.Add( this.pictureBox ); + this.splitContainer.Panel2.Resize += new System.EventHandler( this.splitContainer_Panel2_Resize ); + this.splitContainer.Size = new System.Drawing.Size( 524, 358 ); + this.splitContainer.SplitterDistance = 51; + this.splitContainer.TabIndex = 1; + this.splitContainer.TabStop = false; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 13F ); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.SystemColors.Control; + this.ClientSize = new System.Drawing.Size( 524, 382 ); + this.Controls.Add( this.splitContainer ); + this.Controls.Add( this.menuStrip ); + this.MainMenuStrip = this.menuStrip; + this.MinimumSize = new System.Drawing.Size( 540, 420 ); + this.Name = "MainForm"; + this.Text = "Simple Shape Checker"; + this.Load += new System.EventHandler( this.MainForm_Load ); + ( (System.ComponentModel.ISupportInitialize) ( this.pictureBox ) ).EndInit( ); + this.menuStrip.ResumeLayout( false ); + this.menuStrip.PerformLayout( ); + this.groupBox1.ResumeLayout( false ); + this.groupBox1.PerformLayout( ); + this.splitContainer.Panel1.ResumeLayout( false ); + this.splitContainer.Panel2.ResumeLayout( false ); + this.splitContainer.ResumeLayout( false ); + this.ResumeLayout( false ); + this.PerformLayout( ); + + } + + #endregion + + private System.Windows.Forms.PictureBox pictureBox; + private System.Windows.Forms.MenuStrip menuStrip; + private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem openToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem loadDemoImage1ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem loadDemoImage2ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem loadDemoImage3ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem loadDemoImage4ToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripMenuItem2; + private System.Windows.Forms.OpenFileDialog openFileDialog; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.SplitContainer splitContainer; + private System.Windows.Forms.ToolTip toolTip; + private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem; + } +} + diff --git a/Samples/Imaging/Detection (Shape)/MainForm.cs b/Samples/Imaging/Detection (Shape)/MainForm.cs new file mode 100644 index 0000000000..e3078d0a8 --- /dev/null +++ b/Samples/Imaging/Detection (Shape)/MainForm.cs @@ -0,0 +1,238 @@ +// Simple Shape Checker sample application +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.Data; +using System.Drawing; +using System.Drawing.Imaging; +using System.Windows.Forms; +using System.Reflection; + +using AForge; +using AForge.Imaging; +using AForge.Imaging.Filters; +using AForge.Math.Geometry; + +namespace SampleApp +{ + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + } + + // Exit from application + private void exitToolStripMenuItem_Click(object sender, EventArgs e) + { + this.Close(); + } + + // On loading of the form + private void MainForm_Load(object sender, EventArgs e) + { + LoadDemo("coins.jpg"); + } + + // Open file + private void openToolStripMenuItem_Click(object sender, EventArgs e) + { + if (openFileDialog.ShowDialog() == DialogResult.OK) + { + try + { + ProcessImage((Bitmap)Bitmap.FromFile(openFileDialog.FileName)); + } + catch + { + MessageBox.Show("Failed loading selected image file.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } + + // Load first demo image + private void loadDemoImage1ToolStripMenuItem_Click(object sender, EventArgs e) + { + LoadDemo("coins.jpg"); + } + + // Load second demo image + private void loadDemoImage2ToolStripMenuItem_Click(object sender, EventArgs e) + { + LoadDemo("demo.png"); + } + + // Load third demo image + private void loadDemoImage3ToolStripMenuItem_Click(object sender, EventArgs e) + { + LoadDemo("demo1.png"); + } + + // Load fourth demo image + private void loadDemoImage4ToolStripMenuItem_Click(object sender, EventArgs e) + { + LoadDemo("demo2.png"); + } + + // Load one of the embedded demo image + private void LoadDemo(string embeddedFileName) + { + // load arrow bitmap + Assembly assembly = this.GetType().Assembly; + Bitmap image = new Bitmap(assembly.GetManifestResourceStream("SampleApp." + embeddedFileName)); + ProcessImage(image); + } + + // Process image + private void ProcessImage(Bitmap bitmap) + { + // lock image + BitmapData bitmapData = bitmap.LockBits( + new Rectangle(0, 0, bitmap.Width, bitmap.Height), + ImageLockMode.ReadWrite, bitmap.PixelFormat); + + // step 1 - turn background to black + ColorFiltering colorFilter = new ColorFiltering(); + + colorFilter.Red = new IntRange(0, 64); + colorFilter.Green = new IntRange(0, 64); + colorFilter.Blue = new IntRange(0, 64); + colorFilter.FillOutsideRange = false; + + colorFilter.ApplyInPlace(bitmapData); + + // step 2 - locating objects + BlobCounter blobCounter = new BlobCounter(); + + blobCounter.FilterBlobs = true; + blobCounter.MinHeight = 5; + blobCounter.MinWidth = 5; + + blobCounter.ProcessImage(bitmapData); + Blob[] blobs = blobCounter.GetObjectsInformation(); + bitmap.UnlockBits(bitmapData); + + // step 3 - check objects' type and highlight + SimpleShapeChecker shapeChecker = new SimpleShapeChecker(); + + Graphics g = Graphics.FromImage(bitmap); + Pen yellowPen = new Pen(Color.Yellow, 2); // circles + Pen redPen = new Pen(Color.Red, 2); // quadrilateral + Pen brownPen = new Pen(Color.Brown, 2); // quadrilateral with known sub-type + Pen greenPen = new Pen(Color.Green, 2); // known triangle + Pen bluePen = new Pen(Color.Blue, 2); // triangle + + for (int i = 0, n = blobs.Length; i < n; i++) + { + List edgePoints = blobCounter.GetBlobsEdgePoints(blobs[i]); + + AForge.Point center; + float radius; + + // is circle ? + if (shapeChecker.IsCircle(edgePoints, out center, out radius)) + { + g.DrawEllipse(yellowPen, + (float)(center.X - radius), (float)(center.Y - radius), + (float)(radius * 2), (float)(radius * 2)); + } + else + { + List corners; + + // is triangle or quadrilateral + if (shapeChecker.IsConvexPolygon(edgePoints, out corners)) + { + // get sub-type + PolygonSubType subType = shapeChecker.CheckPolygonSubType(corners); + + Pen pen; + + if (subType == PolygonSubType.Unknown) + { + pen = (corners.Count == 4) ? redPen : bluePen; + } + else + { + pen = (corners.Count == 4) ? brownPen : greenPen; + } + + g.DrawPolygon(pen, ToPointsArray(corners)); + } + } + } + + yellowPen.Dispose(); + redPen.Dispose(); + greenPen.Dispose(); + bluePen.Dispose(); + brownPen.Dispose(); + g.Dispose(); + + // put new image to clipboard + Clipboard.SetDataObject(bitmap); + // and to picture box + pictureBox.Image = bitmap; + + UpdatePictureBoxPosition(); + } + + // Size of main panel has changed + private void splitContainer_Panel2_Resize(object sender, EventArgs e) + { + UpdatePictureBoxPosition(); + } + + // Update size and position of picture box control + private void UpdatePictureBoxPosition() + { + int imageWidth; + int imageHeight; + + if (pictureBox.Image == null) + { + imageWidth = 320; + imageHeight = 240; + } + else + { + imageWidth = pictureBox.Image.Width; + imageHeight = pictureBox.Image.Height; + } + + Rectangle rc = splitContainer.Panel2.ClientRectangle; + + pictureBox.SuspendLayout(); + pictureBox.Location = new System.Drawing.Point((rc.Width - imageWidth - 2) / 2, (rc.Height - imageHeight - 2) / 2); + pictureBox.Size = new Size(imageWidth + 2, imageHeight + 2); + pictureBox.ResumeLayout(); + } + + // Conver list of AForge.NET's points to array of .NET points + private System.Drawing.Point[] ToPointsArray(List points) + { + System.Drawing.Point[] array = new System.Drawing.Point[points.Count]; + + for (int i = 0, n = points.Count; i < n; i++) + { + array[i] = new System.Drawing.Point(points[i].X, points[i].Y); + } + + return array; + } + + // Show about form + private void aboutToolStripMenuItem_Click(object sender, EventArgs e) + { + AboutForm form = new AboutForm(); + + form.ShowDialog(); + } + } +} diff --git a/Samples/Imaging/Detection (Shape)/MainForm.resx b/Samples/Imaging/Detection (Shape)/MainForm.resx new file mode 100644 index 0000000000..8916ec6d1 --- /dev/null +++ b/Samples/Imaging/Detection (Shape)/MainForm.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 262, 16 + + + 129, 16 + + \ No newline at end of file diff --git a/Samples/Imaging/Detection (Shape)/Program.cs b/Samples/Imaging/Detection (Shape)/Program.cs new file mode 100644 index 0000000000..bf6372ed8 --- /dev/null +++ b/Samples/Imaging/Detection (Shape)/Program.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; + +namespace SampleApp +{ + static class Program + { + [STAThread] + static void Main() + { + if (Environment.OSVersion.Version.Major >= 6) + SetProcessDPIAware(); + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + + [System.Runtime.InteropServices.DllImport("user32.dll")] + private static extern bool SetProcessDPIAware(); + } +} diff --git a/Samples/Imaging/Detection (Shape)/Properties/AssemblyInfo.cs b/Samples/Imaging/Detection (Shape)/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..96a42e1da --- /dev/null +++ b/Samples/Imaging/Detection (Shape)/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle( "Simple Shape Checker" )] +[assembly: AssemblyDescription( "Sample application of AForge.NET framework" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "AForge" )] +[assembly: AssemblyProduct( "AForge.NET" )] +[assembly: AssemblyCopyright( "AForge © 2010" )] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible( false )] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid( "8dadf358-4b02-42ac-a48a-4eff3b4384ec" )] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion( "1.0.0.0" )] +[assembly: AssemblyFileVersion( "1.0.0.0" )] diff --git a/Samples/Imaging/Detection (Shape)/Properties/Resources.Designer.cs b/Samples/Imaging/Detection (Shape)/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..7b58e53ee --- /dev/null +++ b/Samples/Imaging/Detection (Shape)/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Samples/Vision/Kinect/Properties/Resources.resx b/Samples/Imaging/Detection (Shape)/Properties/Resources.resx similarity index 100% rename from Samples/Vision/Kinect/Properties/Resources.resx rename to Samples/Imaging/Detection (Shape)/Properties/Resources.resx diff --git a/Samples/Imaging/Detection (Shape)/Properties/Settings.Designer.cs b/Samples/Imaging/Detection (Shape)/Properties/Settings.Designer.cs new file mode 100644 index 0000000000..dbc9e5d22 --- /dev/null +++ b/Samples/Imaging/Detection (Shape)/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Samples/Imaging/Detection (Shape)/Properties/Settings.settings b/Samples/Imaging/Detection (Shape)/Properties/Settings.settings new file mode 100644 index 0000000000..39645652a --- /dev/null +++ b/Samples/Imaging/Detection (Shape)/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Samples/Imaging/Detection (Shape)/ShapeChecker.sln b/Samples/Imaging/Detection (Shape)/ShapeChecker.sln new file mode 100644 index 0000000000..f8063682f --- /dev/null +++ b/Samples/Imaging/Detection (Shape)/ShapeChecker.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C# Express 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShapeChecker", "ShapeChecker.csproj", "{722FD1AB-4193-45B1-A94E-10B6E5C9AA05}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {722FD1AB-4193-45B1-A94E-10B6E5C9AA05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {722FD1AB-4193-45B1-A94E-10B6E5C9AA05}.Debug|Any CPU.Build.0 = Debug|Any CPU + {722FD1AB-4193-45B1-A94E-10B6E5C9AA05}.Release|Any CPU.ActiveCfg = Release|Any CPU + {722FD1AB-4193-45B1-A94E-10B6E5C9AA05}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/Imaging/Detection (Shape)/app.config b/Samples/Imaging/Detection (Shape)/app.config new file mode 100644 index 0000000000..57c0f2cbc --- /dev/null +++ b/Samples/Imaging/Detection (Shape)/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Samples/Imaging/Detection (Shape)/coins.jpg b/Samples/Imaging/Detection (Shape)/coins.jpg new file mode 100644 index 0000000000..fda16685e Binary files /dev/null and b/Samples/Imaging/Detection (Shape)/coins.jpg differ diff --git a/Samples/Imaging/Detection (Shape)/demo.png b/Samples/Imaging/Detection (Shape)/demo.png new file mode 100644 index 0000000000..2b1e3c6fb Binary files /dev/null and b/Samples/Imaging/Detection (Shape)/demo.png differ diff --git a/Samples/Imaging/Detection (Shape)/demo1.png b/Samples/Imaging/Detection (Shape)/demo1.png new file mode 100644 index 0000000000..7715d43d8 Binary files /dev/null and b/Samples/Imaging/Detection (Shape)/demo1.png differ diff --git a/Samples/Imaging/Detection (Shape)/demo2.png b/Samples/Imaging/Detection (Shape)/demo2.png new file mode 100644 index 0000000000..5196c1781 Binary files /dev/null and b/Samples/Imaging/Detection (Shape)/demo2.png differ diff --git a/Samples/Imaging/Filters (Images)/Accord.dll.config b/Samples/Imaging/Filters (Images)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Imaging/Filters (Images)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Imaging/Filters (Images)/App.ico b/Samples/Imaging/Filters (Images)/App.ico new file mode 100644 index 0000000000..3a5525fd7 Binary files /dev/null and b/Samples/Imaging/Filters (Images)/App.ico differ diff --git a/Samples/Imaging/Filters (Images)/AssemblyInfo.cs b/Samples/Imaging/Filters (Images)/AssemblyInfo.cs new file mode 100644 index 0000000000..1c196c095 --- /dev/null +++ b/Samples/Imaging/Filters (Images)/AssemblyInfo.cs @@ -0,0 +1,59 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle("Imaging Filters Demo")] +[assembly: AssemblyDescription("Imaging Filters Demo sample")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("AForge")] +[assembly: AssemblyProduct("AForge.NET")] +[assembly: AssemblyCopyright("AForge 2009")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("2.0.1.0")] +[assembly: AssemblyFileVersion("2.0.1.0")] + +// +// In order to sign your assembly you must specify a key to use. Refer to the +// Microsoft .NET Framework documentation for more information on assembly signing. +// +// Use the attributes below to control which key is used for signing. +// +// Notes: +// (*) If no key is specified, the assembly is not signed. +// (*) KeyName refers to a key that has been installed in the Crypto Service +// Provider (CSP) on your machine. KeyFile refers to a file which contains +// a key. +// (*) If the KeyFile and the KeyName values are both specified, the +// following processing occurs: +// (1) If the KeyName can be found in the CSP, that key is used. +// (2) If the KeyName does not exist and the KeyFile does exist, the key +// in the KeyFile is installed into the CSP and used. +// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. +// When specifying the KeyFile, the location of the KeyFile should be +// relative to the project output directory which is +// %Project Directory%\obj\. For example, if your KeyFile is +// located in the project directory, you would specify the AssemblyKeyFile +// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] +// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework +// documentation for more information on this. +// +[assembly: AssemblyDelaySign(false)] +[assembly: AssemblyKeyFile("")] +[assembly: AssemblyKeyName("")] diff --git a/Samples/Imaging/Filters (Images)/Filters (Images).csproj b/Samples/Imaging/Filters (Images)/Filters (Images).csproj new file mode 100644 index 0000000000..d3dc47c43 --- /dev/null +++ b/Samples/Imaging/Filters (Images)/Filters (Images).csproj @@ -0,0 +1,188 @@ + + + + Local + 8.0.50727 + 2.0 + {744FC79F-5B6D-44AD-8C34-1ABB6EABAE6B} + Debug + AnyCPU + App.ico + + + Filters %28images%29 + + + JScript + Grid + IE50 + false + WinExe + SampleApp + OnBuildSuccess + SampleApp.Program + + + + + 3.5 + v4.0 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + bin\Debug\ + false + 285212672 + false + + + DEBUG;TRACE + + + true + 4096 + false + + + false + false + false + false + 4 + full + prompt + + + bin\Release\ + false + 285212672 + false + + + TRACE + + + false + 4096 + false + + + true + false + false + false + 4 + none + prompt + + + true + bin\x86\Debug\ + DEBUG;TRACE + 285212672 + 4096 + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + 285212672 + true + 4096 + x86 + prompt + MinimumRecommendedRules.ruleset + + + + ..\..\..\Release\net40\Accord.dll + + + ..\..\..\Release\net40\Accord.Imaging.dll + + + ..\..\..\Release\net40\Accord.Math.dll + + + System + + + System.Data + + + System.Drawing + + + System.Windows.Forms + + + System.XML + + + + + + + Code + + + Form + + + MainForm.cs + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + PreserveNewest + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/Imaging/Filters (Images)/FiltersDemo.sln b/Samples/Imaging/Filters (Images)/FiltersDemo.sln new file mode 100644 index 0000000000..3f0060e78 --- /dev/null +++ b/Samples/Imaging/Filters (Images)/FiltersDemo.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C# Express 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FiltersDemo", "FiltersDemo.csproj", "{744FC79F-5B6D-44AD-8C34-1ABB6EABAE6B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {744FC79F-5B6D-44AD-8C34-1ABB6EABAE6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {744FC79F-5B6D-44AD-8C34-1ABB6EABAE6B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {744FC79F-5B6D-44AD-8C34-1ABB6EABAE6B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {744FC79F-5B6D-44AD-8C34-1ABB6EABAE6B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/Imaging/Filters (Images)/MainForm.cs b/Samples/Imaging/Filters (Images)/MainForm.cs new file mode 100644 index 0000000000..5937d51d5 --- /dev/null +++ b/Samples/Imaging/Filters (Images)/MainForm.cs @@ -0,0 +1,854 @@ +// Image Processing filters demo +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +using System; +using System.Drawing; +using System.Drawing.Imaging; +using System.Collections; +using System.ComponentModel; +using System.Windows.Forms; +using System.Data; + +using AForge; +using AForge.Imaging; +using AForge.Imaging.Filters; +using AForge.Imaging.Textures; + +namespace SampleApp +{ + /// + /// Summary description for MainForm. + /// + public class MainForm : System.Windows.Forms.Form + { + private System.Windows.Forms.MenuItem fileItem; + private System.Windows.Forms.MenuItem openFileItem; + private System.Windows.Forms.MenuItem menuItem3; + private System.Windows.Forms.MenuItem exitFilrItem; + private System.Windows.Forms.OpenFileDialog openFileDialog; + private System.Windows.Forms.PictureBox pictureBox; + private System.Windows.Forms.MainMenu mainMenu; + private System.Windows.Forms.MenuItem sizeItem; + private System.Windows.Forms.MenuItem normalSizeItem; + private System.Windows.Forms.MenuItem stretchedSizeItem; + private System.Windows.Forms.MenuItem centeredSizeItem; + private System.Windows.Forms.MenuItem filtersItem; + private System.Windows.Forms.MenuItem noneFiltersItem; + private System.Windows.Forms.MenuItem menuItem1; + private System.Windows.Forms.MenuItem sepiaFiltersItem; + private System.Windows.Forms.MenuItem invertFiltersItem; + private System.Windows.Forms.MenuItem rotateChannelFiltersItem; + private System.Windows.Forms.MenuItem grayscaleFiltersItem; + private System.Windows.Forms.MenuItem colorFiltersItem; + private System.Windows.Forms.MenuItem menuItem2; + private System.Windows.Forms.MenuItem hueModifierFiltersItem; + private System.Windows.Forms.MenuItem saturationAdjustingFiltersItem; + private System.Windows.Forms.MenuItem brightnessAdjustingFiltersItem; + private System.Windows.Forms.MenuItem contrastAdjustingFiltersItem; + private System.Windows.Forms.MenuItem hslFiltersItem; + private System.Windows.Forms.MenuItem menuItem4; + private System.Windows.Forms.MenuItem yCbCrLinearFiltersItem; + private System.Windows.Forms.MenuItem yCbCrFiltersItem; + private System.Windows.Forms.MenuItem menuItem5; + private System.Windows.Forms.MenuItem thresholdFiltersItem; + private System.Windows.Forms.MenuItem floydFiltersItem; + private System.Windows.Forms.MenuItem orderedDitheringFiltersItem; + private System.Windows.Forms.MenuItem menuItem6; + private System.Windows.Forms.MenuItem convolutionFiltersItem; + private System.Windows.Forms.MenuItem sharpenFiltersItem; + private System.Windows.Forms.MenuItem menuItem7; + private System.Windows.Forms.MenuItem differenceEdgesFiltersItem; + private System.Windows.Forms.MenuItem homogenityEdgesFiltersItem; + private System.Windows.Forms.MenuItem sobelEdgesFiltersItem; + private System.Windows.Forms.MenuItem rgbLinearFiltersItem; + private System.Windows.Forms.MenuItem menuItem8; + private System.Windows.Forms.MenuItem jitterFiltersItem; + private System.Windows.Forms.MenuItem oilFiltersItem; + private MenuItem gaussianFiltersItem; + private MenuItem textureFiltersItem; + private IContainer components; + + private System.Drawing.Bitmap sourceImage; + private System.Drawing.Bitmap filteredImage; + + + public MainForm() + { + InitializeComponent(); + + // set default size mode of picture box + pictureBox.SizeMode = PictureBoxSizeMode.StretchImage; + } + + /// + /// Clean up any resources being used. + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (components != null) + { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.mainMenu = new System.Windows.Forms.MainMenu(this.components); + this.fileItem = new System.Windows.Forms.MenuItem(); + this.openFileItem = new System.Windows.Forms.MenuItem(); + this.menuItem3 = new System.Windows.Forms.MenuItem(); + this.exitFilrItem = new System.Windows.Forms.MenuItem(); + this.filtersItem = new System.Windows.Forms.MenuItem(); + this.noneFiltersItem = new System.Windows.Forms.MenuItem(); + this.menuItem1 = new System.Windows.Forms.MenuItem(); + this.grayscaleFiltersItem = new System.Windows.Forms.MenuItem(); + this.sepiaFiltersItem = new System.Windows.Forms.MenuItem(); + this.invertFiltersItem = new System.Windows.Forms.MenuItem(); + this.rotateChannelFiltersItem = new System.Windows.Forms.MenuItem(); + this.colorFiltersItem = new System.Windows.Forms.MenuItem(); + this.rgbLinearFiltersItem = new System.Windows.Forms.MenuItem(); + this.menuItem2 = new System.Windows.Forms.MenuItem(); + this.hueModifierFiltersItem = new System.Windows.Forms.MenuItem(); + this.saturationAdjustingFiltersItem = new System.Windows.Forms.MenuItem(); + this.brightnessAdjustingFiltersItem = new System.Windows.Forms.MenuItem(); + this.contrastAdjustingFiltersItem = new System.Windows.Forms.MenuItem(); + this.hslFiltersItem = new System.Windows.Forms.MenuItem(); + this.menuItem4 = new System.Windows.Forms.MenuItem(); + this.yCbCrLinearFiltersItem = new System.Windows.Forms.MenuItem(); + this.yCbCrFiltersItem = new System.Windows.Forms.MenuItem(); + this.menuItem5 = new System.Windows.Forms.MenuItem(); + this.thresholdFiltersItem = new System.Windows.Forms.MenuItem(); + this.floydFiltersItem = new System.Windows.Forms.MenuItem(); + this.orderedDitheringFiltersItem = new System.Windows.Forms.MenuItem(); + this.menuItem6 = new System.Windows.Forms.MenuItem(); + this.convolutionFiltersItem = new System.Windows.Forms.MenuItem(); + this.sharpenFiltersItem = new System.Windows.Forms.MenuItem(); + this.gaussianFiltersItem = new System.Windows.Forms.MenuItem(); + this.menuItem7 = new System.Windows.Forms.MenuItem(); + this.differenceEdgesFiltersItem = new System.Windows.Forms.MenuItem(); + this.homogenityEdgesFiltersItem = new System.Windows.Forms.MenuItem(); + this.sobelEdgesFiltersItem = new System.Windows.Forms.MenuItem(); + this.menuItem8 = new System.Windows.Forms.MenuItem(); + this.jitterFiltersItem = new System.Windows.Forms.MenuItem(); + this.oilFiltersItem = new System.Windows.Forms.MenuItem(); + this.textureFiltersItem = new System.Windows.Forms.MenuItem(); + this.sizeItem = new System.Windows.Forms.MenuItem(); + this.normalSizeItem = new System.Windows.Forms.MenuItem(); + this.stretchedSizeItem = new System.Windows.Forms.MenuItem(); + this.centeredSizeItem = new System.Windows.Forms.MenuItem(); + this.openFileDialog = new System.Windows.Forms.OpenFileDialog(); + this.pictureBox = new System.Windows.Forms.PictureBox(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).BeginInit(); + this.SuspendLayout(); + // + // mainMenu + // + this.mainMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { + this.fileItem, + this.filtersItem, + this.sizeItem}); + // + // fileItem + // + this.fileItem.Index = 0; + this.fileItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { + this.openFileItem, + this.menuItem3, + this.exitFilrItem}); + this.fileItem.Text = "&File"; + // + // openFileItem + // + this.openFileItem.Index = 0; + this.openFileItem.Shortcut = System.Windows.Forms.Shortcut.CtrlO; + this.openFileItem.Text = "&Open"; + this.openFileItem.Click += new System.EventHandler(this.openFileItem_Click); + // + // menuItem3 + // + this.menuItem3.Index = 1; + this.menuItem3.Text = "-"; + // + // exitFilrItem + // + this.exitFilrItem.Index = 2; + this.exitFilrItem.Text = "E&xit"; + this.exitFilrItem.Click += new System.EventHandler(this.exitFilrItem_Click); + // + // filtersItem + // + this.filtersItem.Enabled = false; + this.filtersItem.Index = 1; + this.filtersItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { + this.noneFiltersItem, + this.menuItem1, + this.grayscaleFiltersItem, + this.sepiaFiltersItem, + this.invertFiltersItem, + this.rotateChannelFiltersItem, + this.colorFiltersItem, + this.rgbLinearFiltersItem, + this.menuItem2, + this.hueModifierFiltersItem, + this.saturationAdjustingFiltersItem, + this.brightnessAdjustingFiltersItem, + this.contrastAdjustingFiltersItem, + this.hslFiltersItem, + this.menuItem4, + this.yCbCrLinearFiltersItem, + this.yCbCrFiltersItem, + this.menuItem5, + this.thresholdFiltersItem, + this.floydFiltersItem, + this.orderedDitheringFiltersItem, + this.menuItem6, + this.convolutionFiltersItem, + this.sharpenFiltersItem, + this.gaussianFiltersItem, + this.menuItem7, + this.differenceEdgesFiltersItem, + this.homogenityEdgesFiltersItem, + this.sobelEdgesFiltersItem, + this.menuItem8, + this.jitterFiltersItem, + this.oilFiltersItem, + this.textureFiltersItem}); + this.filtersItem.Text = "Fi<ers"; + // + // noneFiltersItem + // + this.noneFiltersItem.Index = 0; + this.noneFiltersItem.Text = "&None"; + this.noneFiltersItem.Click += new System.EventHandler(this.noneFiltersItem_Click); + // + // menuItem1 + // + this.menuItem1.Index = 1; + this.menuItem1.Text = "-"; + // + // grayscaleFiltersItem + // + this.grayscaleFiltersItem.Index = 2; + this.grayscaleFiltersItem.Text = "&Grayscale"; + this.grayscaleFiltersItem.Click += new System.EventHandler(this.grayscaleFiltersItem_Click); + // + // sepiaFiltersItem + // + this.sepiaFiltersItem.Index = 3; + this.sepiaFiltersItem.Text = "&Sepia"; + this.sepiaFiltersItem.Click += new System.EventHandler(this.sepiaFiltersItem_Click); + // + // invertFiltersItem + // + this.invertFiltersItem.Index = 4; + this.invertFiltersItem.Text = "&Invert"; + this.invertFiltersItem.Click += new System.EventHandler(this.invertFiltersItem_Click); + // + // rotateChannelFiltersItem + // + this.rotateChannelFiltersItem.Index = 5; + this.rotateChannelFiltersItem.Text = "&Rotate channel"; + this.rotateChannelFiltersItem.Click += new System.EventHandler(this.rotateChannelFiltersItem_Click); + // + // colorFiltersItem + // + this.colorFiltersItem.Index = 6; + this.colorFiltersItem.Text = "Color filtering"; + this.colorFiltersItem.Click += new System.EventHandler(this.colorFiltersItem_Click); + // + // rgbLinearFiltersItem + // + this.rgbLinearFiltersItem.Index = 7; + this.rgbLinearFiltersItem.Text = "Levels linear correction"; + this.rgbLinearFiltersItem.Click += new System.EventHandler(this.rgbLinearFiltersItem_Click); + // + // menuItem2 + // + this.menuItem2.Index = 8; + this.menuItem2.Text = "-"; + // + // hueModifierFiltersItem + // + this.hueModifierFiltersItem.Index = 9; + this.hueModifierFiltersItem.Text = "Hue modifier"; + this.hueModifierFiltersItem.Click += new System.EventHandler(this.hueModifierFiltersItem_Click); + // + // saturationAdjustingFiltersItem + // + this.saturationAdjustingFiltersItem.Index = 10; + this.saturationAdjustingFiltersItem.Text = "Saturation adjusting"; + this.saturationAdjustingFiltersItem.Click += new System.EventHandler(this.saturationAdjustingFiltersItem_Click); + // + // brightnessAdjustingFiltersItem + // + this.brightnessAdjustingFiltersItem.Index = 11; + this.brightnessAdjustingFiltersItem.Text = "Brightness adjusting"; + this.brightnessAdjustingFiltersItem.Click += new System.EventHandler(this.brightnessAdjustingFiltersItem_Click); + // + // contrastAdjustingFiltersItem + // + this.contrastAdjustingFiltersItem.Index = 12; + this.contrastAdjustingFiltersItem.Text = "Contrast adjusting"; + this.contrastAdjustingFiltersItem.Click += new System.EventHandler(this.contrastAdjustingFiltersItem_Click); + // + // hslFiltersItem + // + this.hslFiltersItem.Index = 13; + this.hslFiltersItem.Text = "HSL filtering"; + this.hslFiltersItem.Click += new System.EventHandler(this.hslFiltersItem_Click); + // + // menuItem4 + // + this.menuItem4.Index = 14; + this.menuItem4.Text = "-"; + // + // yCbCrLinearFiltersItem + // + this.yCbCrLinearFiltersItem.Index = 15; + this.yCbCrLinearFiltersItem.Text = "YCbCr linear correction"; + this.yCbCrLinearFiltersItem.Click += new System.EventHandler(this.yCbCrLinearFiltersItem_Click); + // + // yCbCrFiltersItem + // + this.yCbCrFiltersItem.Index = 16; + this.yCbCrFiltersItem.Text = "YCbCr filtering"; + this.yCbCrFiltersItem.Click += new System.EventHandler(this.yCbCrFiltersItem_Click); + // + // menuItem5 + // + this.menuItem5.Index = 17; + this.menuItem5.Text = "-"; + // + // thresholdFiltersItem + // + this.thresholdFiltersItem.Index = 18; + this.thresholdFiltersItem.Text = "Threshold &binarization"; + this.thresholdFiltersItem.Click += new System.EventHandler(this.thresholdFiltersItem_Click); + // + // floydFiltersItem + // + this.floydFiltersItem.Index = 19; + this.floydFiltersItem.Text = "Floyd-Steinberg dithering"; + this.floydFiltersItem.Click += new System.EventHandler(this.floydFiltersItem_Click); + // + // orderedDitheringFiltersItem + // + this.orderedDitheringFiltersItem.Index = 20; + this.orderedDitheringFiltersItem.Text = "Ordered dithering"; + this.orderedDitheringFiltersItem.Click += new System.EventHandler(this.orderedDitheringFiltersItem_Click); + // + // menuItem6 + // + this.menuItem6.Index = 21; + this.menuItem6.Text = "-"; + // + // convolutionFiltersItem + // + this.convolutionFiltersItem.Index = 22; + this.convolutionFiltersItem.Text = "Convolution"; + this.convolutionFiltersItem.Click += new System.EventHandler(this.convolutionFiltersItem_Click); + // + // sharpenFiltersItem + // + this.sharpenFiltersItem.Index = 23; + this.sharpenFiltersItem.Text = "Sharpen"; + this.sharpenFiltersItem.Click += new System.EventHandler(this.sharpenFiltersItem_Click); + // + // gaussianFiltersItem + // + this.gaussianFiltersItem.Index = 24; + this.gaussianFiltersItem.Text = "Gaussian blur"; + this.gaussianFiltersItem.Click += new System.EventHandler(this.gaussianFiltersItem_Click); + // + // menuItem7 + // + this.menuItem7.Index = 25; + this.menuItem7.Text = "-"; + // + // differenceEdgesFiltersItem + // + this.differenceEdgesFiltersItem.Index = 26; + this.differenceEdgesFiltersItem.Text = "Difference edge detector"; + this.differenceEdgesFiltersItem.Click += new System.EventHandler(this.differenceEdgesFiltersItem_Click); + // + // homogenityEdgesFiltersItem + // + this.homogenityEdgesFiltersItem.Index = 27; + this.homogenityEdgesFiltersItem.Text = "Homogenity edge detector"; + this.homogenityEdgesFiltersItem.Click += new System.EventHandler(this.homogenityEdgesFiltersItem_Click); + // + // sobelEdgesFiltersItem + // + this.sobelEdgesFiltersItem.Index = 28; + this.sobelEdgesFiltersItem.Text = "Sobel edge detector"; + this.sobelEdgesFiltersItem.Click += new System.EventHandler(this.sobelEdgesFiltersItem_Click); + // + // menuItem8 + // + this.menuItem8.Index = 29; + this.menuItem8.Text = "-"; + // + // jitterFiltersItem + // + this.jitterFiltersItem.Index = 30; + this.jitterFiltersItem.Text = "Jitter"; + this.jitterFiltersItem.Click += new System.EventHandler(this.jitterFiltersItem_Click); + // + // oilFiltersItem + // + this.oilFiltersItem.Index = 31; + this.oilFiltersItem.Text = "Oil Painting"; + this.oilFiltersItem.Click += new System.EventHandler(this.oilFiltersItem_Click); + // + // textureFiltersItem + // + this.textureFiltersItem.Index = 32; + this.textureFiltersItem.Text = "Texture"; + this.textureFiltersItem.Click += new System.EventHandler(this.textureFiltersItem_Click); + // + // sizeItem + // + this.sizeItem.Index = 2; + this.sizeItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { + this.normalSizeItem, + this.stretchedSizeItem, + this.centeredSizeItem}); + this.sizeItem.Text = "&Size mode"; + this.sizeItem.Popup += new System.EventHandler(this.sizeItem_Popup); + // + // normalSizeItem + // + this.normalSizeItem.Index = 0; + this.normalSizeItem.Text = "&Normal"; + this.normalSizeItem.Click += new System.EventHandler(this.normalSizeItem_Click); + // + // stretchedSizeItem + // + this.stretchedSizeItem.Index = 1; + this.stretchedSizeItem.Text = "&Stretched"; + this.stretchedSizeItem.Click += new System.EventHandler(this.stretchedSizeItem_Click); + // + // centeredSizeItem + // + this.centeredSizeItem.Index = 2; + this.centeredSizeItem.Text = "&Centered"; + this.centeredSizeItem.Click += new System.EventHandler(this.centeredSizeItem_Click); + // + // openFileDialog + // + this.openFileDialog.Filter = "Image files (*.jpg,*.png,*.tif,*.bmp,*.gif)|*.jpg;*.png;*.tif;*.bmp;*.gif|JPG fil" + + "es (*.jpg)|*.jpg|PNG files (*.png)|*.png|TIF files (*.tif)|*.tif|BMP files (*.bm" + + "p)|*.bmp|GIF files (*.gif)|*.gif"; + this.openFileDialog.Title = "Open image"; + // + // pictureBox + // + this.pictureBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.pictureBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.pictureBox.Location = new System.Drawing.Point(10, 7); + this.pictureBox.Name = "pictureBox"; + this.pictureBox.Size = new System.Drawing.Size(785, 529); + this.pictureBox.TabIndex = 0; + this.pictureBox.TabStop = false; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(804, 543); + this.Controls.Add(this.pictureBox); + this.Menu = this.mainMenu; + this.MinimumSize = new System.Drawing.Size(512, 351); + this.Name = "MainForm"; + this.Text = "Image Processing filters demo"; + ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).EndInit(); + this.ResumeLayout(false); + + } + #endregion + + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.Run(new MainForm()); + } + + // On File->Exit menu item + private void exitFilrItem_Click(object sender, System.EventArgs e) + { + Application.Exit(); + } + + // On File->Open menu item + private void openFileItem_Click(object sender, System.EventArgs e) + { + try + { + // show file open dialog + if (openFileDialog.ShowDialog() == DialogResult.OK) + { + // load image + sourceImage = (Bitmap)Bitmap.FromFile(openFileDialog.FileName); + + // check pixel format + if ((sourceImage.PixelFormat == PixelFormat.Format16bppGrayScale) || + (Bitmap.GetPixelFormatSize(sourceImage.PixelFormat) > 32)) + { + MessageBox.Show("The demo application supports only color images.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + // free image + sourceImage.Dispose(); + sourceImage = null; + } + else + { + // make sure the image has 24 bpp format + if (sourceImage.PixelFormat != PixelFormat.Format24bppRgb) + { + Bitmap temp = AForge.Imaging.Image.Clone(sourceImage, PixelFormat.Format24bppRgb); + sourceImage.Dispose(); + sourceImage = temp; + } + } + + ClearCurrentImage(); + + // display image + pictureBox.Image = sourceImage; + noneFiltersItem.Checked = true; + + // enable filters menu + filtersItem.Enabled = (sourceImage != null); + } + } + catch + { + MessageBox.Show("Failed loading the image", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + // On Size mode->Normal menu item + private void normalSizeItem_Click(object sender, System.EventArgs e) + { + pictureBox.SizeMode = PictureBoxSizeMode.Normal; + } + + // On Size mode->Stretched menu item + private void stretchedSizeItem_Click(object sender, System.EventArgs e) + { + pictureBox.SizeMode = PictureBoxSizeMode.StretchImage; + } + + // On Size mode->Centered size menu item + private void centeredSizeItem_Click(object sender, System.EventArgs e) + { + pictureBox.SizeMode = PictureBoxSizeMode.CenterImage; + } + + // On Size menu item popup + private void sizeItem_Popup(object sender, System.EventArgs e) + { + normalSizeItem.Checked = (pictureBox.SizeMode == PictureBoxSizeMode.Normal); + stretchedSizeItem.Checked = (pictureBox.SizeMode == PictureBoxSizeMode.StretchImage); + centeredSizeItem.Checked = (pictureBox.SizeMode == PictureBoxSizeMode.CenterImage); + } + + // Clear current image in picture box + private void ClearCurrentImage() + { + // clear current image from picture box + pictureBox.Image = null; + // free current image + if ((noneFiltersItem.Checked == false) && (filteredImage != null)) + { + filteredImage.Dispose(); + filteredImage = null; + } + // uncheck all menu items + foreach (MenuItem item in filtersItem.MenuItems) + item.Checked = false; + } + + // Apply filter to the source image and show the filtered image + private void ApplyFilter(IFilter filter) + { + ClearCurrentImage(); + // apply filter + filteredImage = filter.Apply(sourceImage); + // display filtered image + pictureBox.Image = filteredImage; + } + + // On Filters->None item + private void noneFiltersItem_Click(object sender, System.EventArgs e) + { + ClearCurrentImage(); + // display source image + pictureBox.Image = sourceImage; + noneFiltersItem.Checked = true; + } + + // On Filters->Grayscale item + private void grayscaleFiltersItem_Click(object sender, System.EventArgs e) + { + ApplyFilter(Grayscale.CommonAlgorithms.BT709); + grayscaleFiltersItem.Checked = true; + } + + // On Filters->Sepia item + private void sepiaFiltersItem_Click(object sender, System.EventArgs e) + { + ApplyFilter(new Sepia()); + sepiaFiltersItem.Checked = true; + } + + // On Filters->Invert item + private void invertFiltersItem_Click(object sender, System.EventArgs e) + { + ApplyFilter(new Invert()); + invertFiltersItem.Checked = true; + } + + // On Filters->Rotate Channels item + private void rotateChannelFiltersItem_Click(object sender, System.EventArgs e) + { + ApplyFilter(new RotateChannels()); + rotateChannelFiltersItem.Checked = true; + } + + // On Filters->Color filtering + private void colorFiltersItem_Click(object sender, System.EventArgs e) + { + ApplyFilter(new ColorFiltering(new IntRange(25, 230), new IntRange(25, 230), new IntRange(25, 230))); + colorFiltersItem.Checked = true; + } + + // On Filters->Hue modifier + private void hueModifierFiltersItem_Click(object sender, System.EventArgs e) + { + ApplyFilter(new HueModifier(50)); + hueModifierFiltersItem.Checked = true; + } + + // On Filters->Saturation adjusting + private void saturationAdjustingFiltersItem_Click(object sender, System.EventArgs e) + { + ApplyFilter(new SaturationCorrection(0.15f)); + saturationAdjustingFiltersItem.Checked = true; + } + + // On Filters->Brightness adjusting + private void brightnessAdjustingFiltersItem_Click(object sender, System.EventArgs e) + { + ApplyFilter(new BrightnessCorrection()); + brightnessAdjustingFiltersItem.Checked = true; + } + + // On Filters->Contrast adjusting + private void contrastAdjustingFiltersItem_Click(object sender, System.EventArgs e) + { + ApplyFilter(new ContrastCorrection()); + contrastAdjustingFiltersItem.Checked = true; + } + + // On Filters->HSL filtering + private void hslFiltersItem_Click(object sender, System.EventArgs e) + { + ApplyFilter(new HSLFiltering(new IntRange(330, 30), new Range(0, 1), new Range(0, 1))); + hslFiltersItem.Checked = true; + } + + // On Filters->YCbCr filtering + private void yCbCrLinearFiltersItem_Click(object sender, System.EventArgs e) + { + YCbCrLinear filter = new YCbCrLinear(); + + filter.InCb = new Range(-0.3f, 0.3f); + + ApplyFilter(filter); + yCbCrLinearFiltersItem.Checked = true; + } + + // On Filters->YCbCr filtering + private void yCbCrFiltersItem_Click(object sender, System.EventArgs e) + { + ApplyFilter(new YCbCrFiltering(new Range(0.2f, 0.9f), new Range(-0.3f, 0.3f), new Range(-0.3f, 0.3f))); + yCbCrFiltersItem.Checked = true; + } + + // On Filters->Threshold binarization + private void thresholdFiltersItem_Click(object sender, System.EventArgs e) + { + // save original image + Bitmap originalImage = sourceImage; + // get grayscale image + sourceImage = Grayscale.CommonAlgorithms.RMY.Apply(sourceImage); + // apply threshold filter + ApplyFilter(new Threshold()); + // delete grayscale image and restore original + sourceImage.Dispose(); + sourceImage = originalImage; + + thresholdFiltersItem.Checked = true; + } + + // On Filters->Floyd-Steinberg dithering + private void floydFiltersItem_Click(object sender, System.EventArgs e) + { + // save original image + Bitmap originalImage = sourceImage; + // get grayscale image + sourceImage = Grayscale.CommonAlgorithms.RMY.Apply(sourceImage); + // apply threshold filter + ApplyFilter(new FloydSteinbergDithering()); + // delete grayscale image and restore original + sourceImage.Dispose(); + sourceImage = originalImage; + + floydFiltersItem.Checked = true; + } + + // On Filters->Ordered dithering + private void orderedDitheringFiltersItem_Click(object sender, System.EventArgs e) + { + // save original image + Bitmap originalImage = sourceImage; + // get grayscale image + sourceImage = Grayscale.CommonAlgorithms.RMY.Apply(sourceImage); + // apply threshold filter + ApplyFilter(new OrderedDithering()); + // delete grayscale image and restore original + sourceImage.Dispose(); + sourceImage = originalImage; + + orderedDitheringFiltersItem.Checked = true; + } + + // On Filters->Correlation + private void convolutionFiltersItem_Click(object sender, System.EventArgs e) + { + ApplyFilter(new Convolution(new int[,] { + { 1, 2, 3, 2, 1 }, + { 2, 4, 5, 4, 2 }, + { 3, 5, 6, 5, 3 }, + { 2, 4, 5, 4, 2 }, + { 1, 2, 3, 2, 1 } })); + convolutionFiltersItem.Checked = true; + } + + // On Filters->Sharpen + private void sharpenFiltersItem_Click(object sender, System.EventArgs e) + { + ApplyFilter(new Sharpen()); + sharpenFiltersItem.Checked = true; + } + + // On Filters->Difference edge detector + private void differenceEdgesFiltersItem_Click(object sender, System.EventArgs e) + { + // save original image + Bitmap originalImage = sourceImage; + // get grayscale image + sourceImage = Grayscale.CommonAlgorithms.RMY.Apply(sourceImage); + // apply edge filter + ApplyFilter(new DifferenceEdgeDetector()); + // delete grayscale image and restore original + sourceImage.Dispose(); + sourceImage = originalImage; + + differenceEdgesFiltersItem.Checked = true; + } + + // On Filters->Homogenity edge detector + private void homogenityEdgesFiltersItem_Click(object sender, System.EventArgs e) + { + // save original image + Bitmap originalImage = sourceImage; + // get grayscale image + sourceImage = Grayscale.CommonAlgorithms.RMY.Apply(sourceImage); + // apply edge filter + ApplyFilter(new HomogenityEdgeDetector()); + // delete grayscale image and restore original + sourceImage.Dispose(); + sourceImage = originalImage; + + homogenityEdgesFiltersItem.Checked = true; + } + + // On Filters->Sobel edge detector + private void sobelEdgesFiltersItem_Click(object sender, System.EventArgs e) + { + // save original image + Bitmap originalImage = sourceImage; + // get grayscale image + sourceImage = Grayscale.CommonAlgorithms.RMY.Apply(sourceImage); + // apply edge filter + ApplyFilter(new SobelEdgeDetector()); + // delete grayscale image and restore original + sourceImage.Dispose(); + sourceImage = originalImage; + + sobelEdgesFiltersItem.Checked = true; + } + + // On Filters->Levels Linear Correction + private void rgbLinearFiltersItem_Click(object sender, System.EventArgs e) + { + LevelsLinear filter = new LevelsLinear(); + + filter.InRed = new IntRange(30, 230); + filter.InGreen = new IntRange(50, 240); + filter.InBlue = new IntRange(10, 210); + + ApplyFilter(filter); + rgbLinearFiltersItem.Checked = true; + } + + // On Filters->Jitter + private void jitterFiltersItem_Click(object sender, System.EventArgs e) + { + ApplyFilter(new Jitter()); + jitterFiltersItem.Checked = true; + } + + // On Filters->Oil Painting + private void oilFiltersItem_Click(object sender, System.EventArgs e) + { + ApplyFilter(new OilPainting()); + oilFiltersItem.Checked = true; + } + + // On Filters->Gaussin blur + private void gaussianFiltersItem_Click(object sender, EventArgs e) + { + ApplyFilter(new GaussianBlur(2.0, 7)); + gaussianFiltersItem.Checked = true; + } + + // On Filters->Texture + private void textureFiltersItem_Click(object sender, EventArgs e) + { + ApplyFilter(new Texturer(new TextileTexture(), 1.0, 0.8)); + textureFiltersItem.Checked = true; + } + } +} diff --git a/Samples/Imaging/Filters (Images)/MainForm.resx b/Samples/Imaging/Filters (Images)/MainForm.resx new file mode 100644 index 0000000000..fa61c0790 --- /dev/null +++ b/Samples/Imaging/Filters (Images)/MainForm.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 1017, 15 + + \ No newline at end of file diff --git a/Samples/Imaging/Filters (Images)/Program.cs b/Samples/Imaging/Filters (Images)/Program.cs new file mode 100644 index 0000000000..bf6372ed8 --- /dev/null +++ b/Samples/Imaging/Filters (Images)/Program.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; + +namespace SampleApp +{ + static class Program + { + [STAThread] + static void Main() + { + if (Environment.OSVersion.Version.Major >= 6) + SetProcessDPIAware(); + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + + [System.Runtime.InteropServices.DllImport("user32.dll")] + private static extern bool SetProcessDPIAware(); + } +} diff --git a/Samples/Imaging/Filters (Images)/app.config b/Samples/Imaging/Filters (Images)/app.config new file mode 100644 index 0000000000..57c0f2cbc --- /dev/null +++ b/Samples/Imaging/Filters (Images)/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Samples/Imaging/Hough Transform/Accord.dll.config b/Samples/Imaging/Hough Transform/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Imaging/Hough Transform/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Imaging/Hough Transform/Hough Transform.csproj b/Samples/Imaging/Hough Transform/Hough Transform.csproj new file mode 100644 index 0000000000..3ea00ab59 --- /dev/null +++ b/Samples/Imaging/Hough Transform/Hough Transform.csproj @@ -0,0 +1,156 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {6B66B73D-481C-479B-AC13-F5E332D12293} + WinExe + Properties + SampleApp + HoughTransformation + + + 3.5 + v4.0 + + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + SampleApp.Program + + + + ..\..\..\Release\net40\Accord.dll + + + ..\..\..\Release\net40\Accord.Imaging.dll + + + ..\..\..\Release\net40\Accord.Math.dll + + + + + + + + + Form + + + MainForm.cs + + + + + Designer + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + \ No newline at end of file diff --git a/Samples/Imaging/Hough Transform/HoughTransformation.sln b/Samples/Imaging/Hough Transform/HoughTransformation.sln new file mode 100644 index 0000000000..d053f1a05 --- /dev/null +++ b/Samples/Imaging/Hough Transform/HoughTransformation.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C# Express 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HoughTransformation", "HoughTransformation.csproj", "{6B66B73D-481C-479B-AC13-F5E332D12293}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6B66B73D-481C-479B-AC13-F5E332D12293}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6B66B73D-481C-479B-AC13-F5E332D12293}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6B66B73D-481C-479B-AC13-F5E332D12293}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6B66B73D-481C-479B-AC13-F5E332D12293}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/Imaging/Hough Transform/MainForm.Designer.cs b/Samples/Imaging/Hough Transform/MainForm.Designer.cs new file mode 100644 index 0000000000..88fa2afb6 --- /dev/null +++ b/Samples/Imaging/Hough Transform/MainForm.Designer.cs @@ -0,0 +1,216 @@ +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.menuStrip1 = new System.Windows.Forms.MenuStrip( ); + this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.openToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator( ); + this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.openFileDialog = new System.Windows.Forms.OpenFileDialog( ); + this.tabControl = new System.Windows.Forms.TabControl( ); + this.tabPage1 = new System.Windows.Forms.TabPage( ); + this.sourcePictureBox = new System.Windows.Forms.PictureBox( ); + this.tabPage2 = new System.Windows.Forms.TabPage( ); + this.houghLinePictureBox = new System.Windows.Forms.PictureBox( ); + this.tabPage3 = new System.Windows.Forms.TabPage( ); + this.houghCirclePictureBox = new System.Windows.Forms.PictureBox( ); + this.menuStrip1.SuspendLayout( ); + this.tabControl.SuspendLayout( ); + this.tabPage1.SuspendLayout( ); + ( (System.ComponentModel.ISupportInitialize) ( this.sourcePictureBox ) ).BeginInit( ); + this.tabPage2.SuspendLayout( ); + ( (System.ComponentModel.ISupportInitialize) ( this.houghLinePictureBox ) ).BeginInit( ); + this.tabPage3.SuspendLayout( ); + ( (System.ComponentModel.ISupportInitialize) ( this.houghCirclePictureBox ) ).BeginInit( ); + this.SuspendLayout( ); + // + // menuStrip1 + // + this.menuStrip1.Items.AddRange( new System.Windows.Forms.ToolStripItem[] { + this.fileToolStripMenuItem} ); + this.menuStrip1.Location = new System.Drawing.Point( 0, 0 ); + this.menuStrip1.Name = "menuStrip1"; + this.menuStrip1.Size = new System.Drawing.Size( 632, 24 ); + this.menuStrip1.TabIndex = 0; + this.menuStrip1.Text = "mainMenuStrip"; + // + // fileToolStripMenuItem + // + this.fileToolStripMenuItem.DropDownItems.AddRange( new System.Windows.Forms.ToolStripItem[] { + this.openToolStripMenuItem, + this.toolStripMenuItem1, + this.exitToolStripMenuItem} ); + this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; + this.fileToolStripMenuItem.Size = new System.Drawing.Size( 35, 20 ); + this.fileToolStripMenuItem.Text = "&File"; + // + // openToolStripMenuItem + // + this.openToolStripMenuItem.Name = "openToolStripMenuItem"; + this.openToolStripMenuItem.ShortcutKeys = ( (System.Windows.Forms.Keys) ( ( System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O ) ) ); + this.openToolStripMenuItem.Size = new System.Drawing.Size( 151, 22 ); + this.openToolStripMenuItem.Text = "&Open"; + this.openToolStripMenuItem.Click += new System.EventHandler( this.openToolStripMenuItem_Click ); + // + // toolStripMenuItem1 + // + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + this.toolStripMenuItem1.Size = new System.Drawing.Size( 148, 6 ); + // + // exitToolStripMenuItem + // + this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; + this.exitToolStripMenuItem.Size = new System.Drawing.Size( 151, 22 ); + this.exitToolStripMenuItem.Text = "E&xit"; + this.exitToolStripMenuItem.Click += new System.EventHandler( this.exitToolStripMenuItem_Click ); + // + // openFileDialog + // + this.openFileDialog.Filter = "Image files (*.jpg,*.png,*.tif,*.bmp,*.gif)|*.jpg;*.png;*.tif;*.bmp;*.gif|JPG fil" + + "es (*.jpg)|*.jpg|PNG files (*.png)|*.png|TIF files (*.tif)|*.tif|BMP files (*.bm" + + "p)|*.bmp|GIF files (*.gif)|*.gif"; + this.openFileDialog.Title = "Open image"; + // + // tabControl + // + this.tabControl.Controls.Add( this.tabPage1 ); + this.tabControl.Controls.Add( this.tabPage2 ); + this.tabControl.Controls.Add( this.tabPage3 ); + this.tabControl.Dock = System.Windows.Forms.DockStyle.Fill; + this.tabControl.Location = new System.Drawing.Point( 0, 24 ); + this.tabControl.Name = "tabControl"; + this.tabControl.SelectedIndex = 0; + this.tabControl.Size = new System.Drawing.Size( 632, 442 ); + this.tabControl.TabIndex = 1; + // + // tabPage1 + // + this.tabPage1.Controls.Add( this.sourcePictureBox ); + this.tabPage1.Location = new System.Drawing.Point( 4, 22 ); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.Padding = new System.Windows.Forms.Padding( 3 ); + this.tabPage1.Size = new System.Drawing.Size( 624, 416 ); + this.tabPage1.TabIndex = 0; + this.tabPage1.Text = "Original image"; + this.tabPage1.UseVisualStyleBackColor = true; + // + // sourcePictureBox + // + this.sourcePictureBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.sourcePictureBox.Location = new System.Drawing.Point( 3, 3 ); + this.sourcePictureBox.Name = "sourcePictureBox"; + this.sourcePictureBox.Size = new System.Drawing.Size( 618, 410 ); + this.sourcePictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; + this.sourcePictureBox.TabIndex = 0; + this.sourcePictureBox.TabStop = false; + // + // tabPage2 + // + this.tabPage2.Controls.Add( this.houghLinePictureBox ); + this.tabPage2.Location = new System.Drawing.Point( 4, 22 ); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.Padding = new System.Windows.Forms.Padding( 3 ); + this.tabPage2.Size = new System.Drawing.Size( 624, 416 ); + this.tabPage2.TabIndex = 1; + this.tabPage2.Text = "Hough lines"; + this.tabPage2.UseVisualStyleBackColor = true; + // + // houghLinePictureBox + // + this.houghLinePictureBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.houghLinePictureBox.Location = new System.Drawing.Point( 3, 3 ); + this.houghLinePictureBox.Name = "houghLinePictureBox"; + this.houghLinePictureBox.Size = new System.Drawing.Size( 618, 410 ); + this.houghLinePictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; + this.houghLinePictureBox.TabIndex = 0; + this.houghLinePictureBox.TabStop = false; + // + // tabPage3 + // + this.tabPage3.Controls.Add( this.houghCirclePictureBox ); + this.tabPage3.Location = new System.Drawing.Point( 4, 22 ); + this.tabPage3.Name = "tabPage3"; + this.tabPage3.Size = new System.Drawing.Size( 624, 416 ); + this.tabPage3.TabIndex = 2; + this.tabPage3.Text = "Hough circles"; + this.tabPage3.UseVisualStyleBackColor = true; + // + // houghCirclePictureBox + // + this.houghCirclePictureBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.houghCirclePictureBox.Location = new System.Drawing.Point( 0, 0 ); + this.houghCirclePictureBox.Name = "houghCirclePictureBox"; + this.houghCirclePictureBox.Size = new System.Drawing.Size( 624, 416 ); + this.houghCirclePictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; + this.houghCirclePictureBox.TabIndex = 0; + this.houghCirclePictureBox.TabStop = false; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 13F ); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size( 632, 466 ); + this.Controls.Add( this.tabControl ); + this.Controls.Add( this.menuStrip1 ); + this.MainMenuStrip = this.menuStrip1; + this.Name = "MainForm"; + this.Text = "Hough transformation"; + this.menuStrip1.ResumeLayout( false ); + this.menuStrip1.PerformLayout( ); + this.tabControl.ResumeLayout( false ); + this.tabPage1.ResumeLayout( false ); + ( (System.ComponentModel.ISupportInitialize) ( this.sourcePictureBox ) ).EndInit( ); + this.tabPage2.ResumeLayout( false ); + ( (System.ComponentModel.ISupportInitialize) ( this.houghLinePictureBox ) ).EndInit( ); + this.tabPage3.ResumeLayout( false ); + ( (System.ComponentModel.ISupportInitialize) ( this.houghCirclePictureBox ) ).EndInit( ); + this.ResumeLayout( false ); + this.PerformLayout( ); + + } + + #endregion + + private System.Windows.Forms.MenuStrip menuStrip1; + private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem openToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; + private System.Windows.Forms.OpenFileDialog openFileDialog; + private System.Windows.Forms.TabControl tabControl; + private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.PictureBox sourcePictureBox; + private System.Windows.Forms.TabPage tabPage2; + private System.Windows.Forms.PictureBox houghLinePictureBox; + private System.Windows.Forms.TabPage tabPage3; + private System.Windows.Forms.PictureBox houghCirclePictureBox; + } +} + diff --git a/Samples/Imaging/Hough Transform/MainForm.cs b/Samples/Imaging/Hough Transform/MainForm.cs new file mode 100644 index 0000000000..13893370b --- /dev/null +++ b/Samples/Imaging/Hough Transform/MainForm.cs @@ -0,0 +1,166 @@ +// Hough line and circle transformation demo +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Drawing.Imaging; +using System.Text; +using System.Windows.Forms; + +using AForge; +using AForge.Imaging; +using AForge.Imaging.Filters; + +namespace SampleApp +{ + public partial class MainForm : Form + { + // binarization filtering sequence + private FiltersSequence filter = new FiltersSequence( + Grayscale.CommonAlgorithms.BT709, + new Threshold(64) + ); + + HoughLineTransformation lineTransform = new HoughLineTransformation(); + HoughCircleTransformation circleTransform = new HoughCircleTransformation(35); + + + public MainForm() + { + InitializeComponent(); + + lineTransform.MinLineIntensity = 10; + circleTransform.MinCircleIntensity = 20; + } + + // Exit from application + private void exitToolStripMenuItem_Click(object sender, EventArgs e) + { + Application.Exit(); + } + + // Open image file + private void openToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + // show file open dialog + if (openFileDialog.ShowDialog() == DialogResult.OK) + { + // load image + Bitmap tempImage = (Bitmap)Bitmap.FromFile(openFileDialog.FileName); + Bitmap image = AForge.Imaging.Image.Clone(tempImage, PixelFormat.Format24bppRgb); + tempImage.Dispose(); + + // lock the source image + BitmapData sourceData = image.LockBits( + new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, image.PixelFormat); + + // binarize the image + UnmanagedImage binarySource = filter.Apply(new UnmanagedImage(sourceData)); + + // apply Hough line transform + lineTransform.ProcessImage(binarySource); + + // get lines using relative intensity + HoughLine[] lines = lineTransform.GetLinesByRelativeIntensity(0.2); + + foreach (HoughLine line in lines) + { + string s = string.Format("Theta = {0}, R = {1}, I = {2} ({3})", line.Theta, line.Radius, line.Intensity, line.RelativeIntensity); + System.Diagnostics.Debug.WriteLine(s); + + // uncomment to highlight detected lines + /* + // get line's radius and theta values + int r = line.Radius; + double t = line.Theta; + + // check if line is in lower part of the image + if ( r < 0 ) + { + t += 180; + r = -r; + } + + // convert degrees to radians + t = ( t / 180 ) * Math.PI; + + // get image centers (all coordinate are measured relative + // to center) + int w2 = image.Width /2; + int h2 = image.Height / 2; + + double x0 = 0, x1 = 0, y0 = 0, y1 = 0; + + if ( line.Theta != 0 ) + { + // none vertical line + x0 = -w2; // most left point + x1 = w2; // most right point + + // calculate corresponding y values + y0 = ( -Math.Cos( t ) * x0 + r ) / Math.Sin( t ); + y1 = ( -Math.Cos( t ) * x1 + r ) / Math.Sin( t ); + } + else + { + // vertical line + x0 = line.Radius; + x1 = line.Radius; + + y0 = h2; + y1 = -h2; + } + + // draw line on the image + Drawing.Line( sourceData, + new IntPoint( (int) x0 + w2, h2 - (int) y0 ), + new IntPoint( (int) x1 + w2, h2 - (int) y1 ), + Color.Red ); */ + } + + System.Diagnostics.Debug.WriteLine("Found lines: " + lineTransform.LinesCount); + System.Diagnostics.Debug.WriteLine("Max intensity: " + lineTransform.MaxIntensity); + + // apply Hough circle transform + circleTransform.ProcessImage(binarySource); + // get circles using relative intensity + HoughCircle[] circles = circleTransform.GetCirclesByRelativeIntensity(0.5); + + foreach (HoughCircle circle in circles) + { + string s = string.Format("X = {0}, Y = {1}, I = {2} ({3})", circle.X, circle.Y, circle.Intensity, circle.RelativeIntensity); + System.Diagnostics.Debug.WriteLine(s); + } + + System.Diagnostics.Debug.WriteLine("Found circles: " + circleTransform.CirclesCount); + System.Diagnostics.Debug.WriteLine("Max intensity: " + circleTransform.MaxIntensity); + + // unlock source image + image.UnlockBits(sourceData); + // dispose temporary binary source image + binarySource.Dispose(); + + // show images + sourcePictureBox.Image = image; + houghLinePictureBox.Image = lineTransform.ToBitmap(); + houghCirclePictureBox.Image = circleTransform.ToBitmap(); + } + } + catch + { + MessageBox.Show("Failed loading the image", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } +} diff --git a/Samples/Imaging/Hough Transform/MainForm.resx b/Samples/Imaging/Hough Transform/MainForm.resx new file mode 100644 index 0000000000..d6c4c0664 --- /dev/null +++ b/Samples/Imaging/Hough Transform/MainForm.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 126, 17 + + \ No newline at end of file diff --git a/Samples/Imaging/Hough Transform/Program.cs b/Samples/Imaging/Hough Transform/Program.cs new file mode 100644 index 0000000000..27eb5b7c0 --- /dev/null +++ b/Samples/Imaging/Hough Transform/Program.cs @@ -0,0 +1,29 @@ +// AForge Framework +// Hough line transformation demo +// +// Copyright Andrew Kirillov, 2007 +// andrew.kirillov@gmail.com +// + +using System; +using System.Windows.Forms; + +namespace SampleApp +{ + static class Program + { + [STAThread] + static void Main() + { + if (Environment.OSVersion.Version.Major >= 6) + SetProcessDPIAware(); + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + + [System.Runtime.InteropServices.DllImport("user32.dll")] + private static extern bool SetProcessDPIAware(); + } +} diff --git a/Samples/Imaging/Hough Transform/Properties/AssemblyInfo.cs b/Samples/Imaging/Hough Transform/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..3577fa158 --- /dev/null +++ b/Samples/Imaging/Hough Transform/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Imaging Hough Transform")] +[assembly: AssemblyDescription("Imaging Hough Transform sample")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("AForge")] +[assembly: AssemblyProduct("AForge.NET")] +[assembly: AssemblyCopyright("AForge © 2007")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("ea39829a-94e6-4fc9-a728-b501df075bf9")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("2.0.1.0")] +[assembly: AssemblyFileVersion("2.0.1.0")] diff --git a/Samples/Imaging/Hough Transform/Properties/Resources.Designer.cs b/Samples/Imaging/Hough Transform/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..7b58e53ee --- /dev/null +++ b/Samples/Imaging/Hough Transform/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Samples/Imaging/Hough Transform/Properties/Resources.resx b/Samples/Imaging/Hough Transform/Properties/Resources.resx new file mode 100644 index 0000000000..25a61211c --- /dev/null +++ b/Samples/Imaging/Hough Transform/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Imaging/Hough Transform/Properties/Settings.Designer.cs b/Samples/Imaging/Hough Transform/Properties/Settings.Designer.cs new file mode 100644 index 0000000000..dbc9e5d22 --- /dev/null +++ b/Samples/Imaging/Hough Transform/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Samples/Imaging/Hough Transform/Properties/Settings.settings b/Samples/Imaging/Hough Transform/Properties/Settings.settings new file mode 100644 index 0000000000..39645652a --- /dev/null +++ b/Samples/Imaging/Hough Transform/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Samples/Imaging/Hough Transform/Sample Images/sample.bmp b/Samples/Imaging/Hough Transform/Sample Images/sample.bmp new file mode 100644 index 0000000000..bf8b49078 Binary files /dev/null and b/Samples/Imaging/Hough Transform/Sample Images/sample.bmp differ diff --git a/Samples/Imaging/Hough Transform/app.config b/Samples/Imaging/Hough Transform/app.config new file mode 100644 index 0000000000..57c0f2cbc --- /dev/null +++ b/Samples/Imaging/Hough Transform/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Samples/Imaging/Image Viewer/Accord.dll.config b/Samples/Imaging/Image Viewer/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Imaging/Image Viewer/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Imaging/Image Viewer/Image Viewer.csproj b/Samples/Imaging/Image Viewer/Image Viewer.csproj new file mode 100644 index 0000000000..02a974d82 --- /dev/null +++ b/Samples/Imaging/Image Viewer/Image Viewer.csproj @@ -0,0 +1,155 @@ + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {EE5B96F4-EEB3-4606-98C9-6F1242B41FD2} + WinExe + Properties + SampleApp + ImageViewer + v4.0 + 512 + + + 3.5 + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + SampleApp.Program + + + + ..\..\..\Release\net40\Accord.dll + + + ..\..\..\Release\net40\Accord.Controls.Imaging.dll + + + ..\..\..\Release\net40\Accord.Imaging.dll + + + + + + + + Form + + + MainForm.cs + + + + + MainForm.cs + Designer + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + \ No newline at end of file diff --git a/Samples/Imaging/Image Viewer/ImageViewer.sln b/Samples/Imaging/Image Viewer/ImageViewer.sln new file mode 100644 index 0000000000..25ac821f0 --- /dev/null +++ b/Samples/Imaging/Image Viewer/ImageViewer.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C# Express 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageViewer", "ImageViewer.csproj", "{EE5B96F4-EEB3-4606-98C9-6F1242B41FD2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EE5B96F4-EEB3-4606-98C9-6F1242B41FD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EE5B96F4-EEB3-4606-98C9-6F1242B41FD2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EE5B96F4-EEB3-4606-98C9-6F1242B41FD2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EE5B96F4-EEB3-4606-98C9-6F1242B41FD2}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/Imaging/Image Viewer/MainForm.Designer.cs b/Samples/Imaging/Image Viewer/MainForm.Designer.cs new file mode 100644 index 0000000000..722350520 --- /dev/null +++ b/Samples/Imaging/Image Viewer/MainForm.Designer.cs @@ -0,0 +1,181 @@ +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.openFileDialog = new System.Windows.Forms.OpenFileDialog( ); + this.mainMenuStrip = new System.Windows.Forms.MenuStrip( ); + this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.openToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator( ); + this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.statusStrip = new System.Windows.Forms.StatusStrip( ); + this.splitContainer1 = new System.Windows.Forms.SplitContainer( ); + this.pictureBox = new AForge.Controls.PictureBox( ); + this.propertyGrid = new System.Windows.Forms.PropertyGrid( ); + this.mainMenuStrip.SuspendLayout( ); + this.splitContainer1.Panel1.SuspendLayout( ); + this.splitContainer1.Panel2.SuspendLayout( ); + this.splitContainer1.SuspendLayout( ); + ( (System.ComponentModel.ISupportInitialize) ( this.pictureBox ) ).BeginInit( ); + this.SuspendLayout( ); + // + // openFileDialog + // + this.openFileDialog.Filter = "All files (*.*)|*.*|Flexible Image Transport System images (*.fit, *.fits)|*.fit;" + + "*.fits|PNM (Portable Any Map) images (*.pbm, *.pgm, *.ppm, *.pnm)|*.pbm;*.pgm;*." + + "ppm;*.pnm"; + this.openFileDialog.Title = "Select image file"; + // + // mainMenuStrip + // + this.mainMenuStrip.Items.AddRange( new System.Windows.Forms.ToolStripItem[] { + this.fileToolStripMenuItem} ); + this.mainMenuStrip.Location = new System.Drawing.Point( 0, 0 ); + this.mainMenuStrip.Name = "mainMenuStrip"; + this.mainMenuStrip.Size = new System.Drawing.Size( 528, 24 ); + this.mainMenuStrip.TabIndex = 0; + // + // fileToolStripMenuItem + // + this.fileToolStripMenuItem.DropDownItems.AddRange( new System.Windows.Forms.ToolStripItem[] { + this.openToolStripMenuItem, + this.toolStripMenuItem1, + this.exitToolStripMenuItem} ); + this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; + this.fileToolStripMenuItem.Size = new System.Drawing.Size( 35, 20 ); + this.fileToolStripMenuItem.Text = "&File"; + // + // openToolStripMenuItem + // + this.openToolStripMenuItem.Name = "openToolStripMenuItem"; + this.openToolStripMenuItem.ShortcutKeys = ( (System.Windows.Forms.Keys) ( ( System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O ) ) ); + this.openToolStripMenuItem.Size = new System.Drawing.Size( 151, 22 ); + this.openToolStripMenuItem.Text = "&Open"; + this.openToolStripMenuItem.Click += new System.EventHandler( this.openToolStripMenuItem_Click ); + // + // toolStripMenuItem1 + // + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + this.toolStripMenuItem1.Size = new System.Drawing.Size( 148, 6 ); + // + // exitToolStripMenuItem + // + this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; + this.exitToolStripMenuItem.Size = new System.Drawing.Size( 151, 22 ); + this.exitToolStripMenuItem.Text = "E&xit"; + this.exitToolStripMenuItem.Click += new System.EventHandler( this.exitToolStripMenuItem_Click ); + // + // statusStrip + // + this.statusStrip.Location = new System.Drawing.Point( 0, 284 ); + this.statusStrip.Name = "statusStrip"; + this.statusStrip.Size = new System.Drawing.Size( 528, 22 ); + this.statusStrip.TabIndex = 1; + this.statusStrip.Text = "statusStrip1"; + // + // splitContainer1 + // + this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer1.Location = new System.Drawing.Point( 0, 24 ); + this.splitContainer1.Name = "splitContainer1"; + // + // splitContainer1.Panel1 + // + this.splitContainer1.Panel1.Controls.Add( this.pictureBox ); + // + // splitContainer1.Panel2 + // + this.splitContainer1.Panel2.Controls.Add( this.propertyGrid ); + this.splitContainer1.Size = new System.Drawing.Size( 528, 260 ); + this.splitContainer1.SplitterDistance = 359; + this.splitContainer1.TabIndex = 2; + // + // pictureBox + // + this.pictureBox.Anchor = ( (System.Windows.Forms.AnchorStyles) ( ( ( ( System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom ) + | System.Windows.Forms.AnchorStyles.Left ) + | System.Windows.Forms.AnchorStyles.Right ) ) ); + this.pictureBox.BackColor = System.Drawing.SystemColors.ControlDark; + this.pictureBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.pictureBox.Image = null; + this.pictureBox.Location = new System.Drawing.Point( 10, 10 ); + this.pictureBox.Name = "pictureBox"; + this.pictureBox.Size = new System.Drawing.Size( 338, 240 ); + this.pictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; + this.pictureBox.TabIndex = 0; + this.pictureBox.TabStop = false; + // + // propertyGrid + // + this.propertyGrid.Dock = System.Windows.Forms.DockStyle.Fill; + this.propertyGrid.Enabled = false; + this.propertyGrid.HelpVisible = false; + this.propertyGrid.Location = new System.Drawing.Point( 0, 0 ); + this.propertyGrid.Name = "propertyGrid"; + this.propertyGrid.Size = new System.Drawing.Size( 165, 260 ); + this.propertyGrid.TabIndex = 0; + this.propertyGrid.ToolbarVisible = false; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 13F ); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size( 528, 306 ); + this.Controls.Add( this.splitContainer1 ); + this.Controls.Add( this.statusStrip ); + this.Controls.Add( this.mainMenuStrip ); + this.MainMenuStrip = this.mainMenuStrip; + this.Name = "MainForm"; + this.Text = "Image Viewer"; + this.mainMenuStrip.ResumeLayout( false ); + this.mainMenuStrip.PerformLayout( ); + this.splitContainer1.Panel1.ResumeLayout( false ); + this.splitContainer1.Panel2.ResumeLayout( false ); + this.splitContainer1.ResumeLayout( false ); + ( (System.ComponentModel.ISupportInitialize) ( this.pictureBox ) ).EndInit( ); + this.ResumeLayout( false ); + this.PerformLayout( ); + + } + + #endregion + + private System.Windows.Forms.OpenFileDialog openFileDialog; + private System.Windows.Forms.MenuStrip mainMenuStrip; + private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem openToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; + private System.Windows.Forms.StatusStrip statusStrip; + private System.Windows.Forms.SplitContainer splitContainer1; + private System.Windows.Forms.PropertyGrid propertyGrid; + private AForge.Controls.PictureBox pictureBox; + } +} + diff --git a/Samples/Imaging/Image Viewer/MainForm.cs b/Samples/Imaging/Image Viewer/MainForm.cs new file mode 100644 index 0000000000..ac0e174a3 --- /dev/null +++ b/Samples/Imaging/Image Viewer/MainForm.cs @@ -0,0 +1,68 @@ +// Image Viewer sample application +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Text; +using System.Windows.Forms; +using System.IO; + +using AForge.Imaging.Formats; + +namespace SampleApp +{ + + public partial class MainForm : Form + { + + public MainForm() + { + InitializeComponent(); + } + + // Exit from application + private void exitToolStripMenuItem_Click(object sender, EventArgs e) + { + Application.Exit(); + } + + // Open image file + private void openToolStripMenuItem_Click(object sender, EventArgs e) + { + if (openFileDialog.ShowDialog() == DialogResult.OK) + { + try + { + ImageInfo imageInfo = null; + + pictureBox.Image = ImageDecoder.DecodeFromFile(openFileDialog.FileName, out imageInfo); + + propertyGrid.SelectedObject = imageInfo; + propertyGrid.ExpandAllGridItems(); + } + catch (NotSupportedException ex) + { + MessageBox.Show("Image format is not supported: " + ex.Message, "Error", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + catch (ArgumentException ex) + { + MessageBox.Show("Invalid image: " + ex.Message, "Error", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + catch + { + MessageBox.Show("Failed loading the image", "Error", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } + } +} diff --git a/Samples/Imaging/Image Viewer/MainForm.resx b/Samples/Imaging/Image Viewer/MainForm.resx new file mode 100644 index 0000000000..7e75d7e54 --- /dev/null +++ b/Samples/Imaging/Image Viewer/MainForm.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 141, 17 + + + 276, 17 + + \ No newline at end of file diff --git a/Samples/Imaging/Image Viewer/Program.cs b/Samples/Imaging/Image Viewer/Program.cs new file mode 100644 index 0000000000..316268492 --- /dev/null +++ b/Samples/Imaging/Image Viewer/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Windows.Forms; + +namespace SampleApp +{ + static class Program + { + [STAThread] + static void Main() + { + if (Environment.OSVersion.Version.Major >= 6) + SetProcessDPIAware(); + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + + [System.Runtime.InteropServices.DllImport("user32.dll")] + private static extern bool SetProcessDPIAware(); + } +} diff --git a/Samples/Imaging/Image Viewer/Properties/AssemblyInfo.cs b/Samples/Imaging/Image Viewer/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..ce2087a97 --- /dev/null +++ b/Samples/Imaging/Image Viewer/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle( "Image Viewer" )] +[assembly: AssemblyDescription( "Image Viewer sample" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "AForge" )] +[assembly: AssemblyProduct( "AForge.NET" )] +[assembly: AssemblyCopyright( "AForge © 2008" )] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible( false )] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid( "c7230f0a-0be1-4281-92b1-41cafd41399c" )] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion( "2.0.0.0" )] +[assembly: AssemblyFileVersion( "2.0.0.0" )] diff --git a/Samples/Imaging/Image Viewer/Properties/Resources.Designer.cs b/Samples/Imaging/Image Viewer/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..7b58e53ee --- /dev/null +++ b/Samples/Imaging/Image Viewer/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Samples/Imaging/Image Viewer/Properties/Resources.resx b/Samples/Imaging/Image Viewer/Properties/Resources.resx new file mode 100644 index 0000000000..af7dbebba --- /dev/null +++ b/Samples/Imaging/Image Viewer/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Imaging/Image Viewer/Properties/Settings.Designer.cs b/Samples/Imaging/Image Viewer/Properties/Settings.Designer.cs new file mode 100644 index 0000000000..dbc9e5d22 --- /dev/null +++ b/Samples/Imaging/Image Viewer/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Samples/Imaging/Image Viewer/Properties/Settings.settings b/Samples/Imaging/Image Viewer/Properties/Settings.settings new file mode 100644 index 0000000000..39645652a --- /dev/null +++ b/Samples/Imaging/Image Viewer/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Samples/Imaging/Image Viewer/app.config b/Samples/Imaging/Image Viewer/app.config new file mode 100644 index 0000000000..57c0f2cbc --- /dev/null +++ b/Samples/Imaging/Image Viewer/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Samples/Imaging/Panorama (FREAK)/Accord.dll.config b/Samples/Imaging/Panorama (FREAK)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Imaging/Panorama (FREAK)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Imaging/Panorama (FREAK)/MainForm.Designer.cs b/Samples/Imaging/Panorama (FREAK)/MainForm.Designer.cs index 1ce9c2451..af0b5bb29 100644 --- a/Samples/Imaging/Panorama (FREAK)/MainForm.Designer.cs +++ b/Samples/Imaging/Panorama (FREAK)/MainForm.Designer.cs @@ -1,33 +1,33 @@ -namespace Panorama.FREAK -{ - partial class MainForm - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { this.components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); this.imageList1 = new System.Windows.Forms.ImageList(this.components); @@ -133,17 +133,17 @@ private void InitializeComponent() ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).EndInit(); this.ResumeLayout(false); - } - - #endregion - - private System.Windows.Forms.Button button1; - private System.Windows.Forms.Button button2; - private System.Windows.Forms.ImageList imageList1; - private System.Windows.Forms.PictureBox pictureBox; - private System.Windows.Forms.Button button4; - private System.Windows.Forms.Button button5; - private System.Windows.Forms.Button button3; - } -} - + } + + #endregion + + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.ImageList imageList1; + private System.Windows.Forms.PictureBox pictureBox; + private System.Windows.Forms.Button button4; + private System.Windows.Forms.Button button5; + private System.Windows.Forms.Button button3; + } +} + diff --git a/Samples/Imaging/Panorama (FREAK)/MainForm.cs b/Samples/Imaging/Panorama (FREAK)/MainForm.cs index 2033a749d..550d057db 100644 --- a/Samples/Imaging/Panorama (FREAK)/MainForm.cs +++ b/Samples/Imaging/Panorama (FREAK)/MainForm.cs @@ -38,12 +38,12 @@ using Accord.Math; using AForge; -namespace Panorama.FREAK +namespace SampleApp { public partial class MainForm : Form { - private Bitmap img1 = Panorama.FREAK.Properties.Resources.UFSCar_Lake1; - private Bitmap img2 = Panorama.FREAK.Properties.Resources.UFSCar_Lake2; + private Bitmap img1 = SampleApp.Properties.Resources.UFSCar_Lake1; + private Bitmap img2 = SampleApp.Properties.Resources.UFSCar_Lake2; private FastRetinaKeypoint[] keyPoints1; private FastRetinaKeypoint[] keyPoints2; diff --git a/Samples/Imaging/Panorama (FREAK)/Panorama (FREAK).csproj b/Samples/Imaging/Panorama (FREAK)/Panorama (FREAK).csproj index 5bb6c8eed..5d7dce7fb 100644 --- a/Samples/Imaging/Panorama (FREAK)/Panorama (FREAK).csproj +++ b/Samples/Imaging/Panorama (FREAK)/Panorama (FREAK).csproj @@ -1,164 +1,162 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {CE77124B-B24F-476E-8C83-835EC8675DD7} - WinExe - Properties - Panorama.FREAK - Panorama %28FREAK%29 - v4.0 - 512 - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - - true - bin\x86\Debug\ - DEBUG;TRACE - full - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - bin\x86\Release\ - TRACE - true - pdbonly - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - framework.ico - - - - False - ..\..\..\Release\net40\Accord.dll - - - False - ..\..\..\Release\net40\Accord.Imaging.dll - - - False - ..\..\..\Release\net40\Accord.Math.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Imaging.dll - - - - 3.5 - - - - - - - - - Form - - - MainForm.cs - - - - - MainForm.cs - Designer - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - - - - - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - - - - + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {CE77124B-B24F-476E-8C83-835EC8675DD7} + WinExe + Properties + SampleApp + Panorama %28FREAK%29 + v4.0 + 512 + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + framework.ico + + + SampleApp.Program + + + + False + ..\..\..\Release\net40\Accord.dll + + + False + ..\..\..\Release\net40\Accord.Imaging.dll + + + False + ..\..\..\Release\net40\Accord.Math.dll + + + + 3.5 + + + + + + + + + Form + + + MainForm.cs + + + + + MainForm.cs + Designer + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + + + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + --> \ No newline at end of file diff --git a/Samples/Imaging/Panorama (FREAK)/Program.cs b/Samples/Imaging/Panorama (FREAK)/Program.cs index 158506dcb..316268492 100644 --- a/Samples/Imaging/Panorama (FREAK)/Program.cs +++ b/Samples/Imaging/Panorama (FREAK)/Program.cs @@ -1,7 +1,7 @@ using System; using System.Windows.Forms; -namespace Panorama.FREAK +namespace SampleApp { static class Program { diff --git a/Samples/Imaging/Panorama (FREAK)/Properties/Resources.Designer.cs b/Samples/Imaging/Panorama (FREAK)/Properties/Resources.Designer.cs index 180222eee..ed0575d93 100644 --- a/Samples/Imaging/Panorama (FREAK)/Properties/Resources.Designer.cs +++ b/Samples/Imaging/Panorama (FREAK)/Properties/Resources.Designer.cs @@ -1,103 +1,103 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.18052 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Panorama.FREAK.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Panorama.FREAK.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap UFSCar_CompDept1 { - get { - object obj = ResourceManager.GetObject("UFSCar_CompDept1", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap UFSCar_CompDept2 { - get { - object obj = ResourceManager.GetObject("UFSCar_CompDept2", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap UFSCar_Lake1 { - get { - object obj = ResourceManager.GetObject("UFSCar_Lake1", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap UFSCar_Lake2 { - get { - object obj = ResourceManager.GetObject("UFSCar_Lake2", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap UFSCar_CompDept1 { + get { + object obj = ResourceManager.GetObject("UFSCar_CompDept1", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap UFSCar_CompDept2 { + get { + object obj = ResourceManager.GetObject("UFSCar_CompDept2", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap UFSCar_Lake1 { + get { + object obj = ResourceManager.GetObject("UFSCar_Lake1", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap UFSCar_Lake2 { + get { + object obj = ResourceManager.GetObject("UFSCar_Lake2", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/Samples/Imaging/Panorama (FREAK)/Properties/Settings.Designer.cs b/Samples/Imaging/Panorama (FREAK)/Properties/Settings.Designer.cs index 25e634d02..dbc9e5d22 100644 --- a/Samples/Imaging/Panorama (FREAK)/Properties/Settings.Designer.cs +++ b/Samples/Imaging/Panorama (FREAK)/Properties/Settings.Designer.cs @@ -1,26 +1,26 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.18052 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Panorama.FREAK.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Samples/Imaging/Panorama (Harris)/Accord.dll.config b/Samples/Imaging/Panorama (Harris)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Imaging/Panorama (Harris)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Imaging/Panorama (Harris)/MainForm.Designer.cs b/Samples/Imaging/Panorama (Harris)/MainForm.Designer.cs index d2725357b..373daf30b 100644 --- a/Samples/Imaging/Panorama (Harris)/MainForm.Designer.cs +++ b/Samples/Imaging/Panorama (Harris)/MainForm.Designer.cs @@ -1,33 +1,33 @@ -namespace Panorama.Harris -{ - partial class MainForm - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { this.components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); this.imageList1 = new System.Windows.Forms.ImageList(this.components); @@ -133,17 +133,17 @@ private void InitializeComponent() ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).EndInit(); this.ResumeLayout(false); - } - - #endregion - - private System.Windows.Forms.Button button1; - private System.Windows.Forms.Button button2; - private System.Windows.Forms.ImageList imageList1; - private System.Windows.Forms.PictureBox pictureBox; - private System.Windows.Forms.Button button4; - private System.Windows.Forms.Button button5; - private System.Windows.Forms.Button button3; - } -} - + } + + #endregion + + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.ImageList imageList1; + private System.Windows.Forms.PictureBox pictureBox; + private System.Windows.Forms.Button button4; + private System.Windows.Forms.Button button5; + private System.Windows.Forms.Button button3; + } +} + diff --git a/Samples/Imaging/Panorama (Harris)/MainForm.cs b/Samples/Imaging/Panorama (Harris)/MainForm.cs index d53923348..6442f9f6e 100644 --- a/Samples/Imaging/Panorama (Harris)/MainForm.cs +++ b/Samples/Imaging/Panorama (Harris)/MainForm.cs @@ -38,12 +38,12 @@ using Accord.Math; using AForge; -namespace Panorama.Harris +namespace SampleApp { public partial class MainForm : Form { - private Bitmap img1 = Panorama.Harris.Properties.Resources.UFSCar_CompDept1; - private Bitmap img2 = Panorama.Harris.Properties.Resources.UFSCar_CompDept2; + private Bitmap img1 = SampleApp.Properties.Resources.UFSCar_CompDept1; + private Bitmap img2 = SampleApp.Properties.Resources.UFSCar_CompDept2; private IntPoint[] harrisPoints1; private IntPoint[] harrisPoints2; diff --git a/Samples/Imaging/Panorama (Harris)/Panorama (Harris).csproj b/Samples/Imaging/Panorama (Harris)/Panorama (Harris).csproj index 29ad43780..0d8e77254 100644 --- a/Samples/Imaging/Panorama (Harris)/Panorama (Harris).csproj +++ b/Samples/Imaging/Panorama (Harris)/Panorama (Harris).csproj @@ -1,164 +1,162 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {AEA25552-0508-4D42-AFBA-95DBB0BFBA67} - WinExe - Properties - Panorama.Harris - Panorama %28Harris%29 - v4.0 - 512 - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - - true - bin\x86\Debug\ - DEBUG;TRACE - full - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - bin\x86\Release\ - TRACE - true - pdbonly - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - framework.ico - - - - False - ..\..\..\Release\net40\Accord.dll - - - False - ..\..\..\Release\net40\Accord.Imaging.dll - - - False - ..\..\..\Release\net40\Accord.Math.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Imaging.dll - - - - 3.5 - - - - - - - - - Form - - - MainForm.cs - - - - - MainForm.cs - Designer - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - - - - - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - - - - + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {AEA25552-0508-4D42-AFBA-95DBB0BFBA67} + WinExe + Properties + SampleApp + Panorama %28Harris%29 + v4.0 + 512 + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + framework.ico + + + SampleApp.Program + + + + False + ..\..\..\Release\net40\Accord.dll + + + False + ..\..\..\Release\net40\Accord.Imaging.dll + + + False + ..\..\..\Release\net40\Accord.Math.dll + + + + 3.5 + + + + + + + + + Form + + + MainForm.cs + + + + + MainForm.cs + Designer + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + + + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + --> \ No newline at end of file diff --git a/Samples/Imaging/Panorama (Harris)/Program.cs b/Samples/Imaging/Panorama (Harris)/Program.cs index 5c4c2042e..316268492 100644 --- a/Samples/Imaging/Panorama (Harris)/Program.cs +++ b/Samples/Imaging/Panorama (Harris)/Program.cs @@ -1,7 +1,7 @@ using System; using System.Windows.Forms; -namespace Panorama.Harris +namespace SampleApp { static class Program { diff --git a/Samples/Imaging/Panorama (Harris)/Properties/Resources.Designer.cs b/Samples/Imaging/Panorama (Harris)/Properties/Resources.Designer.cs index 24de622e2..ed0575d93 100644 --- a/Samples/Imaging/Panorama (Harris)/Properties/Resources.Designer.cs +++ b/Samples/Imaging/Panorama (Harris)/Properties/Resources.Designer.cs @@ -1,103 +1,103 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.18052 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Panorama.Harris.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Panorama.Harris.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap UFSCar_CompDept1 { - get { - object obj = ResourceManager.GetObject("UFSCar_CompDept1", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap UFSCar_CompDept2 { - get { - object obj = ResourceManager.GetObject("UFSCar_CompDept2", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap UFSCar_Lake1 { - get { - object obj = ResourceManager.GetObject("UFSCar_Lake1", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap UFSCar_Lake2 { - get { - object obj = ResourceManager.GetObject("UFSCar_Lake2", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap UFSCar_CompDept1 { + get { + object obj = ResourceManager.GetObject("UFSCar_CompDept1", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap UFSCar_CompDept2 { + get { + object obj = ResourceManager.GetObject("UFSCar_CompDept2", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap UFSCar_Lake1 { + get { + object obj = ResourceManager.GetObject("UFSCar_Lake1", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap UFSCar_Lake2 { + get { + object obj = ResourceManager.GetObject("UFSCar_Lake2", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/Samples/Imaging/Panorama (Harris)/Properties/Settings.Designer.cs b/Samples/Imaging/Panorama (Harris)/Properties/Settings.Designer.cs index a7a7ea2e0..dbc9e5d22 100644 --- a/Samples/Imaging/Panorama (Harris)/Properties/Settings.Designer.cs +++ b/Samples/Imaging/Panorama (Harris)/Properties/Settings.Designer.cs @@ -1,26 +1,26 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.18052 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Panorama.Harris.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Samples/Imaging/Panorama (SURF)/Accord.dll.config b/Samples/Imaging/Panorama (SURF)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Imaging/Panorama (SURF)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Imaging/Panorama (SURF)/MainForm.Designer.cs b/Samples/Imaging/Panorama (SURF)/MainForm.Designer.cs index fb50457fe..c194f65e6 100644 --- a/Samples/Imaging/Panorama (SURF)/MainForm.Designer.cs +++ b/Samples/Imaging/Panorama (SURF)/MainForm.Designer.cs @@ -1,33 +1,33 @@ -namespace Panorama -{ - partial class MainForm - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { this.components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); this.imageList1 = new System.Windows.Forms.ImageList(this.components); @@ -133,17 +133,17 @@ private void InitializeComponent() ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).EndInit(); this.ResumeLayout(false); - } - - #endregion - - private System.Windows.Forms.Button button1; - private System.Windows.Forms.Button button2; - private System.Windows.Forms.ImageList imageList1; - private System.Windows.Forms.PictureBox pictureBox; - private System.Windows.Forms.Button button4; - private System.Windows.Forms.Button button5; - private System.Windows.Forms.Button button3; - } -} - + } + + #endregion + + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.ImageList imageList1; + private System.Windows.Forms.PictureBox pictureBox; + private System.Windows.Forms.Button button4; + private System.Windows.Forms.Button button5; + private System.Windows.Forms.Button button3; + } +} + diff --git a/Samples/Imaging/Panorama (SURF)/MainForm.cs b/Samples/Imaging/Panorama (SURF)/MainForm.cs index c4ae64110..113ef5ca9 100644 --- a/Samples/Imaging/Panorama (SURF)/MainForm.cs +++ b/Samples/Imaging/Panorama (SURF)/MainForm.cs @@ -1,171 +1,170 @@ -// Accord.NET Sample Applications -// http://accord-framework.net -// -// Copyright © 2009-2014, César Souza -// All rights reserved. 3-BSD License: -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// * Neither the name of the Accord.NET Framework authors nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -using System; -using System.Drawing; -using System.Windows.Forms; -using Accord.Imaging; -using Accord.Imaging.Filters; -using Accord.Math; -using AForge; -using Panorama.SURF.Properties; - -namespace Panorama -{ - public partial class MainForm : Form - { - private Bitmap img1 = Resources.UFSCar_Lake1; - private Bitmap img2 = Resources.UFSCar_Lake2; - - private SpeededUpRobustFeaturePoint[] surfPoints1; - private SpeededUpRobustFeaturePoint[] surfPoints2; - - private IntPoint[] correlationPoints1; - private IntPoint[] correlationPoints2; - - private MatrixH homography; - - - public MainForm() - { - InitializeComponent(); - - // Concatenate and show entire image at start - Concatenate concatenate = new Concatenate(img1); - pictureBox.Image = concatenate.Apply(img2); - } - - - private void btnSurf_Click(object sender, EventArgs e) - { - // Step 1: Detect feature points using Surf Corners Detector - SpeededUpRobustFeaturesDetector surf = new SpeededUpRobustFeaturesDetector(); - - surfPoints1 = surf.ProcessImage(img1).ToArray(); - surfPoints2 = surf.ProcessImage(img2).ToArray(); - - // Show the marked points in the original images - Bitmap img1mark = new FeaturesMarker(surfPoints1).Apply(img1); - Bitmap img2mark = new FeaturesMarker(surfPoints2).Apply(img2); - - // Concatenate the two images together in a single image (just to show on screen) - Concatenate concatenate = new Concatenate(img1mark); - pictureBox.Image = concatenate.Apply(img2mark); - } - - private void btnCorrelation_Click(object sender, EventArgs e) - { - if (surfPoints1 == null) - { - MessageBox.Show("Please, click SURF button first! :-)"); - return; - } - - // Step 2: Match feature points using a k-NN - KNearestNeighborMatching matcher = new KNearestNeighborMatching(5); - IntPoint[][] matches = matcher.Match(surfPoints1, surfPoints2); - - // Get the two sets of points - correlationPoints1 = matches[0]; - correlationPoints2 = matches[1]; - - // Concatenate the two images in a single image (just to show on screen) - Concatenate concat = new Concatenate(img1); - Bitmap img3 = concat.Apply(img2); - - // Show the marked correlations in the concatenated image - PairsMarker pairs = new PairsMarker( - correlationPoints1, // Add image1's width to the X points to show the markings correctly - correlationPoints2.Apply(p => new IntPoint(p.X + img1.Width, p.Y))); - - pictureBox.Image = pairs.Apply(img3); - } - - private void btnRansac_Click(object sender, EventArgs e) - { - if (correlationPoints1 == null) - { - MessageBox.Show("Please, click Nearest Neighbor button first! :-)"); - return; - } - - if (correlationPoints1.Length < 4 || correlationPoints2.Length < 4) - { - MessageBox.Show("Insufficient points to attempt a fit."); - return; - } - - // Step 3: Create the homography matrix using a robust estimator - RansacHomographyEstimator ransac = new RansacHomographyEstimator(0.001, 0.99); - homography = ransac.Estimate(correlationPoints1, correlationPoints2); - - // Plot RANSAC results against correlation results - IntPoint[] inliers1 = correlationPoints1.Submatrix(ransac.Inliers); - IntPoint[] inliers2 = correlationPoints2.Submatrix(ransac.Inliers); - - // Concatenate the two images in a single image (just to show on screen) - Concatenate concat = new Concatenate(img1); - Bitmap img3 = concat.Apply(img2); - - // Show the marked correlations in the concatenated image - PairsMarker pairs = new PairsMarker( - inliers1, // Add image1's width to the X points to show the markings correctly - inliers2.Apply(p => new IntPoint(p.X + img1.Width, p.Y))); - - pictureBox.Image = pairs.Apply(img3); - } - - private void btnBlend_Click(object sender, EventArgs e) - { - if (homography == null) - { - MessageBox.Show("Please, click RANSAC button first! :-)"); - return; - } - - // Step 4: Project and blend the second image using the homography - Blend blend = new Blend(homography, img1); - pictureBox.Image = blend.Apply(img2); - } - - private void btnDoItAll_Click(object sender, EventArgs e) - { - // Do it all - btnSurf_Click(sender, e); - btnCorrelation_Click(sender, e); - btnRansac_Click(sender, e); - btnBlend_Click(sender, e); - } - - - } -} +// Accord.NET Sample Applications +// http://accord-framework.net +// +// Copyright © 2009-2014, César Souza +// All rights reserved. 3-BSD License: +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of the Accord.NET Framework authors nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +using System; +using System.Drawing; +using System.Windows.Forms; +using Accord.Imaging; +using Accord.Imaging.Filters; +using Accord.Math; +using AForge; + +namespace SampleApp +{ + public partial class MainForm : Form + { + private Bitmap img1 = Properties.Resources.UFSCar_Lake1; + private Bitmap img2 = Properties.Resources.UFSCar_Lake2; + + private SpeededUpRobustFeaturePoint[] surfPoints1; + private SpeededUpRobustFeaturePoint[] surfPoints2; + + private IntPoint[] correlationPoints1; + private IntPoint[] correlationPoints2; + + private MatrixH homography; + + + public MainForm() + { + InitializeComponent(); + + // Concatenate and show entire image at start + Concatenate concatenate = new Concatenate(img1); + pictureBox.Image = concatenate.Apply(img2); + } + + + private void btnSurf_Click(object sender, EventArgs e) + { + // Step 1: Detect feature points using Surf Corners Detector + SpeededUpRobustFeaturesDetector surf = new SpeededUpRobustFeaturesDetector(); + + surfPoints1 = surf.ProcessImage(img1).ToArray(); + surfPoints2 = surf.ProcessImage(img2).ToArray(); + + // Show the marked points in the original images + Bitmap img1mark = new FeaturesMarker(surfPoints1).Apply(img1); + Bitmap img2mark = new FeaturesMarker(surfPoints2).Apply(img2); + + // Concatenate the two images together in a single image (just to show on screen) + Concatenate concatenate = new Concatenate(img1mark); + pictureBox.Image = concatenate.Apply(img2mark); + } + + private void btnCorrelation_Click(object sender, EventArgs e) + { + if (surfPoints1 == null) + { + MessageBox.Show("Please, click SURF button first! :-)"); + return; + } + + // Step 2: Match feature points using a k-NN + KNearestNeighborMatching matcher = new KNearestNeighborMatching(5); + IntPoint[][] matches = matcher.Match(surfPoints1, surfPoints2); + + // Get the two sets of points + correlationPoints1 = matches[0]; + correlationPoints2 = matches[1]; + + // Concatenate the two images in a single image (just to show on screen) + Concatenate concat = new Concatenate(img1); + Bitmap img3 = concat.Apply(img2); + + // Show the marked correlations in the concatenated image + PairsMarker pairs = new PairsMarker( + correlationPoints1, // Add image1's width to the X points to show the markings correctly + correlationPoints2.Apply(p => new IntPoint(p.X + img1.Width, p.Y))); + + pictureBox.Image = pairs.Apply(img3); + } + + private void btnRansac_Click(object sender, EventArgs e) + { + if (correlationPoints1 == null) + { + MessageBox.Show("Please, click Nearest Neighbor button first! :-)"); + return; + } + + if (correlationPoints1.Length < 4 || correlationPoints2.Length < 4) + { + MessageBox.Show("Insufficient points to attempt a fit."); + return; + } + + // Step 3: Create the homography matrix using a robust estimator + RansacHomographyEstimator ransac = new RansacHomographyEstimator(0.001, 0.99); + homography = ransac.Estimate(correlationPoints1, correlationPoints2); + + // Plot RANSAC results against correlation results + IntPoint[] inliers1 = correlationPoints1.Submatrix(ransac.Inliers); + IntPoint[] inliers2 = correlationPoints2.Submatrix(ransac.Inliers); + + // Concatenate the two images in a single image (just to show on screen) + Concatenate concat = new Concatenate(img1); + Bitmap img3 = concat.Apply(img2); + + // Show the marked correlations in the concatenated image + PairsMarker pairs = new PairsMarker( + inliers1, // Add image1's width to the X points to show the markings correctly + inliers2.Apply(p => new IntPoint(p.X + img1.Width, p.Y))); + + pictureBox.Image = pairs.Apply(img3); + } + + private void btnBlend_Click(object sender, EventArgs e) + { + if (homography == null) + { + MessageBox.Show("Please, click RANSAC button first! :-)"); + return; + } + + // Step 4: Project and blend the second image using the homography + Blend blend = new Blend(homography, img1); + pictureBox.Image = blend.Apply(img2); + } + + private void btnDoItAll_Click(object sender, EventArgs e) + { + // Do it all + btnSurf_Click(sender, e); + btnCorrelation_Click(sender, e); + btnRansac_Click(sender, e); + btnBlend_Click(sender, e); + } + + + } +} diff --git a/Samples/Imaging/Panorama (SURF)/Panorama (SURF).csproj b/Samples/Imaging/Panorama (SURF)/Panorama (SURF).csproj index 5e1aa1cff..ebd9d19a4 100644 --- a/Samples/Imaging/Panorama (SURF)/Panorama (SURF).csproj +++ b/Samples/Imaging/Panorama (SURF)/Panorama (SURF).csproj @@ -1,164 +1,162 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {27305F98-F71E-4FF4-8759-F13D58555200} - WinExe - Properties - Panorama.SURF - Panorama %28SURF%29 - v4.0 - 512 - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - - true - bin\x86\Debug\ - DEBUG;TRACE - full - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - bin\x86\Release\ - TRACE - true - pdbonly - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - framework.ico - - - - False - ..\..\..\Release\net40\Accord.dll - - - False - ..\..\..\Release\net40\Accord.Imaging.dll - - - False - ..\..\..\Release\net40\Accord.Math.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Imaging.dll - - - - 3.5 - - - - - - - - - Form - - - MainForm.cs - - - - - MainForm.cs - Designer - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - - - - - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - - - - + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {27305F98-F71E-4FF4-8759-F13D58555200} + WinExe + Properties + SampleApp + Panorama %28SURF%29 + v4.0 + 512 + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + framework.ico + + + SampleApp.Program + + + + False + ..\..\..\Release\net40\Accord.dll + + + False + ..\..\..\Release\net40\Accord.Imaging.dll + + + False + ..\..\..\Release\net40\Accord.Math.dll + + + + 3.5 + + + + + + + + + Form + + + MainForm.cs + + + + + MainForm.cs + Designer + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + + + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + --> \ No newline at end of file diff --git a/Samples/Imaging/Panorama (SURF)/Program.cs b/Samples/Imaging/Panorama (SURF)/Program.cs index d20c67d70..958cf8677 100644 --- a/Samples/Imaging/Panorama (SURF)/Program.cs +++ b/Samples/Imaging/Panorama (SURF)/Program.cs @@ -3,7 +3,7 @@ using System.Linq; using System.Windows.Forms; -namespace Panorama +namespace SampleApp { static class Program { diff --git a/Samples/Imaging/Panorama (SURF)/Properties/Resources.Designer.cs b/Samples/Imaging/Panorama (SURF)/Properties/Resources.Designer.cs index 985ad11d2..ed0575d93 100644 --- a/Samples/Imaging/Panorama (SURF)/Properties/Resources.Designer.cs +++ b/Samples/Imaging/Panorama (SURF)/Properties/Resources.Designer.cs @@ -1,103 +1,103 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.18052 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Panorama.SURF.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Panorama.SURF.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap UFSCar_CompDept1 { - get { - object obj = ResourceManager.GetObject("UFSCar_CompDept1", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap UFSCar_CompDept2 { - get { - object obj = ResourceManager.GetObject("UFSCar_CompDept2", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap UFSCar_Lake1 { - get { - object obj = ResourceManager.GetObject("UFSCar_Lake1", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap UFSCar_Lake2 { - get { - object obj = ResourceManager.GetObject("UFSCar_Lake2", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap UFSCar_CompDept1 { + get { + object obj = ResourceManager.GetObject("UFSCar_CompDept1", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap UFSCar_CompDept2 { + get { + object obj = ResourceManager.GetObject("UFSCar_CompDept2", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap UFSCar_Lake1 { + get { + object obj = ResourceManager.GetObject("UFSCar_Lake1", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap UFSCar_Lake2 { + get { + object obj = ResourceManager.GetObject("UFSCar_Lake2", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/Samples/Imaging/Panorama (SURF)/Properties/Settings.Designer.cs b/Samples/Imaging/Panorama (SURF)/Properties/Settings.Designer.cs index c45c28b09..dbc9e5d22 100644 --- a/Samples/Imaging/Panorama (SURF)/Properties/Settings.Designer.cs +++ b/Samples/Imaging/Panorama (SURF)/Properties/Settings.Designer.cs @@ -1,26 +1,26 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.18052 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Panorama.SURF.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Samples/Imaging/Pose Estimation (POSIT)/Accord.dll.config b/Samples/Imaging/Pose Estimation (POSIT)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Imaging/Pose Estimation (POSIT)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Imaging/Pose Estimation (POSIT)/MainForm.Designer.cs b/Samples/Imaging/Pose Estimation (POSIT)/MainForm.Designer.cs new file mode 100644 index 0000000000..15dcda2cd --- /dev/null +++ b/Samples/Imaging/Pose Estimation (POSIT)/MainForm.Designer.cs @@ -0,0 +1,905 @@ +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.components = new System.ComponentModel.Container( ); + this.mainPanel = new System.Windows.Forms.Panel( ); + this.groupBox1 = new System.Windows.Forms.GroupBox( ); + this.label7 = new System.Windows.Forms.Label( ); + this.label6 = new System.Windows.Forms.Label( ); + this.label5 = new System.Windows.Forms.Label( ); + this.pictureBox = new System.Windows.Forms.PictureBox( ); + this.mainMenu = new System.Windows.Forms.MenuStrip( ); + this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.openImageToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator( ); + this.openSample1ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.openSample2ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.openSample3ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.openSample4ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.openSample5ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator( ); + this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.openFileDialog = new System.Windows.Forms.OpenFileDialog( ); + this.panel1 = new System.Windows.Forms.Panel( ); + this.poseGroupBox = new System.Windows.Forms.GroupBox( ); + this.alternatePoseButton = new System.Windows.Forms.Button( ); + this.bestPoseButton = new System.Windows.Forms.Button( ); + this.focalLengthBox = new System.Windows.Forms.TextBox( ); + this.focalLengthLabel = new System.Windows.Forms.Label( ); + this.copositRadio = new System.Windows.Forms.RadioButton( ); + this.positRadio = new System.Windows.Forms.RadioButton( ); + this.estimatePostButton = new System.Windows.Forms.Button( ); + this.estimatedTransformationMatrixControl = new MatrixControl( ); + this.modelPointsGroupBox = new System.Windows.Forms.GroupBox( ); + this.modelPoint4zBox = new System.Windows.Forms.TextBox( ); + this.modelPoint4yBox = new System.Windows.Forms.TextBox( ); + this.modelPoint4xBox = new System.Windows.Forms.TextBox( ); + this.modelPoint3zBox = new System.Windows.Forms.TextBox( ); + this.modelPoint3yBox = new System.Windows.Forms.TextBox( ); + this.modelPoint3xBox = new System.Windows.Forms.TextBox( ); + this.modelPoint2zBox = new System.Windows.Forms.TextBox( ); + this.modelPoint2yBox = new System.Windows.Forms.TextBox( ); + this.modelPoint2xBox = new System.Windows.Forms.TextBox( ); + this.modelPoint1zBox = new System.Windows.Forms.TextBox( ); + this.modelPoint1yBox = new System.Windows.Forms.TextBox( ); + this.modelPoint1xBox = new System.Windows.Forms.TextBox( ); + this.modelPoint4Label = new System.Windows.Forms.Label( ); + this.modelPoint1Label = new System.Windows.Forms.Label( ); + this.modelPoint3Label = new System.Windows.Forms.Label( ); + this.modelPoint2Label = new System.Windows.Forms.Label( ); + this.imagePointsGroupBox = new System.Windows.Forms.GroupBox( ); + this.imagePoint4ColorLabel = new System.Windows.Forms.Label( ); + this.imagePoint3ColorLabel = new System.Windows.Forms.Label( ); + this.imagePoint2ColorLabel = new System.Windows.Forms.Label( ); + this.imagePoint1ColorLabel = new System.Windows.Forms.Label( ); + this.locate4Button = new System.Windows.Forms.Button( ); + this.imagePoint4Box = new System.Windows.Forms.TextBox( ); + this.label4 = new System.Windows.Forms.Label( ); + this.locate3Button = new System.Windows.Forms.Button( ); + this.imagePoint3Box = new System.Windows.Forms.TextBox( ); + this.label3 = new System.Windows.Forms.Label( ); + this.locate2Button = new System.Windows.Forms.Button( ); + this.imagePoint2Box = new System.Windows.Forms.TextBox( ); + this.label2 = new System.Windows.Forms.Label( ); + this.locate1Button = new System.Windows.Forms.Button( ); + this.imagePoint1Box = new System.Windows.Forms.TextBox( ); + this.label1 = new System.Windows.Forms.Label( ); + this.statusStrip = new System.Windows.Forms.StatusStrip( ); + this.statusLabel = new System.Windows.Forms.ToolStripStatusLabel( ); + this.estimationLabel = new System.Windows.Forms.ToolStripStatusLabel( ); + this.imageSizeLabel = new System.Windows.Forms.ToolStripStatusLabel( ); + this.errorProvider = new System.Windows.Forms.ErrorProvider( this.components ); + this.toolTip = new System.Windows.Forms.ToolTip( this.components ); + this.mainPanel.SuspendLayout( ); + this.groupBox1.SuspendLayout( ); + ( (System.ComponentModel.ISupportInitialize) ( this.pictureBox ) ).BeginInit( ); + this.mainMenu.SuspendLayout( ); + this.panel1.SuspendLayout( ); + this.poseGroupBox.SuspendLayout( ); + this.modelPointsGroupBox.SuspendLayout( ); + this.imagePointsGroupBox.SuspendLayout( ); + this.statusStrip.SuspendLayout( ); + ( (System.ComponentModel.ISupportInitialize) ( this.errorProvider ) ).BeginInit( ); + this.SuspendLayout( ); + // + // mainPanel + // + this.mainPanel.Anchor = ( (System.Windows.Forms.AnchorStyles) ( ( ( ( System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom ) + | System.Windows.Forms.AnchorStyles.Left ) + | System.Windows.Forms.AnchorStyles.Right ) ) ); + this.mainPanel.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; + this.mainPanel.Controls.Add( this.groupBox1 ); + this.mainPanel.Controls.Add( this.pictureBox ); + this.mainPanel.Location = new System.Drawing.Point( 0, 27 ); + this.mainPanel.Name = "mainPanel"; + this.mainPanel.Size = new System.Drawing.Size( 974, 478 ); + this.mainPanel.TabIndex = 1; + // + // groupBox1 + // + this.groupBox1.Controls.Add( this.label7 ); + this.groupBox1.Controls.Add( this.label6 ); + this.groupBox1.Controls.Add( this.label5 ); + this.groupBox1.ForeColor = System.Drawing.SystemColors.ControlText; + this.groupBox1.Location = new System.Drawing.Point( 10, 5 ); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size( 65, 85 ); + this.groupBox1.TabIndex = 1; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Legend"; + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Font = new System.Drawing.Font( "Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ( (byte) ( 204 ) ) ); + this.label7.ForeColor = System.Drawing.Color.Lime; + this.label7.Location = new System.Drawing.Point( 10, 60 ); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size( 41, 13 ); + this.label7.TabIndex = 2; + this.label7.Text = "Z axis"; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Font = new System.Drawing.Font( "Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ( (byte) ( 204 ) ) ); + this.label6.ForeColor = System.Drawing.Color.Red; + this.label6.Location = new System.Drawing.Point( 10, 40 ); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size( 41, 13 ); + this.label6.TabIndex = 1; + this.label6.Text = "Y axis"; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Font = new System.Drawing.Font( "Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ( (byte) ( 204 ) ) ); + this.label5.ForeColor = System.Drawing.Color.Blue; + this.label5.Location = new System.Drawing.Point( 10, 20 ); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size( 41, 13 ); + this.label5.TabIndex = 0; + this.label5.Text = "X axis"; + // + // pictureBox + // + this.pictureBox.BackColor = System.Drawing.SystemColors.ControlDark; + this.pictureBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.pictureBox.Location = new System.Drawing.Point( 299, 128 ); + this.pictureBox.Name = "pictureBox"; + this.pictureBox.Size = new System.Drawing.Size( 320, 240 ); + this.pictureBox.TabIndex = 0; + this.pictureBox.TabStop = false; + this.pictureBox.MouseMove += new System.Windows.Forms.MouseEventHandler( this.pictureBox_MouseMove ); + this.pictureBox.MouseClick += new System.Windows.Forms.MouseEventHandler( this.pictureBox_MouseClick ); + this.pictureBox.Paint += new System.Windows.Forms.PaintEventHandler( this.pictureBox_Paint ); + // + // mainMenu + // + this.mainMenu.Items.AddRange( new System.Windows.Forms.ToolStripItem[] { + this.fileToolStripMenuItem} ); + this.mainMenu.Location = new System.Drawing.Point( 0, 0 ); + this.mainMenu.Name = "mainMenu"; + this.mainMenu.Size = new System.Drawing.Size( 974, 24 ); + this.mainMenu.TabIndex = 0; + // + // fileToolStripMenuItem + // + this.fileToolStripMenuItem.DropDownItems.AddRange( new System.Windows.Forms.ToolStripItem[] { + this.openImageToolStripMenuItem, + this.toolStripMenuItem2, + this.openSample1ToolStripMenuItem, + this.openSample2ToolStripMenuItem, + this.openSample3ToolStripMenuItem, + this.openSample4ToolStripMenuItem, + this.openSample5ToolStripMenuItem, + this.toolStripMenuItem1, + this.exitToolStripMenuItem} ); + this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; + this.fileToolStripMenuItem.Size = new System.Drawing.Size( 37, 20 ); + this.fileToolStripMenuItem.Text = "&File"; + // + // openImageToolStripMenuItem + // + this.openImageToolStripMenuItem.Name = "openImageToolStripMenuItem"; + this.openImageToolStripMenuItem.ShortcutKeys = ( (System.Windows.Forms.Keys) ( ( System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O ) ) ); + this.openImageToolStripMenuItem.Size = new System.Drawing.Size( 193, 22 ); + this.openImageToolStripMenuItem.Text = "&Open image"; + this.openImageToolStripMenuItem.Click += new System.EventHandler( this.openImageToolStripMenuItem_Click ); + // + // toolStripMenuItem2 + // + this.toolStripMenuItem2.Name = "toolStripMenuItem2"; + this.toolStripMenuItem2.Size = new System.Drawing.Size( 190, 6 ); + // + // openSample1ToolStripMenuItem + // + this.openSample1ToolStripMenuItem.Name = "openSample1ToolStripMenuItem"; + this.openSample1ToolStripMenuItem.ShortcutKeys = ( (System.Windows.Forms.Keys) ( ( System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.D1 ) ) ); + this.openSample1ToolStripMenuItem.Size = new System.Drawing.Size( 193, 22 ); + this.openSample1ToolStripMenuItem.Tag = "0"; + this.openSample1ToolStripMenuItem.Text = "Open sample &1"; + this.openSample1ToolStripMenuItem.Click += new System.EventHandler( this.openSampleToolStripMenuItem_Click ); + // + // openSample2ToolStripMenuItem + // + this.openSample2ToolStripMenuItem.Name = "openSample2ToolStripMenuItem"; + this.openSample2ToolStripMenuItem.ShortcutKeys = ( (System.Windows.Forms.Keys) ( ( System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.D2 ) ) ); + this.openSample2ToolStripMenuItem.Size = new System.Drawing.Size( 193, 22 ); + this.openSample2ToolStripMenuItem.Tag = "1"; + this.openSample2ToolStripMenuItem.Text = "Open sample &2"; + this.openSample2ToolStripMenuItem.Click += new System.EventHandler( this.openSampleToolStripMenuItem_Click ); + // + // openSample3ToolStripMenuItem + // + this.openSample3ToolStripMenuItem.Name = "openSample3ToolStripMenuItem"; + this.openSample3ToolStripMenuItem.ShortcutKeys = ( (System.Windows.Forms.Keys) ( ( System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.D3 ) ) ); + this.openSample3ToolStripMenuItem.Size = new System.Drawing.Size( 193, 22 ); + this.openSample3ToolStripMenuItem.Tag = "2"; + this.openSample3ToolStripMenuItem.Text = "Open sample &3"; + this.openSample3ToolStripMenuItem.Click += new System.EventHandler( this.openSampleToolStripMenuItem_Click ); + // + // openSample4ToolStripMenuItem + // + this.openSample4ToolStripMenuItem.Name = "openSample4ToolStripMenuItem"; + this.openSample4ToolStripMenuItem.ShortcutKeys = ( (System.Windows.Forms.Keys) ( ( System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.D4 ) ) ); + this.openSample4ToolStripMenuItem.Size = new System.Drawing.Size( 193, 22 ); + this.openSample4ToolStripMenuItem.Tag = "3"; + this.openSample4ToolStripMenuItem.Text = "Open sample &4"; + this.openSample4ToolStripMenuItem.Click += new System.EventHandler( this.openSampleToolStripMenuItem_Click ); + // + // openSample5ToolStripMenuItem + // + this.openSample5ToolStripMenuItem.Name = "openSample5ToolStripMenuItem"; + this.openSample5ToolStripMenuItem.ShortcutKeys = ( (System.Windows.Forms.Keys) ( ( System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.D5 ) ) ); + this.openSample5ToolStripMenuItem.Size = new System.Drawing.Size( 193, 22 ); + this.openSample5ToolStripMenuItem.Tag = "4"; + this.openSample5ToolStripMenuItem.Text = "Open sample &5"; + this.openSample5ToolStripMenuItem.Click += new System.EventHandler( this.openSampleToolStripMenuItem_Click ); + // + // toolStripMenuItem1 + // + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + this.toolStripMenuItem1.Size = new System.Drawing.Size( 190, 6 ); + // + // exitToolStripMenuItem + // + this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; + this.exitToolStripMenuItem.Size = new System.Drawing.Size( 193, 22 ); + this.exitToolStripMenuItem.Text = "E&xit"; + this.exitToolStripMenuItem.Click += new System.EventHandler( this.exitToolStripMenuItem_Click ); + // + // openFileDialog + // + this.openFileDialog.Filter = "Image files (*.jpg, *.bmp, *.png)|*.jpg; *.bmp; *.png"; + this.openFileDialog.Title = "Select a image file"; + // + // panel1 + // + this.panel1.Anchor = ( (System.Windows.Forms.AnchorStyles) ( ( ( System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left ) + | System.Windows.Forms.AnchorStyles.Right ) ) ); + this.panel1.Controls.Add( this.poseGroupBox ); + this.panel1.Controls.Add( this.modelPointsGroupBox ); + this.panel1.Controls.Add( this.imagePointsGroupBox ); + this.panel1.Location = new System.Drawing.Point( 0, 511 ); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size( 974, 130 ); + this.panel1.TabIndex = 2; + // + // poseGroupBox + // + this.poseGroupBox.Anchor = ( (System.Windows.Forms.AnchorStyles) ( ( ( ( System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom ) + | System.Windows.Forms.AnchorStyles.Left ) + | System.Windows.Forms.AnchorStyles.Right ) ) ); + this.poseGroupBox.Controls.Add( this.alternatePoseButton ); + this.poseGroupBox.Controls.Add( this.bestPoseButton ); + this.poseGroupBox.Controls.Add( this.focalLengthBox ); + this.poseGroupBox.Controls.Add( this.focalLengthLabel ); + this.poseGroupBox.Controls.Add( this.copositRadio ); + this.poseGroupBox.Controls.Add( this.positRadio ); + this.poseGroupBox.Controls.Add( this.estimatePostButton ); + this.poseGroupBox.Controls.Add( this.estimatedTransformationMatrixControl ); + this.poseGroupBox.Location = new System.Drawing.Point( 530, 0 ); + this.poseGroupBox.Name = "poseGroupBox"; + this.poseGroupBox.Size = new System.Drawing.Size( 432, 127 ); + this.poseGroupBox.TabIndex = 2; + this.poseGroupBox.TabStop = false; + this.poseGroupBox.Text = "Pose estimation"; + // + // alternatePoseButton + // + this.alternatePoseButton.Location = new System.Drawing.Point( 345, 7 ); + this.alternatePoseButton.Name = "alternatePoseButton"; + this.alternatePoseButton.Size = new System.Drawing.Size( 20, 20 ); + this.alternatePoseButton.TabIndex = 2; + this.alternatePoseButton.Text = "&A"; + this.toolTip.SetToolTip( this.alternatePoseButton, "Select alternate CoPOSIT estimation" ); + this.alternatePoseButton.UseVisualStyleBackColor = true; + this.alternatePoseButton.Click += new System.EventHandler( this.alternatePoseButton_Click ); + // + // bestPoseButton + // + this.bestPoseButton.Location = new System.Drawing.Point( 320, 7 ); + this.bestPoseButton.Name = "bestPoseButton"; + this.bestPoseButton.Size = new System.Drawing.Size( 20, 20 ); + this.bestPoseButton.TabIndex = 1; + this.bestPoseButton.Text = "&B"; + this.toolTip.SetToolTip( this.bestPoseButton, "Select best CoPOSIT estimation" ); + this.bestPoseButton.UseVisualStyleBackColor = true; + this.bestPoseButton.Click += new System.EventHandler( this.bestPoseButton_Click ); + // + // focalLengthBox + // + this.focalLengthBox.Location = new System.Drawing.Point( 95, 50 ); + this.focalLengthBox.Name = "focalLengthBox"; + this.focalLengthBox.Size = new System.Drawing.Size( 85, 20 ); + this.focalLengthBox.TabIndex = 4; + this.focalLengthBox.Leave += new System.EventHandler( this.focalLengthBox_Leave ); + // + // focalLengthLabel + // + this.focalLengthLabel.AutoSize = true; + this.focalLengthLabel.Location = new System.Drawing.Point( 10, 53 ); + this.focalLengthLabel.Name = "focalLengthLabel"; + this.focalLengthLabel.Size = new System.Drawing.Size( 68, 13 ); + this.focalLengthLabel.TabIndex = 3; + this.focalLengthLabel.Text = "Focal length:"; + this.toolTip.SetToolTip( this.focalLengthLabel, "Effective Focal Length" ); + // + // copositRadio + // + this.copositRadio.AutoSize = true; + this.copositRadio.Location = new System.Drawing.Point( 80, 23 ); + this.copositRadio.Name = "copositRadio"; + this.copositRadio.Size = new System.Drawing.Size( 102, 17 ); + this.copositRadio.TabIndex = 2; + this.copositRadio.TabStop = true; + this.copositRadio.Text = "Coplanar POSIT"; + this.copositRadio.UseVisualStyleBackColor = true; + this.copositRadio.CheckedChanged += new System.EventHandler( this.copositRadio_CheckedChanged ); + // + // positRadio + // + this.positRadio.AutoSize = true; + this.positRadio.Location = new System.Drawing.Point( 10, 23 ); + this.positRadio.Name = "positRadio"; + this.positRadio.Size = new System.Drawing.Size( 57, 17 ); + this.positRadio.TabIndex = 1; + this.positRadio.TabStop = true; + this.positRadio.Text = "POSIT"; + this.positRadio.UseVisualStyleBackColor = true; + // + // estimatePostButton + // + this.estimatePostButton.Location = new System.Drawing.Point( 105, 93 ); + this.estimatePostButton.Name = "estimatePostButton"; + this.estimatePostButton.Size = new System.Drawing.Size( 75, 23 ); + this.estimatePostButton.TabIndex = 0; + this.estimatePostButton.Text = "&Estimate"; + this.estimatePostButton.UseVisualStyleBackColor = true; + this.estimatePostButton.Click += new System.EventHandler( this.estimatePostButton_Click ); + // + // estimatedTransformationMatrixControl + // + this.estimatedTransformationMatrixControl.Location = new System.Drawing.Point( 190, 10 ); + this.estimatedTransformationMatrixControl.Name = "estimatedTransformationMatrixControl"; + this.estimatedTransformationMatrixControl.Size = new System.Drawing.Size( 230, 110 ); + this.estimatedTransformationMatrixControl.TabIndex = 5; + this.estimatedTransformationMatrixControl.Title = "Estimated transformation"; + // + // modelPointsGroupBox + // + this.modelPointsGroupBox.Anchor = ( (System.Windows.Forms.AnchorStyles) ( ( ( System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom ) + | System.Windows.Forms.AnchorStyles.Left ) ) ); + this.modelPointsGroupBox.Controls.Add( this.modelPoint4zBox ); + this.modelPointsGroupBox.Controls.Add( this.modelPoint4yBox ); + this.modelPointsGroupBox.Controls.Add( this.modelPoint4xBox ); + this.modelPointsGroupBox.Controls.Add( this.modelPoint3zBox ); + this.modelPointsGroupBox.Controls.Add( this.modelPoint3yBox ); + this.modelPointsGroupBox.Controls.Add( this.modelPoint3xBox ); + this.modelPointsGroupBox.Controls.Add( this.modelPoint2zBox ); + this.modelPointsGroupBox.Controls.Add( this.modelPoint2yBox ); + this.modelPointsGroupBox.Controls.Add( this.modelPoint2xBox ); + this.modelPointsGroupBox.Controls.Add( this.modelPoint1zBox ); + this.modelPointsGroupBox.Controls.Add( this.modelPoint1yBox ); + this.modelPointsGroupBox.Controls.Add( this.modelPoint1xBox ); + this.modelPointsGroupBox.Controls.Add( this.modelPoint4Label ); + this.modelPointsGroupBox.Controls.Add( this.modelPoint1Label ); + this.modelPointsGroupBox.Controls.Add( this.modelPoint3Label ); + this.modelPointsGroupBox.Controls.Add( this.modelPoint2Label ); + this.modelPointsGroupBox.Location = new System.Drawing.Point( 250, 0 ); + this.modelPointsGroupBox.Name = "modelPointsGroupBox"; + this.modelPointsGroupBox.Size = new System.Drawing.Size( 270, 127 ); + this.modelPointsGroupBox.TabIndex = 1; + this.modelPointsGroupBox.TabStop = false; + this.modelPointsGroupBox.Text = "Model coordinates (x, y, z)"; + // + // modelPoint4zBox + // + this.modelPoint4zBox.Location = new System.Drawing.Point( 200, 95 ); + this.modelPoint4zBox.Name = "modelPoint4zBox"; + this.modelPoint4zBox.Size = new System.Drawing.Size( 60, 20 ); + this.modelPoint4zBox.TabIndex = 15; + this.modelPoint4zBox.Tag = "32"; + this.modelPoint4zBox.Leave += new System.EventHandler( this.modelPointBox_Leave ); + // + // modelPoint4yBox + // + this.modelPoint4yBox.Location = new System.Drawing.Point( 135, 95 ); + this.modelPoint4yBox.Name = "modelPoint4yBox"; + this.modelPoint4yBox.Size = new System.Drawing.Size( 60, 20 ); + this.modelPoint4yBox.TabIndex = 14; + this.modelPoint4yBox.Tag = "31"; + this.modelPoint4yBox.Leave += new System.EventHandler( this.modelPointBox_Leave ); + // + // modelPoint4xBox + // + this.modelPoint4xBox.Location = new System.Drawing.Point( 70, 95 ); + this.modelPoint4xBox.Name = "modelPoint4xBox"; + this.modelPoint4xBox.Size = new System.Drawing.Size( 60, 20 ); + this.modelPoint4xBox.TabIndex = 13; + this.modelPoint4xBox.Tag = "30"; + this.modelPoint4xBox.Leave += new System.EventHandler( this.modelPointBox_Leave ); + // + // modelPoint3zBox + // + this.modelPoint3zBox.Location = new System.Drawing.Point( 200, 70 ); + this.modelPoint3zBox.Name = "modelPoint3zBox"; + this.modelPoint3zBox.Size = new System.Drawing.Size( 60, 20 ); + this.modelPoint3zBox.TabIndex = 11; + this.modelPoint3zBox.Tag = "22"; + this.modelPoint3zBox.Leave += new System.EventHandler( this.modelPointBox_Leave ); + // + // modelPoint3yBox + // + this.modelPoint3yBox.Location = new System.Drawing.Point( 135, 70 ); + this.modelPoint3yBox.Name = "modelPoint3yBox"; + this.modelPoint3yBox.Size = new System.Drawing.Size( 60, 20 ); + this.modelPoint3yBox.TabIndex = 10; + this.modelPoint3yBox.Tag = "21"; + this.modelPoint3yBox.Leave += new System.EventHandler( this.modelPointBox_Leave ); + // + // modelPoint3xBox + // + this.modelPoint3xBox.Location = new System.Drawing.Point( 70, 70 ); + this.modelPoint3xBox.Name = "modelPoint3xBox"; + this.modelPoint3xBox.Size = new System.Drawing.Size( 60, 20 ); + this.modelPoint3xBox.TabIndex = 9; + this.modelPoint3xBox.Tag = "20"; + this.modelPoint3xBox.Leave += new System.EventHandler( this.modelPointBox_Leave ); + // + // modelPoint2zBox + // + this.modelPoint2zBox.Location = new System.Drawing.Point( 200, 45 ); + this.modelPoint2zBox.Name = "modelPoint2zBox"; + this.modelPoint2zBox.Size = new System.Drawing.Size( 60, 20 ); + this.modelPoint2zBox.TabIndex = 7; + this.modelPoint2zBox.Tag = "12"; + this.modelPoint2zBox.Leave += new System.EventHandler( this.modelPointBox_Leave ); + // + // modelPoint2yBox + // + this.modelPoint2yBox.Location = new System.Drawing.Point( 135, 45 ); + this.modelPoint2yBox.Name = "modelPoint2yBox"; + this.modelPoint2yBox.Size = new System.Drawing.Size( 60, 20 ); + this.modelPoint2yBox.TabIndex = 6; + this.modelPoint2yBox.Tag = "11"; + this.modelPoint2yBox.Leave += new System.EventHandler( this.modelPointBox_Leave ); + // + // modelPoint2xBox + // + this.modelPoint2xBox.Location = new System.Drawing.Point( 70, 45 ); + this.modelPoint2xBox.Name = "modelPoint2xBox"; + this.modelPoint2xBox.Size = new System.Drawing.Size( 60, 20 ); + this.modelPoint2xBox.TabIndex = 5; + this.modelPoint2xBox.Tag = "10"; + this.modelPoint2xBox.Leave += new System.EventHandler( this.modelPointBox_Leave ); + // + // modelPoint1zBox + // + this.modelPoint1zBox.Location = new System.Drawing.Point( 200, 20 ); + this.modelPoint1zBox.Name = "modelPoint1zBox"; + this.modelPoint1zBox.Size = new System.Drawing.Size( 60, 20 ); + this.modelPoint1zBox.TabIndex = 3; + this.modelPoint1zBox.Tag = "2"; + this.modelPoint1zBox.Leave += new System.EventHandler( this.modelPointBox_Leave ); + // + // modelPoint1yBox + // + this.modelPoint1yBox.Location = new System.Drawing.Point( 135, 20 ); + this.modelPoint1yBox.Name = "modelPoint1yBox"; + this.modelPoint1yBox.Size = new System.Drawing.Size( 60, 20 ); + this.modelPoint1yBox.TabIndex = 2; + this.modelPoint1yBox.Tag = "1"; + this.modelPoint1yBox.Leave += new System.EventHandler( this.modelPointBox_Leave ); + // + // modelPoint1xBox + // + this.modelPoint1xBox.Location = new System.Drawing.Point( 70, 20 ); + this.modelPoint1xBox.Name = "modelPoint1xBox"; + this.modelPoint1xBox.Size = new System.Drawing.Size( 60, 20 ); + this.modelPoint1xBox.TabIndex = 1; + this.modelPoint1xBox.Tag = "0"; + this.modelPoint1xBox.Leave += new System.EventHandler( this.modelPointBox_Leave ); + // + // modelPoint4Label + // + this.modelPoint4Label.AutoSize = true; + this.modelPoint4Label.Location = new System.Drawing.Point( 10, 98 ); + this.modelPoint4Label.Name = "modelPoint4Label"; + this.modelPoint4Label.Size = new System.Drawing.Size( 43, 13 ); + this.modelPoint4Label.TabIndex = 12; + this.modelPoint4Label.Text = "Point 4:"; + // + // modelPoint1Label + // + this.modelPoint1Label.AutoSize = true; + this.modelPoint1Label.Location = new System.Drawing.Point( 10, 23 ); + this.modelPoint1Label.Name = "modelPoint1Label"; + this.modelPoint1Label.Size = new System.Drawing.Size( 43, 13 ); + this.modelPoint1Label.TabIndex = 0; + this.modelPoint1Label.Text = "Point 1:"; + // + // modelPoint3Label + // + this.modelPoint3Label.AutoSize = true; + this.modelPoint3Label.Location = new System.Drawing.Point( 10, 73 ); + this.modelPoint3Label.Name = "modelPoint3Label"; + this.modelPoint3Label.Size = new System.Drawing.Size( 43, 13 ); + this.modelPoint3Label.TabIndex = 8; + this.modelPoint3Label.Text = "Point 3:"; + // + // modelPoint2Label + // + this.modelPoint2Label.AutoSize = true; + this.modelPoint2Label.Location = new System.Drawing.Point( 10, 48 ); + this.modelPoint2Label.Name = "modelPoint2Label"; + this.modelPoint2Label.Size = new System.Drawing.Size( 43, 13 ); + this.modelPoint2Label.TabIndex = 4; + this.modelPoint2Label.Text = "Point 2:"; + // + // imagePointsGroupBox + // + this.imagePointsGroupBox.Anchor = ( (System.Windows.Forms.AnchorStyles) ( ( ( System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom ) + | System.Windows.Forms.AnchorStyles.Left ) ) ); + this.imagePointsGroupBox.Controls.Add( this.imagePoint4ColorLabel ); + this.imagePointsGroupBox.Controls.Add( this.imagePoint3ColorLabel ); + this.imagePointsGroupBox.Controls.Add( this.imagePoint2ColorLabel ); + this.imagePointsGroupBox.Controls.Add( this.imagePoint1ColorLabel ); + this.imagePointsGroupBox.Controls.Add( this.locate4Button ); + this.imagePointsGroupBox.Controls.Add( this.imagePoint4Box ); + this.imagePointsGroupBox.Controls.Add( this.label4 ); + this.imagePointsGroupBox.Controls.Add( this.locate3Button ); + this.imagePointsGroupBox.Controls.Add( this.imagePoint3Box ); + this.imagePointsGroupBox.Controls.Add( this.label3 ); + this.imagePointsGroupBox.Controls.Add( this.locate2Button ); + this.imagePointsGroupBox.Controls.Add( this.imagePoint2Box ); + this.imagePointsGroupBox.Controls.Add( this.label2 ); + this.imagePointsGroupBox.Controls.Add( this.locate1Button ); + this.imagePointsGroupBox.Controls.Add( this.imagePoint1Box ); + this.imagePointsGroupBox.Controls.Add( this.label1 ); + this.imagePointsGroupBox.Location = new System.Drawing.Point( 10, 0 ); + this.imagePointsGroupBox.Name = "imagePointsGroupBox"; + this.imagePointsGroupBox.Size = new System.Drawing.Size( 230, 127 ); + this.imagePointsGroupBox.TabIndex = 0; + this.imagePointsGroupBox.TabStop = false; + this.imagePointsGroupBox.Text = "Image coordinates (x, y)"; + // + // imagePoint4ColorLabel + // + this.imagePoint4ColorLabel.BackColor = System.Drawing.Color.Black; + this.imagePoint4ColorLabel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.imagePoint4ColorLabel.Location = new System.Drawing.Point( 55, 115 ); + this.imagePoint4ColorLabel.Name = "imagePoint4ColorLabel"; + this.imagePoint4ColorLabel.Size = new System.Drawing.Size( 75, 4 ); + this.imagePoint4ColorLabel.TabIndex = 20; + // + // imagePoint3ColorLabel + // + this.imagePoint3ColorLabel.BackColor = System.Drawing.Color.Black; + this.imagePoint3ColorLabel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.imagePoint3ColorLabel.Location = new System.Drawing.Point( 55, 90 ); + this.imagePoint3ColorLabel.Name = "imagePoint3ColorLabel"; + this.imagePoint3ColorLabel.Size = new System.Drawing.Size( 75, 4 ); + this.imagePoint3ColorLabel.TabIndex = 19; + // + // imagePoint2ColorLabel + // + this.imagePoint2ColorLabel.BackColor = System.Drawing.Color.Black; + this.imagePoint2ColorLabel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.imagePoint2ColorLabel.Location = new System.Drawing.Point( 55, 65 ); + this.imagePoint2ColorLabel.Name = "imagePoint2ColorLabel"; + this.imagePoint2ColorLabel.Size = new System.Drawing.Size( 75, 4 ); + this.imagePoint2ColorLabel.TabIndex = 18; + // + // imagePoint1ColorLabel + // + this.imagePoint1ColorLabel.BackColor = System.Drawing.Color.Black; + this.imagePoint1ColorLabel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.imagePoint1ColorLabel.Location = new System.Drawing.Point( 55, 40 ); + this.imagePoint1ColorLabel.Name = "imagePoint1ColorLabel"; + this.imagePoint1ColorLabel.Size = new System.Drawing.Size( 75, 4 ); + this.imagePoint1ColorLabel.TabIndex = 17; + // + // locate4Button + // + this.locate4Button.Location = new System.Drawing.Point( 140, 94 ); + this.locate4Button.Name = "locate4Button"; + this.locate4Button.Size = new System.Drawing.Size( 75, 23 ); + this.locate4Button.TabIndex = 11; + this.locate4Button.Tag = "3"; + this.locate4Button.Text = "Locate &4th"; + this.locate4Button.UseVisualStyleBackColor = true; + this.locate4Button.Click += new System.EventHandler( this.locatePointButton_Click ); + // + // imagePoint4Box + // + this.imagePoint4Box.Location = new System.Drawing.Point( 55, 95 ); + this.imagePoint4Box.Name = "imagePoint4Box"; + this.imagePoint4Box.ReadOnly = true; + this.imagePoint4Box.Size = new System.Drawing.Size( 75, 20 ); + this.imagePoint4Box.TabIndex = 10; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point( 10, 98 ); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size( 43, 13 ); + this.label4.TabIndex = 9; + this.label4.Text = "Point 4:"; + // + // locate3Button + // + this.locate3Button.Location = new System.Drawing.Point( 140, 69 ); + this.locate3Button.Name = "locate3Button"; + this.locate3Button.Size = new System.Drawing.Size( 75, 23 ); + this.locate3Button.TabIndex = 8; + this.locate3Button.Tag = "2"; + this.locate3Button.Text = "Locate &3rd"; + this.locate3Button.UseVisualStyleBackColor = true; + this.locate3Button.Click += new System.EventHandler( this.locatePointButton_Click ); + // + // imagePoint3Box + // + this.imagePoint3Box.Location = new System.Drawing.Point( 55, 70 ); + this.imagePoint3Box.Name = "imagePoint3Box"; + this.imagePoint3Box.ReadOnly = true; + this.imagePoint3Box.Size = new System.Drawing.Size( 75, 20 ); + this.imagePoint3Box.TabIndex = 7; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point( 10, 73 ); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size( 43, 13 ); + this.label3.TabIndex = 6; + this.label3.Text = "Point 3:"; + // + // locate2Button + // + this.locate2Button.Location = new System.Drawing.Point( 140, 44 ); + this.locate2Button.Name = "locate2Button"; + this.locate2Button.Size = new System.Drawing.Size( 75, 23 ); + this.locate2Button.TabIndex = 5; + this.locate2Button.Tag = "1"; + this.locate2Button.Text = "Locate &2nd"; + this.locate2Button.UseVisualStyleBackColor = true; + this.locate2Button.Click += new System.EventHandler( this.locatePointButton_Click ); + // + // imagePoint2Box + // + this.imagePoint2Box.Location = new System.Drawing.Point( 55, 45 ); + this.imagePoint2Box.Name = "imagePoint2Box"; + this.imagePoint2Box.ReadOnly = true; + this.imagePoint2Box.Size = new System.Drawing.Size( 75, 20 ); + this.imagePoint2Box.TabIndex = 4; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point( 10, 48 ); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size( 43, 13 ); + this.label2.TabIndex = 3; + this.label2.Text = "Point 2:"; + // + // locate1Button + // + this.locate1Button.Location = new System.Drawing.Point( 140, 19 ); + this.locate1Button.Name = "locate1Button"; + this.locate1Button.Size = new System.Drawing.Size( 75, 23 ); + this.locate1Button.TabIndex = 2; + this.locate1Button.Tag = "0"; + this.locate1Button.Text = "Locate &1st"; + this.locate1Button.UseVisualStyleBackColor = true; + this.locate1Button.Click += new System.EventHandler( this.locatePointButton_Click ); + // + // imagePoint1Box + // + this.imagePoint1Box.Location = new System.Drawing.Point( 55, 20 ); + this.imagePoint1Box.Name = "imagePoint1Box"; + this.imagePoint1Box.ReadOnly = true; + this.imagePoint1Box.Size = new System.Drawing.Size( 75, 20 ); + this.imagePoint1Box.TabIndex = 1; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point( 10, 23 ); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size( 43, 13 ); + this.label1.TabIndex = 0; + this.label1.Text = "Point 1:"; + // + // statusStrip + // + this.statusStrip.Items.AddRange( new System.Windows.Forms.ToolStripItem[] { + this.statusLabel, + this.estimationLabel, + this.imageSizeLabel} ); + this.statusStrip.Location = new System.Drawing.Point( 0, 644 ); + this.statusStrip.Name = "statusStrip"; + this.statusStrip.Size = new System.Drawing.Size( 974, 22 ); + this.statusStrip.TabIndex = 3; + // + // statusLabel + // + this.statusLabel.AutoSize = false; + this.statusLabel.BorderSides = ( (System.Windows.Forms.ToolStripStatusLabelBorderSides) ( ( ( ( System.Windows.Forms.ToolStripStatusLabelBorderSides.Left | System.Windows.Forms.ToolStripStatusLabelBorderSides.Top ) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Right ) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Bottom ) ) ); + this.statusLabel.BorderStyle = System.Windows.Forms.Border3DStyle.SunkenInner; + this.statusLabel.Name = "statusLabel"; + this.statusLabel.Size = new System.Drawing.Size( 300, 17 ); + this.statusLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // estimationLabel + // + this.estimationLabel.AutoSize = false; + this.estimationLabel.BorderSides = ( (System.Windows.Forms.ToolStripStatusLabelBorderSides) ( ( ( ( System.Windows.Forms.ToolStripStatusLabelBorderSides.Left | System.Windows.Forms.ToolStripStatusLabelBorderSides.Top ) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Right ) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Bottom ) ) ); + this.estimationLabel.BorderStyle = System.Windows.Forms.Border3DStyle.SunkenInner; + this.estimationLabel.Name = "estimationLabel"; + this.estimationLabel.Size = new System.Drawing.Size( 539, 17 ); + this.estimationLabel.Spring = true; + this.estimationLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // imageSizeLabel + // + this.imageSizeLabel.AutoSize = false; + this.imageSizeLabel.BorderSides = ( (System.Windows.Forms.ToolStripStatusLabelBorderSides) ( ( ( ( System.Windows.Forms.ToolStripStatusLabelBorderSides.Left | System.Windows.Forms.ToolStripStatusLabelBorderSides.Top ) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Right ) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Bottom ) ) ); + this.imageSizeLabel.BorderStyle = System.Windows.Forms.Border3DStyle.SunkenInner; + this.imageSizeLabel.Name = "imageSizeLabel"; + this.imageSizeLabel.Size = new System.Drawing.Size( 120, 17 ); + this.imageSizeLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // errorProvider + // + this.errorProvider.ContainerControl = this; + // + // toolTip + // + this.toolTip.AutoPopDelay = 5000; + this.toolTip.InitialDelay = 100; + this.toolTip.ReshowDelay = 100; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 13F ); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size( 974, 666 ); + this.Controls.Add( this.statusStrip ); + this.Controls.Add( this.panel1 ); + this.Controls.Add( this.mainPanel ); + this.Controls.Add( this.mainMenu ); + this.MainMenuStrip = this.mainMenu; + this.Name = "MainForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Pose Estimation"; + this.Resize += new System.EventHandler( this.MainForm_Resize ); + this.mainPanel.ResumeLayout( false ); + this.groupBox1.ResumeLayout( false ); + this.groupBox1.PerformLayout( ); + ( (System.ComponentModel.ISupportInitialize) ( this.pictureBox ) ).EndInit( ); + this.mainMenu.ResumeLayout( false ); + this.mainMenu.PerformLayout( ); + this.panel1.ResumeLayout( false ); + this.poseGroupBox.ResumeLayout( false ); + this.poseGroupBox.PerformLayout( ); + this.modelPointsGroupBox.ResumeLayout( false ); + this.modelPointsGroupBox.PerformLayout( ); + this.imagePointsGroupBox.ResumeLayout( false ); + this.imagePointsGroupBox.PerformLayout( ); + this.statusStrip.ResumeLayout( false ); + this.statusStrip.PerformLayout( ); + ( (System.ComponentModel.ISupportInitialize) ( this.errorProvider ) ).EndInit( ); + this.ResumeLayout( false ); + this.PerformLayout( ); + + } + + #endregion + + private System.Windows.Forms.Panel mainPanel; + private System.Windows.Forms.PictureBox pictureBox; + private System.Windows.Forms.MenuStrip mainMenu; + private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem openImageToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1; + private System.Windows.Forms.OpenFileDialog openFileDialog; + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.GroupBox imagePointsGroupBox; + private System.Windows.Forms.Button locate1Button; + private System.Windows.Forms.TextBox imagePoint1Box; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.StatusStrip statusStrip; + private System.Windows.Forms.ToolStripStatusLabel statusLabel; + private System.Windows.Forms.Button locate4Button; + private System.Windows.Forms.TextBox imagePoint4Box; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Button locate3Button; + private System.Windows.Forms.TextBox imagePoint3Box; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Button locate2Button; + private System.Windows.Forms.TextBox imagePoint2Box; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.ToolStripStatusLabel imageSizeLabel; + private System.Windows.Forms.GroupBox modelPointsGroupBox; + private System.Windows.Forms.TextBox modelPoint1xBox; + private System.Windows.Forms.Label modelPoint4Label; + private System.Windows.Forms.Label modelPoint1Label; + private System.Windows.Forms.Label modelPoint3Label; + private System.Windows.Forms.Label modelPoint2Label; + private System.Windows.Forms.TextBox modelPoint4zBox; + private System.Windows.Forms.TextBox modelPoint4yBox; + private System.Windows.Forms.TextBox modelPoint4xBox; + private System.Windows.Forms.TextBox modelPoint3zBox; + private System.Windows.Forms.TextBox modelPoint3yBox; + private System.Windows.Forms.TextBox modelPoint3xBox; + private System.Windows.Forms.TextBox modelPoint2zBox; + private System.Windows.Forms.TextBox modelPoint2yBox; + private System.Windows.Forms.TextBox modelPoint2xBox; + private System.Windows.Forms.TextBox modelPoint1zBox; + private System.Windows.Forms.TextBox modelPoint1yBox; + private System.Windows.Forms.ErrorProvider errorProvider; + private System.Windows.Forms.GroupBox poseGroupBox; + private System.Windows.Forms.Button estimatePostButton; + private System.Windows.Forms.Label imagePoint1ColorLabel; + private System.Windows.Forms.Label imagePoint4ColorLabel; + private System.Windows.Forms.Label imagePoint3ColorLabel; + private System.Windows.Forms.Label imagePoint2ColorLabel; + private System.Windows.Forms.RadioButton copositRadio; + private System.Windows.Forms.RadioButton positRadio; + private System.Windows.Forms.TextBox focalLengthBox; + private System.Windows.Forms.Label focalLengthLabel; + private MatrixControl estimatedTransformationMatrixControl; + private System.Windows.Forms.ToolStripMenuItem openSample1ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem openSample2ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem openSample3ToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripMenuItem2; + private System.Windows.Forms.ToolStripMenuItem openSample4ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem openSample5ToolStripMenuItem; + private System.Windows.Forms.ToolStripStatusLabel estimationLabel; + private System.Windows.Forms.Button alternatePoseButton; + private System.Windows.Forms.Button bestPoseButton; + private System.Windows.Forms.ToolTip toolTip; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Label label6; + } +} + diff --git a/Samples/Imaging/Pose Estimation (POSIT)/MainForm.cs b/Samples/Imaging/Pose Estimation (POSIT)/MainForm.cs new file mode 100644 index 0000000000..6190a2253 --- /dev/null +++ b/Samples/Imaging/Pose Estimation (POSIT)/MainForm.cs @@ -0,0 +1,701 @@ +// 3D Pose Estimation (2) sample application +// AForge.NET Framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2009-2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Text; +using System.Windows.Forms; +using System.Globalization; +using System.Reflection; + +using AForge; +using AForge.Math; +using AForge.Math.Geometry; + +namespace SampleApp +{ + public partial class MainForm : Form + { + private readonly AForge.Point emptyPoint = new AForge.Point(-30000, -30000); + + // image point of the object to estimate pose for + private AForge.Point[] imagePoints = new AForge.Point[4]; + // model points + private Vector3[] modelPoints = new Vector3[4]; + // camera's focal length + private float focalLength; + // estimated transformation + private Matrix3x3 rotationMatrix, bestRotationMatrix, alternateRotationMatrix; + private Vector3 translationVector, bestTranslationVector, alternateTranslationVector; + private bool isPoseEstimated = false; + private float modelRadius; + + // size of the opened image + private Size imageSize = new Size(0, 0); + + // colors used to highlight points on image + private Color[] pointsColors = new Color[4] + { + Color.Yellow, Color.Blue, Color.Red, Color.Lime + }; + + private bool useCoplanarPosit = false; + + // point index currently locating with mouse + private int pointIndexToLocate = -1; + private AForge.Point pointPreviousValue; + + // model used to draw coordinate system's axes + private Vector3[] axesModel = new Vector3[] + { + new Vector3( 0, 0, 0 ), + new Vector3( 1, 0, 0 ), + new Vector3( 0, 1, 0 ), + new Vector3( 0, 0, 1 ), + }; + + // a structure describing built-in sample + private struct Sample + { + public readonly string ImageName; + public readonly AForge.Point[] ImagePoints; + public readonly Vector3[] ModelPoints; + public readonly float FocalLength; + public readonly bool IsCoplanar; + + public Sample(string imageName, AForge.Point[] imagePoints, Vector3[] modelPoints, float focalLength, bool isCoplanar) + { + ImageName = imageName; + ImagePoints = imagePoints; + ModelPoints = modelPoints; + FocalLength = focalLength; + IsCoplanar = isCoplanar; + } + } + + #region Embedded samples + private Sample[] samples = new Sample[] + { + // ----- + new Sample( + "sample1.jpg", + new AForge.Point[] + { + new AForge.Point( -4, 29 ), + new AForge.Point( -180, 86 ), + new AForge.Point( -5, -102 ), + new AForge.Point( 76, 137 ), + }, + new Vector3[] + { + new Vector3( 28, 28, -28 ), + new Vector3( -28, 28, -28 ), + new Vector3( 28, -28, -28 ), + new Vector3( 28, 28, 28 ), + }, + 640, false ), + + // ----- + new Sample( + "sample2.jpg", + new AForge.Point[] + { + new AForge.Point( -11, 58 ), + new AForge.Point( -125, 84 ), + new AForge.Point( -7, -35 ), + new AForge.Point( 37, 124 ), + }, + new Vector3[] + { + new Vector3( 28, 28, -28 ), + new Vector3( -28, 28, -28 ), + new Vector3( 28, -28, -28 ), + new Vector3( 28, 28, 28 ), + }, + 640, false ), + + // ----- + new Sample( + "sample3.jpg", + new AForge.Point[] + { + new AForge.Point( 4, 55 ), + new AForge.Point( -80, 81 ), + new AForge.Point( 3, -8 ), + new AForge.Point( 40, 109 ), + }, + new Vector3[] + { + new Vector3( 28, 28, -28 ), + new Vector3( -28, 28, -28 ), + new Vector3( 28, -28, -28 ), + new Vector3( 28, 28, 28 ), + }, + 640, false ), + + // ----- + new Sample( + "sample4.jpg", + new AForge.Point[] + { + new AForge.Point( -77, 48 ), + new AForge.Point( 44, 66 ), + new AForge.Point( 75, -36 ), + new AForge.Point( -61, -58 ), + }, + new Vector3[] + { + new Vector3( -56.5f, 0, 56.5f ), + new Vector3( 56.5f, 0, 56.5f ), + new Vector3( 56.5f, 0, -56.5f ), + new Vector3( -56.5f, 0, -56.5f ), + }, + 640, true ), + + // ----- + new Sample( + "sample5.jpg", + new AForge.Point[] + { + new AForge.Point( -117, 33 ), + new AForge.Point( -15, 86 ), + new AForge.Point( 89, 38 ), + new AForge.Point( -13, -30 ), + }, + new Vector3[] + { + new Vector3( -56.5f, 0, 56.5f ), + new Vector3( 56.5f, 0, 56.5f ), + new Vector3( 56.5f, 0, -56.5f ), + new Vector3( -56.5f, 0, -56.5f ), + }, + 640, true ), + }; + #endregion + + // Class constructor + public MainForm() + { + InitializeComponent(); + EnableControls(false); + UpdatePictureBoxPositon(); + + imagePoint1ColorLabel.BackColor = pointsColors[0]; + imagePoint2ColorLabel.BackColor = pointsColors[1]; + imagePoint3ColorLabel.BackColor = pointsColors[2]; + imagePoint4ColorLabel.BackColor = pointsColors[3]; + + if (useCoplanarPosit) + { + copositRadio.Checked = true; + } + else + { + positRadio.Checked = true; + } + + imagePoints[0] = emptyPoint; + imagePoints[1] = emptyPoint; + imagePoints[2] = emptyPoint; + imagePoints[3] = emptyPoint; + + ClearEstimation(); + } + + // On File->Exit - close the application + private void exitToolStripMenuItem_Click(object sender, EventArgs e) + { + this.Close(); + } + + // On File->Open - open an image file + private void openImageToolStripMenuItem_Click(object sender, EventArgs e) + { + if (openFileDialog.ShowDialog() == DialogResult.OK) + { + try + { + OpenImage((Bitmap)Bitmap.FromFile(openFileDialog.FileName)); + + // reset image points + imagePoints[0] = emptyPoint; + imagePoints[1] = emptyPoint; + imagePoints[2] = emptyPoint; + imagePoints[3] = emptyPoint; + + imagePoint1Box.Text = + imagePoint2Box.Text = + imagePoint3Box.Text = + imagePoint4Box.Text = string.Empty; + + // clear current pose estimation + ClearEstimation(); + + // set default focal length to image width + focalLength = imageSize.Width; + focalLengthBox.Text = focalLength.ToString(CultureInfo.InvariantCulture); + } + catch (Exception ex) + { + MessageBox.Show("Failed opening selected file.\n\nException: " + ex.Message); + } + } + } + + // Open one of the embedded samples + private void openSampleToolStripMenuItem_Click(object sender, EventArgs e) + { + ToolStripMenuItem menuItem = (ToolStripMenuItem)sender; + int sampleIndex = int.Parse((string)menuItem.Tag); + + Sample sample = samples[sampleIndex]; + + OpenEmbeddedImage(sample.ImageName); + + // set image points + imagePoints = (AForge.Point[])sample.ImagePoints.Clone(); + + imagePoint1Box.Text = imagePoints[0].ToString(); + imagePoint2Box.Text = imagePoints[1].ToString(); + imagePoint3Box.Text = imagePoints[2].ToString(); + imagePoint4Box.Text = imagePoints[3].ToString(); + + // set model points + modelPoints = (Vector3[])sample.ModelPoints.Clone(); + + modelPoint1xBox.Text = modelPoints[0].X.ToString(); + modelPoint1yBox.Text = modelPoints[0].Y.ToString(); + modelPoint1zBox.Text = modelPoints[0].Z.ToString(); + + modelPoint2xBox.Text = modelPoints[1].X.ToString(); + modelPoint2yBox.Text = modelPoints[1].Y.ToString(); + modelPoint2zBox.Text = modelPoints[1].Z.ToString(); + + modelPoint3xBox.Text = modelPoints[2].X.ToString(); + modelPoint3yBox.Text = modelPoints[2].Y.ToString(); + modelPoint3zBox.Text = modelPoints[2].Z.ToString(); + + modelPoint4xBox.Text = modelPoints[3].X.ToString(); + modelPoint4yBox.Text = modelPoints[3].Y.ToString(); + modelPoint4zBox.Text = modelPoints[3].Z.ToString(); + + // set focal length + focalLength = sample.FocalLength; + focalLengthBox.Text = focalLength.ToString(); + + // POSIT or Coplanar POSIT + useCoplanarPosit = sample.IsCoplanar; + if (useCoplanarPosit) + { + copositRadio.Checked = true; + } + else + { + positRadio.Checked = true; + } + + errorProvider.Clear(); + + EstimatePose(); + } + + // Enable/disable controls which are available when image is opened + private void EnableControls(bool enable) + { + imagePointsGroupBox.Enabled = enable; + modelPointsGroupBox.Enabled = enable; + poseGroupBox.Enabled = enable; + } + + // Close current image + private void CloseImage() + { + pictureBox.Image = null; + EnableControls(false); + } + + // Open image which is embedded into the assembly as resource + private void OpenEmbeddedImage(string imageName) + { + // load arrow bitmap + Assembly assembly = this.GetType().Assembly; + Bitmap image = new Bitmap(assembly.GetManifestResourceStream("SampleApp.Samples." + imageName)); + OpenImage(image); + } + + // Opens the specified image + private void OpenImage(Bitmap image) + { + // close previous image if any + CloseImage(); + + // open new image + imageSize = image.Size; + + pictureBox.Image = image; + pictureBox.Size = new Size(imageSize.Width + 2, imageSize.Height + 2); + imageSizeLabel.Text = string.Format("{0} x {1}", image.Width, image.Height); + + ClearEstimation(); + UpdatePictureBoxPositon(); + EnableControls(true); + } + + private void ClearEstimation() + { + isPoseEstimated = false; + estimatedTransformationMatrixControl.Clear(); + bestPoseButton.Visible = false; + alternatePoseButton.Visible = false; + } + + // Paint image points on the image + private void pictureBox_Paint(object sender, PaintEventArgs e) + { + Graphics g = e.Graphics; + + if (pictureBox.Image != null) + { + int cx = imageSize.Width / 2; + int cy = imageSize.Height / 2; + + for (int i = 0; i < 4; i++) + { + if (imagePoints[i] != emptyPoint) + { + using (Brush brush = new SolidBrush(pointsColors[i])) + { + g.FillEllipse(brush, new Rectangle( + (int)(cx + imagePoints[i].X - 3), + (int)(cy - imagePoints[i].Y - 3), + 7, 7)); + } + } + } + + if ((isPoseEstimated) && (pointIndexToLocate == -1)) + { + AForge.Point[] projectedAxes = PerformProjection(axesModel, + // create tranformation matrix + Matrix4x4.CreateTranslation(translationVector) * // 3: translate + Matrix4x4.CreateFromRotation(rotationMatrix) * // 2: rotate + Matrix4x4.CreateDiagonal( + new Vector4(modelRadius, modelRadius, modelRadius, 1)), // 1: scale + imageSize.Width + ); + + using (Pen pen = new Pen(Color.Blue, 5)) + { + g.DrawLine(pen, + cx + projectedAxes[0].X, cy - projectedAxes[0].Y, + cx + projectedAxes[1].X, cy - projectedAxes[1].Y); + } + + using (Pen pen = new Pen(Color.Red, 5)) + { + g.DrawLine(pen, + cx + projectedAxes[0].X, cy - projectedAxes[0].Y, + cx + projectedAxes[2].X, cy - projectedAxes[2].Y); + } + + using (Pen pen = new Pen(Color.Lime, 5)) + { + g.DrawLine(pen, + cx + projectedAxes[0].X, cy - projectedAxes[0].Y, + cx + projectedAxes[3].X, cy - projectedAxes[3].Y); + } + } + } + } + + private AForge.Point[] PerformProjection(Vector3[] model, Matrix4x4 transformationMatrix, int viewSize) + { + AForge.Point[] projectedPoints = new AForge.Point[model.Length]; + + for (int i = 0; i < model.Length; i++) + { + Vector3 scenePoint = (transformationMatrix * model[i].ToVector4()).ToVector3(); + + projectedPoints[i] = new AForge.Point( + (int)(scenePoint.X / scenePoint.Z * viewSize), + (int)(scenePoint.Y / scenePoint.Z * viewSize)); + } + + return projectedPoints; + } + + // Update position of picture box so it is centered in the main panel + private void UpdatePictureBoxPositon() + { + pictureBox.Location = new System.Drawing.Point( + (mainPanel.Width - pictureBox.Width) / 2, + (mainPanel.Height - pictureBox.Height) / 2); + } + + // On resize of main form + private void MainForm_Resize(object sender, EventArgs e) + { + UpdatePictureBoxPositon(); + } + + // One of the locate point button were clicked + private void locatePointButton_Click(object sender, EventArgs e) + { + pictureBox.Capture = true; + + Button sourceButton = (Button)sender; + pointIndexToLocate = int.Parse((string)sourceButton.Tag); + + pointPreviousValue = imagePoints[pointIndexToLocate]; + imagePoints[pointIndexToLocate] = emptyPoint; + + statusLabel.Text = string.Format("Locate point #{0} in the image ...", pointIndexToLocate + 1); + pictureBox.Invalidate(); + } + + // Mouse click on the image - accept new point or reject it (depending on mouse button) + private void pictureBox_MouseClick(object sender, MouseEventArgs e) + { + if (pointIndexToLocate != -1) + { + pictureBox.Cursor = Cursors.Default; + pictureBox.Capture = false; + statusLabel.Text = string.Empty; + + if (e.Button == MouseButtons.Left) + { + int x = Math.Max(0, Math.Min(e.X, imageSize.Width - 1)); + int y = Math.Max(0, Math.Min(e.Y, imageSize.Height - 1)); + + imagePoints[pointIndexToLocate] = new AForge.Point(x - imageSize.Width / 2, imageSize.Height / 2 - y); + + TextBox imagePointTextBox = (TextBox)imagePointsGroupBox.Controls[string.Format("imagePoint{0}Box", pointIndexToLocate + 1)]; + imagePointTextBox.Text = imagePoints[pointIndexToLocate].ToString(); + } + else + { + imagePoints[pointIndexToLocate] = pointPreviousValue; + } + + ClearEstimation(); + + pointIndexToLocate = -1; + pictureBox.Invalidate(); + } + } + + private void pictureBox_MouseMove(object sender, MouseEventArgs e) + { + if (pointIndexToLocate != -1) + { + pictureBox.Cursor = Cursors.Help; + } + } + + // Leaving one of the model point's boxes - validate it + private void modelPointBox_Leave(object sender, EventArgs e) + { + GetCoordinateValue((TextBox)sender); + } + + private void GetCoordinateValue(TextBox textBox) + { + int tag = int.Parse((string)textBox.Tag); + int pointIndex = tag / 10; + int coordinateIndex = tag % 10; + float coordinateValue, oldValue = 0; + + textBox.Text = textBox.Text.Trim(); + + // try parsing the coordinate value + if (float.TryParse(textBox.Text, NumberStyles.Float, CultureInfo.InvariantCulture, out coordinateValue)) + { + switch (coordinateIndex) + { + case 0: + oldValue = modelPoints[pointIndex].X; + modelPoints[pointIndex].X = coordinateValue; + break; + case 1: + oldValue = modelPoints[pointIndex].Y; + modelPoints[pointIndex].Y = coordinateValue; + break; + case 2: + oldValue = modelPoints[pointIndex].Z; + modelPoints[pointIndex].Z = coordinateValue; + break; + } + errorProvider.Clear(); + + if (oldValue != coordinateValue) + { + ClearEstimation(); + } + } + else + { + Label pointLabel = (Label)modelPointsGroupBox.Controls[string.Format("modelPoint{0}Label", pointIndex + 1)]; + + errorProvider.SetError(pointLabel, string.Format("Failed parsing {0} coordinate", + (coordinateIndex == 0) ? "X" : ((coordinateIndex == 1) ? "Y" : "Z"))); + + textBox.Text = string.Empty; + } + } + + // Validate focal length on leaving the text box + private void focalLengthBox_Leave(object sender, EventArgs e) + { + float value; + + if (float.TryParse(focalLengthBox.Text, NumberStyles.Float, CultureInfo.InvariantCulture, out value)) + { + focalLength = value; + } + else + { + focalLengthBox.Text = focalLength.ToString(); + errorProvider.SetError(focalLengthLabel, "Wrong focal length was specified. Restored to previous value."); + } + } + + // Switch between POSIT and CoPOSIT algorithms + private void copositRadio_CheckedChanged(object sender, EventArgs e) + { + useCoplanarPosit = copositRadio.Checked; + } + + private void estimatePostButton_Click(object sender, EventArgs e) + { + EstimatePose(); + } + + // Estimate 3D position + private void EstimatePose() + { + try + { + // check if all image coordinates are specified + if ((string.IsNullOrEmpty(imagePoint1Box.Text)) || + (string.IsNullOrEmpty(imagePoint2Box.Text)) || + (string.IsNullOrEmpty(imagePoint3Box.Text)) || + (string.IsNullOrEmpty(imagePoint4Box.Text))) + { + throw new ApplicationException("Some image coordinates are not specified."); + } + + // check if all model coordnates are specified + if ((string.IsNullOrEmpty(modelPoint1xBox.Text)) || + (string.IsNullOrEmpty(modelPoint2xBox.Text)) || + (string.IsNullOrEmpty(modelPoint3xBox.Text)) || + (string.IsNullOrEmpty(modelPoint4xBox.Text)) || + (string.IsNullOrEmpty(modelPoint1yBox.Text)) || + (string.IsNullOrEmpty(modelPoint2yBox.Text)) || + (string.IsNullOrEmpty(modelPoint3yBox.Text)) || + (string.IsNullOrEmpty(modelPoint4yBox.Text)) || + ((!useCoplanarPosit) && ( + (string.IsNullOrEmpty(modelPoint1zBox.Text)) || + (string.IsNullOrEmpty(modelPoint2zBox.Text)) || + (string.IsNullOrEmpty(modelPoint3zBox.Text)) || + (string.IsNullOrEmpty(modelPoint4zBox.Text))))) + { + throw new ApplicationException("Some model coordinates are not specified."); + } + + // calculate model's center + Vector3 modelCenter = new Vector3( + (modelPoints[0].X + modelPoints[1].X + modelPoints[2].X + modelPoints[3].X) / 4, + (modelPoints[0].Y + modelPoints[1].Y + modelPoints[2].Y + modelPoints[3].Y) / 4, + (modelPoints[0].Z + modelPoints[1].Z + modelPoints[2].Z + modelPoints[3].Z) / 4 + ); + + // calculate ~ model's radius + modelRadius = 0; + foreach (Vector3 modelPoint in modelPoints) + { + float distanceToCenter = (modelPoint - modelCenter).Norm; + if (distanceToCenter > modelRadius) + { + modelRadius = distanceToCenter; + } + } + + if (!useCoplanarPosit) + { + Posit posit = new Posit(modelPoints, focalLength); + posit.EstimatePose(imagePoints, out rotationMatrix, out translationVector); + + bestPoseButton.Visible = alternatePoseButton.Visible = false; + } + else + { + CoplanarPosit coposit = new CoplanarPosit(modelPoints, focalLength); + coposit.EstimatePose(imagePoints, out rotationMatrix, out translationVector); + + bestRotationMatrix = coposit.BestEstimatedRotation; + bestTranslationVector = coposit.BestEstimatedTranslation; + + alternateRotationMatrix = coposit.AlternateEstimatedRotation; + alternateTranslationVector = coposit.AlternateEstimatedTranslation; + + bestPoseButton.Visible = alternatePoseButton.Visible = true; + } + + isPoseEstimated = true; + UpdateEstimationInformation(); + pictureBox.Invalidate(); + } + catch (ApplicationException ex) + { + MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void UpdateEstimationInformation() + { + estimatedTransformationMatrixControl.SetMatrix( + Matrix4x4.CreateTranslation(translationVector) * + Matrix4x4.CreateFromRotation(rotationMatrix)); + + float estimatedYaw; + float estimatedPitch; + float estimatedRoll; + + rotationMatrix.ExtractYawPitchRoll(out estimatedYaw, out estimatedPitch, out estimatedRoll); + + estimatedYaw *= (float)(180.0 / Math.PI); + estimatedPitch *= (float)(180.0 / Math.PI); + estimatedRoll *= (float)(180.0 / Math.PI); + + estimationLabel.Text = string.Format("Rotation: (yaw(y)={0}, pitch(x)={1}, roll(z)={2})", + estimatedYaw, estimatedPitch, estimatedRoll); + } + + // Select best pose estimation + private void bestPoseButton_Click(object sender, EventArgs e) + { + rotationMatrix = bestRotationMatrix; + translationVector = bestTranslationVector; + + UpdateEstimationInformation(); + pictureBox.Invalidate(); + } + + // Select alternate pose estimation + private void alternatePoseButton_Click(object sender, EventArgs e) + { + rotationMatrix = alternateRotationMatrix; + translationVector = alternateTranslationVector; + + UpdateEstimationInformation(); + pictureBox.Invalidate(); + } + } +} diff --git a/Samples/Imaging/Pose Estimation (POSIT)/MainForm.resx b/Samples/Imaging/Pose Estimation (POSIT)/MainForm.resx new file mode 100644 index 0000000000..f141aba4f --- /dev/null +++ b/Samples/Imaging/Pose Estimation (POSIT)/MainForm.resx @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 127, 17 + + + 483, 17 + + + 251, 17 + + + 360, 17 + + \ No newline at end of file diff --git a/Samples/Imaging/Pose Estimation (POSIT)/MatrixControl.Designer.cs b/Samples/Imaging/Pose Estimation (POSIT)/MatrixControl.Designer.cs new file mode 100644 index 0000000000..5ef81fd17 --- /dev/null +++ b/Samples/Imaging/Pose Estimation (POSIT)/MatrixControl.Designer.cs @@ -0,0 +1,238 @@ +namespace SampleApp +{ + partial class MatrixControl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.groupBox = new System.Windows.Forms.GroupBox( ); + this.i3_j3_Box = new System.Windows.Forms.TextBox( ); + this.i3_j2_Box = new System.Windows.Forms.TextBox( ); + this.i3_j1_Box = new System.Windows.Forms.TextBox( ); + this.i3_j0_Box = new System.Windows.Forms.TextBox( ); + this.i2_j3_Box = new System.Windows.Forms.TextBox( ); + this.i2_j2_Box = new System.Windows.Forms.TextBox( ); + this.i2_j1_Box = new System.Windows.Forms.TextBox( ); + this.i2_j0_Box = new System.Windows.Forms.TextBox( ); + this.i1_j3_Box = new System.Windows.Forms.TextBox( ); + this.i1_j2_Box = new System.Windows.Forms.TextBox( ); + this.i1_j1_Box = new System.Windows.Forms.TextBox( ); + this.i1_j0_Box = new System.Windows.Forms.TextBox( ); + this.i0_j3_Box = new System.Windows.Forms.TextBox( ); + this.i0_j2_Box = new System.Windows.Forms.TextBox( ); + this.i0_j1_Box = new System.Windows.Forms.TextBox( ); + this.i0_j0_Box = new System.Windows.Forms.TextBox( ); + this.groupBox.SuspendLayout( ); + this.SuspendLayout( ); + // + // groupBox + // + this.groupBox.Controls.Add( this.i3_j3_Box ); + this.groupBox.Controls.Add( this.i3_j2_Box ); + this.groupBox.Controls.Add( this.i3_j1_Box ); + this.groupBox.Controls.Add( this.i3_j0_Box ); + this.groupBox.Controls.Add( this.i2_j3_Box ); + this.groupBox.Controls.Add( this.i2_j2_Box ); + this.groupBox.Controls.Add( this.i2_j1_Box ); + this.groupBox.Controls.Add( this.i2_j0_Box ); + this.groupBox.Controls.Add( this.i1_j3_Box ); + this.groupBox.Controls.Add( this.i1_j2_Box ); + this.groupBox.Controls.Add( this.i1_j1_Box ); + this.groupBox.Controls.Add( this.i1_j0_Box ); + this.groupBox.Controls.Add( this.i0_j3_Box ); + this.groupBox.Controls.Add( this.i0_j2_Box ); + this.groupBox.Controls.Add( this.i0_j1_Box ); + this.groupBox.Controls.Add( this.i0_j0_Box ); + this.groupBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.groupBox.Location = new System.Drawing.Point( 0, 0 ); + this.groupBox.Name = "groupBox"; + this.groupBox.Size = new System.Drawing.Size( 230, 110 ); + this.groupBox.TabIndex = 0; + this.groupBox.TabStop = false; + // + // i3_j3_Box + // + this.i3_j3_Box.Location = new System.Drawing.Point( 160, 80 ); + this.i3_j3_Box.Name = "i3_j3_Box"; + this.i3_j3_Box.ReadOnly = true; + this.i3_j3_Box.Size = new System.Drawing.Size( 50, 20 ); + this.i3_j3_Box.TabIndex = 15; + // + // i3_j2_Box + // + this.i3_j2_Box.Location = new System.Drawing.Point( 110, 80 ); + this.i3_j2_Box.Name = "i3_j2_Box"; + this.i3_j2_Box.ReadOnly = true; + this.i3_j2_Box.Size = new System.Drawing.Size( 50, 20 ); + this.i3_j2_Box.TabIndex = 14; + // + // i3_j1_Box + // + this.i3_j1_Box.Location = new System.Drawing.Point( 60, 80 ); + this.i3_j1_Box.Name = "i3_j1_Box"; + this.i3_j1_Box.ReadOnly = true; + this.i3_j1_Box.Size = new System.Drawing.Size( 50, 20 ); + this.i3_j1_Box.TabIndex = 13; + // + // i3_j0_Box + // + this.i3_j0_Box.Location = new System.Drawing.Point( 10, 80 ); + this.i3_j0_Box.Name = "i3_j0_Box"; + this.i3_j0_Box.ReadOnly = true; + this.i3_j0_Box.Size = new System.Drawing.Size( 50, 20 ); + this.i3_j0_Box.TabIndex = 12; + // + // i2_j3_Box + // + this.i2_j3_Box.Location = new System.Drawing.Point( 160, 60 ); + this.i2_j3_Box.Name = "i2_j3_Box"; + this.i2_j3_Box.ReadOnly = true; + this.i2_j3_Box.Size = new System.Drawing.Size( 50, 20 ); + this.i2_j3_Box.TabIndex = 11; + // + // i2_j2_Box + // + this.i2_j2_Box.Location = new System.Drawing.Point( 110, 60 ); + this.i2_j2_Box.Name = "i2_j2_Box"; + this.i2_j2_Box.ReadOnly = true; + this.i2_j2_Box.Size = new System.Drawing.Size( 50, 20 ); + this.i2_j2_Box.TabIndex = 10; + // + // i2_j1_Box + // + this.i2_j1_Box.Location = new System.Drawing.Point( 60, 60 ); + this.i2_j1_Box.Name = "i2_j1_Box"; + this.i2_j1_Box.ReadOnly = true; + this.i2_j1_Box.Size = new System.Drawing.Size( 50, 20 ); + this.i2_j1_Box.TabIndex = 9; + // + // i2_j0_Box + // + this.i2_j0_Box.Location = new System.Drawing.Point( 10, 60 ); + this.i2_j0_Box.Name = "i2_j0_Box"; + this.i2_j0_Box.ReadOnly = true; + this.i2_j0_Box.Size = new System.Drawing.Size( 50, 20 ); + this.i2_j0_Box.TabIndex = 8; + // + // i1_j3_Box + // + this.i1_j3_Box.Location = new System.Drawing.Point( 160, 40 ); + this.i1_j3_Box.Name = "i1_j3_Box"; + this.i1_j3_Box.ReadOnly = true; + this.i1_j3_Box.Size = new System.Drawing.Size( 50, 20 ); + this.i1_j3_Box.TabIndex = 7; + // + // i1_j2_Box + // + this.i1_j2_Box.Location = new System.Drawing.Point( 110, 40 ); + this.i1_j2_Box.Name = "i1_j2_Box"; + this.i1_j2_Box.ReadOnly = true; + this.i1_j2_Box.Size = new System.Drawing.Size( 50, 20 ); + this.i1_j2_Box.TabIndex = 6; + // + // i1_j1_Box + // + this.i1_j1_Box.Location = new System.Drawing.Point( 60, 40 ); + this.i1_j1_Box.Name = "i1_j1_Box"; + this.i1_j1_Box.ReadOnly = true; + this.i1_j1_Box.Size = new System.Drawing.Size( 50, 20 ); + this.i1_j1_Box.TabIndex = 5; + // + // i1_j0_Box + // + this.i1_j0_Box.Location = new System.Drawing.Point( 10, 40 ); + this.i1_j0_Box.Name = "i1_j0_Box"; + this.i1_j0_Box.ReadOnly = true; + this.i1_j0_Box.Size = new System.Drawing.Size( 50, 20 ); + this.i1_j0_Box.TabIndex = 4; + // + // i0_j3_Box + // + this.i0_j3_Box.Location = new System.Drawing.Point( 160, 20 ); + this.i0_j3_Box.Name = "i0_j3_Box"; + this.i0_j3_Box.ReadOnly = true; + this.i0_j3_Box.Size = new System.Drawing.Size( 50, 20 ); + this.i0_j3_Box.TabIndex = 3; + // + // i0_j2_Box + // + this.i0_j2_Box.Location = new System.Drawing.Point( 110, 20 ); + this.i0_j2_Box.Name = "i0_j2_Box"; + this.i0_j2_Box.ReadOnly = true; + this.i0_j2_Box.Size = new System.Drawing.Size( 50, 20 ); + this.i0_j2_Box.TabIndex = 2; + // + // i0_j1_Box + // + this.i0_j1_Box.Location = new System.Drawing.Point( 60, 20 ); + this.i0_j1_Box.Name = "i0_j1_Box"; + this.i0_j1_Box.ReadOnly = true; + this.i0_j1_Box.Size = new System.Drawing.Size( 50, 20 ); + this.i0_j1_Box.TabIndex = 1; + // + // i0_j0_Box + // + this.i0_j0_Box.Location = new System.Drawing.Point( 10, 20 ); + this.i0_j0_Box.Name = "i0_j0_Box"; + this.i0_j0_Box.ReadOnly = true; + this.i0_j0_Box.Size = new System.Drawing.Size( 50, 20 ); + this.i0_j0_Box.TabIndex = 0; + // + // MatrixControl + // + this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 13F ); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add( this.groupBox ); + this.Name = "MatrixControl"; + this.Size = new System.Drawing.Size( 230, 110 ); + this.Load += new System.EventHandler( this.MatrixControl_Load ); + this.groupBox.ResumeLayout( false ); + this.groupBox.PerformLayout( ); + this.ResumeLayout( false ); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox; + private System.Windows.Forms.TextBox i0_j0_Box; + private System.Windows.Forms.TextBox i3_j3_Box; + private System.Windows.Forms.TextBox i3_j2_Box; + private System.Windows.Forms.TextBox i3_j1_Box; + private System.Windows.Forms.TextBox i3_j0_Box; + private System.Windows.Forms.TextBox i2_j3_Box; + private System.Windows.Forms.TextBox i2_j2_Box; + private System.Windows.Forms.TextBox i2_j1_Box; + private System.Windows.Forms.TextBox i2_j0_Box; + private System.Windows.Forms.TextBox i1_j3_Box; + private System.Windows.Forms.TextBox i1_j2_Box; + private System.Windows.Forms.TextBox i1_j1_Box; + private System.Windows.Forms.TextBox i1_j0_Box; + private System.Windows.Forms.TextBox i0_j3_Box; + private System.Windows.Forms.TextBox i0_j2_Box; + private System.Windows.Forms.TextBox i0_j1_Box; + } +} diff --git a/Samples/Imaging/Pose Estimation (POSIT)/MatrixControl.cs b/Samples/Imaging/Pose Estimation (POSIT)/MatrixControl.cs new file mode 100644 index 0000000000..680997468 --- /dev/null +++ b/Samples/Imaging/Pose Estimation (POSIT)/MatrixControl.cs @@ -0,0 +1,87 @@ +// 3D Pose Estimation (2) sample application +// AForge.NET Framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2009-2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +using AForge.Math; + +namespace SampleApp +{ + public partial class MatrixControl : UserControl + { + private Dictionary textBoxes = new Dictionary( ); + + public string Title + { + get { return groupBox.Text; } + set { groupBox.Text = value; } + } + + public MatrixControl( ) + { + InitializeComponent( ); + } + + public void SetMatrix( Matrix4x4 matrix ) + { + float[] array = matrix.ToArray( ); + + for ( int i = 0, k = 0; i < 4; i++ ) + { + for ( int j = 0; j < 4; j++, k++ ) + { + string textBoxName = string.Format( "i{0}_j{1}_Box", i, j ); + + if ( textBoxes.ContainsKey( textBoxName ) ) + { + textBoxes[textBoxName].Text = FormatFloat( array[k] ); + } + } + } + } + + public void Clear( ) + { + for ( int i = 0, k = 0; i < 4; i++ ) + { + for ( int j = 0; j < 4; j++, k++ ) + { + string textBoxName = string.Format( "i{0}_j{1}_Box", i, j ); + + if ( textBoxes.ContainsKey( textBoxName ) ) + { + textBoxes[textBoxName].Text = string.Empty; + } + } + } + } + + private static string FormatFloat( float floatValue ) + { + return String.Format( "{0:0.####}", floatValue ); + } + + private void MatrixControl_Load( object sender, EventArgs e ) + { + textBoxes.Clear( ); + + foreach ( Control c in groupBox.Controls ) + { + if ( c is TextBox ) + { + textBoxes.Add( c.Name, (TextBox) c ); + } + } + } + } +} diff --git a/Samples/Imaging/Pose Estimation (POSIT)/MatrixControl.resx b/Samples/Imaging/Pose Estimation (POSIT)/MatrixControl.resx new file mode 100644 index 0000000000..19dc0dd8b --- /dev/null +++ b/Samples/Imaging/Pose Estimation (POSIT)/MatrixControl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Imaging/Pose Estimation (POSIT)/Pose Estimation (POSIT).csproj b/Samples/Imaging/Pose Estimation (POSIT)/Pose Estimation (POSIT).csproj new file mode 100644 index 0000000000..69b8937aa --- /dev/null +++ b/Samples/Imaging/Pose Estimation (POSIT)/Pose Estimation (POSIT).csproj @@ -0,0 +1,169 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {651EBEC1-045E-4A74-A9F6-7E8DD223DD7A} + WinExe + Properties + SampleApp + Pose Estimation + v4.0 + 512 + + + 3.5 + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + SampleApp.Program + + + + ..\..\..\Release\net40\Accord.dll + + + ..\..\..\Release\net40\Accord.Math.dll + + + + + + + + Form + + + MainForm.cs + + + UserControl + + + MatrixControl.cs + + + + + MainForm.cs + + + MatrixControl.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + + + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + \ No newline at end of file diff --git a/Samples/Imaging/Pose Estimation (POSIT)/Pose Estimation.sln b/Samples/Imaging/Pose Estimation (POSIT)/Pose Estimation.sln new file mode 100644 index 0000000000..61ff9b283 --- /dev/null +++ b/Samples/Imaging/Pose Estimation (POSIT)/Pose Estimation.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C# Express 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pose Estimation", "Pose Estimation.csproj", "{651EBEC1-045E-4A74-A9F6-7E8DD223DD7A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {651EBEC1-045E-4A74-A9F6-7E8DD223DD7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {651EBEC1-045E-4A74-A9F6-7E8DD223DD7A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {651EBEC1-045E-4A74-A9F6-7E8DD223DD7A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {651EBEC1-045E-4A74-A9F6-7E8DD223DD7A}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/Imaging/Pose Estimation (POSIT)/Program.cs b/Samples/Imaging/Pose Estimation (POSIT)/Program.cs new file mode 100644 index 0000000000..f7c4840ea --- /dev/null +++ b/Samples/Imaging/Pose Estimation (POSIT)/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Windows.Forms; + +namespace SampleApp +{ + static class Program + { + [STAThread] + static void Main() + { + if (Environment.OSVersion.Version.Major >= 6) + SetProcessDPIAware(); + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + + [System.Runtime.InteropServices.DllImport("user32.dll")] + private static extern bool SetProcessDPIAware(); + } +} \ No newline at end of file diff --git a/Samples/Imaging/Pose Estimation (POSIT)/Properties/AssemblyInfo.cs b/Samples/Imaging/Pose Estimation (POSIT)/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..f6abb4a15 --- /dev/null +++ b/Samples/Imaging/Pose Estimation (POSIT)/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle( "Pose Estimation" )] +[assembly: AssemblyDescription( "" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "" )] +[assembly: AssemblyProduct( "Pose Estimation" )] +[assembly: AssemblyCopyright( "Copyright © 2011" )] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible( false )] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid( "8d257fdd-192f-4789-a86d-2bd42917c32f" )] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion( "1.0.0.0" )] +[assembly: AssemblyFileVersion( "1.0.0.0" )] diff --git a/Samples/Imaging/Pose Estimation (POSIT)/Properties/Resources.Designer.cs b/Samples/Imaging/Pose Estimation (POSIT)/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..7b58e53ee --- /dev/null +++ b/Samples/Imaging/Pose Estimation (POSIT)/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Samples/Imaging/Pose Estimation (POSIT)/Properties/Resources.resx b/Samples/Imaging/Pose Estimation (POSIT)/Properties/Resources.resx new file mode 100644 index 0000000000..af7dbebba --- /dev/null +++ b/Samples/Imaging/Pose Estimation (POSIT)/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Imaging/Pose Estimation (POSIT)/Properties/Settings.Designer.cs b/Samples/Imaging/Pose Estimation (POSIT)/Properties/Settings.Designer.cs new file mode 100644 index 0000000000..dbc9e5d22 --- /dev/null +++ b/Samples/Imaging/Pose Estimation (POSIT)/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Samples/Imaging/Pose Estimation (POSIT)/Properties/Settings.settings b/Samples/Imaging/Pose Estimation (POSIT)/Properties/Settings.settings new file mode 100644 index 0000000000..39645652a --- /dev/null +++ b/Samples/Imaging/Pose Estimation (POSIT)/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Samples/Imaging/Pose Estimation (POSIT)/Samples/sample1.jpg b/Samples/Imaging/Pose Estimation (POSIT)/Samples/sample1.jpg new file mode 100644 index 0000000000..5fc7ac413 Binary files /dev/null and b/Samples/Imaging/Pose Estimation (POSIT)/Samples/sample1.jpg differ diff --git a/Samples/Imaging/Pose Estimation (POSIT)/Samples/sample2.jpg b/Samples/Imaging/Pose Estimation (POSIT)/Samples/sample2.jpg new file mode 100644 index 0000000000..86c3c5276 Binary files /dev/null and b/Samples/Imaging/Pose Estimation (POSIT)/Samples/sample2.jpg differ diff --git a/Samples/Imaging/Pose Estimation (POSIT)/Samples/sample3.jpg b/Samples/Imaging/Pose Estimation (POSIT)/Samples/sample3.jpg new file mode 100644 index 0000000000..164a95da0 Binary files /dev/null and b/Samples/Imaging/Pose Estimation (POSIT)/Samples/sample3.jpg differ diff --git a/Samples/Imaging/Pose Estimation (POSIT)/Samples/sample4.jpg b/Samples/Imaging/Pose Estimation (POSIT)/Samples/sample4.jpg new file mode 100644 index 0000000000..47e0fb85c Binary files /dev/null and b/Samples/Imaging/Pose Estimation (POSIT)/Samples/sample4.jpg differ diff --git a/Samples/Imaging/Pose Estimation (POSIT)/Samples/sample5.jpg b/Samples/Imaging/Pose Estimation (POSIT)/Samples/sample5.jpg new file mode 100644 index 0000000000..ec98cd076 Binary files /dev/null and b/Samples/Imaging/Pose Estimation (POSIT)/Samples/sample5.jpg differ diff --git a/Samples/Imaging/Pose Estimation (POSIT)/app.config b/Samples/Imaging/Pose Estimation (POSIT)/app.config new file mode 100644 index 0000000000..57c0f2cbc --- /dev/null +++ b/Samples/Imaging/Pose Estimation (POSIT)/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Samples/Imaging/Texture/Accord.dll.config b/Samples/Imaging/Texture/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Imaging/Texture/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Imaging/Texture/MainForm.Designer.cs b/Samples/Imaging/Texture/MainForm.Designer.cs new file mode 100644 index 0000000000..1e6acb8bc --- /dev/null +++ b/Samples/Imaging/Texture/MainForm.Designer.cs @@ -0,0 +1,109 @@ +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.label1 = new System.Windows.Forms.Label( ); + this.texturesCombo = new System.Windows.Forms.ComboBox( ); + this.pictureBox = new System.Windows.Forms.PictureBox( ); + this.regenerateButton = new System.Windows.Forms.Button( ); + ( (System.ComponentModel.ISupportInitialize) ( this.pictureBox ) ).BeginInit( ); + this.SuspendLayout( ); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point( 10, 12 ); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size( 46, 13 ); + this.label1.TabIndex = 0; + this.label1.Text = "&Texture:"; + // + // texturesCombo + // + this.texturesCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.texturesCombo.FormattingEnabled = true; + this.texturesCombo.Items.AddRange( new object[] { + "Clouds", + "Marble", + "Wood", + "Labyrinth", + "Textile"} ); + this.texturesCombo.Location = new System.Drawing.Point( 60, 10 ); + this.texturesCombo.Name = "texturesCombo"; + this.texturesCombo.Size = new System.Drawing.Size( 150, 21 ); + this.texturesCombo.TabIndex = 1; + this.texturesCombo.SelectedIndexChanged += new System.EventHandler( this.texturesCombo_SelectedIndexChanged ); + // + // pictureBox + // + this.pictureBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.pictureBox.Location = new System.Drawing.Point( 10, 40 ); + this.pictureBox.Name = "pictureBox"; + this.pictureBox.Size = new System.Drawing.Size( 300, 300 ); + this.pictureBox.TabIndex = 2; + this.pictureBox.TabStop = false; + // + // regenerateButton + // + this.regenerateButton.Location = new System.Drawing.Point( 235, 10 ); + this.regenerateButton.Name = "regenerateButton"; + this.regenerateButton.Size = new System.Drawing.Size( 75, 23 ); + this.regenerateButton.TabIndex = 3; + this.regenerateButton.Text = "&Regenerate"; + this.regenerateButton.UseVisualStyleBackColor = true; + this.regenerateButton.Click += new System.EventHandler( this.regenerateButton_Click ); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 13F ); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size( 320, 350 ); + this.Controls.Add( this.regenerateButton ); + this.Controls.Add( this.pictureBox ); + this.Controls.Add( this.texturesCombo ); + this.Controls.Add( this.label1 ); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.Name = "MainForm"; + this.Text = "Textures Demo"; + ( (System.ComponentModel.ISupportInitialize) ( this.pictureBox ) ).EndInit( ); + this.ResumeLayout( false ); + this.PerformLayout( ); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.ComboBox texturesCombo; + private System.Windows.Forms.PictureBox pictureBox; + private System.Windows.Forms.Button regenerateButton; + } +} + diff --git a/Samples/Imaging/Texture/MainForm.cs b/Samples/Imaging/Texture/MainForm.cs new file mode 100644 index 0000000000..b56efe3ec --- /dev/null +++ b/Samples/Imaging/Texture/MainForm.cs @@ -0,0 +1,98 @@ +// Textures demo +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Drawing.Imaging; +using System.Text; +using System.Windows.Forms; + +using AForge.Imaging; +using AForge.Imaging.Textures; + +namespace SampleApp +{ + public partial class MainForm : Form + { + ITextureGenerator textureGenerator = null; + + public MainForm( ) + { + InitializeComponent( ); + + // show first texture + texturesCombo.SelectedIndex = 0; + } + + // Texture changed + private void texturesCombo_SelectedIndexChanged( object sender, EventArgs e ) + { + // create texture generator + switch ( texturesCombo.SelectedIndex ) + { + case 0: // clouds + textureGenerator = new CloudsTexture( ); + break; + case 1: // marble + textureGenerator = new MarbleTexture( ); + break; + case 2: // wood + textureGenerator = new WoodTexture( 7 ); + break; + case 3: // labyrinth + textureGenerator = new LabyrinthTexture( ); + break; + case 4: // textile + textureGenerator = new TextileTexture( ); + break; + default: + textureGenerator = null; + break; + } + + // show texture + ShowTexture( ); + } + + // Generate and show texture + private void ShowTexture( ) + { + // check generator + if ( textureGenerator == null ) + { + pictureBox.Image = null; + return; + } + + int width = pictureBox.ClientRectangle.Width; + int height = pictureBox.ClientRectangle.Height; + + // generate texture + float[,] texture = textureGenerator.Generate( width, height ); + + // create bitmap from the texture + Bitmap image = TextureTools.ToBitmap( texture ); + + // show image + pictureBox.Image = image; + } + + // Regenerate texture + private void regenerateButton_Click( object sender, EventArgs e ) + { + if ( textureGenerator != null ) + { + textureGenerator.Reset( ); + ShowTexture( ); + } + } + } +} \ No newline at end of file diff --git a/Samples/Imaging/Texture/MainForm.resx b/Samples/Imaging/Texture/MainForm.resx new file mode 100644 index 0000000000..19dc0dd8b --- /dev/null +++ b/Samples/Imaging/Texture/MainForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Imaging/Texture/Program.cs b/Samples/Imaging/Texture/Program.cs new file mode 100644 index 0000000000..8e8b08bb6 --- /dev/null +++ b/Samples/Imaging/Texture/Program.cs @@ -0,0 +1,30 @@ +// Textures demo +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +using System; +using System.Windows.Forms; + +namespace SampleApp +{ + static class Program + { + [STAThread] + static void Main() + { + if (Environment.OSVersion.Version.Major >= 6) + SetProcessDPIAware(); + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + + [System.Runtime.InteropServices.DllImport("user32.dll")] + private static extern bool SetProcessDPIAware(); + } +} \ No newline at end of file diff --git a/Samples/Imaging/Texture/Properties/AssemblyInfo.cs b/Samples/Imaging/Texture/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..9dfdc2824 --- /dev/null +++ b/Samples/Imaging/Texture/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Imaging Textures Demo")] +[assembly: AssemblyDescription("Imaging Textures Demo sample")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("AForge")] +[assembly: AssemblyProduct("AForge.NET")] +[assembly: AssemblyCopyright("AForge © 2009")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("b03a4989-02d0-4f71-b9a1-673f6635e276")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("2.0.0.0")] +[assembly: AssemblyFileVersion("2.0.0.0")] diff --git a/Samples/Imaging/Texture/Properties/Resources.Designer.cs b/Samples/Imaging/Texture/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..7b58e53ee --- /dev/null +++ b/Samples/Imaging/Texture/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Samples/Imaging/Texture/Properties/Resources.resx b/Samples/Imaging/Texture/Properties/Resources.resx new file mode 100644 index 0000000000..25a61211c --- /dev/null +++ b/Samples/Imaging/Texture/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Imaging/Texture/Properties/Settings.Designer.cs b/Samples/Imaging/Texture/Properties/Settings.Designer.cs new file mode 100644 index 0000000000..dbc9e5d22 --- /dev/null +++ b/Samples/Imaging/Texture/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Samples/Imaging/Texture/Properties/Settings.settings b/Samples/Imaging/Texture/Properties/Settings.settings new file mode 100644 index 0000000000..39645652a --- /dev/null +++ b/Samples/Imaging/Texture/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Samples/Imaging/Texture/Textures.csproj b/Samples/Imaging/Texture/Textures.csproj new file mode 100644 index 0000000000..8f0d38a28 --- /dev/null +++ b/Samples/Imaging/Texture/Textures.csproj @@ -0,0 +1,158 @@ + + + + Debug + AnyCPU + 8.0.50727 + 2.0 + {E34CC841-CE29-4B39-9BE5-D98502330F55} + WinExe + Properties + SampleApp + TexturesDemo + + + 3.5 + v4.0 + + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + true + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + true + + + true + bin\x86\Debug\ + DEBUG;TRACE + true + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + + ..\..\..\Release\net40\Accord.dll + + + ..\..\..\Release\net40\Accord.Imaging.dll + + + ..\..\..\Release\net40\Accord.Math.dll + + + + + + + + + + Form + + + MainForm.cs + + + + + Designer + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + \ No newline at end of file diff --git a/Samples/Imaging/Texture/TexturesDemo.sln b/Samples/Imaging/Texture/TexturesDemo.sln new file mode 100644 index 0000000000..f56e73bf2 --- /dev/null +++ b/Samples/Imaging/Texture/TexturesDemo.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C# Express 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TexturesDemo", "TexturesDemo.csproj", "{E34CC841-CE29-4B39-9BE5-D98502330F55}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E34CC841-CE29-4B39-9BE5-D98502330F55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E34CC841-CE29-4B39-9BE5-D98502330F55}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E34CC841-CE29-4B39-9BE5-D98502330F55}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E34CC841-CE29-4B39-9BE5-D98502330F55}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/Imaging/Texture/app.config b/Samples/Imaging/Texture/app.config new file mode 100644 index 0000000000..57c0f2cbc --- /dev/null +++ b/Samples/Imaging/Texture/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Samples/Imaging/Wavelets/Accord.dll.config b/Samples/Imaging/Wavelets/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Imaging/Wavelets/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Imaging/Wavelets/MainForm.Designer.cs b/Samples/Imaging/Wavelets/MainForm.Designer.cs index be0203f67..5feba30d1 100644 --- a/Samples/Imaging/Wavelets/MainForm.Designer.cs +++ b/Samples/Imaging/Wavelets/MainForm.Designer.cs @@ -1,33 +1,33 @@ -namespace Wavelets -{ - partial class MainForm - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); this.button1 = new System.Windows.Forms.Button(); this.numIterations = new System.Windows.Forms.NumericUpDown(); @@ -140,17 +140,17 @@ private void InitializeComponent() this.ResumeLayout(false); this.PerformLayout(); - } - - #endregion - - private System.Windows.Forms.Button button1; - private System.Windows.Forms.NumericUpDown numIterations; - private System.Windows.Forms.Label label2; - private System.Windows.Forms.Button button2; - private System.Windows.Forms.ComboBox cbWavelet; - private AForge.Controls.PictureBox pictureBox; - private System.Windows.Forms.Button button3; - } -} - + } + + #endregion + + private System.Windows.Forms.Button button1; + private System.Windows.Forms.NumericUpDown numIterations; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.ComboBox cbWavelet; + private AForge.Controls.PictureBox pictureBox; + private System.Windows.Forms.Button button3; + } +} + diff --git a/Samples/Imaging/Wavelets/MainForm.cs b/Samples/Imaging/Wavelets/MainForm.cs index 6e1cf460e..05582706f 100644 --- a/Samples/Imaging/Wavelets/MainForm.cs +++ b/Samples/Imaging/Wavelets/MainForm.cs @@ -36,7 +36,7 @@ using Accord.Imaging.Filters; using Accord.Math.Wavelets; -namespace Wavelets +namespace SampleApp { public partial class MainForm : Form { @@ -50,7 +50,7 @@ public MainForm() cbWavelet.DataSource = new String[] { "Haar", "CDF" }; - lenna = Wavelets.Properties.Resources.lena512; + lenna = Properties.Resources.lena512; // Use 16bpp for enhanced precision lenna = AForge.Imaging.Image.Convert8bppTo16bpp( lenna); diff --git a/Samples/Imaging/Wavelets/Program.cs b/Samples/Imaging/Wavelets/Program.cs index 06f8846f1..316268492 100644 --- a/Samples/Imaging/Wavelets/Program.cs +++ b/Samples/Imaging/Wavelets/Program.cs @@ -1,9 +1,7 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Windows.Forms; -namespace Wavelets +namespace SampleApp { static class Program { diff --git a/Samples/Imaging/Wavelets/Properties/Resources.Designer.cs b/Samples/Imaging/Wavelets/Properties/Resources.Designer.cs index e1d86e6b6..80ca087bc 100644 --- a/Samples/Imaging/Wavelets/Properties/Resources.Designer.cs +++ b/Samples/Imaging/Wavelets/Properties/Resources.Designer.cs @@ -1,70 +1,73 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.239 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Wavelets.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Wavelets.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - internal static System.Drawing.Bitmap lena512 { - get { - object obj = ResourceManager.GetObject("lena512", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap lena512 { + get { + object obj = ResourceManager.GetObject("lena512", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/Samples/Imaging/Wavelets/Properties/Settings.Designer.cs b/Samples/Imaging/Wavelets/Properties/Settings.Designer.cs index e4a5f2f58..dbc9e5d22 100644 --- a/Samples/Imaging/Wavelets/Properties/Settings.Designer.cs +++ b/Samples/Imaging/Wavelets/Properties/Settings.Designer.cs @@ -1,26 +1,26 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.239 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Wavelets.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Samples/Imaging/Wavelets/Wavelets.csproj b/Samples/Imaging/Wavelets/Wavelets.csproj index de378ae03..42e4c3328 100644 --- a/Samples/Imaging/Wavelets/Wavelets.csproj +++ b/Samples/Imaging/Wavelets/Wavelets.csproj @@ -1,158 +1,155 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {4D100C6D-963E-4AE7-AEAF-91040D4F0332} - WinExe - Properties - Wavelets - Wavelets - v4.0 - 512 - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - - true - bin\x86\Debug\ - DEBUG;TRACE - full - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - bin\x86\Release\ - TRACE - true - pdbonly - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - framework.ico - - - - False - ..\..\..\Release\net40\Accord.dll - - - False - ..\..\..\Release\net40\Accord.Imaging.dll - - - False - ..\..\..\Release\net40\Accord.Math.dll - - - ..\..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Controls.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Imaging.dll - - - - 3.5 - - - - - - - - - Form - - - MainForm.cs - - - - - MainForm.cs - Designer - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - - - - + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {4D100C6D-963E-4AE7-AEAF-91040D4F0332} + WinExe + Properties + SampleApp + Wavelets + v4.0 + 512 + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + framework.ico + + + + False + ..\..\..\Release\net40\Accord.dll + + + ..\..\..\Release\net40\Accord.Controls.dll + + + ..\..\..\Release\net40\Accord.Controls.Imaging.dll + + + False + ..\..\..\Release\net40\Accord.Imaging.dll + + + False + ..\..\..\Release\net40\Accord.Math.dll + + + + 3.5 + + + + + + + + Form + + + MainForm.cs + + + + + MainForm.cs + Designer + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + --> \ No newline at end of file diff --git a/Samples/MachineLearning/Animat/Accord.dll.config b/Samples/MachineLearning/Animat/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/MachineLearning/Animat/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/MachineLearning/Animat/Animat (Sarsa, QLearning).csproj b/Samples/MachineLearning/Animat/Animat (Sarsa, QLearning).csproj new file mode 100644 index 0000000000..42045e642 --- /dev/null +++ b/Samples/MachineLearning/Animat/Animat (Sarsa, QLearning).csproj @@ -0,0 +1,166 @@ + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {B4892057-CAE6-41F4-A75D-88E61331A2D0} + WinExe + Properties + Animat + Animat + + + 3.5 + v4.0 + + + false + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + + ..\..\..\Release\net40\Accord.MachineLearning.dll + + + + + + + + + + Component + + + CellWorld.cs + + + Form + + + MainForm.cs + + + + + Designer + CellWorld.cs + + + Designer + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 2.0 %28x86%29 + false + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + true + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + \ No newline at end of file diff --git a/Samples/MachineLearning/Animat/Animat.sln b/Samples/MachineLearning/Animat/Animat.sln new file mode 100644 index 0000000000..a9a7c6022 --- /dev/null +++ b/Samples/MachineLearning/Animat/Animat.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C# Express 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Animat", "Animat.csproj", "{B4892057-CAE6-41F4-A75D-88E61331A2D0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B4892057-CAE6-41F4-A75D-88E61331A2D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B4892057-CAE6-41F4-A75D-88E61331A2D0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B4892057-CAE6-41F4-A75D-88E61331A2D0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B4892057-CAE6-41F4-A75D-88E61331A2D0}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/MachineLearning/Animat/CellWorld.Designer.cs b/Samples/MachineLearning/Animat/CellWorld.Designer.cs new file mode 100644 index 0000000000..99fe03e11 --- /dev/null +++ b/Samples/MachineLearning/Animat/CellWorld.Designer.cs @@ -0,0 +1,41 @@ +namespace Animat +{ + partial class CellWorld + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.SuspendLayout( ); + // + // CellWorld + // + this.ResumeLayout( false ); + + } + + #endregion + } +} diff --git a/Samples/MachineLearning/Animat/CellWorld.cs b/Samples/MachineLearning/Animat/CellWorld.cs new file mode 100644 index 0000000000..366e9be23 --- /dev/null +++ b/Samples/MachineLearning/Animat/CellWorld.cs @@ -0,0 +1,120 @@ +// Animat sample application +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Text; +using System.Windows.Forms; + +namespace Animat +{ + public partial class CellWorld : Control + { + private Pen blackPen = new Pen( Color.Black ); + private Brush whiteBrush = new SolidBrush( Color.White ); + + private int[,] map = null; + private Color[] coloring = null; + + /// + /// World's map + /// + /// + public int[,] Map + { + get { return map; } + set + { + map = value; + Invalidate( ); + } + } + + /// + /// World's coloring + /// + /// + public Color[] Coloring + { + get { return coloring; } + set + { + coloring = value; + Invalidate( ); + } + } + + // Control's constructor + public CellWorld( ) + { + InitializeComponent( ); + + // update control's style + SetStyle( ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | + ControlStyles.DoubleBuffer | ControlStyles.UserPaint, true ); + } + + // Paint the control + protected override void OnPaint( PaintEventArgs pe ) + { + Graphics g = pe.Graphics; + int clientWidth = ClientRectangle.Width; + int clientHeight = ClientRectangle.Height; + + // fill with white background + g.FillRectangle( whiteBrush, 0, 0, clientWidth - 1, clientHeight - 1 ); + + // draw a black rectangle + g.DrawRectangle( blackPen, 0, 0, clientWidth - 1, clientHeight - 1 ); + + if ( ( map != null ) && ( coloring != null ) ) + { + int brushesCount = coloring.Length; + int cellWidth = (int) ( clientWidth / map.GetLength( 1 ) ); + int cellHeight = (int) ( clientHeight / map.GetLength( 0 ) ); + + // create brushes + Brush[] brushes = new Brush[brushesCount]; + for ( int i = 0; i < brushesCount; i++ ) + { + brushes[i] = new SolidBrush( coloring[i] ); + } + + // draw the world + for ( int i = 0, n = map.GetLength( 0 ); i < n; i++ ) + { + int ch = ( i < n - 1 ) ? cellHeight : clientHeight - i * cellHeight - 1; + + for ( int j = 0, k = map.GetLength( 1 ); j < k; j++ ) + { + int cw = ( j < k - 1 ) ? cellWidth : clientWidth - j * cellWidth - 1; + + // check if we have appropriate brush + if ( map[i, j] < brushesCount ) + { + g.FillRectangle( brushes[map[i, j]], j * cellWidth, i * cellHeight, cw, ch ); + g.DrawRectangle( blackPen, j * cellWidth, i * cellHeight, cw, ch ); + } + } + } + + // release brushes + for ( int i = 0; i < brushesCount; i++ ) + { + brushes[i].Dispose( ); + } + } + + // Calling the base class OnPaint + base.OnPaint( pe ); + } + } +} diff --git a/Samples/MachineLearning/Animat/CellWorld.resx b/Samples/MachineLearning/Animat/CellWorld.resx new file mode 100644 index 0000000000..52a9ad3e7 --- /dev/null +++ b/Samples/MachineLearning/Animat/CellWorld.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + False + + \ No newline at end of file diff --git a/Samples/MachineLearning/Animat/Data files/sample1.map b/Samples/MachineLearning/Animat/Data files/sample1.map new file mode 100644 index 0000000000..0764e60b9 --- /dev/null +++ b/Samples/MachineLearning/Animat/Data files/sample1.map @@ -0,0 +1,20 @@ +; Map file +; +; 1st line - 2 numbers: map size (width and height) +; 2st line - number of agents (n) +; next n lines - two pairs of (x, y) coordinates of agent's start and stop positions +; next (height) lines - map +; +; 0 - free space available for motion +; 1 - wall +; +6 6 +1 +1 1 4 4 + +1 1 1 1 1 1 +1 0 0 0 0 1 +1 0 0 0 0 1 +1 0 0 0 0 1 +1 0 0 0 0 1 +1 1 1 1 1 1 diff --git a/Samples/MachineLearning/Animat/Data files/sample2.map b/Samples/MachineLearning/Animat/Data files/sample2.map new file mode 100644 index 0000000000..eee33176b --- /dev/null +++ b/Samples/MachineLearning/Animat/Data files/sample2.map @@ -0,0 +1,24 @@ +; Map file +; +; 1st line - 2 numbers: map size (width and height) +; 2st line - number of agents (n) +; next n lines - two pairs of (x, y) coordinates of agent's start and stop positions +; next (height) lines - map +; +; 0 - free space available for motion +; 1 - wall +; +10 10 +1 +1 1 8 8 + +1 1 1 1 1 1 1 1 1 1 +1 0 0 0 0 1 0 0 0 1 +1 0 0 0 0 1 0 0 0 1 +1 0 0 0 0 0 0 0 0 1 +1 0 0 0 0 1 0 0 0 1 +1 0 0 0 0 1 0 0 0 1 +1 0 0 0 0 1 0 0 0 1 +1 0 0 0 0 1 0 0 0 1 +1 0 0 0 0 0 0 0 0 1 +1 1 1 1 1 1 1 1 1 1 diff --git a/Samples/MachineLearning/Animat/Data files/test1.map b/Samples/MachineLearning/Animat/Data files/test1.map new file mode 100644 index 0000000000..0eef53325 --- /dev/null +++ b/Samples/MachineLearning/Animat/Data files/test1.map @@ -0,0 +1,23 @@ +; Map file +; +; 1st line - 2 numbers: map size (width and height) +; 2st line - number of agents (n) +; next n lines - two pairs of (x, y) coordinates of agent's start and stop positions +; next (height) lines - map +; +; 0 - free space available for motion +; 1 - wall +; +9 9 +1 +1 4 7 4 + +1 1 1 1 1 1 1 1 1 +1 1 0 0 0 0 0 0 1 +1 1 0 0 0 1 1 0 1 +1 0 0 1 0 0 0 0 1 +1 0 0 1 1 1 1 0 1 +1 0 0 1 1 0 0 0 1 +1 1 0 1 0 0 0 0 1 +1 1 0 1 0 1 1 0 1 +1 1 1 1 1 1 1 1 1 diff --git a/Samples/MachineLearning/Animat/Data files/test2.map b/Samples/MachineLearning/Animat/Data files/test2.map new file mode 100644 index 0000000000..899e5bbdd --- /dev/null +++ b/Samples/MachineLearning/Animat/Data files/test2.map @@ -0,0 +1,23 @@ +; Map file +; +; 1st line - 2 numbers: map size (width and height) +; 2st line - number of agents (n) +; next n lines - two pairs of (x, y) coordinates of agent's start and stop positions +; next (height) lines - map +; +; 0 - free space available for motion +; 1 - wall +; +9 9 +1 +1 4 7 4 + +1 1 1 1 1 1 1 1 1 +1 0 0 1 0 0 0 0 1 +1 0 0 1 0 1 1 0 1 +1 0 0 1 0 0 0 0 1 +1 0 0 1 1 1 1 0 1 +1 0 0 1 1 0 0 0 1 +1 1 0 0 0 0 0 0 1 +1 1 0 0 0 1 1 0 1 +1 1 1 1 1 1 1 1 1 diff --git a/Samples/MachineLearning/Animat/Data files/test3.map b/Samples/MachineLearning/Animat/Data files/test3.map new file mode 100644 index 0000000000..fbcba5857 --- /dev/null +++ b/Samples/MachineLearning/Animat/Data files/test3.map @@ -0,0 +1,23 @@ +; Map file +; +; 1st line - 2 numbers: map size (width and height) +; 2st line - number of agents (n) +; next n lines - two pairs of (x, y) coordinates of agent's start and stop positions +; next (height) lines - map +; +; 0 - free space available for motion +; 1 - wall +; +9 9 +1 +7 4 1 4 + +1 1 1 1 1 1 1 1 1 +1 1 0 0 0 0 0 0 1 +1 1 0 0 0 1 1 0 1 +1 0 0 1 0 0 0 0 1 +1 0 0 1 1 1 1 0 1 +1 0 0 1 1 0 0 0 1 +1 1 0 1 0 0 0 0 1 +1 1 0 1 0 1 1 0 1 +1 1 1 1 1 1 1 1 1 diff --git a/Samples/MachineLearning/Animat/MainForm.Designer.cs b/Samples/MachineLearning/Animat/MainForm.Designer.cs new file mode 100644 index 0000000000..e33dcccb5 --- /dev/null +++ b/Samples/MachineLearning/Animat/MainForm.Designer.cs @@ -0,0 +1,384 @@ +namespace Animat +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.groupBox1 = new System.Windows.Forms.GroupBox( ); + this.worldSizeBox = new System.Windows.Forms.TextBox( ); + this.label1 = new System.Windows.Forms.Label( ); + this.cellWorld = new Animat.CellWorld( ); + this.loadButton = new System.Windows.Forms.Button( ); + this.openFileDialog = new System.Windows.Forms.OpenFileDialog( ); + this.groupBox2 = new System.Windows.Forms.GroupBox( ); + this.algorithmCombo = new System.Windows.Forms.ComboBox( ); + this.label10 = new System.Windows.Forms.Label( ); + this.goalRewardBox = new System.Windows.Forms.TextBox( ); + this.label9 = new System.Windows.Forms.Label( ); + this.wallRewardBox = new System.Windows.Forms.TextBox( ); + this.label8 = new System.Windows.Forms.Label( ); + this.moveRewardBox = new System.Windows.Forms.TextBox( ); + this.label7 = new System.Windows.Forms.Label( ); + this.label6 = new System.Windows.Forms.Label( ); + this.iterationsBox = new System.Windows.Forms.TextBox( ); + this.label5 = new System.Windows.Forms.Label( ); + this.learningRateBox = new System.Windows.Forms.TextBox( ); + this.label4 = new System.Windows.Forms.Label( ); + this.explorationRateBox = new System.Windows.Forms.TextBox( ); + this.label3 = new System.Windows.Forms.Label( ); + this.groupBox3 = new System.Windows.Forms.GroupBox( ); + this.showSolutionButton = new System.Windows.Forms.Button( ); + this.iterationBox = new System.Windows.Forms.TextBox( ); + this.label2 = new System.Windows.Forms.Label( ); + this.stopButton = new System.Windows.Forms.Button( ); + this.startLearningButton = new System.Windows.Forms.Button( ); + this.groupBox1.SuspendLayout( ); + this.groupBox2.SuspendLayout( ); + this.groupBox3.SuspendLayout( ); + this.SuspendLayout( ); + // + // groupBox1 + // + this.groupBox1.Controls.Add( this.worldSizeBox ); + this.groupBox1.Controls.Add( this.label1 ); + this.groupBox1.Controls.Add( this.cellWorld ); + this.groupBox1.Controls.Add( this.loadButton ); + this.groupBox1.Location = new System.Drawing.Point( 10, 10 ); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size( 300, 335 ); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Map"; + // + // worldSizeBox + // + this.worldSizeBox.Location = new System.Drawing.Point( 220, 307 ); + this.worldSizeBox.Name = "worldSizeBox"; + this.worldSizeBox.ReadOnly = true; + this.worldSizeBox.Size = new System.Drawing.Size( 70, 20 ); + this.worldSizeBox.TabIndex = 3; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point( 160, 309 ); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size( 59, 13 ); + this.label1.TabIndex = 2; + this.label1.Text = "World size:"; + // + // cellWorld + // + this.cellWorld.Coloring = null; + this.cellWorld.Location = new System.Drawing.Point( 10, 20 ); + this.cellWorld.Map = null; + this.cellWorld.Name = "cellWorld"; + this.cellWorld.Size = new System.Drawing.Size( 280, 280 ); + this.cellWorld.TabIndex = 1; + this.cellWorld.Text = "cellWorld1"; + // + // loadButton + // + this.loadButton.Location = new System.Drawing.Point( 10, 305 ); + this.loadButton.Name = "loadButton"; + this.loadButton.Size = new System.Drawing.Size( 75, 23 ); + this.loadButton.TabIndex = 0; + this.loadButton.Text = "&Load"; + this.loadButton.UseVisualStyleBackColor = true; + this.loadButton.Click += new System.EventHandler( this.loadButton_Click ); + // + // openFileDialog + // + this.openFileDialog.Filter = "MAP (World\'s map file) (*.map)|*.map"; + this.openFileDialog.Title = "Select map file"; + // + // groupBox2 + // + this.groupBox2.Controls.Add( this.algorithmCombo ); + this.groupBox2.Controls.Add( this.label10 ); + this.groupBox2.Controls.Add( this.goalRewardBox ); + this.groupBox2.Controls.Add( this.label9 ); + this.groupBox2.Controls.Add( this.wallRewardBox ); + this.groupBox2.Controls.Add( this.label8 ); + this.groupBox2.Controls.Add( this.moveRewardBox ); + this.groupBox2.Controls.Add( this.label7 ); + this.groupBox2.Controls.Add( this.label6 ); + this.groupBox2.Controls.Add( this.iterationsBox ); + this.groupBox2.Controls.Add( this.label5 ); + this.groupBox2.Controls.Add( this.learningRateBox ); + this.groupBox2.Controls.Add( this.label4 ); + this.groupBox2.Controls.Add( this.explorationRateBox ); + this.groupBox2.Controls.Add( this.label3 ); + this.groupBox2.Location = new System.Drawing.Point( 320, 10 ); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size( 187, 220 ); + this.groupBox2.TabIndex = 1; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Settings"; + // + // algorithmCombo + // + this.algorithmCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.algorithmCombo.FormattingEnabled = true; + this.algorithmCombo.Items.AddRange( new object[] { + "Q-Learning", + "Sarsa"} ); + this.algorithmCombo.Location = new System.Drawing.Point( 105, 20 ); + this.algorithmCombo.Name = "algorithmCombo"; + this.algorithmCombo.Size = new System.Drawing.Size( 70, 21 ); + this.algorithmCombo.TabIndex = 1; + // + // label10 + // + this.label10.AutoSize = true; + this.label10.Location = new System.Drawing.Point( 10, 22 ); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size( 96, 13 ); + this.label10.TabIndex = 0; + this.label10.Text = "Learning &algorithm:"; + // + // goalRewardBox + // + this.goalRewardBox.Location = new System.Drawing.Point( 125, 180 ); + this.goalRewardBox.Name = "goalRewardBox"; + this.goalRewardBox.Size = new System.Drawing.Size( 50, 20 ); + this.goalRewardBox.TabIndex = 13; + // + // label9 + // + this.label9.Location = new System.Drawing.Point( 10, 182 ); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size( 70, 15 ); + this.label9.TabIndex = 12; + this.label9.Text = "&Goal reward:"; + // + // wallRewardBox + // + this.wallRewardBox.Location = new System.Drawing.Point( 125, 155 ); + this.wallRewardBox.Name = "wallRewardBox"; + this.wallRewardBox.Size = new System.Drawing.Size( 50, 20 ); + this.wallRewardBox.TabIndex = 11; + // + // label8 + // + this.label8.Location = new System.Drawing.Point( 10, 157 ); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size( 80, 15 ); + this.label8.TabIndex = 10; + this.label8.Text = "&Wall reward:"; + // + // moveRewardBox + // + this.moveRewardBox.Location = new System.Drawing.Point( 125, 130 ); + this.moveRewardBox.Name = "moveRewardBox"; + this.moveRewardBox.Size = new System.Drawing.Size( 50, 20 ); + this.moveRewardBox.TabIndex = 9; + // + // label7 + // + this.label7.Location = new System.Drawing.Point( 10, 132 ); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size( 100, 15 ); + this.label7.TabIndex = 8; + this.label7.Text = "&Move reward:"; + // + // label6 + // + this.label6.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.label6.Location = new System.Drawing.Point( 10, 121 ); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size( 165, 2 ); + this.label6.TabIndex = 14; + // + // iterationsBox + // + this.iterationsBox.Location = new System.Drawing.Point( 125, 95 ); + this.iterationsBox.Name = "iterationsBox"; + this.iterationsBox.Size = new System.Drawing.Size( 50, 20 ); + this.iterationsBox.TabIndex = 7; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point( 10, 97 ); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size( 96, 13 ); + this.label5.TabIndex = 6; + this.label5.Text = "Learning &iterations:"; + // + // learningRateBox + // + this.learningRateBox.Location = new System.Drawing.Point( 125, 70 ); + this.learningRateBox.Name = "learningRateBox"; + this.learningRateBox.Size = new System.Drawing.Size( 50, 20 ); + this.learningRateBox.TabIndex = 5; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point( 10, 72 ); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size( 95, 13 ); + this.label4.TabIndex = 4; + this.label4.Text = "Initial learning &rate:"; + // + // explorationRateBox + // + this.explorationRateBox.Location = new System.Drawing.Point( 125, 45 ); + this.explorationRateBox.Name = "explorationRateBox"; + this.explorationRateBox.Size = new System.Drawing.Size( 50, 20 ); + this.explorationRateBox.TabIndex = 3; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point( 10, 48 ); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size( 109, 13 ); + this.label3.TabIndex = 2; + this.label3.Text = "Initial &exploration rate:"; + // + // groupBox3 + // + this.groupBox3.Controls.Add( this.showSolutionButton ); + this.groupBox3.Controls.Add( this.iterationBox ); + this.groupBox3.Controls.Add( this.label2 ); + this.groupBox3.Controls.Add( this.stopButton ); + this.groupBox3.Controls.Add( this.startLearningButton ); + this.groupBox3.Location = new System.Drawing.Point( 320, 235 ); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Size = new System.Drawing.Size( 187, 110 ); + this.groupBox3.TabIndex = 2; + this.groupBox3.TabStop = false; + this.groupBox3.Text = "Learning"; + // + // showSolutionButton + // + this.showSolutionButton.Enabled = false; + this.showSolutionButton.Location = new System.Drawing.Point( 10, 80 ); + this.showSolutionButton.Name = "showSolutionButton"; + this.showSolutionButton.Size = new System.Drawing.Size( 155, 23 ); + this.showSolutionButton.TabIndex = 4; + this.showSolutionButton.Text = "S&how solution"; + this.showSolutionButton.UseVisualStyleBackColor = true; + this.showSolutionButton.Click += new System.EventHandler( this.showSolutionButton_Click ); + // + // iterationBox + // + this.iterationBox.Location = new System.Drawing.Point( 65, 20 ); + this.iterationBox.Name = "iterationBox"; + this.iterationBox.ReadOnly = true; + this.iterationBox.Size = new System.Drawing.Size( 100, 20 ); + this.iterationBox.TabIndex = 1; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point( 10, 23 ); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size( 48, 13 ); + this.label2.TabIndex = 0; + this.label2.Text = "Iteration:"; + // + // stopButton + // + this.stopButton.Enabled = false; + this.stopButton.Location = new System.Drawing.Point( 90, 50 ); + this.stopButton.Name = "stopButton"; + this.stopButton.Size = new System.Drawing.Size( 75, 23 ); + this.stopButton.TabIndex = 3; + this.stopButton.Text = "S&top"; + this.stopButton.UseVisualStyleBackColor = true; + this.stopButton.Click += new System.EventHandler( this.stopButton_Click ); + // + // startLearningButton + // + this.startLearningButton.Enabled = false; + this.startLearningButton.Location = new System.Drawing.Point( 10, 50 ); + this.startLearningButton.Name = "startLearningButton"; + this.startLearningButton.Size = new System.Drawing.Size( 75, 23 ); + this.startLearningButton.TabIndex = 2; + this.startLearningButton.Text = "&Start"; + this.startLearningButton.UseVisualStyleBackColor = true; + this.startLearningButton.Click += new System.EventHandler( this.startLearningButton_Click ); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 13F ); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size( 519, 355 ); + this.Controls.Add( this.groupBox3 ); + this.Controls.Add( this.groupBox2 ); + this.Controls.Add( this.groupBox1 ); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.Name = "MainForm"; + this.Text = "Animat"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler( this.MainForm_FormClosing ); + this.groupBox1.ResumeLayout( false ); + this.groupBox1.PerformLayout( ); + this.groupBox2.ResumeLayout( false ); + this.groupBox2.PerformLayout( ); + this.groupBox3.ResumeLayout( false ); + this.groupBox3.PerformLayout( ); + this.ResumeLayout( false ); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Button loadButton; + private System.Windows.Forms.OpenFileDialog openFileDialog; + private CellWorld cellWorld; + private System.Windows.Forms.TextBox worldSizeBox; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.TextBox iterationBox; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Button stopButton; + private System.Windows.Forms.Button startLearningButton; + private System.Windows.Forms.Button showSolutionButton; + private System.Windows.Forms.TextBox learningRateBox; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.TextBox explorationRateBox; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox iterationsBox; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.TextBox goalRewardBox; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.TextBox wallRewardBox; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.TextBox moveRewardBox; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.ComboBox algorithmCombo; + private System.Windows.Forms.Label label10; + } +} + diff --git a/Samples/MachineLearning/Animat/MainForm.cs b/Samples/MachineLearning/Animat/MainForm.cs new file mode 100644 index 0000000000..8ec0f73b9 --- /dev/null +++ b/Samples/MachineLearning/Animat/MainForm.cs @@ -0,0 +1,639 @@ +// Animat sample application +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; +using System.IO; +using System.Threading; + +using AForge.MachineLearning; + +namespace Animat +{ + public partial class MainForm : Form + { + // map and its dimension + private int[,] map = null; + private int[,] mapToDisplay = null; + private int mapWidth; + private int mapHeight; + + // agent' start and stop position + private int agentStartX; + private int agentStartY; + private int agentStopX; + private int agentStopY; + + // flag to stop background job + private volatile bool needToStop = false; + + // worker thread + private Thread workerThread = null; + + // learning settings + int learningIterations = 100; + private double explorationRate = 0.5; + private double learningRate = 0.5; + + private double moveReward = 0; + private double wallReward = -1; + private double goalReward = 1; + + // Q-Learning algorithm + private QLearning qLearning = null; + // Sarsa algorithm + private Sarsa sarsa = null; + + // Form constructor + public MainForm( ) + { + InitializeComponent( ); + + // set world colors + cellWorld.Coloring = new Color[] { Color.White, Color.Green, Color.Black, Color.Red }; + + // show settings + ShowSettings( ); + algorithmCombo.SelectedIndex = 0; + + openFileDialog.InitialDirectory = Path.Combine(Application.StartupPath, "Data files"); + } + + // Form is closing + private void MainForm_FormClosing( object sender, FormClosingEventArgs e ) + { + // check if worker thread is running + if ( ( workerThread != null ) && ( workerThread.IsAlive ) ) + { + needToStop = true; + while ( !workerThread.Join( 100 ) ) + Application.DoEvents( ); + } + } + + // Delegates to enable async calls for setting controls properties + private delegate void SetTextCallback( System.Windows.Forms.Control control, string text ); + + // Thread safe updating of control's text property + private void SetText( System.Windows.Forms.Control control, string text ) + { + if ( control.InvokeRequired ) + { + SetTextCallback d = new SetTextCallback( SetText ); + Invoke( d, new object[] { control, text } ); + } + else + { + control.Text = text; + } + } + + // Delegates to enable async calls for setting controls properties + private delegate void EnableCallback( bool enable ); + + // Enable/disale controls (safe for threading) + private void EnableControls( bool enable ) + { + if ( InvokeRequired ) + { + EnableCallback d = new EnableCallback( EnableControls ); + Invoke( d, new object[] { enable } ); + } + else + { + loadButton.Enabled = enable; + + algorithmCombo.Enabled = enable; + explorationRateBox.Enabled = enable; + learningRateBox.Enabled = enable; + iterationsBox.Enabled = enable; + + moveRewardBox.Enabled = enable; + wallRewardBox.Enabled = enable; + goalRewardBox.Enabled = enable; + + startLearningButton.Enabled = enable; + showSolutionButton.Enabled = enable; + stopButton.Enabled = !enable; + } + } + + // Show settings + private void ShowSettings( ) + { + explorationRateBox.Text = explorationRate.ToString( ); + learningRateBox.Text = learningRate.ToString( ); + iterationsBox.Text = learningIterations.ToString( ); + + moveRewardBox.Text = moveReward.ToString( ); + wallRewardBox.Text = wallReward.ToString( ); + goalRewardBox.Text = goalReward.ToString( ); + } + + // Get settings + private void GetSettings( ) + { + // explortion rate + try + { + explorationRate = Math.Max( 0.0, Math.Min( 1.0, double.Parse( explorationRateBox.Text ) ) ); + } + catch + { + explorationRate = 0.5; + } + // learning rate + try + { + learningRate = Math.Max( 0.0, Math.Min( 1.0, double.Parse( learningRateBox.Text ) ) ); + } + catch + { + learningRate = 0.5; + } + // learning iterations + try + { + learningIterations = Math.Max( 10, Math.Min( 100000, int.Parse( iterationsBox.Text ) ) ); + } + catch + { + learningIterations = 100; + } + + // move reward + try + { + moveReward = Math.Max( -100, Math.Min( 100, double.Parse( moveRewardBox.Text ) ) ); + } + catch + { + moveReward = 0; + } + // wall reward + try + { + wallReward = Math.Max( -100, Math.Min( 100, double.Parse( wallRewardBox.Text ) ) ); + } + catch + { + wallReward = -1; + } + // goal reward + try + { + goalReward = Math.Max( -100, Math.Min( 100, double.Parse( goalRewardBox.Text ) ) ); + } + catch + { + goalReward = 1; + } + } + + // On "Load" button click + private void loadButton_Click( object sender, EventArgs e ) + { + // show file selection dialog + if ( openFileDialog.ShowDialog( ) == DialogResult.OK ) + { + StreamReader reader = null; + + try + { + // open selected file + reader = File.OpenText( openFileDialog.FileName ); + string str = null; + // line counter + int lines = 0; + int j = 0; + + // read the file + while ( ( str = reader.ReadLine( ) ) != null ) + { + str = str.Trim( ); + + // skip comments and empty lines + if ( ( str == string.Empty ) || ( str[0] == ';' ) || ( str[0] == '\0' ) ) + continue; + + // split the string + string[] strs = str.Split( ' ' ); + + // check the line + if ( lines == 0 ) + { + // get world size + mapWidth = int.Parse( strs[0] ); + mapHeight = int.Parse( strs[1] ); + map = new int[mapHeight, mapWidth]; + } + else if ( lines == 1 ) + { + // get agents count + if ( int.Parse( strs[0] ) != 1 ) + { + MessageBox.Show( "The application supports only 1 agent in the worlds", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); + break; + } + } + else if ( lines == 2 ) + { + // agent position + agentStartX = int.Parse( strs[0] ); + agentStartY = int.Parse( strs[1] ); + agentStopX = int.Parse( strs[2] ); + agentStopY = int.Parse( strs[3] ); + + // check position + if ( + ( agentStartX < 0 ) || ( agentStartX >= mapWidth ) || + ( agentStartY < 0 ) || ( agentStartY >= mapHeight ) || + ( agentStopX < 0 ) || ( agentStopX >= mapWidth ) || + ( agentStopY < 0 ) || ( agentStopY >= mapHeight ) + ) + { + MessageBox.Show( "Agent's start and stop coordinates should be inside the world area ", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); + break; + } + } + else if ( lines > 2 ) + { + // map lines + if ( j < mapHeight ) + { + for ( int i = 0; i < mapWidth; i++ ) + { + map[j, i] = int.Parse( strs[i] ); + if ( map[j, i] > 1 ) + map[j, i] = 1; + } + j++; + } + } + lines++; + } + + // set world's map + mapToDisplay = (int[,]) map.Clone( ); + mapToDisplay[agentStartY, agentStartX] = 2; + mapToDisplay[agentStopY, agentStopX] = 3; + cellWorld.Map = mapToDisplay; + + // show world's size + worldSizeBox.Text = string.Format( "{0} x {1}", mapWidth, mapHeight ); + + // enable learning button + startLearningButton.Enabled = true; + } + catch ( Exception ) + { + MessageBox.Show( "Failed reading the map file", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); + return; + } + finally + { + // close file + if ( reader != null ) + reader.Close( ); + } + } + } + + // On "Start" learning button click + private void startLearningButton_Click( object sender, EventArgs e ) + { + // get settings + GetSettings( ); + ShowSettings( ); + + iterationBox.Text = string.Empty; + + // destroy algorithms + qLearning = null; + sarsa = null; + + if ( algorithmCombo.SelectedIndex == 0 ) + { + // create new QLearning algorithm's instance + qLearning = new QLearning( 256, 4, new TabuSearchExploration( 4, new EpsilonGreedyExploration( explorationRate ) ) ); + workerThread = new Thread( new ThreadStart( QLearningThread ) ); + } + else + { + // create new Sarsa algorithm's instance + sarsa = new Sarsa( 256, 4, new TabuSearchExploration( 4, new EpsilonGreedyExploration( explorationRate ) ) ); + workerThread = new Thread( new ThreadStart( SarsaThread ) ); + } + + // disable all settings controls except "Stop" button + EnableControls( false ); + + // run worker thread + needToStop = false; + workerThread.Start( ); + } + + // On "Stop" button click + private void stopButton_Click( object sender, EventArgs e ) + { + if ( workerThread != null ) + { + // stop worker thread + needToStop = true; + while ( !workerThread.Join( 100 ) ) + Application.DoEvents( ); + workerThread = null; + } + } + + // On "Show Solution" button + private void showSolutionButton_Click( object sender, EventArgs e ) + { + // check if learning algorithm was run before + if ( ( qLearning == null ) && ( sarsa == null ) ) + return; + + // disable all settings controls except "Stop" button + EnableControls( false ); + + // run worker thread + needToStop = false; + workerThread = new Thread( new ThreadStart( ShowSolutionThread ) ); + workerThread.Start( ); + } + + // Q-Learning thread + private void QLearningThread( ) + { + int iteration = 0; + // curent coordinates of the agent + int agentCurrentX, agentCurrentY; + // exploration policy + TabuSearchExploration tabuPolicy = (TabuSearchExploration) qLearning.ExplorationPolicy; + EpsilonGreedyExploration explorationPolicy = (EpsilonGreedyExploration) tabuPolicy.BasePolicy; + + // loop + while ( ( !needToStop ) && ( iteration < learningIterations ) ) + { + // set exploration rate for this iteration + explorationPolicy.Epsilon = explorationRate - ( (double) iteration / learningIterations ) * explorationRate; + // set learning rate for this iteration + qLearning.LearningRate = learningRate - ( (double) iteration / learningIterations ) * learningRate; + // clear tabu list + tabuPolicy.ResetTabuList( ); + + // reset agent's coordinates to the starting position + agentCurrentX = agentStartX; + agentCurrentY = agentStartY; + + // steps performed by agent to get to the goal + int steps = 0; + + while ( ( !needToStop ) && ( ( agentCurrentX != agentStopX ) || ( agentCurrentY != agentStopY ) ) ) + { + steps++; + // get agent's current state + int currentState = GetStateNumber( agentCurrentX, agentCurrentY ); + // get the action for this state + int action = qLearning.GetAction( currentState ); + // update agent's current position and get his reward + double reward = UpdateAgentPosition( ref agentCurrentX, ref agentCurrentY, action ); + // get agent's next state + int nextState = GetStateNumber( agentCurrentX, agentCurrentY ); + // do learning of the agent - update his Q-function + qLearning.UpdateState( currentState, action, reward, nextState ); + + // set tabu action + tabuPolicy.SetTabuAction( ( action + 2 ) % 4, 1 ); + } + + System.Diagnostics.Debug.WriteLine( steps ); + + iteration++; + + // show current iteration + SetText( iterationBox, iteration.ToString( ) ); + } + + // enable settings controls + EnableControls( true ); + } + + // Sarsa thread + private void SarsaThread( ) + { + int iteration = 0; + // curent coordinates of the agent + int agentCurrentX, agentCurrentY; + // exploration policy + TabuSearchExploration tabuPolicy = (TabuSearchExploration) sarsa.ExplorationPolicy; + EpsilonGreedyExploration explorationPolicy = (EpsilonGreedyExploration) tabuPolicy.BasePolicy; + + // loop + while ( ( !needToStop ) && ( iteration < learningIterations ) ) + { + // set exploration rate for this iteration + explorationPolicy.Epsilon = explorationRate - ( (double) iteration / learningIterations ) * explorationRate; + // set learning rate for this iteration + sarsa.LearningRate = learningRate - ( (double) iteration / learningIterations ) * learningRate; + // clear tabu list + tabuPolicy.ResetTabuList( ); + + // reset agent's coordinates to the starting position + agentCurrentX = agentStartX; + agentCurrentY = agentStartY; + + // steps performed by agent to get to the goal + int steps = 1; + // previous state and action + int previousState = GetStateNumber( agentCurrentX, agentCurrentY ); + int previousAction = sarsa.GetAction( previousState ); + // update agent's current position and get his reward + double reward = UpdateAgentPosition( ref agentCurrentX, ref agentCurrentY, previousAction ); + + while ( ( !needToStop ) && ( ( agentCurrentX != agentStopX ) || ( agentCurrentY != agentStopY ) ) ) + { + steps++; + + // set tabu action + tabuPolicy.SetTabuAction( ( previousAction + 2 ) % 4, 1 ); + + // get agent's next state + int nextState = GetStateNumber( agentCurrentX, agentCurrentY ); + // get agent's next action + int nextAction = sarsa.GetAction( nextState ); + // do learning of the agent - update his Q-function + sarsa.UpdateState( previousState, previousAction, reward, nextState, nextAction ); + + // update agent's new position and get his reward + reward = UpdateAgentPosition( ref agentCurrentX, ref agentCurrentY, nextAction ); + + previousState = nextState; + previousAction = nextAction; + } + + if ( !needToStop ) + { + // update Q-function if terminal state was reached + sarsa.UpdateState( previousState, previousAction, reward ); + } + + System.Diagnostics.Debug.WriteLine( steps ); + + iteration++; + + // show current iteration + SetText( iterationBox, iteration.ToString( ) ); + } + + // enable settings controls + EnableControls( true ); + } + + // Show solution thread + private void ShowSolutionThread( ) + { + // set exploration rate to 0, so agent uses only what he learnt + TabuSearchExploration tabuPolicy = null; + EpsilonGreedyExploration exploratioPolicy = null; + + if ( qLearning != null ) + tabuPolicy = (TabuSearchExploration) qLearning.ExplorationPolicy; + else + tabuPolicy = (TabuSearchExploration) sarsa.ExplorationPolicy; + + exploratioPolicy = (EpsilonGreedyExploration) tabuPolicy.BasePolicy; + + exploratioPolicy.Epsilon = 0; + tabuPolicy.ResetTabuList( ); + + // curent coordinates of the agent + int agentCurrentX = agentStartX, agentCurrentY = agentStartY; + + // pripate the map to display + Array.Copy( map, mapToDisplay, mapWidth * mapHeight ); + mapToDisplay[agentStartY, agentStartX] = 2; + mapToDisplay[agentStopY, agentStopX] = 3; + + while ( !needToStop ) + { + // dispay the map + cellWorld.Map = mapToDisplay; + // sleep for a while + Thread.Sleep( 200 ); + + // check if we have reached the end point + if ( ( agentCurrentX == agentStopX ) && ( agentCurrentY == agentStopY ) ) + { + // restore the map + mapToDisplay[agentStartY, agentStartX] = 2; + mapToDisplay[agentStopY, agentStopX] = 3; + + agentCurrentX = agentStartX; + agentCurrentY = agentStartY; + + cellWorld.Map = mapToDisplay; + Thread.Sleep( 200 ); + } + + // remove agent from current position + mapToDisplay[agentCurrentY, agentCurrentX] = 0; + + // get agent's current state + int currentState = GetStateNumber( agentCurrentX, agentCurrentY ); + // get the action for this state + int action = ( qLearning != null ) ? qLearning.GetAction( currentState ) : sarsa.GetAction( currentState ); + // update agent's current position and get his reward + double reward = UpdateAgentPosition( ref agentCurrentX, ref agentCurrentY, action ); + + // put agent to the new position + mapToDisplay[agentCurrentY, agentCurrentX] = 2; + } + + // enable settings controls + EnableControls( true ); + } + + // Update agent position and return reward for the move + private double UpdateAgentPosition( ref int currentX, ref int currentY, int action ) + { + // default reward is equal to moving reward + double reward = moveReward; + // moving direction + int dx = 0, dy = 0; + + switch ( action ) + { + case 0: // go to north (up) + dy = -1; + break; + case 1: // go to east (right) + dx = 1; + break; + case 2: // go to south (down) + dy = 1; + break; + case 3: // go to west (left) + dx = -1; + break; + } + + int newX = currentX + dx; + int newY = currentY + dy; + + // check new agent's coordinates + if ( + ( map[newY, newX] != 0 ) || + ( newX < 0 ) || ( newX >= mapWidth ) || + ( newY < 0 ) || ( newY >= mapHeight ) + ) + { + // we found a wall or got outside of the world + reward = wallReward; + } + else + { + currentX = newX; + currentY = newY; + + // check if we found the goal + if ( ( currentX == agentStopX ) && ( currentY == agentStopY ) ) + reward = goalReward; + } + + return reward; + } + + // Get state number from agent's receptors in the specified position + private int GetStateNumber( int x, int y ) + { + int c1 = ( map[y - 1, x - 1] != 0 ) ? 1 : 0; + int c2 = ( map[y - 1, x] != 0 ) ? 1 : 0; + int c3 = ( map[y - 1, x + 1] != 0 ) ? 1 : 0; + int c4 = ( map[y, x + 1] != 0 ) ? 1 : 0; + int c5 = ( map[y + 1, x + 1] != 0 ) ? 1 : 0; + int c6 = ( map[y + 1, x] != 0 ) ? 1 : 0; + int c7 = ( map[y + 1, x - 1] != 0 ) ? 1 : 0; + int c8 = ( map[y, x - 1] != 0 ) ? 1 : 0; + + return c1 | + ( c2 << 1 ) | + ( c3 << 2 ) | + ( c4 << 3 ) | + ( c5 << 4 ) | + ( c6 << 5 ) | + ( c7 << 6 ) | + ( c8 << 7 ); + } + } +} \ No newline at end of file diff --git a/Samples/MachineLearning/Animat/MainForm.resx b/Samples/MachineLearning/Animat/MainForm.resx new file mode 100644 index 0000000000..f901ebb7c --- /dev/null +++ b/Samples/MachineLearning/Animat/MainForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/Samples/MachineLearning/Animat/Program.cs b/Samples/MachineLearning/Animat/Program.cs new file mode 100644 index 0000000000..93b991e4b --- /dev/null +++ b/Samples/MachineLearning/Animat/Program.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; + +namespace Animat +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main( ) + { + Application.EnableVisualStyles( ); + Application.SetCompatibleTextRenderingDefault( false ); + Application.Run( new MainForm( ) ); + } + } +} \ No newline at end of file diff --git a/Samples/MachineLearning/Animat/Properties/AssemblyInfo.cs b/Samples/MachineLearning/Animat/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..99502c8c6 --- /dev/null +++ b/Samples/MachineLearning/Animat/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle( "Machine Learning Animat" )] +[assembly: AssemblyDescription( "Machine Learning Animat sample" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "AForge" )] +[assembly: AssemblyProduct( "AForge.NET" )] +[assembly: AssemblyCopyright( "AForge © 2008" )] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible( false )] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid( "072ee388-941b-4c71-bec5-58622a68210c" )] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion( "2.0.0.0" )] +[assembly: AssemblyFileVersion( "2.0.0.0" )] diff --git a/Samples/MachineLearning/Animat/Properties/Resources.Designer.cs b/Samples/MachineLearning/Animat/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..cc796415f --- /dev/null +++ b/Samples/MachineLearning/Animat/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Animat.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Animat.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Samples/MachineLearning/Animat/Properties/Resources.resx b/Samples/MachineLearning/Animat/Properties/Resources.resx new file mode 100644 index 0000000000..25a61211c --- /dev/null +++ b/Samples/MachineLearning/Animat/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/MachineLearning/Animat/Properties/Settings.Designer.cs b/Samples/MachineLearning/Animat/Properties/Settings.Designer.cs new file mode 100644 index 0000000000..82f1cd4b5 --- /dev/null +++ b/Samples/MachineLearning/Animat/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Animat.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Samples/MachineLearning/Animat/Properties/Settings.settings b/Samples/MachineLearning/Animat/Properties/Settings.settings new file mode 100644 index 0000000000..39645652a --- /dev/null +++ b/Samples/MachineLearning/Animat/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Samples/MachineLearning/Animat/app.config b/Samples/MachineLearning/Animat/app.config new file mode 100644 index 0000000000..57c0f2cbc --- /dev/null +++ b/Samples/MachineLearning/Animat/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Samples/MachineLearning/Classification (SVMs)/Accord.dll.config b/Samples/MachineLearning/Classification (SVMs)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/MachineLearning/Classification (SVMs)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/MachineLearning/Classification (SVMs)/Classification (SVMs).csproj b/Samples/MachineLearning/Classification (SVMs)/Classification (SVMs).csproj index d32e9efeb..d363d8230 100644 --- a/Samples/MachineLearning/Classification (SVMs)/Classification (SVMs).csproj +++ b/Samples/MachineLearning/Classification (SVMs)/Classification (SVMs).csproj @@ -86,19 +86,12 @@ False ..\..\..\Release\net40\Accord.Statistics.dll - - False - ..\..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Math.dll - 3.5 + @@ -139,6 +132,9 @@ + + PreserveNewest + diff --git a/Samples/MachineLearning/Clustering (GMM)/Accord.dll.config b/Samples/MachineLearning/Clustering (GMM)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/MachineLearning/Clustering (GMM)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/MachineLearning/Clustering (GMM)/Clustering (GMMs).csproj b/Samples/MachineLearning/Clustering (GMM)/Clustering (GMMs).csproj index 17c85fea8..0a5f77db2 100644 --- a/Samples/MachineLearning/Clustering (GMM)/Clustering (GMMs).csproj +++ b/Samples/MachineLearning/Clustering (GMM)/Clustering (GMMs).csproj @@ -1,186 +1,181 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {6EE43C30-5232-4B18-802B-7D536EA4DCCE} - WinExe - Properties - Clustering.GMMs - Clustering %28GMMs%29 - v4.0 - 512 - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - AllRules.ruleset - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - AllRules.ruleset - - - true - bin\x86\Debug\ - DEBUG;TRACE - full - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - bin\x86\Release\ - TRACE - true - pdbonly - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - framework.ico - - - - False - ..\..\..\Release\net40\Accord.dll - - - False - ..\..\..\Release\net40\Accord.Controls.dll - - - False - ..\..\..\Release\net40\Accord.MachineLearning.dll - - - False - ..\..\..\Release\net40\Accord.Math.dll - - - False - ..\..\..\Release\net40\Accord.Statistics.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Math.dll - - - - 3.5 - - - 3.5 - - - 3.5 - - - - - - - - False - ..\..\..\Externals\ZedGraph\ZedGraph.dll - - - - - Form - - - MainForm.cs - - - - - MainForm.cs - Designer - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - - - - + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {6EE43C30-5232-4B18-802B-7D536EA4DCCE} + WinExe + Properties + Clustering.GMMs + Clustering %28GMMs%29 + v4.0 + 512 + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + AllRules.ruleset + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + AllRules.ruleset + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + framework.ico + + + + False + ..\..\..\Release\net40\Accord.dll + + + False + ..\..\..\Release\net40\Accord.Controls.dll + + + False + ..\..\..\Release\net40\Accord.MachineLearning.dll + + + False + ..\..\..\Release\net40\Accord.Math.dll + + + False + ..\..\..\Release\net40\Accord.Statistics.dll + + + + 3.5 + + + 3.5 + + + + + + + False + ..\..\..\Externals\ZedGraph\ZedGraph.dll + + + + + Form + + + MainForm.cs + + + + + MainForm.cs + Designer + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + --> \ No newline at end of file diff --git a/Samples/MachineLearning/Clustering (K-Means)/Accord.dll.config b/Samples/MachineLearning/Clustering (K-Means)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/MachineLearning/Clustering (K-Means)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/MachineLearning/Clustering (K-Means)/Clustering (K-Means, MeanShift).csproj b/Samples/MachineLearning/Clustering (K-Means)/Clustering (K-Means, MeanShift).csproj index f386421d1..e29e7240f 100644 --- a/Samples/MachineLearning/Clustering (K-Means)/Clustering (K-Means, MeanShift).csproj +++ b/Samples/MachineLearning/Clustering (K-Means)/Clustering (K-Means, MeanShift).csproj @@ -1,185 +1,180 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {8433F722-C197-4BCD-9E5D-08A6B2FAF23A} - WinExe - Properties - Clustering.K_Means - Clustering %28K-Means%29 - v4.0 - 512 - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - AllRules.ruleset - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - AllRules.ruleset - - - true - bin\x86\Debug\ - DEBUG;TRACE - full - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - bin\x86\Release\ - TRACE - true - pdbonly - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - framework.ico - - - - False - ..\..\..\Release\net40\Accord.dll - - - False - ..\..\..\Release\net40\Accord.Imaging.dll - - - False - ..\..\..\Release\net40\Accord.MachineLearning.dll - - - False - ..\..\..\Release\net40\Accord.Math.dll - - - False - ..\..\..\Release\net40\Accord.Statistics.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Imaging.dll - - - - 3.5 - - - 3.5 - - - 3.5 - - - - - - - - - - Form - - - MainForm.cs - - - - - MainForm.cs - Designer - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - - - - + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {8433F722-C197-4BCD-9E5D-08A6B2FAF23A} + WinExe + Properties + Clustering.K_Means + Clustering %28K-Means%29 + v4.0 + 512 + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + AllRules.ruleset + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + AllRules.ruleset + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + framework.ico + + + + False + ..\..\..\Release\net40\Accord.dll + + + False + ..\..\..\Release\net40\Accord.Imaging.dll + + + False + ..\..\..\Release\net40\Accord.MachineLearning.dll + + + False + ..\..\..\Release\net40\Accord.Math.dll + + + False + ..\..\..\Release\net40\Accord.Statistics.dll + + + + 3.5 + + + 3.5 + + + + + + + + + Form + + + MainForm.cs + + + + + MainForm.cs + Designer + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + --> \ No newline at end of file diff --git a/Samples/MachineLearning/Decision Trees/Accord.dll.config b/Samples/MachineLearning/Decision Trees/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/MachineLearning/Decision Trees/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/MachineLearning/Decision Trees/Decision Trees.csproj b/Samples/MachineLearning/Decision Trees/Decision Trees.csproj index 5c99a8e7d..5ee3952cc 100644 --- a/Samples/MachineLearning/Decision Trees/Decision Trees.csproj +++ b/Samples/MachineLearning/Decision Trees/Decision Trees.csproj @@ -62,21 +62,12 @@ False ..\..\..\Release\net40\Accord.Statistics.dll - - False - ..\..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Math.dll - + - - @@ -123,6 +114,9 @@ TableSelectDialog.cs + + PreserveNewest + diff --git a/Samples/MachineLearning/Feature Selection (SVMs)/Accord.dll.config b/Samples/MachineLearning/Feature Selection (SVMs)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/MachineLearning/Feature Selection (SVMs)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/MachineLearning/Feature Selection (SVMs)/Feature Selection (SVMs).csproj b/Samples/MachineLearning/Feature Selection (SVMs)/Feature Selection (SVMs).csproj index a52d68cd1..779a40091 100644 --- a/Samples/MachineLearning/Feature Selection (SVMs)/Feature Selection (SVMs).csproj +++ b/Samples/MachineLearning/Feature Selection (SVMs)/Feature Selection (SVMs).csproj @@ -89,19 +89,12 @@ False ..\..\..\Release\net40\Accord.Statistics.dll - - False - ..\..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Math.dll - 3.5 + @@ -142,6 +135,9 @@ + + PreserveNewest + diff --git a/Samples/MachineLearning/Fitting (RANSAC)/Accord.dll.config b/Samples/MachineLearning/Fitting (RANSAC)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/MachineLearning/Fitting (RANSAC)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/MachineLearning/Fitting (RANSAC)/Fitting (RANSAC).csproj b/Samples/MachineLearning/Fitting (RANSAC)/Fitting (RANSAC).csproj index 52b5fed8a..c525816b9 100644 --- a/Samples/MachineLearning/Fitting (RANSAC)/Fitting (RANSAC).csproj +++ b/Samples/MachineLearning/Fitting (RANSAC)/Fitting (RANSAC).csproj @@ -78,16 +78,13 @@ False ..\..\..\Release\net40\Accord.Statistics.dll - - False - ..\..\..\Externals\AForge.NET\AForge.Math.dll - 3.5 + @@ -133,6 +130,9 @@ TableSelectDialog.cs + + PreserveNewest + SettingsSingleFileGenerator Settings.Designer.cs diff --git a/Samples/MachineLearning/Gestures (SVMs)/Accord.dll.config b/Samples/MachineLearning/Gestures (SVMs)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/MachineLearning/Gestures (SVMs)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/MachineLearning/Gestures (SVMs)/Gestures (SVM-DTW).csproj b/Samples/MachineLearning/Gestures (SVMs)/Gestures (SVM-DTW).csproj index f13d688c9..2ac333fcf 100644 --- a/Samples/MachineLearning/Gestures (SVMs)/Gestures (SVM-DTW).csproj +++ b/Samples/MachineLearning/Gestures (SVMs)/Gestures (SVM-DTW).csproj @@ -1,200 +1,180 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {7F23856B-B95C-42B3-B6AF-663FA35324D6} - WinExe - Properties - Gestures.SVMs - Gestures %28SVM-DTW%29 - v4.0 - 512 - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - AllRules.ruleset - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - AllRules.ruleset - - - true - bin\x86\Debug\ - DEBUG;TRACE - full - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - bin\x86\Release\ - TRACE - true - pdbonly - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - framework.ico - - - - False - ..\..\..\Release\net40\Accord.dll - - - False - ..\..\..\Release\net40\Accord.MachineLearning.dll - - - False - ..\..\..\Release\net40\Accord.Math.dll - - - False - ..\..\..\Release\net40\Accord.Statistics.dll - - - - - 3.5 - - - 3.5 - - - 3.5 - - - - - - - - False - ..\..\..\Externals\ZedGraph\ZedGraph.dll - - - - - UserControl - - - Canvas.cs - - - - Form - - - MainForm.cs - - - - - - - - Canvas.cs - Designer - - - MainForm.cs - Designer - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - - - - - PreserveNewest - - - PreserveNewest - - - + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {7F23856B-B95C-42B3-B6AF-663FA35324D6} + WinExe + Properties + Gestures.SVMs + Gestures %28SVM-DTW%29 + v4.0 + 512 + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + framework.ico + + + + False + ..\..\..\Release\net40\Accord.dll + + + False + ..\..\..\Release\net40\Accord.MachineLearning.dll + + + False + ..\..\..\Release\net40\Accord.Math.dll + + + False + ..\..\..\Release\net40\Accord.Statistics.dll + + + + + 3.5 + + + 3.5 + + + + + + + False + ..\..\..\Externals\ZedGraph\ZedGraph.dll + + + + + UserControl + + + Canvas.cs + + + + Form + + + MainForm.cs + + + + + + + + Canvas.cs + Designer + + + MainForm.cs + Designer + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + PreserveNewest + + + PreserveNewest + + + + --> \ No newline at end of file diff --git a/Samples/MachineLearning/Handwriting (SVMs)/Accord.dll.config b/Samples/MachineLearning/Handwriting (SVMs)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/MachineLearning/Handwriting (SVMs)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/MachineLearning/Handwriting (SVMs)/Handwriting (SVM).csproj b/Samples/MachineLearning/Handwriting (SVMs)/Handwriting (SVM).csproj index cfa04eb31..d5c1d4b9e 100644 --- a/Samples/MachineLearning/Handwriting (SVMs)/Handwriting (SVM).csproj +++ b/Samples/MachineLearning/Handwriting (SVMs)/Handwriting (SVM).csproj @@ -77,13 +77,6 @@ False ..\..\..\Release\net40\Accord.Statistics.dll - - False - ..\..\..\Externals\AForge.NET\AForge.dll - - - ..\..\..\Externals\AForge.NET\AForge.Math.dll - 3.5 @@ -129,6 +122,9 @@ Resources.resx True + + PreserveNewest + diff --git a/Samples/MachineLearning/Liblinear (SVMs)/Accord.dll.config b/Samples/MachineLearning/Liblinear (SVMs)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/MachineLearning/Liblinear (SVMs)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/MachineLearning/Liblinear (SVMs)/Liblinear (Linear SVMs).csproj b/Samples/MachineLearning/Liblinear (SVMs)/Liblinear (Linear SVMs).csproj index 9010d2358..2b5d7ec51 100644 --- a/Samples/MachineLearning/Liblinear (SVMs)/Liblinear (Linear SVMs).csproj +++ b/Samples/MachineLearning/Liblinear (SVMs)/Liblinear (Linear SVMs).csproj @@ -1,94 +1,97 @@ - - - - Debug - x86 - 8.0.30703 - 2.0 - {1E055676-77A0-4C5B-B449-FF58CA5066E0} - Exe - Properties - Liblinear - linear - v4.0 - - - 512 - - - x86 - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - x86 - pdbonly - true - bin\x86\Release\ - TRACE - prompt - 4 - - - Liblinear.Train - - - - False - ..\..\..\Release\net40\Accord.dll - - - ..\..\..\Release\net40\Accord.IO.dll - - - False - ..\..\..\Release\net40\Accord.MachineLearning.dll - - - False - ..\..\..\Release\net40\Accord.Math.dll - - - False - ..\..\..\Release\net40\Accord.Statistics.dll - - - - - - - - - - - - - - - - - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - + + + + Debug + x86 + 8.0.30703 + 2.0 + {1E055676-77A0-4C5B-B449-FF58CA5066E0} + Exe + Properties + Liblinear + linear + v4.0 + + + 512 + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + bin\x86\Release\ + TRACE + prompt + 4 + + + Liblinear.Train + + + + False + ..\..\..\Release\net40\Accord.dll + + + ..\..\..\Release\net40\Accord.IO.dll + + + False + ..\..\..\Release\net40\Accord.MachineLearning.dll + + + False + ..\..\..\Release\net40\Accord.Math.dll + + + False + ..\..\..\Release\net40\Accord.Statistics.dll + + + + + + + + + + + + + + + + + + PreserveNewest + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + --> \ No newline at end of file diff --git a/Samples/MachineLearning/Naive Bayes/Accord.dll.config b/Samples/MachineLearning/Naive Bayes/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/MachineLearning/Naive Bayes/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/MachineLearning/Naive Bayes/MainForm.cs b/Samples/MachineLearning/Naive Bayes/MainForm.cs index 450cc4811..f04591a5e 100644 --- a/Samples/MachineLearning/Naive Bayes/MainForm.cs +++ b/Samples/MachineLearning/Naive Bayes/MainForm.cs @@ -122,13 +122,15 @@ private void btnCreate_Click(object sender, EventArgs e) var y2 = bayes.Distributions[1, 1].Generate(1000); // Combine in a single graph - var w1 = Matrix.Stack(x1, y1).Transpose(); - var w2 = Matrix.Stack(x2, y2).Transpose(); + double[,] w1 = Matrix.Stack(x1, y1).Transpose(); + double[,] w2 = Matrix.Stack(x2, y2).Transpose(); - var z = Matrix.Vector(2000, value: 1.0); - for (int i = 0; i < 1000; i++) z[i] = 0; + double[] z = Matrix.Vector(2000, value: 1.0); + for (int i = 0; i < 1000; i++) + z[i] = 0; - var graph = Matrix.Stack(w1, w2).Concatenate(z); + var a = Matrix.Stack(new double[][,] { w1, w2 }); + var graph = a.Concatenate(z); CreateScatterplot(zedGraphControl2, graph); diff --git a/Samples/MachineLearning/Naive Bayes/Naive Bayes.csproj b/Samples/MachineLearning/Naive Bayes/Naive Bayes.csproj index d8657522f..8ec3bd290 100644 --- a/Samples/MachineLearning/Naive Bayes/Naive Bayes.csproj +++ b/Samples/MachineLearning/Naive Bayes/Naive Bayes.csproj @@ -62,21 +62,12 @@ False ..\..\..\Release\net40\Accord.Statistics.dll - - False - ..\..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Math.dll - + - - @@ -123,6 +114,9 @@ TableSelectDialog.cs + + PreserveNewest + diff --git a/Samples/MachineLearning/Regression (SVMs)/Accord.dll.config b/Samples/MachineLearning/Regression (SVMs)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/MachineLearning/Regression (SVMs)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/MachineLearning/Regression (SVMs)/Regression (SVMs).csproj b/Samples/MachineLearning/Regression (SVMs)/Regression (SVMs).csproj index 7d52fa3af..d38b9cbf5 100644 --- a/Samples/MachineLearning/Regression (SVMs)/Regression (SVMs).csproj +++ b/Samples/MachineLearning/Regression (SVMs)/Regression (SVMs).csproj @@ -65,50 +65,32 @@ - ..\..\packages\Accord.2.14.0\lib\net40\Accord.dll + ..\..\..\Release\net40\Accord.dll - - False - ..\..\packages\Accord.Controls.2.14.0\lib\net40\Accord.Controls.dll + + ..\..\..\Release\net40\Accord.Controls.dll - - ..\..\packages\Accord.Imaging.2.14.0\lib\net40\Accord.Imaging.dll + + ..\..\..\Release\net40\Accord.IO.dll - - False - ..\..\packages\Accord.IO.2.14.0\lib\net40\Accord.IO.dll + + ..\..\..\Release\net40\Accord.MachineLearning.dll - - False - ..\..\packages\Accord.MachineLearning.2.14.0\lib\net40\Accord.MachineLearning.dll - - - False - ..\..\packages\Accord.MachineLearning.GPL.2.14.0\lib\net40\Accord.MachineLearning.GPL.dll + + ..\..\..\Release\net40\GPL\Accord.MachineLearning.GPL.dll - ..\..\packages\Accord.Math.2.14.0\lib\net40\Accord.Math.dll - - - False - ..\..\packages\Accord.Statistics.2.14.0\lib\net40\Accord.Statistics.dll - - - False - ..\..\packages\AForge.2.2.5\lib\AForge.dll + ..\..\..\Release\net40\Accord.Math.dll - - ..\..\packages\AForge.Imaging.2.2.5\lib\AForge.Imaging.dll - - - False - ..\..\packages\AForge.Math.2.2.5\lib\AForge.Math.dll + + ..\..\..\Release\net40\Accord.Statistics.dll 3.5 + @@ -139,6 +121,10 @@ + + PreserveNewest + + PreserveNewest diff --git a/Samples/Statistics/Tabular filters/app.config b/Samples/MachineLearning/Regression (SVMs)/app.config similarity index 100% rename from Samples/Statistics/Tabular filters/app.config rename to Samples/MachineLearning/Regression (SVMs)/app.config diff --git a/Samples/MachineLearning/Regression (SVMs)/packages.config b/Samples/MachineLearning/Regression (SVMs)/packages.config index 3da7118a1..eb764e066 100644 --- a/Samples/MachineLearning/Regression (SVMs)/packages.config +++ b/Samples/MachineLearning/Regression (SVMs)/packages.config @@ -1,15 +1,4 @@  - - - - - - - - - - - \ No newline at end of file diff --git a/Samples/Math/Kinematics/Accord.dll.config b/Samples/Math/Kinematics/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Math/Kinematics/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Math/Kinematics/Kinematics.csproj b/Samples/Math/Kinematics/Kinematics.csproj index 6f32fd9a4..58ca84736 100644 --- a/Samples/Math/Kinematics/Kinematics.csproj +++ b/Samples/Math/Kinematics/Kinematics.csproj @@ -1,112 +1,110 @@ - - - - Debug - x86 - 8.0.30703 - 2.0 - {3B1150A4-A32C-4B2F-8BC1-14FDB5C4FDEE} - WinExe - Properties - DenavitKinematics - Denavit Hartenberg - v4.0 - Client - 512 - - - x86 - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - x86 - pdbonly - true - bin\x86\Release\ - TRACE - prompt - 4 - - - framework.ico - - - - False - ..\..\..\Release\net40\Accord.dll - - - False - ..\..\..\Release\net40\Accord.Controls.dll - - - False - ..\..\..\Release\net40\Accord.Math.dll - - - ..\..\..\Externals\AForge.NET\AForge.dll - - - ..\..\..\Externals\AForge.NET\AForge.Math.dll - - - - - - - - - - - - - - - Form - - - MainForm.cs - - - - - MainForm.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - + + + + Debug + x86 + 8.0.30703 + 2.0 + {3B1150A4-A32C-4B2F-8BC1-14FDB5C4FDEE} + WinExe + Properties + SampleApp + Denavit Hartenberg + v4.0 + Client + 512 + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + bin\x86\Release\ + TRACE + prompt + 4 + + + framework.ico + + + SampleApp.Program + + + + False + ..\..\..\Release\net40\Accord.dll + + + False + ..\..\..\Release\net40\Accord.Controls.dll + + + False + ..\..\..\Release\net40\Accord.Math.dll + + + + + + + + + + + + + Form + + + MainForm.cs + + + + + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + --> \ No newline at end of file diff --git a/Samples/Math/Kinematics/MainForm.Designer.cs b/Samples/Math/Kinematics/MainForm.Designer.cs index 013553afd..c287db0c4 100644 --- a/Samples/Math/Kinematics/MainForm.Designer.cs +++ b/Samples/Math/Kinematics/MainForm.Designer.cs @@ -1,33 +1,33 @@ -namespace DenavitKinematics -{ - partial class MainForm - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { this.components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); this.pictureBox1 = new System.Windows.Forms.PictureBox(); @@ -111,16 +111,16 @@ private void InitializeComponent() this.ResumeLayout(false); this.PerformLayout(); - } - - #endregion - - private System.Windows.Forms.PictureBox pictureBox1; - private System.Windows.Forms.PictureBox pictureBox2; - private System.Windows.Forms.PictureBox pictureBox3; - private System.Windows.Forms.Timer timer1; - private System.Windows.Forms.Button button1; - private System.Windows.Forms.Label label1; - } -} - + } + + #endregion + + private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.PictureBox pictureBox2; + private System.Windows.Forms.PictureBox pictureBox3; + private System.Windows.Forms.Timer timer1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Label label1; + } +} + diff --git a/Samples/Math/Kinematics/MainForm.cs b/Samples/Math/Kinematics/MainForm.cs index 301c2acaa..24fd3e1ed 100644 --- a/Samples/Math/Kinematics/MainForm.cs +++ b/Samples/Math/Kinematics/MainForm.cs @@ -39,7 +39,7 @@ using Accord.Math.Kinematics; using AForge.Math; -namespace DenavitKinematics +namespace SampleApp { /// /// Denavit-Hartenberg models for kinematic chains. diff --git a/Samples/Math/Kinematics/Program.cs b/Samples/Math/Kinematics/Program.cs index 927a93807..316268492 100644 --- a/Samples/Math/Kinematics/Program.cs +++ b/Samples/Math/Kinematics/Program.cs @@ -1,7 +1,7 @@ using System; using System.Windows.Forms; -namespace DenavitKinematics +namespace SampleApp { static class Program { diff --git a/Samples/Math/Kinematics/Properties/Resources.Designer.cs b/Samples/Math/Kinematics/Properties/Resources.Designer.cs index 051eff601..7b58e53ee 100644 --- a/Samples/Math/Kinematics/Properties/Resources.Designer.cs +++ b/Samples/Math/Kinematics/Properties/Resources.Designer.cs @@ -1,63 +1,63 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.18052 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace DenavitKinematics.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DenavitKinematics.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Samples/Math/Kinematics/Properties/Settings.Designer.cs b/Samples/Math/Kinematics/Properties/Settings.Designer.cs index 74ba070c0..dbc9e5d22 100644 --- a/Samples/Math/Kinematics/Properties/Settings.Designer.cs +++ b/Samples/Math/Kinematics/Properties/Settings.Designer.cs @@ -1,26 +1,26 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.18052 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace DenavitKinematics.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Samples/Math/Matrices/Accord.dll.config b/Samples/Math/Matrices/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Math/Matrices/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Math/Matrices/Matrices.csproj b/Samples/Math/Matrices/Matrices.csproj index f237842b1..068378e72 100644 --- a/Samples/Math/Matrices/Matrices.csproj +++ b/Samples/Math/Matrices/Matrices.csproj @@ -1,138 +1,140 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {DB8C60E0-D225-4DBB-917A-12EA86506A13} - Exe - Properties - Matrices - Matrices - v4.0 - 512 - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - AllRules.ruleset - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - AllRules.ruleset - - - true - bin\x86\Debug\ - DEBUG;TRACE - full - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - bin\x86\Release\ - TRACE - true - pdbonly - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - framework.ico - - - - False - ..\..\..\Release\net40\Accord.dll - - - False - ..\..\..\Release\net40\Accord.Math.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Math.dll - - - - 3.5 - - - 3.5 - - - 3.5 - - - - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - - - - + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {DB8C60E0-D225-4DBB-917A-12EA86506A13} + Exe + Properties + SampleApp + Matrices + v4.0 + 512 + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + AllRules.ruleset + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + AllRules.ruleset + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + framework.ico + + + + False + ..\..\..\Release\net40\Accord.dll + + + False + ..\..\..\Release\net40\Accord.Math.dll + + + + 3.5 + + + + 3.5 + + + 3.5 + + + + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + + PreserveNewest + + + + --> \ No newline at end of file diff --git a/Samples/Math/Pose Coordinates (POSIT)/Accord.dll.config b/Samples/Math/Pose Coordinates (POSIT)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Math/Pose Coordinates (POSIT)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Math/Pose Coordinates (POSIT)/MainForm.Designer.cs b/Samples/Math/Pose Coordinates (POSIT)/MainForm.Designer.cs new file mode 100644 index 0000000000..4468801b7 --- /dev/null +++ b/Samples/Math/Pose Coordinates (POSIT)/MainForm.Designer.cs @@ -0,0 +1,1045 @@ +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.label1 = new System.Windows.Forms.Label(); + this.yawBox = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.pitchBox = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.rollBox = new System.Windows.Forms.TextBox(); + this.groupBox4 = new System.Windows.Forms.GroupBox(); + this.label10 = new System.Windows.Forms.Label(); + this.zObjectBox = new System.Windows.Forms.TextBox(); + this.label11 = new System.Windows.Forms.Label(); + this.yObjectBox = new System.Windows.Forms.TextBox(); + this.label12 = new System.Windows.Forms.Label(); + this.xObjectBox = new System.Windows.Forms.TextBox(); + this.toolTip = new System.Windows.Forms.ToolTip(this.components); + this.label17 = new System.Windows.Forms.Label(); + this.label18 = new System.Windows.Forms.Label(); + this.label19 = new System.Windows.Forms.Label(); + this.targetTransformationMatrixControl = new SampleApp.MatrixControl(); + this.errorProvider = new System.Windows.Forms.ErrorProvider(this.components); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.label7 = new System.Windows.Forms.Label(); + this.zLookAtBox = new System.Windows.Forms.TextBox(); + this.label8 = new System.Windows.Forms.Label(); + this.yLookAtBox = new System.Windows.Forms.TextBox(); + this.label9 = new System.Windows.Forms.Label(); + this.xLookAtBox = new System.Windows.Forms.TextBox(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.label6 = new System.Windows.Forms.Label(); + this.zCameraBox = new System.Windows.Forms.TextBox(); + this.label5 = new System.Windows.Forms.Label(); + this.yCameraBox = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.xCameraBox = new System.Windows.Forms.TextBox(); + this.groupBox5 = new System.Windows.Forms.GroupBox(); + this.worldRendererControl = new SampleApp.WorldRendererControl(); + this.groupBox6 = new System.Windows.Forms.GroupBox(); + this.objectPoint4ColorLabel = new System.Windows.Forms.Label(); + this.objectPoint3ColorLabel = new System.Windows.Forms.Label(); + this.objectPoint2ColorLabel = new System.Windows.Forms.Label(); + this.objectPoint1ColorLabel = new System.Windows.Forms.Label(); + this.objectPoint4Box = new System.Windows.Forms.TextBox(); + this.label16 = new System.Windows.Forms.Label(); + this.objectPoint3Box = new System.Windows.Forms.TextBox(); + this.label15 = new System.Windows.Forms.Label(); + this.objectPoint2Box = new System.Windows.Forms.TextBox(); + this.label14 = new System.Windows.Forms.Label(); + this.objectPoint1Box = new System.Windows.Forms.TextBox(); + this.label13 = new System.Windows.Forms.Label(); + this.objectTypeCombo = new System.Windows.Forms.ComboBox(); + this.groupBox7 = new System.Windows.Forms.GroupBox(); + this.screenPoint4ColorLabel = new System.Windows.Forms.Label(); + this.screenPoint3ColorLabel = new System.Windows.Forms.Label(); + this.screenPoint2ColorLabel = new System.Windows.Forms.Label(); + this.screenPoint1ColorLabel = new System.Windows.Forms.Label(); + this.screenPoint4Box = new System.Windows.Forms.TextBox(); + this.label21 = new System.Windows.Forms.Label(); + this.screenPoint3Box = new System.Windows.Forms.TextBox(); + this.label22 = new System.Windows.Forms.Label(); + this.screenPoint2Box = new System.Windows.Forms.TextBox(); + this.label23 = new System.Windows.Forms.Label(); + this.screenPoint1Box = new System.Windows.Forms.TextBox(); + this.label24 = new System.Windows.Forms.Label(); + this.groupBox8 = new System.Windows.Forms.GroupBox(); + this.label20 = new System.Windows.Forms.Label(); + this.estimatedZObjectBox = new System.Windows.Forms.TextBox(); + this.label25 = new System.Windows.Forms.Label(); + this.estimatedYObjectBox = new System.Windows.Forms.TextBox(); + this.label26 = new System.Windows.Forms.Label(); + this.estimatedXObjectBox = new System.Windows.Forms.TextBox(); + this.estimatedYawBox = new System.Windows.Forms.TextBox(); + this.estimatedPitchBox = new System.Windows.Forms.TextBox(); + this.estimatedRollBox = new System.Windows.Forms.TextBox(); + this.estimatedTransformationMatrixControl = new SampleApp.MatrixControl(); + this.viewMatrixControl = new SampleApp.MatrixControl(); + this.transformationMatrixControl = new SampleApp.MatrixControl(); + this.groupBox2.SuspendLayout(); + this.groupBox4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit(); + this.groupBox3.SuspendLayout(); + this.groupBox1.SuspendLayout(); + this.groupBox5.SuspendLayout(); + this.groupBox6.SuspendLayout(); + this.groupBox7.SuspendLayout(); + this.groupBox8.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.label1); + this.groupBox2.Controls.Add(this.yawBox); + this.groupBox2.Controls.Add(this.label2); + this.groupBox2.Controls.Add(this.pitchBox); + this.groupBox2.Controls.Add(this.label3); + this.groupBox2.Controls.Add(this.rollBox); + this.groupBox2.Location = new System.Drawing.Point(15, 115); + this.groupBox2.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox2.Size = new System.Drawing.Size(562, 77); + this.groupBox2.TabIndex = 1; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Object Rotation"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(15, 35); + this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(65, 20); + this.label1.TabIndex = 0; + this.label1.Text = "Yaw (y):"; + this.toolTip.SetToolTip(this.label1, "Rotation around Y axis"); + // + // yawBox + // + this.yawBox.Location = new System.Drawing.Point(90, 31); + this.yawBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.yawBox.Name = "yawBox"; + this.yawBox.Size = new System.Drawing.Size(88, 26); + this.yawBox.TabIndex = 1; + this.yawBox.TextChanged += new System.EventHandler(this.yawBox_TextChanged); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(195, 35); + this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(69, 20); + this.label2.TabIndex = 2; + this.label2.Text = "Pitch (x):"; + this.toolTip.SetToolTip(this.label2, "Rotation around X axis"); + // + // pitchBox + // + this.pitchBox.Location = new System.Drawing.Point(270, 31); + this.pitchBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.pitchBox.Name = "pitchBox"; + this.pitchBox.Size = new System.Drawing.Size(88, 26); + this.pitchBox.TabIndex = 3; + this.pitchBox.TextChanged += new System.EventHandler(this.pitchBox_TextChanged); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(375, 35); + this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(62, 20); + this.label3.TabIndex = 4; + this.label3.Text = "Roll (z):"; + this.toolTip.SetToolTip(this.label3, "Rotation around Z axis"); + // + // rollBox + // + this.rollBox.Location = new System.Drawing.Point(442, 31); + this.rollBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.rollBox.Name = "rollBox"; + this.rollBox.Size = new System.Drawing.Size(88, 26); + this.rollBox.TabIndex = 5; + this.rollBox.TextChanged += new System.EventHandler(this.rollBox_TextChanged); + // + // groupBox4 + // + this.groupBox4.Controls.Add(this.label10); + this.groupBox4.Controls.Add(this.zObjectBox); + this.groupBox4.Controls.Add(this.label11); + this.groupBox4.Controls.Add(this.yObjectBox); + this.groupBox4.Controls.Add(this.label12); + this.groupBox4.Controls.Add(this.xObjectBox); + this.groupBox4.Location = new System.Drawing.Point(15, 208); + this.groupBox4.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox4.Name = "groupBox4"; + this.groupBox4.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox4.Size = new System.Drawing.Size(562, 77); + this.groupBox4.TabIndex = 2; + this.groupBox4.TabStop = false; + this.groupBox4.Text = "Object Position"; + // + // label10 + // + this.label10.AutoSize = true; + this.label10.Location = new System.Drawing.Point(408, 35); + this.label10.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(23, 20); + this.label10.TabIndex = 4; + this.label10.Text = "Z:"; + // + // zObjectBox + // + this.zObjectBox.Location = new System.Drawing.Point(442, 31); + this.zObjectBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.zObjectBox.Name = "zObjectBox"; + this.zObjectBox.Size = new System.Drawing.Size(88, 26); + this.zObjectBox.TabIndex = 5; + this.zObjectBox.TextChanged += new System.EventHandler(this.zObjectBox_TextChanged); + // + // label11 + // + this.label11.AutoSize = true; + this.label11.Location = new System.Drawing.Point(236, 35); + this.label11.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(24, 20); + this.label11.TabIndex = 2; + this.label11.Text = "Y:"; + // + // yObjectBox + // + this.yObjectBox.Location = new System.Drawing.Point(270, 31); + this.yObjectBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.yObjectBox.Name = "yObjectBox"; + this.yObjectBox.Size = new System.Drawing.Size(88, 26); + this.yObjectBox.TabIndex = 3; + this.yObjectBox.TextChanged += new System.EventHandler(this.yObjectBox_TextChanged); + // + // label12 + // + this.label12.AutoSize = true; + this.label12.Location = new System.Drawing.Point(60, 35); + this.label12.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label12.Name = "label12"; + this.label12.Size = new System.Drawing.Size(24, 20); + this.label12.TabIndex = 0; + this.label12.Text = "X:"; + // + // xObjectBox + // + this.xObjectBox.Location = new System.Drawing.Point(90, 31); + this.xObjectBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.xObjectBox.Name = "xObjectBox"; + this.xObjectBox.Size = new System.Drawing.Size(88, 26); + this.xObjectBox.TabIndex = 1; + this.xObjectBox.TextChanged += new System.EventHandler(this.xObjectBox_TextChanged); + // + // toolTip + // + this.toolTip.AutoPopDelay = 5000; + this.toolTip.InitialDelay = 100; + this.toolTip.ReshowDelay = 100; + // + // label17 + // + this.label17.AutoSize = true; + this.label17.Location = new System.Drawing.Point(15, 35); + this.label17.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label17.Name = "label17"; + this.label17.Size = new System.Drawing.Size(65, 20); + this.label17.TabIndex = 31; + this.label17.Text = "Yaw (y):"; + this.toolTip.SetToolTip(this.label17, "Rotation around Y axis"); + // + // label18 + // + this.label18.AutoSize = true; + this.label18.Location = new System.Drawing.Point(195, 35); + this.label18.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label18.Name = "label18"; + this.label18.Size = new System.Drawing.Size(69, 20); + this.label18.TabIndex = 33; + this.label18.Text = "Pitch (x):"; + this.toolTip.SetToolTip(this.label18, "Rotation around X axis"); + // + // label19 + // + this.label19.AutoSize = true; + this.label19.Location = new System.Drawing.Point(375, 35); + this.label19.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label19.Name = "label19"; + this.label19.Size = new System.Drawing.Size(62, 20); + this.label19.TabIndex = 35; + this.label19.Text = "Roll (z):"; + this.toolTip.SetToolTip(this.label19, "Rotation around Z axis"); + // + // targetTransformationMatrixControl + // + this.targetTransformationMatrixControl.Location = new System.Drawing.Point(915, 23); + this.targetTransformationMatrixControl.Margin = new System.Windows.Forms.Padding(6, 8, 6, 8); + this.targetTransformationMatrixControl.Name = "targetTransformationMatrixControl"; + this.targetTransformationMatrixControl.Size = new System.Drawing.Size(330, 169); + this.targetTransformationMatrixControl.TabIndex = 37; + this.targetTransformationMatrixControl.Title = "Target Transformation"; + this.toolTip.SetToolTip(this.targetTransformationMatrixControl, "The matrix shows target transformation which View Matrix multiplies with World Tr" + + "ansformation Matrix"); + // + // errorProvider + // + this.errorProvider.ContainerControl = this; + // + // groupBox3 + // + this.groupBox3.Controls.Add(this.label7); + this.groupBox3.Controls.Add(this.zLookAtBox); + this.groupBox3.Controls.Add(this.label8); + this.groupBox3.Controls.Add(this.yLookAtBox); + this.groupBox3.Controls.Add(this.label9); + this.groupBox3.Controls.Add(this.xLookAtBox); + this.groupBox3.Location = new System.Drawing.Point(15, 392); + this.groupBox3.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox3.Size = new System.Drawing.Size(562, 77); + this.groupBox3.TabIndex = 4; + this.groupBox3.TabStop = false; + this.groupBox3.Text = "Look At"; + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point(408, 35); + this.label7.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(23, 20); + this.label7.TabIndex = 4; + this.label7.Text = "Z:"; + // + // zLookAtBox + // + this.zLookAtBox.Location = new System.Drawing.Point(442, 31); + this.zLookAtBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.zLookAtBox.Name = "zLookAtBox"; + this.zLookAtBox.Size = new System.Drawing.Size(88, 26); + this.zLookAtBox.TabIndex = 5; + this.zLookAtBox.TextChanged += new System.EventHandler(this.zLookAtBox_TextChanged); + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point(236, 35); + this.label8.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(24, 20); + this.label8.TabIndex = 2; + this.label8.Text = "Y:"; + // + // yLookAtBox + // + this.yLookAtBox.Location = new System.Drawing.Point(270, 31); + this.yLookAtBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.yLookAtBox.Name = "yLookAtBox"; + this.yLookAtBox.Size = new System.Drawing.Size(88, 26); + this.yLookAtBox.TabIndex = 3; + this.yLookAtBox.TextChanged += new System.EventHandler(this.yLookAtBox_TextChanged); + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Location = new System.Drawing.Point(60, 35); + this.label9.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(24, 20); + this.label9.TabIndex = 0; + this.label9.Text = "X:"; + // + // xLookAtBox + // + this.xLookAtBox.Location = new System.Drawing.Point(90, 31); + this.xLookAtBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.xLookAtBox.Name = "xLookAtBox"; + this.xLookAtBox.Size = new System.Drawing.Size(88, 26); + this.xLookAtBox.TabIndex = 1; + this.xLookAtBox.TextChanged += new System.EventHandler(this.xLookAtBox_TextChanged); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.label6); + this.groupBox1.Controls.Add(this.zCameraBox); + this.groupBox1.Controls.Add(this.label5); + this.groupBox1.Controls.Add(this.yCameraBox); + this.groupBox1.Controls.Add(this.label4); + this.groupBox1.Controls.Add(this.xCameraBox); + this.groupBox1.Location = new System.Drawing.Point(15, 300); + this.groupBox1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox1.Size = new System.Drawing.Size(562, 77); + this.groupBox1.TabIndex = 3; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Camera Position"; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(408, 35); + this.label6.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(23, 20); + this.label6.TabIndex = 4; + this.label6.Text = "Z:"; + // + // zCameraBox + // + this.zCameraBox.Location = new System.Drawing.Point(442, 31); + this.zCameraBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.zCameraBox.Name = "zCameraBox"; + this.zCameraBox.Size = new System.Drawing.Size(88, 26); + this.zCameraBox.TabIndex = 5; + this.zCameraBox.TextChanged += new System.EventHandler(this.zCameraBox_TextChanged); + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(236, 35); + this.label5.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(24, 20); + this.label5.TabIndex = 2; + this.label5.Text = "Y:"; + // + // yCameraBox + // + this.yCameraBox.Location = new System.Drawing.Point(270, 31); + this.yCameraBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.yCameraBox.Name = "yCameraBox"; + this.yCameraBox.Size = new System.Drawing.Size(88, 26); + this.yCameraBox.TabIndex = 3; + this.yCameraBox.TextChanged += new System.EventHandler(this.yCameraBox_TextChanged); + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(60, 35); + this.label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(24, 20); + this.label4.TabIndex = 0; + this.label4.Text = "X:"; + // + // xCameraBox + // + this.xCameraBox.Location = new System.Drawing.Point(90, 31); + this.xCameraBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.xCameraBox.Name = "xCameraBox"; + this.xCameraBox.Size = new System.Drawing.Size(88, 26); + this.xCameraBox.TabIndex = 1; + this.xCameraBox.TextChanged += new System.EventHandler(this.xCameraBox_TextChanged); + // + // groupBox5 + // + this.groupBox5.Controls.Add(this.worldRendererControl); + this.groupBox5.Location = new System.Drawing.Point(938, 115); + this.groupBox5.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox5.Name = "groupBox5"; + this.groupBox5.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox5.Size = new System.Drawing.Size(330, 354); + this.groupBox5.TabIndex = 7; + this.groupBox5.TabStop = false; + this.groupBox5.Text = "Object"; + // + // worldRendererControl + // + this.worldRendererControl.Location = new System.Drawing.Point(15, 28); + this.worldRendererControl.Margin = new System.Windows.Forms.Padding(6, 8, 6, 8); + this.worldRendererControl.Name = "worldRendererControl"; + this.worldRendererControl.Size = new System.Drawing.Size(300, 308); + this.worldRendererControl.TabIndex = 13; + this.worldRendererControl.ViewMatrix = ((AForge.Math.Matrix4x4)(resources.GetObject("worldRendererControl.ViewMatrix"))); + this.worldRendererControl.WorldMatrix = ((AForge.Math.Matrix4x4)(resources.GetObject("worldRendererControl.WorldMatrix"))); + // + // groupBox6 + // + this.groupBox6.Controls.Add(this.objectPoint4ColorLabel); + this.groupBox6.Controls.Add(this.objectPoint3ColorLabel); + this.groupBox6.Controls.Add(this.objectPoint2ColorLabel); + this.groupBox6.Controls.Add(this.objectPoint1ColorLabel); + this.groupBox6.Controls.Add(this.objectPoint4Box); + this.groupBox6.Controls.Add(this.label16); + this.groupBox6.Controls.Add(this.objectPoint3Box); + this.groupBox6.Controls.Add(this.label15); + this.groupBox6.Controls.Add(this.objectPoint2Box); + this.groupBox6.Controls.Add(this.label14); + this.groupBox6.Controls.Add(this.objectPoint1Box); + this.groupBox6.Controls.Add(this.label13); + this.groupBox6.Controls.Add(this.objectTypeCombo); + this.groupBox6.Location = new System.Drawing.Point(15, 15); + this.groupBox6.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox6.Name = "groupBox6"; + this.groupBox6.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox6.Size = new System.Drawing.Size(1252, 85); + this.groupBox6.TabIndex = 0; + this.groupBox6.TabStop = false; + this.groupBox6.Text = "Object"; + // + // objectPoint4ColorLabel + // + this.objectPoint4ColorLabel.BackColor = System.Drawing.Color.Black; + this.objectPoint4ColorLabel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.objectPoint4ColorLabel.Location = new System.Drawing.Point(1065, 62); + this.objectPoint4ColorLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.objectPoint4ColorLabel.Name = "objectPoint4ColorLabel"; + this.objectPoint4ColorLabel.Size = new System.Drawing.Size(172, 5); + this.objectPoint4ColorLabel.TabIndex = 27; + // + // objectPoint3ColorLabel + // + this.objectPoint3ColorLabel.BackColor = System.Drawing.Color.Black; + this.objectPoint3ColorLabel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.objectPoint3ColorLabel.Location = new System.Drawing.Point(802, 62); + this.objectPoint3ColorLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.objectPoint3ColorLabel.Name = "objectPoint3ColorLabel"; + this.objectPoint3ColorLabel.Size = new System.Drawing.Size(172, 5); + this.objectPoint3ColorLabel.TabIndex = 26; + // + // objectPoint2ColorLabel + // + this.objectPoint2ColorLabel.BackColor = System.Drawing.Color.Black; + this.objectPoint2ColorLabel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.objectPoint2ColorLabel.Location = new System.Drawing.Point(540, 62); + this.objectPoint2ColorLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.objectPoint2ColorLabel.Name = "objectPoint2ColorLabel"; + this.objectPoint2ColorLabel.Size = new System.Drawing.Size(172, 5); + this.objectPoint2ColorLabel.TabIndex = 25; + // + // objectPoint1ColorLabel + // + this.objectPoint1ColorLabel.BackColor = System.Drawing.Color.Black; + this.objectPoint1ColorLabel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.objectPoint1ColorLabel.Location = new System.Drawing.Point(278, 62); + this.objectPoint1ColorLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.objectPoint1ColorLabel.Name = "objectPoint1ColorLabel"; + this.objectPoint1ColorLabel.Size = new System.Drawing.Size(172, 5); + this.objectPoint1ColorLabel.TabIndex = 16; + // + // objectPoint4Box + // + this.objectPoint4Box.Location = new System.Drawing.Point(1065, 31); + this.objectPoint4Box.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.objectPoint4Box.Name = "objectPoint4Box"; + this.objectPoint4Box.ReadOnly = true; + this.objectPoint4Box.Size = new System.Drawing.Size(170, 26); + this.objectPoint4Box.TabIndex = 8; + // + // label16 + // + this.label16.AutoSize = true; + this.label16.Location = new System.Drawing.Point(990, 35); + this.label16.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label16.Name = "label16"; + this.label16.Size = new System.Drawing.Size(71, 20); + this.label16.TabIndex = 7; + this.label16.Text = "Point #4:"; + // + // objectPoint3Box + // + this.objectPoint3Box.Location = new System.Drawing.Point(802, 31); + this.objectPoint3Box.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.objectPoint3Box.Name = "objectPoint3Box"; + this.objectPoint3Box.ReadOnly = true; + this.objectPoint3Box.Size = new System.Drawing.Size(170, 26); + this.objectPoint3Box.TabIndex = 6; + // + // label15 + // + this.label15.AutoSize = true; + this.label15.Location = new System.Drawing.Point(728, 35); + this.label15.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label15.Name = "label15"; + this.label15.Size = new System.Drawing.Size(71, 20); + this.label15.TabIndex = 5; + this.label15.Text = "Point #3:"; + // + // objectPoint2Box + // + this.objectPoint2Box.Location = new System.Drawing.Point(540, 31); + this.objectPoint2Box.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.objectPoint2Box.Name = "objectPoint2Box"; + this.objectPoint2Box.ReadOnly = true; + this.objectPoint2Box.Size = new System.Drawing.Size(170, 26); + this.objectPoint2Box.TabIndex = 4; + // + // label14 + // + this.label14.AutoSize = true; + this.label14.Location = new System.Drawing.Point(465, 35); + this.label14.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label14.Name = "label14"; + this.label14.Size = new System.Drawing.Size(71, 20); + this.label14.TabIndex = 3; + this.label14.Text = "Point #2:"; + // + // objectPoint1Box + // + this.objectPoint1Box.Location = new System.Drawing.Point(278, 31); + this.objectPoint1Box.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.objectPoint1Box.Name = "objectPoint1Box"; + this.objectPoint1Box.ReadOnly = true; + this.objectPoint1Box.Size = new System.Drawing.Size(170, 26); + this.objectPoint1Box.TabIndex = 2; + // + // label13 + // + this.label13.AutoSize = true; + this.label13.Location = new System.Drawing.Point(202, 35); + this.label13.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label13.Name = "label13"; + this.label13.Size = new System.Drawing.Size(71, 20); + this.label13.TabIndex = 1; + this.label13.Text = "Point #1:"; + // + // objectTypeCombo + // + this.objectTypeCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.objectTypeCombo.FormattingEnabled = true; + this.objectTypeCombo.Items.AddRange(new object[] { + "POSIT", + "CoPOSIT"}); + this.objectTypeCombo.Location = new System.Drawing.Point(15, 31); + this.objectTypeCombo.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.objectTypeCombo.Name = "objectTypeCombo"; + this.objectTypeCombo.Size = new System.Drawing.Size(163, 28); + this.objectTypeCombo.TabIndex = 0; + this.objectTypeCombo.SelectedIndexChanged += new System.EventHandler(this.objectTypeCombo_SelectedIndexChanged); + // + // groupBox7 + // + this.groupBox7.Controls.Add(this.screenPoint4ColorLabel); + this.groupBox7.Controls.Add(this.screenPoint3ColorLabel); + this.groupBox7.Controls.Add(this.screenPoint2ColorLabel); + this.groupBox7.Controls.Add(this.screenPoint1ColorLabel); + this.groupBox7.Controls.Add(this.screenPoint4Box); + this.groupBox7.Controls.Add(this.label21); + this.groupBox7.Controls.Add(this.screenPoint3Box); + this.groupBox7.Controls.Add(this.label22); + this.groupBox7.Controls.Add(this.screenPoint2Box); + this.groupBox7.Controls.Add(this.label23); + this.groupBox7.Controls.Add(this.screenPoint1Box); + this.groupBox7.Controls.Add(this.label24); + this.groupBox7.Location = new System.Drawing.Point(15, 477); + this.groupBox7.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox7.Name = "groupBox7"; + this.groupBox7.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox7.Size = new System.Drawing.Size(1252, 85); + this.groupBox7.TabIndex = 28; + this.groupBox7.TabStop = false; + this.groupBox7.Text = "Projected Points"; + // + // screenPoint4ColorLabel + // + this.screenPoint4ColorLabel.BackColor = System.Drawing.Color.Black; + this.screenPoint4ColorLabel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.screenPoint4ColorLabel.Location = new System.Drawing.Point(1065, 62); + this.screenPoint4ColorLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.screenPoint4ColorLabel.Name = "screenPoint4ColorLabel"; + this.screenPoint4ColorLabel.Size = new System.Drawing.Size(172, 5); + this.screenPoint4ColorLabel.TabIndex = 27; + // + // screenPoint3ColorLabel + // + this.screenPoint3ColorLabel.BackColor = System.Drawing.Color.Black; + this.screenPoint3ColorLabel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.screenPoint3ColorLabel.Location = new System.Drawing.Point(802, 62); + this.screenPoint3ColorLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.screenPoint3ColorLabel.Name = "screenPoint3ColorLabel"; + this.screenPoint3ColorLabel.Size = new System.Drawing.Size(172, 5); + this.screenPoint3ColorLabel.TabIndex = 26; + // + // screenPoint2ColorLabel + // + this.screenPoint2ColorLabel.BackColor = System.Drawing.Color.Black; + this.screenPoint2ColorLabel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.screenPoint2ColorLabel.Location = new System.Drawing.Point(540, 62); + this.screenPoint2ColorLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.screenPoint2ColorLabel.Name = "screenPoint2ColorLabel"; + this.screenPoint2ColorLabel.Size = new System.Drawing.Size(172, 5); + this.screenPoint2ColorLabel.TabIndex = 25; + // + // screenPoint1ColorLabel + // + this.screenPoint1ColorLabel.BackColor = System.Drawing.Color.Black; + this.screenPoint1ColorLabel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.screenPoint1ColorLabel.Location = new System.Drawing.Point(278, 62); + this.screenPoint1ColorLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.screenPoint1ColorLabel.Name = "screenPoint1ColorLabel"; + this.screenPoint1ColorLabel.Size = new System.Drawing.Size(172, 5); + this.screenPoint1ColorLabel.TabIndex = 16; + // + // screenPoint4Box + // + this.screenPoint4Box.Location = new System.Drawing.Point(1065, 31); + this.screenPoint4Box.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.screenPoint4Box.Name = "screenPoint4Box"; + this.screenPoint4Box.ReadOnly = true; + this.screenPoint4Box.Size = new System.Drawing.Size(170, 26); + this.screenPoint4Box.TabIndex = 8; + // + // label21 + // + this.label21.AutoSize = true; + this.label21.Location = new System.Drawing.Point(990, 35); + this.label21.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label21.Name = "label21"; + this.label21.Size = new System.Drawing.Size(71, 20); + this.label21.TabIndex = 7; + this.label21.Text = "Point #4:"; + // + // screenPoint3Box + // + this.screenPoint3Box.Location = new System.Drawing.Point(802, 31); + this.screenPoint3Box.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.screenPoint3Box.Name = "screenPoint3Box"; + this.screenPoint3Box.ReadOnly = true; + this.screenPoint3Box.Size = new System.Drawing.Size(170, 26); + this.screenPoint3Box.TabIndex = 6; + // + // label22 + // + this.label22.AutoSize = true; + this.label22.Location = new System.Drawing.Point(728, 35); + this.label22.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label22.Name = "label22"; + this.label22.Size = new System.Drawing.Size(71, 20); + this.label22.TabIndex = 5; + this.label22.Text = "Point #3:"; + // + // screenPoint2Box + // + this.screenPoint2Box.Location = new System.Drawing.Point(540, 31); + this.screenPoint2Box.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.screenPoint2Box.Name = "screenPoint2Box"; + this.screenPoint2Box.ReadOnly = true; + this.screenPoint2Box.Size = new System.Drawing.Size(170, 26); + this.screenPoint2Box.TabIndex = 4; + // + // label23 + // + this.label23.AutoSize = true; + this.label23.Location = new System.Drawing.Point(465, 35); + this.label23.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label23.Name = "label23"; + this.label23.Size = new System.Drawing.Size(71, 20); + this.label23.TabIndex = 3; + this.label23.Text = "Point #2:"; + // + // screenPoint1Box + // + this.screenPoint1Box.Location = new System.Drawing.Point(278, 31); + this.screenPoint1Box.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.screenPoint1Box.Name = "screenPoint1Box"; + this.screenPoint1Box.ReadOnly = true; + this.screenPoint1Box.Size = new System.Drawing.Size(170, 26); + this.screenPoint1Box.TabIndex = 2; + // + // label24 + // + this.label24.AutoSize = true; + this.label24.Location = new System.Drawing.Point(202, 35); + this.label24.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label24.Name = "label24"; + this.label24.Size = new System.Drawing.Size(71, 20); + this.label24.TabIndex = 1; + this.label24.Text = "Point #1:"; + // + // groupBox8 + // + this.groupBox8.Controls.Add(this.label20); + this.groupBox8.Controls.Add(this.estimatedZObjectBox); + this.groupBox8.Controls.Add(this.label25); + this.groupBox8.Controls.Add(this.estimatedYObjectBox); + this.groupBox8.Controls.Add(this.label26); + this.groupBox8.Controls.Add(this.estimatedXObjectBox); + this.groupBox8.Controls.Add(this.targetTransformationMatrixControl); + this.groupBox8.Controls.Add(this.label17); + this.groupBox8.Controls.Add(this.estimatedYawBox); + this.groupBox8.Controls.Add(this.label18); + this.groupBox8.Controls.Add(this.estimatedPitchBox); + this.groupBox8.Controls.Add(this.label19); + this.groupBox8.Controls.Add(this.estimatedRollBox); + this.groupBox8.Controls.Add(this.estimatedTransformationMatrixControl); + this.groupBox8.Location = new System.Drawing.Point(15, 569); + this.groupBox8.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox8.Name = "groupBox8"; + this.groupBox8.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox8.Size = new System.Drawing.Size(1252, 208); + this.groupBox8.TabIndex = 29; + this.groupBox8.TabStop = false; + this.groupBox8.Text = "Pose Estimation"; + // + // label20 + // + this.label20.AutoSize = true; + this.label20.Location = new System.Drawing.Point(408, 74); + this.label20.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label20.Name = "label20"; + this.label20.Size = new System.Drawing.Size(23, 20); + this.label20.TabIndex = 42; + this.label20.Text = "Z:"; + // + // estimatedZObjectBox + // + this.estimatedZObjectBox.Location = new System.Drawing.Point(442, 69); + this.estimatedZObjectBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.estimatedZObjectBox.Name = "estimatedZObjectBox"; + this.estimatedZObjectBox.ReadOnly = true; + this.estimatedZObjectBox.Size = new System.Drawing.Size(88, 26); + this.estimatedZObjectBox.TabIndex = 43; + // + // label25 + // + this.label25.AutoSize = true; + this.label25.Location = new System.Drawing.Point(236, 74); + this.label25.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label25.Name = "label25"; + this.label25.Size = new System.Drawing.Size(24, 20); + this.label25.TabIndex = 40; + this.label25.Text = "Y:"; + // + // estimatedYObjectBox + // + this.estimatedYObjectBox.Location = new System.Drawing.Point(270, 69); + this.estimatedYObjectBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.estimatedYObjectBox.Name = "estimatedYObjectBox"; + this.estimatedYObjectBox.ReadOnly = true; + this.estimatedYObjectBox.Size = new System.Drawing.Size(88, 26); + this.estimatedYObjectBox.TabIndex = 41; + // + // label26 + // + this.label26.AutoSize = true; + this.label26.Location = new System.Drawing.Point(60, 74); + this.label26.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label26.Name = "label26"; + this.label26.Size = new System.Drawing.Size(24, 20); + this.label26.TabIndex = 38; + this.label26.Text = "X:"; + // + // estimatedXObjectBox + // + this.estimatedXObjectBox.Location = new System.Drawing.Point(90, 69); + this.estimatedXObjectBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.estimatedXObjectBox.Name = "estimatedXObjectBox"; + this.estimatedXObjectBox.ReadOnly = true; + this.estimatedXObjectBox.Size = new System.Drawing.Size(88, 26); + this.estimatedXObjectBox.TabIndex = 39; + // + // estimatedYawBox + // + this.estimatedYawBox.Location = new System.Drawing.Point(90, 31); + this.estimatedYawBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.estimatedYawBox.Name = "estimatedYawBox"; + this.estimatedYawBox.ReadOnly = true; + this.estimatedYawBox.Size = new System.Drawing.Size(88, 26); + this.estimatedYawBox.TabIndex = 32; + // + // estimatedPitchBox + // + this.estimatedPitchBox.Location = new System.Drawing.Point(270, 31); + this.estimatedPitchBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.estimatedPitchBox.Name = "estimatedPitchBox"; + this.estimatedPitchBox.ReadOnly = true; + this.estimatedPitchBox.Size = new System.Drawing.Size(88, 26); + this.estimatedPitchBox.TabIndex = 34; + // + // estimatedRollBox + // + this.estimatedRollBox.Location = new System.Drawing.Point(442, 31); + this.estimatedRollBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.estimatedRollBox.Name = "estimatedRollBox"; + this.estimatedRollBox.ReadOnly = true; + this.estimatedRollBox.Size = new System.Drawing.Size(88, 26); + this.estimatedRollBox.TabIndex = 36; + // + // estimatedTransformationMatrixControl + // + this.estimatedTransformationMatrixControl.Location = new System.Drawing.Point(578, 23); + this.estimatedTransformationMatrixControl.Margin = new System.Windows.Forms.Padding(6, 8, 6, 8); + this.estimatedTransformationMatrixControl.Name = "estimatedTransformationMatrixControl"; + this.estimatedTransformationMatrixControl.Size = new System.Drawing.Size(330, 169); + this.estimatedTransformationMatrixControl.TabIndex = 30; + this.estimatedTransformationMatrixControl.Title = "Estimated Transformation"; + // + // viewMatrixControl + // + this.viewMatrixControl.Location = new System.Drawing.Point(592, 300); + this.viewMatrixControl.Margin = new System.Windows.Forms.Padding(6, 8, 6, 8); + this.viewMatrixControl.Name = "viewMatrixControl"; + this.viewMatrixControl.Size = new System.Drawing.Size(330, 169); + this.viewMatrixControl.TabIndex = 6; + this.viewMatrixControl.Title = "View Matrix"; + // + // transformationMatrixControl + // + this.transformationMatrixControl.Location = new System.Drawing.Point(592, 115); + this.transformationMatrixControl.Margin = new System.Windows.Forms.Padding(6, 8, 6, 8); + this.transformationMatrixControl.Name = "transformationMatrixControl"; + this.transformationMatrixControl.Size = new System.Drawing.Size(330, 169); + this.transformationMatrixControl.TabIndex = 5; + this.transformationMatrixControl.Title = "World Transformation Matrix"; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(1284, 795); + this.Controls.Add(this.groupBox8); + this.Controls.Add(this.groupBox7); + this.Controls.Add(this.groupBox6); + this.Controls.Add(this.groupBox5); + this.Controls.Add(this.viewMatrixControl); + this.Controls.Add(this.groupBox3); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.transformationMatrixControl); + this.Controls.Add(this.groupBox4); + this.Controls.Add(this.groupBox2); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.MaximizeBox = false; + this.Name = "MainForm"; + this.Text = "Pose Estimation"; + this.Load += new System.EventHandler(this.MainForm_Load); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.groupBox4.ResumeLayout(false); + this.groupBox4.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit(); + this.groupBox3.ResumeLayout(false); + this.groupBox3.PerformLayout(); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.groupBox5.ResumeLayout(false); + this.groupBox6.ResumeLayout(false); + this.groupBox6.PerformLayout(); + this.groupBox7.ResumeLayout(false); + this.groupBox7.PerformLayout(); + this.groupBox8.ResumeLayout(false); + this.groupBox8.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox yawBox; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox pitchBox; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox rollBox; + private System.Windows.Forms.GroupBox groupBox4; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.TextBox zObjectBox; + private System.Windows.Forms.Label label11; + private System.Windows.Forms.TextBox yObjectBox; + private System.Windows.Forms.Label label12; + private System.Windows.Forms.TextBox xObjectBox; + private System.Windows.Forms.ToolTip toolTip; + private System.Windows.Forms.ErrorProvider errorProvider; + private MatrixControl transformationMatrixControl; + private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.TextBox zLookAtBox; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.TextBox yLookAtBox; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.TextBox xLookAtBox; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.TextBox zCameraBox; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.TextBox yCameraBox; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.TextBox xCameraBox; + private MatrixControl viewMatrixControl; + private System.Windows.Forms.GroupBox groupBox5; + private WorldRendererControl worldRendererControl; + private System.Windows.Forms.GroupBox groupBox6; + private System.Windows.Forms.TextBox objectPoint1Box; + private System.Windows.Forms.Label label13; + private System.Windows.Forms.ComboBox objectTypeCombo; + private System.Windows.Forms.TextBox objectPoint4Box; + private System.Windows.Forms.Label label16; + private System.Windows.Forms.TextBox objectPoint3Box; + private System.Windows.Forms.Label label15; + private System.Windows.Forms.TextBox objectPoint2Box; + private System.Windows.Forms.Label label14; + private System.Windows.Forms.Label objectPoint4ColorLabel; + private System.Windows.Forms.Label objectPoint3ColorLabel; + private System.Windows.Forms.Label objectPoint2ColorLabel; + private System.Windows.Forms.Label objectPoint1ColorLabel; + private System.Windows.Forms.GroupBox groupBox7; + private System.Windows.Forms.Label screenPoint4ColorLabel; + private System.Windows.Forms.Label screenPoint3ColorLabel; + private System.Windows.Forms.Label screenPoint2ColorLabel; + private System.Windows.Forms.Label screenPoint1ColorLabel; + private System.Windows.Forms.TextBox screenPoint4Box; + private System.Windows.Forms.Label label21; + private System.Windows.Forms.TextBox screenPoint3Box; + private System.Windows.Forms.Label label22; + private System.Windows.Forms.TextBox screenPoint2Box; + private System.Windows.Forms.Label label23; + private System.Windows.Forms.TextBox screenPoint1Box; + private System.Windows.Forms.Label label24; + private System.Windows.Forms.GroupBox groupBox8; + private MatrixControl estimatedTransformationMatrixControl; + private System.Windows.Forms.Label label17; + private System.Windows.Forms.TextBox estimatedYawBox; + private System.Windows.Forms.Label label18; + private System.Windows.Forms.TextBox estimatedPitchBox; + private System.Windows.Forms.Label label19; + private System.Windows.Forms.TextBox estimatedRollBox; + private MatrixControl targetTransformationMatrixControl; + private System.Windows.Forms.Label label20; + private System.Windows.Forms.TextBox estimatedZObjectBox; + private System.Windows.Forms.Label label25; + private System.Windows.Forms.TextBox estimatedYObjectBox; + private System.Windows.Forms.Label label26; + private System.Windows.Forms.TextBox estimatedXObjectBox; + } +} + diff --git a/Samples/Math/Pose Coordinates (POSIT)/MainForm.cs b/Samples/Math/Pose Coordinates (POSIT)/MainForm.cs new file mode 100644 index 0000000000..eff1f6c85 --- /dev/null +++ b/Samples/Math/Pose Coordinates (POSIT)/MainForm.cs @@ -0,0 +1,413 @@ +// 3D Pose Estimation sample application +// AForge.NET Framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2009-2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Windows.Forms; + +using AForge.Math; +using AForge.Math.Geometry; + +namespace SampleApp +{ + public partial class MainForm : Form + { + private int updating = 0; + + // object rotation + private float yaw = 0.0f, pitch = 0.0f, roll = 0.0f; + // object position + private float xObject = 0.0f, yObject = 0.0f, zObject = 0.0f; + // camera position + private float xCamera = 0.0f, yCamera = 0.0f, zCamera = 5.0f; + // the point camera looks at + private float xLookAt = 0.0f, yLookAt = 0.0f, zLookAt = 0.0f; + + // object points for POSIT case + private readonly Vector3[] positObject = new Vector3[4] + { + new Vector3( -0.5f, -0.5f, 0 ), + new Vector3( 0.5f, -0.5f, 0 ), + new Vector3( -0.5f, 0.5f, 0 ), + new Vector3( -0.5f, -0.5f, -1 ), + }; + + // object points for CoPOSIT case + private readonly Vector3[] copositObject = new Vector3[4] + { + new Vector3( -0.5f, -0.5f, 0 ), + new Vector3( 0.5f, -0.5f, 0 ), + new Vector3( 0.5f, 0.5f, 0 ), + new Vector3( -0.5f, 0.5f, 0 ), + }; + + // colors for object's vertices + private readonly Color[] vertexColors = new Color[] + { + Color.Yellow, + Color.Blue, + Color.Red, + Color.Green + }; + + // list of ribs for the POSIT object + private readonly int[,] positRibs = new int[3, 2] + { + { 0, 1 }, + { 0, 2 }, + { 0, 3 }, + }; + + // list of ribs for the CoPOSIT object + private readonly int[,] copositRibs = new int[4, 2] + { + { 0, 1 }, + { 1, 2 }, + { 2, 3 }, + { 3, 0 }, + }; + + private Posit posit = null; + private CoplanarPosit coposit = null; + + private Matrix4x4 transformationMatrix = Matrix4x4.Identity; + private Matrix4x4 viewMatrix = Matrix4x4.Identity; + + public MainForm( ) + { + InitializeComponent( ); + + posit = new Posit( positObject, -200 ); + coposit = new CoplanarPosit( copositObject, 200 ); + } + + // Form got loaded + private void MainForm_Load( object sender, EventArgs e ) + { + StartUpdating( ); + + screenPoint1ColorLabel.BackColor = objectPoint1ColorLabel.BackColor = vertexColors[0]; + screenPoint2ColorLabel.BackColor = objectPoint2ColorLabel.BackColor = vertexColors[1]; + screenPoint3ColorLabel.BackColor = objectPoint3ColorLabel.BackColor = vertexColors[2]; + screenPoint4ColorLabel.BackColor = objectPoint4ColorLabel.BackColor = vertexColors[3]; + + objectTypeCombo.SelectedIndex = 0; + + yawBox.Text = yaw.ToString( ); + pitchBox.Text = pitch.ToString( ); + rollBox.Text = roll.ToString( ); + + xObjectBox.Text = xObject.ToString( ); + yObjectBox.Text = yObject.ToString( ); + zObjectBox.Text = zObject.ToString( ); + + xCameraBox.Text = xCamera.ToString( ); + yCameraBox.Text = yCamera.ToString( ); + zCameraBox.Text = zCamera.ToString( ); + + xLookAtBox.Text = xLookAt.ToString( ); + yLookAtBox.Text = yLookAt.ToString( ); + zLookAtBox.Text = zLookAt.ToString( ); + + EndUpdating( ); + + UpdateTransformationMatrix( ); + UpdateViewMatrix( ); + } + + + private void StartUpdating( ) + { + updating++; + } + + private void EndUpdating( ) + { + updating--; + } + + private bool IsUpdating + { + get { return updating > 0; } + } + + // Parse float value from the text in the specified text box + private bool GetFloatValue( TextBox textBox, ref float floatValue ) + { + bool ret = false; + + if ( float.TryParse( textBox.Text, out floatValue ) ) + { + errorProvider.Clear( ); + ret = true; + } + else + { + errorProvider.SetError( textBox, "Failed parsing float value" ); + } + + return ret; + } + + // Yaw edit box has changed + private void yawBox_TextChanged( object sender, EventArgs e ) + { + if ( !IsUpdating ) + { + if ( GetFloatValue( yawBox, ref yaw ) ) + { + UpdateTransformationMatrix( ); + } + } + } + + // Pitch edit box has changed + private void pitchBox_TextChanged( object sender, EventArgs e ) + { + if ( !IsUpdating ) + { + if ( GetFloatValue( pitchBox, ref pitch ) ) + { + UpdateTransformationMatrix( ); + } + } + } + + // Roll edit box has changed + private void rollBox_TextChanged( object sender, EventArgs e ) + { + if ( !IsUpdating ) + { + if ( GetFloatValue( rollBox, ref roll ) ) + { + UpdateTransformationMatrix( ); + } + } + } + + // Object X position edit box has changed + private void xObjectBox_TextChanged( object sender, EventArgs e ) + { + if ( !IsUpdating ) + { + if ( GetFloatValue( xObjectBox, ref xObject ) ) + { + UpdateTransformationMatrix( ); + } + } + } + + // Object Y position edit box has changed + private void yObjectBox_TextChanged( object sender, EventArgs e ) + { + if ( !IsUpdating ) + { + if ( GetFloatValue( yObjectBox, ref yObject ) ) + { + UpdateTransformationMatrix( ); + } + } + } + + // Object Z position edit box has changed + private void zObjectBox_TextChanged( object sender, EventArgs e ) + { + if ( !IsUpdating ) + { + if ( GetFloatValue( zObjectBox, ref zObject ) ) + { + UpdateTransformationMatrix( ); + } + } + } + + // Camera's X position edit box has changed + private void xCameraBox_TextChanged( object sender, EventArgs e ) + { + if ( !IsUpdating ) + { + if ( GetFloatValue( xCameraBox, ref xCamera ) ) + { + UpdateViewMatrix( ); + } + } + } + + // Camera's Y position edit box has changed + private void yCameraBox_TextChanged( object sender, EventArgs e ) + { + if ( !IsUpdating ) + { + if ( GetFloatValue( yCameraBox, ref yCamera ) ) + { + UpdateViewMatrix( ); + } + } + } + + // Camera's Z position edit box has changed + private void zCameraBox_TextChanged( object sender, EventArgs e ) + { + if ( !IsUpdating ) + { + if ( GetFloatValue( zCameraBox, ref zCamera ) ) + { + UpdateViewMatrix( ); + } + } + } + + // Camera's look at point's X position edit box has changed + private void xLookAtBox_TextChanged( object sender, EventArgs e ) + { + if ( !IsUpdating ) + { + if ( GetFloatValue( xLookAtBox, ref xLookAt ) ) + { + UpdateViewMatrix( ); + } + } + } + + // Camera's look at point's Y position edit box has changed + private void yLookAtBox_TextChanged( object sender, EventArgs e ) + { + if ( !IsUpdating ) + { + if ( GetFloatValue( yLookAtBox, ref yLookAt ) ) + { + UpdateViewMatrix( ); + } + } + } + + // Camera's look at point's Z position edit box has changed + private void zLookAtBox_TextChanged( object sender, EventArgs e ) + { + if ( !IsUpdating ) + { + if ( GetFloatValue( zLookAtBox, ref zLookAt ) ) + { + UpdateViewMatrix( ); + } + } + } + + // Calculate new world transformation matrix + private void UpdateTransformationMatrix( ) + { + float rYaw = (float) ( yaw / 180 * Math.PI ); + float rPitch = (float) ( pitch / 180 * Math.PI ); + float rRoll = (float) ( roll / 180 * Math.PI ); + + transformationMatrix = + Matrix4x4.CreateTranslation( new Vector3( xObject, yObject, zObject ) ) * + Matrix4x4.CreateFromYawPitchRoll( rYaw, rPitch, rRoll ); + + worldRendererControl.WorldMatrix = transformationMatrix; + transformationMatrixControl.SetMatrix( transformationMatrix ); + targetTransformationMatrixControl.SetMatrix( viewMatrix * transformationMatrix ); + + UpdateProjectedPoints( ); + EstimatePose( ); + } + + // Calculate new view transformation matrix + private void UpdateViewMatrix( ) + { + viewMatrix = Matrix4x4.CreateLookAt( + new Vector3( xCamera, yCamera, zCamera ), + new Vector3( xLookAt, yLookAt, zLookAt ) ); + + worldRendererControl.ViewMatrix = viewMatrix; + viewMatrixControl.SetMatrix( viewMatrix ); + targetTransformationMatrixControl.SetMatrix( viewMatrix * transformationMatrix ); + + UpdateProjectedPoints( ); + EstimatePose( ); + } + + // Show current coordinates of object's projected points + private void UpdateProjectedPoints( ) + { + AForge.Point[] projectedPoints = worldRendererControl.ProjectedPoints; + + screenPoint1Box.Text = projectedPoints[0].ToString( ); + screenPoint2Box.Text = projectedPoints[1].ToString( ); + screenPoint3Box.Text = projectedPoints[2].ToString( ); + screenPoint4Box.Text = projectedPoints[3].ToString( ); + } + + // Object type has changed + private void objectTypeCombo_SelectedIndexChanged( object sender, EventArgs e ) + { + Vector3[] vertices = null; + + if ( objectTypeCombo.SelectedIndex == 0 ) + { + vertices = positObject; + worldRendererControl.SetObject( vertices = positObject, vertexColors, positRibs ); + } + else + { + vertices = copositObject; + worldRendererControl.SetObject( vertices = copositObject, vertexColors, copositRibs ); + } + + objectPoint1Box.Text = vertices[0].ToString( ); + objectPoint2Box.Text = vertices[1].ToString( ); + objectPoint3Box.Text = vertices[2].ToString( ); + objectPoint4Box.Text = vertices[3].ToString( ); + + UpdateProjectedPoints( ); + EstimatePose( ); + } + + // Estimate pose of the object from its screen (projected) points + private void EstimatePose( ) + { + AForge.Point[] projectedPoints = worldRendererControl.ProjectedPoints; + Matrix3x3 rotationMatrix = Matrix3x3.Identity; + Vector3 translationVector = new Vector3( 0 ); + + if ( objectTypeCombo.SelectedIndex == 0 ) + { + posit.EstimatePose( projectedPoints, out rotationMatrix, out translationVector ); + } + else + { + coposit.EstimatePose( projectedPoints, out rotationMatrix, out translationVector ); + } + + estimatedTransformationMatrixControl.SetMatrix( + Matrix4x4.CreateTranslation( translationVector ) * + Matrix4x4.CreateFromRotation( rotationMatrix ) ); + + float estimatedYaw; + float estimatedPitch; + float estimatedRoll; + + rotationMatrix.ExtractYawPitchRoll( out estimatedYaw, out estimatedPitch, out estimatedRoll ); + + estimatedYaw *= (float) ( 180.0 / Math.PI ); + estimatedPitch *= (float) ( 180.0 / Math.PI ); + estimatedRoll *= (float) ( 180.0 / Math.PI ); + + estimatedYawBox.Text = estimatedYaw.ToString( "F3" ); + estimatedPitchBox.Text = estimatedPitch.ToString( "F3" ); + estimatedRollBox.Text = estimatedRoll.ToString( "F3" ); + + estimatedXObjectBox.Text = translationVector.X.ToString( "F3" ); + estimatedYObjectBox.Text = translationVector.Y.ToString( "F3" ); + estimatedZObjectBox.Text = translationVector.Z.ToString( "F3" ); + } + } +} diff --git a/Samples/Math/Pose Coordinates (POSIT)/MainForm.resx b/Samples/Math/Pose Coordinates (POSIT)/MainForm.resx new file mode 100644 index 0000000000..b22d5f7fb --- /dev/null +++ b/Samples/Math/Pose Coordinates (POSIT)/MainForm.resx @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 17, 17 + + + 136, 17 + + \ No newline at end of file diff --git a/Samples/Math/Pose Coordinates (POSIT)/MatrixControl.Designer.cs b/Samples/Math/Pose Coordinates (POSIT)/MatrixControl.Designer.cs new file mode 100644 index 0000000000..5f68f4185 --- /dev/null +++ b/Samples/Math/Pose Coordinates (POSIT)/MatrixControl.Designer.cs @@ -0,0 +1,257 @@ +namespace SampleApp +{ + partial class MatrixControl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.groupBox = new System.Windows.Forms.GroupBox(); + this.i3_j3_Box = new System.Windows.Forms.TextBox(); + this.i3_j2_Box = new System.Windows.Forms.TextBox(); + this.i3_j1_Box = new System.Windows.Forms.TextBox(); + this.i3_j0_Box = new System.Windows.Forms.TextBox(); + this.i2_j3_Box = new System.Windows.Forms.TextBox(); + this.i2_j2_Box = new System.Windows.Forms.TextBox(); + this.i2_j1_Box = new System.Windows.Forms.TextBox(); + this.i2_j0_Box = new System.Windows.Forms.TextBox(); + this.i1_j3_Box = new System.Windows.Forms.TextBox(); + this.i1_j2_Box = new System.Windows.Forms.TextBox(); + this.i1_j1_Box = new System.Windows.Forms.TextBox(); + this.i1_j0_Box = new System.Windows.Forms.TextBox(); + this.i0_j3_Box = new System.Windows.Forms.TextBox(); + this.i0_j2_Box = new System.Windows.Forms.TextBox(); + this.i0_j1_Box = new System.Windows.Forms.TextBox(); + this.i0_j0_Box = new System.Windows.Forms.TextBox(); + this.groupBox.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox + // + this.groupBox.Controls.Add(this.i3_j3_Box); + this.groupBox.Controls.Add(this.i3_j2_Box); + this.groupBox.Controls.Add(this.i3_j1_Box); + this.groupBox.Controls.Add(this.i3_j0_Box); + this.groupBox.Controls.Add(this.i2_j3_Box); + this.groupBox.Controls.Add(this.i2_j2_Box); + this.groupBox.Controls.Add(this.i2_j1_Box); + this.groupBox.Controls.Add(this.i2_j0_Box); + this.groupBox.Controls.Add(this.i1_j3_Box); + this.groupBox.Controls.Add(this.i1_j2_Box); + this.groupBox.Controls.Add(this.i1_j1_Box); + this.groupBox.Controls.Add(this.i1_j0_Box); + this.groupBox.Controls.Add(this.i0_j3_Box); + this.groupBox.Controls.Add(this.i0_j2_Box); + this.groupBox.Controls.Add(this.i0_j1_Box); + this.groupBox.Controls.Add(this.i0_j0_Box); + this.groupBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.groupBox.Location = new System.Drawing.Point(0, 0); + this.groupBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox.Name = "groupBox"; + this.groupBox.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox.Size = new System.Drawing.Size(345, 169); + this.groupBox.TabIndex = 0; + this.groupBox.TabStop = false; + // + // i3_j3_Box + // + this.i3_j3_Box.Location = new System.Drawing.Point(240, 123); + this.i3_j3_Box.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.i3_j3_Box.Name = "i3_j3_Box"; + this.i3_j3_Box.ReadOnly = true; + this.i3_j3_Box.Size = new System.Drawing.Size(73, 26); + this.i3_j3_Box.TabIndex = 15; + // + // i3_j2_Box + // + this.i3_j2_Box.Location = new System.Drawing.Point(165, 123); + this.i3_j2_Box.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.i3_j2_Box.Name = "i3_j2_Box"; + this.i3_j2_Box.ReadOnly = true; + this.i3_j2_Box.Size = new System.Drawing.Size(73, 26); + this.i3_j2_Box.TabIndex = 14; + // + // i3_j1_Box + // + this.i3_j1_Box.Location = new System.Drawing.Point(90, 123); + this.i3_j1_Box.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.i3_j1_Box.Name = "i3_j1_Box"; + this.i3_j1_Box.ReadOnly = true; + this.i3_j1_Box.Size = new System.Drawing.Size(73, 26); + this.i3_j1_Box.TabIndex = 13; + // + // i3_j0_Box + // + this.i3_j0_Box.Location = new System.Drawing.Point(15, 123); + this.i3_j0_Box.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.i3_j0_Box.Name = "i3_j0_Box"; + this.i3_j0_Box.ReadOnly = true; + this.i3_j0_Box.Size = new System.Drawing.Size(73, 26); + this.i3_j0_Box.TabIndex = 12; + // + // i2_j3_Box + // + this.i2_j3_Box.Location = new System.Drawing.Point(240, 92); + this.i2_j3_Box.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.i2_j3_Box.Name = "i2_j3_Box"; + this.i2_j3_Box.ReadOnly = true; + this.i2_j3_Box.Size = new System.Drawing.Size(73, 26); + this.i2_j3_Box.TabIndex = 11; + // + // i2_j2_Box + // + this.i2_j2_Box.Location = new System.Drawing.Point(165, 92); + this.i2_j2_Box.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.i2_j2_Box.Name = "i2_j2_Box"; + this.i2_j2_Box.ReadOnly = true; + this.i2_j2_Box.Size = new System.Drawing.Size(73, 26); + this.i2_j2_Box.TabIndex = 10; + // + // i2_j1_Box + // + this.i2_j1_Box.Location = new System.Drawing.Point(90, 92); + this.i2_j1_Box.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.i2_j1_Box.Name = "i2_j1_Box"; + this.i2_j1_Box.ReadOnly = true; + this.i2_j1_Box.Size = new System.Drawing.Size(73, 26); + this.i2_j1_Box.TabIndex = 9; + // + // i2_j0_Box + // + this.i2_j0_Box.Location = new System.Drawing.Point(15, 92); + this.i2_j0_Box.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.i2_j0_Box.Name = "i2_j0_Box"; + this.i2_j0_Box.ReadOnly = true; + this.i2_j0_Box.Size = new System.Drawing.Size(73, 26); + this.i2_j0_Box.TabIndex = 8; + // + // i1_j3_Box + // + this.i1_j3_Box.Location = new System.Drawing.Point(240, 62); + this.i1_j3_Box.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.i1_j3_Box.Name = "i1_j3_Box"; + this.i1_j3_Box.ReadOnly = true; + this.i1_j3_Box.Size = new System.Drawing.Size(73, 26); + this.i1_j3_Box.TabIndex = 7; + // + // i1_j2_Box + // + this.i1_j2_Box.Location = new System.Drawing.Point(165, 62); + this.i1_j2_Box.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.i1_j2_Box.Name = "i1_j2_Box"; + this.i1_j2_Box.ReadOnly = true; + this.i1_j2_Box.Size = new System.Drawing.Size(73, 26); + this.i1_j2_Box.TabIndex = 6; + // + // i1_j1_Box + // + this.i1_j1_Box.Location = new System.Drawing.Point(90, 62); + this.i1_j1_Box.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.i1_j1_Box.Name = "i1_j1_Box"; + this.i1_j1_Box.ReadOnly = true; + this.i1_j1_Box.Size = new System.Drawing.Size(73, 26); + this.i1_j1_Box.TabIndex = 5; + // + // i1_j0_Box + // + this.i1_j0_Box.Location = new System.Drawing.Point(15, 62); + this.i1_j0_Box.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.i1_j0_Box.Name = "i1_j0_Box"; + this.i1_j0_Box.ReadOnly = true; + this.i1_j0_Box.Size = new System.Drawing.Size(73, 26); + this.i1_j0_Box.TabIndex = 4; + // + // i0_j3_Box + // + this.i0_j3_Box.Location = new System.Drawing.Point(240, 31); + this.i0_j3_Box.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.i0_j3_Box.Name = "i0_j3_Box"; + this.i0_j3_Box.ReadOnly = true; + this.i0_j3_Box.Size = new System.Drawing.Size(73, 26); + this.i0_j3_Box.TabIndex = 3; + // + // i0_j2_Box + // + this.i0_j2_Box.Location = new System.Drawing.Point(165, 31); + this.i0_j2_Box.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.i0_j2_Box.Name = "i0_j2_Box"; + this.i0_j2_Box.ReadOnly = true; + this.i0_j2_Box.Size = new System.Drawing.Size(73, 26); + this.i0_j2_Box.TabIndex = 2; + // + // i0_j1_Box + // + this.i0_j1_Box.Location = new System.Drawing.Point(90, 31); + this.i0_j1_Box.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.i0_j1_Box.Name = "i0_j1_Box"; + this.i0_j1_Box.ReadOnly = true; + this.i0_j1_Box.Size = new System.Drawing.Size(73, 26); + this.i0_j1_Box.TabIndex = 1; + // + // i0_j0_Box + // + this.i0_j0_Box.Location = new System.Drawing.Point(15, 31); + this.i0_j0_Box.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.i0_j0_Box.Name = "i0_j0_Box"; + this.i0_j0_Box.ReadOnly = true; + this.i0_j0_Box.Size = new System.Drawing.Size(73, 26); + this.i0_j0_Box.TabIndex = 0; + // + // MatrixControl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.Controls.Add(this.groupBox); + this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.Name = "MatrixControl"; + this.Size = new System.Drawing.Size(345, 169); + this.Load += new System.EventHandler(this.MatrixControl_Load); + this.groupBox.ResumeLayout(false); + this.groupBox.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox; + private System.Windows.Forms.TextBox i0_j0_Box; + private System.Windows.Forms.TextBox i3_j3_Box; + private System.Windows.Forms.TextBox i3_j2_Box; + private System.Windows.Forms.TextBox i3_j1_Box; + private System.Windows.Forms.TextBox i3_j0_Box; + private System.Windows.Forms.TextBox i2_j3_Box; + private System.Windows.Forms.TextBox i2_j2_Box; + private System.Windows.Forms.TextBox i2_j1_Box; + private System.Windows.Forms.TextBox i2_j0_Box; + private System.Windows.Forms.TextBox i1_j3_Box; + private System.Windows.Forms.TextBox i1_j2_Box; + private System.Windows.Forms.TextBox i1_j1_Box; + private System.Windows.Forms.TextBox i1_j0_Box; + private System.Windows.Forms.TextBox i0_j3_Box; + private System.Windows.Forms.TextBox i0_j2_Box; + private System.Windows.Forms.TextBox i0_j1_Box; + } +} diff --git a/Samples/Math/Pose Coordinates (POSIT)/MatrixControl.cs b/Samples/Math/Pose Coordinates (POSIT)/MatrixControl.cs new file mode 100644 index 0000000000..f08999328 --- /dev/null +++ b/Samples/Math/Pose Coordinates (POSIT)/MatrixControl.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Text; +using System.Windows.Forms; + +using AForge.Math; + +namespace SampleApp +{ + public partial class MatrixControl : UserControl + { + private Dictionary textBoxes = new Dictionary( ); + + public string Title + { + get { return groupBox.Text; } + set { groupBox.Text = value; } + } + + public MatrixControl( ) + { + InitializeComponent( ); + } + + public void SetMatrix( Matrix4x4 matrix ) + { + float[] array = matrix.ToArray( ); + + for ( int i = 0, k = 0; i < 4; i++ ) + { + for ( int j = 0; j < 4; j++, k++ ) + { + string textBoxName = string.Format( "i{0}_j{1}_Box", i, j ); + + if ( textBoxes.ContainsKey( textBoxName ) ) + { + textBoxes[textBoxName].Text = FormatFloat( array[k] ); + } + } + } + } + + private static string FormatFloat( float floatValue ) + { + return String.Format( "{0:0.####}", floatValue ); + } + + private void MatrixControl_Load( object sender, EventArgs e ) + { + textBoxes.Clear( ); + + foreach ( Control c in groupBox.Controls ) + { + if ( c is TextBox ) + { + textBoxes.Add( c.Name, (TextBox) c ); + } + } + } + } +} diff --git a/Samples/Vision/Kinect/VideoCaptureDeviceForm.resx b/Samples/Math/Pose Coordinates (POSIT)/MatrixControl.resx similarity index 100% rename from Samples/Vision/Kinect/VideoCaptureDeviceForm.resx rename to Samples/Math/Pose Coordinates (POSIT)/MatrixControl.resx diff --git a/Samples/Math/Pose Coordinates (POSIT)/Pose Coordinates (POSIT).csproj b/Samples/Math/Pose Coordinates (POSIT)/Pose Coordinates (POSIT).csproj new file mode 100644 index 0000000000..711fae7d3 --- /dev/null +++ b/Samples/Math/Pose Coordinates (POSIT)/Pose Coordinates (POSIT).csproj @@ -0,0 +1,170 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {3B59E324-53FC-4837-AF37-61FC4B51E2D1} + WinExe + Properties + SampleApp + Pose Estimation + v4.0 + 512 + + + 3.5 + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + SampleApp.Program + + + + ..\..\..\Release\net40\Accord.dll + + + ..\..\..\Release\net40\Accord.Math.dll + + + + + + + + + Form + + + MainForm.cs + + + UserControl + + + MatrixControl.cs + + + + + MainForm.cs + + + MatrixControl.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + WorldRendererControl.cs + + + True + Resources.resx + True + + + PreserveNewest + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + UserControl + + + WorldRendererControl.cs + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + \ No newline at end of file diff --git a/Samples/Math/Pose Coordinates (POSIT)/Pose Estimation.sln b/Samples/Math/Pose Coordinates (POSIT)/Pose Estimation.sln new file mode 100644 index 0000000000..d53706f47 --- /dev/null +++ b/Samples/Math/Pose Coordinates (POSIT)/Pose Estimation.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C# Express 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pose Estimation", "Pose Estimation.csproj", "{3B59E324-53FC-4837-AF37-61FC4B51E2D1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3B59E324-53FC-4837-AF37-61FC4B51E2D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3B59E324-53FC-4837-AF37-61FC4B51E2D1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3B59E324-53FC-4837-AF37-61FC4B51E2D1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3B59E324-53FC-4837-AF37-61FC4B51E2D1}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/Math/Pose Coordinates (POSIT)/Program.cs b/Samples/Math/Pose Coordinates (POSIT)/Program.cs new file mode 100644 index 0000000000..316268492 --- /dev/null +++ b/Samples/Math/Pose Coordinates (POSIT)/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Windows.Forms; + +namespace SampleApp +{ + static class Program + { + [STAThread] + static void Main() + { + if (Environment.OSVersion.Version.Major >= 6) + SetProcessDPIAware(); + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + + [System.Runtime.InteropServices.DllImport("user32.dll")] + private static extern bool SetProcessDPIAware(); + } +} diff --git a/Samples/Math/Pose Coordinates (POSIT)/Properties/AssemblyInfo.cs b/Samples/Math/Pose Coordinates (POSIT)/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..8cd2b3ef0 --- /dev/null +++ b/Samples/Math/Pose Coordinates (POSIT)/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle( "3D Pose Estimation" )] +[assembly: AssemblyDescription( "3D Pose Estimation Sample" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "AForge" )] +[assembly: AssemblyProduct( "AForge.NET" )] +[assembly: AssemblyCopyright( "AForge © 2011" )] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible( false )] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid( "43b2f529-cf41-4d57-8dc0-4d1ab0dabfae" )] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion( "1.0.0.0" )] +[assembly: AssemblyFileVersion( "1.0.0.0" )] diff --git a/Samples/Math/Pose Coordinates (POSIT)/Properties/Resources.Designer.cs b/Samples/Math/Pose Coordinates (POSIT)/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..7b58e53ee --- /dev/null +++ b/Samples/Math/Pose Coordinates (POSIT)/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Samples/Math/Pose Coordinates (POSIT)/Properties/Resources.resx b/Samples/Math/Pose Coordinates (POSIT)/Properties/Resources.resx new file mode 100644 index 0000000000..af7dbebba --- /dev/null +++ b/Samples/Math/Pose Coordinates (POSIT)/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Math/Pose Coordinates (POSIT)/Properties/Settings.Designer.cs b/Samples/Math/Pose Coordinates (POSIT)/Properties/Settings.Designer.cs new file mode 100644 index 0000000000..dbc9e5d22 --- /dev/null +++ b/Samples/Math/Pose Coordinates (POSIT)/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Samples/Math/Pose Coordinates (POSIT)/Properties/Settings.settings b/Samples/Math/Pose Coordinates (POSIT)/Properties/Settings.settings new file mode 100644 index 0000000000..39645652a --- /dev/null +++ b/Samples/Math/Pose Coordinates (POSIT)/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Samples/Math/Pose Coordinates (POSIT)/WorldRendererControl.Designer.cs b/Samples/Math/Pose Coordinates (POSIT)/WorldRendererControl.Designer.cs new file mode 100644 index 0000000000..9aa8d5d38 --- /dev/null +++ b/Samples/Math/Pose Coordinates (POSIT)/WorldRendererControl.Designer.cs @@ -0,0 +1,46 @@ +namespace SampleApp +{ + partial class WorldRendererControl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.SuspendLayout( ); + // + // WorldRendererControl + // + this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 13F ); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Name = "WorldRendererControl"; + this.Size = new System.Drawing.Size( 154, 150 ); + this.Paint += new System.Windows.Forms.PaintEventHandler( this.WorldRendererControl_Paint ); + this.ResumeLayout( false ); + + } + + #endregion + } +} diff --git a/Samples/Math/Pose Coordinates (POSIT)/WorldRendererControl.cs b/Samples/Math/Pose Coordinates (POSIT)/WorldRendererControl.cs new file mode 100644 index 0000000000..6ed16c830 --- /dev/null +++ b/Samples/Math/Pose Coordinates (POSIT)/WorldRendererControl.cs @@ -0,0 +1,163 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Text; +using System.Windows.Forms; + +using AForge.Math; + +namespace SampleApp +{ + public partial class WorldRendererControl : UserControl + { + private Vector3[] objectPoints = null; + private Vector3[] objectScenePoints = null; + private AForge.Point[] projectedPoints = null; + private Color[] colors = null; + private int[,] lines = null; + + + private Matrix4x4 worldMatrix = new Matrix4x4( ); + private Matrix4x4 viewMatrix = new Matrix4x4( ); + private Matrix4x4 perspectiveMatrix = new Matrix4x4( ); + + public Matrix4x4 WorldMatrix + { + get { return worldMatrix; } + set + { + worldMatrix = value; + Recalculate( ); + } + } + + public Matrix4x4 ViewMatrix + { + get { return viewMatrix; } + set + { + viewMatrix = value; + Recalculate( ); + } + } + + public AForge.Point[] ProjectedPoints + { + get { return projectedPoints; } + } + + public WorldRendererControl( ) + { + InitializeComponent( ); + + objectPoints = new Vector3[] + { + new Vector3( 0, 0, 0 ), + }; + + colors = new Color[] + { + Color.White, + }; + + lines = new int[0, 2]; + + // create default matrices + worldMatrix = Matrix4x4.Identity; + viewMatrix = Matrix4x4.CreateLookAt( new Vector3( 0, 0, 5 ), new Vector3( 0, 0, 0 ) ); + perspectiveMatrix = Matrix4x4.CreatePerspective( 1, 1, 1, 1000 ); + + Recalculate( ); + } + + public void SetObject( Vector3[] vertices, Color[] colors, int[,] ribs ) + { + if ( vertices.Length != colors.Length ) + { + throw new ArgumentException( "Number of colors must be equal to number of vertices." ); + } + + if ( ribs.GetLength( 1 ) != 2 ) + { + throw new ArgumentException( "Ribs array must have 2 coordinates per rib." ); + } + + this.objectPoints = (Vector3[]) vertices.Clone( ); + this.colors = (Color[]) colors.Clone( ); + this.lines = (int[,]) ribs.Clone( ); + + Recalculate( ); + } + + private void Recalculate( ) + { + int pointsCount = objectPoints.Length; + objectScenePoints = new Vector3[pointsCount]; + projectedPoints = new AForge.Point[pointsCount]; + + int cx = ClientRectangle.Width / 2; + int cy = ClientRectangle.Height / 2; + + for ( int i = 0; i < pointsCount; i++ ) + { + objectScenePoints[i] = ( perspectiveMatrix * + ( viewMatrix * + ( worldMatrix * objectPoints[i].ToVector4( ) ) ) ).ToVector3( ); + + projectedPoints[i] = new AForge.Point( + (int) ( cx * objectScenePoints[i].X ), + (int) ( cy * objectScenePoints[i].Y ) ); + } + + Invalidate( ); + } + + private void WorldRendererControl_Paint( object sender, PaintEventArgs e ) + { + Graphics g = e.Graphics; + Pen linesPen = new Pen( Color.White ); + + using ( SolidBrush brush = new SolidBrush( Color.Black ) ) + { + g.FillRectangle( brush, this.ClientRectangle ); + } + + if ( projectedPoints != null ) + { + int cx = ClientRectangle.Width / 2; + int cy = ClientRectangle.Height / 2; + + Point[] screenPoints = new Point[projectedPoints.Length]; + + for ( int i = 0, n = projectedPoints.Length; i < n; i++ ) + { + screenPoints[i] = new Point( (int) ( cx + projectedPoints[i].X ), + (int) ( cy - projectedPoints[i].Y ) ); + } + + for ( int i = 0; i < lines.GetLength( 0 ); i++ ) + { + int lineStart = lines[i, 0]; + int lineEnd = lines[i, 1]; + + if ( ( lineStart < projectedPoints.Length ) && ( lineEnd < projectedPoints.Length ) ) + { + g.DrawLine( linesPen, screenPoints[lineStart], screenPoints[lineEnd]); + } + } + + for ( int i = 0; i < projectedPoints.Length; i++ ) + { + using ( SolidBrush pointsBrush = new SolidBrush( colors[i] ) ) + { + g.FillRectangle( pointsBrush, screenPoints[i].X - 2, screenPoints[i].Y - 2, 5, 5 ); + } + } + } + + linesPen.Dispose( ); + } + } +} diff --git a/Samples/Math/Pose Coordinates (POSIT)/WorldRendererControl.resx b/Samples/Math/Pose Coordinates (POSIT)/WorldRendererControl.resx new file mode 100644 index 0000000000..19dc0dd8b --- /dev/null +++ b/Samples/Math/Pose Coordinates (POSIT)/WorldRendererControl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Math/Pose Coordinates (POSIT)/app.config b/Samples/Math/Pose Coordinates (POSIT)/app.config new file mode 100644 index 0000000000..57c0f2cbc --- /dev/null +++ b/Samples/Math/Pose Coordinates (POSIT)/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Samples/Math/Solver (Goldfarb-Idnani)/Accord.dll.config b/Samples/Math/Solver (Goldfarb-Idnani)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Math/Solver (Goldfarb-Idnani)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Math/Solver (Goldfarb-Idnani)/MainForm.Designer.cs b/Samples/Math/Solver (Goldfarb-Idnani)/MainForm.Designer.cs index 786d576d2..6d988f69f 100644 --- a/Samples/Math/Solver (Goldfarb-Idnani)/MainForm.Designer.cs +++ b/Samples/Math/Solver (Goldfarb-Idnani)/MainForm.Designer.cs @@ -1,33 +1,33 @@ -namespace Solver.QP -{ - partial class MainForm - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); this.tbObjective = new System.Windows.Forms.TextBox(); this.label1 = new System.Windows.Forms.Label(); @@ -176,19 +176,19 @@ private void InitializeComponent() this.groupBox3.PerformLayout(); this.ResumeLayout(false); - } - - #endregion - - private System.Windows.Forms.TextBox tbObjective; - private System.Windows.Forms.Label label1; - private System.Windows.Forms.ComboBox comboBox1; - private System.Windows.Forms.GroupBox groupBox1; - private System.Windows.Forms.GroupBox groupBox2; - private System.Windows.Forms.TextBox tbConstraints; - private System.Windows.Forms.Button button1; - private System.Windows.Forms.TextBox tbSolution; - private System.Windows.Forms.GroupBox groupBox3; - } -} - + } + + #endregion + + private System.Windows.Forms.TextBox tbObjective; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.ComboBox comboBox1; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.TextBox tbConstraints; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.TextBox tbSolution; + private System.Windows.Forms.GroupBox groupBox3; + } +} + diff --git a/Samples/Math/Solver (Goldfarb-Idnani)/MainForm.cs b/Samples/Math/Solver (Goldfarb-Idnani)/MainForm.cs index d98bda97c..a003d63b6 100644 --- a/Samples/Math/Solver (Goldfarb-Idnani)/MainForm.cs +++ b/Samples/Math/Solver (Goldfarb-Idnani)/MainForm.cs @@ -36,7 +36,7 @@ using System.Text; using System.Windows.Forms; -namespace Solver.QP +namespace SampleApp { /// /// Goldfarb-Idnani solver for Quadratic Programming (QP) problems diff --git a/Samples/Math/Solver (Goldfarb-Idnani)/Program.cs b/Samples/Math/Solver (Goldfarb-Idnani)/Program.cs index 4a0b76f2c..316268492 100644 --- a/Samples/Math/Solver (Goldfarb-Idnani)/Program.cs +++ b/Samples/Math/Solver (Goldfarb-Idnani)/Program.cs @@ -1,7 +1,7 @@ using System; using System.Windows.Forms; -namespace Solver.QP +namespace SampleApp { static class Program { diff --git a/Samples/Math/Solver (Goldfarb-Idnani)/Properties/Resources.Designer.cs b/Samples/Math/Solver (Goldfarb-Idnani)/Properties/Resources.Designer.cs index ba42aed17..7b58e53ee 100644 --- a/Samples/Math/Solver (Goldfarb-Idnani)/Properties/Resources.Designer.cs +++ b/Samples/Math/Solver (Goldfarb-Idnani)/Properties/Resources.Designer.cs @@ -1,63 +1,63 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.18052 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Solver.QP.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Solver.QP.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Samples/Math/Solver (Goldfarb-Idnani)/Properties/Settings.Designer.cs b/Samples/Math/Solver (Goldfarb-Idnani)/Properties/Settings.Designer.cs index 8ad18b847..dbc9e5d22 100644 --- a/Samples/Math/Solver (Goldfarb-Idnani)/Properties/Settings.Designer.cs +++ b/Samples/Math/Solver (Goldfarb-Idnani)/Properties/Settings.Designer.cs @@ -1,26 +1,26 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.18052 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Solver.QP.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Samples/Math/Solver (Goldfarb-Idnani)/Quadratic Programing (QP).csproj b/Samples/Math/Solver (Goldfarb-Idnani)/Quadratic Programing (QP).csproj index e3562367c..8a2828eaf 100644 --- a/Samples/Math/Solver (Goldfarb-Idnani)/Quadratic Programing (QP).csproj +++ b/Samples/Math/Solver (Goldfarb-Idnani)/Quadratic Programing (QP).csproj @@ -1,101 +1,106 @@ - - - - Debug - x86 - 8.0.30703 - 2.0 - {38C27270-D29A-48B0-BF49-B90C049C42E1} - WinExe - Properties - Solver - Solver - v4.0 - Client - 512 - - - x86 - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - x86 - pdbonly - true - bin\x86\Release\ - TRACE - prompt - 4 - - - framework.ico - - - - False - ..\..\..\Release\net40\Accord.dll - - - False - ..\..\..\Release\net40\Accord.Math.dll - - - - - - - - - - - - - - - Form - - - MainForm.cs - - - - - MainForm.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - + + + + Debug + x86 + 8.0.30703 + 2.0 + {38C27270-D29A-48B0-BF49-B90C049C42E1} + WinExe + Properties + SampleApp + Solver + v4.0 + Client + 512 + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + bin\x86\Release\ + TRACE + prompt + 4 + + + framework.ico + + + SampleApp.Program + + + + False + ..\..\..\Release\net40\Accord.dll + + + False + ..\..\..\Release\net40\Accord.Math.dll + + + + + + + + + + + + + Form + + + MainForm.cs + + + + + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + --> \ No newline at end of file diff --git a/Samples/Neuro/Classification (ANN)/AboutBox.Designer.cs b/Samples/Neuro/Classification (ANN)/AboutBox.Designer.cs index 73c47984a..f6d7e7190 100644 --- a/Samples/Neuro/Classification (ANN)/AboutBox.Designer.cs +++ b/Samples/Neuro/Classification (ANN)/AboutBox.Designer.cs @@ -1,32 +1,32 @@ -namespace Classification.ANNs -{ - partial class AboutBox - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { +namespace SampleApp +{ + partial class AboutBox + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AboutBox)); this.tableLayoutPanel = new System.Windows.Forms.TableLayoutPanel(); this.logoPictureBox = new System.Windows.Forms.PictureBox(); @@ -174,17 +174,17 @@ private void InitializeComponent() ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).EndInit(); this.ResumeLayout(false); - } - - #endregion - - private System.Windows.Forms.TableLayoutPanel tableLayoutPanel; - private System.Windows.Forms.PictureBox logoPictureBox; - private System.Windows.Forms.Label labelProductName; - private System.Windows.Forms.Label labelVersion; - private System.Windows.Forms.Label labelCopyright; - private System.Windows.Forms.Label labelCompanyName; - private System.Windows.Forms.TextBox textBoxDescription; - private System.Windows.Forms.Button okButton; - } -} + } + + #endregion + + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel; + private System.Windows.Forms.PictureBox logoPictureBox; + private System.Windows.Forms.Label labelProductName; + private System.Windows.Forms.Label labelVersion; + private System.Windows.Forms.Label labelCopyright; + private System.Windows.Forms.Label labelCompanyName; + private System.Windows.Forms.TextBox textBoxDescription; + private System.Windows.Forms.Button okButton; + } +} diff --git a/Samples/Neuro/Classification (ANN)/AboutBox.cs b/Samples/Neuro/Classification (ANN)/AboutBox.cs index 87c1a450e..af9eda35c 100644 --- a/Samples/Neuro/Classification (ANN)/AboutBox.cs +++ b/Samples/Neuro/Classification (ANN)/AboutBox.cs @@ -6,7 +6,7 @@ using System.Reflection; using System.Windows.Forms; -namespace Classification.ANNs +namespace SampleApp { partial class AboutBox : Form { diff --git a/Samples/Neuro/Classification (ANN)/Accord.dll.config b/Samples/Neuro/Classification (ANN)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Neuro/Classification (ANN)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Neuro/Classification (ANN)/Classification (ANNs).csproj b/Samples/Neuro/Classification (ANN)/Classification (ANNs).csproj index 65b779e3c..92b5a8ea6 100644 --- a/Samples/Neuro/Classification (ANN)/Classification (ANNs).csproj +++ b/Samples/Neuro/Classification (ANN)/Classification (ANNs).csproj @@ -65,25 +65,12 @@ False ..\..\..\Release\net40\Accord.Statistics.dll - - False - ..\..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Math.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Neuro.dll - + - - @@ -134,6 +121,9 @@ TableSelectDialog.cs Designer + + PreserveNewest + SettingsSingleFileGenerator @@ -152,13 +142,6 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + diff --git a/Samples/Neuro/Clustering (SOM)/App.ico b/Samples/Neuro/Clustering (SOM)/App.ico new file mode 100644 index 0000000000..3a5525fd7 Binary files /dev/null and b/Samples/Neuro/Clustering (SOM)/App.ico differ diff --git a/Samples/Neuro/Clustering (SOM)/AssemblyInfo.cs b/Samples/Neuro/Clustering (SOM)/AssemblyInfo.cs new file mode 100644 index 0000000000..c93a8fb1b --- /dev/null +++ b/Samples/Neuro/Clustering (SOM)/AssemblyInfo.cs @@ -0,0 +1,59 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle( "Neuro SOM Colors" )] +[assembly: AssemblyDescription( "Neuro SOM Colors sample" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "AForge" )] +[assembly: AssemblyProduct( "AForge.NET" )] +[assembly: AssemblyCopyright( "AForge 2008" )] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion( "2.0.0.0" )] +[assembly: AssemblyFileVersion( "2.0.0.0" )] + +// +// In order to sign your assembly you must specify a key to use. Refer to the +// Microsoft .NET Framework documentation for more information on assembly signing. +// +// Use the attributes below to control which key is used for signing. +// +// Notes: +// (*) If no key is specified, the assembly is not signed. +// (*) KeyName refers to a key that has been installed in the Crypto Service +// Provider (CSP) on your machine. KeyFile refers to a file which contains +// a key. +// (*) If the KeyFile and the KeyName values are both specified, the +// following processing occurs: +// (1) If the KeyName can be found in the CSP, that key is used. +// (2) If the KeyName does not exist and the KeyFile does exist, the key +// in the KeyFile is installed into the CSP and used. +// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. +// When specifying the KeyFile, the location of the KeyFile should be +// relative to the project output directory which is +// %Project Directory%\obj\. For example, if your KeyFile is +// located in the project directory, you would specify the AssemblyKeyFile +// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] +// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework +// documentation for more information on this. +// +[assembly: AssemblyDelaySign( false )] +[assembly: AssemblyKeyFile( "" )] +[assembly: AssemblyKeyName( "" )] diff --git a/Samples/Neuro/Clustering (SOM)/BufferedPanel.cs b/Samples/Neuro/Clustering (SOM)/BufferedPanel.cs new file mode 100644 index 0000000000..970b22c17 --- /dev/null +++ b/Samples/Neuro/Clustering (SOM)/BufferedPanel.cs @@ -0,0 +1,19 @@ +using System; +using System.Windows.Forms; + +namespace SampleApp +{ + /// + /// Dummy class to enable double buffering in Panel + /// + public class BufferedPanel : System.Windows.Forms.Panel + { + // Construcor + public BufferedPanel() + { + // Update control style + SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | + ControlStyles.DoubleBuffer | ControlStyles.UserPaint, true); + } + } +} diff --git a/Samples/Neuro/Clustering (SOM)/Clustering (SOM).csproj b/Samples/Neuro/Clustering (SOM)/Clustering (SOM).csproj new file mode 100644 index 0000000000..887115045 --- /dev/null +++ b/Samples/Neuro/Clustering (SOM)/Clustering (SOM).csproj @@ -0,0 +1,147 @@ + + + + Local + 9.0.21022 + 2.0 + {59E2469C-197F-4A4C-9D52-AA58EA49927E} + Debug + AnyCPU + App.ico + + + Color + + + JScript + Grid + IE50 + false + WinExe + Color + OnBuildSuccess + SampleApp.Program + + + + + 3.5 + v4.0 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + bin\x86\Debug\ + DEBUG;TRACE + 285212672 + true + 4096 + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + 285212672 + true + true + 4096 + x86 + prompt + MinimumRecommendedRules.ruleset + + + + ..\..\..\Release\net40\Accord.dll + + + ..\..\..\Release\net40\Accord.Math.dll + + + ..\..\..\Release\net40\Accord.Neuro.dll + + + System + + + System.Data + + + System.Drawing + + + System.Windows.Forms + + + System.XML + + + + + + + Code + + + Component + + + Form + + + MainForm.cs + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + PreserveNewest + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/Neuro/Clustering (SOM)/Color.sln b/Samples/Neuro/Clustering (SOM)/Color.sln new file mode 100644 index 0000000000..73b91bd86 --- /dev/null +++ b/Samples/Neuro/Clustering (SOM)/Color.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C# Express 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Color", "Color.csproj", "{59E2469C-197F-4A4C-9D52-AA58EA49927E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {59E2469C-197F-4A4C-9D52-AA58EA49927E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {59E2469C-197F-4A4C-9D52-AA58EA49927E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {59E2469C-197F-4A4C-9D52-AA58EA49927E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {59E2469C-197F-4A4C-9D52-AA58EA49927E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/Neuro/Clustering (SOM)/MainForm.cs b/Samples/Neuro/Clustering (SOM)/MainForm.cs new file mode 100644 index 0000000000..01a72bd27 --- /dev/null +++ b/Samples/Neuro/Clustering (SOM)/MainForm.cs @@ -0,0 +1,520 @@ +// Color Clustering using Kohonen SOM +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +using System; +using System.Drawing; +using System.Drawing.Imaging; +using System.Collections; +using System.ComponentModel; +using System.Windows.Forms; +using System.Data; +using System.Threading; + +using AForge; +using AForge.Neuro; +using AForge.Neuro.Learning; + +namespace SampleApp +{ + + public class MainForm : System.Windows.Forms.Form + { + private System.Windows.Forms.GroupBox groupBox1; + private BufferedPanel mapPanel; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox iterationsBox; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox rateBox; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox radiusBox; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Button startButton; + private System.Windows.Forms.Button stopButton; + private System.Windows.Forms.Button randomizeButton; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.TextBox currentIterationBox; + /// + /// Required designer variable. + /// + private System.ComponentModel.Container components = null; + + private DistanceNetwork network; + private Bitmap mapBitmap; + private Random rand = new Random(); + + private int iterations = 5000; + private double learningRate = 0.1; + private double radius = 15; + + private Thread workerThread = null; + private volatile bool needToStop = false; + + // Constructor + public MainForm() + { + InitializeComponent(); + + // Create network + network = new DistanceNetwork(3, 100 * 100); + + // Create map bitmap + mapBitmap = new Bitmap(200, 200, PixelFormat.Format24bppRgb); + + // + RandomizeNetwork(); + UpdateSettings(); + } + + /// + /// Clean up any resources being used. + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (components != null) + { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.randomizeButton = new System.Windows.Forms.Button(); + this.mapPanel = new SampleApp.BufferedPanel(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.currentIterationBox = new System.Windows.Forms.TextBox(); + this.label5 = new System.Windows.Forms.Label(); + this.stopButton = new System.Windows.Forms.Button(); + this.startButton = new System.Windows.Forms.Button(); + this.label4 = new System.Windows.Forms.Label(); + this.radiusBox = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.rateBox = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.iterationsBox = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.randomizeButton); + this.groupBox1.Controls.Add(this.mapPanel); + this.groupBox1.Location = new System.Drawing.Point(16, 15); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(355, 387); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Map"; + // + // randomizeButton + // + this.randomizeButton.Location = new System.Drawing.Point(16, 336); + this.randomizeButton.Name = "randomizeButton"; + this.randomizeButton.Size = new System.Drawing.Size(120, 34); + this.randomizeButton.TabIndex = 1; + this.randomizeButton.Text = "&Randomize"; + this.randomizeButton.Click += new System.EventHandler(this.randomizeButton_Click); + // + // mapPanel + // + this.mapPanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.mapPanel.Location = new System.Drawing.Point(16, 29); + this.mapPanel.Name = "mapPanel"; + this.mapPanel.Size = new System.Drawing.Size(323, 295); + this.mapPanel.TabIndex = 0; + this.mapPanel.Paint += new System.Windows.Forms.PaintEventHandler(this.mapPanel_Paint); + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.currentIterationBox); + this.groupBox2.Controls.Add(this.label5); + this.groupBox2.Controls.Add(this.stopButton); + this.groupBox2.Controls.Add(this.startButton); + this.groupBox2.Controls.Add(this.label4); + this.groupBox2.Controls.Add(this.radiusBox); + this.groupBox2.Controls.Add(this.label3); + this.groupBox2.Controls.Add(this.rateBox); + this.groupBox2.Controls.Add(this.label2); + this.groupBox2.Controls.Add(this.iterationsBox); + this.groupBox2.Controls.Add(this.label1); + this.groupBox2.Location = new System.Drawing.Point(384, 15); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(304, 387); + this.groupBox2.TabIndex = 1; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Neural Network"; + // + // currentIterationBox + // + this.currentIterationBox.Location = new System.Drawing.Point(176, 175); + this.currentIterationBox.Name = "currentIterationBox"; + this.currentIterationBox.ReadOnly = true; + this.currentIterationBox.Size = new System.Drawing.Size(112, 26); + this.currentIterationBox.TabIndex = 10; + // + // label5 + // + this.label5.Location = new System.Drawing.Point(16, 178); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(160, 24); + this.label5.TabIndex = 9; + this.label5.Text = "Curren iteration:"; + // + // stopButton + // + this.stopButton.Enabled = false; + this.stopButton.Location = new System.Drawing.Point(168, 336); + this.stopButton.Name = "stopButton"; + this.stopButton.Size = new System.Drawing.Size(120, 34); + this.stopButton.TabIndex = 8; + this.stopButton.Text = "S&top"; + this.stopButton.Click += new System.EventHandler(this.stopButton_Click); + // + // startButton + // + this.startButton.Location = new System.Drawing.Point(32, 336); + this.startButton.Name = "startButton"; + this.startButton.Size = new System.Drawing.Size(120, 34); + this.startButton.TabIndex = 7; + this.startButton.Text = "&Start"; + this.startButton.Click += new System.EventHandler(this.startButton_Click); + // + // label4 + // + this.label4.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.label4.Location = new System.Drawing.Point(16, 146); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(272, 3); + this.label4.TabIndex = 6; + // + // radiusBox + // + this.radiusBox.Location = new System.Drawing.Point(176, 102); + this.radiusBox.Name = "radiusBox"; + this.radiusBox.Size = new System.Drawing.Size(112, 26); + this.radiusBox.TabIndex = 5; + // + // label3 + // + this.label3.Location = new System.Drawing.Point(16, 105); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(160, 24); + this.label3.TabIndex = 4; + this.label3.Text = "Initial radius:"; + // + // rateBox + // + this.rateBox.Location = new System.Drawing.Point(176, 66); + this.rateBox.Name = "rateBox"; + this.rateBox.Size = new System.Drawing.Size(112, 26); + this.rateBox.TabIndex = 3; + // + // label2 + // + this.label2.Location = new System.Drawing.Point(16, 69); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(160, 23); + this.label2.TabIndex = 2; + this.label2.Text = "Initial learning rate:"; + // + // iterationsBox + // + this.iterationsBox.Location = new System.Drawing.Point(176, 29); + this.iterationsBox.Name = "iterationsBox"; + this.iterationsBox.Size = new System.Drawing.Size(112, 26); + this.iterationsBox.TabIndex = 1; + // + // label1 + // + this.label1.Location = new System.Drawing.Point(16, 32); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(96, 24); + this.label1.TabIndex = 0; + this.label1.Text = "Iteraions:"; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(698, 416); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.Name = "MainForm"; + this.Text = "Color Clustering using Kohonen SOM"; + this.Closing += new System.ComponentModel.CancelEventHandler(this.MainForm_Closing); + this.groupBox1.ResumeLayout(false); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.ResumeLayout(false); + + } + #endregion + + + // Delegates to enable async calls for setting controls properties + private delegate void SetTextCallback(System.Windows.Forms.Control control, string text); + + // Thread safe updating of control's text property + private void SetText(System.Windows.Forms.Control control, string text) + { + if (control.InvokeRequired) + { + SetTextCallback d = new SetTextCallback(SetText); + Invoke(d, new object[] { control, text }); + } + else + { + control.Text = text; + } + } + + // On main form closing + private void MainForm_Closing(object sender, System.ComponentModel.CancelEventArgs e) + { + // check if worker thread is running + if ((workerThread != null) && (workerThread.IsAlive)) + { + needToStop = true; + while (!workerThread.Join(100)) + Application.DoEvents(); + } + } + + // Update settings controls + private void UpdateSettings() + { + iterationsBox.Text = iterations.ToString(); + rateBox.Text = learningRate.ToString(); + radiusBox.Text = radius.ToString(); + } + + // On "Rundomize" button clicked + private void randomizeButton_Click(object sender, System.EventArgs e) + { + RandomizeNetwork(); + } + + // Radnomize weights of network + private void RandomizeNetwork() + { + Neuron.RandRange = new Range(0, 255); + + // randomize net + network.Randomize(); + + // update map + UpdateMap(); + } + + // Update map from network weights + private void UpdateMap() + { + // lock + Monitor.Enter(this); + + // lock bitmap + BitmapData mapData = mapBitmap.LockBits(new Rectangle(0, 0, 200, 200), + ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); + + int stride = mapData.Stride; + int offset = stride - 200 * 3; + Layer layer = network.Layers[0]; + + unsafe + { + byte* ptr = (byte*)mapData.Scan0; + + // for all rows + for (int y = 0, i = 0; y < 100; y++) + { + // for all pixels + for (int x = 0; x < 100; x++, i++, ptr += 6) + { + Neuron neuron = layer.Neurons[i]; + + // red + ptr[2] = ptr[2 + 3] = ptr[2 + stride] = ptr[2 + 3 + stride] = + (byte)Math.Max(0, Math.Min(255, neuron.Weights[0])); + + // green + ptr[1] = ptr[1 + 3] = ptr[1 + stride] = ptr[1 + 3 + stride] = + (byte)Math.Max(0, Math.Min(255, neuron.Weights[1])); + + // blue + ptr[0] = ptr[0 + 3] = ptr[0 + stride] = ptr[0 + 3 + stride] = + (byte)Math.Max(0, Math.Min(255, neuron.Weights[2])); + } + + ptr += offset; + ptr += stride; + } + } + + // unlock image + mapBitmap.UnlockBits(mapData); + + // unlock + Monitor.Exit(this); + + // invalidate maps panel + mapPanel.Invalidate(); + } + + // Paint map + private void mapPanel_Paint(object sender, System.Windows.Forms.PaintEventArgs e) + { + Graphics g = e.Graphics; + + // lock + Monitor.Enter(this); + + // drat image + g.DrawImage(mapBitmap, 0, 0, 200, 200); + + // unlock + Monitor.Exit(this); + } + + // Delegates to enable async calls for setting controls properties + private delegate void EnableCallback(bool enable); + + // Enable/disale controls (safe for threading) + private void EnableControls(bool enable) + { + if (InvokeRequired) + { + EnableCallback d = new EnableCallback(EnableControls); + Invoke(d, new object[] { enable }); + } + else + { + iterationsBox.Enabled = enable; + rateBox.Enabled = enable; + radiusBox.Enabled = enable; + + startButton.Enabled = enable; + randomizeButton.Enabled = enable; + stopButton.Enabled = !enable; + } + } + + // On "Start" button click + private void startButton_Click(object sender, System.EventArgs e) + { + // get iterations count + try + { + iterations = Math.Max(10, Math.Min(1000000, int.Parse(iterationsBox.Text))); + } + catch + { + iterations = 5000; + } + // get learning rate + try + { + learningRate = Math.Max(0.00001, Math.Min(1.0, double.Parse(rateBox.Text))); + } + catch + { + learningRate = 0.1; + } + // get radius + try + { + radius = Math.Max(5, Math.Min(75, int.Parse(radiusBox.Text))); + } + catch + { + radius = 15; + } + // update settings controls + UpdateSettings(); + + // disable all settings controls except "Stop" button + EnableControls(false); + + // run worker thread + needToStop = false; + workerThread = new Thread(new ThreadStart(SearchSolution)); + workerThread.Start(); + } + + // On "Stop" button click + private void stopButton_Click(object sender, System.EventArgs e) + { + // stop worker thread + needToStop = true; + while (!workerThread.Join(100)) + Application.DoEvents(); + workerThread = null; + } + + // Worker thread + void SearchSolution() + { + // create learning algorithm + SOMLearning trainer = new SOMLearning(network); + + // input + double[] input = new double[3]; + + double fixedLearningRate = learningRate / 10; + double driftingLearningRate = fixedLearningRate * 9; + + // iterations + int i = 0; + + // loop + while (!needToStop) + { + trainer.LearningRate = driftingLearningRate * (iterations - i) / iterations + fixedLearningRate; + trainer.LearningRadius = (double)radius * (iterations - i) / iterations; + + input[0] = rand.Next(256); + input[1] = rand.Next(256); + input[2] = rand.Next(256); + + trainer.Run(input); + + // update map once per 50 iterations + if ((i % 10) == 9) + { + UpdateMap(); + } + + // increase current iteration + i++; + + // set current iteration's info + SetText(currentIterationBox, i.ToString()); + + // stop ? + if (i >= iterations) + break; + } + + // enable settings controls + EnableControls(true); + } + } +} diff --git a/Samples/Vision/Kinect/VisionForm.resx b/Samples/Neuro/Clustering (SOM)/MainForm.resx similarity index 100% rename from Samples/Vision/Kinect/VisionForm.resx rename to Samples/Neuro/Clustering (SOM)/MainForm.resx diff --git a/Samples/Neuro/Clustering (SOM)/Program.cs b/Samples/Neuro/Clustering (SOM)/Program.cs new file mode 100644 index 0000000000..316268492 --- /dev/null +++ b/Samples/Neuro/Clustering (SOM)/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Windows.Forms; + +namespace SampleApp +{ + static class Program + { + [STAThread] + static void Main() + { + if (Environment.OSVersion.Version.Major >= 6) + SetProcessDPIAware(); + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + + [System.Runtime.InteropServices.DllImport("user32.dll")] + private static extern bool SetProcessDPIAware(); + } +} diff --git a/Samples/Neuro/Clustering (SOM)/app.config b/Samples/Neuro/Clustering (SOM)/app.config new file mode 100644 index 0000000000..57c0f2cbc --- /dev/null +++ b/Samples/Neuro/Clustering (SOM)/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Samples/Neuro/Deep Learning/Accord.dll.config b/Samples/Neuro/Deep Learning/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Neuro/Deep Learning/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Neuro/Deep Learning/Deep Learning.csproj b/Samples/Neuro/Deep Learning/Deep Learning.csproj index 3a7437a35..c4be58ec3 100644 --- a/Samples/Neuro/Deep Learning/Deep Learning.csproj +++ b/Samples/Neuro/Deep Learning/Deep Learning.csproj @@ -42,40 +42,25 @@ - ..\..\packages\Accord.2.14.0\lib\net40\Accord.dll + ..\..\..\Release\net40\Accord.dll - ..\..\packages\Accord.Controls.2.14.0\lib\net40\Accord.Controls.dll + ..\..\..\Release\net40\Accord.Controls.dll - ..\..\packages\Accord.Imaging.2.14.0\lib\net40\Accord.Imaging.dll + ..\..\..\Release\net40\Accord.Imaging.dll - ..\..\packages\Accord.MachineLearning.2.14.0\lib\net40\Accord.MachineLearning.dll + ..\..\..\Release\net40\Accord.MachineLearning.dll - ..\..\packages\Accord.Math.2.14.0\lib\net40\Accord.Math.dll + ..\..\..\Release\net40\Accord.Math.dll - ..\..\packages\Accord.Neuro.2.14.0\lib\net40\Accord.Neuro.dll + ..\..\..\Release\net40\Accord.Neuro.dll - ..\..\packages\Accord.Statistics.2.14.0\lib\net40\Accord.Statistics.dll - - - ..\..\packages\AForge.2.2.5\lib\AForge.dll - - - ..\..\packages\AForge.Genetic.2.2.5\lib\AForge.Genetic.dll - - - ..\..\packages\AForge.Imaging.2.2.5\lib\AForge.Imaging.dll - - - ..\..\packages\AForge.Math.2.2.5\lib\AForge.Math.dll - - - ..\..\packages\AForge.Neuro.2.2.5\lib\AForge.Neuro.dll + ..\..\..\Release\net40\Accord.Statistics.dll packages\MahApps.Metro.0.10.0.1\lib\net40\MahApps.Metro.dll @@ -188,6 +173,9 @@ ResXFileCodeGenerator Resources.Designer.cs + + PreserveNewest + diff --git a/Samples/Neuro/Deep Learning/app.config b/Samples/Neuro/Deep Learning/app.config index b952dc975..2d718e8ea 100644 --- a/Samples/Neuro/Deep Learning/app.config +++ b/Samples/Neuro/Deep Learning/app.config @@ -1,17 +1,5 @@  - - - - - - - - - - - - diff --git a/Samples/Neuro/Deep Learning/packages.config b/Samples/Neuro/Deep Learning/packages.config index 71149ae92..977cf1ae1 100644 --- a/Samples/Neuro/Deep Learning/packages.config +++ b/Samples/Neuro/Deep Learning/packages.config @@ -1,17 +1,5 @@  - - - - - - - - - - - - diff --git a/Samples/Neuro/Levenberg-Marquardt/Accord.dll.config b/Samples/Neuro/Levenberg-Marquardt/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Neuro/Levenberg-Marquardt/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Neuro/Levenberg-Marquardt/Applications/Approximation.cs b/Samples/Neuro/Levenberg-Marquardt/Applications/Approximation.cs index 0a19ac6d4..5732475c0 100644 --- a/Samples/Neuro/Levenberg-Marquardt/Applications/Approximation.cs +++ b/Samples/Neuro/Levenberg-Marquardt/Applications/Approximation.cs @@ -49,7 +49,7 @@ using System.Threading; using System.Windows.Forms; -namespace Samples.LM +namespace SampleApp { /// /// Summary description for Form1. diff --git a/Samples/Neuro/Levenberg-Marquardt/Applications/Approximation.resx b/Samples/Neuro/Levenberg-Marquardt/Applications/Approximation.resx index 679ff3f0e..d97bbc6ed 100644 --- a/Samples/Neuro/Levenberg-Marquardt/Applications/Approximation.resx +++ b/Samples/Neuro/Levenberg-Marquardt/Applications/Approximation.resx @@ -117,21 +117,8 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + 17, 17 - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAElBRm9yZ2UsIFZlcnNpb249Mi4yLjUuMCwgQ3VsdHVyZT1uZXV0 - cmFsLCBQdWJsaWNLZXlUb2tlbj1jMWRiNmZmNGVhYTA2YWViBQEAAAAMQUZvcmdlLlJhbmdlAgAAAANt - aW4DbWF4AAALCwIAAAAAAAAAAACAPws= - - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAElBRm9yZ2UsIFZlcnNpb249Mi4yLjUuMCwgQ3VsdHVyZT1uZXV0 - cmFsLCBQdWJsaWNLZXlUb2tlbj1jMWRiNmZmNGVhYTA2YWViBQEAAAAMQUZvcmdlLlJhbmdlAgAAAANt - aW4DbWF4AAALCwIAAAAAAAAAAACAPws= - \ No newline at end of file diff --git a/Samples/Neuro/Levenberg-Marquardt/Applications/TimeSeries.cs b/Samples/Neuro/Levenberg-Marquardt/Applications/TimeSeries.cs index b454883d1..78ba1334f 100644 --- a/Samples/Neuro/Levenberg-Marquardt/Applications/TimeSeries.cs +++ b/Samples/Neuro/Levenberg-Marquardt/Applications/TimeSeries.cs @@ -44,7 +44,7 @@ using Accord.IO; using Accord.Math; -namespace Samples.LM +namespace SampleApp { public class TimeSeries : System.Windows.Forms.Form { @@ -496,15 +496,6 @@ private void InitializeComponent() } #endregion - /// - /// The main entry point for the application. - /// - [STAThread] - static void Main() - { - Application.Run(new MainForm()); - } - // Delegates to enable async calls for setting controls properties private delegate void SetTextCallback(System.Windows.Forms.Control control, string text); private delegate void AddSubItemCallback(System.Windows.Forms.ListView control, int item, string subitemText); diff --git a/Samples/Neuro/Levenberg-Marquardt/Applications/TimeSeries.resx b/Samples/Neuro/Levenberg-Marquardt/Applications/TimeSeries.resx index c9ec46a16..d97bbc6ed 100644 --- a/Samples/Neuro/Levenberg-Marquardt/Applications/TimeSeries.resx +++ b/Samples/Neuro/Levenberg-Marquardt/Applications/TimeSeries.resx @@ -117,21 +117,8 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - AAEAAAD/////AQAAAAAAAAAMAgAAAElBRm9yZ2UsIFZlcnNpb249Mi4yLjUuMCwgQ3VsdHVyZT1uZXV0 - cmFsLCBQdWJsaWNLZXlUb2tlbj1jMWRiNmZmNGVhYTA2YWViBQEAAAAMQUZvcmdlLlJhbmdlAgAAAANt - aW4DbWF4AAALCwIAAAAAAAAAAACAPws= - - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAElBRm9yZ2UsIFZlcnNpb249Mi4yLjUuMCwgQ3VsdHVyZT1uZXV0 - cmFsLCBQdWJsaWNLZXlUb2tlbj1jMWRiNmZmNGVhYTA2YWViBQEAAAAMQUZvcmdlLlJhbmdlAgAAAANt - aW4DbWF4AAALCwIAAAAAAAAAAACAPws= - - - + + 17, 17 - + \ No newline at end of file diff --git a/Samples/Neuro/Levenberg-Marquardt/Applications/XorProblem.cs b/Samples/Neuro/Levenberg-Marquardt/Applications/XorProblem.cs index 19148cb88..afd8fe400 100644 --- a/Samples/Neuro/Levenberg-Marquardt/Applications/XorProblem.cs +++ b/Samples/Neuro/Levenberg-Marquardt/Applications/XorProblem.cs @@ -42,7 +42,7 @@ using AForge.Controls; using AForge.Neuro; -namespace Samples.LM +namespace SampleApp { public class XorProblem : Form { @@ -119,233 +119,233 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(XorProblem)); - this.groupBox1 = new System.Windows.Forms.GroupBox(); - this.stopButton = new System.Windows.Forms.Button(); - this.startButton = new System.Windows.Forms.Button(); - this.label5 = new System.Windows.Forms.Label(); - this.currentErrorBox = new System.Windows.Forms.TextBox(); - this.label11 = new System.Windows.Forms.Label(); - this.currentIterationBox = new System.Windows.Forms.TextBox(); - this.label8 = new System.Windows.Forms.Label(); - this.label7 = new System.Windows.Forms.Label(); - this.sigmoidTypeCombo = new System.Windows.Forms.ComboBox(); - this.errorLimitBox = new System.Windows.Forms.TextBox(); - this.label3 = new System.Windows.Forms.Label(); - this.alphaBox = new System.Windows.Forms.TextBox(); - this.label2 = new System.Windows.Forms.Label(); - this.learningRateBox = new System.Windows.Forms.TextBox(); - this.label1 = new System.Windows.Forms.Label(); - this.label4 = new System.Windows.Forms.Label(); - this.groupBox2 = new System.Windows.Forms.GroupBox(); - this.errorChart = new AForge.Controls.Chart(); - this.saveFilesCheck = new System.Windows.Forms.CheckBox(); - this.groupBox1.SuspendLayout(); - this.groupBox2.SuspendLayout(); - this.SuspendLayout(); - // - // groupBox1 - // - this.groupBox1.Controls.Add(this.stopButton); - this.groupBox1.Controls.Add(this.startButton); - this.groupBox1.Controls.Add(this.label5); - this.groupBox1.Controls.Add(this.currentErrorBox); - this.groupBox1.Controls.Add(this.label11); - this.groupBox1.Controls.Add(this.currentIterationBox); - this.groupBox1.Controls.Add(this.label8); - this.groupBox1.Controls.Add(this.label7); - this.groupBox1.Controls.Add(this.sigmoidTypeCombo); - this.groupBox1.Controls.Add(this.errorLimitBox); - this.groupBox1.Controls.Add(this.label3); - this.groupBox1.Controls.Add(this.alphaBox); - this.groupBox1.Controls.Add(this.label2); - this.groupBox1.Controls.Add(this.learningRateBox); - this.groupBox1.Controls.Add(this.label1); - this.groupBox1.Controls.Add(this.label4); - this.groupBox1.Location = new System.Drawing.Point(16, 15); - this.groupBox1.Name = "groupBox1"; - this.groupBox1.Size = new System.Drawing.Size(312, 380); - this.groupBox1.TabIndex = 0; - this.groupBox1.TabStop = false; - this.groupBox1.Text = "Neural Network"; - // - // stopButton - // - this.stopButton.Enabled = false; - this.stopButton.Location = new System.Drawing.Point(176, 329); - this.stopButton.Name = "stopButton"; - this.stopButton.Size = new System.Drawing.Size(120, 33); - this.stopButton.TabIndex = 28; - this.stopButton.Text = "S&top"; - this.stopButton.Click += new System.EventHandler(this.stopButton_Click); - // - // startButton - // - this.startButton.Location = new System.Drawing.Point(40, 329); - this.startButton.Name = "startButton"; - this.startButton.Size = new System.Drawing.Size(120, 33); - this.startButton.TabIndex = 27; - this.startButton.Text = "&Start"; - this.startButton.Click += new System.EventHandler(this.startButton_Click); - // - // label5 - // - this.label5.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.label5.Location = new System.Drawing.Point(16, 308); - this.label5.Name = "label5"; - this.label5.Size = new System.Drawing.Size(280, 3); - this.label5.TabIndex = 26; - // - // currentErrorBox - // - this.currentErrorBox.Location = new System.Drawing.Point(200, 270); - this.currentErrorBox.Name = "currentErrorBox"; - this.currentErrorBox.ReadOnly = true; - this.currentErrorBox.Size = new System.Drawing.Size(96, 26); - this.currentErrorBox.TabIndex = 25; - // - // label11 - // - this.label11.Location = new System.Drawing.Point(16, 273); - this.label11.Name = "label11"; - this.label11.Size = new System.Drawing.Size(194, 21); - this.label11.TabIndex = 24; - this.label11.Text = "Current summary error:"; - // - // currentIterationBox - // - this.currentIterationBox.Location = new System.Drawing.Point(200, 234); - this.currentIterationBox.Name = "currentIterationBox"; - this.currentIterationBox.ReadOnly = true; - this.currentIterationBox.Size = new System.Drawing.Size(96, 26); - this.currentIterationBox.TabIndex = 23; - // - // label8 - // - this.label8.Location = new System.Drawing.Point(16, 237); - this.label8.Name = "label8"; - this.label8.Size = new System.Drawing.Size(157, 23); - this.label8.TabIndex = 22; - this.label8.Text = "Current iteration:"; - // - // label7 - // - this.label7.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.label7.Location = new System.Drawing.Point(16, 219); - this.label7.Name = "label7"; - this.label7.Size = new System.Drawing.Size(280, 3); - this.label7.TabIndex = 21; - // - // sigmoidTypeCombo - // - this.sigmoidTypeCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.sigmoidTypeCombo.Items.AddRange(new object[] { - "Unipolar", - "Bipolar"}); - this.sigmoidTypeCombo.Location = new System.Drawing.Point(200, 140); - this.sigmoidTypeCombo.Name = "sigmoidTypeCombo"; - this.sigmoidTypeCombo.Size = new System.Drawing.Size(96, 28); - this.sigmoidTypeCombo.TabIndex = 9; - // - // errorLimitBox - // - this.errorLimitBox.Location = new System.Drawing.Point(200, 104); - this.errorLimitBox.Name = "errorLimitBox"; - this.errorLimitBox.Size = new System.Drawing.Size(96, 26); - this.errorLimitBox.TabIndex = 7; - // - // label3 - // - this.label3.Location = new System.Drawing.Point(16, 107); - this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(176, 22); - this.label3.TabIndex = 6; - this.label3.Text = "Learning error limit:"; - // - // alphaBox - // - this.alphaBox.Location = new System.Drawing.Point(200, 67); - this.alphaBox.Name = "alphaBox"; - this.alphaBox.Size = new System.Drawing.Size(96, 26); - this.alphaBox.TabIndex = 5; - // - // label2 - // - this.label2.Location = new System.Drawing.Point(16, 70); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(192, 22); - this.label2.TabIndex = 4; - this.label2.Text = "Sigmoid\'s alpha value:"; - // - // learningRateBox - // - this.learningRateBox.Location = new System.Drawing.Point(200, 29); - this.learningRateBox.Name = "learningRateBox"; - this.learningRateBox.Size = new System.Drawing.Size(96, 26); - this.learningRateBox.TabIndex = 1; - // - // label1 - // - this.label1.Location = new System.Drawing.Point(16, 32); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(125, 21); - this.label1.TabIndex = 0; - this.label1.Text = "Learning rate:"; - // - // label4 - // - this.label4.Location = new System.Drawing.Point(16, 143); - this.label4.Name = "label4"; - this.label4.Size = new System.Drawing.Size(160, 22); - this.label4.TabIndex = 8; - this.label4.Text = "Sigmoid\'s type:"; - // - // groupBox2 - // - this.groupBox2.Controls.Add(this.errorChart); - this.groupBox2.Controls.Add(this.saveFilesCheck); - this.groupBox2.Location = new System.Drawing.Point(344, 15); - this.groupBox2.Name = "groupBox2"; - this.groupBox2.Size = new System.Drawing.Size(352, 380); - this.groupBox2.TabIndex = 1; - this.groupBox2.TabStop = false; - this.groupBox2.Text = "Error\'s dynamics"; - // - // errorChart - // - this.errorChart.Location = new System.Drawing.Point(16, 29); - this.errorChart.Name = "errorChart"; - this.errorChart.RangeX = ((AForge.Range)(resources.GetObject("errorChart.RangeX"))); - this.errorChart.RangeY = ((AForge.Range)(resources.GetObject("errorChart.RangeY"))); - this.errorChart.Size = new System.Drawing.Size(320, 300); - this.errorChart.TabIndex = 2; - this.errorChart.Text = "chart1"; - // - // saveFilesCheck - // - this.saveFilesCheck.Location = new System.Drawing.Point(16, 341); - this.saveFilesCheck.Name = "saveFilesCheck"; - this.saveFilesCheck.Size = new System.Drawing.Size(320, 26); - this.saveFilesCheck.TabIndex = 1; - this.saveFilesCheck.Text = "Save errors to files"; - // - // XorProblem - // - this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; - this.ClientSize = new System.Drawing.Size(707, 409); - this.Controls.Add(this.groupBox2); - this.Controls.Add(this.groupBox1); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - this.MaximizeBox = false; - this.Name = "XorProblem"; - this.Text = "XOR Problem (Levenberg-Marquardt)"; - this.Closing += new System.ComponentModel.CancelEventHandler(this.MainForm_Closing); - this.groupBox1.ResumeLayout(false); - this.groupBox1.PerformLayout(); - this.groupBox2.ResumeLayout(false); - this.ResumeLayout(false); - + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(XorProblem)); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.stopButton = new System.Windows.Forms.Button(); + this.startButton = new System.Windows.Forms.Button(); + this.label5 = new System.Windows.Forms.Label(); + this.currentErrorBox = new System.Windows.Forms.TextBox(); + this.label11 = new System.Windows.Forms.Label(); + this.currentIterationBox = new System.Windows.Forms.TextBox(); + this.label8 = new System.Windows.Forms.Label(); + this.label7 = new System.Windows.Forms.Label(); + this.sigmoidTypeCombo = new System.Windows.Forms.ComboBox(); + this.errorLimitBox = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.alphaBox = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.learningRateBox = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.errorChart = new AForge.Controls.Chart(); + this.saveFilesCheck = new System.Windows.Forms.CheckBox(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.stopButton); + this.groupBox1.Controls.Add(this.startButton); + this.groupBox1.Controls.Add(this.label5); + this.groupBox1.Controls.Add(this.currentErrorBox); + this.groupBox1.Controls.Add(this.label11); + this.groupBox1.Controls.Add(this.currentIterationBox); + this.groupBox1.Controls.Add(this.label8); + this.groupBox1.Controls.Add(this.label7); + this.groupBox1.Controls.Add(this.sigmoidTypeCombo); + this.groupBox1.Controls.Add(this.errorLimitBox); + this.groupBox1.Controls.Add(this.label3); + this.groupBox1.Controls.Add(this.alphaBox); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.learningRateBox); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.label4); + this.groupBox1.Location = new System.Drawing.Point(16, 15); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(312, 380); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Neural Network"; + // + // stopButton + // + this.stopButton.Enabled = false; + this.stopButton.Location = new System.Drawing.Point(176, 329); + this.stopButton.Name = "stopButton"; + this.stopButton.Size = new System.Drawing.Size(120, 33); + this.stopButton.TabIndex = 28; + this.stopButton.Text = "S&top"; + this.stopButton.Click += new System.EventHandler(this.stopButton_Click); + // + // startButton + // + this.startButton.Location = new System.Drawing.Point(40, 329); + this.startButton.Name = "startButton"; + this.startButton.Size = new System.Drawing.Size(120, 33); + this.startButton.TabIndex = 27; + this.startButton.Text = "&Start"; + this.startButton.Click += new System.EventHandler(this.startButton_Click); + // + // label5 + // + this.label5.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.label5.Location = new System.Drawing.Point(16, 308); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(280, 3); + this.label5.TabIndex = 26; + // + // currentErrorBox + // + this.currentErrorBox.Location = new System.Drawing.Point(200, 270); + this.currentErrorBox.Name = "currentErrorBox"; + this.currentErrorBox.ReadOnly = true; + this.currentErrorBox.Size = new System.Drawing.Size(96, 26); + this.currentErrorBox.TabIndex = 25; + // + // label11 + // + this.label11.Location = new System.Drawing.Point(16, 273); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(194, 21); + this.label11.TabIndex = 24; + this.label11.Text = "Current summary error:"; + // + // currentIterationBox + // + this.currentIterationBox.Location = new System.Drawing.Point(200, 234); + this.currentIterationBox.Name = "currentIterationBox"; + this.currentIterationBox.ReadOnly = true; + this.currentIterationBox.Size = new System.Drawing.Size(96, 26); + this.currentIterationBox.TabIndex = 23; + // + // label8 + // + this.label8.Location = new System.Drawing.Point(16, 237); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(157, 23); + this.label8.TabIndex = 22; + this.label8.Text = "Current iteration:"; + // + // label7 + // + this.label7.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.label7.Location = new System.Drawing.Point(16, 219); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(280, 3); + this.label7.TabIndex = 21; + // + // sigmoidTypeCombo + // + this.sigmoidTypeCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.sigmoidTypeCombo.Items.AddRange(new object[] { + "Unipolar", + "Bipolar"}); + this.sigmoidTypeCombo.Location = new System.Drawing.Point(200, 140); + this.sigmoidTypeCombo.Name = "sigmoidTypeCombo"; + this.sigmoidTypeCombo.Size = new System.Drawing.Size(96, 28); + this.sigmoidTypeCombo.TabIndex = 9; + // + // errorLimitBox + // + this.errorLimitBox.Location = new System.Drawing.Point(200, 104); + this.errorLimitBox.Name = "errorLimitBox"; + this.errorLimitBox.Size = new System.Drawing.Size(96, 26); + this.errorLimitBox.TabIndex = 7; + // + // label3 + // + this.label3.Location = new System.Drawing.Point(16, 107); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(176, 22); + this.label3.TabIndex = 6; + this.label3.Text = "Learning error limit:"; + // + // alphaBox + // + this.alphaBox.Location = new System.Drawing.Point(200, 67); + this.alphaBox.Name = "alphaBox"; + this.alphaBox.Size = new System.Drawing.Size(96, 26); + this.alphaBox.TabIndex = 5; + // + // label2 + // + this.label2.Location = new System.Drawing.Point(16, 70); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(192, 22); + this.label2.TabIndex = 4; + this.label2.Text = "Sigmoid\'s alpha value:"; + // + // learningRateBox + // + this.learningRateBox.Location = new System.Drawing.Point(200, 29); + this.learningRateBox.Name = "learningRateBox"; + this.learningRateBox.Size = new System.Drawing.Size(96, 26); + this.learningRateBox.TabIndex = 1; + // + // label1 + // + this.label1.Location = new System.Drawing.Point(16, 32); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(125, 21); + this.label1.TabIndex = 0; + this.label1.Text = "Learning rate:"; + // + // label4 + // + this.label4.Location = new System.Drawing.Point(16, 143); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(160, 22); + this.label4.TabIndex = 8; + this.label4.Text = "Sigmoid\'s type:"; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.errorChart); + this.groupBox2.Controls.Add(this.saveFilesCheck); + this.groupBox2.Location = new System.Drawing.Point(344, 15); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(352, 380); + this.groupBox2.TabIndex = 1; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Error\'s dynamics"; + // + // errorChart + // + this.errorChart.Location = new System.Drawing.Point(16, 29); + this.errorChart.Name = "errorChart"; + this.errorChart.RangeX = ((AForge.Range)(resources.GetObject("errorChart.RangeX"))); + this.errorChart.RangeY = ((AForge.Range)(resources.GetObject("errorChart.RangeY"))); + this.errorChart.Size = new System.Drawing.Size(320, 300); + this.errorChart.TabIndex = 2; + this.errorChart.Text = "chart1"; + // + // saveFilesCheck + // + this.saveFilesCheck.Location = new System.Drawing.Point(16, 341); + this.saveFilesCheck.Name = "saveFilesCheck"; + this.saveFilesCheck.Size = new System.Drawing.Size(320, 26); + this.saveFilesCheck.TabIndex = 1; + this.saveFilesCheck.Text = "Save errors to files"; + // + // XorProblem + // + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(707, 409); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.Name = "XorProblem"; + this.Text = "XOR Problem (Levenberg-Marquardt)"; + this.Closing += new System.ComponentModel.CancelEventHandler(this.MainForm_Closing); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.groupBox2.ResumeLayout(false); + this.ResumeLayout(false); + } #endregion diff --git a/Samples/Neuro/Levenberg-Marquardt/Applications/XorProblem.resx b/Samples/Neuro/Levenberg-Marquardt/Applications/XorProblem.resx index 368d2bea2..c7e0d4bdf 100644 --- a/Samples/Neuro/Levenberg-Marquardt/Applications/XorProblem.resx +++ b/Samples/Neuro/Levenberg-Marquardt/Applications/XorProblem.resx @@ -117,18 +117,4 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - AAEAAAD/////AQAAAAAAAAAMAgAAAElBRm9yZ2UsIFZlcnNpb249Mi4yLjUuMCwgQ3VsdHVyZT1uZXV0 - cmFsLCBQdWJsaWNLZXlUb2tlbj1jMWRiNmZmNGVhYTA2YWViBQEAAAAMQUZvcmdlLlJhbmdlAgAAAANt - aW4DbWF4AAALCwIAAAAAAAAAAACAPws= - - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAElBRm9yZ2UsIFZlcnNpb249Mi4yLjUuMCwgQ3VsdHVyZT1uZXV0 - cmFsLCBQdWJsaWNLZXlUb2tlbj1jMWRiNmZmNGVhYTA2YWViBQEAAAAMQUZvcmdlLlJhbmdlAgAAAANt - aW4DbWF4AAALCwIAAAAAAAAAAACAPws= - - \ No newline at end of file diff --git a/Samples/Neuro/Levenberg-Marquardt/Levenberg-Marquardt.csproj b/Samples/Neuro/Levenberg-Marquardt/Levenberg-Marquardt.csproj index 13f5e6caf..a63467878 100644 --- a/Samples/Neuro/Levenberg-Marquardt/Levenberg-Marquardt.csproj +++ b/Samples/Neuro/Levenberg-Marquardt/Levenberg-Marquardt.csproj @@ -20,7 +20,8 @@ WinExe Samples.LM OnBuildSuccess - Samples.LM.Program + + @@ -74,6 +75,9 @@ False ..\..\..\Release\net40\Accord.dll + + ..\..\..\Release\net40\Accord.Controls.dll + ..\..\..\Release\net40\Accord.IO.dll @@ -93,22 +97,6 @@ False ..\..\..\Release\net40\Accord.Statistics.dll - - False - ..\..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Controls.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Math.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Neuro.dll - System @@ -121,6 +109,7 @@ System.Drawing + System.Windows.Forms @@ -195,6 +184,9 @@ + + PreserveNewest + PreserveNewest diff --git a/Samples/Neuro/Levenberg-Marquardt/MainForm.Designer.cs b/Samples/Neuro/Levenberg-Marquardt/MainForm.Designer.cs index 53f23c285..0867371c8 100644 --- a/Samples/Neuro/Levenberg-Marquardt/MainForm.Designer.cs +++ b/Samples/Neuro/Levenberg-Marquardt/MainForm.Designer.cs @@ -1,33 +1,33 @@ -namespace Samples.LM -{ - partial class MainForm - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); this.btnApproximation = new System.Windows.Forms.Button(); this.btnTimeSeries = new System.Windows.Forms.Button(); @@ -77,12 +77,12 @@ private void InitializeComponent() this.Text = "Levenberg-Marquardt sample applications"; this.ResumeLayout(false); - } - - #endregion - - private System.Windows.Forms.Button btnApproximation; - private System.Windows.Forms.Button btnTimeSeries; - private System.Windows.Forms.Button btnXOR; - } + } + + #endregion + + private System.Windows.Forms.Button btnApproximation; + private System.Windows.Forms.Button btnTimeSeries; + private System.Windows.Forms.Button btnXOR; + } } \ No newline at end of file diff --git a/Samples/Neuro/Levenberg-Marquardt/MainForm.cs b/Samples/Neuro/Levenberg-Marquardt/MainForm.cs index 20248131d..6d53688e3 100644 --- a/Samples/Neuro/Levenberg-Marquardt/MainForm.cs +++ b/Samples/Neuro/Levenberg-Marquardt/MainForm.cs @@ -1,7 +1,7 @@ using System; using System.Windows.Forms; -namespace Samples.LM +namespace SampleApp { /// /// Levenberg-Marquardt multiple sample applications. diff --git a/Samples/Neuro/Levenberg-Marquardt/Program.cs b/Samples/Neuro/Levenberg-Marquardt/Program.cs index 4bacce66d..316268492 100644 --- a/Samples/Neuro/Levenberg-Marquardt/Program.cs +++ b/Samples/Neuro/Levenberg-Marquardt/Program.cs @@ -1,7 +1,7 @@ using System; using System.Windows.Forms; -namespace Samples.LM +namespace SampleApp { static class Program { diff --git a/Samples/Neuro/Levenberg-Marquardt/app.config b/Samples/Neuro/Levenberg-Marquardt/app.config index e47f3b99b..86fcc8b74 100644 --- a/Samples/Neuro/Levenberg-Marquardt/app.config +++ b/Samples/Neuro/Levenberg-Marquardt/app.config @@ -1,19 +1,6 @@ - - - - - - - - - - - - - - - - - + + + + diff --git a/Samples/Neuro/Perceptron/Accord.dll.config b/Samples/Neuro/Perceptron/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Neuro/Perceptron/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Neuro/Perceptron/Applications/DeltaRule.cs b/Samples/Neuro/Perceptron/Applications/DeltaRule.cs new file mode 100644 index 0000000000..ecf0ccee8 --- /dev/null +++ b/Samples/Neuro/Perceptron/Applications/DeltaRule.cs @@ -0,0 +1,1005 @@ +// Classifier using Delta Rule Learning +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +using System; +using System.Drawing; +using System.Collections; +using System.ComponentModel; +using System.Windows.Forms; +using System.Data; +using System.IO; +using System.Threading; + +using AForge; +using AForge.Neuro; +using AForge.Neuro.Learning; +using AForge.Controls; + +namespace SampleApp +{ + + public class DeltaRuleForm : System.Windows.Forms.Form + { + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Button loadButton; + private System.Windows.Forms.OpenFileDialog openFileDialog; + private System.Windows.Forms.ListView dataList; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.TextBox learningRateBox; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox alphaBox; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox errorLimitBox; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.TextBox iterationsBox; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.TextBox neuronsBox; + private System.Windows.Forms.CheckBox oneNeuronForTwoCheck; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.TextBox currentIterationBox; + private System.Windows.Forms.Button stopButton; + private System.Windows.Forms.Button startButton; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.TextBox classesBox; + private System.Windows.Forms.CheckBox errorLimitCheck; + private System.Windows.Forms.Label label11; + private System.Windows.Forms.TextBox currentErrorBox; + private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.Label label12; + private System.Windows.Forms.ListView weightsList; + private System.Windows.Forms.Label label13; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.ColumnHeader columnHeader3; + private System.Windows.Forms.CheckBox saveFilesCheck; + private AForge.Controls.Chart errorChart; + /// + /// Required designer variable. + /// + private System.ComponentModel.Container components = null; + + private int samples = 0; + private int variables = 0; + private double[,] data = null; + private int[] classes = null; + private int classesCount = 0; + private int[] samplesPerClass = null; + private int neuronsCount = 0; + + private double learningRate = 0.1; + private double sigmoidAlphaValue = 2.0; + private double learningErrorLimit = 0.1; + private double iterationLimit = 1000; + private bool useOneNeuronForTwoClasses = false; + private bool useErrorLimit = true; + private bool saveStatisticsToFiles = false; + + private Thread workerThread = null; + private volatile bool needToStop = false; + + public DeltaRuleForm() + { + InitializeComponent(); + + // update settings controls + UpdateSettings(); + + // initialize charts + errorChart.AddDataSeries("error", Color.Red, Chart.SeriesType.Line, 1); + + openFileDialog.InitialDirectory = Path.Combine(Application.StartupPath, "Sample data (delta rule)"); + } + + /// + /// Clean up any resources being used. + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (components != null) + { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DeltaRuleForm)); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.classesBox = new System.Windows.Forms.TextBox(); + this.label10 = new System.Windows.Forms.Label(); + this.dataList = new System.Windows.Forms.ListView(); + this.loadButton = new System.Windows.Forms.Button(); + this.openFileDialog = new System.Windows.Forms.OpenFileDialog(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.currentErrorBox = new System.Windows.Forms.TextBox(); + this.label11 = new System.Windows.Forms.Label(); + this.label9 = new System.Windows.Forms.Label(); + this.currentIterationBox = new System.Windows.Forms.TextBox(); + this.label8 = new System.Windows.Forms.Label(); + this.label7 = new System.Windows.Forms.Label(); + this.errorLimitCheck = new System.Windows.Forms.CheckBox(); + this.oneNeuronForTwoCheck = new System.Windows.Forms.CheckBox(); + this.neuronsBox = new System.Windows.Forms.TextBox(); + this.label6 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.iterationsBox = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.errorLimitBox = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.alphaBox = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.learningRateBox = new System.Windows.Forms.TextBox(); + this.stopButton = new System.Windows.Forms.Button(); + this.startButton = new System.Windows.Forms.Button(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.saveFilesCheck = new System.Windows.Forms.CheckBox(); + this.label13 = new System.Windows.Forms.Label(); + this.weightsList = new System.Windows.Forms.ListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.errorChart = new AForge.Controls.Chart(); + this.label12 = new System.Windows.Forms.Label(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.groupBox3.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.classesBox); + this.groupBox1.Controls.Add(this.label10); + this.groupBox1.Controls.Add(this.dataList); + this.groupBox1.Controls.Add(this.loadButton); + this.groupBox1.Location = new System.Drawing.Point(16, 15); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(368, 482); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Data"; + // + // classesBox + // + this.classesBox.Location = new System.Drawing.Point(304, 434); + this.classesBox.Name = "classesBox"; + this.classesBox.ReadOnly = true; + this.classesBox.Size = new System.Drawing.Size(48, 26); + this.classesBox.TabIndex = 3; + // + // label10 + // + this.label10.Location = new System.Drawing.Point(224, 437); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(80, 18); + this.label10.TabIndex = 2; + this.label10.Text = "Classes:"; + // + // dataList + // + this.dataList.FullRowSelect = true; + this.dataList.GridLines = true; + this.dataList.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.dataList.Location = new System.Drawing.Point(16, 29); + this.dataList.Name = "dataList"; + this.dataList.Size = new System.Drawing.Size(336, 395); + this.dataList.TabIndex = 0; + this.dataList.UseCompatibleStateImageBehavior = false; + this.dataList.View = System.Windows.Forms.View.Details; + // + // loadButton + // + this.loadButton.Location = new System.Drawing.Point(16, 434); + this.loadButton.Name = "loadButton"; + this.loadButton.Size = new System.Drawing.Size(120, 34); + this.loadButton.TabIndex = 1; + this.loadButton.Text = "&Load"; + this.loadButton.Click += new System.EventHandler(this.loadButton_Click); + // + // openFileDialog + // + this.openFileDialog.Filter = "CSV (Comma delimited) (*.csv)|*.csv"; + this.openFileDialog.Title = "Select data file"; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.currentErrorBox); + this.groupBox2.Controls.Add(this.label11); + this.groupBox2.Controls.Add(this.label9); + this.groupBox2.Controls.Add(this.currentIterationBox); + this.groupBox2.Controls.Add(this.label8); + this.groupBox2.Controls.Add(this.label7); + this.groupBox2.Controls.Add(this.errorLimitCheck); + this.groupBox2.Controls.Add(this.oneNeuronForTwoCheck); + this.groupBox2.Controls.Add(this.neuronsBox); + this.groupBox2.Controls.Add(this.label6); + this.groupBox2.Controls.Add(this.label5); + this.groupBox2.Controls.Add(this.iterationsBox); + this.groupBox2.Controls.Add(this.label4); + this.groupBox2.Controls.Add(this.errorLimitBox); + this.groupBox2.Controls.Add(this.label3); + this.groupBox2.Controls.Add(this.alphaBox); + this.groupBox2.Controls.Add(this.label2); + this.groupBox2.Controls.Add(this.label1); + this.groupBox2.Controls.Add(this.learningRateBox); + this.groupBox2.Controls.Add(this.stopButton); + this.groupBox2.Controls.Add(this.startButton); + this.groupBox2.Location = new System.Drawing.Point(400, 15); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(296, 482); + this.groupBox2.TabIndex = 1; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Training"; + // + // currentErrorBox + // + this.currentErrorBox.Location = new System.Drawing.Point(200, 373); + this.currentErrorBox.Name = "currentErrorBox"; + this.currentErrorBox.ReadOnly = true; + this.currentErrorBox.Size = new System.Drawing.Size(80, 26); + this.currentErrorBox.TabIndex = 20; + // + // label11 + // + this.label11.Location = new System.Drawing.Point(16, 376); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(194, 20); + this.label11.TabIndex = 19; + this.label11.Text = "Current average error:"; + // + // label9 + // + this.label9.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.label9.Location = new System.Drawing.Point(16, 414); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(264, 3); + this.label9.TabIndex = 18; + // + // currentIterationBox + // + this.currentIterationBox.Location = new System.Drawing.Point(200, 336); + this.currentIterationBox.Name = "currentIterationBox"; + this.currentIterationBox.ReadOnly = true; + this.currentIterationBox.Size = new System.Drawing.Size(80, 26); + this.currentIterationBox.TabIndex = 17; + // + // label8 + // + this.label8.Location = new System.Drawing.Point(16, 339); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(157, 23); + this.label8.TabIndex = 16; + this.label8.Text = "Current iteration:"; + // + // label7 + // + this.label7.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.label7.Location = new System.Drawing.Point(16, 322); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(264, 2); + this.label7.TabIndex = 15; + // + // errorLimitCheck + // + this.errorLimitCheck.Location = new System.Drawing.Point(16, 270); + this.errorLimitCheck.Name = "errorLimitCheck"; + this.errorLimitCheck.Size = new System.Drawing.Size(251, 44); + this.errorLimitCheck.TabIndex = 14; + this.errorLimitCheck.Text = "Use error limit (checked) or iterations limit"; + // + // oneNeuronForTwoCheck + // + this.oneNeuronForTwoCheck.Enabled = false; + this.oneNeuronForTwoCheck.Location = new System.Drawing.Point(16, 241); + this.oneNeuronForTwoCheck.Name = "oneNeuronForTwoCheck"; + this.oneNeuronForTwoCheck.Size = new System.Drawing.Size(269, 22); + this.oneNeuronForTwoCheck.TabIndex = 13; + this.oneNeuronForTwoCheck.Text = "Use 1 neuron for 2 classes"; + this.oneNeuronForTwoCheck.CheckedChanged += new System.EventHandler(this.oneNeuronForTwoCheck_CheckedChanged); + // + // neuronsBox + // + this.neuronsBox.Location = new System.Drawing.Point(200, 197); + this.neuronsBox.Name = "neuronsBox"; + this.neuronsBox.ReadOnly = true; + this.neuronsBox.Size = new System.Drawing.Size(80, 26); + this.neuronsBox.TabIndex = 12; + // + // label6 + // + this.label6.Location = new System.Drawing.Point(16, 200); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(94, 18); + this.label6.TabIndex = 11; + this.label6.Text = "Neurons:"; + // + // label5 + // + this.label5.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204))); + this.label5.Location = new System.Drawing.Point(200, 168); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(93, 25); + this.label5.TabIndex = 10; + this.label5.Text = "( 0 - inifinity )"; + // + // iterationsBox + // + this.iterationsBox.Location = new System.Drawing.Point(200, 139); + this.iterationsBox.Name = "iterationsBox"; + this.iterationsBox.Size = new System.Drawing.Size(80, 26); + this.iterationsBox.TabIndex = 9; + // + // label4 + // + this.label4.Location = new System.Drawing.Point(16, 142); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(144, 19); + this.label4.TabIndex = 8; + this.label4.Text = "Iterations limit:"; + // + // errorLimitBox + // + this.errorLimitBox.Location = new System.Drawing.Point(200, 102); + this.errorLimitBox.Name = "errorLimitBox"; + this.errorLimitBox.Size = new System.Drawing.Size(80, 26); + this.errorLimitBox.TabIndex = 7; + // + // label3 + // + this.label3.Location = new System.Drawing.Point(16, 105); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(176, 22); + this.label3.TabIndex = 6; + this.label3.Text = "Learning error limit:"; + // + // alphaBox + // + this.alphaBox.Location = new System.Drawing.Point(200, 66); + this.alphaBox.Name = "alphaBox"; + this.alphaBox.Size = new System.Drawing.Size(80, 26); + this.alphaBox.TabIndex = 5; + // + // label2 + // + this.label2.Location = new System.Drawing.Point(16, 69); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(192, 22); + this.label2.TabIndex = 4; + this.label2.Text = "Sigmoid\'s alpha value:"; + // + // label1 + // + this.label1.Location = new System.Drawing.Point(16, 32); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(120, 24); + this.label1.TabIndex = 2; + this.label1.Text = "Learning rate:"; + // + // learningRateBox + // + this.learningRateBox.Location = new System.Drawing.Point(200, 29); + this.learningRateBox.Name = "learningRateBox"; + this.learningRateBox.Size = new System.Drawing.Size(80, 26); + this.learningRateBox.TabIndex = 3; + // + // stopButton + // + this.stopButton.Enabled = false; + this.stopButton.Location = new System.Drawing.Point(160, 434); + this.stopButton.Name = "stopButton"; + this.stopButton.Size = new System.Drawing.Size(120, 34); + this.stopButton.TabIndex = 6; + this.stopButton.Text = "S&top"; + this.stopButton.Click += new System.EventHandler(this.stopButton_Click); + // + // startButton + // + this.startButton.Enabled = false; + this.startButton.Location = new System.Drawing.Point(16, 434); + this.startButton.Name = "startButton"; + this.startButton.Size = new System.Drawing.Size(120, 34); + this.startButton.TabIndex = 5; + this.startButton.Text = "&Start"; + this.startButton.Click += new System.EventHandler(this.startButton_Click); + // + // groupBox3 + // + this.groupBox3.Controls.Add(this.saveFilesCheck); + this.groupBox3.Controls.Add(this.label13); + this.groupBox3.Controls.Add(this.weightsList); + this.groupBox3.Controls.Add(this.errorChart); + this.groupBox3.Controls.Add(this.label12); + this.groupBox3.Location = new System.Drawing.Point(712, 15); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Size = new System.Drawing.Size(352, 482); + this.groupBox3.TabIndex = 2; + this.groupBox3.TabStop = false; + this.groupBox3.Text = "Solution"; + // + // saveFilesCheck + // + this.saveFilesCheck.Location = new System.Drawing.Point(16, 446); + this.saveFilesCheck.Name = "saveFilesCheck"; + this.saveFilesCheck.Size = new System.Drawing.Size(312, 22); + this.saveFilesCheck.TabIndex = 4; + this.saveFilesCheck.Text = "Save weights and errors to files"; + // + // label13 + // + this.label13.Location = new System.Drawing.Point(16, 248); + this.label13.Name = "label13"; + this.label13.Size = new System.Drawing.Size(160, 18); + this.label13.TabIndex = 3; + this.label13.Text = "Error\'s dynamics:"; + // + // weightsList + // + this.weightsList.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2, + this.columnHeader3}); + this.weightsList.FullRowSelect = true; + this.weightsList.GridLines = true; + this.weightsList.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.weightsList.Location = new System.Drawing.Point(16, 51); + this.weightsList.Name = "weightsList"; + this.weightsList.Size = new System.Drawing.Size(320, 190); + this.weightsList.TabIndex = 2; + this.weightsList.UseCompatibleStateImageBehavior = false; + this.weightsList.View = System.Windows.Forms.View.Details; + // + // columnHeader1 + // + this.columnHeader1.Text = "Neuron"; + // + // columnHeader2 + // + this.columnHeader2.Text = "Weight"; + // + // columnHeader3 + // + this.columnHeader3.Text = "Value"; + // + // errorChart + // + this.errorChart.Location = new System.Drawing.Point(16, 270); + this.errorChart.Name = "errorChart"; + this.errorChart.RangeX = ((AForge.Range)(resources.GetObject("errorChart.RangeX"))); + this.errorChart.RangeY = ((AForge.Range)(resources.GetObject("errorChart.RangeY"))); + this.errorChart.Size = new System.Drawing.Size(320, 161); + this.errorChart.TabIndex = 1; + this.errorChart.Text = "chart1"; + // + // label12 + // + this.label12.Location = new System.Drawing.Point(16, 29); + this.label12.Name = "label12"; + this.label12.Size = new System.Drawing.Size(160, 22); + this.label12.TabIndex = 0; + this.label12.Text = "Network weights:"; + // + // DeltaRuleForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(1076, 512); + this.Controls.Add(this.groupBox3); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.Name = "DeltaRuleForm"; + this.Text = "Classifier using Delta Rule Learning"; + this.Closing += new System.ComponentModel.CancelEventHandler(this.MainForm_Closing); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.groupBox3.ResumeLayout(false); + this.ResumeLayout(false); + + } + #endregion + + + // Delegates to enable async calls for setting controls properties + private delegate void SetTextCallback(System.Windows.Forms.Control control, string text); + private delegate void ClearListCallback(System.Windows.Forms.ListView control); + private delegate ListViewItem AddListItemCallback(System.Windows.Forms.ListView control, string itemText); + private delegate void AddListSubitemCallback(ListViewItem item, string subItemText); + + // Thread safe updating of control's text property + private void SetText(System.Windows.Forms.Control control, string text) + { + if (control.InvokeRequired) + { + SetTextCallback d = new SetTextCallback(SetText); + Invoke(d, new object[] { control, text }); + } + else + { + control.Text = text; + } + } + + // Thread safe clearing of list view + private void ClearList(System.Windows.Forms.ListView control) + { + if (control.InvokeRequired) + { + ClearListCallback d = new ClearListCallback(ClearList); + Invoke(d, new object[] { control }); + } + else + { + control.Items.Clear(); + } + } + + // Thread safe adding of item to list control + private ListViewItem AddListItem(System.Windows.Forms.ListView control, string itemText) + { + ListViewItem item = null; + + if (control.InvokeRequired) + { + AddListItemCallback d = new AddListItemCallback(AddListItem); + item = (ListViewItem)Invoke(d, new object[] { control, itemText }); + } + else + { + item = control.Items.Add(itemText); + } + + return item; + } + + // Thread safe adding of subitem to list control + private void AddListSubitem(ListViewItem item, string subItemText) + { + if (this.InvokeRequired) + { + AddListSubitemCallback d = new AddListSubitemCallback(AddListSubitem); + Invoke(d, new object[] { item, subItemText }); + } + else + { + item.SubItems.Add(subItemText); + } + } + + // On main form closing + private void MainForm_Closing(object sender, System.ComponentModel.CancelEventArgs e) + { + // check if worker thread is running + if ((workerThread != null) && (workerThread.IsAlive)) + { + needToStop = true; + while (!workerThread.Join(100)) + Application.DoEvents(); + } + } + + // Load input data + private void loadButton_Click(object sender, System.EventArgs e) + { + // data file format: + // X1, X2, ..., Xn, class + + // load maximum 10 classes ! + + // show file selection dialog + if (openFileDialog.ShowDialog() == DialogResult.OK) + { + StreamReader reader = null; + + // temp buffers (for 200 samples only) + double[,] tempData = null; + int[] tempClasses = new int[200]; + + // min and max X values + double minX = double.MaxValue; + double maxX = double.MinValue; + + // samples count + samples = 0; + // classes count + classesCount = 0; + samplesPerClass = new int[10]; + + try + { + string str = null; + + // open selected file + reader = File.OpenText(openFileDialog.FileName); + + // read the data + while ((samples < 200) && ((str = reader.ReadLine()) != null)) + { + // split the string + string[] strs = str.Split(';'); + if (strs.Length == 1) + strs = str.Split(','); + + // allocate data array + if (samples == 0) + { + variables = strs.Length - 1; + tempData = new double[200, variables]; + } + + // parse data + for (int j = 0; j < variables; j++) + { + tempData[samples, j] = double.Parse(strs[j]); + } + tempClasses[samples] = int.Parse(strs[variables]); + + // skip classes over 10, except only first 10 classes + if (tempClasses[samples] >= 10) + continue; + + // count the amount of different classes + if (tempClasses[samples] >= classesCount) + classesCount = tempClasses[samples] + 1; + // count samples per class + samplesPerClass[tempClasses[samples]]++; + + // search for min value + if (tempData[samples, 0] < minX) + minX = tempData[samples, 0]; + // search for max value + if (tempData[samples, 0] > maxX) + maxX = tempData[samples, 0]; + + samples++; + } + + // allocate and set data + data = new double[samples, variables]; + Array.Copy(tempData, 0, data, 0, samples * variables); + classes = new int[samples]; + Array.Copy(tempClasses, 0, classes, 0, samples); + } + catch (Exception) + { + MessageBox.Show("Failed reading the file", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + finally + { + // close file + if (reader != null) + reader.Close(); + } + + // update list and chart + UpdateDataListView(); + + classesBox.Text = classesCount.ToString(); + oneNeuronForTwoCheck.Enabled = (classesCount == 2); + + // set neurons count + neuronsCount = ((classesCount == 2) && (useOneNeuronForTwoClasses)) ? 1 : classesCount; + neuronsBox.Text = neuronsCount.ToString(); + + ClearSolution(); + startButton.Enabled = true; + } + } + + // Update settings controls + private void UpdateSettings() + { + learningRateBox.Text = learningRate.ToString(); + alphaBox.Text = sigmoidAlphaValue.ToString(); + errorLimitBox.Text = learningErrorLimit.ToString(); + iterationsBox.Text = iterationLimit.ToString(); + + oneNeuronForTwoCheck.Checked = useOneNeuronForTwoClasses; + errorLimitCheck.Checked = useErrorLimit; + saveFilesCheck.Checked = saveStatisticsToFiles; + } + + // Update data in list view + private void UpdateDataListView() + { + // remove all curent data and columns + dataList.Items.Clear(); + dataList.Columns.Clear(); + + // add columns + for (int i = 0, n = variables; i < n; i++) + { + dataList.Columns.Add(string.Format("X{0}", i + 1), + 50, HorizontalAlignment.Left); + } + dataList.Columns.Add("Class", 50, HorizontalAlignment.Left); + + // add items + for (int i = 0; i < samples; i++) + { + dataList.Items.Add(data[i, 0].ToString()); + + for (int j = 1; j < variables; j++) + { + dataList.Items[i].SubItems.Add(data[i, j].ToString()); + } + dataList.Items[i].SubItems.Add(classes[i].ToString()); + } + } + + // Use or not one neuron to classify two classes + private void oneNeuronForTwoCheck_CheckedChanged(object sender, System.EventArgs e) + { + useOneNeuronForTwoClasses = oneNeuronForTwoCheck.Checked; + // update neurons count box + neuronsCount = ((classesCount == 2) && (useOneNeuronForTwoClasses)) ? 1 : classesCount; + neuronsBox.Text = neuronsCount.ToString(); + } + + // Delegates to enable async calls for setting controls properties + private delegate void EnableCallback(bool enable); + + // Enable/disale controls (safe for threading) + private void EnableControls(bool enable) + { + if (InvokeRequired) + { + EnableCallback d = new EnableCallback(EnableControls); + Invoke(d, new object[] { enable }); + } + else + { + learningRateBox.Enabled = enable; + alphaBox.Enabled = enable; + errorLimitBox.Enabled = enable; + iterationsBox.Enabled = enable; + oneNeuronForTwoCheck.Enabled = ((enable) && (classesCount == 2)); + errorLimitCheck.Enabled = enable; + saveFilesCheck.Enabled = enable; + + loadButton.Enabled = enable; + startButton.Enabled = enable; + stopButton.Enabled = !enable; + } + } + + // Clear current solution + private void ClearSolution() + { + errorChart.UpdateDataSeries("error", null); + weightsList.Items.Clear(); + currentIterationBox.Text = string.Empty; + currentErrorBox.Text = string.Empty; + } + + // On "Start" button click + private void startButton_Click(object sender, System.EventArgs e) + { + // get learning rate + try + { + learningRate = Math.Max(0.00001, Math.Min(1, double.Parse(learningRateBox.Text))); + } + catch + { + learningRate = 0.1; + } + // get sigmoid's alpha value + try + { + sigmoidAlphaValue = Math.Max(0.01, Math.Min(100, double.Parse(alphaBox.Text))); + } + catch + { + sigmoidAlphaValue = 2; + } + // get learning error limit + try + { + learningErrorLimit = Math.Max(0, double.Parse(errorLimitBox.Text)); + } + catch + { + learningErrorLimit = 0.1; + } + // get iterations limit + try + { + iterationLimit = Math.Max(0, int.Parse(iterationsBox.Text)); + } + catch + { + iterationLimit = 1000; + } + + useOneNeuronForTwoClasses = oneNeuronForTwoCheck.Checked; + useErrorLimit = errorLimitCheck.Checked; + saveStatisticsToFiles = saveFilesCheck.Checked; + + // update settings controls + UpdateSettings(); + + // disable all settings controls + EnableControls(false); + + // run worker thread + needToStop = false; + workerThread = new Thread(new ThreadStart(SearchSolution)); + workerThread.Start(); + } + + // On "Stop" button click + private void stopButton_Click(object sender, System.EventArgs e) + { + // stop worker thread + needToStop = true; + while (!workerThread.Join(100)) + Application.DoEvents(); + workerThread = null; + } + + // Worker thread + void SearchSolution() + { + bool reducedNetwork = ((classesCount == 2) && (useOneNeuronForTwoClasses)); + + // prepare learning data + double[][] input = new double[samples][]; + double[][] output = new double[samples][]; + + for (int i = 0; i < samples; i++) + { + input[i] = new double[variables]; + output[i] = new double[neuronsCount]; + + // set input + for (int j = 0; j < variables; j++) + input[i][j] = data[i, j]; + // set output + if (reducedNetwork) + { + output[i][0] = classes[i]; + } + else + { + output[i][classes[i]] = 1; + } + } + + // create perceptron + ActivationNetwork network = new ActivationNetwork( + new SigmoidFunction(sigmoidAlphaValue), variables, neuronsCount); + ActivationLayer layer = network.Layers[0] as ActivationLayer; + // create teacher + DeltaRuleLearning teacher = new DeltaRuleLearning(network); + // set learning rate + teacher.LearningRate = learningRate; + + // iterations + int iteration = 1; + + // statistic files + StreamWriter errorsFile = null; + StreamWriter weightsFile = null; + + try + { + // check if we need to save statistics to files + if (saveStatisticsToFiles) + { + // open files + errorsFile = File.CreateText("errors.csv"); + weightsFile = File.CreateText("weights.csv"); + } + + // erros list + ArrayList errorsList = new ArrayList(); + + // loop + while (!needToStop) + { + // save current weights + if (weightsFile != null) + { + for (int i = 0; i < neuronsCount; i++) + { + weightsFile.Write("neuron" + i + ","); + for (int j = 0; j < variables; j++) + weightsFile.Write(layer.Neurons[i].Weights[j] + ","); + weightsFile.WriteLine(((ActivationNeuron)layer.Neurons[i]).Threshold); + } + } + + // run epoch of learning procedure + double error = teacher.RunEpoch(input, output) / samples; + errorsList.Add(error); + + // save current error + if (errorsFile != null) + { + errorsFile.WriteLine(error); + } + + // show current iteration & error + SetText(currentIterationBox, iteration.ToString()); + SetText(currentErrorBox, error.ToString()); + iteration++; + + // check if we need to stop + if ((useErrorLimit) && (error <= learningErrorLimit)) + break; + if ((!useErrorLimit) && (iterationLimit != 0) && (iteration > iterationLimit)) + break; + } + + // show perceptron's weights + ClearList(weightsList); + for (int i = 0; i < neuronsCount; i++) + { + string neuronName = string.Format("Neuron {0}", i + 1); + ListViewItem item = null; + + // add all weights + for (int j = 0; j < variables; j++) + { + item = AddListItem(weightsList, neuronName); + AddListSubitem(item, string.Format("Weight {0}", j + 1)); + AddListSubitem(item, layer.Neurons[i].Weights[0].ToString("F6")); + } + // threshold + item = AddListItem(weightsList, neuronName); + AddListSubitem(item, "Threshold"); + AddListSubitem(item, ((ActivationNeuron)layer.Neurons[i]).Threshold.ToString("F6")); + } + + // show error's dynamics + double[,] errors = new double[errorsList.Count, 2]; + + for (int i = 0, n = errorsList.Count; i < n; i++) + { + errors[i, 0] = i; + errors[i, 1] = (double)errorsList[i]; + } + + errorChart.RangeX = new Range(0, errorsList.Count - 1); + errorChart.UpdateDataSeries("error", errors); + } + catch (IOException) + { + MessageBox.Show("Failed writing file", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + finally + { + // close files + if (errorsFile != null) + errorsFile.Close(); + if (weightsFile != null) + weightsFile.Close(); + } + + // enable settings controls + EnableControls(true); + } + } +} diff --git a/Samples/Neuro/Perceptron/Applications/DeltaRule.resx b/Samples/Neuro/Perceptron/Applications/DeltaRule.resx new file mode 100644 index 0000000000..d97bbc6ed --- /dev/null +++ b/Samples/Neuro/Perceptron/Applications/DeltaRule.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 17, 17 + + \ No newline at end of file diff --git a/Samples/Neuro/Perceptron/Applications/OneLayerPerceptron.cs b/Samples/Neuro/Perceptron/Applications/OneLayerPerceptron.cs new file mode 100644 index 0000000000..f0283a270 --- /dev/null +++ b/Samples/Neuro/Perceptron/Applications/OneLayerPerceptron.cs @@ -0,0 +1,766 @@ +// One-Layer Perceptron Classifier +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +using System; +using System.Drawing; +using System.Collections; +using System.ComponentModel; +using System.Windows.Forms; +using System.Data; +using System.IO; +using System.Threading; + +using AForge; +using AForge.Neuro; +using AForge.Neuro.Learning; +using AForge.Controls; + +namespace SampleApp +{ + + public class OneLayerPerceptronForm : System.Windows.Forms.Form + { + private System.Windows.Forms.GroupBox groupBox1; + private AForge.Controls.Chart chart; + private System.Windows.Forms.Button loadButton; + private System.Windows.Forms.OpenFileDialog openFileDialog; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox learningRateBox; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox iterationsBox; + private System.Windows.Forms.Button stopButton; + private System.Windows.Forms.Button startButton; + private System.Windows.Forms.CheckBox saveFilesCheck; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.ListView weightsList; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.ColumnHeader columnHeader3; + private System.Windows.Forms.GroupBox groupBox3; + private AForge.Controls.Chart errorChart; + /// + /// Required designer variable. + /// + private System.ComponentModel.Container components = null; + + private int samples = 0; + private double[,] data = null; + private int[] classes = null; + private int classesCount = 0; + private int[] samplesPerClass = null; + + private double learningRate = 0.1; + private bool saveStatisticsToFiles = false; + + private Thread workerThread = null; + private volatile bool needToStop = false; + + // color for data series + private static Color[] dataSereisColors = + { + Color.Red, Color.Blue, + Color.Green, Color.DarkOrange, + Color.Violet, Color.Brown, + Color.Black, Color.Pink, + Color.Olive, Color.Navy + }; + + public OneLayerPerceptronForm() + { + InitializeComponent(); + + // update some controls + saveFilesCheck.Checked = saveStatisticsToFiles; + UpdateSettings(); + + // initialize charts + errorChart.AddDataSeries("error", Color.Red, Chart.SeriesType.ConnectedDots, 3); + + openFileDialog.InitialDirectory = Path.Combine(Application.StartupPath, "Sample data (one layer)"); + } + + /// + /// Clean up any resources being used. + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (components != null) + { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(OneLayerPerceptronForm)); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.loadButton = new System.Windows.Forms.Button(); + this.chart = new AForge.Controls.Chart(); + this.openFileDialog = new System.Windows.Forms.OpenFileDialog(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.weightsList = new System.Windows.Forms.ListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.label4 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.saveFilesCheck = new System.Windows.Forms.CheckBox(); + this.stopButton = new System.Windows.Forms.Button(); + this.startButton = new System.Windows.Forms.Button(); + this.iterationsBox = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.learningRateBox = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.errorChart = new AForge.Controls.Chart(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.groupBox3.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.loadButton); + this.groupBox1.Controls.Add(this.chart); + this.groupBox1.Location = new System.Drawing.Point(16, 15); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(352, 372); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Data"; + // + // loadButton + // + this.loadButton.Location = new System.Drawing.Point(16, 329); + this.loadButton.Name = "loadButton"; + this.loadButton.Size = new System.Drawing.Size(120, 33); + this.loadButton.TabIndex = 1; + this.loadButton.Text = "&Load"; + this.loadButton.Click += new System.EventHandler(this.loadButton_Click); + // + // chart + // + this.chart.Location = new System.Drawing.Point(16, 29); + this.chart.Name = "chart"; + this.chart.RangeX = ((AForge.Range)(resources.GetObject("chart.RangeX"))); + this.chart.RangeY = ((AForge.Range)(resources.GetObject("chart.RangeY"))); + this.chart.Size = new System.Drawing.Size(320, 293); + this.chart.TabIndex = 0; + // + // openFileDialog + // + this.openFileDialog.Filter = "CSV (Comma delimited) (*.csv)|*.csv"; + this.openFileDialog.Title = "Select data file"; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.weightsList); + this.groupBox2.Controls.Add(this.label4); + this.groupBox2.Controls.Add(this.label3); + this.groupBox2.Controls.Add(this.saveFilesCheck); + this.groupBox2.Controls.Add(this.stopButton); + this.groupBox2.Controls.Add(this.startButton); + this.groupBox2.Controls.Add(this.iterationsBox); + this.groupBox2.Controls.Add(this.label2); + this.groupBox2.Controls.Add(this.learningRateBox); + this.groupBox2.Controls.Add(this.label1); + this.groupBox2.Location = new System.Drawing.Point(384, 15); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(384, 599); + this.groupBox2.TabIndex = 1; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Training"; + // + // weightsList + // + this.weightsList.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2, + this.columnHeader3}); + this.weightsList.FullRowSelect = true; + this.weightsList.GridLines = true; + this.weightsList.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.weightsList.Location = new System.Drawing.Point(16, 190); + this.weightsList.Name = "weightsList"; + this.weightsList.Size = new System.Drawing.Size(352, 395); + this.weightsList.TabIndex = 14; + this.weightsList.UseCompatibleStateImageBehavior = false; + this.weightsList.View = System.Windows.Forms.View.Details; + // + // columnHeader1 + // + this.columnHeader1.Text = "Neuron"; + // + // columnHeader2 + // + this.columnHeader2.Text = "Weigh"; + // + // columnHeader3 + // + this.columnHeader3.Text = "Value"; + this.columnHeader3.Width = 65; + // + // label4 + // + this.label4.Location = new System.Drawing.Point(16, 161); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(88, 23); + this.label4.TabIndex = 13; + this.label4.Text = "Weights:"; + // + // label3 + // + this.label3.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.label3.Location = new System.Drawing.Point(16, 146); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(352, 3); + this.label3.TabIndex = 12; + // + // saveFilesCheck + // + this.saveFilesCheck.Location = new System.Drawing.Point(16, 117); + this.saveFilesCheck.Name = "saveFilesCheck"; + this.saveFilesCheck.Size = new System.Drawing.Size(240, 23); + this.saveFilesCheck.TabIndex = 11; + this.saveFilesCheck.Text = "Save weights and errors to files"; + // + // stopButton + // + this.stopButton.Enabled = false; + this.stopButton.Location = new System.Drawing.Point(248, 72); + this.stopButton.Name = "stopButton"; + this.stopButton.Size = new System.Drawing.Size(120, 33); + this.stopButton.TabIndex = 10; + this.stopButton.Text = "S&top"; + this.stopButton.Click += new System.EventHandler(this.stopButton_Click); + // + // startButton + // + this.startButton.Enabled = false; + this.startButton.Location = new System.Drawing.Point(248, 28); + this.startButton.Name = "startButton"; + this.startButton.Size = new System.Drawing.Size(120, 33); + this.startButton.TabIndex = 9; + this.startButton.Text = "&Start"; + this.startButton.Click += new System.EventHandler(this.startButton_Click); + // + // iterationsBox + // + this.iterationsBox.Location = new System.Drawing.Point(144, 73); + this.iterationsBox.Name = "iterationsBox"; + this.iterationsBox.ReadOnly = true; + this.iterationsBox.Size = new System.Drawing.Size(80, 26); + this.iterationsBox.TabIndex = 3; + // + // label2 + // + this.label2.Location = new System.Drawing.Point(16, 76); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(88, 19); + this.label2.TabIndex = 2; + this.label2.Text = "Iterations:"; + // + // learningRateBox + // + this.learningRateBox.Location = new System.Drawing.Point(144, 29); + this.learningRateBox.Name = "learningRateBox"; + this.learningRateBox.Size = new System.Drawing.Size(80, 26); + this.learningRateBox.TabIndex = 1; + // + // label1 + // + this.label1.Location = new System.Drawing.Point(16, 32); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(128, 25); + this.label1.TabIndex = 0; + this.label1.Text = "Learning rate:"; + // + // groupBox3 + // + this.groupBox3.Controls.Add(this.errorChart); + this.groupBox3.Location = new System.Drawing.Point(16, 395); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Size = new System.Drawing.Size(352, 219); + this.groupBox3.TabIndex = 2; + this.groupBox3.TabStop = false; + this.groupBox3.Text = "Error\'s dynamics"; + // + // errorChart + // + this.errorChart.Location = new System.Drawing.Point(16, 29); + this.errorChart.Name = "errorChart"; + this.errorChart.RangeX = ((AForge.Range)(resources.GetObject("errorChart.RangeX"))); + this.errorChart.RangeY = ((AForge.Range)(resources.GetObject("errorChart.RangeY"))); + this.errorChart.Size = new System.Drawing.Size(320, 176); + this.errorChart.TabIndex = 0; + this.errorChart.Text = "chart1"; + // + // OneLayerPerceptronForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(794, 634); + this.Controls.Add(this.groupBox3); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.Name = "OneLayerPerceptronForm"; + this.Text = "One-Layer Perceptron Classifier"; + this.Closing += new System.ComponentModel.CancelEventHandler(this.MainForm_Closing); + this.groupBox1.ResumeLayout(false); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.groupBox3.ResumeLayout(false); + this.ResumeLayout(false); + + } + #endregion + + + + // Delegates to enable async calls for setting controls properties + private delegate void SetTextCallback(System.Windows.Forms.Control control, string text); + private delegate void ClearListCallback(System.Windows.Forms.ListView control); + private delegate ListViewItem AddListItemCallback(System.Windows.Forms.ListView control, string itemText); + private delegate void AddListSubitemCallback(ListViewItem item, string subItemText); + + // Thread safe updating of control's text property + private void SetText(System.Windows.Forms.Control control, string text) + { + if (control.InvokeRequired) + { + SetTextCallback d = new SetTextCallback(SetText); + Invoke(d, new object[] { control, text }); + } + else + { + control.Text = text; + } + } + + // Thread safe clearing of list view + private void ClearList(System.Windows.Forms.ListView control) + { + if (control.InvokeRequired) + { + ClearListCallback d = new ClearListCallback(ClearList); + Invoke(d, new object[] { control }); + } + else + { + control.Items.Clear(); + } + } + + // Thread safe adding of item to list control + private ListViewItem AddListItem(System.Windows.Forms.ListView control, string itemText) + { + ListViewItem item = null; + + if (control.InvokeRequired) + { + AddListItemCallback d = new AddListItemCallback(AddListItem); + item = (ListViewItem)Invoke(d, new object[] { control, itemText }); + } + else + { + item = control.Items.Add(itemText); + } + + return item; + } + + // Thread safe adding of subitem to list control + private void AddListSubitem(ListViewItem item, string subItemText) + { + if (this.InvokeRequired) + { + AddListSubitemCallback d = new AddListSubitemCallback(AddListSubitem); + Invoke(d, new object[] { item, subItemText }); + } + else + { + item.SubItems.Add(subItemText); + } + } + + // On main form closing + private void MainForm_Closing(object sender, System.ComponentModel.CancelEventArgs e) + { + // check if worker thread is running + if ((workerThread != null) && (workerThread.IsAlive)) + { + needToStop = true; + while (!workerThread.Join(100)) + Application.DoEvents(); + } + } + + // Load input data + private void loadButton_Click(object sender, System.EventArgs e) + { + // data file format: + // X1, X2, class + + // load maximum 10 classes ! + + // show file selection dialog + if (openFileDialog.ShowDialog() == DialogResult.OK) + { + StreamReader reader = null; + + // temp buffers (for 200 samples only) + float[,] tempData = new float[200, 2]; + int[] tempClasses = new int[200]; + + // min and max X values + float minX = float.MaxValue; + float maxX = float.MinValue; + + // samples count + samples = 0; + // classes count + classesCount = 0; + samplesPerClass = new int[10]; + + try + { + string str = null; + + // open selected file + reader = File.OpenText(openFileDialog.FileName); + + // read the data + while ((samples < 200) && ((str = reader.ReadLine()) != null)) + { + // split the string + string[] strs = str.Split(';'); + if (strs.Length == 1) + strs = str.Split(','); + + // check tokens count + if (strs.Length != 3) + throw new ApplicationException("Invalid file format"); + + // parse tokens + tempData[samples, 0] = float.Parse(strs[0]); + tempData[samples, 1] = float.Parse(strs[1]); + tempClasses[samples] = int.Parse(strs[2]); + + // skip classes over 10, except only first 10 classes + if (tempClasses[samples] >= 10) + continue; + + // count the amount of different classes + if (tempClasses[samples] >= classesCount) + classesCount = tempClasses[samples] + 1; + // count samples per class + samplesPerClass[tempClasses[samples]]++; + + // search for min value + if (tempData[samples, 0] < minX) + minX = tempData[samples, 0]; + // search for max value + if (tempData[samples, 0] > maxX) + maxX = tempData[samples, 0]; + + samples++; + } + + // allocate and set data + data = new double[samples, 2]; + Array.Copy(tempData, 0, data, 0, samples * 2); + classes = new int[samples]; + Array.Copy(tempClasses, 0, classes, 0, samples); + + // clear current result + weightsList.Items.Clear(); + errorChart.UpdateDataSeries("error", null); + } + catch (Exception) + { + MessageBox.Show("Failed reading the file", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + finally + { + // close file + if (reader != null) + reader.Close(); + } + + // update chart + chart.RangeX = new Range(minX, maxX); + ShowTrainingData(); + + // enable start button + startButton.Enabled = true; + } + } + + // Update settings controls + private void UpdateSettings() + { + learningRateBox.Text = learningRate.ToString(); + } + + // Show training data on chart + private void ShowTrainingData() + { + double[][,] dataSeries = new double[classesCount][,]; + int[] indexes = new int[classesCount]; + + // allocate data arrays + for (int i = 0; i < classesCount; i++) + { + dataSeries[i] = new double[samplesPerClass[i], 2]; + } + + // fill data arrays + for (int i = 0; i < samples; i++) + { + // get sample's class + int dataClass = classes[i]; + // copy data into appropriate array + dataSeries[dataClass][indexes[dataClass], 0] = data[i, 0]; + dataSeries[dataClass][indexes[dataClass], 1] = data[i, 1]; + indexes[dataClass]++; + } + + // remove all previous data series from chart control + chart.RemoveAllDataSeries(); + + // add new data series + for (int i = 0; i < classesCount; i++) + { + string className = string.Format("class" + i); + + // add data series + chart.AddDataSeries(className, dataSereisColors[i], Chart.SeriesType.Dots, 5); + chart.UpdateDataSeries(className, dataSeries[i]); + // add classifier + chart.AddDataSeries(string.Format("classifier" + i), Color.Gray, Chart.SeriesType.Line, 1, false); + } + } + + // Delegates to enable async calls for setting controls properties + private delegate void EnableCallback(bool enable); + + // Enable/disale controls (safe for threading) + private void EnableControls(bool enable) + { + if (InvokeRequired) + { + EnableCallback d = new EnableCallback(EnableControls); + Invoke(d, new object[] { enable }); + } + else + { + learningRateBox.Enabled = enable; + loadButton.Enabled = enable; + startButton.Enabled = enable; + saveFilesCheck.Enabled = enable; + stopButton.Enabled = !enable; + } + } + + // On "Start" button click + private void startButton_Click(object sender, System.EventArgs e) + { + // get learning rate + try + { + learningRate = Math.Max(0.00001, Math.Min(1, double.Parse(learningRateBox.Text))); + } + catch + { + learningRate = 0.1; + } + saveStatisticsToFiles = saveFilesCheck.Checked; + + // update settings controls + UpdateSettings(); + + // disable all settings controls + EnableControls(false); + + // run worker thread + needToStop = false; + workerThread = new Thread(new ThreadStart(SearchSolution)); + workerThread.Start(); + } + + // On "Stop" button click + private void stopButton_Click(object sender, System.EventArgs e) + { + // stop worker thread + needToStop = true; + while (!workerThread.Join(100)) + Application.DoEvents(); + workerThread = null; + } + + // Worker thread + void SearchSolution() + { + // prepare learning data + double[][] input = new double[samples][]; + double[][] output = new double[samples][]; + + for (int i = 0; i < samples; i++) + { + input[i] = new double[2]; + output[i] = new double[classesCount]; + + // set input + input[i][0] = data[i, 0]; + input[i][1] = data[i, 1]; + // set output + output[i][classes[i]] = 1; + } + + // create perceptron + ActivationNetwork network = new ActivationNetwork(new ThresholdFunction(), 2, classesCount); + ActivationLayer layer = network.Layers[0] as ActivationLayer; + // create teacher + PerceptronLearning teacher = new PerceptronLearning(network); + // set learning rate + teacher.LearningRate = learningRate; + + // iterations + int iteration = 1; + + // statistic files + StreamWriter errorsFile = null; + StreamWriter weightsFile = null; + + try + { + // check if we need to save statistics to files + if (saveStatisticsToFiles) + { + // open files + errorsFile = File.CreateText("errors.csv"); + weightsFile = File.CreateText("weights.csv"); + } + + // erros list + ArrayList errorsList = new ArrayList(); + + // loop + while (!needToStop) + { + // save current weights + if (weightsFile != null) + { + for (int i = 0; i < classesCount; i++) + { + weightsFile.Write("neuron" + i + ","); + weightsFile.Write(layer.Neurons[i].Weights[0] + ","); + weightsFile.Write(layer.Neurons[i].Weights[1] + ","); + weightsFile.WriteLine(((ActivationNeuron)layer.Neurons[i]).Threshold); + } + } + + // run epoch of learning procedure + double error = teacher.RunEpoch(input, output); + errorsList.Add(error); + + // save current error + if (errorsFile != null) + { + errorsFile.WriteLine(error); + } + + // show current iteration + SetText(iterationsBox, iteration.ToString()); + + // stop if no error + if (error == 0) + break; + + // show classifiers + for (int j = 0; j < classesCount; j++) + { + double k = (layer.Neurons[j].Weights[1] != 0) ? (-layer.Neurons[j].Weights[0] / layer.Neurons[j].Weights[1]) : 0; + double b = (layer.Neurons[j].Weights[1] != 0) ? (-((ActivationNeuron)layer.Neurons[j]).Threshold / layer.Neurons[j].Weights[1]) : 0; + + double[,] classifier = new double[2, 2] { + { chart.RangeX.Min, chart.RangeX.Min * k + b }, + { chart.RangeX.Max, chart.RangeX.Max * k + b } + }; + + // update chart + chart.UpdateDataSeries(string.Format("classifier" + j), classifier); + } + + iteration++; + } + + // show perceptron's weights + ClearList(weightsList); + for (int i = 0; i < classesCount; i++) + { + string neuronName = string.Format("Neuron {0}", i + 1); + + // weight 0 + ListViewItem item = AddListItem(weightsList, neuronName); + AddListSubitem(item, "Weight 1"); + AddListSubitem(item, layer.Neurons[i].Weights[0].ToString("F6")); + // weight 1 + item = AddListItem(weightsList, neuronName); + AddListSubitem(item, "Weight 2"); + AddListSubitem(item, layer.Neurons[i].Weights[1].ToString("F6")); + // threshold + item = AddListItem(weightsList, neuronName); + AddListSubitem(item, "Threshold"); + AddListSubitem(item, ((ActivationNeuron)layer.Neurons[i]).Threshold.ToString("F6")); + } + + // show error's dynamics + double[,] errors = new double[errorsList.Count, 2]; + + for (int i = 0, n = errorsList.Count; i < n; i++) + { + errors[i, 0] = i; + errors[i, 1] = (double)errorsList[i]; + } + + errorChart.RangeX = new Range(0, errorsList.Count - 1); + errorChart.UpdateDataSeries("error", errors); + } + catch (IOException) + { + MessageBox.Show("Failed writing file", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + finally + { + // close files + if (errorsFile != null) + errorsFile.Close(); + if (weightsFile != null) + weightsFile.Close(); + } + + // enable settings controls + EnableControls(true); + } + } +} diff --git a/Samples/Neuro/Perceptron/Applications/OneLayerPerceptron.resx b/Samples/Neuro/Perceptron/Applications/OneLayerPerceptron.resx new file mode 100644 index 0000000000..d97bbc6ed --- /dev/null +++ b/Samples/Neuro/Perceptron/Applications/OneLayerPerceptron.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 17, 17 + + \ No newline at end of file diff --git a/Samples/Neuro/Perceptron/Applications/Perceptron.cs b/Samples/Neuro/Perceptron/Applications/Perceptron.cs new file mode 100644 index 0000000000..c31b38ed1 --- /dev/null +++ b/Samples/Neuro/Perceptron/Applications/Perceptron.cs @@ -0,0 +1,808 @@ +// Perceptron Classifier +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +using System; +using System.Drawing; +using System.Collections; +using System.ComponentModel; +using System.Windows.Forms; +using System.Data; +using System.IO; +using System.Threading; + +using AForge; +using AForge.Neuro; +using AForge.Neuro.Learning; +using AForge.Controls; + +namespace SampleApp +{ + + public class PerceptronForm : System.Windows.Forms.Form + { + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.ListView dataList; + private System.Windows.Forms.Button loadButton; + private System.Windows.Forms.OpenFileDialog openFileDialog; + private AForge.Controls.Chart chart; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox learningRateBox; + private System.Windows.Forms.Button startButton; + private System.Windows.Forms.Label noVisualizationLabel; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.ListView weightsList; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.TextBox iterationsBox; + private System.Windows.Forms.Button stopButton; + private System.Windows.Forms.Label label5; + private AForge.Controls.Chart errorChart; + private System.Windows.Forms.CheckBox saveFilesCheck; + /// + /// Required designer variable. + /// + private System.ComponentModel.Container components = null; + + private int samples = 0; + private int variables = 0; + private double[,] data = null; + private int[] classes = null; + + private double learningRate = 0.1; + private bool saveStatisticsToFiles = false; + + private Thread workerThread = null; + private volatile bool needToStop = false; + + public PerceptronForm() + { + InitializeComponent(); + + // initialize charts + chart.AddDataSeries("class1", Color.Red, Chart.SeriesType.Dots, 5); + chart.AddDataSeries("class2", Color.Blue, Chart.SeriesType.Dots, 5); + chart.AddDataSeries("classifier", Color.Gray, Chart.SeriesType.Line, 1, false); + + errorChart.AddDataSeries("error", Color.Red, Chart.SeriesType.ConnectedDots, 3, false); + + // update some controls + saveFilesCheck.Checked = saveStatisticsToFiles; + UpdateSettings(); + + openFileDialog.InitialDirectory = Path.Combine(Application.StartupPath, "Sample data (perceptron)"); + } + + /// + /// Clean up any resources being used. + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (components != null) + { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PerceptronForm)); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.chart = new AForge.Controls.Chart(); + this.loadButton = new System.Windows.Forms.Button(); + this.dataList = new System.Windows.Forms.ListView(); + this.noVisualizationLabel = new System.Windows.Forms.Label(); + this.openFileDialog = new System.Windows.Forms.OpenFileDialog(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.saveFilesCheck = new System.Windows.Forms.CheckBox(); + this.errorChart = new AForge.Controls.Chart(); + this.label5 = new System.Windows.Forms.Label(); + this.stopButton = new System.Windows.Forms.Button(); + this.iterationsBox = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.weightsList = new System.Windows.Forms.ListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.label3 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.startButton = new System.Windows.Forms.Button(); + this.learningRateBox = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.chart); + this.groupBox1.Controls.Add(this.loadButton); + this.groupBox1.Controls.Add(this.dataList); + this.groupBox1.Controls.Add(this.noVisualizationLabel); + this.groupBox1.Location = new System.Drawing.Point(16, 15); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(304, 613); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Data"; + // + // chart + // + this.chart.Location = new System.Drawing.Point(16, 314); + this.chart.Name = "chart"; + this.chart.RangeX = ((AForge.Range)(resources.GetObject("chart.RangeX"))); + this.chart.RangeY = ((AForge.Range)(resources.GetObject("chart.RangeY"))); + this.chart.Size = new System.Drawing.Size(272, 249); + this.chart.TabIndex = 2; + this.chart.Text = "chart1"; + // + // loadButton + // + this.loadButton.Location = new System.Drawing.Point(16, 570); + this.loadButton.Name = "loadButton"; + this.loadButton.Size = new System.Drawing.Size(120, 34); + this.loadButton.TabIndex = 1; + this.loadButton.Text = "&Load"; + this.loadButton.Click += new System.EventHandler(this.loadButton_Click); + // + // dataList + // + this.dataList.FullRowSelect = true; + this.dataList.GridLines = true; + this.dataList.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.dataList.Location = new System.Drawing.Point(16, 29); + this.dataList.Name = "dataList"; + this.dataList.Size = new System.Drawing.Size(272, 278); + this.dataList.TabIndex = 0; + this.dataList.UseCompatibleStateImageBehavior = false; + this.dataList.View = System.Windows.Forms.View.Details; + // + // noVisualizationLabel + // + this.noVisualizationLabel.Location = new System.Drawing.Point(16, 314); + this.noVisualizationLabel.Name = "noVisualizationLabel"; + this.noVisualizationLabel.Size = new System.Drawing.Size(272, 249); + this.noVisualizationLabel.TabIndex = 2; + this.noVisualizationLabel.Text = "Visualization is not available."; + this.noVisualizationLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + this.noVisualizationLabel.Visible = false; + // + // openFileDialog + // + this.openFileDialog.Filter = "CSV (Comma delimited) (*.csv)|*.csv"; + this.openFileDialog.Title = "Select data file"; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.saveFilesCheck); + this.groupBox2.Controls.Add(this.errorChart); + this.groupBox2.Controls.Add(this.label5); + this.groupBox2.Controls.Add(this.stopButton); + this.groupBox2.Controls.Add(this.iterationsBox); + this.groupBox2.Controls.Add(this.label4); + this.groupBox2.Controls.Add(this.weightsList); + this.groupBox2.Controls.Add(this.label3); + this.groupBox2.Controls.Add(this.label2); + this.groupBox2.Controls.Add(this.startButton); + this.groupBox2.Controls.Add(this.learningRateBox); + this.groupBox2.Controls.Add(this.label1); + this.groupBox2.Location = new System.Drawing.Point(336, 15); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(384, 613); + this.groupBox2.TabIndex = 1; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Training"; + // + // saveFilesCheck + // + this.saveFilesCheck.Location = new System.Drawing.Point(16, 117); + this.saveFilesCheck.Name = "saveFilesCheck"; + this.saveFilesCheck.Size = new System.Drawing.Size(291, 23); + this.saveFilesCheck.TabIndex = 11; + this.saveFilesCheck.Text = "Save weights and errors to files"; + // + // errorChart + // + this.errorChart.Location = new System.Drawing.Point(16, 395); + this.errorChart.Name = "errorChart"; + this.errorChart.RangeX = ((AForge.Range)(resources.GetObject("errorChart.RangeX"))); + this.errorChart.RangeY = ((AForge.Range)(resources.GetObject("errorChart.RangeY"))); + this.errorChart.Size = new System.Drawing.Size(352, 204); + this.errorChart.TabIndex = 10; + // + // label5 + // + this.label5.Location = new System.Drawing.Point(16, 365); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(162, 22); + this.label5.TabIndex = 9; + this.label5.Text = "Error\'s dynamics:"; + // + // stopButton + // + this.stopButton.Enabled = false; + this.stopButton.Location = new System.Drawing.Point(248, 72); + this.stopButton.Name = "stopButton"; + this.stopButton.Size = new System.Drawing.Size(120, 33); + this.stopButton.TabIndex = 8; + this.stopButton.Text = "S&top"; + this.stopButton.Click += new System.EventHandler(this.stopButton_Click); + // + // iterationsBox + // + this.iterationsBox.Location = new System.Drawing.Point(144, 73); + this.iterationsBox.Name = "iterationsBox"; + this.iterationsBox.ReadOnly = true; + this.iterationsBox.Size = new System.Drawing.Size(80, 26); + this.iterationsBox.TabIndex = 7; + // + // label4 + // + this.label4.Location = new System.Drawing.Point(16, 76); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(104, 23); + this.label4.TabIndex = 6; + this.label4.Text = "Iterations:"; + // + // weightsList + // + this.weightsList.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2}); + this.weightsList.FullRowSelect = true; + this.weightsList.GridLines = true; + this.weightsList.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.weightsList.Location = new System.Drawing.Point(16, 190); + this.weightsList.Name = "weightsList"; + this.weightsList.Size = new System.Drawing.Size(352, 161); + this.weightsList.TabIndex = 5; + this.weightsList.UseCompatibleStateImageBehavior = false; + this.weightsList.View = System.Windows.Forms.View.Details; + // + // columnHeader1 + // + this.columnHeader1.Text = "Weight"; + this.columnHeader1.Width = 70; + // + // columnHeader2 + // + this.columnHeader2.Text = "Value"; + this.columnHeader2.Width = 100; + // + // label3 + // + this.label3.Location = new System.Drawing.Point(16, 161); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(179, 23); + this.label3.TabIndex = 4; + this.label3.Text = "Perceptron weights:"; + // + // label2 + // + this.label2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.label2.Location = new System.Drawing.Point(16, 146); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(352, 3); + this.label2.TabIndex = 3; + // + // startButton + // + this.startButton.Enabled = false; + this.startButton.Location = new System.Drawing.Point(248, 28); + this.startButton.Name = "startButton"; + this.startButton.Size = new System.Drawing.Size(120, 33); + this.startButton.TabIndex = 2; + this.startButton.Text = "&Start"; + this.startButton.Click += new System.EventHandler(this.startButton_Click); + // + // learningRateBox + // + this.learningRateBox.Location = new System.Drawing.Point(144, 29); + this.learningRateBox.Name = "learningRateBox"; + this.learningRateBox.Size = new System.Drawing.Size(80, 26); + this.learningRateBox.TabIndex = 1; + // + // label1 + // + this.label1.Location = new System.Drawing.Point(16, 32); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(120, 24); + this.label1.TabIndex = 0; + this.label1.Text = "Learning rate:"; + // + // PerceptronForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(732, 646); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.Name = "PerceptronForm"; + this.Text = "Perceptron Classifier"; + this.Closing += new System.ComponentModel.CancelEventHandler(this.MainForm_Closing); + this.groupBox1.ResumeLayout(false); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.ResumeLayout(false); + + } + #endregion + + + + // Delegates to enable async calls for setting controls properties + private delegate void SetTextCallback(System.Windows.Forms.Control control, string text); + private delegate void ClearListCallback(System.Windows.Forms.ListView control); + private delegate ListViewItem AddListItemCallback(System.Windows.Forms.ListView control, string itemText); + private delegate void AddListSubitemCallback(ListViewItem item, string subItemText); + + // Thread safe updating of control's text property + private void SetText(System.Windows.Forms.Control control, string text) + { + if (control.InvokeRequired) + { + SetTextCallback d = new SetTextCallback(SetText); + Invoke(d, new object[] { control, text }); + } + else + { + control.Text = text; + } + } + + // Thread safe clearing of list view + private void ClearList(System.Windows.Forms.ListView control) + { + if (control.InvokeRequired) + { + ClearListCallback d = new ClearListCallback(ClearList); + Invoke(d, new object[] { control }); + } + else + { + control.Items.Clear(); + } + } + + // Thread safe adding of item to list control + private ListViewItem AddListItem(System.Windows.Forms.ListView control, string itemText) + { + ListViewItem item = null; + + if (control.InvokeRequired) + { + AddListItemCallback d = new AddListItemCallback(AddListItem); + item = (ListViewItem)Invoke(d, new object[] { control, itemText }); + } + else + { + item = control.Items.Add(itemText); + } + + return item; + } + + // Thread safe adding of subitem to list control + private void AddListSubitem(ListViewItem item, string subItemText) + { + if (this.InvokeRequired) + { + AddListSubitemCallback d = new AddListSubitemCallback(AddListSubitem); + Invoke(d, new object[] { item, subItemText }); + } + else + { + item.SubItems.Add(subItemText); + } + } + + // On main form closing + private void MainForm_Closing(object sender, System.ComponentModel.CancelEventArgs e) + { + // check if worker thread is running + if ((workerThread != null) && (workerThread.IsAlive)) + { + needToStop = true; + while (!workerThread.Join(100)) + Application.DoEvents(); + } + } + + // On "Load" button click - load data + private void loadButton_Click(object sender, System.EventArgs e) + { + // data file format: + // X1, X2, ... Xn, class (0|1) + + // show file selection dialog + if (openFileDialog.ShowDialog() == DialogResult.OK) + { + StreamReader reader = null; + + // temp buffers (for 50 samples only) + float[,] tempData = null; + int[] tempClasses = new int[50]; + + // min and max X values + float minX = float.MaxValue; + float maxX = float.MinValue; + + // samples count + samples = 0; + + try + { + string str = null; + + // open selected file + reader = File.OpenText(openFileDialog.FileName); + + // read the data + while ((samples < 50) && ((str = reader.ReadLine()) != null)) + { + // split the string + string[] strs = str.Split(';'); + if (strs.Length == 1) + strs = str.Split(','); + + // allocate data array + if (samples == 0) + { + variables = strs.Length - 1; + tempData = new float[50, variables]; + } + + // parse data + for (int j = 0; j < variables; j++) + { + tempData[samples, j] = float.Parse(strs[j]); + } + tempClasses[samples] = int.Parse(strs[variables]); + + // search for min value + if (tempData[samples, 0] < minX) + minX = tempData[samples, 0]; + // search for max value + if (tempData[samples, 0] > maxX) + maxX = tempData[samples, 0]; + + samples++; + } + + // allocate and set data + data = new double[samples, variables]; + Array.Copy(tempData, 0, data, 0, samples * variables); + classes = new int[samples]; + Array.Copy(tempClasses, 0, classes, 0, samples); + + // clear current result + ClearCurrentSolution(); + } + catch (Exception) + { + MessageBox.Show("Failed reading the file", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + finally + { + // close file + if (reader != null) + reader.Close(); + } + + // update list and chart + UpdateDataListView(); + + // show chart or not + bool showChart = (variables == 2); + + if (showChart) + { + chart.RangeX = new Range(minX, maxX); + ShowTrainingData(); + } + + chart.Visible = showChart; + noVisualizationLabel.Visible = !showChart; + + // enable start button + startButton.Enabled = true; + } + } + + // Update settings controls + private void UpdateSettings() + { + learningRateBox.Text = learningRate.ToString(); + } + + // Update data in list view + private void UpdateDataListView() + { + // remove all curent data and columns + dataList.Items.Clear(); + dataList.Columns.Clear(); + + // add columns + for (int i = 0, n = variables; i < n; i++) + { + dataList.Columns.Add(string.Format("X{0}", i + 1), + 50, HorizontalAlignment.Left); + } + dataList.Columns.Add("Class", 50, HorizontalAlignment.Left); + + // add items + for (int i = 0; i < samples; i++) + { + dataList.Items.Add(data[i, 0].ToString()); + + for (int j = 1; j < variables; j++) + { + dataList.Items[i].SubItems.Add(data[i, j].ToString()); + } + dataList.Items[i].SubItems.Add(classes[i].ToString()); + } + } + + // Show training data on chart + private void ShowTrainingData() + { + int class1Size = 0; + int class2Size = 0; + + // calculate number of samples in each class + for (int i = 0, n = samples; i < n; i++) + { + if (classes[i] == 0) + class1Size++; + else + class2Size++; + } + + // allocate classes arrays + double[,] class1 = new double[class1Size, 2]; + double[,] class2 = new double[class2Size, 2]; + + // fill classes arrays + for (int i = 0, c1 = 0, c2 = 0; i < samples; i++) + { + if (classes[i] == 0) + { + // class 1 + class1[c1, 0] = data[i, 0]; + class1[c1, 1] = data[i, 1]; + c1++; + } + else + { + // class 2 + class2[c2, 0] = data[i, 0]; + class2[c2, 1] = data[i, 1]; + c2++; + } + } + + // updata chart control + chart.UpdateDataSeries("class1", class1); + chart.UpdateDataSeries("class2", class2); + } + + // Delegates to enable async calls for setting controls properties + private delegate void EnableCallback(bool enable); + + // Enable/disale controls (safe for threading) + private void EnableControls(bool enable) + { + if (InvokeRequired) + { + EnableCallback d = new EnableCallback(EnableControls); + Invoke(d, new object[] { enable }); + } + else + { + learningRateBox.Enabled = enable; + loadButton.Enabled = enable; + startButton.Enabled = enable; + saveFilesCheck.Enabled = enable; + stopButton.Enabled = !enable; + } + } + + // Clear current solution + private void ClearCurrentSolution() + { + chart.UpdateDataSeries("classifier", null); + errorChart.UpdateDataSeries("error", null); + weightsList.Items.Clear(); + } + + // On button "Start" - start learning procedure + private void startButton_Click(object sender, System.EventArgs e) + { + // get learning rate + try + { + learningRate = Math.Max(0.00001, Math.Min(1, double.Parse(learningRateBox.Text))); + } + catch + { + learningRate = 0.1; + } + saveStatisticsToFiles = saveFilesCheck.Checked; + + // update settings controls + UpdateSettings(); + + // disable all settings controls + EnableControls(false); + + // run worker thread + needToStop = false; + workerThread = new Thread(new ThreadStart(SearchSolution)); + workerThread.Start(); + } + + // On button "Stop" - stop learning procedure + private void stopButton_Click(object sender, System.EventArgs e) + { + // stop worker thread + needToStop = true; + while (!workerThread.Join(100)) + Application.DoEvents(); + workerThread = null; + } + + // Worker thread + void SearchSolution() + { + // prepare learning data + double[][] input = new double[samples][]; + double[][] output = new double[samples][]; + + for (int i = 0; i < samples; i++) + { + input[i] = new double[variables]; + output[i] = new double[1]; + + // copy input + for (int j = 0; j < variables; j++) + input[i][j] = data[i, j]; + // copy output + output[i][0] = classes[i]; + } + + // create perceptron + ActivationNetwork network = new ActivationNetwork(new ThresholdFunction(), variables, 1); + ActivationNeuron neuron = network.Layers[0].Neurons[0] as ActivationNeuron; + // create teacher + PerceptronLearning teacher = new PerceptronLearning(network); + // set learning rate + teacher.LearningRate = learningRate; + + // iterations + int iteration = 1; + + // statistic files + StreamWriter errorsFile = null; + StreamWriter weightsFile = null; + + try + { + // check if we need to save statistics to files + if (saveStatisticsToFiles) + { + // open files + errorsFile = File.CreateText("errors.csv"); + weightsFile = File.CreateText("weights.csv"); + } + + // erros list + ArrayList errorsList = new ArrayList(); + + // loop + while (!needToStop) + { + // save current weights + if (weightsFile != null) + { + for (int i = 0; i < variables; i++) + { + weightsFile.Write(neuron.Weights[i] + ","); + } + weightsFile.WriteLine(neuron.Threshold); + } + + // run epoch of learning procedure + double error = teacher.RunEpoch(input, output); + errorsList.Add(error); + + // show current iteration + SetText(iterationsBox, iteration.ToString()); + + // save current error + if (errorsFile != null) + { + errorsFile.WriteLine(error); + } + + // show classifier in the case of 2 dimensional data + if ((neuron.InputsCount == 2) && (neuron.Weights[1] != 0)) + { + double k = -neuron.Weights[0] / neuron.Weights[1]; + double b = -neuron.Threshold / neuron.Weights[1]; + + double[,] classifier = new double[2, 2] { + { chart.RangeX.Min, chart.RangeX.Min * k + b }, + { chart.RangeX.Max, chart.RangeX.Max * k + b } + }; + // update chart + chart.UpdateDataSeries("classifier", classifier); + } + + // stop if no error + if (error == 0) + break; + + iteration++; + } + + // show perceptron's weights + ListViewItem item = null; + + ClearList(weightsList); + for (int i = 0; i < variables; i++) + { + item = AddListItem(weightsList, string.Format("Weight {0}", i + 1)); + AddListSubitem(item, neuron.Weights[i].ToString("F6")); + } + item = AddListItem(weightsList, "Threshold"); + AddListSubitem(item, neuron.Threshold.ToString("F6")); + + // show error's dynamics + double[,] errors = new double[errorsList.Count, 2]; + + for (int i = 0, n = errorsList.Count; i < n; i++) + { + errors[i, 0] = i; + errors[i, 1] = (double)errorsList[i]; + } + + errorChart.RangeX = new Range(0, errorsList.Count - 1); + errorChart.RangeY = new Range(0, samples); + errorChart.UpdateDataSeries("error", errors); + } + catch (IOException) + { + MessageBox.Show("Failed writing file", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + finally + { + // close files + if (errorsFile != null) + errorsFile.Close(); + if (weightsFile != null) + weightsFile.Close(); + } + + // enable settings controls + EnableControls(true); + } + } +} diff --git a/Samples/Neuro/Perceptron/Applications/Perceptron.resx b/Samples/Neuro/Perceptron/Applications/Perceptron.resx new file mode 100644 index 0000000000..d97bbc6ed --- /dev/null +++ b/Samples/Neuro/Perceptron/Applications/Perceptron.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 17, 17 + + \ No newline at end of file diff --git a/Samples/Neuro/Perceptron/MainForm.Designer.cs b/Samples/Neuro/Perceptron/MainForm.Designer.cs new file mode 100644 index 0000000000..3ed9054d4 --- /dev/null +++ b/Samples/Neuro/Perceptron/MainForm.Designer.cs @@ -0,0 +1,92 @@ +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); + this.btnApproximation = new System.Windows.Forms.Button(); + this.btnTimeSeries = new System.Windows.Forms.Button(); + this.btnXOR = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // btnApproximation + // + this.btnApproximation.Location = new System.Drawing.Point(18, 18); + this.btnApproximation.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.btnApproximation.Name = "btnApproximation"; + this.btnApproximation.Size = new System.Drawing.Size(240, 120); + this.btnApproximation.TabIndex = 0; + this.btnApproximation.Text = "Delta-Rule Learning"; + this.btnApproximation.UseVisualStyleBackColor = true; + this.btnApproximation.Click += new System.EventHandler(this.btnDeltaRule_Click); + // + // btnTimeSeries + // + this.btnTimeSeries.Location = new System.Drawing.Point(267, 18); + this.btnTimeSeries.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.btnTimeSeries.Name = "btnTimeSeries"; + this.btnTimeSeries.Size = new System.Drawing.Size(240, 120); + this.btnTimeSeries.TabIndex = 0; + this.btnTimeSeries.Text = "One Layer Perceptron"; + this.btnTimeSeries.UseVisualStyleBackColor = true; + this.btnTimeSeries.Click += new System.EventHandler(this.btnOneLayerPerceptron_Click); + // + // btnXOR + // + this.btnXOR.Location = new System.Drawing.Point(516, 18); + this.btnXOR.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.btnXOR.Name = "btnXOR"; + this.btnXOR.Size = new System.Drawing.Size(240, 120); + this.btnXOR.TabIndex = 0; + this.btnXOR.Text = "Perceptron"; + this.btnXOR.UseVisualStyleBackColor = true; + this.btnXOR.Click += new System.EventHandler(this.btnPerceptron_Click); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(776, 154); + this.Controls.Add(this.btnXOR); + this.Controls.Add(this.btnTimeSeries); + this.Controls.Add(this.btnApproximation); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.Name = "MainForm"; + this.Text = "Perceptron sample applications"; + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button btnApproximation; + private System.Windows.Forms.Button btnTimeSeries; + private System.Windows.Forms.Button btnXOR; + } +} \ No newline at end of file diff --git a/Samples/Neuro/Perceptron/MainForm.cs b/Samples/Neuro/Perceptron/MainForm.cs new file mode 100644 index 0000000000..ab49a1346 --- /dev/null +++ b/Samples/Neuro/Perceptron/MainForm.cs @@ -0,0 +1,60 @@ +using System; +using System.Windows.Forms; + +namespace SampleApp +{ + /// + /// Perceptron multiple sample applications. + /// + /// + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + } + + + /// + /// Launches the delta rule sample application. + /// + /// + private void btnDeltaRule_Click(object sender, EventArgs e) + { + launch(new DeltaRuleForm()); + } + + /// + /// Launches the one-layer perceptron sample application. + /// + /// + private void btnOneLayerPerceptron_Click(object sender, EventArgs e) + { + launch(new OneLayerPerceptronForm()); + } + + /// + /// Launches the Perceptron sample application. + /// + /// + private void btnPerceptron_Click(object sender, EventArgs e) + { + launch(new PerceptronForm()); + } + + + + + private void launch(Form form) + { + form.Show(); + form.FormClosed += new FormClosedEventHandler(form_FormClosed); + WindowState = FormWindowState.Minimized; + } + + void form_FormClosed(object sender, FormClosedEventArgs e) + { + WindowState = FormWindowState.Normal; + } + } +} diff --git a/Samples/Neuro/Perceptron/MainForm.resx b/Samples/Neuro/Perceptron/MainForm.resx new file mode 100644 index 0000000000..d41ef54cf --- /dev/null +++ b/Samples/Neuro/Perceptron/MainForm.resx @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + AAABAAMAEBAAAAAAIABoBAAANgAAACAgAAAAACAAqBAAAJ4EAAAwMAAAAAAgAKglAABGFQAAKAAAABAA + AAAgAAAAAQAgAAAAAABABAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wEAAAA7AAAAVQAA + AF0AAAAJ////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAtwAA + ADkAAAA/AAAAff///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABEAAAADAAAACQAAANcAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADVAAAAJf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAvQAAAEn///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAGwAAAM0AAACrAAAANf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAGQAAAJcAAACtAAAAlwAAAIEAAAA/////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAGUAAAAxAAAAfwAAAJ8AAAALAAAAi////wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAABlAAAAMQAAAGMAAAC7AAAADQAAAIn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAFwAAAJkAAABtAAAA2wAAAIEAAAA9////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAZAAAAgQAAAPMAAAAx////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAAAkAAADvAAAADf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAA2wAA + AB3///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AK8AAAAzAAAAAwAAABP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABTAAAAaQAAADEAAADD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAAwAAAFcAAABVAAAAPf///wH///8B////Af///wEAAP//AAD//wAA//8AAP//AAD//wAA + //8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//KAAAACAAAABAAAAAAQAgAAAA + AACAEAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABcAAABRAAAAYQAAAEcAAAAL////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAvAAAApwAAAF8AAABBAAAAfwAAAKMAAAAh////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAI8AAAD5AAAAcwAAAAMAAAAHAAAApQAAAKkAAAAL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAdwAAAOEAAABrAAAAA////wEAAABNAAAA5wAAAFv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAPAAAAMQAAAA3///8B////AQAAAB0AAADhAAAAsf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ANMAAAD5AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAtwAAAP8AAAAz////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAACdAAAA/wAAAF3///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAIcAAAD/AAAAh////wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAcQAAAP8AAACdAAAAA////wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABfAAAA/wAAALsAAAAf////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAYwAAANcAAAD/AAAA9QAA + AN0AAAClAAAAK////wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACQAAAIMAAADRAAAAjQAA + AP8AAADjAAAAYwAAAKcAAADFAAAAMf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABXAAAA2QAA + AC0AAAA1AAAA8wAAAOsAAAAv////AQAAAJUAAADDAAAABf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ALcAAAB7////AQAAACsAAADjAAAA/QAAADv///8BAAAAJwAAAMsAAABB////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAA3QAAAEP///8BAAAAHwAAAM8AAAD/AAAASf///wEAAAAFAAAAsQAAAHH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADfAAAARf///wEAAAAVAAAAvwAAAP8AAABp////AQAAAAUAAACxAAAAbf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAALcAAAB9////AQAAAAsAAACtAAAA/wAAAIH///8BAAAAKwAA + AM0AAAA5////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAATwAAANsAAAAzAAAAAwAAAKEAAAD/AAAAmwAA + AAUAAACXAAAAvwAAAAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAewAAANkAAABrAAAApQAA + AP8AAADRAAAApwAAAL8AAAAt////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAWwAA + AMUAAADrAAAA/wAAAPUAAACVAAAAJ////wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAAwAAAE8AAAD/AAAA2QAAAAX///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAHwAAAP8AAADdAAAAEf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAFAAAA/wAAAOEAAAAd////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAADfAAAA5wAAAC3///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAALcAAADtAAAAQf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAhQAA + APUAAABX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABPAAAA7wAAAHP///8B////AQAAAA0AAAA3AAAAE////wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAABkAAADPAAAAmwAAAAf///8BAAAAZQAAAOcAAACL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAGMAAADjAAAAH////wEAAABdAAAA9QAAAKn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAACwAAAIEAAAChAAAAUwAAAF8AAACpAAAAN/// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAADkAAABXAAAATQAA + ABf///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAwAAAAYAAAAAEA + IAAAAAAAgCUAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAcAAAAPAAAAEwAAABMAAAARAAAACQAAAAP///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAADAAAAHQAAAGMAAACvAAAA0QAAANUAAAC7AAAAdQAA + ACkAAAAF////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAATAAAApQAAANcAAABXAAAACQAA + AA0AAABTAAAAwwAAALsAAAA/AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABHAAAA/wAA + APEAAACNAAAAC////wH///8BAAAATQAAANcAAADBAAAAKQAAAAP///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABtAAAA/wAAAP8AAAC/AAAAG////wH///8BAAAABwAAAKEAAAD5AAAAhQAAAAn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAAA5AAAAxQAAANUAAACBAAAADf///wH///8B////AQAAAGcAAADnAAAA6QAA + ACf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAFAAAAPQAAAEsAAAAb////Af///wH///8B////AQAA + ADUAAADVAAAA/wAAAHX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAA8AAADJAAAA/wAAANH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAC7AAAA/QAAAPsAAAAL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACjAAAA+QAAAP8AAABB////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA8wAA + AP8AAABp////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAB3AAAA7wAAAP8AAACb////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAABnAAAA7QAAAP8AAAC/////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAABNAAAA5wAAAP8AAADf////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAA/AAAA5QAAAP8AAADtAAAAB/// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAxAAAA4QAA + AP8AAADxAAAANQAAAAn///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AB0AAABjAAAA6QAAAP8AAAD5AAAAowAAAG8AAABBAAAAFf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAFAAAAPQAAAJUAAADfAAAA/QAAAP8AAAD9AAAA5wAAAOcAAADRAAAAgwAAACv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAAUAAABNAAAAwwAAANkAAACRAAAA6wAAAP8AAAD5AAAArQAAAGsAAACtAAAA5QAA + AKMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAADkAAAC/AAAA1wAAAGkAAAAVAAAA0QAAAP8AAAD5AAAAmQAA + AAUAAAApAAAAiwAAAOMAAACXAAAAIf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAEwAAAIUAAADjAAAAcwAAAA////8BAAAAtwAA + APsAAAD7AAAAs////wH///8BAAAAHQAAAJkAAADnAAAAWwAAAAX///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAOQAAAMUAAACrAAAAJ/// + /wH///8BAAAAoQAAAPsAAAD/AAAA0f///wH///8BAAAAAwAAAEcAAADNAAAAnQAAAB////8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAA + AOsAAAB1AAAABf///wH///8BAAAAhwAAAPcAAAD/AAAA1////wH///8B////AQAAABcAAACfAAAAzwAA + ADf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAZwAAAPUAAAD/AAAA3QAAABn///8B////AQAA + AAMAAACLAAAA6QAAAEP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAVQAAAPMAAAD/AAAA4wAA + ADf///8B////AQAAAAMAAACLAAAA5wAAAEP///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAAAPEAAAB7AAAABf///wH///8BAAAANwAA + APEAAAD/AAAA5QAAAEX///8B////AQAAABcAAAChAAAAxQAAADP///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAANwAAAMMAAACtAAAAKf// + /wH///8BAAAAGwAAAO0AAAD/AAAA6wAAAF////8BAAAAAwAAAE8AAADVAAAAlQAAABv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAADwAA + AH0AAADnAAAAeQAAABH///8BAAAACwAAAO0AAAD/AAAA7wAAAHEAAAADAAAAIQAAAJ0AAADpAAAAWQAA + AAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAADUAAAC1AAAA2wAAAHUAAAAdAAAAAwAAAN8AAAD/AAAA9QAAAJMAAAArAAAAkQAA + AN8AAACPAAAAHf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAUAAABJAAAAuwAAAOMAAACdAAAAZQAAANsAAAD/AAAA+wAA + ANEAAACtAAAA4QAAAJsAAAAr////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAFAAAAOQAAAIsAAADVAAAA5wAA + APcAAAD/AAAA/wAAAPcAAADDAAAAdQAAACf///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABcAAABFAAAAaQAAALkAAAD/AAAA/wAAANUAAAA5AAAADf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAABQAAAGMAAAD/AAAA/wAAAMcAAAAJ////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////AQAAADcAAAD/AAAA/wAAAMsAAAAV////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAABUAAAD/AAAA/wAA + AM8AAAAh////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AAMAAAD/AAAA/wAAANMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADdAAAA/wAAANkAAAA9////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAACtAAAA/wAAAOEAAABV////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA/wAAAOUAAABl////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABTAAAA/wAA + AO8AAAB9////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAnAAAA8wAAAPcAAACX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAAAPAAAAwQAAAP0AAACtAAAABf///wH///8B////AQAAABsAAABTAAAASwAA + AAf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAHAAAAbQAAAP8AAADBAAAAIf///wH///8BAAAABwAA + AH0AAADbAAAA0wAAAEv///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAADAAAAKwAAANcAAADbAAAAVf// + /wH///8BAAAACwAAALUAAAD/AAAA/wAAAJX///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACwAA + AGkAAADvAAAAmwAAABP///8BAAAABQAAAHEAAADpAAAA/wAAAGv///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAABcAAACDAAAA4QAAAIcAAAAtAAAAGwAAAFMAAADTAAAAsQAAAB3///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAMAAAAVAAAAWwAAAKkAAADFAAAAxwAAAKsAAABjAAAAHwAA + AAP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAAA0AAAATAAAAEwAA + AA8AAAAH////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8= + + + \ No newline at end of file diff --git a/Samples/Neuro/Perceptron/Perceptron.csproj b/Samples/Neuro/Perceptron/Perceptron.csproj new file mode 100644 index 0000000000..2305b4938 --- /dev/null +++ b/Samples/Neuro/Perceptron/Perceptron.csproj @@ -0,0 +1,228 @@ + + + + Local + 9.0.21022 + 2.0 + {7FA21B39-6926-412C-BB5E-99F957E5CC19} + Debug + AnyCPU + framework.ico + + + Perceptron + + + JScript + Grid + IE50 + false + WinExe + SampleApp + OnBuildSuccess + SampleApp.Program + + + + + 3.5 + v4.0 + false + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true + + + + true + bin\x86\Debug\ + DEBUG;TRACE + 285212672 + 4096 + full + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + bin\x86\Release\ + TRACE + 285212672 + true + 4096 + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + + False + ..\..\..\Release\net40\Accord.dll + + + ..\..\..\Release\net40\Accord.Controls.dll + + + ..\..\..\Release\net40\Accord.IO.dll + + + False + ..\..\..\Release\net40\Accord.MachineLearning.dll + + + False + ..\..\..\Release\net40\Accord.Math.dll + + + False + ..\..\..\Release\net40\Accord.Neuro.dll + + + False + ..\..\..\Release\net40\Accord.Statistics.dll + + + System + + + 3.5 + + + System.Data + + + System.Drawing + + + + System.Windows.Forms + + + System.XML + + + + + Form + + + Form + + + Form + + + + + Form + + + MainForm.cs + + + DeltaRule.cs + + + OneLayerPerceptron.cs + + + Perceptron.cs + + + MainForm.cs + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 2.0 %28x86%29 + false + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + true + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + PreserveNewest + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/Neuro/Perceptron/Program.cs b/Samples/Neuro/Perceptron/Program.cs new file mode 100644 index 0000000000..316268492 --- /dev/null +++ b/Samples/Neuro/Perceptron/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Windows.Forms; + +namespace SampleApp +{ + static class Program + { + [STAThread] + static void Main() + { + if (Environment.OSVersion.Version.Major >= 6) + SetProcessDPIAware(); + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + + [System.Runtime.InteropServices.DllImport("user32.dll")] + private static extern bool SetProcessDPIAware(); + } +} diff --git a/Samples/Neuro/Perceptron/Properties/AssemblyInfo.cs b/Samples/Neuro/Perceptron/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..88dea08c9 --- /dev/null +++ b/Samples/Neuro/Perceptron/Properties/AssemblyInfo.cs @@ -0,0 +1,32 @@ +using System; +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Levenberg-Marquardt suite of sample applications")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Accord.NET")] +[assembly: AssemblyProduct("Accord.NET Framework")] +[assembly: AssemblyCopyright("Copyright Csar Souza, 2009-2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: AssemblyDescription( +@"This sample application shows how to use Levenberg-Marquardt (LM) learning to teach artificial neural networks to predict time series, approximate functions or solve binary classification problems.")] + + + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. +[assembly: ComVisible(false)] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/Samples/Neuro/Perceptron/Sample data (delta rule)/and.csv b/Samples/Neuro/Perceptron/Sample data (delta rule)/and.csv new file mode 100644 index 0000000000..4b7b3ea78 --- /dev/null +++ b/Samples/Neuro/Perceptron/Sample data (delta rule)/and.csv @@ -0,0 +1,4 @@ +0,0,0 +0,1,0 +1,0,0 +1,1,1 diff --git a/Samples/Neuro/Perceptron/Sample data (delta rule)/cube.csv b/Samples/Neuro/Perceptron/Sample data (delta rule)/cube.csv new file mode 100644 index 0000000000..6aa44f78d --- /dev/null +++ b/Samples/Neuro/Perceptron/Sample data (delta rule)/cube.csv @@ -0,0 +1,8 @@ +0,0,0,0 +0,0,1,0 +0,1,0,0 +0,1,1,0 +1,0,0,1 +1,0,1,1 +1,1,0,1 +1,1,1,1 diff --git a/Samples/Neuro/Perceptron/Sample data (delta rule)/or.csv b/Samples/Neuro/Perceptron/Sample data (delta rule)/or.csv new file mode 100644 index 0000000000..5f14b20dd --- /dev/null +++ b/Samples/Neuro/Perceptron/Sample data (delta rule)/or.csv @@ -0,0 +1,4 @@ +0,0,0 +0,1,1 +1,0,1 +1,1,1 diff --git a/Samples/Neuro/Perceptron/Sample data (delta rule)/sample1.csv b/Samples/Neuro/Perceptron/Sample data (delta rule)/sample1.csv new file mode 100644 index 0000000000..96e7ba7d6 --- /dev/null +++ b/Samples/Neuro/Perceptron/Sample data (delta rule)/sample1.csv @@ -0,0 +1,15 @@ +0.1,0.1,0 +0.2,0.3,0 +0.3,0.4,0 +0.1,0.3,0 +0.2,0.5,0 +0.1,1,1 +0.2,1.1,1 +0.3,0.9,1 +0.4,0.8,1 +0.2,0.9,1 +1,0.4,2 +0.9,0.5,2 +0.8,0.6,2 +0.9,0.4,2 +1,0.5,2 diff --git a/Samples/Neuro/Perceptron/Sample data (delta rule)/sample2.csv b/Samples/Neuro/Perceptron/Sample data (delta rule)/sample2.csv new file mode 100644 index 0000000000..934a55a0b --- /dev/null +++ b/Samples/Neuro/Perceptron/Sample data (delta rule)/sample2.csv @@ -0,0 +1,20 @@ +0.1,0.4,0 +0.2,0.2,0 +0.3,0.1,0 +0.1,0.2,0 +0.2,0.5,0 +0.7,0.2,1 +0.8,0.3,1 +0.9,0.4,1 +0.7,0.1,1 +0.8,0.2,1 +0.1,0.6,2 +0.2,0.7,2 +0.3,0.8,2 +0.3,0.9,2 +0.1,0.6,2 +0.7,0.9,3 +0.8,0.9,3 +0.7,0.8,3 +0.8,0.7,3 +0.9,0.7,3 diff --git a/Samples/Neuro/Perceptron/Sample data (one layer)/sample1.csv b/Samples/Neuro/Perceptron/Sample data (one layer)/sample1.csv new file mode 100644 index 0000000000..96e7ba7d6 --- /dev/null +++ b/Samples/Neuro/Perceptron/Sample data (one layer)/sample1.csv @@ -0,0 +1,15 @@ +0.1,0.1,0 +0.2,0.3,0 +0.3,0.4,0 +0.1,0.3,0 +0.2,0.5,0 +0.1,1,1 +0.2,1.1,1 +0.3,0.9,1 +0.4,0.8,1 +0.2,0.9,1 +1,0.4,2 +0.9,0.5,2 +0.8,0.6,2 +0.9,0.4,2 +1,0.5,2 diff --git a/Samples/Neuro/Perceptron/Sample data (one layer)/sample2.csv b/Samples/Neuro/Perceptron/Sample data (one layer)/sample2.csv new file mode 100644 index 0000000000..934a55a0b --- /dev/null +++ b/Samples/Neuro/Perceptron/Sample data (one layer)/sample2.csv @@ -0,0 +1,20 @@ +0.1,0.4,0 +0.2,0.2,0 +0.3,0.1,0 +0.1,0.2,0 +0.2,0.5,0 +0.7,0.2,1 +0.8,0.3,1 +0.9,0.4,1 +0.7,0.1,1 +0.8,0.2,1 +0.1,0.6,2 +0.2,0.7,2 +0.3,0.8,2 +0.3,0.9,2 +0.1,0.6,2 +0.7,0.9,3 +0.8,0.9,3 +0.7,0.8,3 +0.8,0.7,3 +0.9,0.7,3 diff --git a/Samples/Neuro/Perceptron/Sample data (perceptron)/and.csv b/Samples/Neuro/Perceptron/Sample data (perceptron)/and.csv new file mode 100644 index 0000000000..4b7b3ea78 --- /dev/null +++ b/Samples/Neuro/Perceptron/Sample data (perceptron)/and.csv @@ -0,0 +1,4 @@ +0,0,0 +0,1,0 +1,0,0 +1,1,1 diff --git a/Samples/Neuro/Perceptron/Sample data (perceptron)/cube.csv b/Samples/Neuro/Perceptron/Sample data (perceptron)/cube.csv new file mode 100644 index 0000000000..6aa44f78d --- /dev/null +++ b/Samples/Neuro/Perceptron/Sample data (perceptron)/cube.csv @@ -0,0 +1,8 @@ +0,0,0,0 +0,0,1,0 +0,1,0,0 +0,1,1,0 +1,0,0,1 +1,0,1,1 +1,1,0,1 +1,1,1,1 diff --git a/Samples/Neuro/Perceptron/Sample data (perceptron)/or.csv b/Samples/Neuro/Perceptron/Sample data (perceptron)/or.csv new file mode 100644 index 0000000000..5f14b20dd --- /dev/null +++ b/Samples/Neuro/Perceptron/Sample data (perceptron)/or.csv @@ -0,0 +1,4 @@ +0,0,0 +0,1,1 +1,0,1 +1,1,1 diff --git a/Samples/Neuro/Perceptron/app.config b/Samples/Neuro/Perceptron/app.config new file mode 100644 index 0000000000..86fcc8b74 --- /dev/null +++ b/Samples/Neuro/Perceptron/app.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Vision/Kinect/framework.ico b/Samples/Neuro/Perceptron/framework.ico similarity index 100% rename from Samples/Vision/Kinect/framework.ico rename to Samples/Neuro/Perceptron/framework.ico diff --git a/Samples/Neuro/Resilient Backpropagation/Accord.dll.config b/Samples/Neuro/Resilient Backpropagation/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Neuro/Resilient Backpropagation/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Neuro/Resilient Backpropagation/Applications/Approximation.cs b/Samples/Neuro/Resilient Backpropagation/Applications/Approximation.cs index 956bcecc0..36647d200 100644 --- a/Samples/Neuro/Resilient Backpropagation/Applications/Approximation.cs +++ b/Samples/Neuro/Resilient Backpropagation/Applications/Approximation.cs @@ -49,7 +49,7 @@ using System.Threading; using System.Windows.Forms; -namespace Samples.Rprop +namespace SampleApp { public class Approximation : Form { diff --git a/Samples/Neuro/Resilient Backpropagation/Applications/Approximation.resx b/Samples/Neuro/Resilient Backpropagation/Applications/Approximation.resx index 679ff3f0e..d97bbc6ed 100644 --- a/Samples/Neuro/Resilient Backpropagation/Applications/Approximation.resx +++ b/Samples/Neuro/Resilient Backpropagation/Applications/Approximation.resx @@ -117,21 +117,8 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + 17, 17 - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAElBRm9yZ2UsIFZlcnNpb249Mi4yLjUuMCwgQ3VsdHVyZT1uZXV0 - cmFsLCBQdWJsaWNLZXlUb2tlbj1jMWRiNmZmNGVhYTA2YWViBQEAAAAMQUZvcmdlLlJhbmdlAgAAAANt - aW4DbWF4AAALCwIAAAAAAAAAAACAPws= - - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAElBRm9yZ2UsIFZlcnNpb249Mi4yLjUuMCwgQ3VsdHVyZT1uZXV0 - cmFsLCBQdWJsaWNLZXlUb2tlbj1jMWRiNmZmNGVhYTA2YWViBQEAAAAMQUZvcmdlLlJhbmdlAgAAAANt - aW4DbWF4AAALCwIAAAAAAAAAAACAPws= - \ No newline at end of file diff --git a/Samples/Neuro/Resilient Backpropagation/Applications/TimeSeries.cs b/Samples/Neuro/Resilient Backpropagation/Applications/TimeSeries.cs index 9ba5f62ba..75c8e3dee 100644 --- a/Samples/Neuro/Resilient Backpropagation/Applications/TimeSeries.cs +++ b/Samples/Neuro/Resilient Backpropagation/Applications/TimeSeries.cs @@ -48,7 +48,7 @@ using System.Globalization; using Accord.Math; -namespace Samples.Rprop +namespace SampleApp { public class TimeSeries : System.Windows.Forms.Form { @@ -104,12 +104,8 @@ public class TimeSeries : System.Windows.Forms.Form private GroupBox groupBox3; private double[,] predictionDelimiter = new double[2, 2] { { 0, 0 }, { 0, 0 } }; - // Constructor public TimeSeries() { - // - // Required for Windows Form Designer support - // InitializeComponent(); // initialize chart control diff --git a/Samples/Neuro/Resilient Backpropagation/Applications/TimeSeries.resx b/Samples/Neuro/Resilient Backpropagation/Applications/TimeSeries.resx index c9ec46a16..d97bbc6ed 100644 --- a/Samples/Neuro/Resilient Backpropagation/Applications/TimeSeries.resx +++ b/Samples/Neuro/Resilient Backpropagation/Applications/TimeSeries.resx @@ -117,21 +117,8 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - AAEAAAD/////AQAAAAAAAAAMAgAAAElBRm9yZ2UsIFZlcnNpb249Mi4yLjUuMCwgQ3VsdHVyZT1uZXV0 - cmFsLCBQdWJsaWNLZXlUb2tlbj1jMWRiNmZmNGVhYTA2YWViBQEAAAAMQUZvcmdlLlJhbmdlAgAAAANt - aW4DbWF4AAALCwIAAAAAAAAAAACAPws= - - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAElBRm9yZ2UsIFZlcnNpb249Mi4yLjUuMCwgQ3VsdHVyZT1uZXV0 - cmFsLCBQdWJsaWNLZXlUb2tlbj1jMWRiNmZmNGVhYTA2YWViBQEAAAAMQUZvcmdlLlJhbmdlAgAAAANt - aW4DbWF4AAALCwIAAAAAAAAAAACAPws= - - - + + 17, 17 - + \ No newline at end of file diff --git a/Samples/Neuro/Resilient Backpropagation/Applications/XorProblem.cs b/Samples/Neuro/Resilient Backpropagation/Applications/XorProblem.cs index 761700baa..681c547c2 100644 --- a/Samples/Neuro/Resilient Backpropagation/Applications/XorProblem.cs +++ b/Samples/Neuro/Resilient Backpropagation/Applications/XorProblem.cs @@ -46,7 +46,7 @@ using AForge.Controls; using AForge.Neuro; -namespace Samples.Rprop +namespace SampleApp { public class XorProblem : System.Windows.Forms.Form { @@ -86,12 +86,8 @@ public class XorProblem : System.Windows.Forms.Form private volatile bool needToStop = false; - // Constructor public XorProblem() { - // - // Required for Windows Form Designer support - // InitializeComponent(); // update controls @@ -123,233 +119,233 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(XorProblem)); - this.groupBox1 = new System.Windows.Forms.GroupBox(); - this.stopButton = new System.Windows.Forms.Button(); - this.startButton = new System.Windows.Forms.Button(); - this.label5 = new System.Windows.Forms.Label(); - this.currentErrorBox = new System.Windows.Forms.TextBox(); - this.label11 = new System.Windows.Forms.Label(); - this.currentIterationBox = new System.Windows.Forms.TextBox(); - this.label8 = new System.Windows.Forms.Label(); - this.label7 = new System.Windows.Forms.Label(); - this.sigmoidTypeCombo = new System.Windows.Forms.ComboBox(); - this.errorLimitBox = new System.Windows.Forms.TextBox(); - this.label3 = new System.Windows.Forms.Label(); - this.alphaBox = new System.Windows.Forms.TextBox(); - this.label2 = new System.Windows.Forms.Label(); - this.learningRateBox = new System.Windows.Forms.TextBox(); - this.label1 = new System.Windows.Forms.Label(); - this.label4 = new System.Windows.Forms.Label(); - this.groupBox2 = new System.Windows.Forms.GroupBox(); - this.errorChart = new AForge.Controls.Chart(); - this.saveFilesCheck = new System.Windows.Forms.CheckBox(); - this.groupBox1.SuspendLayout(); - this.groupBox2.SuspendLayout(); - this.SuspendLayout(); - // - // groupBox1 - // - this.groupBox1.Controls.Add(this.stopButton); - this.groupBox1.Controls.Add(this.startButton); - this.groupBox1.Controls.Add(this.label5); - this.groupBox1.Controls.Add(this.currentErrorBox); - this.groupBox1.Controls.Add(this.label11); - this.groupBox1.Controls.Add(this.currentIterationBox); - this.groupBox1.Controls.Add(this.label8); - this.groupBox1.Controls.Add(this.label7); - this.groupBox1.Controls.Add(this.sigmoidTypeCombo); - this.groupBox1.Controls.Add(this.errorLimitBox); - this.groupBox1.Controls.Add(this.label3); - this.groupBox1.Controls.Add(this.alphaBox); - this.groupBox1.Controls.Add(this.label2); - this.groupBox1.Controls.Add(this.learningRateBox); - this.groupBox1.Controls.Add(this.label1); - this.groupBox1.Controls.Add(this.label4); - this.groupBox1.Location = new System.Drawing.Point(16, 15); - this.groupBox1.Name = "groupBox1"; - this.groupBox1.Size = new System.Drawing.Size(312, 380); - this.groupBox1.TabIndex = 0; - this.groupBox1.TabStop = false; - this.groupBox1.Text = "Neural Network"; - // - // stopButton - // - this.stopButton.Enabled = false; - this.stopButton.Location = new System.Drawing.Point(176, 329); - this.stopButton.Name = "stopButton"; - this.stopButton.Size = new System.Drawing.Size(120, 33); - this.stopButton.TabIndex = 28; - this.stopButton.Text = "S&top"; - this.stopButton.Click += new System.EventHandler(this.stopButton_Click); - // - // startButton - // - this.startButton.Location = new System.Drawing.Point(40, 329); - this.startButton.Name = "startButton"; - this.startButton.Size = new System.Drawing.Size(120, 33); - this.startButton.TabIndex = 27; - this.startButton.Text = "&Start"; - this.startButton.Click += new System.EventHandler(this.startButton_Click); - // - // label5 - // - this.label5.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.label5.Location = new System.Drawing.Point(16, 308); - this.label5.Name = "label5"; - this.label5.Size = new System.Drawing.Size(280, 3); - this.label5.TabIndex = 26; - // - // currentErrorBox - // - this.currentErrorBox.Location = new System.Drawing.Point(200, 270); - this.currentErrorBox.Name = "currentErrorBox"; - this.currentErrorBox.ReadOnly = true; - this.currentErrorBox.Size = new System.Drawing.Size(96, 26); - this.currentErrorBox.TabIndex = 25; - // - // label11 - // - this.label11.Location = new System.Drawing.Point(16, 273); - this.label11.Name = "label11"; - this.label11.Size = new System.Drawing.Size(194, 21); - this.label11.TabIndex = 24; - this.label11.Text = "Current summary error:"; - // - // currentIterationBox - // - this.currentIterationBox.Location = new System.Drawing.Point(200, 234); - this.currentIterationBox.Name = "currentIterationBox"; - this.currentIterationBox.ReadOnly = true; - this.currentIterationBox.Size = new System.Drawing.Size(96, 26); - this.currentIterationBox.TabIndex = 23; - // - // label8 - // - this.label8.Location = new System.Drawing.Point(16, 237); - this.label8.Name = "label8"; - this.label8.Size = new System.Drawing.Size(157, 23); - this.label8.TabIndex = 22; - this.label8.Text = "Current iteration:"; - // - // label7 - // - this.label7.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.label7.Location = new System.Drawing.Point(16, 219); - this.label7.Name = "label7"; - this.label7.Size = new System.Drawing.Size(280, 3); - this.label7.TabIndex = 21; - // - // sigmoidTypeCombo - // - this.sigmoidTypeCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.sigmoidTypeCombo.Items.AddRange(new object[] { - "Unipolar", - "Bipolar"}); - this.sigmoidTypeCombo.Location = new System.Drawing.Point(200, 140); - this.sigmoidTypeCombo.Name = "sigmoidTypeCombo"; - this.sigmoidTypeCombo.Size = new System.Drawing.Size(96, 28); - this.sigmoidTypeCombo.TabIndex = 9; - // - // errorLimitBox - // - this.errorLimitBox.Location = new System.Drawing.Point(200, 104); - this.errorLimitBox.Name = "errorLimitBox"; - this.errorLimitBox.Size = new System.Drawing.Size(96, 26); - this.errorLimitBox.TabIndex = 7; - // - // label3 - // - this.label3.Location = new System.Drawing.Point(16, 107); - this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(176, 22); - this.label3.TabIndex = 6; - this.label3.Text = "Learning error limit:"; - // - // alphaBox - // - this.alphaBox.Location = new System.Drawing.Point(200, 67); - this.alphaBox.Name = "alphaBox"; - this.alphaBox.Size = new System.Drawing.Size(96, 26); - this.alphaBox.TabIndex = 5; - // - // label2 - // - this.label2.Location = new System.Drawing.Point(16, 70); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(192, 22); - this.label2.TabIndex = 4; - this.label2.Text = "Sigmoid\'s alpha value:"; - // - // learningRateBox - // - this.learningRateBox.Location = new System.Drawing.Point(200, 29); - this.learningRateBox.Name = "learningRateBox"; - this.learningRateBox.Size = new System.Drawing.Size(96, 26); - this.learningRateBox.TabIndex = 1; - // - // label1 - // - this.label1.Location = new System.Drawing.Point(16, 32); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(125, 21); - this.label1.TabIndex = 0; - this.label1.Text = "Learning rate:"; - // - // label4 - // - this.label4.Location = new System.Drawing.Point(16, 143); - this.label4.Name = "label4"; - this.label4.Size = new System.Drawing.Size(160, 22); - this.label4.TabIndex = 8; - this.label4.Text = "Sigmoid\'s type:"; - // - // groupBox2 - // - this.groupBox2.Controls.Add(this.errorChart); - this.groupBox2.Controls.Add(this.saveFilesCheck); - this.groupBox2.Location = new System.Drawing.Point(344, 15); - this.groupBox2.Name = "groupBox2"; - this.groupBox2.Size = new System.Drawing.Size(352, 380); - this.groupBox2.TabIndex = 1; - this.groupBox2.TabStop = false; - this.groupBox2.Text = "Error\'s dynamics"; - // - // errorChart - // - this.errorChart.Location = new System.Drawing.Point(16, 29); - this.errorChart.Name = "errorChart"; - this.errorChart.RangeX = ((AForge.Range)(resources.GetObject("errorChart.RangeX"))); - this.errorChart.RangeY = ((AForge.Range)(resources.GetObject("errorChart.RangeY"))); - this.errorChart.Size = new System.Drawing.Size(320, 300); - this.errorChart.TabIndex = 2; - this.errorChart.Text = "chart1"; - // - // saveFilesCheck - // - this.saveFilesCheck.Location = new System.Drawing.Point(16, 341); - this.saveFilesCheck.Name = "saveFilesCheck"; - this.saveFilesCheck.Size = new System.Drawing.Size(320, 26); - this.saveFilesCheck.TabIndex = 1; - this.saveFilesCheck.Text = "Save errors to files"; - // - // XorProblem - // - this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; - this.ClientSize = new System.Drawing.Size(708, 409); - this.Controls.Add(this.groupBox2); - this.Controls.Add(this.groupBox1); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - this.MaximizeBox = false; - this.Name = "XorProblem"; - this.Text = "XOR Problem (Resilient Backpropagation)"; - this.Closing += new System.ComponentModel.CancelEventHandler(this.MainForm_Closing); - this.groupBox1.ResumeLayout(false); - this.groupBox1.PerformLayout(); - this.groupBox2.ResumeLayout(false); - this.ResumeLayout(false); - + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(XorProblem)); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.stopButton = new System.Windows.Forms.Button(); + this.startButton = new System.Windows.Forms.Button(); + this.label5 = new System.Windows.Forms.Label(); + this.currentErrorBox = new System.Windows.Forms.TextBox(); + this.label11 = new System.Windows.Forms.Label(); + this.currentIterationBox = new System.Windows.Forms.TextBox(); + this.label8 = new System.Windows.Forms.Label(); + this.label7 = new System.Windows.Forms.Label(); + this.sigmoidTypeCombo = new System.Windows.Forms.ComboBox(); + this.errorLimitBox = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.alphaBox = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.learningRateBox = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.errorChart = new AForge.Controls.Chart(); + this.saveFilesCheck = new System.Windows.Forms.CheckBox(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.stopButton); + this.groupBox1.Controls.Add(this.startButton); + this.groupBox1.Controls.Add(this.label5); + this.groupBox1.Controls.Add(this.currentErrorBox); + this.groupBox1.Controls.Add(this.label11); + this.groupBox1.Controls.Add(this.currentIterationBox); + this.groupBox1.Controls.Add(this.label8); + this.groupBox1.Controls.Add(this.label7); + this.groupBox1.Controls.Add(this.sigmoidTypeCombo); + this.groupBox1.Controls.Add(this.errorLimitBox); + this.groupBox1.Controls.Add(this.label3); + this.groupBox1.Controls.Add(this.alphaBox); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.learningRateBox); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.label4); + this.groupBox1.Location = new System.Drawing.Point(16, 15); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(312, 380); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Neural Network"; + // + // stopButton + // + this.stopButton.Enabled = false; + this.stopButton.Location = new System.Drawing.Point(176, 329); + this.stopButton.Name = "stopButton"; + this.stopButton.Size = new System.Drawing.Size(120, 33); + this.stopButton.TabIndex = 28; + this.stopButton.Text = "S&top"; + this.stopButton.Click += new System.EventHandler(this.stopButton_Click); + // + // startButton + // + this.startButton.Location = new System.Drawing.Point(40, 329); + this.startButton.Name = "startButton"; + this.startButton.Size = new System.Drawing.Size(120, 33); + this.startButton.TabIndex = 27; + this.startButton.Text = "&Start"; + this.startButton.Click += new System.EventHandler(this.startButton_Click); + // + // label5 + // + this.label5.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.label5.Location = new System.Drawing.Point(16, 308); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(280, 3); + this.label5.TabIndex = 26; + // + // currentErrorBox + // + this.currentErrorBox.Location = new System.Drawing.Point(200, 270); + this.currentErrorBox.Name = "currentErrorBox"; + this.currentErrorBox.ReadOnly = true; + this.currentErrorBox.Size = new System.Drawing.Size(96, 26); + this.currentErrorBox.TabIndex = 25; + // + // label11 + // + this.label11.Location = new System.Drawing.Point(16, 273); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(194, 21); + this.label11.TabIndex = 24; + this.label11.Text = "Current summary error:"; + // + // currentIterationBox + // + this.currentIterationBox.Location = new System.Drawing.Point(200, 234); + this.currentIterationBox.Name = "currentIterationBox"; + this.currentIterationBox.ReadOnly = true; + this.currentIterationBox.Size = new System.Drawing.Size(96, 26); + this.currentIterationBox.TabIndex = 23; + // + // label8 + // + this.label8.Location = new System.Drawing.Point(16, 237); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(157, 23); + this.label8.TabIndex = 22; + this.label8.Text = "Current iteration:"; + // + // label7 + // + this.label7.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.label7.Location = new System.Drawing.Point(16, 219); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(280, 3); + this.label7.TabIndex = 21; + // + // sigmoidTypeCombo + // + this.sigmoidTypeCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.sigmoidTypeCombo.Items.AddRange(new object[] { + "Unipolar", + "Bipolar"}); + this.sigmoidTypeCombo.Location = new System.Drawing.Point(200, 140); + this.sigmoidTypeCombo.Name = "sigmoidTypeCombo"; + this.sigmoidTypeCombo.Size = new System.Drawing.Size(96, 28); + this.sigmoidTypeCombo.TabIndex = 9; + // + // errorLimitBox + // + this.errorLimitBox.Location = new System.Drawing.Point(200, 104); + this.errorLimitBox.Name = "errorLimitBox"; + this.errorLimitBox.Size = new System.Drawing.Size(96, 26); + this.errorLimitBox.TabIndex = 7; + // + // label3 + // + this.label3.Location = new System.Drawing.Point(16, 107); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(176, 22); + this.label3.TabIndex = 6; + this.label3.Text = "Learning error limit:"; + // + // alphaBox + // + this.alphaBox.Location = new System.Drawing.Point(200, 67); + this.alphaBox.Name = "alphaBox"; + this.alphaBox.Size = new System.Drawing.Size(96, 26); + this.alphaBox.TabIndex = 5; + // + // label2 + // + this.label2.Location = new System.Drawing.Point(16, 70); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(192, 22); + this.label2.TabIndex = 4; + this.label2.Text = "Sigmoid\'s alpha value:"; + // + // learningRateBox + // + this.learningRateBox.Location = new System.Drawing.Point(200, 29); + this.learningRateBox.Name = "learningRateBox"; + this.learningRateBox.Size = new System.Drawing.Size(96, 26); + this.learningRateBox.TabIndex = 1; + // + // label1 + // + this.label1.Location = new System.Drawing.Point(16, 32); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(125, 21); + this.label1.TabIndex = 0; + this.label1.Text = "Learning rate:"; + // + // label4 + // + this.label4.Location = new System.Drawing.Point(16, 143); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(160, 22); + this.label4.TabIndex = 8; + this.label4.Text = "Sigmoid\'s type:"; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.errorChart); + this.groupBox2.Controls.Add(this.saveFilesCheck); + this.groupBox2.Location = new System.Drawing.Point(344, 15); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(352, 380); + this.groupBox2.TabIndex = 1; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Error\'s dynamics"; + // + // errorChart + // + this.errorChart.Location = new System.Drawing.Point(16, 29); + this.errorChart.Name = "errorChart"; + this.errorChart.RangeX = ((AForge.Range)(resources.GetObject("errorChart.RangeX"))); + this.errorChart.RangeY = ((AForge.Range)(resources.GetObject("errorChart.RangeY"))); + this.errorChart.Size = new System.Drawing.Size(320, 300); + this.errorChart.TabIndex = 2; + this.errorChart.Text = "chart1"; + // + // saveFilesCheck + // + this.saveFilesCheck.Location = new System.Drawing.Point(16, 341); + this.saveFilesCheck.Name = "saveFilesCheck"; + this.saveFilesCheck.Size = new System.Drawing.Size(320, 26); + this.saveFilesCheck.TabIndex = 1; + this.saveFilesCheck.Text = "Save errors to files"; + // + // XorProblem + // + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(708, 409); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.Name = "XorProblem"; + this.Text = "XOR Problem (Resilient Backpropagation)"; + this.Closing += new System.ComponentModel.CancelEventHandler(this.MainForm_Closing); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.groupBox2.ResumeLayout(false); + this.ResumeLayout(false); + } #endregion diff --git a/Samples/Neuro/Resilient Backpropagation/Applications/XorProblem.resx b/Samples/Neuro/Resilient Backpropagation/Applications/XorProblem.resx index 368d2bea2..c7e0d4bdf 100644 --- a/Samples/Neuro/Resilient Backpropagation/Applications/XorProblem.resx +++ b/Samples/Neuro/Resilient Backpropagation/Applications/XorProblem.resx @@ -117,18 +117,4 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - AAEAAAD/////AQAAAAAAAAAMAgAAAElBRm9yZ2UsIFZlcnNpb249Mi4yLjUuMCwgQ3VsdHVyZT1uZXV0 - cmFsLCBQdWJsaWNLZXlUb2tlbj1jMWRiNmZmNGVhYTA2YWViBQEAAAAMQUZvcmdlLlJhbmdlAgAAAANt - aW4DbWF4AAALCwIAAAAAAAAAAACAPws= - - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAElBRm9yZ2UsIFZlcnNpb249Mi4yLjUuMCwgQ3VsdHVyZT1uZXV0 - cmFsLCBQdWJsaWNLZXlUb2tlbj1jMWRiNmZmNGVhYTA2YWViBQEAAAAMQUZvcmdlLlJhbmdlAgAAAANt - aW4DbWF4AAALCwIAAAAAAAAAAACAPws= - - \ No newline at end of file diff --git a/Samples/Neuro/Resilient Backpropagation/MainForm.Designer.cs b/Samples/Neuro/Resilient Backpropagation/MainForm.Designer.cs index 1686fa2d5..d16bbde41 100644 --- a/Samples/Neuro/Resilient Backpropagation/MainForm.Designer.cs +++ b/Samples/Neuro/Resilient Backpropagation/MainForm.Designer.cs @@ -1,33 +1,33 @@ -namespace Samples.Rprop -{ - partial class MainForm - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); this.btnApproximation = new System.Windows.Forms.Button(); this.btnTimeSeries = new System.Windows.Forms.Button(); @@ -77,12 +77,12 @@ private void InitializeComponent() this.Text = "Resilient Backpropagation sample applications"; this.ResumeLayout(false); - } - - #endregion - - private System.Windows.Forms.Button btnApproximation; - private System.Windows.Forms.Button btnTimeSeries; - private System.Windows.Forms.Button btnXOR; - } + } + + #endregion + + private System.Windows.Forms.Button btnApproximation; + private System.Windows.Forms.Button btnTimeSeries; + private System.Windows.Forms.Button btnXOR; + } } \ No newline at end of file diff --git a/Samples/Neuro/Resilient Backpropagation/MainForm.cs b/Samples/Neuro/Resilient Backpropagation/MainForm.cs index e53f6ac09..cf38072ed 100644 --- a/Samples/Neuro/Resilient Backpropagation/MainForm.cs +++ b/Samples/Neuro/Resilient Backpropagation/MainForm.cs @@ -1,7 +1,7 @@ using System; using System.Windows.Forms; -namespace Samples.Rprop +namespace SampleApp { /// /// Resilient Backpropagation multiple sample applications. diff --git a/Samples/Neuro/Resilient Backpropagation/Program.cs b/Samples/Neuro/Resilient Backpropagation/Program.cs index 4f55db20d..316268492 100644 --- a/Samples/Neuro/Resilient Backpropagation/Program.cs +++ b/Samples/Neuro/Resilient Backpropagation/Program.cs @@ -1,7 +1,7 @@ using System; using System.Windows.Forms; -namespace Samples.Rprop +namespace SampleApp { static class Program { diff --git a/Samples/Neuro/Resilient Backpropagation/Resilient Backpropagation.csproj b/Samples/Neuro/Resilient Backpropagation/Resilient Backpropagation.csproj index 24723e55c..956cc5ccb 100644 --- a/Samples/Neuro/Resilient Backpropagation/Resilient Backpropagation.csproj +++ b/Samples/Neuro/Resilient Backpropagation/Resilient Backpropagation.csproj @@ -20,7 +20,7 @@ WinExe Samples.Rprop OnBuildSuccess - Samples.Rprop.Program + SampleApp.Program @@ -74,6 +74,9 @@ False ..\..\..\Release\net40\Accord.dll + + ..\..\..\Release\net40\Accord.Controls.dll + ..\..\..\Release\net40\Accord.IO.dll @@ -89,22 +92,6 @@ False ..\..\..\Release\net40\Accord.Statistics.dll - - False - ..\..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Controls.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Math.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Neuro.dll - System @@ -117,6 +104,7 @@ System.Drawing + System.Windows.Forms @@ -189,6 +177,9 @@ + + PreserveNewest + PreserveNewest diff --git a/Samples/Neuro/Resilient Backpropagation/app.config b/Samples/Neuro/Resilient Backpropagation/app.config index e47f3b99b..86fcc8b74 100644 --- a/Samples/Neuro/Resilient Backpropagation/app.config +++ b/Samples/Neuro/Resilient Backpropagation/app.config @@ -1,19 +1,6 @@ - - - - - - - - - - - - - - - - - + + + + diff --git a/Samples/Neuro/Self-Organizing Maps (SOM)/2DOrganizing.sln b/Samples/Neuro/Self-Organizing Maps (SOM)/2DOrganizing.sln new file mode 100644 index 0000000000..dc6a9f58c --- /dev/null +++ b/Samples/Neuro/Self-Organizing Maps (SOM)/2DOrganizing.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C# Express 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "2DOrganizing", "2DOrganizing.csproj", "{C646B987-EA7E-4D82-A930-448DE583FEB3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C646B987-EA7E-4D82-A930-448DE583FEB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C646B987-EA7E-4D82-A930-448DE583FEB3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C646B987-EA7E-4D82-A930-448DE583FEB3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C646B987-EA7E-4D82-A930-448DE583FEB3}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/Neuro/Self-Organizing Maps (SOM)/Accord.dll.config b/Samples/Neuro/Self-Organizing Maps (SOM)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Neuro/Self-Organizing Maps (SOM)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Neuro/Self-Organizing Maps (SOM)/App.ico b/Samples/Neuro/Self-Organizing Maps (SOM)/App.ico new file mode 100644 index 0000000000..3a5525fd7 Binary files /dev/null and b/Samples/Neuro/Self-Organizing Maps (SOM)/App.ico differ diff --git a/Samples/Neuro/Self-Organizing Maps (SOM)/AssemblyInfo.cs b/Samples/Neuro/Self-Organizing Maps (SOM)/AssemblyInfo.cs new file mode 100644 index 0000000000..9eeb652eb --- /dev/null +++ b/Samples/Neuro/Self-Organizing Maps (SOM)/AssemblyInfo.cs @@ -0,0 +1,59 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle( "Neuro SOM Organizing" )] +[assembly: AssemblyDescription( "Neuro SOM Organizing sample" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "AForge" )] +[assembly: AssemblyProduct( "AForge.NET" )] +[assembly: AssemblyCopyright( "AForge 2008" )] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion( "2.0.0.0" )] +[assembly: AssemblyFileVersion( "2.0.0.0" )] + +// +// In order to sign your assembly you must specify a key to use. Refer to the +// Microsoft .NET Framework documentation for more information on assembly signing. +// +// Use the attributes below to control which key is used for signing. +// +// Notes: +// (*) If no key is specified, the assembly is not signed. +// (*) KeyName refers to a key that has been installed in the Crypto Service +// Provider (CSP) on your machine. KeyFile refers to a file which contains +// a key. +// (*) If the KeyFile and the KeyName values are both specified, the +// following processing occurs: +// (1) If the KeyName can be found in the CSP, that key is used. +// (2) If the KeyName does not exist and the KeyFile does exist, the key +// in the KeyFile is installed into the CSP and used. +// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. +// When specifying the KeyFile, the location of the KeyFile should be +// relative to the project output directory which is +// %Project Directory%\obj\. For example, if your KeyFile is +// located in the project directory, you would specify the AssemblyKeyFile +// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] +// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework +// documentation for more information on this. +// +[assembly: AssemblyDelaySign( false )] +[assembly: AssemblyKeyFile( "" )] +[assembly: AssemblyKeyName( "" )] diff --git a/Samples/Neuro/Self-Organizing Maps (SOM)/BufferedPanel.cs b/Samples/Neuro/Self-Organizing Maps (SOM)/BufferedPanel.cs new file mode 100644 index 0000000000..43f6f8adf --- /dev/null +++ b/Samples/Neuro/Self-Organizing Maps (SOM)/BufferedPanel.cs @@ -0,0 +1,19 @@ +using System; +using System.Windows.Forms; + +namespace SampleApp +{ + /// + /// Dummy class to enable doble buffering in Panel + /// + public class BufferedPanel : System.Windows.Forms.Panel + { + // Construcor + public BufferedPanel( ) + { + // Update control style + SetStyle( ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | + ControlStyles.DoubleBuffer | ControlStyles.UserPaint, true ); + } + } +} diff --git a/Samples/Neuro/Self-Organizing Maps (SOM)/MainForm.cs b/Samples/Neuro/Self-Organizing Maps (SOM)/MainForm.cs new file mode 100644 index 0000000000..8b7f6f2c9 --- /dev/null +++ b/Samples/Neuro/Self-Organizing Maps (SOM)/MainForm.cs @@ -0,0 +1,736 @@ +// Kohonen SOM 2D Organizing +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +using System; +using System.Drawing; +using System.Collections; +using System.ComponentModel; +using System.Windows.Forms; +using System.Data; +using System.Threading; + +using AForge; +using AForge.Neuro; +using AForge.Neuro.Learning; + +namespace SampleApp +{ + + public class MainForm : System.Windows.Forms.Form + { + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Button generateButton; + private BufferedPanel pointsPanel; + private System.Windows.Forms.GroupBox groupBox2; + private BufferedPanel mapPanel; + private System.Windows.Forms.CheckBox showConnectionsCheck; + private System.Windows.Forms.CheckBox showInactiveCheck; + private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox sizeBox; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox radiusBox; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.TextBox rateBox; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.TextBox iterationsBox; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.TextBox currentIterationBox; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.Button stopButton; + private System.Windows.Forms.Button startButton; + /// + /// Required designer variable. + /// + private System.ComponentModel.Container components = null; + + + private const int groupRadius = 20; + private const int pointsCount = 100; + private int[,] points = new int[pointsCount, 2]; // x, y + private double[][] trainingSet = new double[pointsCount][]; + private int[, ,] map; + + private int networkSize = 15; + private int iterations = 500; + private double learningRate = 0.3; + private int learningRadius = 3; + + private Random rand = new Random(); + private Thread workerThread = null; + private volatile bool needToStop = false; + + public MainForm() + { + InitializeComponent(); + + GeneratePoints(); + UpdateSettings(); + } + + /// + /// Clean up any resources being used. + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (components != null) + { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.generateButton = new System.Windows.Forms.Button(); + this.pointsPanel = new SampleApp.BufferedPanel(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.showInactiveCheck = new System.Windows.Forms.CheckBox(); + this.showConnectionsCheck = new System.Windows.Forms.CheckBox(); + this.mapPanel = new SampleApp.BufferedPanel(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.stopButton = new System.Windows.Forms.Button(); + this.startButton = new System.Windows.Forms.Button(); + this.currentIterationBox = new System.Windows.Forms.TextBox(); + this.label8 = new System.Windows.Forms.Label(); + this.label7 = new System.Windows.Forms.Label(); + this.radiusBox = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.rateBox = new System.Windows.Forms.TextBox(); + this.label5 = new System.Windows.Forms.Label(); + this.iterationsBox = new System.Windows.Forms.TextBox(); + this.label6 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.sizeBox = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.groupBox3.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.generateButton); + this.groupBox1.Controls.Add(this.pointsPanel); + this.groupBox1.Location = new System.Drawing.Point(16, 15); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(352, 431); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Points"; + // + // generateButton + // + this.generateButton.Location = new System.Drawing.Point(16, 380); + this.generateButton.Name = "generateButton"; + this.generateButton.Size = new System.Drawing.Size(120, 34); + this.generateButton.TabIndex = 1; + this.generateButton.Text = "&Generate"; + this.generateButton.Click += new System.EventHandler(this.generateButton_Click); + // + // pointsPanel + // + this.pointsPanel.BackColor = System.Drawing.Color.White; + this.pointsPanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.pointsPanel.Location = new System.Drawing.Point(16, 29); + this.pointsPanel.Name = "pointsPanel"; + this.pointsPanel.Size = new System.Drawing.Size(320, 293); + this.pointsPanel.TabIndex = 0; + this.pointsPanel.Paint += new System.Windows.Forms.PaintEventHandler(this.pointsPanel_Paint); + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.showInactiveCheck); + this.groupBox2.Controls.Add(this.showConnectionsCheck); + this.groupBox2.Controls.Add(this.mapPanel); + this.groupBox2.Location = new System.Drawing.Point(384, 15); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(352, 431); + this.groupBox2.TabIndex = 1; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Map"; + // + // showInactiveCheck + // + this.showInactiveCheck.Checked = true; + this.showInactiveCheck.CheckState = System.Windows.Forms.CheckState.Checked; + this.showInactiveCheck.Location = new System.Drawing.Point(16, 387); + this.showInactiveCheck.Name = "showInactiveCheck"; + this.showInactiveCheck.Size = new System.Drawing.Size(256, 24); + this.showInactiveCheck.TabIndex = 2; + this.showInactiveCheck.Text = "Show Inactive Neurons"; + this.showInactiveCheck.CheckedChanged += new System.EventHandler(this.showInactiveCheck_CheckedChanged); + // + // showConnectionsCheck + // + this.showConnectionsCheck.Checked = true; + this.showConnectionsCheck.CheckState = System.Windows.Forms.CheckState.Checked; + this.showConnectionsCheck.Location = new System.Drawing.Point(16, 351); + this.showConnectionsCheck.Name = "showConnectionsCheck"; + this.showConnectionsCheck.Size = new System.Drawing.Size(240, 23); + this.showConnectionsCheck.TabIndex = 1; + this.showConnectionsCheck.Text = "Show Connections"; + this.showConnectionsCheck.CheckedChanged += new System.EventHandler(this.showConnectionsCheck_CheckedChanged); + // + // mapPanel + // + this.mapPanel.BackColor = System.Drawing.Color.White; + this.mapPanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.mapPanel.Location = new System.Drawing.Point(16, 29); + this.mapPanel.Name = "mapPanel"; + this.mapPanel.Size = new System.Drawing.Size(320, 293); + this.mapPanel.TabIndex = 0; + this.mapPanel.Paint += new System.Windows.Forms.PaintEventHandler(this.mapPanel_Paint); + // + // groupBox3 + // + this.groupBox3.Controls.Add(this.stopButton); + this.groupBox3.Controls.Add(this.startButton); + this.groupBox3.Controls.Add(this.currentIterationBox); + this.groupBox3.Controls.Add(this.label8); + this.groupBox3.Controls.Add(this.label7); + this.groupBox3.Controls.Add(this.radiusBox); + this.groupBox3.Controls.Add(this.label4); + this.groupBox3.Controls.Add(this.rateBox); + this.groupBox3.Controls.Add(this.label5); + this.groupBox3.Controls.Add(this.iterationsBox); + this.groupBox3.Controls.Add(this.label6); + this.groupBox3.Controls.Add(this.label3); + this.groupBox3.Controls.Add(this.label2); + this.groupBox3.Controls.Add(this.sizeBox); + this.groupBox3.Controls.Add(this.label1); + this.groupBox3.Location = new System.Drawing.Point(752, 15); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Size = new System.Drawing.Size(288, 431); + this.groupBox3.TabIndex = 2; + this.groupBox3.TabStop = false; + this.groupBox3.Text = "Neural Network"; + // + // stopButton + // + this.stopButton.Enabled = false; + this.stopButton.Location = new System.Drawing.Point(152, 380); + this.stopButton.Name = "stopButton"; + this.stopButton.Size = new System.Drawing.Size(120, 34); + this.stopButton.TabIndex = 16; + this.stopButton.Text = "S&top"; + this.stopButton.Click += new System.EventHandler(this.stopButton_Click); + // + // startButton + // + this.startButton.Location = new System.Drawing.Point(16, 380); + this.startButton.Name = "startButton"; + this.startButton.Size = new System.Drawing.Size(120, 34); + this.startButton.TabIndex = 15; + this.startButton.Text = "&Start"; + this.startButton.Click += new System.EventHandler(this.startButton_Click); + // + // currentIterationBox + // + this.currentIterationBox.Location = new System.Drawing.Point(176, 234); + this.currentIterationBox.Name = "currentIterationBox"; + this.currentIterationBox.ReadOnly = true; + this.currentIterationBox.Size = new System.Drawing.Size(96, 26); + this.currentIterationBox.TabIndex = 14; + // + // label8 + // + this.label8.Location = new System.Drawing.Point(16, 237); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(160, 23); + this.label8.TabIndex = 13; + this.label8.Text = "Curren iteration:"; + // + // label7 + // + this.label7.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.label7.Location = new System.Drawing.Point(16, 216); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(256, 3); + this.label7.TabIndex = 12; + // + // radiusBox + // + this.radiusBox.Location = new System.Drawing.Point(176, 175); + this.radiusBox.Name = "radiusBox"; + this.radiusBox.Size = new System.Drawing.Size(96, 26); + this.radiusBox.TabIndex = 11; + // + // label4 + // + this.label4.Location = new System.Drawing.Point(16, 178); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(160, 24); + this.label4.TabIndex = 10; + this.label4.Text = "Initial radius:"; + // + // rateBox + // + this.rateBox.Location = new System.Drawing.Point(176, 139); + this.rateBox.Name = "rateBox"; + this.rateBox.Size = new System.Drawing.Size(96, 26); + this.rateBox.TabIndex = 9; + // + // label5 + // + this.label5.Location = new System.Drawing.Point(16, 142); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(160, 23); + this.label5.TabIndex = 8; + this.label5.Text = "Initial learning rate:"; + // + // iterationsBox + // + this.iterationsBox.Location = new System.Drawing.Point(176, 102); + this.iterationsBox.Name = "iterationsBox"; + this.iterationsBox.Size = new System.Drawing.Size(96, 26); + this.iterationsBox.TabIndex = 7; + // + // label6 + // + this.label6.Location = new System.Drawing.Point(16, 105); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(96, 24); + this.label6.TabIndex = 6; + this.label6.Text = "Iteraions:"; + // + // label3 + // + this.label3.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.label3.Location = new System.Drawing.Point(16, 88); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(256, 3); + this.label3.TabIndex = 3; + // + // label2 + // + this.label2.Location = new System.Drawing.Point(16, 60); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(240, 22); + this.label2.TabIndex = 2; + this.label2.Text = "(neurons count = size * size)"; + // + // sizeBox + // + this.sizeBox.Location = new System.Drawing.Point(176, 29); + this.sizeBox.Name = "sizeBox"; + this.sizeBox.Size = new System.Drawing.Size(96, 26); + this.sizeBox.TabIndex = 1; + // + // label1 + // + this.label1.Location = new System.Drawing.Point(16, 32); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(86, 24); + this.label1.TabIndex = 0; + this.label1.Text = "Size:"; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(1054, 468); + this.Controls.Add(this.groupBox3); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.Name = "MainForm"; + this.Text = "Kohonen SOM 2D Organizing"; + this.Closing += new System.ComponentModel.CancelEventHandler(this.MainForm_Closing); + this.groupBox1.ResumeLayout(false); + this.groupBox2.ResumeLayout(false); + this.groupBox3.ResumeLayout(false); + this.groupBox3.PerformLayout(); + this.ResumeLayout(false); + + } + #endregion + + + // Delegates to enable async calls for setting controls properties + private delegate void SetTextCallback(System.Windows.Forms.Control control, string text); + + // Thread safe updating of control's text property + private void SetText(System.Windows.Forms.Control control, string text) + { + if (control.InvokeRequired) + { + SetTextCallback d = new SetTextCallback(SetText); + Invoke(d, new object[] { control, text }); + } + else + { + control.Text = text; + } + } + + // On main form closing + private void MainForm_Closing(object sender, System.ComponentModel.CancelEventArgs e) + { + // check if worker thread is running + if ((workerThread != null) && (workerThread.IsAlive)) + { + needToStop = true; + while (!workerThread.Join(100)) + Application.DoEvents(); + } + } + + // Update settings controls + private void UpdateSettings() + { + sizeBox.Text = networkSize.ToString(); + iterationsBox.Text = iterations.ToString(); + rateBox.Text = learningRate.ToString(); + radiusBox.Text = learningRadius.ToString(); + } + + // On "Generate" button click + private void generateButton_Click(object sender, System.EventArgs e) + { + GeneratePoints(); + } + + // Generate point + private void GeneratePoints() + { + int width = pointsPanel.ClientRectangle.Width; + int height = pointsPanel.ClientRectangle.Height; + int diameter = groupRadius * 2; + + // generate groups of ten points + for (int i = 0; i < pointsCount; ) + { + int cx = rand.Next(width); + int cy = rand.Next(height); + + // generate group + for (int j = 0; (i < pointsCount) && (j < 10); ) + { + int x = cx + rand.Next(diameter) - groupRadius; + int y = cy + rand.Next(diameter) - groupRadius; + + // check if wee are not out + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) + { + continue; + } + + // add point + points[i, 0] = x; + points[i, 1] = y; + + j++; + i++; + } + } + + map = null; + pointsPanel.Invalidate(); + mapPanel.Invalidate(); + } + + // Paint points + private void pointsPanel_Paint(object sender, System.Windows.Forms.PaintEventArgs e) + { + Graphics g = e.Graphics; + + using (Brush brush = new SolidBrush(Color.Blue)) + { + // draw all points + for (int i = 0, n = points.GetLength(0); i < n; i++) + { + g.FillEllipse(brush, points[i, 0] - 2, points[i, 1] - 2, 5, 5); + } + } + } + + // Paint map + private void mapPanel_Paint(object sender, System.Windows.Forms.PaintEventArgs e) + { + Graphics g = e.Graphics; + + if (map != null) + { + // + bool showConnections = showConnectionsCheck.Checked; + bool showInactive = showInactiveCheck.Checked; + + // pens and brushes + Brush brush = new SolidBrush(Color.Blue); + Brush brushGray = new SolidBrush(Color.FromArgb(192, 192, 192)); + Pen pen = new Pen(Color.Blue, 1); + Pen penGray = new Pen(Color.FromArgb(192, 192, 192), 1); + + // lock + Monitor.Enter(this); + + if (showConnections) + { + // draw connections + for (int i = 0, n = map.GetLength(0); i < n; i++) + { + for (int j = 0, k = map.GetLength(1); j < k; j++) + { + if ((!showInactive) && (map[i, j, 2] == 0)) + continue; + + // left + if ((i > 0) && ((showInactive) || (map[i - 1, j, 2] == 1))) + { + g.DrawLine(((map[i, j, 2] == 0) || (map[i - 1, j, 2] == 0)) ? penGray : pen, map[i, j, 0], map[i, j, 1], map[i - 1, j, 0], map[i - 1, j, 1]); + } + + // right + if ((i < n - 1) && ((showInactive) || (map[i + 1, j, 2] == 1))) + { + g.DrawLine(((map[i, j, 2] == 0) || (map[i + 1, j, 2] == 0)) ? penGray : pen, map[i, j, 0], map[i, j, 1], map[i + 1, j, 0], map[i + 1, j, 1]); + } + + // top + if ((j > 0) && ((showInactive) || (map[i, j - 1, 2] == 1))) + { + g.DrawLine(((map[i, j, 2] == 0) || (map[i, j - 1, 2] == 0)) ? penGray : pen, map[i, j, 0], map[i, j, 1], map[i, j - 1, 0], map[i, j - 1, 1]); + } + + // bottom + if ((j < k - 1) && ((showInactive) || (map[i, j + 1, 2] == 1))) + { + g.DrawLine(((map[i, j, 2] == 0) || (map[i, j + 1, 2] == 0)) ? penGray : pen, map[i, j, 0], map[i, j, 1], map[i, j + 1, 0], map[i, j + 1, 1]); + } + } + } + } + + // draw the map + for (int i = 0, n = map.GetLength(0); i < n; i++) + { + for (int j = 0, k = map.GetLength(1); j < k; j++) + { + if ((!showInactive) && (map[i, j, 2] == 0)) + continue; + + // draw the point + g.FillEllipse((map[i, j, 2] == 0) ? brushGray : brush, map[i, j, 0] - 2, map[i, j, 1] - 2, 5, 5); + } + } + + // unlock + Monitor.Exit(this); + + brush.Dispose(); + brushGray.Dispose(); + pen.Dispose(); + penGray.Dispose(); + } + } + + // Delegates to enable async calls for setting controls properties + private delegate void EnableCallback(bool enable); + + // Enable/disale controls (safe for threading) + private void EnableControls(bool enable) + { + if (InvokeRequired) + { + EnableCallback d = new EnableCallback(EnableControls); + Invoke(d, new object[] { enable }); + } + else + { + sizeBox.Enabled = enable; + iterationsBox.Enabled = enable; + rateBox.Enabled = enable; + radiusBox.Enabled = enable; + + startButton.Enabled = enable; + generateButton.Enabled = enable; + stopButton.Enabled = !enable; + } + } + + // Show/hide connections on map + private void showConnectionsCheck_CheckedChanged(object sender, System.EventArgs e) + { + mapPanel.Invalidate(); + } + + // Show/hide inactive neurons on map + private void showInactiveCheck_CheckedChanged(object sender, System.EventArgs e) + { + mapPanel.Invalidate(); + } + + // On "Start" button click + private void startButton_Click(object sender, System.EventArgs e) + { + // get network size + try + { + networkSize = Math.Max(5, Math.Min(50, int.Parse(sizeBox.Text))); + } + catch + { + networkSize = 15; + } + // get iterations count + try + { + iterations = Math.Max(10, Math.Min(1000000, int.Parse(iterationsBox.Text))); + } + catch + { + iterations = 500; + } + // get learning rate + try + { + learningRate = Math.Max(0.00001, Math.Min(1.0, double.Parse(rateBox.Text))); + } + catch + { + learningRate = 0.3; + } + // get radius + try + { + learningRadius = Math.Max(1, Math.Min(30, int.Parse(radiusBox.Text))); + } + catch + { + learningRadius = 3; + } + // update settings controls + UpdateSettings(); + + // disable all settings controls except "Stop" button + EnableControls(false); + + // generate training set + for (int i = 0; i < pointsCount; i++) + { + // create new training sample + trainingSet[i] = new double[2] { points[i, 0], points[i, 1] }; + } + + // run worker thread + needToStop = false; + workerThread = new Thread(new ThreadStart(SearchSolution)); + workerThread.Start(); + } + + // On "Stop" button click + private void stopButton_Click(object sender, System.EventArgs e) + { + // stop worker thread + needToStop = true; + while (!workerThread.Join(100)) + Application.DoEvents(); + workerThread = null; + } + + // Worker thread + void SearchSolution() + { + // set random generators range + Neuron.RandRange = new Range(0, Math.Max(pointsPanel.ClientRectangle.Width, pointsPanel.ClientRectangle.Height)); + + // create network + DistanceNetwork network = new DistanceNetwork(2, networkSize * networkSize); + + // create learning algorithm + SOMLearning trainer = new SOMLearning(network, networkSize, networkSize); + + // create map + map = new int[networkSize, networkSize, 3]; + + double fixedLearningRate = learningRate / 10; + double driftingLearningRate = fixedLearningRate * 9; + + // iterations + int i = 0; + + // loop + while (!needToStop) + { + trainer.LearningRate = driftingLearningRate * (iterations - i) / iterations + fixedLearningRate; + trainer.LearningRadius = (double)learningRadius * (iterations - i) / iterations; + + // run training epoch + trainer.RunEpoch(trainingSet); + + // update map + UpdateMap(network); + + // increase current iteration + i++; + + // set current iteration's info + SetText(currentIterationBox, i.ToString()); + + // stop ? + if (i >= iterations) + break; + } + + // enable settings controls + EnableControls(true); + } + + // Update map + private void UpdateMap(DistanceNetwork network) + { + // get first layer + Layer layer = network.Layers[0]; + + // lock + Monitor.Enter(this); + + // run through all neurons + for (int i = 0; i < layer.Neurons.Length; i++) + { + Neuron neuron = layer.Neurons[i]; + + int x = i % networkSize; + int y = i / networkSize; + + map[y, x, 0] = (int)neuron.Weights[0]; + map[y, x, 1] = (int)neuron.Weights[1]; + map[y, x, 2] = 0; + } + + // collect active neurons + for (int i = 0; i < pointsCount; i++) + { + network.Compute(trainingSet[i]); + int w = network.GetWinner(); + + map[w / networkSize, w % networkSize, 2] = 1; + } + + // unlock + Monitor.Exit(this); + + // + mapPanel.Invalidate(); + } + } +} diff --git a/Samples/Neuro/Self-Organizing Maps (SOM)/MainForm.resx b/Samples/Neuro/Self-Organizing Maps (SOM)/MainForm.resx new file mode 100644 index 0000000000..c7e0d4bdf --- /dev/null +++ b/Samples/Neuro/Self-Organizing Maps (SOM)/MainForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Neuro/Self-Organizing Maps (SOM)/Program.cs b/Samples/Neuro/Self-Organizing Maps (SOM)/Program.cs new file mode 100644 index 0000000000..316268492 --- /dev/null +++ b/Samples/Neuro/Self-Organizing Maps (SOM)/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Windows.Forms; + +namespace SampleApp +{ + static class Program + { + [STAThread] + static void Main() + { + if (Environment.OSVersion.Version.Major >= 6) + SetProcessDPIAware(); + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + + [System.Runtime.InteropServices.DllImport("user32.dll")] + private static extern bool SetProcessDPIAware(); + } +} diff --git a/Samples/Neuro/Self-Organizing Maps (SOM)/Self Organizing Maps (SOM).csproj b/Samples/Neuro/Self-Organizing Maps (SOM)/Self Organizing Maps (SOM).csproj new file mode 100644 index 0000000000..d3b70d968 --- /dev/null +++ b/Samples/Neuro/Self-Organizing Maps (SOM)/Self Organizing Maps (SOM).csproj @@ -0,0 +1,145 @@ + + + + Local + 9.0.21022 + 2.0 + {C646B987-EA7E-4D82-A930-448DE583FEB3} + Debug + AnyCPU + App.ico + + + Self-Organinizing Maps %28SOM%29 + + + JScript + Grid + IE50 + false + WinExe + SampleApp + OnBuildSuccess + SampleApp.Program + + + + + 3.5 + v4.0 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + bin\x86\Debug\ + DEBUG;TRACE + 285212672 + 4096 + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + 285212672 + true + 4096 + x86 + prompt + MinimumRecommendedRules.ruleset + + + + ..\..\..\Release\net40\Accord.dll + + + ..\..\..\Release\net40\Accord.Math.dll + + + ..\..\..\Release\net40\Accord.Neuro.dll + + + System + + + System.Data + + + System.Drawing + + + System.Windows.Forms + + + System.XML + + + + + + + Code + + + Component + + + Form + + + MainForm.cs + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + PreserveNewest + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/Neuro/Self-Organizing Maps (SOM)/app.config b/Samples/Neuro/Self-Organizing Maps (SOM)/app.config new file mode 100644 index 0000000000..57c0f2cbc --- /dev/null +++ b/Samples/Neuro/Self-Organizing Maps (SOM)/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Samples/Neuro/Travelling Salesman (SOM)/Accord.dll.config b/Samples/Neuro/Travelling Salesman (SOM)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Neuro/Travelling Salesman (SOM)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Neuro/Travelling Salesman (SOM)/App.ico b/Samples/Neuro/Travelling Salesman (SOM)/App.ico new file mode 100644 index 0000000000..3a5525fd7 Binary files /dev/null and b/Samples/Neuro/Travelling Salesman (SOM)/App.ico differ diff --git a/Samples/Neuro/Travelling Salesman (SOM)/AssemblyInfo.cs b/Samples/Neuro/Travelling Salesman (SOM)/AssemblyInfo.cs new file mode 100644 index 0000000000..4d63d10b3 --- /dev/null +++ b/Samples/Neuro/Travelling Salesman (SOM)/AssemblyInfo.cs @@ -0,0 +1,59 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle("Neuro SOM SampleApp")] +[assembly: AssemblyDescription("Neuro SOM SampleApp sample")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("AForge")] +[assembly: AssemblyProduct("AForge.NET")] +[assembly: AssemblyCopyright("AForge 2008")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("2.0.0.0")] +[assembly: AssemblyFileVersion("2.0.0.0")] + +// +// In order to sign your assembly you must specify a key to use. Refer to the +// Microsoft .NET Framework documentation for more information on assembly signing. +// +// Use the attributes below to control which key is used for signing. +// +// Notes: +// (*) If no key is specified, the assembly is not signed. +// (*) KeyName refers to a key that has been installed in the Crypto Service +// Provider (CSP) on your machine. KeyFile refers to a file which contains +// a key. +// (*) If the KeyFile and the KeyName values are both specified, the +// following processing occurs: +// (1) If the KeyName can be found in the CSP, that key is used. +// (2) If the KeyName does not exist and the KeyFile does exist, the key +// in the KeyFile is installed into the CSP and used. +// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. +// When specifying the KeyFile, the location of the KeyFile should be +// relative to the project output directory which is +// %Project Directory%\obj\. For example, if your KeyFile is +// located in the project directory, you would specify the AssemblyKeyFile +// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] +// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework +// documentation for more information on this. +// +[assembly: AssemblyDelaySign(false)] +[assembly: AssemblyKeyFile("")] +[assembly: AssemblyKeyName("")] diff --git a/Samples/Neuro/Travelling Salesman (SOM)/MainForm.cs b/Samples/Neuro/Travelling Salesman (SOM)/MainForm.cs new file mode 100644 index 0000000000..0d0c8dda1 --- /dev/null +++ b/Samples/Neuro/Travelling Salesman (SOM)/MainForm.cs @@ -0,0 +1,553 @@ +// Traveling Salesman Problem using Elastic Net +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +using System; +using System.Drawing; +using System.Collections; +using System.ComponentModel; +using System.Windows.Forms; +using System.Data; +using System.Threading; + +using AForge; +using AForge.Neuro; +using AForge.Neuro.Learning; +using AForge.Controls; + +namespace SampleApp +{ + + public class MainForm : System.Windows.Forms.Form + { + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Button generateMapButton; + private System.Windows.Forms.TextBox citiesCountBox; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox neuronsBox; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox currentIterationBox; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.TextBox rateBox; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.TextBox iterationsBox; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Button stopButton; + private System.Windows.Forms.Button startButton; + private AForge.Controls.Chart chart; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.TextBox radiusBox; + /// + /// Required designer variable. + /// + private System.ComponentModel.Container components = null; + + private int citiesCount = 10; + private int neurons = 20; + private int iterations = 500; + private double learningRate = 0.5; + private double learningRadius = 0.5; + + private double[,] map = null; + private Random rand = new Random(); + + private Thread workerThread = null; + private volatile bool needToStop = false; + + public MainForm() + { + InitializeComponent(); + + // initialize chart + chart.AddDataSeries("cities", Color.Red, Chart.SeriesType.Dots, 5, false); + chart.AddDataSeries("path", Color.Blue, Chart.SeriesType.Line, 1, false); + chart.RangeX = new Range(0, 1000); + chart.RangeY = new Range(0, 1000); + + // + UpdateSettings(); + GenerateMap(); + } + + /// + /// Clean up any resources being used. + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (components != null) + { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.generateMapButton = new System.Windows.Forms.Button(); + this.citiesCountBox = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.stopButton = new System.Windows.Forms.Button(); + this.startButton = new System.Windows.Forms.Button(); + this.currentIterationBox = new System.Windows.Forms.TextBox(); + this.label8 = new System.Windows.Forms.Label(); + this.label7 = new System.Windows.Forms.Label(); + this.rateBox = new System.Windows.Forms.TextBox(); + this.label5 = new System.Windows.Forms.Label(); + this.iterationsBox = new System.Windows.Forms.TextBox(); + this.label6 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.neuronsBox = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.radiusBox = new System.Windows.Forms.TextBox(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.SuspendLayout(); + this.chart = new AForge.Controls.Chart(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.generateMapButton); + this.groupBox1.Controls.Add(this.citiesCountBox); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.chart); + this.groupBox1.Location = new System.Drawing.Point(10, 10); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(300, 340); + this.groupBox1.TabIndex = 1; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Map"; + // + // generateMapButton + // + this.generateMapButton.Location = new System.Drawing.Point(110, 309); + this.generateMapButton.Name = "generateMapButton"; + this.generateMapButton.Size = new System.Drawing.Size(75, 22); + this.generateMapButton.TabIndex = 3; + this.generateMapButton.Text = "&Generate"; + this.generateMapButton.Click += new System.EventHandler(this.generateMapButton_Click); + // + // citiesCountBox + // + this.citiesCountBox.Location = new System.Drawing.Point(50, 310); + this.citiesCountBox.Name = "citiesCountBox"; + this.citiesCountBox.Size = new System.Drawing.Size(50, 20); + this.citiesCountBox.TabIndex = 2; + this.citiesCountBox.Text = ""; + // + // label1 + // + this.label1.Location = new System.Drawing.Point(10, 312); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(40, 16); + this.label1.TabIndex = 1; + this.label1.Text = "Cities:"; + // + // chart + // + this.chart.Location = new System.Drawing.Point(10, 20); + this.chart.Name = "chart"; + this.chart.Size = new System.Drawing.Size(280, 280); + this.chart.TabIndex = 4; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.radiusBox); + this.groupBox2.Controls.Add(this.label4); + this.groupBox2.Controls.Add(this.stopButton); + this.groupBox2.Controls.Add(this.startButton); + this.groupBox2.Controls.Add(this.currentIterationBox); + this.groupBox2.Controls.Add(this.label8); + this.groupBox2.Controls.Add(this.label7); + this.groupBox2.Controls.Add(this.rateBox); + this.groupBox2.Controls.Add(this.label5); + this.groupBox2.Controls.Add(this.iterationsBox); + this.groupBox2.Controls.Add(this.label6); + this.groupBox2.Controls.Add(this.label3); + this.groupBox2.Controls.Add(this.neuronsBox); + this.groupBox2.Controls.Add(this.label2); + this.groupBox2.Location = new System.Drawing.Point(320, 10); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(180, 340); + this.groupBox2.TabIndex = 2; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Neural Network"; + // + // stopButton + // + this.stopButton.Enabled = false; + this.stopButton.Location = new System.Drawing.Point(95, 305); + this.stopButton.Name = "stopButton"; + this.stopButton.TabIndex = 23; + this.stopButton.Text = "S&top"; + this.stopButton.Click += new System.EventHandler(this.stopButton_Click); + // + // startButton + // + this.startButton.Location = new System.Drawing.Point(10, 305); + this.startButton.Name = "startButton"; + this.startButton.TabIndex = 22; + this.startButton.Text = "&Start"; + this.startButton.Click += new System.EventHandler(this.startButton_Click); + // + // currentIterationBox + // + this.currentIterationBox.Location = new System.Drawing.Point(110, 150); + this.currentIterationBox.Name = "currentIterationBox"; + this.currentIterationBox.ReadOnly = true; + this.currentIterationBox.Size = new System.Drawing.Size(60, 20); + this.currentIterationBox.TabIndex = 21; + this.currentIterationBox.Text = ""; + // + // label8 + // + this.label8.Location = new System.Drawing.Point(10, 152); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(100, 16); + this.label8.TabIndex = 20; + this.label8.Text = "Curren iteration:"; + // + // label7 + // + this.label7.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.label7.Location = new System.Drawing.Point(10, 139); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(160, 2); + this.label7.TabIndex = 19; + // + // rateBox + // + this.rateBox.Location = new System.Drawing.Point(110, 85); + this.rateBox.Name = "rateBox"; + this.rateBox.Size = new System.Drawing.Size(60, 20); + this.rateBox.TabIndex = 18; + this.rateBox.Text = ""; + // + // label5 + // + this.label5.Location = new System.Drawing.Point(10, 87); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(100, 16); + this.label5.TabIndex = 17; + this.label5.Text = "Initial learning rate:"; + // + // iterationsBox + // + this.iterationsBox.Location = new System.Drawing.Point(110, 60); + this.iterationsBox.Name = "iterationsBox"; + this.iterationsBox.Size = new System.Drawing.Size(60, 20); + this.iterationsBox.TabIndex = 16; + this.iterationsBox.Text = ""; + // + // label6 + // + this.label6.Location = new System.Drawing.Point(10, 62); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(60, 16); + this.label6.TabIndex = 15; + this.label6.Text = "Iteraions:"; + // + // label3 + // + this.label3.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.label3.Location = new System.Drawing.Point(10, 48); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(160, 2); + this.label3.TabIndex = 4; + // + // neuronsBox + // + this.neuronsBox.Location = new System.Drawing.Point(110, 20); + this.neuronsBox.Name = "neuronsBox"; + this.neuronsBox.Size = new System.Drawing.Size(60, 20); + this.neuronsBox.TabIndex = 1; + this.neuronsBox.Text = ""; + // + // label2 + // + this.label2.Location = new System.Drawing.Point(10, 22); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(60, 16); + this.label2.TabIndex = 0; + this.label2.Text = "Neurons:"; + // + // label4 + // + this.label4.Location = new System.Drawing.Point(10, 112); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(100, 16); + this.label4.TabIndex = 24; + this.label4.Text = "Learning radius:"; + // + // radiusBox + // + this.radiusBox.Location = new System.Drawing.Point(110, 110); + this.radiusBox.Name = "radiusBox"; + this.radiusBox.Size = new System.Drawing.Size(60, 20); + this.radiusBox.TabIndex = 25; + this.radiusBox.Text = ""; + // + // MainForm + // + this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); + this.ClientSize = new System.Drawing.Size(509, 360); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.Name = "MainForm"; + this.Text = "Traveling Salesman Problem using Elastic Net"; + this.Closing += new System.ComponentModel.CancelEventHandler(this.MainForm_Closing); + this.groupBox1.ResumeLayout(false); + this.groupBox2.ResumeLayout(false); + this.ResumeLayout(false); + + } + #endregion + + + // Delegates to enable async calls for setting controls properties + private delegate void SetTextCallback(System.Windows.Forms.Control control, string text); + + // Thread safe updating of control's text property + private void SetText(System.Windows.Forms.Control control, string text) + { + if (control.InvokeRequired) + { + SetTextCallback d = new SetTextCallback(SetText); + Invoke(d, new object[] { control, text }); + } + else + { + control.Text = text; + } + } + + // On main form closing + private void MainForm_Closing(object sender, System.ComponentModel.CancelEventArgs e) + { + // check if worker thread is running + if ((workerThread != null) && (workerThread.IsAlive)) + { + needToStop = true; + while (!workerThread.Join(100)) + Application.DoEvents(); + } + } + + // Update settings controls + private void UpdateSettings() + { + citiesCountBox.Text = citiesCount.ToString(); + neuronsBox.Text = neurons.ToString(); + iterationsBox.Text = iterations.ToString(); + rateBox.Text = learningRate.ToString(); + radiusBox.Text = learningRadius.ToString(); + } + + // Generate new map for the Traivaling Salesman problem + private void GenerateMap() + { + Random rand = new Random((int)DateTime.Now.Ticks); + + // create coordinates array + map = new double[citiesCount, 2]; + + for (int i = 0; i < citiesCount; i++) + { + map[i, 0] = rand.Next(1001); + map[i, 1] = rand.Next(1001); + } + + // set the map + chart.UpdateDataSeries("cities", map); + // erase path if it is + chart.UpdateDataSeries("path", null); + } + + // On "Generate" button click - generate map + private void generateMapButton_Click(object sender, System.EventArgs e) + { + // get cities count + try + { + citiesCount = Math.Max(5, Math.Min(50, int.Parse(citiesCountBox.Text))); + } + catch + { + citiesCount = 20; + } + citiesCountBox.Text = citiesCount.ToString(); + + // regenerate map + GenerateMap(); + } + + // Delegates to enable async calls for setting controls properties + private delegate void EnableCallback(bool enable); + + // Enable/disale controls (safe for threading) + private void EnableControls(bool enable) + { + if (InvokeRequired) + { + EnableCallback d = new EnableCallback(EnableControls); + Invoke(d, new object[] { enable }); + } + else + { + neuronsBox.Enabled = enable; + iterationsBox.Enabled = enable; + rateBox.Enabled = enable; + radiusBox.Enabled = enable; + + startButton.Enabled = enable; + generateMapButton.Enabled = enable; + stopButton.Enabled = !enable; + } + } + + // On "Start" button click + private void startButton_Click(object sender, System.EventArgs e) + { + // get network size + try + { + neurons = Math.Max(5, Math.Min(50, int.Parse(neuronsBox.Text))); + } + catch + { + neurons = 20; + } + // get iterations count + try + { + iterations = Math.Max(10, Math.Min(1000000, int.Parse(iterationsBox.Text))); + } + catch + { + iterations = 500; + } + // get learning rate + try + { + learningRate = Math.Max(0.00001, Math.Min(1.0, double.Parse(rateBox.Text))); + } + catch + { + learningRate = 0.5; + } + // get learning radius + try + { + learningRadius = Math.Max(0.00001, Math.Min(1.0, double.Parse(radiusBox.Text))); + } + catch + { + learningRadius = 0.5; + } + // update settings controls + UpdateSettings(); + + // disable all settings controls except "Stop" button + EnableControls(false); + + // run worker thread + needToStop = false; + workerThread = new Thread(new ThreadStart(SearchSolution)); + workerThread.Start(); + } + + // On "Stop" button click + private void stopButton_Click(object sender, System.EventArgs e) + { + // stop worker thread + needToStop = true; + while (!workerThread.Join(100)) + Application.DoEvents(); + workerThread = null; + } + + // Worker thread + void SearchSolution() + { + // set random generators range + Neuron.RandRange = new Range(0, 1000); + + // create network + DistanceNetwork network = new DistanceNetwork(2, neurons); + + // create learning algorithm + ElasticNetworkLearning trainer = new ElasticNetworkLearning(network); + + double fixedLearningRate = learningRate / 20; + double driftingLearningRate = fixedLearningRate * 19; + + // path + double[,] path = new double[neurons + 1, 2]; + + // input + double[] input = new double[2]; + + // iterations + int i = 0; + + // loop + while (!needToStop) + { + // update learning speed & radius + trainer.LearningRate = driftingLearningRate * (iterations - i) / iterations + fixedLearningRate; + trainer.LearningRadius = learningRadius * (iterations - i) / iterations; + + // set network input + int currentCity = rand.Next(citiesCount); + input[0] = map[currentCity, 0]; + input[1] = map[currentCity, 1]; + + // run one training iteration + trainer.Run(input); + + // show current path + for (int j = 0; j < neurons; j++) + { + path[j, 0] = network.Layers[0].Neurons[j].Weights[0]; + path[j, 1] = network.Layers[0].Neurons[j].Weights[1]; + } + path[neurons, 0] = network.Layers[0].Neurons[0].Weights[0]; + path[neurons, 1] = network.Layers[0].Neurons[0].Weights[1]; + + chart.UpdateDataSeries("path", path); + + // increase current iteration + i++; + + // set current iteration's info + SetText(currentIterationBox, i.ToString()); + + // stop ? + if (i >= iterations) + break; + } + + // enable settings controls + EnableControls(true); + } + } +} \ No newline at end of file diff --git a/Samples/Neuro/Travelling Salesman (SOM)/MainForm.resx b/Samples/Neuro/Travelling Salesman (SOM)/MainForm.resx new file mode 100644 index 0000000000..93eebbe4b --- /dev/null +++ b/Samples/Neuro/Travelling Salesman (SOM)/MainForm.resx @@ -0,0 +1,319 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Private + + + 8, 8 + + + True + + + False + + + True + + + Private + + + False + + + Private + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + Private + + + 8, 8 + + + False + + + False + + + True + + + Private + + + False + + + Private + + + Private + + + False + + + Private + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + False + + + Private + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + False + + + Private + + + Private + + + Private + + + False + + + Private + + + False + + + Private + + + Private + + + False + + + Private + + + Private + + + Private + + + False + + + Private + + + False + + + (Default) + + + False + + + False + + + 8, 8 + + + True + + + MainForm + + + 80 + + + False + + + Private + + \ No newline at end of file diff --git a/Samples/Neuro/Travelling Salesman (SOM)/Program.cs b/Samples/Neuro/Travelling Salesman (SOM)/Program.cs new file mode 100644 index 0000000000..316268492 --- /dev/null +++ b/Samples/Neuro/Travelling Salesman (SOM)/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Windows.Forms; + +namespace SampleApp +{ + static class Program + { + [STAThread] + static void Main() + { + if (Environment.OSVersion.Version.Major >= 6) + SetProcessDPIAware(); + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + + [System.Runtime.InteropServices.DllImport("user32.dll")] + private static extern bool SetProcessDPIAware(); + } +} diff --git a/Samples/Neuro/Travelling Salesman (SOM)/TSP.sln b/Samples/Neuro/Travelling Salesman (SOM)/TSP.sln new file mode 100644 index 0000000000..3a2547d8d --- /dev/null +++ b/Samples/Neuro/Travelling Salesman (SOM)/TSP.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C# Express 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TSP", "TSP.csproj", "{6FA77B7F-E933-4B25-AC4C-99E343B35AC8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6FA77B7F-E933-4B25-AC4C-99E343B35AC8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6FA77B7F-E933-4B25-AC4C-99E343B35AC8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6FA77B7F-E933-4B25-AC4C-99E343B35AC8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6FA77B7F-E933-4B25-AC4C-99E343B35AC8}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/Neuro/Travelling Salesman (SOM)/Travelling Salesman (SOM).csproj b/Samples/Neuro/Travelling Salesman (SOM)/Travelling Salesman (SOM).csproj new file mode 100644 index 0000000000..4c9480347 --- /dev/null +++ b/Samples/Neuro/Travelling Salesman (SOM)/Travelling Salesman (SOM).csproj @@ -0,0 +1,192 @@ + + + + Local + 9.0.21022 + 2.0 + {6FA77B7F-E933-4B25-AC4C-99E343B35AC8} + Debug + AnyCPU + App.ico + + + TSP + + + JScript + Grid + IE50 + false + WinExe + TSP + OnBuildSuccess + + + + + + + 3.5 + v4.0 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + bin\Debug\ + false + 285212672 + false + + + DEBUG;TRACE + + + true + 4096 + false + + + false + false + false + false + 4 + full + prompt + + + bin\Release\ + false + 285212672 + false + + + TRACE + + + false + 4096 + false + + + true + false + false + false + 4 + none + prompt + + + true + bin\x86\Debug\ + DEBUG;TRACE + 285212672 + 4096 + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + 285212672 + true + 4096 + x86 + prompt + MinimumRecommendedRules.ruleset + + + + ..\..\..\Release\net40\Accord.dll + + + ..\..\..\Release\net40\Accord.Controls.dll + + + ..\..\..\Release\net40\Accord.Math.dll + + + ..\..\..\Release\net40\Accord.Neuro.dll + + + System + + + System.Data + + + System.Drawing + + + System.Windows.Forms + + + System.XML + + + + + + + Code + + + Form + + + MainForm.cs + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + PreserveNewest + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/Neuro/Travelling Salesman (SOM)/app.config b/Samples/Neuro/Travelling Salesman (SOM)/app.config new file mode 100644 index 0000000000..57c0f2cbc --- /dev/null +++ b/Samples/Neuro/Travelling Salesman (SOM)/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Samples/Samples.sln b/Samples/Samples.sln index 9271f3cb7..e8d66ed68 100644 --- a/Samples/Samples.sln +++ b/Samples/Samples.sln @@ -33,8 +33,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Analysis (KDA)", "Statistic EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sequences (HMM)", "Statistics\Sequences (HMM)\Sequences (HMM).csproj", "{E6CEA943-9111-4CCD-97BD-A63F7DDABBAE}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tabular Filters", "Statistics\Tabular filters\Tabular Filters.csproj", "{6449C3DE-E27F-45A6-AAED-BF7E3028CD0B}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Classification (SVMs)", "MachineLearning\Classification (SVMs)\Classification (SVMs).csproj", "{503EF9C0-CE83-40BE-98B2-3481D9FE3B0D}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Analysis (PLS)", "Statistics\Analysis (PLS)\Analysis (PLS).csproj", "{3929B83A-B1A6-4620-9139-B5DEEEF3DCE4}" @@ -75,7 +73,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Gloves (color tracking)", " EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Controller (interface control)", "Vision\Controller (interface control)\Controller (interface control).csproj", "{95BDACEA-E8DB-4A87-9472-A37F0879179F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dynamic Virtual Wall (Kinect)", "Vision\Kinect\Dynamic Virtual Wall (Kinect).csproj", "{99C1ED90-C4CD-4730-B05C-B99EED60EDD1}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dynamic Virtual Wall (Kinect)", "Vision\Dynamic Virtual Wall (Kinect)\Dynamic Virtual Wall (Kinect).csproj", "{99C1ED90-C4CD-4730-B05C-B99EED60EDD1}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Decision Trees", "MachineLearning\Decision Trees\Decision Trees.csproj", "{67D5F5DD-95D8-4DF3-B4F4-B43A2FCFE02F}" EndProject @@ -122,208 +120,497 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Feature Selection (SVMs)", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Classification (MLR)", "Statistics\Classification (MLR)\Classification (MLR).csproj", "{E0E753EE-4A27-491C-A914-6942A772AAF2}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Detection (Blobs)", "Imaging\Detection (Blobs)\Detection (Blobs).csproj", "{742487A3-DD2E-4F47-9ABB-77E88653A1D3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hough Transform", "Imaging\Hough Transform\Hough Transform.csproj", "{6B66B73D-481C-479B-AC13-F5E332D12293}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Filters (Images)", "Imaging\Filters (Images)\Filters (Images).csproj", "{744FC79F-5B6D-44AD-8C34-1ABB6EABAE6B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Image Viewer", "Imaging\Image Viewer\Image Viewer.csproj", "{EE5B96F4-EEB3-4606-98C9-6F1242B41FD2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Textures", "Imaging\Texture\Textures.csproj", "{E34CC841-CE29-4B39-9BE5-D98502330F55}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Animat (Sarsa, QLearning)", "MachineLearning\Animat\Animat (Sarsa, QLearning).csproj", "{B4892057-CAE6-41F4-A75D-88E61331A2D0}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Genetic", "Genetic", "{17A03FBD-E6BD-4017-ACA1-8D4E0DC6EEBE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Travelling Salesman (GP)", "Genetic\Travelling Salesman (GP)\Travelling Salesman (GP).csproj", "{DEC346FD-C496-4B3E-A0E9-60AE011E3C49}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Fuzzy", "Fuzzy", "{FD30843F-F53A-4D66-A314-068C314D23FE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sets (Fuzzy, Linguistic)", "Fuzzy\Sets (Fuzzy, Linguistic)\Sets (Fuzzy, Linguistic).csproj", "{2C079A0D-8F90-4B4E-85AA-CAD45F7E0CAC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Robot (Inference)", "Fuzzy\Robot (Inference)\Robot (Inference).csproj", "{BCC446EF-0F10-4FBB-AB37-9A9E0B1CDBAB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pose Coordinates (POSIT)", "Math\Pose Coordinates (POSIT)\Pose Coordinates (POSIT).csproj", "{3B59E324-53FC-4837-AF37-61FC4B51E2D1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Self Organizing Maps (SOM)", "Neuro\Self-Organizing Maps (SOM)\Self Organizing Maps (SOM).csproj", "{C646B987-EA7E-4D82-A930-448DE583FEB3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Clustering (SOM)", "Neuro\Clustering (SOM)\Clustering (SOM).csproj", "{59E2469C-197F-4A4C-9D52-AA58EA49927E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Travelling Salesman (SOM)", "Neuro\Travelling Salesman (SOM)\Travelling Salesman (SOM).csproj", "{6FA77B7F-E933-4B25-AC4C-99E343B35AC8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Motion detection", "Vision\Motion detection\Motion detection.csproj", "{9800A224-0BF0-4D5D-A03C-AA7A4842D3B8}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Video", "Video", "{004C9C77-4F14-4ED4-ACAE-781D6B860CA2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kinect Capture", "Video\Kinect Capture\Kinect Capture.csproj", "{B4CB129D-51F9-4C86-B520-7AC50537A70B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Video Player", "Video\Video Player\Video Player.csproj", "{B31C0650-991B-4B28-9864-AE80C1785A3F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Snapshot Maker", "Video\Snapshot Maker\Snapshot Maker.csproj", "{779A59F0-BF3B-4AE5-B323-97D37CD67233}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Two Cameras", "Video\Two Cameras\Two Cameras.csproj", "{AB55ABF6-4AD9-4F8A-9E9D-8B61F89766A6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ximea Sample", "Video\Ximea Sample\Ximea Sample.csproj", "{40C644F9-5AF9-44BB-9649-02149933E092}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Genetic Programming", "Genetic\Genetic Programming\Genetic Programming.csproj", "{2E6B9575-0C86-4034-8A8E-13C880B69A6F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pose Estimation (POSIT)", "Imaging\Pose Estimation (POSIT)\Pose Estimation (POSIT).csproj", "{651EBEC1-045E-4A74-A9F6-7E8DD223DD7A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perceptron", "Neuro\Perceptron\Perceptron.csproj", "{7FA21B39-6926-412C-BB5E-99F957E5CC19}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Filters (Tables)", "Statistics\Filters (Tables)\Filters (Tables).csproj", "{6449C3DE-E27F-45A6-AAED-BF7E3028CD0B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Detection (Shape)", "Imaging\Detection (Shape)\Detection (Shape).csproj", "{722FD1AB-4193-45B1-A94E-10B6E5C9AA05}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x86 = Debug|x86 + Mono|x86 = Mono|x86 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {01BA7F4B-6C29-48D1-ADB5-087B8DCF8AC3}.Debug|x86.ActiveCfg = Debug|x86 {01BA7F4B-6C29-48D1-ADB5-087B8DCF8AC3}.Debug|x86.Build.0 = Debug|x86 + {01BA7F4B-6C29-48D1-ADB5-087B8DCF8AC3}.Mono|x86.ActiveCfg = Release|x86 + {01BA7F4B-6C29-48D1-ADB5-087B8DCF8AC3}.Mono|x86.Build.0 = Release|x86 {01BA7F4B-6C29-48D1-ADB5-087B8DCF8AC3}.Release|x86.ActiveCfg = Release|x86 {01BA7F4B-6C29-48D1-ADB5-087B8DCF8AC3}.Release|x86.Build.0 = Release|x86 {BCFE9369-F0AF-4DD3-9133-0C60D21F94D6}.Debug|x86.ActiveCfg = Debug|x86 {BCFE9369-F0AF-4DD3-9133-0C60D21F94D6}.Debug|x86.Build.0 = Debug|x86 + {BCFE9369-F0AF-4DD3-9133-0C60D21F94D6}.Mono|x86.ActiveCfg = Release|x86 + {BCFE9369-F0AF-4DD3-9133-0C60D21F94D6}.Mono|x86.Build.0 = Release|x86 {BCFE9369-F0AF-4DD3-9133-0C60D21F94D6}.Release|x86.ActiveCfg = Release|x86 {BCFE9369-F0AF-4DD3-9133-0C60D21F94D6}.Release|x86.Build.0 = Release|x86 {8E3093E1-9B62-4F62-A236-CD6EB40F9CC4}.Debug|x86.ActiveCfg = Debug|x86 {8E3093E1-9B62-4F62-A236-CD6EB40F9CC4}.Debug|x86.Build.0 = Debug|x86 + {8E3093E1-9B62-4F62-A236-CD6EB40F9CC4}.Mono|x86.ActiveCfg = Release|x86 + {8E3093E1-9B62-4F62-A236-CD6EB40F9CC4}.Mono|x86.Build.0 = Release|x86 {8E3093E1-9B62-4F62-A236-CD6EB40F9CC4}.Release|x86.ActiveCfg = Release|x86 {8E3093E1-9B62-4F62-A236-CD6EB40F9CC4}.Release|x86.Build.0 = Release|x86 {E6DD6D23-3FFC-4DF8-B2F8-CDA5BF77348D}.Debug|x86.ActiveCfg = Debug|x86 {E6DD6D23-3FFC-4DF8-B2F8-CDA5BF77348D}.Debug|x86.Build.0 = Debug|x86 + {E6DD6D23-3FFC-4DF8-B2F8-CDA5BF77348D}.Mono|x86.ActiveCfg = Release|x86 + {E6DD6D23-3FFC-4DF8-B2F8-CDA5BF77348D}.Mono|x86.Build.0 = Release|x86 {E6DD6D23-3FFC-4DF8-B2F8-CDA5BF77348D}.Release|x86.ActiveCfg = Release|x86 {E6DD6D23-3FFC-4DF8-B2F8-CDA5BF77348D}.Release|x86.Build.0 = Release|x86 {F9975B01-F137-4FB4-855A-D62782AD8E4E}.Debug|x86.ActiveCfg = Debug|x86 {F9975B01-F137-4FB4-855A-D62782AD8E4E}.Debug|x86.Build.0 = Debug|x86 + {F9975B01-F137-4FB4-855A-D62782AD8E4E}.Mono|x86.ActiveCfg = Release|x86 + {F9975B01-F137-4FB4-855A-D62782AD8E4E}.Mono|x86.Build.0 = Release|x86 {F9975B01-F137-4FB4-855A-D62782AD8E4E}.Release|x86.ActiveCfg = Release|x86 {F9975B01-F137-4FB4-855A-D62782AD8E4E}.Release|x86.Build.0 = Release|x86 {3EC64359-C4AB-44C2-BCC0-8617380DB67A}.Debug|x86.ActiveCfg = Debug|x86 {3EC64359-C4AB-44C2-BCC0-8617380DB67A}.Debug|x86.Build.0 = Debug|x86 + {3EC64359-C4AB-44C2-BCC0-8617380DB67A}.Mono|x86.ActiveCfg = Release|x86 + {3EC64359-C4AB-44C2-BCC0-8617380DB67A}.Mono|x86.Build.0 = Release|x86 {3EC64359-C4AB-44C2-BCC0-8617380DB67A}.Release|x86.ActiveCfg = Release|x86 {3EC64359-C4AB-44C2-BCC0-8617380DB67A}.Release|x86.Build.0 = Release|x86 {A5152775-5252-45B2-B091-69C70280C73C}.Debug|x86.ActiveCfg = Debug|x86 {A5152775-5252-45B2-B091-69C70280C73C}.Debug|x86.Build.0 = Debug|x86 + {A5152775-5252-45B2-B091-69C70280C73C}.Mono|x86.ActiveCfg = Release|x86 + {A5152775-5252-45B2-B091-69C70280C73C}.Mono|x86.Build.0 = Release|x86 {A5152775-5252-45B2-B091-69C70280C73C}.Release|x86.ActiveCfg = Release|x86 {A5152775-5252-45B2-B091-69C70280C73C}.Release|x86.Build.0 = Release|x86 {E6CEA943-9111-4CCD-97BD-A63F7DDABBAE}.Debug|x86.ActiveCfg = Debug|x86 {E6CEA943-9111-4CCD-97BD-A63F7DDABBAE}.Debug|x86.Build.0 = Debug|x86 + {E6CEA943-9111-4CCD-97BD-A63F7DDABBAE}.Mono|x86.ActiveCfg = Release|x86 + {E6CEA943-9111-4CCD-97BD-A63F7DDABBAE}.Mono|x86.Build.0 = Release|x86 {E6CEA943-9111-4CCD-97BD-A63F7DDABBAE}.Release|x86.ActiveCfg = Release|x86 {E6CEA943-9111-4CCD-97BD-A63F7DDABBAE}.Release|x86.Build.0 = Release|x86 - {6449C3DE-E27F-45A6-AAED-BF7E3028CD0B}.Debug|x86.ActiveCfg = Debug|x86 - {6449C3DE-E27F-45A6-AAED-BF7E3028CD0B}.Debug|x86.Build.0 = Debug|x86 - {6449C3DE-E27F-45A6-AAED-BF7E3028CD0B}.Release|x86.ActiveCfg = Release|x86 - {6449C3DE-E27F-45A6-AAED-BF7E3028CD0B}.Release|x86.Build.0 = Release|x86 {503EF9C0-CE83-40BE-98B2-3481D9FE3B0D}.Debug|x86.ActiveCfg = Debug|x86 {503EF9C0-CE83-40BE-98B2-3481D9FE3B0D}.Debug|x86.Build.0 = Debug|x86 + {503EF9C0-CE83-40BE-98B2-3481D9FE3B0D}.Mono|x86.ActiveCfg = Release|x86 + {503EF9C0-CE83-40BE-98B2-3481D9FE3B0D}.Mono|x86.Build.0 = Release|x86 {503EF9C0-CE83-40BE-98B2-3481D9FE3B0D}.Release|x86.ActiveCfg = Release|x86 {503EF9C0-CE83-40BE-98B2-3481D9FE3B0D}.Release|x86.Build.0 = Release|x86 {3929B83A-B1A6-4620-9139-B5DEEEF3DCE4}.Debug|x86.ActiveCfg = Debug|x86 {3929B83A-B1A6-4620-9139-B5DEEEF3DCE4}.Debug|x86.Build.0 = Debug|x86 + {3929B83A-B1A6-4620-9139-B5DEEEF3DCE4}.Mono|x86.ActiveCfg = Release|x86 + {3929B83A-B1A6-4620-9139-B5DEEEF3DCE4}.Mono|x86.Build.0 = Release|x86 {3929B83A-B1A6-4620-9139-B5DEEEF3DCE4}.Release|x86.ActiveCfg = Release|x86 {3929B83A-B1A6-4620-9139-B5DEEEF3DCE4}.Release|x86.Build.0 = Release|x86 {ECD64A23-8504-4A68-829D-FB1B6C726C85}.Debug|x86.ActiveCfg = Debug|x86 {ECD64A23-8504-4A68-829D-FB1B6C726C85}.Debug|x86.Build.0 = Debug|x86 + {ECD64A23-8504-4A68-829D-FB1B6C726C85}.Mono|x86.ActiveCfg = Release|x86 + {ECD64A23-8504-4A68-829D-FB1B6C726C85}.Mono|x86.Build.0 = Release|x86 {ECD64A23-8504-4A68-829D-FB1B6C726C85}.Release|x86.ActiveCfg = Release|x86 {ECD64A23-8504-4A68-829D-FB1B6C726C85}.Release|x86.Build.0 = Release|x86 {316F5B16-E308-4ABE-B95D-EF64FFAEF028}.Debug|x86.ActiveCfg = Debug|x86 {316F5B16-E308-4ABE-B95D-EF64FFAEF028}.Debug|x86.Build.0 = Debug|x86 + {316F5B16-E308-4ABE-B95D-EF64FFAEF028}.Mono|x86.ActiveCfg = Release|x86 + {316F5B16-E308-4ABE-B95D-EF64FFAEF028}.Mono|x86.Build.0 = Release|x86 {316F5B16-E308-4ABE-B95D-EF64FFAEF028}.Release|x86.ActiveCfg = Release|x86 {316F5B16-E308-4ABE-B95D-EF64FFAEF028}.Release|x86.Build.0 = Release|x86 {2DE60006-663C-40DB-B7CD-A38644D7BC94}.Debug|x86.ActiveCfg = Debug|x86 {2DE60006-663C-40DB-B7CD-A38644D7BC94}.Debug|x86.Build.0 = Debug|x86 + {2DE60006-663C-40DB-B7CD-A38644D7BC94}.Mono|x86.ActiveCfg = Release|x86 + {2DE60006-663C-40DB-B7CD-A38644D7BC94}.Mono|x86.Build.0 = Release|x86 {2DE60006-663C-40DB-B7CD-A38644D7BC94}.Release|x86.ActiveCfg = Release|x86 {2DE60006-663C-40DB-B7CD-A38644D7BC94}.Release|x86.Build.0 = Release|x86 {AEA25552-0508-4D42-AFBA-95DBB0BFBA67}.Debug|x86.ActiveCfg = Debug|x86 {AEA25552-0508-4D42-AFBA-95DBB0BFBA67}.Debug|x86.Build.0 = Debug|x86 + {AEA25552-0508-4D42-AFBA-95DBB0BFBA67}.Mono|x86.ActiveCfg = Release|x86 + {AEA25552-0508-4D42-AFBA-95DBB0BFBA67}.Mono|x86.Build.0 = Release|x86 {AEA25552-0508-4D42-AFBA-95DBB0BFBA67}.Release|x86.ActiveCfg = Release|x86 {AEA25552-0508-4D42-AFBA-95DBB0BFBA67}.Release|x86.Build.0 = Release|x86 {18DDB224-5488-4833-A4F0-AA98F37F9864}.Debug|x86.ActiveCfg = Debug|x86 {18DDB224-5488-4833-A4F0-AA98F37F9864}.Debug|x86.Build.0 = Debug|x86 + {18DDB224-5488-4833-A4F0-AA98F37F9864}.Mono|x86.ActiveCfg = Release|x86 + {18DDB224-5488-4833-A4F0-AA98F37F9864}.Mono|x86.Build.0 = Release|x86 {18DDB224-5488-4833-A4F0-AA98F37F9864}.Release|x86.ActiveCfg = Release|x86 {18DDB224-5488-4833-A4F0-AA98F37F9864}.Release|x86.Build.0 = Release|x86 {4D100C6D-963E-4AE7-AEAF-91040D4F0332}.Debug|x86.ActiveCfg = Debug|x86 {4D100C6D-963E-4AE7-AEAF-91040D4F0332}.Debug|x86.Build.0 = Debug|x86 + {4D100C6D-963E-4AE7-AEAF-91040D4F0332}.Mono|x86.ActiveCfg = Release|x86 + {4D100C6D-963E-4AE7-AEAF-91040D4F0332}.Mono|x86.Build.0 = Release|x86 {4D100C6D-963E-4AE7-AEAF-91040D4F0332}.Release|x86.ActiveCfg = Release|x86 {4D100C6D-963E-4AE7-AEAF-91040D4F0332}.Release|x86.Build.0 = Release|x86 {EF3F6EA1-38F2-4C3C-8079-C06B8B5DDCC0}.Debug|x86.ActiveCfg = Debug|x86 {EF3F6EA1-38F2-4C3C-8079-C06B8B5DDCC0}.Debug|x86.Build.0 = Debug|x86 + {EF3F6EA1-38F2-4C3C-8079-C06B8B5DDCC0}.Mono|x86.ActiveCfg = Release|x86 + {EF3F6EA1-38F2-4C3C-8079-C06B8B5DDCC0}.Mono|x86.Build.0 = Release|x86 {EF3F6EA1-38F2-4C3C-8079-C06B8B5DDCC0}.Release|x86.ActiveCfg = Release|x86 {EF3F6EA1-38F2-4C3C-8079-C06B8B5DDCC0}.Release|x86.Build.0 = Release|x86 {03CCCD6C-CA56-4CAE-A0A5-1C9660D9424B}.Debug|x86.ActiveCfg = Debug|x86 {03CCCD6C-CA56-4CAE-A0A5-1C9660D9424B}.Debug|x86.Build.0 = Debug|x86 + {03CCCD6C-CA56-4CAE-A0A5-1C9660D9424B}.Mono|x86.ActiveCfg = Release|x86 + {03CCCD6C-CA56-4CAE-A0A5-1C9660D9424B}.Mono|x86.Build.0 = Release|x86 {03CCCD6C-CA56-4CAE-A0A5-1C9660D9424B}.Release|x86.ActiveCfg = Release|x86 {03CCCD6C-CA56-4CAE-A0A5-1C9660D9424B}.Release|x86.Build.0 = Release|x86 {C13A769D-B0EF-42F8-83CA-4431252DD316}.Debug|x86.ActiveCfg = Debug|x86 {C13A769D-B0EF-42F8-83CA-4431252DD316}.Debug|x86.Build.0 = Debug|x86 + {C13A769D-B0EF-42F8-83CA-4431252DD316}.Mono|x86.ActiveCfg = Release|x86 + {C13A769D-B0EF-42F8-83CA-4431252DD316}.Mono|x86.Build.0 = Release|x86 {C13A769D-B0EF-42F8-83CA-4431252DD316}.Release|x86.ActiveCfg = Release|x86 {C13A769D-B0EF-42F8-83CA-4431252DD316}.Release|x86.Build.0 = Release|x86 {DB8C60E0-D225-4DBB-917A-12EA86506A13}.Debug|x86.ActiveCfg = Debug|x86 {DB8C60E0-D225-4DBB-917A-12EA86506A13}.Debug|x86.Build.0 = Debug|x86 + {DB8C60E0-D225-4DBB-917A-12EA86506A13}.Mono|x86.ActiveCfg = Release|x86 + {DB8C60E0-D225-4DBB-917A-12EA86506A13}.Mono|x86.Build.0 = Release|x86 {DB8C60E0-D225-4DBB-917A-12EA86506A13}.Release|x86.ActiveCfg = Release|x86 {DB8C60E0-D225-4DBB-917A-12EA86506A13}.Release|x86.Build.0 = Release|x86 {6EE43C30-5232-4B18-802B-7D536EA4DCCE}.Debug|x86.ActiveCfg = Debug|x86 {6EE43C30-5232-4B18-802B-7D536EA4DCCE}.Debug|x86.Build.0 = Debug|x86 + {6EE43C30-5232-4B18-802B-7D536EA4DCCE}.Mono|x86.ActiveCfg = Release|x86 + {6EE43C30-5232-4B18-802B-7D536EA4DCCE}.Mono|x86.Build.0 = Release|x86 {6EE43C30-5232-4B18-802B-7D536EA4DCCE}.Release|x86.ActiveCfg = Release|x86 {6EE43C30-5232-4B18-802B-7D536EA4DCCE}.Release|x86.Build.0 = Release|x86 {8433F722-C197-4BCD-9E5D-08A6B2FAF23A}.Debug|x86.ActiveCfg = Debug|x86 {8433F722-C197-4BCD-9E5D-08A6B2FAF23A}.Debug|x86.Build.0 = Debug|x86 + {8433F722-C197-4BCD-9E5D-08A6B2FAF23A}.Mono|x86.ActiveCfg = Release|x86 + {8433F722-C197-4BCD-9E5D-08A6B2FAF23A}.Mono|x86.Build.0 = Release|x86 {8433F722-C197-4BCD-9E5D-08A6B2FAF23A}.Release|x86.ActiveCfg = Release|x86 {8433F722-C197-4BCD-9E5D-08A6B2FAF23A}.Release|x86.Build.0 = Release|x86 {36BA745B-850A-4C3C-88F5-125B0171B187}.Debug|x86.ActiveCfg = Debug|x86 {36BA745B-850A-4C3C-88F5-125B0171B187}.Debug|x86.Build.0 = Debug|x86 + {36BA745B-850A-4C3C-88F5-125B0171B187}.Mono|x86.ActiveCfg = Release|x86 + {36BA745B-850A-4C3C-88F5-125B0171B187}.Mono|x86.Build.0 = Release|x86 {36BA745B-850A-4C3C-88F5-125B0171B187}.Release|x86.ActiveCfg = Release|x86 {36BA745B-850A-4C3C-88F5-125B0171B187}.Release|x86.Build.0 = Release|x86 {A37A4E8F-3F41-497A-B5C0-E92ABFF9067F}.Debug|x86.ActiveCfg = Debug|x86 {A37A4E8F-3F41-497A-B5C0-E92ABFF9067F}.Debug|x86.Build.0 = Debug|x86 + {A37A4E8F-3F41-497A-B5C0-E92ABFF9067F}.Mono|x86.ActiveCfg = Release|x86 + {A37A4E8F-3F41-497A-B5C0-E92ABFF9067F}.Mono|x86.Build.0 = Release|x86 {A37A4E8F-3F41-497A-B5C0-E92ABFF9067F}.Release|x86.ActiveCfg = Release|x86 {A37A4E8F-3F41-497A-B5C0-E92ABFF9067F}.Release|x86.Build.0 = Release|x86 {936F3B12-2B1A-468E-9830-51EC9EFB127E}.Debug|x86.ActiveCfg = Debug|x86 {936F3B12-2B1A-468E-9830-51EC9EFB127E}.Debug|x86.Build.0 = Debug|x86 + {936F3B12-2B1A-468E-9830-51EC9EFB127E}.Mono|x86.ActiveCfg = Release|x86 + {936F3B12-2B1A-468E-9830-51EC9EFB127E}.Mono|x86.Build.0 = Release|x86 {936F3B12-2B1A-468E-9830-51EC9EFB127E}.Release|x86.ActiveCfg = Release|x86 {936F3B12-2B1A-468E-9830-51EC9EFB127E}.Release|x86.Build.0 = Release|x86 {F7750412-9EA2-4FCF-A268-AC927188A009}.Debug|x86.ActiveCfg = Debug|x86 {F7750412-9EA2-4FCF-A268-AC927188A009}.Debug|x86.Build.0 = Debug|x86 + {F7750412-9EA2-4FCF-A268-AC927188A009}.Mono|x86.ActiveCfg = Release|x86 + {F7750412-9EA2-4FCF-A268-AC927188A009}.Mono|x86.Build.0 = Release|x86 {F7750412-9EA2-4FCF-A268-AC927188A009}.Release|x86.ActiveCfg = Release|x86 {F7750412-9EA2-4FCF-A268-AC927188A009}.Release|x86.Build.0 = Release|x86 {09D9131B-3277-476F-8500-311E69B58AFB}.Debug|x86.ActiveCfg = Debug|x86 {09D9131B-3277-476F-8500-311E69B58AFB}.Debug|x86.Build.0 = Debug|x86 + {09D9131B-3277-476F-8500-311E69B58AFB}.Mono|x86.ActiveCfg = Release|x86 + {09D9131B-3277-476F-8500-311E69B58AFB}.Mono|x86.Build.0 = Release|x86 {09D9131B-3277-476F-8500-311E69B58AFB}.Release|x86.ActiveCfg = Release|x86 {09D9131B-3277-476F-8500-311E69B58AFB}.Release|x86.Build.0 = Release|x86 {95BDACEA-E8DB-4A87-9472-A37F0879179F}.Debug|x86.ActiveCfg = Debug|x86 {95BDACEA-E8DB-4A87-9472-A37F0879179F}.Debug|x86.Build.0 = Debug|x86 + {95BDACEA-E8DB-4A87-9472-A37F0879179F}.Mono|x86.ActiveCfg = Release|x86 + {95BDACEA-E8DB-4A87-9472-A37F0879179F}.Mono|x86.Build.0 = Release|x86 {95BDACEA-E8DB-4A87-9472-A37F0879179F}.Release|x86.ActiveCfg = Release|x86 {95BDACEA-E8DB-4A87-9472-A37F0879179F}.Release|x86.Build.0 = Release|x86 {99C1ED90-C4CD-4730-B05C-B99EED60EDD1}.Debug|x86.ActiveCfg = Debug|x86 {99C1ED90-C4CD-4730-B05C-B99EED60EDD1}.Debug|x86.Build.0 = Debug|x86 + {99C1ED90-C4CD-4730-B05C-B99EED60EDD1}.Mono|x86.ActiveCfg = Release|x86 + {99C1ED90-C4CD-4730-B05C-B99EED60EDD1}.Mono|x86.Build.0 = Release|x86 {99C1ED90-C4CD-4730-B05C-B99EED60EDD1}.Release|x86.ActiveCfg = Release|x86 {99C1ED90-C4CD-4730-B05C-B99EED60EDD1}.Release|x86.Build.0 = Release|x86 {67D5F5DD-95D8-4DF3-B4F4-B43A2FCFE02F}.Debug|x86.ActiveCfg = Debug|x86 {67D5F5DD-95D8-4DF3-B4F4-B43A2FCFE02F}.Debug|x86.Build.0 = Debug|x86 + {67D5F5DD-95D8-4DF3-B4F4-B43A2FCFE02F}.Mono|x86.ActiveCfg = Release|x86 + {67D5F5DD-95D8-4DF3-B4F4-B43A2FCFE02F}.Mono|x86.Build.0 = Release|x86 {67D5F5DD-95D8-4DF3-B4F4-B43A2FCFE02F}.Release|x86.ActiveCfg = Release|x86 {67D5F5DD-95D8-4DF3-B4F4-B43A2FCFE02F}.Release|x86.Build.0 = Release|x86 {79DAA213-B774-444D-85B1-7AA727C036E7}.Debug|x86.ActiveCfg = Debug|x86 {79DAA213-B774-444D-85B1-7AA727C036E7}.Debug|x86.Build.0 = Debug|x86 + {79DAA213-B774-444D-85B1-7AA727C036E7}.Mono|x86.ActiveCfg = Release|x86 + {79DAA213-B774-444D-85B1-7AA727C036E7}.Mono|x86.Build.0 = Release|x86 {79DAA213-B774-444D-85B1-7AA727C036E7}.Release|x86.ActiveCfg = Release|x86 {79DAA213-B774-444D-85B1-7AA727C036E7}.Release|x86.Build.0 = Release|x86 {6EC8C18C-65ED-4C93-A8E2-7FB5324EF3C5}.Debug|x86.ActiveCfg = Debug|x86 {6EC8C18C-65ED-4C93-A8E2-7FB5324EF3C5}.Debug|x86.Build.0 = Debug|x86 + {6EC8C18C-65ED-4C93-A8E2-7FB5324EF3C5}.Mono|x86.ActiveCfg = Release|x86 + {6EC8C18C-65ED-4C93-A8E2-7FB5324EF3C5}.Mono|x86.Build.0 = Release|x86 {6EC8C18C-65ED-4C93-A8E2-7FB5324EF3C5}.Release|x86.ActiveCfg = Release|x86 {6EC8C18C-65ED-4C93-A8E2-7FB5324EF3C5}.Release|x86.Build.0 = Release|x86 {A3C56C4A-57FC-48A4-A45A-DA12304D06A9}.Debug|x86.ActiveCfg = Debug|x86 {A3C56C4A-57FC-48A4-A45A-DA12304D06A9}.Debug|x86.Build.0 = Debug|x86 + {A3C56C4A-57FC-48A4-A45A-DA12304D06A9}.Mono|x86.ActiveCfg = Release|x86 + {A3C56C4A-57FC-48A4-A45A-DA12304D06A9}.Mono|x86.Build.0 = Release|x86 {A3C56C4A-57FC-48A4-A45A-DA12304D06A9}.Release|x86.ActiveCfg = Release|x86 {A3C56C4A-57FC-48A4-A45A-DA12304D06A9}.Release|x86.Build.0 = Release|x86 {38C27270-D29A-48B0-BF49-B90C049C42E1}.Debug|x86.ActiveCfg = Debug|x86 {38C27270-D29A-48B0-BF49-B90C049C42E1}.Debug|x86.Build.0 = Debug|x86 + {38C27270-D29A-48B0-BF49-B90C049C42E1}.Mono|x86.ActiveCfg = Release|x86 + {38C27270-D29A-48B0-BF49-B90C049C42E1}.Mono|x86.Build.0 = Release|x86 {38C27270-D29A-48B0-BF49-B90C049C42E1}.Release|x86.ActiveCfg = Release|x86 {38C27270-D29A-48B0-BF49-B90C049C42E1}.Release|x86.Build.0 = Release|x86 {F6CFAC9E-A9AF-4DDF-9405-B4B3578E5154}.Debug|x86.ActiveCfg = Debug|x86 {F6CFAC9E-A9AF-4DDF-9405-B4B3578E5154}.Debug|x86.Build.0 = Debug|x86 + {F6CFAC9E-A9AF-4DDF-9405-B4B3578E5154}.Mono|x86.ActiveCfg = Release|x86 + {F6CFAC9E-A9AF-4DDF-9405-B4B3578E5154}.Mono|x86.Build.0 = Release|x86 {F6CFAC9E-A9AF-4DDF-9405-B4B3578E5154}.Release|x86.ActiveCfg = Release|x86 {F6CFAC9E-A9AF-4DDF-9405-B4B3578E5154}.Release|x86.Build.0 = Release|x86 {3AFDA17A-E489-49A7-827F-18DE4CDC7812}.Debug|x86.ActiveCfg = Debug|x86 {3AFDA17A-E489-49A7-827F-18DE4CDC7812}.Debug|x86.Build.0 = Debug|x86 + {3AFDA17A-E489-49A7-827F-18DE4CDC7812}.Mono|x86.ActiveCfg = Release|x86 + {3AFDA17A-E489-49A7-827F-18DE4CDC7812}.Mono|x86.Build.0 = Release|x86 {3AFDA17A-E489-49A7-827F-18DE4CDC7812}.Release|x86.ActiveCfg = Release|x86 {3AFDA17A-E489-49A7-827F-18DE4CDC7812}.Release|x86.Build.0 = Release|x86 {27305F98-F71E-4FF4-8759-F13D58555200}.Debug|x86.ActiveCfg = Debug|x86 {27305F98-F71E-4FF4-8759-F13D58555200}.Debug|x86.Build.0 = Debug|x86 + {27305F98-F71E-4FF4-8759-F13D58555200}.Mono|x86.ActiveCfg = Release|x86 + {27305F98-F71E-4FF4-8759-F13D58555200}.Mono|x86.Build.0 = Release|x86 {27305F98-F71E-4FF4-8759-F13D58555200}.Release|x86.ActiveCfg = Release|x86 {27305F98-F71E-4FF4-8759-F13D58555200}.Release|x86.Build.0 = Release|x86 {CE77124B-B24F-476E-8C83-835EC8675DD7}.Debug|x86.ActiveCfg = Debug|x86 {CE77124B-B24F-476E-8C83-835EC8675DD7}.Debug|x86.Build.0 = Debug|x86 + {CE77124B-B24F-476E-8C83-835EC8675DD7}.Mono|x86.ActiveCfg = Release|x86 + {CE77124B-B24F-476E-8C83-835EC8675DD7}.Mono|x86.Build.0 = Release|x86 {CE77124B-B24F-476E-8C83-835EC8675DD7}.Release|x86.ActiveCfg = Release|x86 {CE77124B-B24F-476E-8C83-835EC8675DD7}.Release|x86.Build.0 = Release|x86 {3B1150A4-A32C-4B2F-8BC1-14FDB5C4FDEE}.Debug|x86.ActiveCfg = Debug|x86 {3B1150A4-A32C-4B2F-8BC1-14FDB5C4FDEE}.Debug|x86.Build.0 = Debug|x86 + {3B1150A4-A32C-4B2F-8BC1-14FDB5C4FDEE}.Mono|x86.ActiveCfg = Release|x86 + {3B1150A4-A32C-4B2F-8BC1-14FDB5C4FDEE}.Mono|x86.Build.0 = Release|x86 {3B1150A4-A32C-4B2F-8BC1-14FDB5C4FDEE}.Release|x86.ActiveCfg = Release|x86 {3B1150A4-A32C-4B2F-8BC1-14FDB5C4FDEE}.Release|x86.Build.0 = Release|x86 {7F23856B-B95C-42B3-B6AF-663FA35324D6}.Debug|x86.ActiveCfg = Debug|x86 {7F23856B-B95C-42B3-B6AF-663FA35324D6}.Debug|x86.Build.0 = Debug|x86 + {7F23856B-B95C-42B3-B6AF-663FA35324D6}.Mono|x86.ActiveCfg = Release|x86 + {7F23856B-B95C-42B3-B6AF-663FA35324D6}.Mono|x86.Build.0 = Release|x86 {7F23856B-B95C-42B3-B6AF-663FA35324D6}.Release|x86.ActiveCfg = Release|x86 {7F23856B-B95C-42B3-B6AF-663FA35324D6}.Release|x86.Build.0 = Release|x86 {AC9EF5B1-166E-41E8-A62E-9A614703AB3B}.Debug|x86.ActiveCfg = Debug|x86 {AC9EF5B1-166E-41E8-A62E-9A614703AB3B}.Debug|x86.Build.0 = Debug|x86 + {AC9EF5B1-166E-41E8-A62E-9A614703AB3B}.Mono|x86.ActiveCfg = Release|x86 + {AC9EF5B1-166E-41E8-A62E-9A614703AB3B}.Mono|x86.Build.0 = Release|x86 {AC9EF5B1-166E-41E8-A62E-9A614703AB3B}.Release|x86.ActiveCfg = Release|x86 {AC9EF5B1-166E-41E8-A62E-9A614703AB3B}.Release|x86.Build.0 = Release|x86 {9C863BCC-46C3-4B54-9B92-B4CC32812C76}.Debug|x86.ActiveCfg = Debug|x86 {9C863BCC-46C3-4B54-9B92-B4CC32812C76}.Debug|x86.Build.0 = Debug|x86 + {9C863BCC-46C3-4B54-9B92-B4CC32812C76}.Mono|x86.ActiveCfg = Release|x86 + {9C863BCC-46C3-4B54-9B92-B4CC32812C76}.Mono|x86.Build.0 = Release|x86 {9C863BCC-46C3-4B54-9B92-B4CC32812C76}.Release|x86.ActiveCfg = Release|x86 {9C863BCC-46C3-4B54-9B92-B4CC32812C76}.Release|x86.Build.0 = Release|x86 {1A7BCB9F-5DD2-4C16-9969-88C31720865F}.Debug|x86.ActiveCfg = Debug|x86 {1A7BCB9F-5DD2-4C16-9969-88C31720865F}.Debug|x86.Build.0 = Debug|x86 + {1A7BCB9F-5DD2-4C16-9969-88C31720865F}.Mono|x86.ActiveCfg = Release|x86 + {1A7BCB9F-5DD2-4C16-9969-88C31720865F}.Mono|x86.Build.0 = Release|x86 {1A7BCB9F-5DD2-4C16-9969-88C31720865F}.Release|x86.ActiveCfg = Release|x86 {1A7BCB9F-5DD2-4C16-9969-88C31720865F}.Release|x86.Build.0 = Release|x86 {41B33248-828B-4D62-83A0-2FFFE89582B0}.Debug|x86.ActiveCfg = Debug|x86 {41B33248-828B-4D62-83A0-2FFFE89582B0}.Debug|x86.Build.0 = Debug|x86 + {41B33248-828B-4D62-83A0-2FFFE89582B0}.Mono|x86.ActiveCfg = Release|x86 + {41B33248-828B-4D62-83A0-2FFFE89582B0}.Mono|x86.Build.0 = Release|x86 {41B33248-828B-4D62-83A0-2FFFE89582B0}.Release|x86.ActiveCfg = Release|x86 {41B33248-828B-4D62-83A0-2FFFE89582B0}.Release|x86.Build.0 = Release|x86 {07337787-AD77-4061-A0A0-C8D83AF3B977}.Debug|x86.ActiveCfg = Debug|x86 {07337787-AD77-4061-A0A0-C8D83AF3B977}.Debug|x86.Build.0 = Debug|x86 + {07337787-AD77-4061-A0A0-C8D83AF3B977}.Mono|x86.ActiveCfg = Release|x86 {07337787-AD77-4061-A0A0-C8D83AF3B977}.Release|x86.ActiveCfg = Release|x86 {07337787-AD77-4061-A0A0-C8D83AF3B977}.Release|x86.Build.0 = Release|x86 {1E055676-77A0-4C5B-B449-FF58CA5066E0}.Debug|x86.ActiveCfg = Debug|x86 {1E055676-77A0-4C5B-B449-FF58CA5066E0}.Debug|x86.Build.0 = Debug|x86 + {1E055676-77A0-4C5B-B449-FF58CA5066E0}.Mono|x86.ActiveCfg = Release|x86 + {1E055676-77A0-4C5B-B449-FF58CA5066E0}.Mono|x86.Build.0 = Release|x86 {1E055676-77A0-4C5B-B449-FF58CA5066E0}.Release|x86.ActiveCfg = Release|x86 {1E055676-77A0-4C5B-B449-FF58CA5066E0}.Release|x86.Build.0 = Release|x86 {19906CFC-8E1C-4F11-98E6-92A73C4F097E}.Debug|x86.ActiveCfg = Debug|x86 {19906CFC-8E1C-4F11-98E6-92A73C4F097E}.Debug|x86.Build.0 = Debug|x86 + {19906CFC-8E1C-4F11-98E6-92A73C4F097E}.Mono|x86.ActiveCfg = Release|x86 + {19906CFC-8E1C-4F11-98E6-92A73C4F097E}.Mono|x86.Build.0 = Release|x86 {19906CFC-8E1C-4F11-98E6-92A73C4F097E}.Release|x86.ActiveCfg = Release|x86 {19906CFC-8E1C-4F11-98E6-92A73C4F097E}.Release|x86.Build.0 = Release|x86 {E0E753EE-4A27-491C-A914-6942A772AAF2}.Debug|x86.ActiveCfg = Debug|x86 {E0E753EE-4A27-491C-A914-6942A772AAF2}.Debug|x86.Build.0 = Debug|x86 + {E0E753EE-4A27-491C-A914-6942A772AAF2}.Mono|x86.ActiveCfg = Release|x86 + {E0E753EE-4A27-491C-A914-6942A772AAF2}.Mono|x86.Build.0 = Release|x86 {E0E753EE-4A27-491C-A914-6942A772AAF2}.Release|x86.ActiveCfg = Release|x86 {E0E753EE-4A27-491C-A914-6942A772AAF2}.Release|x86.Build.0 = Release|x86 + {742487A3-DD2E-4F47-9ABB-77E88653A1D3}.Debug|x86.ActiveCfg = Debug|x86 + {742487A3-DD2E-4F47-9ABB-77E88653A1D3}.Debug|x86.Build.0 = Debug|x86 + {742487A3-DD2E-4F47-9ABB-77E88653A1D3}.Mono|x86.ActiveCfg = Release|x86 + {742487A3-DD2E-4F47-9ABB-77E88653A1D3}.Mono|x86.Build.0 = Release|x86 + {742487A3-DD2E-4F47-9ABB-77E88653A1D3}.Release|x86.ActiveCfg = Release|x86 + {742487A3-DD2E-4F47-9ABB-77E88653A1D3}.Release|x86.Build.0 = Release|x86 + {6B66B73D-481C-479B-AC13-F5E332D12293}.Debug|x86.ActiveCfg = Debug|x86 + {6B66B73D-481C-479B-AC13-F5E332D12293}.Debug|x86.Build.0 = Debug|x86 + {6B66B73D-481C-479B-AC13-F5E332D12293}.Mono|x86.ActiveCfg = Release|x86 + {6B66B73D-481C-479B-AC13-F5E332D12293}.Mono|x86.Build.0 = Release|x86 + {6B66B73D-481C-479B-AC13-F5E332D12293}.Release|x86.ActiveCfg = Release|x86 + {6B66B73D-481C-479B-AC13-F5E332D12293}.Release|x86.Build.0 = Release|x86 + {744FC79F-5B6D-44AD-8C34-1ABB6EABAE6B}.Debug|x86.ActiveCfg = Debug|x86 + {744FC79F-5B6D-44AD-8C34-1ABB6EABAE6B}.Debug|x86.Build.0 = Debug|x86 + {744FC79F-5B6D-44AD-8C34-1ABB6EABAE6B}.Mono|x86.ActiveCfg = Release|x86 + {744FC79F-5B6D-44AD-8C34-1ABB6EABAE6B}.Mono|x86.Build.0 = Release|x86 + {744FC79F-5B6D-44AD-8C34-1ABB6EABAE6B}.Release|x86.ActiveCfg = Release|x86 + {EE5B96F4-EEB3-4606-98C9-6F1242B41FD2}.Debug|x86.ActiveCfg = Debug|x86 + {EE5B96F4-EEB3-4606-98C9-6F1242B41FD2}.Debug|x86.Build.0 = Debug|x86 + {EE5B96F4-EEB3-4606-98C9-6F1242B41FD2}.Mono|x86.ActiveCfg = Release|x86 + {EE5B96F4-EEB3-4606-98C9-6F1242B41FD2}.Mono|x86.Build.0 = Release|x86 + {EE5B96F4-EEB3-4606-98C9-6F1242B41FD2}.Release|x86.ActiveCfg = Release|x86 + {EE5B96F4-EEB3-4606-98C9-6F1242B41FD2}.Release|x86.Build.0 = Release|x86 + {E34CC841-CE29-4B39-9BE5-D98502330F55}.Debug|x86.ActiveCfg = Debug|x86 + {E34CC841-CE29-4B39-9BE5-D98502330F55}.Debug|x86.Build.0 = Debug|x86 + {E34CC841-CE29-4B39-9BE5-D98502330F55}.Mono|x86.ActiveCfg = Release|x86 + {E34CC841-CE29-4B39-9BE5-D98502330F55}.Mono|x86.Build.0 = Release|x86 + {E34CC841-CE29-4B39-9BE5-D98502330F55}.Release|x86.ActiveCfg = Release|x86 + {E34CC841-CE29-4B39-9BE5-D98502330F55}.Release|x86.Build.0 = Release|x86 + {B4892057-CAE6-41F4-A75D-88E61331A2D0}.Debug|x86.ActiveCfg = Debug|x86 + {B4892057-CAE6-41F4-A75D-88E61331A2D0}.Debug|x86.Build.0 = Debug|x86 + {B4892057-CAE6-41F4-A75D-88E61331A2D0}.Mono|x86.ActiveCfg = Release|x86 + {B4892057-CAE6-41F4-A75D-88E61331A2D0}.Mono|x86.Build.0 = Release|x86 + {B4892057-CAE6-41F4-A75D-88E61331A2D0}.Release|x86.ActiveCfg = Release|x86 + {B4892057-CAE6-41F4-A75D-88E61331A2D0}.Release|x86.Build.0 = Release|x86 + {DEC346FD-C496-4B3E-A0E9-60AE011E3C49}.Debug|x86.ActiveCfg = Debug|x86 + {DEC346FD-C496-4B3E-A0E9-60AE011E3C49}.Debug|x86.Build.0 = Debug|x86 + {DEC346FD-C496-4B3E-A0E9-60AE011E3C49}.Mono|x86.ActiveCfg = Release|x86 + {DEC346FD-C496-4B3E-A0E9-60AE011E3C49}.Mono|x86.Build.0 = Release|x86 + {DEC346FD-C496-4B3E-A0E9-60AE011E3C49}.Release|x86.ActiveCfg = Release|x86 + {DEC346FD-C496-4B3E-A0E9-60AE011E3C49}.Release|x86.Build.0 = Release|x86 + {2C079A0D-8F90-4B4E-85AA-CAD45F7E0CAC}.Debug|x86.ActiveCfg = Debug|x86 + {2C079A0D-8F90-4B4E-85AA-CAD45F7E0CAC}.Debug|x86.Build.0 = Debug|x86 + {2C079A0D-8F90-4B4E-85AA-CAD45F7E0CAC}.Mono|x86.ActiveCfg = Release|x86 + {2C079A0D-8F90-4B4E-85AA-CAD45F7E0CAC}.Mono|x86.Build.0 = Release|x86 + {2C079A0D-8F90-4B4E-85AA-CAD45F7E0CAC}.Release|x86.ActiveCfg = Release|x86 + {2C079A0D-8F90-4B4E-85AA-CAD45F7E0CAC}.Release|x86.Build.0 = Release|x86 + {BCC446EF-0F10-4FBB-AB37-9A9E0B1CDBAB}.Debug|x86.ActiveCfg = Debug|x86 + {BCC446EF-0F10-4FBB-AB37-9A9E0B1CDBAB}.Debug|x86.Build.0 = Debug|x86 + {BCC446EF-0F10-4FBB-AB37-9A9E0B1CDBAB}.Mono|x86.ActiveCfg = Release|x86 + {BCC446EF-0F10-4FBB-AB37-9A9E0B1CDBAB}.Mono|x86.Build.0 = Release|x86 + {BCC446EF-0F10-4FBB-AB37-9A9E0B1CDBAB}.Release|x86.ActiveCfg = Release|x86 + {BCC446EF-0F10-4FBB-AB37-9A9E0B1CDBAB}.Release|x86.Build.0 = Release|x86 + {3B59E324-53FC-4837-AF37-61FC4B51E2D1}.Debug|x86.ActiveCfg = Debug|x86 + {3B59E324-53FC-4837-AF37-61FC4B51E2D1}.Debug|x86.Build.0 = Debug|x86 + {3B59E324-53FC-4837-AF37-61FC4B51E2D1}.Mono|x86.ActiveCfg = Release|x86 + {3B59E324-53FC-4837-AF37-61FC4B51E2D1}.Mono|x86.Build.0 = Release|x86 + {3B59E324-53FC-4837-AF37-61FC4B51E2D1}.Release|x86.ActiveCfg = Release|x86 + {3B59E324-53FC-4837-AF37-61FC4B51E2D1}.Release|x86.Build.0 = Release|x86 + {C646B987-EA7E-4D82-A930-448DE583FEB3}.Debug|x86.ActiveCfg = Debug|x86 + {C646B987-EA7E-4D82-A930-448DE583FEB3}.Debug|x86.Build.0 = Debug|x86 + {C646B987-EA7E-4D82-A930-448DE583FEB3}.Mono|x86.ActiveCfg = Release|x86 + {C646B987-EA7E-4D82-A930-448DE583FEB3}.Mono|x86.Build.0 = Release|x86 + {C646B987-EA7E-4D82-A930-448DE583FEB3}.Release|x86.ActiveCfg = Release|x86 + {C646B987-EA7E-4D82-A930-448DE583FEB3}.Release|x86.Build.0 = Release|x86 + {59E2469C-197F-4A4C-9D52-AA58EA49927E}.Debug|x86.ActiveCfg = Debug|x86 + {59E2469C-197F-4A4C-9D52-AA58EA49927E}.Debug|x86.Build.0 = Debug|x86 + {59E2469C-197F-4A4C-9D52-AA58EA49927E}.Mono|x86.ActiveCfg = Release|x86 + {59E2469C-197F-4A4C-9D52-AA58EA49927E}.Mono|x86.Build.0 = Release|x86 + {59E2469C-197F-4A4C-9D52-AA58EA49927E}.Release|x86.ActiveCfg = Release|x86 + {59E2469C-197F-4A4C-9D52-AA58EA49927E}.Release|x86.Build.0 = Release|x86 + {6FA77B7F-E933-4B25-AC4C-99E343B35AC8}.Debug|x86.ActiveCfg = Debug|x86 + {6FA77B7F-E933-4B25-AC4C-99E343B35AC8}.Debug|x86.Build.0 = Debug|x86 + {6FA77B7F-E933-4B25-AC4C-99E343B35AC8}.Mono|x86.ActiveCfg = Release|x86 + {6FA77B7F-E933-4B25-AC4C-99E343B35AC8}.Mono|x86.Build.0 = Release|x86 + {6FA77B7F-E933-4B25-AC4C-99E343B35AC8}.Release|x86.ActiveCfg = Release|x86 + {6FA77B7F-E933-4B25-AC4C-99E343B35AC8}.Release|x86.Build.0 = Release|x86 + {9800A224-0BF0-4D5D-A03C-AA7A4842D3B8}.Debug|x86.ActiveCfg = Debug|x86 + {9800A224-0BF0-4D5D-A03C-AA7A4842D3B8}.Debug|x86.Build.0 = Debug|x86 + {9800A224-0BF0-4D5D-A03C-AA7A4842D3B8}.Mono|x86.ActiveCfg = Release|x86 + {9800A224-0BF0-4D5D-A03C-AA7A4842D3B8}.Mono|x86.Build.0 = Release|x86 + {9800A224-0BF0-4D5D-A03C-AA7A4842D3B8}.Release|x86.ActiveCfg = Release|x86 + {9800A224-0BF0-4D5D-A03C-AA7A4842D3B8}.Release|x86.Build.0 = Release|x86 + {B4CB129D-51F9-4C86-B520-7AC50537A70B}.Debug|x86.ActiveCfg = Debug|x86 + {B4CB129D-51F9-4C86-B520-7AC50537A70B}.Debug|x86.Build.0 = Debug|x86 + {B4CB129D-51F9-4C86-B520-7AC50537A70B}.Mono|x86.ActiveCfg = Release|x86 + {B4CB129D-51F9-4C86-B520-7AC50537A70B}.Mono|x86.Build.0 = Release|x86 + {B4CB129D-51F9-4C86-B520-7AC50537A70B}.Release|x86.ActiveCfg = Release|x86 + {B4CB129D-51F9-4C86-B520-7AC50537A70B}.Release|x86.Build.0 = Release|x86 + {B31C0650-991B-4B28-9864-AE80C1785A3F}.Debug|x86.ActiveCfg = Debug|x86 + {B31C0650-991B-4B28-9864-AE80C1785A3F}.Debug|x86.Build.0 = Debug|x86 + {B31C0650-991B-4B28-9864-AE80C1785A3F}.Mono|x86.ActiveCfg = Release|x86 + {B31C0650-991B-4B28-9864-AE80C1785A3F}.Mono|x86.Build.0 = Release|x86 + {B31C0650-991B-4B28-9864-AE80C1785A3F}.Release|x86.ActiveCfg = Release|x86 + {B31C0650-991B-4B28-9864-AE80C1785A3F}.Release|x86.Build.0 = Release|x86 + {779A59F0-BF3B-4AE5-B323-97D37CD67233}.Debug|x86.ActiveCfg = Debug|x86 + {779A59F0-BF3B-4AE5-B323-97D37CD67233}.Debug|x86.Build.0 = Debug|x86 + {779A59F0-BF3B-4AE5-B323-97D37CD67233}.Mono|x86.ActiveCfg = Release|x86 + {779A59F0-BF3B-4AE5-B323-97D37CD67233}.Mono|x86.Build.0 = Release|x86 + {779A59F0-BF3B-4AE5-B323-97D37CD67233}.Release|x86.ActiveCfg = Release|x86 + {779A59F0-BF3B-4AE5-B323-97D37CD67233}.Release|x86.Build.0 = Release|x86 + {AB55ABF6-4AD9-4F8A-9E9D-8B61F89766A6}.Debug|x86.ActiveCfg = Debug|x86 + {AB55ABF6-4AD9-4F8A-9E9D-8B61F89766A6}.Debug|x86.Build.0 = Debug|x86 + {AB55ABF6-4AD9-4F8A-9E9D-8B61F89766A6}.Mono|x86.ActiveCfg = Release|x86 + {AB55ABF6-4AD9-4F8A-9E9D-8B61F89766A6}.Mono|x86.Build.0 = Release|x86 + {AB55ABF6-4AD9-4F8A-9E9D-8B61F89766A6}.Release|x86.ActiveCfg = Release|x86 + {AB55ABF6-4AD9-4F8A-9E9D-8B61F89766A6}.Release|x86.Build.0 = Release|x86 + {40C644F9-5AF9-44BB-9649-02149933E092}.Debug|x86.ActiveCfg = Debug|x86 + {40C644F9-5AF9-44BB-9649-02149933E092}.Debug|x86.Build.0 = Debug|x86 + {40C644F9-5AF9-44BB-9649-02149933E092}.Mono|x86.ActiveCfg = Release|x86 + {40C644F9-5AF9-44BB-9649-02149933E092}.Mono|x86.Build.0 = Release|x86 + {40C644F9-5AF9-44BB-9649-02149933E092}.Release|x86.ActiveCfg = Release|x86 + {40C644F9-5AF9-44BB-9649-02149933E092}.Release|x86.Build.0 = Release|x86 + {2E6B9575-0C86-4034-8A8E-13C880B69A6F}.Debug|x86.ActiveCfg = Debug|x86 + {2E6B9575-0C86-4034-8A8E-13C880B69A6F}.Debug|x86.Build.0 = Debug|x86 + {2E6B9575-0C86-4034-8A8E-13C880B69A6F}.Mono|x86.ActiveCfg = Release|x86 + {2E6B9575-0C86-4034-8A8E-13C880B69A6F}.Mono|x86.Build.0 = Release|x86 + {2E6B9575-0C86-4034-8A8E-13C880B69A6F}.Release|x86.ActiveCfg = Release|x86 + {2E6B9575-0C86-4034-8A8E-13C880B69A6F}.Release|x86.Build.0 = Release|x86 + {651EBEC1-045E-4A74-A9F6-7E8DD223DD7A}.Debug|x86.ActiveCfg = Debug|x86 + {651EBEC1-045E-4A74-A9F6-7E8DD223DD7A}.Debug|x86.Build.0 = Debug|x86 + {651EBEC1-045E-4A74-A9F6-7E8DD223DD7A}.Mono|x86.ActiveCfg = Release|x86 + {651EBEC1-045E-4A74-A9F6-7E8DD223DD7A}.Mono|x86.Build.0 = Release|x86 + {651EBEC1-045E-4A74-A9F6-7E8DD223DD7A}.Release|x86.ActiveCfg = Release|x86 + {651EBEC1-045E-4A74-A9F6-7E8DD223DD7A}.Release|x86.Build.0 = Release|x86 + {7FA21B39-6926-412C-BB5E-99F957E5CC19}.Debug|x86.ActiveCfg = Debug|x86 + {7FA21B39-6926-412C-BB5E-99F957E5CC19}.Debug|x86.Build.0 = Debug|x86 + {7FA21B39-6926-412C-BB5E-99F957E5CC19}.Mono|x86.ActiveCfg = Release|x86 + {7FA21B39-6926-412C-BB5E-99F957E5CC19}.Mono|x86.Build.0 = Release|x86 + {7FA21B39-6926-412C-BB5E-99F957E5CC19}.Release|x86.ActiveCfg = Release|x86 + {7FA21B39-6926-412C-BB5E-99F957E5CC19}.Release|x86.Build.0 = Release|x86 + {6449C3DE-E27F-45A6-AAED-BF7E3028CD0B}.Debug|x86.ActiveCfg = Debug|x86 + {6449C3DE-E27F-45A6-AAED-BF7E3028CD0B}.Debug|x86.Build.0 = Debug|x86 + {6449C3DE-E27F-45A6-AAED-BF7E3028CD0B}.Mono|x86.ActiveCfg = Release|x86 + {6449C3DE-E27F-45A6-AAED-BF7E3028CD0B}.Mono|x86.Build.0 = Release|x86 + {6449C3DE-E27F-45A6-AAED-BF7E3028CD0B}.Release|x86.ActiveCfg = Release|x86 + {6449C3DE-E27F-45A6-AAED-BF7E3028CD0B}.Release|x86.Build.0 = Release|x86 + {722FD1AB-4193-45B1-A94E-10B6E5C9AA05}.Debug|x86.ActiveCfg = Debug|x86 + {722FD1AB-4193-45B1-A94E-10B6E5C9AA05}.Debug|x86.Build.0 = Debug|x86 + {722FD1AB-4193-45B1-A94E-10B6E5C9AA05}.Mono|x86.ActiveCfg = Release|x86 + {722FD1AB-4193-45B1-A94E-10B6E5C9AA05}.Mono|x86.Build.0 = Release|x86 + {722FD1AB-4193-45B1-A94E-10B6E5C9AA05}.Release|x86.ActiveCfg = Release|x86 + {722FD1AB-4193-45B1-A94E-10B6E5C9AA05}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -337,7 +624,6 @@ Global {3EC64359-C4AB-44C2-BCC0-8617380DB67A} = {473A7C08-02A2-473A-BEC6-891F035674FD} {A5152775-5252-45B2-B091-69C70280C73C} = {473A7C08-02A2-473A-BEC6-891F035674FD} {E6CEA943-9111-4CCD-97BD-A63F7DDABBAE} = {473A7C08-02A2-473A-BEC6-891F035674FD} - {6449C3DE-E27F-45A6-AAED-BF7E3028CD0B} = {473A7C08-02A2-473A-BEC6-891F035674FD} {503EF9C0-CE83-40BE-98B2-3481D9FE3B0D} = {A0409E80-C6CE-4DEA-9825-92A2A6BDDC45} {3929B83A-B1A6-4620-9139-B5DEEEF3DCE4} = {473A7C08-02A2-473A-BEC6-891F035674FD} {ECD64A23-8504-4A68-829D-FB1B6C726C85} = {473A7C08-02A2-473A-BEC6-891F035674FD} @@ -378,6 +664,30 @@ Global {1E055676-77A0-4C5B-B449-FF58CA5066E0} = {A0409E80-C6CE-4DEA-9825-92A2A6BDDC45} {19906CFC-8E1C-4F11-98E6-92A73C4F097E} = {A0409E80-C6CE-4DEA-9825-92A2A6BDDC45} {E0E753EE-4A27-491C-A914-6942A772AAF2} = {473A7C08-02A2-473A-BEC6-891F035674FD} + {742487A3-DD2E-4F47-9ABB-77E88653A1D3} = {B0536923-080A-43F7-8C8A-C7D579AB0DB5} + {6B66B73D-481C-479B-AC13-F5E332D12293} = {B0536923-080A-43F7-8C8A-C7D579AB0DB5} + {744FC79F-5B6D-44AD-8C34-1ABB6EABAE6B} = {B0536923-080A-43F7-8C8A-C7D579AB0DB5} + {EE5B96F4-EEB3-4606-98C9-6F1242B41FD2} = {B0536923-080A-43F7-8C8A-C7D579AB0DB5} + {E34CC841-CE29-4B39-9BE5-D98502330F55} = {B0536923-080A-43F7-8C8A-C7D579AB0DB5} + {B4892057-CAE6-41F4-A75D-88E61331A2D0} = {A0409E80-C6CE-4DEA-9825-92A2A6BDDC45} + {DEC346FD-C496-4B3E-A0E9-60AE011E3C49} = {17A03FBD-E6BD-4017-ACA1-8D4E0DC6EEBE} + {2C079A0D-8F90-4B4E-85AA-CAD45F7E0CAC} = {FD30843F-F53A-4D66-A314-068C314D23FE} + {BCC446EF-0F10-4FBB-AB37-9A9E0B1CDBAB} = {FD30843F-F53A-4D66-A314-068C314D23FE} + {3B59E324-53FC-4837-AF37-61FC4B51E2D1} = {831639B8-4A6B-4462-998D-A8375EA0837C} + {C646B987-EA7E-4D82-A930-448DE583FEB3} = {BE29F5CB-80FB-4CF1-9135-800534B264D3} + {59E2469C-197F-4A4C-9D52-AA58EA49927E} = {BE29F5CB-80FB-4CF1-9135-800534B264D3} + {6FA77B7F-E933-4B25-AC4C-99E343B35AC8} = {BE29F5CB-80FB-4CF1-9135-800534B264D3} + {9800A224-0BF0-4D5D-A03C-AA7A4842D3B8} = {F697B4C2-4712-4596-814B-245E2500AE51} + {B4CB129D-51F9-4C86-B520-7AC50537A70B} = {004C9C77-4F14-4ED4-ACAE-781D6B860CA2} + {B31C0650-991B-4B28-9864-AE80C1785A3F} = {004C9C77-4F14-4ED4-ACAE-781D6B860CA2} + {779A59F0-BF3B-4AE5-B323-97D37CD67233} = {004C9C77-4F14-4ED4-ACAE-781D6B860CA2} + {AB55ABF6-4AD9-4F8A-9E9D-8B61F89766A6} = {004C9C77-4F14-4ED4-ACAE-781D6B860CA2} + {40C644F9-5AF9-44BB-9649-02149933E092} = {004C9C77-4F14-4ED4-ACAE-781D6B860CA2} + {2E6B9575-0C86-4034-8A8E-13C880B69A6F} = {17A03FBD-E6BD-4017-ACA1-8D4E0DC6EEBE} + {651EBEC1-045E-4A74-A9F6-7E8DD223DD7A} = {B0536923-080A-43F7-8C8A-C7D579AB0DB5} + {7FA21B39-6926-412C-BB5E-99F957E5CC19} = {BE29F5CB-80FB-4CF1-9135-800534B264D3} + {6449C3DE-E27F-45A6-AAED-BF7E3028CD0B} = {473A7C08-02A2-473A-BEC6-891F035674FD} + {722FD1AB-4193-45B1-A94E-10B6E5C9AA05} = {B0536923-080A-43F7-8C8A-C7D579AB0DB5} EndGlobalSection GlobalSection(TestCaseManagementSettings) = postSolution CategoryFile = Accord.NET.vsmdi diff --git a/Samples/Statistics/Analysis (KDA)/Accord.dll.config b/Samples/Statistics/Analysis (KDA)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Statistics/Analysis (KDA)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Statistics/Analysis (KDA)/Analysis (KDA).csproj b/Samples/Statistics/Analysis (KDA)/Analysis (KDA).csproj index 297d33a7b..410ab3069 100644 --- a/Samples/Statistics/Analysis (KDA)/Analysis (KDA).csproj +++ b/Samples/Statistics/Analysis (KDA)/Analysis (KDA).csproj @@ -80,20 +80,13 @@ False ..\..\..\Release\net40\Accord.Statistics.dll - - False - ..\..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Math.dll - 3.5 + @@ -127,6 +120,9 @@ TableSelectDialog.cs Designer + + PreserveNewest + diff --git a/Samples/Statistics/Analysis (KDA)/MainForm.resx b/Samples/Statistics/Analysis (KDA)/MainForm.resx index 6ec5fa8cb..b54af1dbc 100644 --- a/Samples/Statistics/Analysis (KDA)/MainForm.resx +++ b/Samples/Statistics/Analysis (KDA)/MainForm.resx @@ -123,38 +123,6 @@ 665, 17 - - - AAEAAAD/////AQAAAAAAAAAMAgAAAFVBY2NvcmQuU3RhdGlzdGljcywgVmVyc2lvbj0yLjE1LjAuMCwg - Q3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1mYTFhODhlMjk1NTVjY2Y3BQEAAAAqQWNjb3Jk - LlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtBwAAAAliaW5WYWx1ZXMJYmluUmFuZ2Vz - E2luY2x1c2l2ZVVwcGVyQm91bmQNYmluQ29sbGVjdGlvbgpjdW11bGF0aXZlBXRpdGxlBHJ1bGUHBwAE - AAEECAYBN0FjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbkNvbGxlY3Rp - b24CAAAAATJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxpemF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQIA - AAACAAAACQMAAAAJBAAAAAEJBQAAAAAGBgAAAAAF+f///zJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxp - emF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQEAAAAHdmFsdWVfXwAIAgAAAAMAAAAPAwAAAAAAAAAIDwQA - AAABAAAABgAAAAAAAAAABQUAAAA3QWNjb3JkLlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9n - cmFtQmluQ29sbGVjdGlvbgEAAAAZUmVhZE9ubHlDb2xsZWN0aW9uYDErbGlzdAQvQWNjb3JkLlN0YXRp - c3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtQmluW10CAAAAAgAAAAkIAAAABwgAAAAAAQAAAAAA - AAAELUFjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbgIAAAAL - - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAFVBY2NvcmQuU3RhdGlzdGljcywgVmVyc2lvbj0yLjE1LjAuMCwg - Q3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1mYTFhODhlMjk1NTVjY2Y3BQEAAAAqQWNjb3Jk - LlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtBwAAAAliaW5WYWx1ZXMJYmluUmFuZ2Vz - E2luY2x1c2l2ZVVwcGVyQm91bmQNYmluQ29sbGVjdGlvbgpjdW11bGF0aXZlBXRpdGxlBHJ1bGUHBwAE - AAEECAYBN0FjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbkNvbGxlY3Rp - b24CAAAAATJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxpemF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQIA - AAACAAAACQMAAAAJBAAAAAEJBQAAAAAGBgAAAAAF+f///zJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxp - emF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQEAAAAHdmFsdWVfXwAIAgAAAAMAAAAPAwAAAAAAAAAIDwQA - AAABAAAABgAAAAAAAAAABQUAAAA3QWNjb3JkLlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9n - cmFtQmluQ29sbGVjdGlvbgEAAAAZUmVhZE9ubHlDb2xsZWN0aW9uYDErbGlzdAQvQWNjb3JkLlN0YXRp - c3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtQmluW10CAAAAAgAAAAkIAAAABwgAAAAAAQAAAAAA - AAAELUFjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbgIAAAAL - - True @@ -206,38 +174,6 @@ True - - - AAEAAAD/////AQAAAAAAAAAMAgAAAFVBY2NvcmQuU3RhdGlzdGljcywgVmVyc2lvbj0yLjE1LjAuMCwg - Q3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1mYTFhODhlMjk1NTVjY2Y3BQEAAAAqQWNjb3Jk - LlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtBwAAAAliaW5WYWx1ZXMJYmluUmFuZ2Vz - E2luY2x1c2l2ZVVwcGVyQm91bmQNYmluQ29sbGVjdGlvbgpjdW11bGF0aXZlBXRpdGxlBHJ1bGUHBwAE - AAEECAYBN0FjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbkNvbGxlY3Rp - b24CAAAAATJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxpemF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQIA - AAACAAAACQMAAAAJBAAAAAEJBQAAAAAGBgAAAAAF+f///zJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxp - emF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQEAAAAHdmFsdWVfXwAIAgAAAAMAAAAPAwAAAAAAAAAIDwQA - AAABAAAABgAAAAAAAAAABQUAAAA3QWNjb3JkLlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9n - cmFtQmluQ29sbGVjdGlvbgEAAAAZUmVhZE9ubHlDb2xsZWN0aW9uYDErbGlzdAQvQWNjb3JkLlN0YXRp - c3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtQmluW10CAAAAAgAAAAkIAAAABwgAAAAAAQAAAAAA - AAAELUFjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbgIAAAAL - - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAFVBY2NvcmQuU3RhdGlzdGljcywgVmVyc2lvbj0yLjE1LjAuMCwg - Q3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1mYTFhODhlMjk1NTVjY2Y3BQEAAAAqQWNjb3Jk - LlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtBwAAAAliaW5WYWx1ZXMJYmluUmFuZ2Vz - E2luY2x1c2l2ZVVwcGVyQm91bmQNYmluQ29sbGVjdGlvbgpjdW11bGF0aXZlBXRpdGxlBHJ1bGUHBwAE - AAEECAYBN0FjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbkNvbGxlY3Rp - b24CAAAAATJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxpemF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQIA - AAACAAAACQMAAAAJBAAAAAEJBQAAAAAGBgAAAAAF+f///zJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxp - emF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQEAAAAHdmFsdWVfXwAIAgAAAAMAAAAPAwAAAAAAAAAIDwQA - AAABAAAABgAAAAAAAAAABQUAAAA3QWNjb3JkLlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9n - cmFtQmluQ29sbGVjdGlvbgEAAAAZUmVhZE9ubHlDb2xsZWN0aW9uYDErbGlzdAQvQWNjb3JkLlN0YXRp - c3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtQmluW10CAAAAAgAAAAkIAAAABwgAAAAAAQAAAAAA - AAAELUFjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbgIAAAAL - - True @@ -256,258 +192,258 @@ - AAABAAMAEBAAAAAAIABoBAAANgAAACAgAAAAACAAqBAAAJ4EAAAwMAAAAAAgAKglAABGFQAAKAAAABAA - AAAgAAAAAQAgAAAAAABABAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wEAAAA7AAAAVQAA - AF0AAAAJ////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAtwAA - ADkAAAA/AAAAff///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ABEAAAADAAAACQAAANcAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAADVAAAAJf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAvQAAAEn///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAGwAAAM0AAACrAAAANf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAGQAAAJcAAACtAAAAlwAAAIEAAAA/////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAGUAAAAxAAAAfwAAAJ8AAAALAAAAi////wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAABlAAAAMQAAAGMAAAC7AAAADQAAAIn///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAFwAAAJkAAABtAAAA2wAAAIEAAAA9////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAZAAAAgQAAAPMAAAAx////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAAAkAAADvAAAADf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAA2wAA - AB3///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - AK8AAAAzAAAAAwAAABP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAABTAAAAaQAAADEAAADD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAAwAAAFcAAABVAAAAPf///wH///8B////Af///wEAAP//AAD//wAA//8AAP//AAD//wAA - //8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//KAAAACAAAABAAAAAAQAgAAAA - AACAEAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ABcAAABRAAAAYQAAAEcAAAAL////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAvAAAApwAAAF8AAABBAAAAfwAAAKMAAAAh////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAAI8AAAD5AAAAcwAAAAMAAAAHAAAApQAAAKkAAAAL////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAdwAAAOEAAABrAAAAA////wEAAABNAAAA5wAAAFv///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAPAAAAMQAAAA3///8B////AQAAAB0AAADhAAAAsf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ANMAAAD5AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAtwAAAP8AAAAz////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAACdAAAA/wAAAF3///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAIcAAAD/AAAAh////wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAcQAAAP8AAACdAAAAA////wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABfAAAA/wAAALsAAAAf////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAYwAAANcAAAD/AAAA9QAA - AN0AAAClAAAAK////wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACQAAAIMAAADRAAAAjQAA - AP8AAADjAAAAYwAAAKcAAADFAAAAMf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABXAAAA2QAA - AC0AAAA1AAAA8wAAAOsAAAAv////AQAAAJUAAADDAAAABf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ALcAAAB7////AQAAACsAAADjAAAA/QAAADv///8BAAAAJwAAAMsAAABB////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAA3QAAAEP///8BAAAAHwAAAM8AAAD/AAAASf///wEAAAAFAAAAsQAAAHH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAADfAAAARf///wEAAAAVAAAAvwAAAP8AAABp////AQAAAAUAAACxAAAAbf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAALcAAAB9////AQAAAAsAAACtAAAA/wAAAIH///8BAAAAKwAA - AM0AAAA5////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAATwAAANsAAAAzAAAAAwAAAKEAAAD/AAAAmwAA - AAUAAACXAAAAvwAAAAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAewAAANkAAABrAAAApQAA - AP8AAADRAAAApwAAAL8AAAAt////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAWwAA - AMUAAADrAAAA/wAAAPUAAACVAAAAJ////wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAAwAAAE8AAAD/AAAA2QAAAAX///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAHwAAAP8AAADdAAAAEf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAFAAAA/wAAAOEAAAAd////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAADfAAAA5wAAAC3///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAALcAAADtAAAAQf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAhQAA - APUAAABX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAABPAAAA7wAAAHP///8B////AQAAAA0AAAA3AAAAE////wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAABkAAADPAAAAmwAAAAf///8BAAAAZQAAAOcAAACL////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAGMAAADjAAAAH////wEAAABdAAAA9QAAAKn///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAACwAAAIEAAAChAAAAUwAAAF8AAACpAAAAN/// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAADkAAABXAAAATQAA - ABf///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAwAAAAYAAAAAEA - IAAAAAAAgCUAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAAcAAAAPAAAAEwAAABMAAAARAAAACQAAAAP///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAADAAAAHQAAAGMAAACvAAAA0QAAANUAAAC7AAAAdQAA - ACkAAAAF////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAATAAAApQAAANcAAABXAAAACQAA - AA0AAABTAAAAwwAAALsAAAA/AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABHAAAA/wAA - APEAAACNAAAAC////wH///8BAAAATQAAANcAAADBAAAAKQAAAAP///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAABtAAAA/wAAAP8AAAC/AAAAG////wH///8BAAAABwAAAKEAAAD5AAAAhQAAAAn///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAAA5AAAAxQAAANUAAACBAAAADf///wH///8B////AQAAAGcAAADnAAAA6QAA - ACf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAFAAAAPQAAAEsAAAAb////Af///wH///8B////AQAA - ADUAAADVAAAA/wAAAHX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAAA8AAADJAAAA/wAAANH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAC7AAAA/QAAAPsAAAAL////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACjAAAA+QAAAP8AAABB////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA8wAA - AP8AAABp////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAB3AAAA7wAAAP8AAACb////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAABnAAAA7QAAAP8AAAC/////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAABNAAAA5wAAAP8AAADf////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAA/AAAA5QAAAP8AAADtAAAAB/// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAxAAAA4QAA - AP8AAADxAAAANQAAAAn///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - AB0AAABjAAAA6QAAAP8AAAD5AAAAowAAAG8AAABBAAAAFf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAFAAAAPQAAAJUAAADfAAAA/QAAAP8AAAD9AAAA5wAAAOcAAADRAAAAgwAAACv///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAAAUAAABNAAAAwwAAANkAAACRAAAA6wAAAP8AAAD5AAAArQAAAGsAAACtAAAA5QAA - AKMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAADkAAAC/AAAA1wAAAGkAAAAVAAAA0QAAAP8AAAD5AAAAmQAA - AAUAAAApAAAAiwAAAOMAAACXAAAAIf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAEwAAAIUAAADjAAAAcwAAAA////8BAAAAtwAA - APsAAAD7AAAAs////wH///8BAAAAHQAAAJkAAADnAAAAWwAAAAX///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAOQAAAMUAAACrAAAAJ/// - /wH///8BAAAAoQAAAPsAAAD/AAAA0f///wH///8BAAAAAwAAAEcAAADNAAAAnQAAAB////8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAA - AOsAAAB1AAAABf///wH///8BAAAAhwAAAPcAAAD/AAAA1////wH///8B////AQAAABcAAACfAAAAzwAA - ADf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAZwAAAPUAAAD/AAAA3QAAABn///8B////AQAA - AAMAAACLAAAA6QAAAEP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAVQAAAPMAAAD/AAAA4wAA - ADf///8B////AQAAAAMAAACLAAAA5wAAAEP///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAAAPEAAAB7AAAABf///wH///8BAAAANwAA - APEAAAD/AAAA5QAAAEX///8B////AQAAABcAAAChAAAAxQAAADP///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAANwAAAMMAAACtAAAAKf// - /wH///8BAAAAGwAAAO0AAAD/AAAA6wAAAF////8BAAAAAwAAAE8AAADVAAAAlQAAABv///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAADwAA - AH0AAADnAAAAeQAAABH///8BAAAACwAAAO0AAAD/AAAA7wAAAHEAAAADAAAAIQAAAJ0AAADpAAAAWQAA - AAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAADUAAAC1AAAA2wAAAHUAAAAdAAAAAwAAAN8AAAD/AAAA9QAAAJMAAAArAAAAkQAA - AN8AAACPAAAAHf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAAUAAABJAAAAuwAAAOMAAACdAAAAZQAAANsAAAD/AAAA+wAA - ANEAAACtAAAA4QAAAJsAAAAr////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAFAAAAOQAAAIsAAADVAAAA5wAA - APcAAAD/AAAA/wAAAPcAAADDAAAAdQAAACf///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ABcAAABFAAAAaQAAALkAAAD/AAAA/wAAANUAAAA5AAAADf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAABQAAAGMAAAD/AAAA/wAAAMcAAAAJ////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////AQAAADcAAAD/AAAA/wAAAMsAAAAV////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAABUAAAD/AAAA/wAA - AM8AAAAh////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - AAMAAAD/AAAA/wAAANMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAADdAAAA/wAAANkAAAA9////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAACtAAAA/wAAAOEAAABV////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA/wAAAOUAAABl////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABTAAAA/wAA - AO8AAAB9////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAnAAAA8wAAAPcAAACX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAAAPAAAAwQAAAP0AAACtAAAABf///wH///8B////AQAAABsAAABTAAAASwAA - AAf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAHAAAAbQAAAP8AAADBAAAAIf///wH///8BAAAABwAA - AH0AAADbAAAA0wAAAEv///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAADAAAAKwAAANcAAADbAAAAVf// - /wH///8BAAAACwAAALUAAAD/AAAA/wAAAJX///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACwAA - AGkAAADvAAAAmwAAABP///8BAAAABQAAAHEAAADpAAAA/wAAAGv///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAABcAAACDAAAA4QAAAIcAAAAtAAAAGwAAAFMAAADTAAAAsQAAAB3///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAAMAAAAVAAAAWwAAAKkAAADFAAAAxwAAAKsAAABjAAAAHwAA - AAP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAAA0AAAATAAAAEwAA - AA8AAAAH////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8= - + AAABAAMAEBAAAAAAIABoBAAANgAAACAgAAAAACAAqBAAAJ4EAAAwMAAAAAAgAKglAABGFQAAKAAAABAA + AAAgAAAAAQAgAAAAAABABAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wEAAAA7AAAAVQAA + AF0AAAAJ////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAtwAA + ADkAAAA/AAAAff///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABEAAAADAAAACQAAANcAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADVAAAAJf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAvQAAAEn///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAGwAAAM0AAACrAAAANf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAGQAAAJcAAACtAAAAlwAAAIEAAAA/////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAGUAAAAxAAAAfwAAAJ8AAAALAAAAi////wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAABlAAAAMQAAAGMAAAC7AAAADQAAAIn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAFwAAAJkAAABtAAAA2wAAAIEAAAA9////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAZAAAAgQAAAPMAAAAx////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAAAkAAADvAAAADf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAA2wAA + AB3///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AK8AAAAzAAAAAwAAABP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABTAAAAaQAAADEAAADD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAAwAAAFcAAABVAAAAPf///wH///8B////Af///wEAAP//AAD//wAA//8AAP//AAD//wAA + //8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//KAAAACAAAABAAAAAAQAgAAAA + AACAEAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABcAAABRAAAAYQAAAEcAAAAL////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAvAAAApwAAAF8AAABBAAAAfwAAAKMAAAAh////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAI8AAAD5AAAAcwAAAAMAAAAHAAAApQAAAKkAAAAL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAdwAAAOEAAABrAAAAA////wEAAABNAAAA5wAAAFv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAPAAAAMQAAAA3///8B////AQAAAB0AAADhAAAAsf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ANMAAAD5AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAtwAAAP8AAAAz////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAACdAAAA/wAAAF3///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAIcAAAD/AAAAh////wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAcQAAAP8AAACdAAAAA////wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABfAAAA/wAAALsAAAAf////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAYwAAANcAAAD/AAAA9QAA + AN0AAAClAAAAK////wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACQAAAIMAAADRAAAAjQAA + AP8AAADjAAAAYwAAAKcAAADFAAAAMf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABXAAAA2QAA + AC0AAAA1AAAA8wAAAOsAAAAv////AQAAAJUAAADDAAAABf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ALcAAAB7////AQAAACsAAADjAAAA/QAAADv///8BAAAAJwAAAMsAAABB////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAA3QAAAEP///8BAAAAHwAAAM8AAAD/AAAASf///wEAAAAFAAAAsQAAAHH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADfAAAARf///wEAAAAVAAAAvwAAAP8AAABp////AQAAAAUAAACxAAAAbf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAALcAAAB9////AQAAAAsAAACtAAAA/wAAAIH///8BAAAAKwAA + AM0AAAA5////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAATwAAANsAAAAzAAAAAwAAAKEAAAD/AAAAmwAA + AAUAAACXAAAAvwAAAAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAewAAANkAAABrAAAApQAA + AP8AAADRAAAApwAAAL8AAAAt////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAWwAA + AMUAAADrAAAA/wAAAPUAAACVAAAAJ////wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAAwAAAE8AAAD/AAAA2QAAAAX///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAHwAAAP8AAADdAAAAEf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAFAAAA/wAAAOEAAAAd////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAADfAAAA5wAAAC3///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAALcAAADtAAAAQf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAhQAA + APUAAABX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABPAAAA7wAAAHP///8B////AQAAAA0AAAA3AAAAE////wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAABkAAADPAAAAmwAAAAf///8BAAAAZQAAAOcAAACL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAGMAAADjAAAAH////wEAAABdAAAA9QAAAKn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAACwAAAIEAAAChAAAAUwAAAF8AAACpAAAAN/// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAADkAAABXAAAATQAA + ABf///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAwAAAAYAAAAAEA + IAAAAAAAgCUAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAcAAAAPAAAAEwAAABMAAAARAAAACQAAAAP///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAADAAAAHQAAAGMAAACvAAAA0QAAANUAAAC7AAAAdQAA + ACkAAAAF////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAATAAAApQAAANcAAABXAAAACQAA + AA0AAABTAAAAwwAAALsAAAA/AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABHAAAA/wAA + APEAAACNAAAAC////wH///8BAAAATQAAANcAAADBAAAAKQAAAAP///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABtAAAA/wAAAP8AAAC/AAAAG////wH///8BAAAABwAAAKEAAAD5AAAAhQAAAAn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAAA5AAAAxQAAANUAAACBAAAADf///wH///8B////AQAAAGcAAADnAAAA6QAA + ACf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAFAAAAPQAAAEsAAAAb////Af///wH///8B////AQAA + ADUAAADVAAAA/wAAAHX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAA8AAADJAAAA/wAAANH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAC7AAAA/QAAAPsAAAAL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACjAAAA+QAAAP8AAABB////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA8wAA + AP8AAABp////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAB3AAAA7wAAAP8AAACb////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAABnAAAA7QAAAP8AAAC/////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAABNAAAA5wAAAP8AAADf////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAA/AAAA5QAAAP8AAADtAAAAB/// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAxAAAA4QAA + AP8AAADxAAAANQAAAAn///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AB0AAABjAAAA6QAAAP8AAAD5AAAAowAAAG8AAABBAAAAFf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAFAAAAPQAAAJUAAADfAAAA/QAAAP8AAAD9AAAA5wAAAOcAAADRAAAAgwAAACv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAAUAAABNAAAAwwAAANkAAACRAAAA6wAAAP8AAAD5AAAArQAAAGsAAACtAAAA5QAA + AKMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAADkAAAC/AAAA1wAAAGkAAAAVAAAA0QAAAP8AAAD5AAAAmQAA + AAUAAAApAAAAiwAAAOMAAACXAAAAIf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAEwAAAIUAAADjAAAAcwAAAA////8BAAAAtwAA + APsAAAD7AAAAs////wH///8BAAAAHQAAAJkAAADnAAAAWwAAAAX///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAOQAAAMUAAACrAAAAJ/// + /wH///8BAAAAoQAAAPsAAAD/AAAA0f///wH///8BAAAAAwAAAEcAAADNAAAAnQAAAB////8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAA + AOsAAAB1AAAABf///wH///8BAAAAhwAAAPcAAAD/AAAA1////wH///8B////AQAAABcAAACfAAAAzwAA + ADf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAZwAAAPUAAAD/AAAA3QAAABn///8B////AQAA + AAMAAACLAAAA6QAAAEP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAVQAAAPMAAAD/AAAA4wAA + ADf///8B////AQAAAAMAAACLAAAA5wAAAEP///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAAAPEAAAB7AAAABf///wH///8BAAAANwAA + APEAAAD/AAAA5QAAAEX///8B////AQAAABcAAAChAAAAxQAAADP///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAANwAAAMMAAACtAAAAKf// + /wH///8BAAAAGwAAAO0AAAD/AAAA6wAAAF////8BAAAAAwAAAE8AAADVAAAAlQAAABv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAADwAA + AH0AAADnAAAAeQAAABH///8BAAAACwAAAO0AAAD/AAAA7wAAAHEAAAADAAAAIQAAAJ0AAADpAAAAWQAA + AAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAADUAAAC1AAAA2wAAAHUAAAAdAAAAAwAAAN8AAAD/AAAA9QAAAJMAAAArAAAAkQAA + AN8AAACPAAAAHf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAUAAABJAAAAuwAAAOMAAACdAAAAZQAAANsAAAD/AAAA+wAA + ANEAAACtAAAA4QAAAJsAAAAr////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAFAAAAOQAAAIsAAADVAAAA5wAA + APcAAAD/AAAA/wAAAPcAAADDAAAAdQAAACf///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABcAAABFAAAAaQAAALkAAAD/AAAA/wAAANUAAAA5AAAADf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAABQAAAGMAAAD/AAAA/wAAAMcAAAAJ////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////AQAAADcAAAD/AAAA/wAAAMsAAAAV////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAABUAAAD/AAAA/wAA + AM8AAAAh////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AAMAAAD/AAAA/wAAANMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADdAAAA/wAAANkAAAA9////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAACtAAAA/wAAAOEAAABV////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA/wAAAOUAAABl////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABTAAAA/wAA + AO8AAAB9////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAnAAAA8wAAAPcAAACX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAAAPAAAAwQAAAP0AAACtAAAABf///wH///8B////AQAAABsAAABTAAAASwAA + AAf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAHAAAAbQAAAP8AAADBAAAAIf///wH///8BAAAABwAA + AH0AAADbAAAA0wAAAEv///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAADAAAAKwAAANcAAADbAAAAVf// + /wH///8BAAAACwAAALUAAAD/AAAA/wAAAJX///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACwAA + AGkAAADvAAAAmwAAABP///8BAAAABQAAAHEAAADpAAAA/wAAAGv///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAABcAAACDAAAA4QAAAIcAAAAtAAAAGwAAAFMAAADTAAAAsQAAAB3///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAMAAAAVAAAAWwAAAKkAAADFAAAAxwAAAKsAAABjAAAAHwAA + AAP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAAA0AAAATAAAAEwAA + AA8AAAAH////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8= + \ No newline at end of file diff --git a/Samples/Statistics/Analysis (KPCA)/Accord.dll.config b/Samples/Statistics/Analysis (KPCA)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Statistics/Analysis (KPCA)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Statistics/Analysis (KPCA)/Analysis (KPCA).csproj b/Samples/Statistics/Analysis (KPCA)/Analysis (KPCA).csproj index 546df7d80..bad97affb 100644 --- a/Samples/Statistics/Analysis (KPCA)/Analysis (KPCA).csproj +++ b/Samples/Statistics/Analysis (KPCA)/Analysis (KPCA).csproj @@ -82,20 +82,13 @@ False ..\..\..\Release\net40\Accord.Statistics.dll - - False - ..\..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Math.dll - 3.5 + @@ -139,6 +132,9 @@ Resources.resx True + + PreserveNewest + diff --git a/Samples/Statistics/Analysis (KPCA)/MainForm.resx b/Samples/Statistics/Analysis (KPCA)/MainForm.resx index 5cdb9e364..d7c368da8 100644 --- a/Samples/Statistics/Analysis (KPCA)/MainForm.resx +++ b/Samples/Statistics/Analysis (KPCA)/MainForm.resx @@ -123,86 +123,86 @@ - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAJHSURBVDhPxZBdSNNhFMb/F110ZZEVhVBgeeHNICiiuggp - olAUyyxI0oSaH1QYC3N+tKnp5ubm1JUua5uuqdNKMwr7kApFItTUkWZqVhSVYmao5Nevvy7UoYR3HXh4 - 4XCe33nOKyy3lAY7l9RWMo0O/raWXxEyo5spVYTNvOGyfIRPfW+ptOkXqaPl6T83hcRmExSdgzAz3NVm - YWyoYla/B+1M9JtxWLPpaH22JORIjI6gKAMB0jyEimIdo4OlbuaprwVMOOMovammpDADc34qppwUrmnl - 5Kni3aFlFg2j3y1z5mnRTJccnNIltQhwq0jFry+mOXNtpWZWDx1Z1NhV3C3JwGFOw25SYjVe5oYhiUKd - HKMmwQUrMWUw/CF3NnZvvYKqUh1TvUroS3fXe7HXkwidMngTS2t5KLbregSzMY2f3Wr4qKW6LJvGR1rX - 0MLor8OhKYTJBn/GHvvxrliCTBrsOqXIoOBHh5K+hmSq7FqmexTQHuUytkaKxuNMNgYyVneA4Qd7GKjc - hjLaRzxH7gIU6JIZaEvgtk1D8wsxSWecCDgNzWFMvwxm/PkhRmr3Mli1nW9lvjRdWc0Jf+/5jzRmyWmv - S+GOLQu6U6BFjPvqKOP1AYw88WOoZif9DgmfLVtxaj1RSLdwNvrkPCA3M54KqxrnvRia9MKcGrUrqFOt - 5H7qKsqT1mGO9+Lqhc2ELdw+U/r0i+gVZ8hMiCDx3DHORwZyKnQ/hw/uYt9uCTskPvh6e7Fp41rWr/Fg - g6eHO+A/lyD8ARfG3mk9fv1YAAAAAElFTkSuQmCC - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAJHSURBVDhPxZBdSNNhFMb/F110ZZEVhVBgeeHNICiiuggp + olAUyyxI0oSaH1QYC3N+tKnp5ubm1JUua5uuqdNKMwr7kApFItTUkWZqVhSVYmao5Nevvy7UoYR3HXh4 + 4XCe33nOKyy3lAY7l9RWMo0O/raWXxEyo5spVYTNvOGyfIRPfW+ptOkXqaPl6T83hcRmExSdgzAz3NVm + YWyoYla/B+1M9JtxWLPpaH22JORIjI6gKAMB0jyEimIdo4OlbuaprwVMOOMovammpDADc34qppwUrmnl + 5Kni3aFlFg2j3y1z5mnRTJccnNIltQhwq0jFry+mOXNtpWZWDx1Z1NhV3C3JwGFOw25SYjVe5oYhiUKd + HKMmwQUrMWUw/CF3NnZvvYKqUh1TvUroS3fXe7HXkwidMngTS2t5KLbregSzMY2f3Wr4qKW6LJvGR1rX + 0MLor8OhKYTJBn/GHvvxrliCTBrsOqXIoOBHh5K+hmSq7FqmexTQHuUytkaKxuNMNgYyVneA4Qd7GKjc + hjLaRzxH7gIU6JIZaEvgtk1D8wsxSWecCDgNzWFMvwxm/PkhRmr3Mli1nW9lvjRdWc0Jf+/5jzRmyWmv + S+GOLQu6U6BFjPvqKOP1AYw88WOoZif9DgmfLVtxaj1RSLdwNvrkPCA3M54KqxrnvRia9MKcGrUrqFOt + 5H7qKsqT1mGO9+Lqhc2ELdw+U/r0i+gVZ8hMiCDx3DHORwZyKnQ/hw/uYt9uCTskPvh6e7Fp41rWr/Fg + g6eHO+A/lyD8ARfG3mk9fv1YAAAAAElFTkSuQmCC + - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAIySURBVDhPrZLfS5NRGMfff6H7boIuuq2pMZyL1eAt11CW - DcOKsB9vpFmaLtNExco0av6CbIVLJ61Wk3BSkT/AFCkRZSpZmrmiJQ41xSaCwdfznL15XEUX0Reem5f3 - 8znnec4j/Zc8fxYGla91CS3eRTx0z6OpMYS7jmnU1X6B/VYA18snUVoyjsKCt8jLHcH5c36ouCQR2NUJ - 1Nas4G9ZXlmFKbULh1Kf8lJxSfI+WeCCyopv6q+/h+DQ/DJ2WV5Ao1FgPegRAveDOS4oLfmq/h6dn/DH - 4AJizD4UXJrCAUuzEDgbZrjgou2DiohshIcnQtgme5GTPYbkJKcQ1N8OckHW2REVi+RXuM8fxGaDG4oy - ALPZIQQ11Z+5QDk1oKJ/hjv7P2FTfCMOH3mFxMQ6IbhROYWOdrCnBI4dfwPr0V4+bRoY9UzXppMjcDdS - rC8hy3YhuFI2gTYf2A4Aza4f7N2/o/zaLB8qDYx6zszwr8P7k1thNFYIweXCMXgeAfedq2xxwjClZUeV - Jd2GtDNFETiJwfs8MBjKhMCWN8pgoLoqzE8miH1GjE7G4PsZjE7OQsm9ij2mFg7rdrug1xcJAa2l4w7W - r00Cgk/n38S7wBwC04u4UGxHrMHF4CbEJtyDLj5fCDIzhljfSxzeavRgyw4Zj9t64GvvQ0d3P3pfD2Kv - 2QqNvgFxDN6urYdWmyMElJMnevh60obRktA701PRtGlg1DOdSkXwzrisaMG/RZLWAE60OMW5fNhvAAAA - AElFTkSuQmCC - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAIySURBVDhPrZLfS5NRGMfff6H7boIuuq2pMZyL1eAt11CW + DcOKsB9vpFmaLtNExco0av6CbIVLJ61Wk3BSkT/AFCkRZSpZmrmiJQ41xSaCwdfznL15XEUX0Reem5f3 + 8znnec4j/Zc8fxYGla91CS3eRTx0z6OpMYS7jmnU1X6B/VYA18snUVoyjsKCt8jLHcH5c36ouCQR2NUJ + 1Nas4G9ZXlmFKbULh1Kf8lJxSfI+WeCCyopv6q+/h+DQ/DJ2WV5Ao1FgPegRAveDOS4oLfmq/h6dn/DH + 4AJizD4UXJrCAUuzEDgbZrjgou2DiohshIcnQtgme5GTPYbkJKcQ1N8OckHW2REVi+RXuM8fxGaDG4oy + ALPZIQQ11Z+5QDk1oKJ/hjv7P2FTfCMOH3mFxMQ6IbhROYWOdrCnBI4dfwPr0V4+bRoY9UzXppMjcDdS + rC8hy3YhuFI2gTYf2A4Aza4f7N2/o/zaLB8qDYx6zszwr8P7k1thNFYIweXCMXgeAfedq2xxwjClZUeV + Jd2GtDNFETiJwfs8MBjKhMCWN8pgoLoqzE8miH1GjE7G4PsZjE7OQsm9ij2mFg7rdrug1xcJAa2l4w7W + r00Cgk/n38S7wBwC04u4UGxHrMHF4CbEJtyDLj5fCDIzhljfSxzeavRgyw4Zj9t64GvvQ0d3P3pfD2Kv + 2QqNvgFxDN6urYdWmyMElJMnevh60obRktA701PRtGlg1DOdSkXwzrisaMG/RZLWAE60OMW5fNhvAAAA + AElFTkSuQmCC + - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAJHSURBVDhPxZBdSNNhFMb/F110ZZEVhVBgeeHNICiiuggp - olAUyyxI0oSaH1QYC3N+tKnp5ubm1JUua5uuqdNKMwr7kApFItTUkWZqVhSVYmao5Nevvy7UoYR3HXh4 - 4XCe33nOKyy3lAY7l9RWMo0O/raWXxEyo5spVYTNvOGyfIRPfW+ptOkXqaPl6T83hcRmExSdgzAz3NVm - YWyoYla/B+1M9JtxWLPpaH22JORIjI6gKAMB0jyEimIdo4OlbuaprwVMOOMovammpDADc34qppwUrmnl - 5Kni3aFlFg2j3y1z5mnRTJccnNIltQhwq0jFry+mOXNtpWZWDx1Z1NhV3C3JwGFOw25SYjVe5oYhiUKd - HKMmwQUrMWUw/CF3NnZvvYKqUh1TvUroS3fXe7HXkwidMngTS2t5KLbregSzMY2f3Wr4qKW6LJvGR1rX - 0MLor8OhKYTJBn/GHvvxrliCTBrsOqXIoOBHh5K+hmSq7FqmexTQHuUytkaKxuNMNgYyVneA4Qd7GKjc - hjLaRzxH7gIU6JIZaEvgtk1D8wsxSWecCDgNzWFMvwxm/PkhRmr3Mli1nW9lvjRdWc0Jf+/5jzRmyWmv - S+GOLQu6U6BFjPvqKOP1AYw88WOoZif9DgmfLVtxaj1RSLdwNvrkPCA3M54KqxrnvRia9MKcGrUrqFOt - 5H7qKsqT1mGO9+Lqhc2ELdw+U/r0i+gVZ8hMiCDx3DHORwZyKnQ/hw/uYt9uCTskPvh6e7Fp41rWr/Fg - g6eHO+A/lyD8ARfG3mk9fv1YAAAAAElFTkSuQmCC - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAJHSURBVDhPxZBdSNNhFMb/F110ZZEVhVBgeeHNICiiuggp + olAUyyxI0oSaH1QYC3N+tKnp5ubm1JUua5uuqdNKMwr7kApFItTUkWZqVhSVYmao5Nevvy7UoYR3HXh4 + 4XCe33nOKyy3lAY7l9RWMo0O/raWXxEyo5spVYTNvOGyfIRPfW+ptOkXqaPl6T83hcRmExSdgzAz3NVm + YWyoYla/B+1M9JtxWLPpaH22JORIjI6gKAMB0jyEimIdo4OlbuaprwVMOOMovammpDADc34qppwUrmnl + 5Kni3aFlFg2j3y1z5mnRTJccnNIltQhwq0jFry+mOXNtpWZWDx1Z1NhV3C3JwGFOw25SYjVe5oYhiUKd + HKMmwQUrMWUw/CF3NnZvvYKqUh1TvUroS3fXe7HXkwidMngTS2t5KLbregSzMY2f3Wr4qKW6LJvGR1rX + 0MLor8OhKYTJBn/GHvvxrliCTBrsOqXIoOBHh5K+hmSq7FqmexTQHuUytkaKxuNMNgYyVneA4Qd7GKjc + hjLaRzxH7gIU6JIZaEvgtk1D8wsxSWecCDgNzWFMvwxm/PkhRmr3Mli1nW9lvjRdWc0Jf+/5jzRmyWmv + S+GOLQu6U6BFjPvqKOP1AYw88WOoZif9DgmfLVtxaj1RSLdwNvrkPCA3M54KqxrnvRia9MKcGrUrqFOt + 5H7qKsqT1mGO9+Lqhc2ELdw+U/r0i+gVZ8hMiCDx3DHORwZyKnQ/hw/uYt9uCTskPvh6e7Fp41rWr/Fg + g6eHO+A/lyD8ARfG3mk9fv1YAAAAAElFTkSuQmCC + - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAIySURBVDhPrZLfS5NRGMfff6H7boIuuq2pMZyL1eAt11CW - DcOKsB9vpFmaLtNExco0av6CbIVLJ61Wk3BSkT/AFCkRZSpZmrmiJQ41xSaCwdfznL15XEUX0Reem5f3 - 8znnec4j/Zc8fxYGla91CS3eRTx0z6OpMYS7jmnU1X6B/VYA18snUVoyjsKCt8jLHcH5c36ouCQR2NUJ - 1Nas4G9ZXlmFKbULh1Kf8lJxSfI+WeCCyopv6q+/h+DQ/DJ2WV5Ao1FgPegRAveDOS4oLfmq/h6dn/DH - 4AJizD4UXJrCAUuzEDgbZrjgou2DiohshIcnQtgme5GTPYbkJKcQ1N8OckHW2REVi+RXuM8fxGaDG4oy - ALPZIQQ11Z+5QDk1oKJ/hjv7P2FTfCMOH3mFxMQ6IbhROYWOdrCnBI4dfwPr0V4+bRoY9UzXppMjcDdS - rC8hy3YhuFI2gTYf2A4Aza4f7N2/o/zaLB8qDYx6zszwr8P7k1thNFYIweXCMXgeAfedq2xxwjClZUeV - Jd2GtDNFETiJwfs8MBjKhMCWN8pgoLoqzE8miH1GjE7G4PsZjE7OQsm9ij2mFg7rdrug1xcJAa2l4w7W - r00Cgk/n38S7wBwC04u4UGxHrMHF4CbEJtyDLj5fCDIzhljfSxzeavRgyw4Zj9t64GvvQ0d3P3pfD2Kv - 2QqNvgFxDN6urYdWmyMElJMnevh60obRktA701PRtGlg1DOdSkXwzrisaMG/RZLWAE60OMW5fNhvAAAA - AElFTkSuQmCC - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAIySURBVDhPrZLfS5NRGMfff6H7boIuuq2pMZyL1eAt11CW + DcOKsB9vpFmaLtNExco0av6CbIVLJ61Wk3BSkT/AFCkRZSpZmrmiJQ41xSaCwdfznL15XEUX0Reem5f3 + 8znnec4j/Zc8fxYGla91CS3eRTx0z6OpMYS7jmnU1X6B/VYA18snUVoyjsKCt8jLHcH5c36ouCQR2NUJ + 1Nas4G9ZXlmFKbULh1Kf8lJxSfI+WeCCyopv6q+/h+DQ/DJ2WV5Ao1FgPegRAveDOS4oLfmq/h6dn/DH + 4AJizD4UXJrCAUuzEDgbZrjgou2DiohshIcnQtgme5GTPYbkJKcQ1N8OckHW2REVi+RXuM8fxGaDG4oy + ALPZIQQ11Z+5QDk1oKJ/hjv7P2FTfCMOH3mFxMQ6IbhROYWOdrCnBI4dfwPr0V4+bRoY9UzXppMjcDdS + rC8hy3YhuFI2gTYf2A4Aza4f7N2/o/zaLB8qDYx6zszwr8P7k1thNFYIweXCMXgeAfedq2xxwjClZUeV + Jd2GtDNFETiJwfs8MBjKhMCWN8pgoLoqzE8miH1GjE7G4PsZjE7OQsm9ij2mFg7rdrug1xcJAa2l4w7W + r00Cgk/n38S7wBwC04u4UGxHrMHF4CbEJtyDLj5fCDIzhljfSxzeavRgyw4Zj9t64GvvQ0d3P3pfD2Kv + 2QqNvgFxDN6urYdWmyMElJMnevh60obRktA701PRtGlg1DOdSkXwzrisaMG/RZLWAE60OMW5fNhvAAAA + AElFTkSuQmCC + 435, 17 - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAJHSURBVDhPxZBdSNNhFMb/F110ZZEVhVBgeeHNICiiuggp - olAUyyxI0oSaH1QYC3N+tKnp5ubm1JUua5uuqdNKMwr7kApFItTUkWZqVhSVYmao5Nevvy7UoYR3HXh4 - 4XCe33nOKyy3lAY7l9RWMo0O/raWXxEyo5spVYTNvOGyfIRPfW+ptOkXqaPl6T83hcRmExSdgzAz3NVm - YWyoYla/B+1M9JtxWLPpaH22JORIjI6gKAMB0jyEimIdo4OlbuaprwVMOOMovammpDADc34qppwUrmnl - 5Kni3aFlFg2j3y1z5mnRTJccnNIltQhwq0jFry+mOXNtpWZWDx1Z1NhV3C3JwGFOw25SYjVe5oYhiUKd - HKMmwQUrMWUw/CF3NnZvvYKqUh1TvUroS3fXe7HXkwidMngTS2t5KLbregSzMY2f3Wr4qKW6LJvGR1rX - 0MLor8OhKYTJBn/GHvvxrliCTBrsOqXIoOBHh5K+hmSq7FqmexTQHuUytkaKxuNMNgYyVneA4Qd7GKjc - hjLaRzxH7gIU6JIZaEvgtk1D8wsxSWecCDgNzWFMvwxm/PkhRmr3Mli1nW9lvjRdWc0Jf+/5jzRmyWmv - S+GOLQu6U6BFjPvqKOP1AYw88WOoZif9DgmfLVtxaj1RSLdwNvrkPCA3M54KqxrnvRia9MKcGrUrqFOt - 5H7qKsqT1mGO9+Lqhc2ELdw+U/r0i+gVZ8hMiCDx3DHORwZyKnQ/hw/uYt9uCTskPvh6e7Fp41rWr/Fg - g6eHO+A/lyD8ARfG3mk9fv1YAAAAAElFTkSuQmCC - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAJHSURBVDhPxZBdSNNhFMb/F110ZZEVhVBgeeHNICiiuggp + olAUyyxI0oSaH1QYC3N+tKnp5ubm1JUua5uuqdNKMwr7kApFItTUkWZqVhSVYmao5Nevvy7UoYR3HXh4 + 4XCe33nOKyy3lAY7l9RWMo0O/raWXxEyo5spVYTNvOGyfIRPfW+ptOkXqaPl6T83hcRmExSdgzAz3NVm + YWyoYla/B+1M9JtxWLPpaH22JORIjI6gKAMB0jyEimIdo4OlbuaprwVMOOMovammpDADc34qppwUrmnl + 5Kni3aFlFg2j3y1z5mnRTJccnNIltQhwq0jFry+mOXNtpWZWDx1Z1NhV3C3JwGFOw25SYjVe5oYhiUKd + HKMmwQUrMWUw/CF3NnZvvYKqUh1TvUroS3fXe7HXkwidMngTS2t5KLbregSzMY2f3Wr4qKW6LJvGR1rX + 0MLor8OhKYTJBn/GHvvxrliCTBrsOqXIoOBHh5K+hmSq7FqmexTQHuUytkaKxuNMNgYyVneA4Qd7GKjc + hjLaRzxH7gIU6JIZaEvgtk1D8wsxSWecCDgNzWFMvwxm/PkhRmr3Mli1nW9lvjRdWc0Jf+/5jzRmyWmv + S+GOLQu6U6BFjPvqKOP1AYw88WOoZif9DgmfLVtxaj1RSLdwNvrkPCA3M54KqxrnvRia9MKcGrUrqFOt + 5H7qKsqT1mGO9+Lqhc2ELdw+U/r0i+gVZ8hMiCDx3DHORwZyKnQ/hw/uYt9uCTskPvh6e7Fp41rWr/Fg + g6eHO+A/lyD8ARfG3mk9fv1YAAAAAElFTkSuQmCC + True @@ -216,38 +216,6 @@ True - - - AAEAAAD/////AQAAAAAAAAAMAgAAAFVBY2NvcmQuU3RhdGlzdGljcywgVmVyc2lvbj0yLjE1LjAuMCwg - Q3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1mYTFhODhlMjk1NTVjY2Y3BQEAAAAqQWNjb3Jk - LlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtBwAAAAliaW5WYWx1ZXMJYmluUmFuZ2Vz - E2luY2x1c2l2ZVVwcGVyQm91bmQNYmluQ29sbGVjdGlvbgpjdW11bGF0aXZlBXRpdGxlBHJ1bGUHBwAE - AAEECAYBN0FjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbkNvbGxlY3Rp - b24CAAAAATJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxpemF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQIA - AAACAAAACQMAAAAJBAAAAAEJBQAAAAAGBgAAAAAF+f///zJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxp - emF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQEAAAAHdmFsdWVfXwAIAgAAAAMAAAAPAwAAAAAAAAAIDwQA - AAABAAAABgAAAAAAAAAABQUAAAA3QWNjb3JkLlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9n - cmFtQmluQ29sbGVjdGlvbgEAAAAZUmVhZE9ubHlDb2xsZWN0aW9uYDErbGlzdAQvQWNjb3JkLlN0YXRp - c3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtQmluW10CAAAAAgAAAAkIAAAABwgAAAAAAQAAAAAA - AAAELUFjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbgIAAAAL - - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAFVBY2NvcmQuU3RhdGlzdGljcywgVmVyc2lvbj0yLjE1LjAuMCwg - Q3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1mYTFhODhlMjk1NTVjY2Y3BQEAAAAqQWNjb3Jk - LlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtBwAAAAliaW5WYWx1ZXMJYmluUmFuZ2Vz - E2luY2x1c2l2ZVVwcGVyQm91bmQNYmluQ29sbGVjdGlvbgpjdW11bGF0aXZlBXRpdGxlBHJ1bGUHBwAE - AAEECAYBN0FjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbkNvbGxlY3Rp - b24CAAAAATJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxpemF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQIA - AAACAAAACQMAAAAJBAAAAAEJBQAAAAAGBgAAAAAF+f///zJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxp - emF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQEAAAAHdmFsdWVfXwAIAgAAAAMAAAAPAwAAAAAAAAAIDwQA - AAABAAAABgAAAAAAAAAABQUAAAA3QWNjb3JkLlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9n - cmFtQmluQ29sbGVjdGlvbgEAAAAZUmVhZE9ubHlDb2xsZWN0aW9uYDErbGlzdAQvQWNjb3JkLlN0YXRp - c3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtQmluW10CAAAAAgAAAAkIAAAABwgAAAAAAQAAAAAA - AAAELUFjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbgIAAAAL - - True @@ -286,258 +254,258 @@ - AAABAAMAEBAAAAAAIABoBAAANgAAACAgAAAAACAAqBAAAJ4EAAAwMAAAAAAgAKglAABGFQAAKAAAABAA - AAAgAAAAAQAgAAAAAABABAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wEAAAA7AAAAVQAA - AF0AAAAJ////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAtwAA - ADkAAAA/AAAAff///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ABEAAAADAAAACQAAANcAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAADVAAAAJf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAvQAAAEn///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAGwAAAM0AAACrAAAANf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAGQAAAJcAAACtAAAAlwAAAIEAAAA/////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAGUAAAAxAAAAfwAAAJ8AAAALAAAAi////wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAABlAAAAMQAAAGMAAAC7AAAADQAAAIn///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAFwAAAJkAAABtAAAA2wAAAIEAAAA9////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAZAAAAgQAAAPMAAAAx////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAAAkAAADvAAAADf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAA2wAA - AB3///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - AK8AAAAzAAAAAwAAABP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAABTAAAAaQAAADEAAADD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAAwAAAFcAAABVAAAAPf///wH///8B////Af///wEAAP//AAD//wAA//8AAP//AAD//wAA - //8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//KAAAACAAAABAAAAAAQAgAAAA - AACAEAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ABcAAABRAAAAYQAAAEcAAAAL////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAvAAAApwAAAF8AAABBAAAAfwAAAKMAAAAh////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAAI8AAAD5AAAAcwAAAAMAAAAHAAAApQAAAKkAAAAL////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAdwAAAOEAAABrAAAAA////wEAAABNAAAA5wAAAFv///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAPAAAAMQAAAA3///8B////AQAAAB0AAADhAAAAsf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ANMAAAD5AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAtwAAAP8AAAAz////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAACdAAAA/wAAAF3///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAIcAAAD/AAAAh////wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAcQAAAP8AAACdAAAAA////wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABfAAAA/wAAALsAAAAf////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAYwAAANcAAAD/AAAA9QAA - AN0AAAClAAAAK////wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACQAAAIMAAADRAAAAjQAA - AP8AAADjAAAAYwAAAKcAAADFAAAAMf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABXAAAA2QAA - AC0AAAA1AAAA8wAAAOsAAAAv////AQAAAJUAAADDAAAABf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ALcAAAB7////AQAAACsAAADjAAAA/QAAADv///8BAAAAJwAAAMsAAABB////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAA3QAAAEP///8BAAAAHwAAAM8AAAD/AAAASf///wEAAAAFAAAAsQAAAHH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAADfAAAARf///wEAAAAVAAAAvwAAAP8AAABp////AQAAAAUAAACxAAAAbf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAALcAAAB9////AQAAAAsAAACtAAAA/wAAAIH///8BAAAAKwAA - AM0AAAA5////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAATwAAANsAAAAzAAAAAwAAAKEAAAD/AAAAmwAA - AAUAAACXAAAAvwAAAAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAewAAANkAAABrAAAApQAA - AP8AAADRAAAApwAAAL8AAAAt////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAWwAA - AMUAAADrAAAA/wAAAPUAAACVAAAAJ////wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAAwAAAE8AAAD/AAAA2QAAAAX///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAHwAAAP8AAADdAAAAEf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAFAAAA/wAAAOEAAAAd////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAADfAAAA5wAAAC3///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAALcAAADtAAAAQf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAhQAA - APUAAABX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAABPAAAA7wAAAHP///8B////AQAAAA0AAAA3AAAAE////wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAABkAAADPAAAAmwAAAAf///8BAAAAZQAAAOcAAACL////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAGMAAADjAAAAH////wEAAABdAAAA9QAAAKn///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAACwAAAIEAAAChAAAAUwAAAF8AAACpAAAAN/// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAADkAAABXAAAATQAA - ABf///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAwAAAAYAAAAAEA - IAAAAAAAgCUAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAAcAAAAPAAAAEwAAABMAAAARAAAACQAAAAP///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAADAAAAHQAAAGMAAACvAAAA0QAAANUAAAC7AAAAdQAA - ACkAAAAF////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAATAAAApQAAANcAAABXAAAACQAA - AA0AAABTAAAAwwAAALsAAAA/AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABHAAAA/wAA - APEAAACNAAAAC////wH///8BAAAATQAAANcAAADBAAAAKQAAAAP///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAABtAAAA/wAAAP8AAAC/AAAAG////wH///8BAAAABwAAAKEAAAD5AAAAhQAAAAn///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAAA5AAAAxQAAANUAAACBAAAADf///wH///8B////AQAAAGcAAADnAAAA6QAA - ACf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAFAAAAPQAAAEsAAAAb////Af///wH///8B////AQAA - ADUAAADVAAAA/wAAAHX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAAA8AAADJAAAA/wAAANH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAC7AAAA/QAAAPsAAAAL////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACjAAAA+QAAAP8AAABB////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA8wAA - AP8AAABp////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAB3AAAA7wAAAP8AAACb////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAABnAAAA7QAAAP8AAAC/////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAABNAAAA5wAAAP8AAADf////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAA/AAAA5QAAAP8AAADtAAAAB/// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAxAAAA4QAA - AP8AAADxAAAANQAAAAn///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - AB0AAABjAAAA6QAAAP8AAAD5AAAAowAAAG8AAABBAAAAFf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAFAAAAPQAAAJUAAADfAAAA/QAAAP8AAAD9AAAA5wAAAOcAAADRAAAAgwAAACv///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAAAUAAABNAAAAwwAAANkAAACRAAAA6wAAAP8AAAD5AAAArQAAAGsAAACtAAAA5QAA - AKMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAADkAAAC/AAAA1wAAAGkAAAAVAAAA0QAAAP8AAAD5AAAAmQAA - AAUAAAApAAAAiwAAAOMAAACXAAAAIf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAEwAAAIUAAADjAAAAcwAAAA////8BAAAAtwAA - APsAAAD7AAAAs////wH///8BAAAAHQAAAJkAAADnAAAAWwAAAAX///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAOQAAAMUAAACrAAAAJ/// - /wH///8BAAAAoQAAAPsAAAD/AAAA0f///wH///8BAAAAAwAAAEcAAADNAAAAnQAAAB////8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAA - AOsAAAB1AAAABf///wH///8BAAAAhwAAAPcAAAD/AAAA1////wH///8B////AQAAABcAAACfAAAAzwAA - ADf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAZwAAAPUAAAD/AAAA3QAAABn///8B////AQAA - AAMAAACLAAAA6QAAAEP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAVQAAAPMAAAD/AAAA4wAA - ADf///8B////AQAAAAMAAACLAAAA5wAAAEP///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAAAPEAAAB7AAAABf///wH///8BAAAANwAA - APEAAAD/AAAA5QAAAEX///8B////AQAAABcAAAChAAAAxQAAADP///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAANwAAAMMAAACtAAAAKf// - /wH///8BAAAAGwAAAO0AAAD/AAAA6wAAAF////8BAAAAAwAAAE8AAADVAAAAlQAAABv///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAADwAA - AH0AAADnAAAAeQAAABH///8BAAAACwAAAO0AAAD/AAAA7wAAAHEAAAADAAAAIQAAAJ0AAADpAAAAWQAA - AAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAADUAAAC1AAAA2wAAAHUAAAAdAAAAAwAAAN8AAAD/AAAA9QAAAJMAAAArAAAAkQAA - AN8AAACPAAAAHf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAAUAAABJAAAAuwAAAOMAAACdAAAAZQAAANsAAAD/AAAA+wAA - ANEAAACtAAAA4QAAAJsAAAAr////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAFAAAAOQAAAIsAAADVAAAA5wAA - APcAAAD/AAAA/wAAAPcAAADDAAAAdQAAACf///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ABcAAABFAAAAaQAAALkAAAD/AAAA/wAAANUAAAA5AAAADf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAABQAAAGMAAAD/AAAA/wAAAMcAAAAJ////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////AQAAADcAAAD/AAAA/wAAAMsAAAAV////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAABUAAAD/AAAA/wAA - AM8AAAAh////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - AAMAAAD/AAAA/wAAANMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAADdAAAA/wAAANkAAAA9////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAACtAAAA/wAAAOEAAABV////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA/wAAAOUAAABl////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABTAAAA/wAA - AO8AAAB9////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAnAAAA8wAAAPcAAACX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAAAPAAAAwQAAAP0AAACtAAAABf///wH///8B////AQAAABsAAABTAAAASwAA - AAf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAHAAAAbQAAAP8AAADBAAAAIf///wH///8BAAAABwAA - AH0AAADbAAAA0wAAAEv///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAADAAAAKwAAANcAAADbAAAAVf// - /wH///8BAAAACwAAALUAAAD/AAAA/wAAAJX///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACwAA - AGkAAADvAAAAmwAAABP///8BAAAABQAAAHEAAADpAAAA/wAAAGv///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAABcAAACDAAAA4QAAAIcAAAAtAAAAGwAAAFMAAADTAAAAsQAAAB3///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAAMAAAAVAAAAWwAAAKkAAADFAAAAxwAAAKsAAABjAAAAHwAA - AAP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAAA0AAAATAAAAEwAA - AA8AAAAH////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8= - + AAABAAMAEBAAAAAAIABoBAAANgAAACAgAAAAACAAqBAAAJ4EAAAwMAAAAAAgAKglAABGFQAAKAAAABAA + AAAgAAAAAQAgAAAAAABABAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wEAAAA7AAAAVQAA + AF0AAAAJ////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAtwAA + ADkAAAA/AAAAff///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABEAAAADAAAACQAAANcAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADVAAAAJf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAvQAAAEn///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAGwAAAM0AAACrAAAANf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAGQAAAJcAAACtAAAAlwAAAIEAAAA/////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAGUAAAAxAAAAfwAAAJ8AAAALAAAAi////wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAABlAAAAMQAAAGMAAAC7AAAADQAAAIn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAFwAAAJkAAABtAAAA2wAAAIEAAAA9////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAZAAAAgQAAAPMAAAAx////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAAAkAAADvAAAADf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAA2wAA + AB3///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AK8AAAAzAAAAAwAAABP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABTAAAAaQAAADEAAADD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAAwAAAFcAAABVAAAAPf///wH///8B////Af///wEAAP//AAD//wAA//8AAP//AAD//wAA + //8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//KAAAACAAAABAAAAAAQAgAAAA + AACAEAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABcAAABRAAAAYQAAAEcAAAAL////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAvAAAApwAAAF8AAABBAAAAfwAAAKMAAAAh////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAI8AAAD5AAAAcwAAAAMAAAAHAAAApQAAAKkAAAAL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAdwAAAOEAAABrAAAAA////wEAAABNAAAA5wAAAFv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAPAAAAMQAAAA3///8B////AQAAAB0AAADhAAAAsf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ANMAAAD5AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAtwAAAP8AAAAz////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAACdAAAA/wAAAF3///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAIcAAAD/AAAAh////wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAcQAAAP8AAACdAAAAA////wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABfAAAA/wAAALsAAAAf////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAYwAAANcAAAD/AAAA9QAA + AN0AAAClAAAAK////wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACQAAAIMAAADRAAAAjQAA + AP8AAADjAAAAYwAAAKcAAADFAAAAMf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABXAAAA2QAA + AC0AAAA1AAAA8wAAAOsAAAAv////AQAAAJUAAADDAAAABf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ALcAAAB7////AQAAACsAAADjAAAA/QAAADv///8BAAAAJwAAAMsAAABB////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAA3QAAAEP///8BAAAAHwAAAM8AAAD/AAAASf///wEAAAAFAAAAsQAAAHH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADfAAAARf///wEAAAAVAAAAvwAAAP8AAABp////AQAAAAUAAACxAAAAbf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAALcAAAB9////AQAAAAsAAACtAAAA/wAAAIH///8BAAAAKwAA + AM0AAAA5////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAATwAAANsAAAAzAAAAAwAAAKEAAAD/AAAAmwAA + AAUAAACXAAAAvwAAAAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAewAAANkAAABrAAAApQAA + AP8AAADRAAAApwAAAL8AAAAt////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAWwAA + AMUAAADrAAAA/wAAAPUAAACVAAAAJ////wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAAwAAAE8AAAD/AAAA2QAAAAX///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAHwAAAP8AAADdAAAAEf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAFAAAA/wAAAOEAAAAd////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAADfAAAA5wAAAC3///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAALcAAADtAAAAQf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAhQAA + APUAAABX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABPAAAA7wAAAHP///8B////AQAAAA0AAAA3AAAAE////wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAABkAAADPAAAAmwAAAAf///8BAAAAZQAAAOcAAACL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAGMAAADjAAAAH////wEAAABdAAAA9QAAAKn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAACwAAAIEAAAChAAAAUwAAAF8AAACpAAAAN/// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAADkAAABXAAAATQAA + ABf///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAwAAAAYAAAAAEA + IAAAAAAAgCUAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAcAAAAPAAAAEwAAABMAAAARAAAACQAAAAP///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAADAAAAHQAAAGMAAACvAAAA0QAAANUAAAC7AAAAdQAA + ACkAAAAF////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAATAAAApQAAANcAAABXAAAACQAA + AA0AAABTAAAAwwAAALsAAAA/AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABHAAAA/wAA + APEAAACNAAAAC////wH///8BAAAATQAAANcAAADBAAAAKQAAAAP///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABtAAAA/wAAAP8AAAC/AAAAG////wH///8BAAAABwAAAKEAAAD5AAAAhQAAAAn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAAA5AAAAxQAAANUAAACBAAAADf///wH///8B////AQAAAGcAAADnAAAA6QAA + ACf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAFAAAAPQAAAEsAAAAb////Af///wH///8B////AQAA + ADUAAADVAAAA/wAAAHX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAA8AAADJAAAA/wAAANH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAC7AAAA/QAAAPsAAAAL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACjAAAA+QAAAP8AAABB////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA8wAA + AP8AAABp////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAB3AAAA7wAAAP8AAACb////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAABnAAAA7QAAAP8AAAC/////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAABNAAAA5wAAAP8AAADf////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAA/AAAA5QAAAP8AAADtAAAAB/// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAxAAAA4QAA + AP8AAADxAAAANQAAAAn///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AB0AAABjAAAA6QAAAP8AAAD5AAAAowAAAG8AAABBAAAAFf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAFAAAAPQAAAJUAAADfAAAA/QAAAP8AAAD9AAAA5wAAAOcAAADRAAAAgwAAACv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAAUAAABNAAAAwwAAANkAAACRAAAA6wAAAP8AAAD5AAAArQAAAGsAAACtAAAA5QAA + AKMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAADkAAAC/AAAA1wAAAGkAAAAVAAAA0QAAAP8AAAD5AAAAmQAA + AAUAAAApAAAAiwAAAOMAAACXAAAAIf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAEwAAAIUAAADjAAAAcwAAAA////8BAAAAtwAA + APsAAAD7AAAAs////wH///8BAAAAHQAAAJkAAADnAAAAWwAAAAX///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAOQAAAMUAAACrAAAAJ/// + /wH///8BAAAAoQAAAPsAAAD/AAAA0f///wH///8BAAAAAwAAAEcAAADNAAAAnQAAAB////8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAA + AOsAAAB1AAAABf///wH///8BAAAAhwAAAPcAAAD/AAAA1////wH///8B////AQAAABcAAACfAAAAzwAA + ADf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAZwAAAPUAAAD/AAAA3QAAABn///8B////AQAA + AAMAAACLAAAA6QAAAEP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAVQAAAPMAAAD/AAAA4wAA + ADf///8B////AQAAAAMAAACLAAAA5wAAAEP///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAAAPEAAAB7AAAABf///wH///8BAAAANwAA + APEAAAD/AAAA5QAAAEX///8B////AQAAABcAAAChAAAAxQAAADP///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAANwAAAMMAAACtAAAAKf// + /wH///8BAAAAGwAAAO0AAAD/AAAA6wAAAF////8BAAAAAwAAAE8AAADVAAAAlQAAABv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAADwAA + AH0AAADnAAAAeQAAABH///8BAAAACwAAAO0AAAD/AAAA7wAAAHEAAAADAAAAIQAAAJ0AAADpAAAAWQAA + AAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAADUAAAC1AAAA2wAAAHUAAAAdAAAAAwAAAN8AAAD/AAAA9QAAAJMAAAArAAAAkQAA + AN8AAACPAAAAHf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAUAAABJAAAAuwAAAOMAAACdAAAAZQAAANsAAAD/AAAA+wAA + ANEAAACtAAAA4QAAAJsAAAAr////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAFAAAAOQAAAIsAAADVAAAA5wAA + APcAAAD/AAAA/wAAAPcAAADDAAAAdQAAACf///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABcAAABFAAAAaQAAALkAAAD/AAAA/wAAANUAAAA5AAAADf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAABQAAAGMAAAD/AAAA/wAAAMcAAAAJ////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////AQAAADcAAAD/AAAA/wAAAMsAAAAV////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAABUAAAD/AAAA/wAA + AM8AAAAh////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AAMAAAD/AAAA/wAAANMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADdAAAA/wAAANkAAAA9////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAACtAAAA/wAAAOEAAABV////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA/wAAAOUAAABl////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABTAAAA/wAA + AO8AAAB9////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAnAAAA8wAAAPcAAACX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAAAPAAAAwQAAAP0AAACtAAAABf///wH///8B////AQAAABsAAABTAAAASwAA + AAf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAHAAAAbQAAAP8AAADBAAAAIf///wH///8BAAAABwAA + AH0AAADbAAAA0wAAAEv///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAADAAAAKwAAANcAAADbAAAAVf// + /wH///8BAAAACwAAALUAAAD/AAAA/wAAAJX///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACwAA + AGkAAADvAAAAmwAAABP///8BAAAABQAAAHEAAADpAAAA/wAAAGv///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAABcAAACDAAAA4QAAAIcAAAAtAAAAGwAAAFMAAADTAAAAsQAAAB3///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAMAAAAVAAAAWwAAAKkAAADFAAAAxwAAAKsAAABjAAAAHwAA + AAP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAAA0AAAATAAAAEwAA + AA8AAAAH////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8= + \ No newline at end of file diff --git a/Samples/Statistics/Analysis (LDA)/Accord.dll.config b/Samples/Statistics/Analysis (LDA)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Statistics/Analysis (LDA)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Statistics/Analysis (LDA)/Analysis (LDA).csproj b/Samples/Statistics/Analysis (LDA)/Analysis (LDA).csproj index 341e1a133..d18e1328c 100644 --- a/Samples/Statistics/Analysis (LDA)/Analysis (LDA).csproj +++ b/Samples/Statistics/Analysis (LDA)/Analysis (LDA).csproj @@ -80,10 +80,6 @@ False ..\..\..\Release\net40\Accord.Statistics.dll - - False - ..\..\..\Externals\AForge.NET\AForge.dll - 3.5 @@ -133,6 +129,9 @@ Resources.resx True + + PreserveNewest + diff --git a/Samples/Statistics/Analysis (LDA)/MainForm.resx b/Samples/Statistics/Analysis (LDA)/MainForm.resx index cbdb9e0f4..d1839514b 100644 --- a/Samples/Statistics/Analysis (LDA)/MainForm.resx +++ b/Samples/Statistics/Analysis (LDA)/MainForm.resx @@ -123,86 +123,86 @@ - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAJHSURBVDhPxZBdSNNhFMb/F110ZZEVhVBgeeHNICiiuggp - olAUyyxI0oSaH1QYC3N+tKnp5ubm1JUua5uuqdNKMwr7kApFItTUkWZqVhSVYmao5Nevvy7UoYR3HXh4 - 4XCe33nOKyy3lAY7l9RWMo0O/raWXxEyo5spVYTNvOGyfIRPfW+ptOkXqaPl6T83hcRmExSdgzAz3NVm - YWyoYla/B+1M9JtxWLPpaH22JORIjI6gKAMB0jyEimIdo4OlbuaprwVMOOMovammpDADc34qppwUrmnl - 5Kni3aFlFg2j3y1z5mnRTJccnNIltQhwq0jFry+mOXNtpWZWDx1Z1NhV3C3JwGFOw25SYjVe5oYhiUKd - HKMmwQUrMWUw/CF3NnZvvYKqUh1TvUroS3fXe7HXkwidMngTS2t5KLbregSzMY2f3Wr4qKW6LJvGR1rX - 0MLor8OhKYTJBn/GHvvxrliCTBrsOqXIoOBHh5K+hmSq7FqmexTQHuUytkaKxuNMNgYyVneA4Qd7GKjc - hjLaRzxH7gIU6JIZaEvgtk1D8wsxSWecCDgNzWFMvwxm/PkhRmr3Mli1nW9lvjRdWc0Jf+/5jzRmyWmv - S+GOLQu6U6BFjPvqKOP1AYw88WOoZif9DgmfLVtxaj1RSLdwNvrkPCA3M54KqxrnvRia9MKcGrUrqFOt - 5H7qKsqT1mGO9+Lqhc2ELdw+U/r0i+gVZ8hMiCDx3DHORwZyKnQ/hw/uYt9uCTskPvh6e7Fp41rWr/Fg - g6eHO+A/lyD8ARfG3mk9fv1YAAAAAElFTkSuQmCC - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAJHSURBVDhPxZBdSNNhFMb/F110ZZEVhVBgeeHNICiiuggp + olAUyyxI0oSaH1QYC3N+tKnp5ubm1JUua5uuqdNKMwr7kApFItTUkWZqVhSVYmao5Nevvy7UoYR3HXh4 + 4XCe33nOKyy3lAY7l9RWMo0O/raWXxEyo5spVYTNvOGyfIRPfW+ptOkXqaPl6T83hcRmExSdgzAz3NVm + YWyoYla/B+1M9JtxWLPpaH22JORIjI6gKAMB0jyEimIdo4OlbuaprwVMOOMovammpDADc34qppwUrmnl + 5Kni3aFlFg2j3y1z5mnRTJccnNIltQhwq0jFry+mOXNtpWZWDx1Z1NhV3C3JwGFOw25SYjVe5oYhiUKd + HKMmwQUrMWUw/CF3NnZvvYKqUh1TvUroS3fXe7HXkwidMngTS2t5KLbregSzMY2f3Wr4qKW6LJvGR1rX + 0MLor8OhKYTJBn/GHvvxrliCTBrsOqXIoOBHh5K+hmSq7FqmexTQHuUytkaKxuNMNgYyVneA4Qd7GKjc + hjLaRzxH7gIU6JIZaEvgtk1D8wsxSWecCDgNzWFMvwxm/PkhRmr3Mli1nW9lvjRdWc0Jf+/5jzRmyWmv + S+GOLQu6U6BFjPvqKOP1AYw88WOoZif9DgmfLVtxaj1RSLdwNvrkPCA3M54KqxrnvRia9MKcGrUrqFOt + 5H7qKsqT1mGO9+Lqhc2ELdw+U/r0i+gVZ8hMiCDx3DHORwZyKnQ/hw/uYt9uCTskPvh6e7Fp41rWr/Fg + g6eHO+A/lyD8ARfG3mk9fv1YAAAAAElFTkSuQmCC + - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAIySURBVDhPrZLfS5NRGMfff6H7boIuuq2pMZyL1eAt11CW - DcOKsB9vpFmaLtNExco0av6CbIVLJ61Wk3BSkT/AFCkRZSpZmrmiJQ41xSaCwdfznL15XEUX0Reem5f3 - 8znnec4j/Zc8fxYGla91CS3eRTx0z6OpMYS7jmnU1X6B/VYA18snUVoyjsKCt8jLHcH5c36ouCQR2NUJ - 1Nas4G9ZXlmFKbULh1Kf8lJxSfI+WeCCyopv6q+/h+DQ/DJ2WV5Ao1FgPegRAveDOS4oLfmq/h6dn/DH - 4AJizD4UXJrCAUuzEDgbZrjgou2DiohshIcnQtgme5GTPYbkJKcQ1N8OckHW2REVi+RXuM8fxGaDG4oy - ALPZIQQ11Z+5QDk1oKJ/hjv7P2FTfCMOH3mFxMQ6IbhROYWOdrCnBI4dfwPr0V4+bRoY9UzXppMjcDdS - rC8hy3YhuFI2gTYf2A4Aza4f7N2/o/zaLB8qDYx6zszwr8P7k1thNFYIweXCMXgeAfedq2xxwjClZUeV - Jd2GtDNFETiJwfs8MBjKhMCWN8pgoLoqzE8miH1GjE7G4PsZjE7OQsm9ij2mFg7rdrug1xcJAa2l4w7W - r00Cgk/n38S7wBwC04u4UGxHrMHF4CbEJtyDLj5fCDIzhljfSxzeavRgyw4Zj9t64GvvQ0d3P3pfD2Kv - 2QqNvgFxDN6urYdWmyMElJMnevh60obRktA701PRtGlg1DOdSkXwzrisaMG/RZLWAE60OMW5fNhvAAAA - AElFTkSuQmCC - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAIySURBVDhPrZLfS5NRGMfff6H7boIuuq2pMZyL1eAt11CW + DcOKsB9vpFmaLtNExco0av6CbIVLJ61Wk3BSkT/AFCkRZSpZmrmiJQ41xSaCwdfznL15XEUX0Reem5f3 + 8znnec4j/Zc8fxYGla91CS3eRTx0z6OpMYS7jmnU1X6B/VYA18snUVoyjsKCt8jLHcH5c36ouCQR2NUJ + 1Nas4G9ZXlmFKbULh1Kf8lJxSfI+WeCCyopv6q+/h+DQ/DJ2WV5Ao1FgPegRAveDOS4oLfmq/h6dn/DH + 4AJizD4UXJrCAUuzEDgbZrjgou2DiohshIcnQtgme5GTPYbkJKcQ1N8OckHW2REVi+RXuM8fxGaDG4oy + ALPZIQQ11Z+5QDk1oKJ/hjv7P2FTfCMOH3mFxMQ6IbhROYWOdrCnBI4dfwPr0V4+bRoY9UzXppMjcDdS + rC8hy3YhuFI2gTYf2A4Aza4f7N2/o/zaLB8qDYx6zszwr8P7k1thNFYIweXCMXgeAfedq2xxwjClZUeV + Jd2GtDNFETiJwfs8MBjKhMCWN8pgoLoqzE8miH1GjE7G4PsZjE7OQsm9ij2mFg7rdrug1xcJAa2l4w7W + r00Cgk/n38S7wBwC04u4UGxHrMHF4CbEJtyDLj5fCDIzhljfSxzeavRgyw4Zj9t64GvvQ0d3P3pfD2Kv + 2QqNvgFxDN6urYdWmyMElJMnevh60obRktA701PRtGlg1DOdSkXwzrisaMG/RZLWAE60OMW5fNhvAAAA + AElFTkSuQmCC + - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAJHSURBVDhPxZBdSNNhFMb/F110ZZEVhVBgeeHNICiiuggp - olAUyyxI0oSaH1QYC3N+tKnp5ubm1JUua5uuqdNKMwr7kApFItTUkWZqVhSVYmao5Nevvy7UoYR3HXh4 - 4XCe33nOKyy3lAY7l9RWMo0O/raWXxEyo5spVYTNvOGyfIRPfW+ptOkXqaPl6T83hcRmExSdgzAz3NVm - YWyoYla/B+1M9JtxWLPpaH22JORIjI6gKAMB0jyEimIdo4OlbuaprwVMOOMovammpDADc34qppwUrmnl - 5Kni3aFlFg2j3y1z5mnRTJccnNIltQhwq0jFry+mOXNtpWZWDx1Z1NhV3C3JwGFOw25SYjVe5oYhiUKd - HKMmwQUrMWUw/CF3NnZvvYKqUh1TvUroS3fXe7HXkwidMngTS2t5KLbregSzMY2f3Wr4qKW6LJvGR1rX - 0MLor8OhKYTJBn/GHvvxrliCTBrsOqXIoOBHh5K+hmSq7FqmexTQHuUytkaKxuNMNgYyVneA4Qd7GKjc - hjLaRzxH7gIU6JIZaEvgtk1D8wsxSWecCDgNzWFMvwxm/PkhRmr3Mli1nW9lvjRdWc0Jf+/5jzRmyWmv - S+GOLQu6U6BFjPvqKOP1AYw88WOoZif9DgmfLVtxaj1RSLdwNvrkPCA3M54KqxrnvRia9MKcGrUrqFOt - 5H7qKsqT1mGO9+Lqhc2ELdw+U/r0i+gVZ8hMiCDx3DHORwZyKnQ/hw/uYt9uCTskPvh6e7Fp41rWr/Fg - g6eHO+A/lyD8ARfG3mk9fv1YAAAAAElFTkSuQmCC - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAJHSURBVDhPxZBdSNNhFMb/F110ZZEVhVBgeeHNICiiuggp + olAUyyxI0oSaH1QYC3N+tKnp5ubm1JUua5uuqdNKMwr7kApFItTUkWZqVhSVYmao5Nevvy7UoYR3HXh4 + 4XCe33nOKyy3lAY7l9RWMo0O/raWXxEyo5spVYTNvOGyfIRPfW+ptOkXqaPl6T83hcRmExSdgzAz3NVm + YWyoYla/B+1M9JtxWLPpaH22JORIjI6gKAMB0jyEimIdo4OlbuaprwVMOOMovammpDADc34qppwUrmnl + 5Kni3aFlFg2j3y1z5mnRTJccnNIltQhwq0jFry+mOXNtpWZWDx1Z1NhV3C3JwGFOw25SYjVe5oYhiUKd + HKMmwQUrMWUw/CF3NnZvvYKqUh1TvUroS3fXe7HXkwidMngTS2t5KLbregSzMY2f3Wr4qKW6LJvGR1rX + 0MLor8OhKYTJBn/GHvvxrliCTBrsOqXIoOBHh5K+hmSq7FqmexTQHuUytkaKxuNMNgYyVneA4Qd7GKjc + hjLaRzxH7gIU6JIZaEvgtk1D8wsxSWecCDgNzWFMvwxm/PkhRmr3Mli1nW9lvjRdWc0Jf+/5jzRmyWmv + S+GOLQu6U6BFjPvqKOP1AYw88WOoZif9DgmfLVtxaj1RSLdwNvrkPCA3M54KqxrnvRia9MKcGrUrqFOt + 5H7qKsqT1mGO9+Lqhc2ELdw+U/r0i+gVZ8hMiCDx3DHORwZyKnQ/hw/uYt9uCTskPvh6e7Fp41rWr/Fg + g6eHO+A/lyD8ARfG3mk9fv1YAAAAAElFTkSuQmCC + - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAIySURBVDhPrZLfS5NRGMfff6H7boIuuq2pMZyL1eAt11CW - DcOKsB9vpFmaLtNExco0av6CbIVLJ61Wk3BSkT/AFCkRZSpZmrmiJQ41xSaCwdfznL15XEUX0Reem5f3 - 8znnec4j/Zc8fxYGla91CS3eRTx0z6OpMYS7jmnU1X6B/VYA18snUVoyjsKCt8jLHcH5c36ouCQR2NUJ - 1Nas4G9ZXlmFKbULh1Kf8lJxSfI+WeCCyopv6q+/h+DQ/DJ2WV5Ao1FgPegRAveDOS4oLfmq/h6dn/DH - 4AJizD4UXJrCAUuzEDgbZrjgou2DiohshIcnQtgme5GTPYbkJKcQ1N8OckHW2REVi+RXuM8fxGaDG4oy - ALPZIQQ11Z+5QDk1oKJ/hjv7P2FTfCMOH3mFxMQ6IbhROYWOdrCnBI4dfwPr0V4+bRoY9UzXppMjcDdS - rC8hy3YhuFI2gTYf2A4Aza4f7N2/o/zaLB8qDYx6zszwr8P7k1thNFYIweXCMXgeAfedq2xxwjClZUeV - Jd2GtDNFETiJwfs8MBjKhMCWN8pgoLoqzE8miH1GjE7G4PsZjE7OQsm9ij2mFg7rdrug1xcJAa2l4w7W - r00Cgk/n38S7wBwC04u4UGxHrMHF4CbEJtyDLj5fCDIzhljfSxzeavRgyw4Zj9t64GvvQ0d3P3pfD2Kv - 2QqNvgFxDN6urYdWmyMElJMnevh60obRktA701PRtGlg1DOdSkXwzrisaMG/RZLWAE60OMW5fNhvAAAA - AElFTkSuQmCC - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAIySURBVDhPrZLfS5NRGMfff6H7boIuuq2pMZyL1eAt11CW + DcOKsB9vpFmaLtNExco0av6CbIVLJ61Wk3BSkT/AFCkRZSpZmrmiJQ41xSaCwdfznL15XEUX0Reem5f3 + 8znnec4j/Zc8fxYGla91CS3eRTx0z6OpMYS7jmnU1X6B/VYA18snUVoyjsKCt8jLHcH5c36ouCQR2NUJ + 1Nas4G9ZXlmFKbULh1Kf8lJxSfI+WeCCyopv6q+/h+DQ/DJ2WV5Ao1FgPegRAveDOS4oLfmq/h6dn/DH + 4AJizD4UXJrCAUuzEDgbZrjgou2DiohshIcnQtgme5GTPYbkJKcQ1N8OckHW2REVi+RXuM8fxGaDG4oy + ALPZIQQ11Z+5QDk1oKJ/hjv7P2FTfCMOH3mFxMQ6IbhROYWOdrCnBI4dfwPr0V4+bRoY9UzXppMjcDdS + rC8hy3YhuFI2gTYf2A4Aza4f7N2/o/zaLB8qDYx6zszwr8P7k1thNFYIweXCMXgeAfedq2xxwjClZUeV + Jd2GtDNFETiJwfs8MBjKhMCWN8pgoLoqzE8miH1GjE7G4PsZjE7OQsm9ij2mFg7rdrug1xcJAa2l4w7W + r00Cgk/n38S7wBwC04u4UGxHrMHF4CbEJtyDLj5fCDIzhljfSxzeavRgyw4Zj9t64GvvQ0d3P3pfD2Kv + 2QqNvgFxDN6urYdWmyMElJMnevh60obRktA701PRtGlg1DOdSkXwzrisaMG/RZLWAE60OMW5fNhvAAAA + AElFTkSuQmCC + 435, 17 - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAJHSURBVDhPxZBdSNNhFMb/F110ZZEVhVBgeeHNICiiuggp - olAUyyxI0oSaH1QYC3N+tKnp5ubm1JUua5uuqdNKMwr7kApFItTUkWZqVhSVYmao5Nevvy7UoYR3HXh4 - 4XCe33nOKyy3lAY7l9RWMo0O/raWXxEyo5spVYTNvOGyfIRPfW+ptOkXqaPl6T83hcRmExSdgzAz3NVm - YWyoYla/B+1M9JtxWLPpaH22JORIjI6gKAMB0jyEimIdo4OlbuaprwVMOOMovammpDADc34qppwUrmnl - 5Kni3aFlFg2j3y1z5mnRTJccnNIltQhwq0jFry+mOXNtpWZWDx1Z1NhV3C3JwGFOw25SYjVe5oYhiUKd - HKMmwQUrMWUw/CF3NnZvvYKqUh1TvUroS3fXe7HXkwidMngTS2t5KLbregSzMY2f3Wr4qKW6LJvGR1rX - 0MLor8OhKYTJBn/GHvvxrliCTBrsOqXIoOBHh5K+hmSq7FqmexTQHuUytkaKxuNMNgYyVneA4Qd7GKjc - hjLaRzxH7gIU6JIZaEvgtk1D8wsxSWecCDgNzWFMvwxm/PkhRmr3Mli1nW9lvjRdWc0Jf+/5jzRmyWmv - S+GOLQu6U6BFjPvqKOP1AYw88WOoZif9DgmfLVtxaj1RSLdwNvrkPCA3M54KqxrnvRia9MKcGrUrqFOt - 5H7qKsqT1mGO9+Lqhc2ELdw+U/r0i+gVZ8hMiCDx3DHORwZyKnQ/hw/uYt9uCTskPvh6e7Fp41rWr/Fg - g6eHO+A/lyD8ARfG3mk9fv1YAAAAAElFTkSuQmCC - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAJHSURBVDhPxZBdSNNhFMb/F110ZZEVhVBgeeHNICiiuggp + olAUyyxI0oSaH1QYC3N+tKnp5ubm1JUua5uuqdNKMwr7kApFItTUkWZqVhSVYmao5Nevvy7UoYR3HXh4 + 4XCe33nOKyy3lAY7l9RWMo0O/raWXxEyo5spVYTNvOGyfIRPfW+ptOkXqaPl6T83hcRmExSdgzAz3NVm + YWyoYla/B+1M9JtxWLPpaH22JORIjI6gKAMB0jyEimIdo4OlbuaprwVMOOMovammpDADc34qppwUrmnl + 5Kni3aFlFg2j3y1z5mnRTJccnNIltQhwq0jFry+mOXNtpWZWDx1Z1NhV3C3JwGFOw25SYjVe5oYhiUKd + HKMmwQUrMWUw/CF3NnZvvYKqUh1TvUroS3fXe7HXkwidMngTS2t5KLbregSzMY2f3Wr4qKW6LJvGR1rX + 0MLor8OhKYTJBn/GHvvxrliCTBrsOqXIoOBHh5K+hmSq7FqmexTQHuUytkaKxuNMNgYyVneA4Qd7GKjc + hjLaRzxH7gIU6JIZaEvgtk1D8wsxSWecCDgNzWFMvwxm/PkhRmr3Mli1nW9lvjRdWc0Jf+/5jzRmyWmv + S+GOLQu6U6BFjPvqKOP1AYw88WOoZif9DgmfLVtxaj1RSLdwNvrkPCA3M54KqxrnvRia9MKcGrUrqFOt + 5H7qKsqT1mGO9+Lqhc2ELdw+U/r0i+gVZ8hMiCDx3DHORwZyKnQ/hw/uYt9uCTskPvh6e7Fp41rWr/Fg + g6eHO+A/lyD8ARfG3mk9fv1YAAAAAElFTkSuQmCC + True @@ -216,38 +216,6 @@ True - - - AAEAAAD/////AQAAAAAAAAAMAgAAAFVBY2NvcmQuU3RhdGlzdGljcywgVmVyc2lvbj0yLjE1LjAuMCwg - Q3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1mYTFhODhlMjk1NTVjY2Y3BQEAAAAqQWNjb3Jk - LlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtBwAAAAliaW5WYWx1ZXMJYmluUmFuZ2Vz - E2luY2x1c2l2ZVVwcGVyQm91bmQNYmluQ29sbGVjdGlvbgpjdW11bGF0aXZlBXRpdGxlBHJ1bGUHBwAE - AAEECAYBN0FjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbkNvbGxlY3Rp - b24CAAAAATJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxpemF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQIA - AAACAAAACQMAAAAJBAAAAAEJBQAAAAAGBgAAAAAF+f///zJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxp - emF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQEAAAAHdmFsdWVfXwAIAgAAAAMAAAAPAwAAAAAAAAAIDwQA - AAABAAAABgAAAAAAAAAABQUAAAA3QWNjb3JkLlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9n - cmFtQmluQ29sbGVjdGlvbgEAAAAZUmVhZE9ubHlDb2xsZWN0aW9uYDErbGlzdAQvQWNjb3JkLlN0YXRp - c3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtQmluW10CAAAAAgAAAAkIAAAABwgAAAAAAQAAAAAA - AAAELUFjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbgIAAAAL - - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAFVBY2NvcmQuU3RhdGlzdGljcywgVmVyc2lvbj0yLjE1LjAuMCwg - Q3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1mYTFhODhlMjk1NTVjY2Y3BQEAAAAqQWNjb3Jk - LlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtBwAAAAliaW5WYWx1ZXMJYmluUmFuZ2Vz - E2luY2x1c2l2ZVVwcGVyQm91bmQNYmluQ29sbGVjdGlvbgpjdW11bGF0aXZlBXRpdGxlBHJ1bGUHBwAE - AAEECAYBN0FjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbkNvbGxlY3Rp - b24CAAAAATJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxpemF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQIA - AAACAAAACQMAAAAJBAAAAAEJBQAAAAAGBgAAAAAF+f///zJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxp - emF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQEAAAAHdmFsdWVfXwAIAgAAAAMAAAAPAwAAAAAAAAAIDwQA - AAABAAAABgAAAAAAAAAABQUAAAA3QWNjb3JkLlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9n - cmFtQmluQ29sbGVjdGlvbgEAAAAZUmVhZE9ubHlDb2xsZWN0aW9uYDErbGlzdAQvQWNjb3JkLlN0YXRp - c3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtQmluW10CAAAAAgAAAAkIAAAABwgAAAAAAQAAAAAA - AAAELUFjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbgIAAAAL - - True @@ -287,38 +255,6 @@ True - - - AAEAAAD/////AQAAAAAAAAAMAgAAAFVBY2NvcmQuU3RhdGlzdGljcywgVmVyc2lvbj0yLjE1LjAuMCwg - Q3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1mYTFhODhlMjk1NTVjY2Y3BQEAAAAqQWNjb3Jk - LlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtBwAAAAliaW5WYWx1ZXMJYmluUmFuZ2Vz - E2luY2x1c2l2ZVVwcGVyQm91bmQNYmluQ29sbGVjdGlvbgpjdW11bGF0aXZlBXRpdGxlBHJ1bGUHBwAE - AAEECAYBN0FjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbkNvbGxlY3Rp - b24CAAAAATJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxpemF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQIA - AAACAAAACQMAAAAJBAAAAAEJBQAAAAAGBgAAAAAF+f///zJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxp - emF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQEAAAAHdmFsdWVfXwAIAgAAAAMAAAAPAwAAAAAAAAAIDwQA - AAABAAAABgAAAAAAAAAABQUAAAA3QWNjb3JkLlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9n - cmFtQmluQ29sbGVjdGlvbgEAAAAZUmVhZE9ubHlDb2xsZWN0aW9uYDErbGlzdAQvQWNjb3JkLlN0YXRp - c3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtQmluW10CAAAAAgAAAAkIAAAABwgAAAAAAQAAAAAA - AAAELUFjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbgIAAAAL - - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAFVBY2NvcmQuU3RhdGlzdGljcywgVmVyc2lvbj0yLjE1LjAuMCwg - Q3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1mYTFhODhlMjk1NTVjY2Y3BQEAAAAqQWNjb3Jk - LlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtBwAAAAliaW5WYWx1ZXMJYmluUmFuZ2Vz - E2luY2x1c2l2ZVVwcGVyQm91bmQNYmluQ29sbGVjdGlvbgpjdW11bGF0aXZlBXRpdGxlBHJ1bGUHBwAE - AAEECAYBN0FjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbkNvbGxlY3Rp - b24CAAAAATJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxpemF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQIA - AAACAAAACQMAAAAJBAAAAAEJBQAAAAAGBgAAAAAF+f///zJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxp - emF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQEAAAAHdmFsdWVfXwAIAgAAAAMAAAAPAwAAAAAAAAAIDwQA - AAABAAAABgAAAAAAAAAABQUAAAA3QWNjb3JkLlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9n - cmFtQmluQ29sbGVjdGlvbgEAAAAZUmVhZE9ubHlDb2xsZWN0aW9uYDErbGlzdAQvQWNjb3JkLlN0YXRp - c3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtQmluW10CAAAAAgAAAAkIAAAABwgAAAAAAQAAAAAA - AAAELUFjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbgIAAAAL - - 17, 56 @@ -327,258 +263,258 @@ - AAABAAMAEBAAAAAAIABoBAAANgAAACAgAAAAACAAqBAAAJ4EAAAwMAAAAAAgAKglAABGFQAAKAAAABAA - AAAgAAAAAQAgAAAAAABABAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wEAAAA7AAAAVQAA - AF0AAAAJ////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAtwAA - ADkAAAA/AAAAff///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ABEAAAADAAAACQAAANcAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAADVAAAAJf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAvQAAAEn///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAGwAAAM0AAACrAAAANf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAGQAAAJcAAACtAAAAlwAAAIEAAAA/////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAGUAAAAxAAAAfwAAAJ8AAAALAAAAi////wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAABlAAAAMQAAAGMAAAC7AAAADQAAAIn///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAFwAAAJkAAABtAAAA2wAAAIEAAAA9////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAZAAAAgQAAAPMAAAAx////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAAAkAAADvAAAADf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAA2wAA - AB3///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - AK8AAAAzAAAAAwAAABP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAABTAAAAaQAAADEAAADD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAAwAAAFcAAABVAAAAPf///wH///8B////Af///wEAAP//AAD//wAA//8AAP//AAD//wAA - //8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//KAAAACAAAABAAAAAAQAgAAAA - AACAEAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ABcAAABRAAAAYQAAAEcAAAAL////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAvAAAApwAAAF8AAABBAAAAfwAAAKMAAAAh////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAAI8AAAD5AAAAcwAAAAMAAAAHAAAApQAAAKkAAAAL////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAdwAAAOEAAABrAAAAA////wEAAABNAAAA5wAAAFv///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAPAAAAMQAAAA3///8B////AQAAAB0AAADhAAAAsf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ANMAAAD5AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAtwAAAP8AAAAz////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAACdAAAA/wAAAF3///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAIcAAAD/AAAAh////wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAcQAAAP8AAACdAAAAA////wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABfAAAA/wAAALsAAAAf////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAYwAAANcAAAD/AAAA9QAA - AN0AAAClAAAAK////wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACQAAAIMAAADRAAAAjQAA - AP8AAADjAAAAYwAAAKcAAADFAAAAMf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABXAAAA2QAA - AC0AAAA1AAAA8wAAAOsAAAAv////AQAAAJUAAADDAAAABf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ALcAAAB7////AQAAACsAAADjAAAA/QAAADv///8BAAAAJwAAAMsAAABB////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAA3QAAAEP///8BAAAAHwAAAM8AAAD/AAAASf///wEAAAAFAAAAsQAAAHH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAADfAAAARf///wEAAAAVAAAAvwAAAP8AAABp////AQAAAAUAAACxAAAAbf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAALcAAAB9////AQAAAAsAAACtAAAA/wAAAIH///8BAAAAKwAA - AM0AAAA5////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAATwAAANsAAAAzAAAAAwAAAKEAAAD/AAAAmwAA - AAUAAACXAAAAvwAAAAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAewAAANkAAABrAAAApQAA - AP8AAADRAAAApwAAAL8AAAAt////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAWwAA - AMUAAADrAAAA/wAAAPUAAACVAAAAJ////wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAAwAAAE8AAAD/AAAA2QAAAAX///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAHwAAAP8AAADdAAAAEf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAFAAAA/wAAAOEAAAAd////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAADfAAAA5wAAAC3///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAALcAAADtAAAAQf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAhQAA - APUAAABX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAABPAAAA7wAAAHP///8B////AQAAAA0AAAA3AAAAE////wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAABkAAADPAAAAmwAAAAf///8BAAAAZQAAAOcAAACL////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAGMAAADjAAAAH////wEAAABdAAAA9QAAAKn///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAACwAAAIEAAAChAAAAUwAAAF8AAACpAAAAN/// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAADkAAABXAAAATQAA - ABf///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAwAAAAYAAAAAEA - IAAAAAAAgCUAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAAcAAAAPAAAAEwAAABMAAAARAAAACQAAAAP///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAADAAAAHQAAAGMAAACvAAAA0QAAANUAAAC7AAAAdQAA - ACkAAAAF////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAATAAAApQAAANcAAABXAAAACQAA - AA0AAABTAAAAwwAAALsAAAA/AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABHAAAA/wAA - APEAAACNAAAAC////wH///8BAAAATQAAANcAAADBAAAAKQAAAAP///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAABtAAAA/wAAAP8AAAC/AAAAG////wH///8BAAAABwAAAKEAAAD5AAAAhQAAAAn///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAAA5AAAAxQAAANUAAACBAAAADf///wH///8B////AQAAAGcAAADnAAAA6QAA - ACf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAFAAAAPQAAAEsAAAAb////Af///wH///8B////AQAA - ADUAAADVAAAA/wAAAHX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAAA8AAADJAAAA/wAAANH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAC7AAAA/QAAAPsAAAAL////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACjAAAA+QAAAP8AAABB////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA8wAA - AP8AAABp////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAB3AAAA7wAAAP8AAACb////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAABnAAAA7QAAAP8AAAC/////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAABNAAAA5wAAAP8AAADf////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAA/AAAA5QAAAP8AAADtAAAAB/// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAxAAAA4QAA - AP8AAADxAAAANQAAAAn///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - AB0AAABjAAAA6QAAAP8AAAD5AAAAowAAAG8AAABBAAAAFf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAFAAAAPQAAAJUAAADfAAAA/QAAAP8AAAD9AAAA5wAAAOcAAADRAAAAgwAAACv///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAAAUAAABNAAAAwwAAANkAAACRAAAA6wAAAP8AAAD5AAAArQAAAGsAAACtAAAA5QAA - AKMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAADkAAAC/AAAA1wAAAGkAAAAVAAAA0QAAAP8AAAD5AAAAmQAA - AAUAAAApAAAAiwAAAOMAAACXAAAAIf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAEwAAAIUAAADjAAAAcwAAAA////8BAAAAtwAA - APsAAAD7AAAAs////wH///8BAAAAHQAAAJkAAADnAAAAWwAAAAX///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAOQAAAMUAAACrAAAAJ/// - /wH///8BAAAAoQAAAPsAAAD/AAAA0f///wH///8BAAAAAwAAAEcAAADNAAAAnQAAAB////8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAA - AOsAAAB1AAAABf///wH///8BAAAAhwAAAPcAAAD/AAAA1////wH///8B////AQAAABcAAACfAAAAzwAA - ADf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAZwAAAPUAAAD/AAAA3QAAABn///8B////AQAA - AAMAAACLAAAA6QAAAEP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAVQAAAPMAAAD/AAAA4wAA - ADf///8B////AQAAAAMAAACLAAAA5wAAAEP///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAAAPEAAAB7AAAABf///wH///8BAAAANwAA - APEAAAD/AAAA5QAAAEX///8B////AQAAABcAAAChAAAAxQAAADP///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAANwAAAMMAAACtAAAAKf// - /wH///8BAAAAGwAAAO0AAAD/AAAA6wAAAF////8BAAAAAwAAAE8AAADVAAAAlQAAABv///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAADwAA - AH0AAADnAAAAeQAAABH///8BAAAACwAAAO0AAAD/AAAA7wAAAHEAAAADAAAAIQAAAJ0AAADpAAAAWQAA - AAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAADUAAAC1AAAA2wAAAHUAAAAdAAAAAwAAAN8AAAD/AAAA9QAAAJMAAAArAAAAkQAA - AN8AAACPAAAAHf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAAUAAABJAAAAuwAAAOMAAACdAAAAZQAAANsAAAD/AAAA+wAA - ANEAAACtAAAA4QAAAJsAAAAr////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAFAAAAOQAAAIsAAADVAAAA5wAA - APcAAAD/AAAA/wAAAPcAAADDAAAAdQAAACf///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ABcAAABFAAAAaQAAALkAAAD/AAAA/wAAANUAAAA5AAAADf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAABQAAAGMAAAD/AAAA/wAAAMcAAAAJ////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////AQAAADcAAAD/AAAA/wAAAMsAAAAV////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAABUAAAD/AAAA/wAA - AM8AAAAh////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - AAMAAAD/AAAA/wAAANMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAADdAAAA/wAAANkAAAA9////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAACtAAAA/wAAAOEAAABV////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA/wAAAOUAAABl////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABTAAAA/wAA - AO8AAAB9////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAnAAAA8wAAAPcAAACX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAAAPAAAAwQAAAP0AAACtAAAABf///wH///8B////AQAAABsAAABTAAAASwAA - AAf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAHAAAAbQAAAP8AAADBAAAAIf///wH///8BAAAABwAA - AH0AAADbAAAA0wAAAEv///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAADAAAAKwAAANcAAADbAAAAVf// - /wH///8BAAAACwAAALUAAAD/AAAA/wAAAJX///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACwAA - AGkAAADvAAAAmwAAABP///8BAAAABQAAAHEAAADpAAAA/wAAAGv///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAABcAAACDAAAA4QAAAIcAAAAtAAAAGwAAAFMAAADTAAAAsQAAAB3///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAAMAAAAVAAAAWwAAAKkAAADFAAAAxwAAAKsAAABjAAAAHwAA - AAP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAAA0AAAATAAAAEwAA - AA8AAAAH////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8= - + AAABAAMAEBAAAAAAIABoBAAANgAAACAgAAAAACAAqBAAAJ4EAAAwMAAAAAAgAKglAABGFQAAKAAAABAA + AAAgAAAAAQAgAAAAAABABAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wEAAAA7AAAAVQAA + AF0AAAAJ////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAtwAA + ADkAAAA/AAAAff///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABEAAAADAAAACQAAANcAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADVAAAAJf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAvQAAAEn///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAGwAAAM0AAACrAAAANf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAGQAAAJcAAACtAAAAlwAAAIEAAAA/////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAGUAAAAxAAAAfwAAAJ8AAAALAAAAi////wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAABlAAAAMQAAAGMAAAC7AAAADQAAAIn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAFwAAAJkAAABtAAAA2wAAAIEAAAA9////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAZAAAAgQAAAPMAAAAx////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAAAkAAADvAAAADf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAA2wAA + AB3///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AK8AAAAzAAAAAwAAABP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABTAAAAaQAAADEAAADD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAAwAAAFcAAABVAAAAPf///wH///8B////Af///wEAAP//AAD//wAA//8AAP//AAD//wAA + //8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//KAAAACAAAABAAAAAAQAgAAAA + AACAEAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABcAAABRAAAAYQAAAEcAAAAL////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAvAAAApwAAAF8AAABBAAAAfwAAAKMAAAAh////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAI8AAAD5AAAAcwAAAAMAAAAHAAAApQAAAKkAAAAL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAdwAAAOEAAABrAAAAA////wEAAABNAAAA5wAAAFv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAPAAAAMQAAAA3///8B////AQAAAB0AAADhAAAAsf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ANMAAAD5AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAtwAAAP8AAAAz////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAACdAAAA/wAAAF3///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAIcAAAD/AAAAh////wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAcQAAAP8AAACdAAAAA////wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABfAAAA/wAAALsAAAAf////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAYwAAANcAAAD/AAAA9QAA + AN0AAAClAAAAK////wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACQAAAIMAAADRAAAAjQAA + AP8AAADjAAAAYwAAAKcAAADFAAAAMf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABXAAAA2QAA + AC0AAAA1AAAA8wAAAOsAAAAv////AQAAAJUAAADDAAAABf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ALcAAAB7////AQAAACsAAADjAAAA/QAAADv///8BAAAAJwAAAMsAAABB////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAA3QAAAEP///8BAAAAHwAAAM8AAAD/AAAASf///wEAAAAFAAAAsQAAAHH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADfAAAARf///wEAAAAVAAAAvwAAAP8AAABp////AQAAAAUAAACxAAAAbf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAALcAAAB9////AQAAAAsAAACtAAAA/wAAAIH///8BAAAAKwAA + AM0AAAA5////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAATwAAANsAAAAzAAAAAwAAAKEAAAD/AAAAmwAA + AAUAAACXAAAAvwAAAAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAewAAANkAAABrAAAApQAA + AP8AAADRAAAApwAAAL8AAAAt////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAWwAA + AMUAAADrAAAA/wAAAPUAAACVAAAAJ////wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAAwAAAE8AAAD/AAAA2QAAAAX///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAHwAAAP8AAADdAAAAEf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAFAAAA/wAAAOEAAAAd////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAADfAAAA5wAAAC3///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAALcAAADtAAAAQf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAhQAA + APUAAABX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABPAAAA7wAAAHP///8B////AQAAAA0AAAA3AAAAE////wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAABkAAADPAAAAmwAAAAf///8BAAAAZQAAAOcAAACL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAGMAAADjAAAAH////wEAAABdAAAA9QAAAKn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAACwAAAIEAAAChAAAAUwAAAF8AAACpAAAAN/// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAADkAAABXAAAATQAA + ABf///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAwAAAAYAAAAAEA + IAAAAAAAgCUAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAcAAAAPAAAAEwAAABMAAAARAAAACQAAAAP///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAADAAAAHQAAAGMAAACvAAAA0QAAANUAAAC7AAAAdQAA + ACkAAAAF////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAATAAAApQAAANcAAABXAAAACQAA + AA0AAABTAAAAwwAAALsAAAA/AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABHAAAA/wAA + APEAAACNAAAAC////wH///8BAAAATQAAANcAAADBAAAAKQAAAAP///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABtAAAA/wAAAP8AAAC/AAAAG////wH///8BAAAABwAAAKEAAAD5AAAAhQAAAAn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAAA5AAAAxQAAANUAAACBAAAADf///wH///8B////AQAAAGcAAADnAAAA6QAA + ACf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAFAAAAPQAAAEsAAAAb////Af///wH///8B////AQAA + ADUAAADVAAAA/wAAAHX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAA8AAADJAAAA/wAAANH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAC7AAAA/QAAAPsAAAAL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACjAAAA+QAAAP8AAABB////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA8wAA + AP8AAABp////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAB3AAAA7wAAAP8AAACb////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAABnAAAA7QAAAP8AAAC/////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAABNAAAA5wAAAP8AAADf////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAA/AAAA5QAAAP8AAADtAAAAB/// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAxAAAA4QAA + AP8AAADxAAAANQAAAAn///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AB0AAABjAAAA6QAAAP8AAAD5AAAAowAAAG8AAABBAAAAFf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAFAAAAPQAAAJUAAADfAAAA/QAAAP8AAAD9AAAA5wAAAOcAAADRAAAAgwAAACv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAAUAAABNAAAAwwAAANkAAACRAAAA6wAAAP8AAAD5AAAArQAAAGsAAACtAAAA5QAA + AKMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAADkAAAC/AAAA1wAAAGkAAAAVAAAA0QAAAP8AAAD5AAAAmQAA + AAUAAAApAAAAiwAAAOMAAACXAAAAIf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAEwAAAIUAAADjAAAAcwAAAA////8BAAAAtwAA + APsAAAD7AAAAs////wH///8BAAAAHQAAAJkAAADnAAAAWwAAAAX///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAOQAAAMUAAACrAAAAJ/// + /wH///8BAAAAoQAAAPsAAAD/AAAA0f///wH///8BAAAAAwAAAEcAAADNAAAAnQAAAB////8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAA + AOsAAAB1AAAABf///wH///8BAAAAhwAAAPcAAAD/AAAA1////wH///8B////AQAAABcAAACfAAAAzwAA + ADf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAZwAAAPUAAAD/AAAA3QAAABn///8B////AQAA + AAMAAACLAAAA6QAAAEP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAVQAAAPMAAAD/AAAA4wAA + ADf///8B////AQAAAAMAAACLAAAA5wAAAEP///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAAAPEAAAB7AAAABf///wH///8BAAAANwAA + APEAAAD/AAAA5QAAAEX///8B////AQAAABcAAAChAAAAxQAAADP///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAANwAAAMMAAACtAAAAKf// + /wH///8BAAAAGwAAAO0AAAD/AAAA6wAAAF////8BAAAAAwAAAE8AAADVAAAAlQAAABv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAADwAA + AH0AAADnAAAAeQAAABH///8BAAAACwAAAO0AAAD/AAAA7wAAAHEAAAADAAAAIQAAAJ0AAADpAAAAWQAA + AAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAADUAAAC1AAAA2wAAAHUAAAAdAAAAAwAAAN8AAAD/AAAA9QAAAJMAAAArAAAAkQAA + AN8AAACPAAAAHf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAUAAABJAAAAuwAAAOMAAACdAAAAZQAAANsAAAD/AAAA+wAA + ANEAAACtAAAA4QAAAJsAAAAr////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAFAAAAOQAAAIsAAADVAAAA5wAA + APcAAAD/AAAA/wAAAPcAAADDAAAAdQAAACf///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABcAAABFAAAAaQAAALkAAAD/AAAA/wAAANUAAAA5AAAADf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAABQAAAGMAAAD/AAAA/wAAAMcAAAAJ////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////AQAAADcAAAD/AAAA/wAAAMsAAAAV////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAABUAAAD/AAAA/wAA + AM8AAAAh////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AAMAAAD/AAAA/wAAANMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADdAAAA/wAAANkAAAA9////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAACtAAAA/wAAAOEAAABV////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA/wAAAOUAAABl////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABTAAAA/wAA + AO8AAAB9////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAnAAAA8wAAAPcAAACX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAAAPAAAAwQAAAP0AAACtAAAABf///wH///8B////AQAAABsAAABTAAAASwAA + AAf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAHAAAAbQAAAP8AAADBAAAAIf///wH///8BAAAABwAA + AH0AAADbAAAA0wAAAEv///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAADAAAAKwAAANcAAADbAAAAVf// + /wH///8BAAAACwAAALUAAAD/AAAA/wAAAJX///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACwAA + AGkAAADvAAAAmwAAABP///8BAAAABQAAAHEAAADpAAAA/wAAAGv///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAABcAAACDAAAA4QAAAIcAAAAtAAAAGwAAAFMAAADTAAAAsQAAAB3///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAMAAAAVAAAAWwAAAKkAAADFAAAAxwAAAKsAAABjAAAAHwAA + AAP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAAA0AAAATAAAAEwAA + AA8AAAAH////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8= + \ No newline at end of file diff --git a/Samples/Statistics/Analysis (PCA)/Accord.dll.config b/Samples/Statistics/Analysis (PCA)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Statistics/Analysis (PCA)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Statistics/Analysis (PCA)/Analysis (PCA).csproj b/Samples/Statistics/Analysis (PCA)/Analysis (PCA).csproj index 8c1dd700c..70a2c66af 100644 --- a/Samples/Statistics/Analysis (PCA)/Analysis (PCA).csproj +++ b/Samples/Statistics/Analysis (PCA)/Analysis (PCA).csproj @@ -80,14 +80,6 @@ False ..\..\..\Release\net40\Accord.Statistics.dll - - False - ..\..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Math.dll - 3.5 @@ -131,6 +123,9 @@ Resources.resx True + + PreserveNewest + diff --git a/Samples/Statistics/Analysis (PCA)/MainForm.resx b/Samples/Statistics/Analysis (PCA)/MainForm.resx index 0278df806..01c459993 100644 --- a/Samples/Statistics/Analysis (PCA)/MainForm.resx +++ b/Samples/Statistics/Analysis (PCA)/MainForm.resx @@ -123,35 +123,35 @@ - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAJHSURBVDhPxZBdSNNhFMb/F110ZZEVhVBgeeHNICiiuggp - olAUyyxI0oSaH1QYC3N+tKnp5ubm1JUua5uuqdNKMwr7kApFItTUkWZqVhSVYmao5Nevvy7UoYR3HXh4 - 4XCe33nOKyy3lAY7l9RWMo0O/raWXxEyo5spVYTNvOGyfIRPfW+ptOkXqaPl6T83hcRmExSdgzAz3NVm - YWyoYla/B+1M9JtxWLPpaH22JORIjI6gKAMB0jyEimIdo4OlbuaprwVMOOMovammpDADc34qppwUrmnl - 5Kni3aFlFg2j3y1z5mnRTJccnNIltQhwq0jFry+mOXNtpWZWDx1Z1NhV3C3JwGFOw25SYjVe5oYhiUKd - HKMmwQUrMWUw/CF3NnZvvYKqUh1TvUroS3fXe7HXkwidMngTS2t5KLbregSzMY2f3Wr4qKW6LJvGR1rX - 0MLor8OhKYTJBn/GHvvxrliCTBrsOqXIoOBHh5K+hmSq7FqmexTQHuUytkaKxuNMNgYyVneA4Qd7GKjc - hjLaRzxH7gIU6JIZaEvgtk1D8wsxSWecCDgNzWFMvwxm/PkhRmr3Mli1nW9lvjRdWc0Jf+/5jzRmyWmv - S+GOLQu6U6BFjPvqKOP1AYw88WOoZif9DgmfLVtxaj1RSLdwNvrkPCA3M54KqxrnvRia9MKcGrUrqFOt - 5H7qKsqT1mGO9+Lqhc2ELdw+U/r0i+gVZ8hMiCDx3DHORwZyKnQ/hw/uYt9uCTskPvh6e7Fp41rWr/Fg - g6eHO+A/lyD8ARfG3mk9fv1YAAAAAElFTkSuQmCC - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAJHSURBVDhPxZBdSNNhFMb/F110ZZEVhVBgeeHNICiiuggp + olAUyyxI0oSaH1QYC3N+tKnp5ubm1JUua5uuqdNKMwr7kApFItTUkWZqVhSVYmao5Nevvy7UoYR3HXh4 + 4XCe33nOKyy3lAY7l9RWMo0O/raWXxEyo5spVYTNvOGyfIRPfW+ptOkXqaPl6T83hcRmExSdgzAz3NVm + YWyoYla/B+1M9JtxWLPpaH22JORIjI6gKAMB0jyEimIdo4OlbuaprwVMOOMovammpDADc34qppwUrmnl + 5Kni3aFlFg2j3y1z5mnRTJccnNIltQhwq0jFry+mOXNtpWZWDx1Z1NhV3C3JwGFOw25SYjVe5oYhiUKd + HKMmwQUrMWUw/CF3NnZvvYKqUh1TvUroS3fXe7HXkwidMngTS2t5KLbregSzMY2f3Wr4qKW6LJvGR1rX + 0MLor8OhKYTJBn/GHvvxrliCTBrsOqXIoOBHh5K+hmSq7FqmexTQHuUytkaKxuNMNgYyVneA4Qd7GKjc + hjLaRzxH7gIU6JIZaEvgtk1D8wsxSWecCDgNzWFMvwxm/PkhRmr3Mli1nW9lvjRdWc0Jf+/5jzRmyWmv + S+GOLQu6U6BFjPvqKOP1AYw88WOoZif9DgmfLVtxaj1RSLdwNvrkPCA3M54KqxrnvRia9MKcGrUrqFOt + 5H7qKsqT1mGO9+Lqhc2ELdw+U/r0i+gVZ8hMiCDx3DHORwZyKnQ/hw/uYt9uCTskPvh6e7Fp41rWr/Fg + g6eHO+A/lyD8ARfG3mk9fv1YAAAAAElFTkSuQmCC + - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAIySURBVDhPrZLfS5NRGMfff6H7boIuuq2pMZyL1eAt11CW - DcOKsB9vpFmaLtNExco0av6CbIVLJ61Wk3BSkT/AFCkRZSpZmrmiJQ41xSaCwdfznL15XEUX0Reem5f3 - 8znnec4j/Zc8fxYGla91CS3eRTx0z6OpMYS7jmnU1X6B/VYA18snUVoyjsKCt8jLHcH5c36ouCQR2NUJ - 1Nas4G9ZXlmFKbULh1Kf8lJxSfI+WeCCyopv6q+/h+DQ/DJ2WV5Ao1FgPegRAveDOS4oLfmq/h6dn/DH - 4AJizD4UXJrCAUuzEDgbZrjgou2DiohshIcnQtgme5GTPYbkJKcQ1N8OckHW2REVi+RXuM8fxGaDG4oy - ALPZIQQ11Z+5QDk1oKJ/hjv7P2FTfCMOH3mFxMQ6IbhROYWOdrCnBI4dfwPr0V4+bRoY9UzXppMjcDdS - rC8hy3YhuFI2gTYf2A4Aza4f7N2/o/zaLB8qDYx6zszwr8P7k1thNFYIweXCMXgeAfedq2xxwjClZUeV - Jd2GtDNFETiJwfs8MBjKhMCWN8pgoLoqzE8miH1GjE7G4PsZjE7OQsm9ij2mFg7rdrug1xcJAa2l4w7W - r00Cgk/n38S7wBwC04u4UGxHrMHF4CbEJtyDLj5fCDIzhljfSxzeavRgyw4Zj9t64GvvQ0d3P3pfD2Kv - 2QqNvgFxDN6urYdWmyMElJMnevh60obRktA701PRtGlg1DOdSkXwzrisaMG/RZLWAE60OMW5fNhvAAAA - AElFTkSuQmCC - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAIySURBVDhPrZLfS5NRGMfff6H7boIuuq2pMZyL1eAt11CW + DcOKsB9vpFmaLtNExco0av6CbIVLJ61Wk3BSkT/AFCkRZSpZmrmiJQ41xSaCwdfznL15XEUX0Reem5f3 + 8znnec4j/Zc8fxYGla91CS3eRTx0z6OpMYS7jmnU1X6B/VYA18snUVoyjsKCt8jLHcH5c36ouCQR2NUJ + 1Nas4G9ZXlmFKbULh1Kf8lJxSfI+WeCCyopv6q+/h+DQ/DJ2WV5Ao1FgPegRAveDOS4oLfmq/h6dn/DH + 4AJizD4UXJrCAUuzEDgbZrjgou2DiohshIcnQtgme5GTPYbkJKcQ1N8OckHW2REVi+RXuM8fxGaDG4oy + ALPZIQQ11Z+5QDk1oKJ/hjv7P2FTfCMOH3mFxMQ6IbhROYWOdrCnBI4dfwPr0V4+bRoY9UzXppMjcDdS + rC8hy3YhuFI2gTYf2A4Aza4f7N2/o/zaLB8qDYx6zszwr8P7k1thNFYIweXCMXgeAfedq2xxwjClZUeV + Jd2GtDNFETiJwfs8MBjKhMCWN8pgoLoqzE8miH1GjE7G4PsZjE7OQsm9ij2mFg7rdrug1xcJAa2l4w7W + r00Cgk/n38S7wBwC04u4UGxHrMHF4CbEJtyDLj5fCDIzhljfSxzeavRgyw4Zj9t64GvvQ0d3P3pfD2Kv + 2QqNvgFxDN6urYdWmyMElJMnevh60obRktA701PRtGlg1DOdSkXwzrisaMG/RZLWAE60OMW5fNhvAAAA + AElFTkSuQmCC + True @@ -183,38 +183,6 @@ True - - - AAEAAAD/////AQAAAAAAAAAMAgAAAFVBY2NvcmQuU3RhdGlzdGljcywgVmVyc2lvbj0yLjE1LjAuMCwg - Q3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1mYTFhODhlMjk1NTVjY2Y3BQEAAAAqQWNjb3Jk - LlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtBwAAAAliaW5WYWx1ZXMJYmluUmFuZ2Vz - E2luY2x1c2l2ZVVwcGVyQm91bmQNYmluQ29sbGVjdGlvbgpjdW11bGF0aXZlBXRpdGxlBHJ1bGUHBwAE - AAEECAYBN0FjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbkNvbGxlY3Rp - b24CAAAAATJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxpemF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQIA - AAACAAAACQMAAAAJBAAAAAEJBQAAAAAGBgAAAAAF+f///zJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxp - emF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQEAAAAHdmFsdWVfXwAIAgAAAAMAAAAPAwAAAAAAAAAIDwQA - AAABAAAABgAAAAAAAAAABQUAAAA3QWNjb3JkLlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9n - cmFtQmluQ29sbGVjdGlvbgEAAAAZUmVhZE9ubHlDb2xsZWN0aW9uYDErbGlzdAQvQWNjb3JkLlN0YXRp - c3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtQmluW10CAAAAAgAAAAkIAAAABwgAAAAAAQAAAAAA - AAAELUFjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbgIAAAAL - - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAFVBY2NvcmQuU3RhdGlzdGljcywgVmVyc2lvbj0yLjE1LjAuMCwg - Q3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1mYTFhODhlMjk1NTVjY2Y3BQEAAAAqQWNjb3Jk - LlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtBwAAAAliaW5WYWx1ZXMJYmluUmFuZ2Vz - E2luY2x1c2l2ZVVwcGVyQm91bmQNYmluQ29sbGVjdGlvbgpjdW11bGF0aXZlBXRpdGxlBHJ1bGUHBwAE - AAEECAYBN0FjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbkNvbGxlY3Rp - b24CAAAAATJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxpemF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQIA - AAACAAAACQMAAAAJBAAAAAEJBQAAAAAGBgAAAAAF+f///zJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxp - emF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQEAAAAHdmFsdWVfXwAIAgAAAAMAAAAPAwAAAAAAAAAIDwQA - AAABAAAABgAAAAAAAAAABQUAAAA3QWNjb3JkLlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9n - cmFtQmluQ29sbGVjdGlvbgEAAAAZUmVhZE9ubHlDb2xsZWN0aW9uYDErbGlzdAQvQWNjb3JkLlN0YXRp - c3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtQmluW10CAAAAAgAAAAkIAAAABwgAAAAAAQAAAAAA - AAAELUFjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbgIAAAAL - - True @@ -247,258 +215,258 @@ - AAABAAMAEBAAAAAAIABoBAAANgAAACAgAAAAACAAqBAAAJ4EAAAwMAAAAAAgAKglAABGFQAAKAAAABAA - AAAgAAAAAQAgAAAAAABABAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wEAAAA7AAAAVQAA - AF0AAAAJ////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAtwAA - ADkAAAA/AAAAff///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ABEAAAADAAAACQAAANcAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAADVAAAAJf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAvQAAAEn///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAGwAAAM0AAACrAAAANf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAGQAAAJcAAACtAAAAlwAAAIEAAAA/////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAGUAAAAxAAAAfwAAAJ8AAAALAAAAi////wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAABlAAAAMQAAAGMAAAC7AAAADQAAAIn///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAFwAAAJkAAABtAAAA2wAAAIEAAAA9////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAZAAAAgQAAAPMAAAAx////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAAAkAAADvAAAADf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAA2wAA - AB3///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - AK8AAAAzAAAAAwAAABP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAABTAAAAaQAAADEAAADD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAAwAAAFcAAABVAAAAPf///wH///8B////Af///wEAAP//AAD//wAA//8AAP//AAD//wAA - //8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//KAAAACAAAABAAAAAAQAgAAAA - AACAEAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ABcAAABRAAAAYQAAAEcAAAAL////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAvAAAApwAAAF8AAABBAAAAfwAAAKMAAAAh////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAAI8AAAD5AAAAcwAAAAMAAAAHAAAApQAAAKkAAAAL////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAdwAAAOEAAABrAAAAA////wEAAABNAAAA5wAAAFv///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAPAAAAMQAAAA3///8B////AQAAAB0AAADhAAAAsf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ANMAAAD5AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAtwAAAP8AAAAz////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAACdAAAA/wAAAF3///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAIcAAAD/AAAAh////wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAcQAAAP8AAACdAAAAA////wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABfAAAA/wAAALsAAAAf////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAYwAAANcAAAD/AAAA9QAA - AN0AAAClAAAAK////wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACQAAAIMAAADRAAAAjQAA - AP8AAADjAAAAYwAAAKcAAADFAAAAMf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABXAAAA2QAA - AC0AAAA1AAAA8wAAAOsAAAAv////AQAAAJUAAADDAAAABf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ALcAAAB7////AQAAACsAAADjAAAA/QAAADv///8BAAAAJwAAAMsAAABB////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAA3QAAAEP///8BAAAAHwAAAM8AAAD/AAAASf///wEAAAAFAAAAsQAAAHH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAADfAAAARf///wEAAAAVAAAAvwAAAP8AAABp////AQAAAAUAAACxAAAAbf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAALcAAAB9////AQAAAAsAAACtAAAA/wAAAIH///8BAAAAKwAA - AM0AAAA5////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAATwAAANsAAAAzAAAAAwAAAKEAAAD/AAAAmwAA - AAUAAACXAAAAvwAAAAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAewAAANkAAABrAAAApQAA - AP8AAADRAAAApwAAAL8AAAAt////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAWwAA - AMUAAADrAAAA/wAAAPUAAACVAAAAJ////wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAAwAAAE8AAAD/AAAA2QAAAAX///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAHwAAAP8AAADdAAAAEf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAFAAAA/wAAAOEAAAAd////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAADfAAAA5wAAAC3///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAALcAAADtAAAAQf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAhQAA - APUAAABX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAABPAAAA7wAAAHP///8B////AQAAAA0AAAA3AAAAE////wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAABkAAADPAAAAmwAAAAf///8BAAAAZQAAAOcAAACL////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAGMAAADjAAAAH////wEAAABdAAAA9QAAAKn///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAACwAAAIEAAAChAAAAUwAAAF8AAACpAAAAN/// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAADkAAABXAAAATQAA - ABf///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAwAAAAYAAAAAEA - IAAAAAAAgCUAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAAcAAAAPAAAAEwAAABMAAAARAAAACQAAAAP///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAADAAAAHQAAAGMAAACvAAAA0QAAANUAAAC7AAAAdQAA - ACkAAAAF////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAATAAAApQAAANcAAABXAAAACQAA - AA0AAABTAAAAwwAAALsAAAA/AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABHAAAA/wAA - APEAAACNAAAAC////wH///8BAAAATQAAANcAAADBAAAAKQAAAAP///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAABtAAAA/wAAAP8AAAC/AAAAG////wH///8BAAAABwAAAKEAAAD5AAAAhQAAAAn///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAAA5AAAAxQAAANUAAACBAAAADf///wH///8B////AQAAAGcAAADnAAAA6QAA - ACf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAFAAAAPQAAAEsAAAAb////Af///wH///8B////AQAA - ADUAAADVAAAA/wAAAHX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAAA8AAADJAAAA/wAAANH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAC7AAAA/QAAAPsAAAAL////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACjAAAA+QAAAP8AAABB////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA8wAA - AP8AAABp////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAB3AAAA7wAAAP8AAACb////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAABnAAAA7QAAAP8AAAC/////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAABNAAAA5wAAAP8AAADf////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAA/AAAA5QAAAP8AAADtAAAAB/// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAxAAAA4QAA - AP8AAADxAAAANQAAAAn///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - AB0AAABjAAAA6QAAAP8AAAD5AAAAowAAAG8AAABBAAAAFf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAFAAAAPQAAAJUAAADfAAAA/QAAAP8AAAD9AAAA5wAAAOcAAADRAAAAgwAAACv///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAAAUAAABNAAAAwwAAANkAAACRAAAA6wAAAP8AAAD5AAAArQAAAGsAAACtAAAA5QAA - AKMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAADkAAAC/AAAA1wAAAGkAAAAVAAAA0QAAAP8AAAD5AAAAmQAA - AAUAAAApAAAAiwAAAOMAAACXAAAAIf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAEwAAAIUAAADjAAAAcwAAAA////8BAAAAtwAA - APsAAAD7AAAAs////wH///8BAAAAHQAAAJkAAADnAAAAWwAAAAX///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAOQAAAMUAAACrAAAAJ/// - /wH///8BAAAAoQAAAPsAAAD/AAAA0f///wH///8BAAAAAwAAAEcAAADNAAAAnQAAAB////8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAA - AOsAAAB1AAAABf///wH///8BAAAAhwAAAPcAAAD/AAAA1////wH///8B////AQAAABcAAACfAAAAzwAA - ADf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAZwAAAPUAAAD/AAAA3QAAABn///8B////AQAA - AAMAAACLAAAA6QAAAEP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAVQAAAPMAAAD/AAAA4wAA - ADf///8B////AQAAAAMAAACLAAAA5wAAAEP///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAAAPEAAAB7AAAABf///wH///8BAAAANwAA - APEAAAD/AAAA5QAAAEX///8B////AQAAABcAAAChAAAAxQAAADP///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAANwAAAMMAAACtAAAAKf// - /wH///8BAAAAGwAAAO0AAAD/AAAA6wAAAF////8BAAAAAwAAAE8AAADVAAAAlQAAABv///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAADwAA - AH0AAADnAAAAeQAAABH///8BAAAACwAAAO0AAAD/AAAA7wAAAHEAAAADAAAAIQAAAJ0AAADpAAAAWQAA - AAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAADUAAAC1AAAA2wAAAHUAAAAdAAAAAwAAAN8AAAD/AAAA9QAAAJMAAAArAAAAkQAA - AN8AAACPAAAAHf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAAUAAABJAAAAuwAAAOMAAACdAAAAZQAAANsAAAD/AAAA+wAA - ANEAAACtAAAA4QAAAJsAAAAr////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAFAAAAOQAAAIsAAADVAAAA5wAA - APcAAAD/AAAA/wAAAPcAAADDAAAAdQAAACf///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ABcAAABFAAAAaQAAALkAAAD/AAAA/wAAANUAAAA5AAAADf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAABQAAAGMAAAD/AAAA/wAAAMcAAAAJ////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////AQAAADcAAAD/AAAA/wAAAMsAAAAV////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAABUAAAD/AAAA/wAA - AM8AAAAh////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - AAMAAAD/AAAA/wAAANMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAADdAAAA/wAAANkAAAA9////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAACtAAAA/wAAAOEAAABV////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA/wAAAOUAAABl////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABTAAAA/wAA - AO8AAAB9////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAnAAAA8wAAAPcAAACX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAAAPAAAAwQAAAP0AAACtAAAABf///wH///8B////AQAAABsAAABTAAAASwAA - AAf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAHAAAAbQAAAP8AAADBAAAAIf///wH///8BAAAABwAA - AH0AAADbAAAA0wAAAEv///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAADAAAAKwAAANcAAADbAAAAVf// - /wH///8BAAAACwAAALUAAAD/AAAA/wAAAJX///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACwAA - AGkAAADvAAAAmwAAABP///8BAAAABQAAAHEAAADpAAAA/wAAAGv///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAABcAAACDAAAA4QAAAIcAAAAtAAAAGwAAAFMAAADTAAAAsQAAAB3///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAAMAAAAVAAAAWwAAAKkAAADFAAAAxwAAAKsAAABjAAAAHwAA - AAP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAAA0AAAATAAAAEwAA - AA8AAAAH////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8= - + AAABAAMAEBAAAAAAIABoBAAANgAAACAgAAAAACAAqBAAAJ4EAAAwMAAAAAAgAKglAABGFQAAKAAAABAA + AAAgAAAAAQAgAAAAAABABAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wEAAAA7AAAAVQAA + AF0AAAAJ////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAtwAA + ADkAAAA/AAAAff///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABEAAAADAAAACQAAANcAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADVAAAAJf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAvQAAAEn///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAGwAAAM0AAACrAAAANf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAGQAAAJcAAACtAAAAlwAAAIEAAAA/////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAGUAAAAxAAAAfwAAAJ8AAAALAAAAi////wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAABlAAAAMQAAAGMAAAC7AAAADQAAAIn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAFwAAAJkAAABtAAAA2wAAAIEAAAA9////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAZAAAAgQAAAPMAAAAx////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAAAkAAADvAAAADf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAA2wAA + AB3///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AK8AAAAzAAAAAwAAABP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABTAAAAaQAAADEAAADD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAAwAAAFcAAABVAAAAPf///wH///8B////Af///wEAAP//AAD//wAA//8AAP//AAD//wAA + //8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//KAAAACAAAABAAAAAAQAgAAAA + AACAEAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABcAAABRAAAAYQAAAEcAAAAL////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAvAAAApwAAAF8AAABBAAAAfwAAAKMAAAAh////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAI8AAAD5AAAAcwAAAAMAAAAHAAAApQAAAKkAAAAL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAdwAAAOEAAABrAAAAA////wEAAABNAAAA5wAAAFv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAPAAAAMQAAAA3///8B////AQAAAB0AAADhAAAAsf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ANMAAAD5AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAtwAAAP8AAAAz////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAACdAAAA/wAAAF3///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAIcAAAD/AAAAh////wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAcQAAAP8AAACdAAAAA////wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABfAAAA/wAAALsAAAAf////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAYwAAANcAAAD/AAAA9QAA + AN0AAAClAAAAK////wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACQAAAIMAAADRAAAAjQAA + AP8AAADjAAAAYwAAAKcAAADFAAAAMf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABXAAAA2QAA + AC0AAAA1AAAA8wAAAOsAAAAv////AQAAAJUAAADDAAAABf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ALcAAAB7////AQAAACsAAADjAAAA/QAAADv///8BAAAAJwAAAMsAAABB////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAA3QAAAEP///8BAAAAHwAAAM8AAAD/AAAASf///wEAAAAFAAAAsQAAAHH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADfAAAARf///wEAAAAVAAAAvwAAAP8AAABp////AQAAAAUAAACxAAAAbf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAALcAAAB9////AQAAAAsAAACtAAAA/wAAAIH///8BAAAAKwAA + AM0AAAA5////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAATwAAANsAAAAzAAAAAwAAAKEAAAD/AAAAmwAA + AAUAAACXAAAAvwAAAAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAewAAANkAAABrAAAApQAA + AP8AAADRAAAApwAAAL8AAAAt////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAWwAA + AMUAAADrAAAA/wAAAPUAAACVAAAAJ////wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAAwAAAE8AAAD/AAAA2QAAAAX///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAHwAAAP8AAADdAAAAEf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAFAAAA/wAAAOEAAAAd////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAADfAAAA5wAAAC3///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAALcAAADtAAAAQf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAhQAA + APUAAABX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABPAAAA7wAAAHP///8B////AQAAAA0AAAA3AAAAE////wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAABkAAADPAAAAmwAAAAf///8BAAAAZQAAAOcAAACL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAGMAAADjAAAAH////wEAAABdAAAA9QAAAKn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAACwAAAIEAAAChAAAAUwAAAF8AAACpAAAAN/// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAADkAAABXAAAATQAA + ABf///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAwAAAAYAAAAAEA + IAAAAAAAgCUAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAcAAAAPAAAAEwAAABMAAAARAAAACQAAAAP///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAADAAAAHQAAAGMAAACvAAAA0QAAANUAAAC7AAAAdQAA + ACkAAAAF////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAATAAAApQAAANcAAABXAAAACQAA + AA0AAABTAAAAwwAAALsAAAA/AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABHAAAA/wAA + APEAAACNAAAAC////wH///8BAAAATQAAANcAAADBAAAAKQAAAAP///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABtAAAA/wAAAP8AAAC/AAAAG////wH///8BAAAABwAAAKEAAAD5AAAAhQAAAAn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAAA5AAAAxQAAANUAAACBAAAADf///wH///8B////AQAAAGcAAADnAAAA6QAA + ACf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAFAAAAPQAAAEsAAAAb////Af///wH///8B////AQAA + ADUAAADVAAAA/wAAAHX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAA8AAADJAAAA/wAAANH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAC7AAAA/QAAAPsAAAAL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACjAAAA+QAAAP8AAABB////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA8wAA + AP8AAABp////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAB3AAAA7wAAAP8AAACb////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAABnAAAA7QAAAP8AAAC/////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAABNAAAA5wAAAP8AAADf////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAA/AAAA5QAAAP8AAADtAAAAB/// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAxAAAA4QAA + AP8AAADxAAAANQAAAAn///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AB0AAABjAAAA6QAAAP8AAAD5AAAAowAAAG8AAABBAAAAFf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAFAAAAPQAAAJUAAADfAAAA/QAAAP8AAAD9AAAA5wAAAOcAAADRAAAAgwAAACv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAAUAAABNAAAAwwAAANkAAACRAAAA6wAAAP8AAAD5AAAArQAAAGsAAACtAAAA5QAA + AKMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAADkAAAC/AAAA1wAAAGkAAAAVAAAA0QAAAP8AAAD5AAAAmQAA + AAUAAAApAAAAiwAAAOMAAACXAAAAIf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAEwAAAIUAAADjAAAAcwAAAA////8BAAAAtwAA + APsAAAD7AAAAs////wH///8BAAAAHQAAAJkAAADnAAAAWwAAAAX///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAOQAAAMUAAACrAAAAJ/// + /wH///8BAAAAoQAAAPsAAAD/AAAA0f///wH///8BAAAAAwAAAEcAAADNAAAAnQAAAB////8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAA + AOsAAAB1AAAABf///wH///8BAAAAhwAAAPcAAAD/AAAA1////wH///8B////AQAAABcAAACfAAAAzwAA + ADf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAZwAAAPUAAAD/AAAA3QAAABn///8B////AQAA + AAMAAACLAAAA6QAAAEP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAVQAAAPMAAAD/AAAA4wAA + ADf///8B////AQAAAAMAAACLAAAA5wAAAEP///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAAAPEAAAB7AAAABf///wH///8BAAAANwAA + APEAAAD/AAAA5QAAAEX///8B////AQAAABcAAAChAAAAxQAAADP///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAANwAAAMMAAACtAAAAKf// + /wH///8BAAAAGwAAAO0AAAD/AAAA6wAAAF////8BAAAAAwAAAE8AAADVAAAAlQAAABv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAADwAA + AH0AAADnAAAAeQAAABH///8BAAAACwAAAO0AAAD/AAAA7wAAAHEAAAADAAAAIQAAAJ0AAADpAAAAWQAA + AAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAADUAAAC1AAAA2wAAAHUAAAAdAAAAAwAAAN8AAAD/AAAA9QAAAJMAAAArAAAAkQAA + AN8AAACPAAAAHf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAUAAABJAAAAuwAAAOMAAACdAAAAZQAAANsAAAD/AAAA+wAA + ANEAAACtAAAA4QAAAJsAAAAr////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAFAAAAOQAAAIsAAADVAAAA5wAA + APcAAAD/AAAA/wAAAPcAAADDAAAAdQAAACf///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABcAAABFAAAAaQAAALkAAAD/AAAA/wAAANUAAAA5AAAADf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAABQAAAGMAAAD/AAAA/wAAAMcAAAAJ////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////AQAAADcAAAD/AAAA/wAAAMsAAAAV////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAABUAAAD/AAAA/wAA + AM8AAAAh////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AAMAAAD/AAAA/wAAANMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADdAAAA/wAAANkAAAA9////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAACtAAAA/wAAAOEAAABV////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA/wAAAOUAAABl////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABTAAAA/wAA + AO8AAAB9////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAnAAAA8wAAAPcAAACX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAAAPAAAAwQAAAP0AAACtAAAABf///wH///8B////AQAAABsAAABTAAAASwAA + AAf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAHAAAAbQAAAP8AAADBAAAAIf///wH///8BAAAABwAA + AH0AAADbAAAA0wAAAEv///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAADAAAAKwAAANcAAADbAAAAVf// + /wH///8BAAAACwAAALUAAAD/AAAA/wAAAJX///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACwAA + AGkAAADvAAAAmwAAABP///8BAAAABQAAAHEAAADpAAAA/wAAAGv///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAABcAAACDAAAA4QAAAIcAAAAtAAAAGwAAAFMAAADTAAAAsQAAAB3///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAMAAAAVAAAAWwAAAKkAAADFAAAAxwAAAKsAAABjAAAAHwAA + AAP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAAA0AAAATAAAAEwAA + AA8AAAAH////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8= + \ No newline at end of file diff --git a/Samples/Statistics/Analysis (PLS)/Accord.dll.config b/Samples/Statistics/Analysis (PLS)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Statistics/Analysis (PLS)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Statistics/Analysis (PLS)/Analysis (PLS).csproj b/Samples/Statistics/Analysis (PLS)/Analysis (PLS).csproj index b0af2788d..89f770d4a 100644 --- a/Samples/Statistics/Analysis (PLS)/Analysis (PLS).csproj +++ b/Samples/Statistics/Analysis (PLS)/Analysis (PLS).csproj @@ -80,10 +80,6 @@ False ..\..\..\Release\net40\Accord.Statistics.dll - - False - ..\..\..\Externals\AForge.NET\AForge.Math.dll - 3.5 @@ -133,6 +129,9 @@ Resources.resx True + + PreserveNewest + diff --git a/Samples/Statistics/Analysis (PLS)/MainForm.resx b/Samples/Statistics/Analysis (PLS)/MainForm.resx index 90066a89c..0d07e4ca0 100644 --- a/Samples/Statistics/Analysis (PLS)/MainForm.resx +++ b/Samples/Statistics/Analysis (PLS)/MainForm.resx @@ -123,19 +123,19 @@ - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAJHSURBVDhPxZBdSNNhFMb/F110ZZEVhVBgeeHNICiiuggp - olAUyyxI0oSaH1QYC3N+tKnp5ubm1JUua5uuqdNKMwr7kApFItTUkWZqVhSVYmao5Nevvy7UoYR3HXh4 - 4XCe33nOKyy3lAY7l9RWMo0O/raWXxEyo5spVYTNvOGyfIRPfW+ptOkXqaPl6T83hcRmExSdgzAz3NVm - YWyoYla/B+1M9JtxWLPpaH22JORIjI6gKAMB0jyEimIdo4OlbuaprwVMOOMovammpDADc34qppwUrmnl - 5Kni3aFlFg2j3y1z5mnRTJccnNIltQhwq0jFry+mOXNtpWZWDx1Z1NhV3C3JwGFOw25SYjVe5oYhiUKd - HKMmwQUrMWUw/CF3NnZvvYKqUh1TvUroS3fXe7HXkwidMngTS2t5KLbregSzMY2f3Wr4qKW6LJvGR1rX - 0MLor8OhKYTJBn/GHvvxrliCTBrsOqXIoOBHh5K+hmSq7FqmexTQHuUytkaKxuNMNgYyVneA4Qd7GKjc - hjLaRzxH7gIU6JIZaEvgtk1D8wsxSWecCDgNzWFMvwxm/PkhRmr3Mli1nW9lvjRdWc0Jf+/5jzRmyWmv - S+GOLQu6U6BFjPvqKOP1AYw88WOoZif9DgmfLVtxaj1RSLdwNvrkPCA3M54KqxrnvRia9MKcGrUrqFOt - 5H7qKsqT1mGO9+Lqhc2ELdw+U/r0i+gVZ8hMiCDx3DHORwZyKnQ/hw/uYt9uCTskPvh6e7Fp41rWr/Fg - g6eHO+A/lyD8ARfG3mk9fv1YAAAAAElFTkSuQmCC - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAJHSURBVDhPxZBdSNNhFMb/F110ZZEVhVBgeeHNICiiuggp + olAUyyxI0oSaH1QYC3N+tKnp5ubm1JUua5uuqdNKMwr7kApFItTUkWZqVhSVYmao5Nevvy7UoYR3HXh4 + 4XCe33nOKyy3lAY7l9RWMo0O/raWXxEyo5spVYTNvOGyfIRPfW+ptOkXqaPl6T83hcRmExSdgzAz3NVm + YWyoYla/B+1M9JtxWLPpaH22JORIjI6gKAMB0jyEimIdo4OlbuaprwVMOOMovammpDADc34qppwUrmnl + 5Kni3aFlFg2j3y1z5mnRTJccnNIltQhwq0jFry+mOXNtpWZWDx1Z1NhV3C3JwGFOw25SYjVe5oYhiUKd + HKMmwQUrMWUw/CF3NnZvvYKqUh1TvUroS3fXe7HXkwidMngTS2t5KLbregSzMY2f3Wr4qKW6LJvGR1rX + 0MLor8OhKYTJBn/GHvvxrliCTBrsOqXIoOBHh5K+hmSq7FqmexTQHuUytkaKxuNMNgYyVneA4Qd7GKjc + hjLaRzxH7gIU6JIZaEvgtk1D8wsxSWecCDgNzWFMvwxm/PkhRmr3Mli1nW9lvjRdWc0Jf+/5jzRmyWmv + S+GOLQu6U6BFjPvqKOP1AYw88WOoZif9DgmfLVtxaj1RSLdwNvrkPCA3M54KqxrnvRia9MKcGrUrqFOt + 5H7qKsqT1mGO9+Lqhc2ELdw+U/r0i+gVZ8hMiCDx3DHORwZyKnQ/hw/uYt9uCTskPvh6e7Fp41rWr/Fg + g6eHO+A/lyD8ARfG3mk9fv1YAAAAAElFTkSuQmCC + 324, 17 @@ -197,38 +197,6 @@ True - - - AAEAAAD/////AQAAAAAAAAAMAgAAAFVBY2NvcmQuU3RhdGlzdGljcywgVmVyc2lvbj0yLjE1LjAuMCwg - Q3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1mYTFhODhlMjk1NTVjY2Y3BQEAAAAqQWNjb3Jk - LlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtBwAAAAliaW5WYWx1ZXMJYmluUmFuZ2Vz - E2luY2x1c2l2ZVVwcGVyQm91bmQNYmluQ29sbGVjdGlvbgpjdW11bGF0aXZlBXRpdGxlBHJ1bGUHBwAE - AAEECAYBN0FjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbkNvbGxlY3Rp - b24CAAAAATJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxpemF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQIA - AAACAAAACQMAAAAJBAAAAAEJBQAAAAAGBgAAAAAF+f///zJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxp - emF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQEAAAAHdmFsdWVfXwAIAgAAAAMAAAAPAwAAAAAAAAAIDwQA - AAABAAAABgAAAAAAAAAABQUAAAA3QWNjb3JkLlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9n - cmFtQmluQ29sbGVjdGlvbgEAAAAZUmVhZE9ubHlDb2xsZWN0aW9uYDErbGlzdAQvQWNjb3JkLlN0YXRp - c3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtQmluW10CAAAAAgAAAAkIAAAABwgAAAAAAQAAAAAA - AAAELUFjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbgIAAAAL - - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAFVBY2NvcmQuU3RhdGlzdGljcywgVmVyc2lvbj0yLjE1LjAuMCwg - Q3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1mYTFhODhlMjk1NTVjY2Y3BQEAAAAqQWNjb3Jk - LlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtBwAAAAliaW5WYWx1ZXMJYmluUmFuZ2Vz - E2luY2x1c2l2ZVVwcGVyQm91bmQNYmluQ29sbGVjdGlvbgpjdW11bGF0aXZlBXRpdGxlBHJ1bGUHBwAE - AAEECAYBN0FjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbkNvbGxlY3Rp - b24CAAAAATJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxpemF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQIA - AAACAAAACQMAAAAJBAAAAAEJBQAAAAAGBgAAAAAF+f///zJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxp - emF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQEAAAAHdmFsdWVfXwAIAgAAAAMAAAAPAwAAAAAAAAAIDwQA - AAABAAAABgAAAAAAAAAABQUAAAA3QWNjb3JkLlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9n - cmFtQmluQ29sbGVjdGlvbgEAAAAZUmVhZE9ubHlDb2xsZWN0aW9uYDErbGlzdAQvQWNjb3JkLlN0YXRp - c3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtQmluW10CAAAAAgAAAAkIAAAABwgAAAAAAQAAAAAA - AAAELUFjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbgIAAAAL - - True @@ -243,258 +211,258 @@ - AAABAAMAEBAAAAAAIABoBAAANgAAACAgAAAAACAAqBAAAJ4EAAAwMAAAAAAgAKglAABGFQAAKAAAABAA - AAAgAAAAAQAgAAAAAABABAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wEAAAA7AAAAVQAA - AF0AAAAJ////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAtwAA - ADkAAAA/AAAAff///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ABEAAAADAAAACQAAANcAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAADVAAAAJf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAvQAAAEn///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAGwAAAM0AAACrAAAANf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAGQAAAJcAAACtAAAAlwAAAIEAAAA/////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAGUAAAAxAAAAfwAAAJ8AAAALAAAAi////wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAABlAAAAMQAAAGMAAAC7AAAADQAAAIn///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAFwAAAJkAAABtAAAA2wAAAIEAAAA9////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAZAAAAgQAAAPMAAAAx////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAAAkAAADvAAAADf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAA2wAA - AB3///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - AK8AAAAzAAAAAwAAABP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAABTAAAAaQAAADEAAADD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAAwAAAFcAAABVAAAAPf///wH///8B////Af///wEAAP//AAD//wAA//8AAP//AAD//wAA - //8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//KAAAACAAAABAAAAAAQAgAAAA - AACAEAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ABcAAABRAAAAYQAAAEcAAAAL////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAvAAAApwAAAF8AAABBAAAAfwAAAKMAAAAh////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAAI8AAAD5AAAAcwAAAAMAAAAHAAAApQAAAKkAAAAL////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAdwAAAOEAAABrAAAAA////wEAAABNAAAA5wAAAFv///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAPAAAAMQAAAA3///8B////AQAAAB0AAADhAAAAsf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ANMAAAD5AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAtwAAAP8AAAAz////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAACdAAAA/wAAAF3///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAIcAAAD/AAAAh////wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAcQAAAP8AAACdAAAAA////wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABfAAAA/wAAALsAAAAf////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAYwAAANcAAAD/AAAA9QAA - AN0AAAClAAAAK////wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACQAAAIMAAADRAAAAjQAA - AP8AAADjAAAAYwAAAKcAAADFAAAAMf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABXAAAA2QAA - AC0AAAA1AAAA8wAAAOsAAAAv////AQAAAJUAAADDAAAABf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ALcAAAB7////AQAAACsAAADjAAAA/QAAADv///8BAAAAJwAAAMsAAABB////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAA3QAAAEP///8BAAAAHwAAAM8AAAD/AAAASf///wEAAAAFAAAAsQAAAHH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAADfAAAARf///wEAAAAVAAAAvwAAAP8AAABp////AQAAAAUAAACxAAAAbf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAALcAAAB9////AQAAAAsAAACtAAAA/wAAAIH///8BAAAAKwAA - AM0AAAA5////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAATwAAANsAAAAzAAAAAwAAAKEAAAD/AAAAmwAA - AAUAAACXAAAAvwAAAAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAewAAANkAAABrAAAApQAA - AP8AAADRAAAApwAAAL8AAAAt////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAWwAA - AMUAAADrAAAA/wAAAPUAAACVAAAAJ////wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAAwAAAE8AAAD/AAAA2QAAAAX///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAHwAAAP8AAADdAAAAEf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAFAAAA/wAAAOEAAAAd////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAADfAAAA5wAAAC3///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAALcAAADtAAAAQf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAhQAA - APUAAABX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAABPAAAA7wAAAHP///8B////AQAAAA0AAAA3AAAAE////wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAABkAAADPAAAAmwAAAAf///8BAAAAZQAAAOcAAACL////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAGMAAADjAAAAH////wEAAABdAAAA9QAAAKn///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAACwAAAIEAAAChAAAAUwAAAF8AAACpAAAAN/// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAADkAAABXAAAATQAA - ABf///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAwAAAAYAAAAAEA - IAAAAAAAgCUAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAAcAAAAPAAAAEwAAABMAAAARAAAACQAAAAP///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAADAAAAHQAAAGMAAACvAAAA0QAAANUAAAC7AAAAdQAA - ACkAAAAF////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAATAAAApQAAANcAAABXAAAACQAA - AA0AAABTAAAAwwAAALsAAAA/AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABHAAAA/wAA - APEAAACNAAAAC////wH///8BAAAATQAAANcAAADBAAAAKQAAAAP///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAABtAAAA/wAAAP8AAAC/AAAAG////wH///8BAAAABwAAAKEAAAD5AAAAhQAAAAn///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAAA5AAAAxQAAANUAAACBAAAADf///wH///8B////AQAAAGcAAADnAAAA6QAA - ACf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAFAAAAPQAAAEsAAAAb////Af///wH///8B////AQAA - ADUAAADVAAAA/wAAAHX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAAA8AAADJAAAA/wAAANH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAC7AAAA/QAAAPsAAAAL////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACjAAAA+QAAAP8AAABB////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA8wAA - AP8AAABp////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAB3AAAA7wAAAP8AAACb////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAABnAAAA7QAAAP8AAAC/////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAABNAAAA5wAAAP8AAADf////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAA/AAAA5QAAAP8AAADtAAAAB/// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAxAAAA4QAA - AP8AAADxAAAANQAAAAn///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - AB0AAABjAAAA6QAAAP8AAAD5AAAAowAAAG8AAABBAAAAFf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAFAAAAPQAAAJUAAADfAAAA/QAAAP8AAAD9AAAA5wAAAOcAAADRAAAAgwAAACv///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAAAUAAABNAAAAwwAAANkAAACRAAAA6wAAAP8AAAD5AAAArQAAAGsAAACtAAAA5QAA - AKMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAADkAAAC/AAAA1wAAAGkAAAAVAAAA0QAAAP8AAAD5AAAAmQAA - AAUAAAApAAAAiwAAAOMAAACXAAAAIf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAEwAAAIUAAADjAAAAcwAAAA////8BAAAAtwAA - APsAAAD7AAAAs////wH///8BAAAAHQAAAJkAAADnAAAAWwAAAAX///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAOQAAAMUAAACrAAAAJ/// - /wH///8BAAAAoQAAAPsAAAD/AAAA0f///wH///8BAAAAAwAAAEcAAADNAAAAnQAAAB////8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAA - AOsAAAB1AAAABf///wH///8BAAAAhwAAAPcAAAD/AAAA1////wH///8B////AQAAABcAAACfAAAAzwAA - ADf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAZwAAAPUAAAD/AAAA3QAAABn///8B////AQAA - AAMAAACLAAAA6QAAAEP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAVQAAAPMAAAD/AAAA4wAA - ADf///8B////AQAAAAMAAACLAAAA5wAAAEP///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAAAPEAAAB7AAAABf///wH///8BAAAANwAA - APEAAAD/AAAA5QAAAEX///8B////AQAAABcAAAChAAAAxQAAADP///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAANwAAAMMAAACtAAAAKf// - /wH///8BAAAAGwAAAO0AAAD/AAAA6wAAAF////8BAAAAAwAAAE8AAADVAAAAlQAAABv///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAADwAA - AH0AAADnAAAAeQAAABH///8BAAAACwAAAO0AAAD/AAAA7wAAAHEAAAADAAAAIQAAAJ0AAADpAAAAWQAA - AAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAADUAAAC1AAAA2wAAAHUAAAAdAAAAAwAAAN8AAAD/AAAA9QAAAJMAAAArAAAAkQAA - AN8AAACPAAAAHf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAAUAAABJAAAAuwAAAOMAAACdAAAAZQAAANsAAAD/AAAA+wAA - ANEAAACtAAAA4QAAAJsAAAAr////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAFAAAAOQAAAIsAAADVAAAA5wAA - APcAAAD/AAAA/wAAAPcAAADDAAAAdQAAACf///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ABcAAABFAAAAaQAAALkAAAD/AAAA/wAAANUAAAA5AAAADf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAABQAAAGMAAAD/AAAA/wAAAMcAAAAJ////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////AQAAADcAAAD/AAAA/wAAAMsAAAAV////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAABUAAAD/AAAA/wAA - AM8AAAAh////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - AAMAAAD/AAAA/wAAANMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAADdAAAA/wAAANkAAAA9////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAACtAAAA/wAAAOEAAABV////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA/wAAAOUAAABl////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABTAAAA/wAA - AO8AAAB9////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAnAAAA8wAAAPcAAACX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAAAPAAAAwQAAAP0AAACtAAAABf///wH///8B////AQAAABsAAABTAAAASwAA - AAf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAHAAAAbQAAAP8AAADBAAAAIf///wH///8BAAAABwAA - AH0AAADbAAAA0wAAAEv///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAADAAAAKwAAANcAAADbAAAAVf// - /wH///8BAAAACwAAALUAAAD/AAAA/wAAAJX///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACwAA - AGkAAADvAAAAmwAAABP///8BAAAABQAAAHEAAADpAAAA/wAAAGv///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAABcAAACDAAAA4QAAAIcAAAAtAAAAGwAAAFMAAADTAAAAsQAAAB3///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAAMAAAAVAAAAWwAAAKkAAADFAAAAxwAAAKsAAABjAAAAHwAA - AAP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAAA0AAAATAAAAEwAA - AA8AAAAH////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8= - + AAABAAMAEBAAAAAAIABoBAAANgAAACAgAAAAACAAqBAAAJ4EAAAwMAAAAAAgAKglAABGFQAAKAAAABAA + AAAgAAAAAQAgAAAAAABABAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wEAAAA7AAAAVQAA + AF0AAAAJ////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAtwAA + ADkAAAA/AAAAff///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABEAAAADAAAACQAAANcAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADVAAAAJf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAvQAAAEn///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAGwAAAM0AAACrAAAANf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAGQAAAJcAAACtAAAAlwAAAIEAAAA/////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAGUAAAAxAAAAfwAAAJ8AAAALAAAAi////wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAABlAAAAMQAAAGMAAAC7AAAADQAAAIn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAFwAAAJkAAABtAAAA2wAAAIEAAAA9////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAZAAAAgQAAAPMAAAAx////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAAAkAAADvAAAADf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAA2wAA + AB3///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AK8AAAAzAAAAAwAAABP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABTAAAAaQAAADEAAADD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAAwAAAFcAAABVAAAAPf///wH///8B////Af///wEAAP//AAD//wAA//8AAP//AAD//wAA + //8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//KAAAACAAAABAAAAAAQAgAAAA + AACAEAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABcAAABRAAAAYQAAAEcAAAAL////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAvAAAApwAAAF8AAABBAAAAfwAAAKMAAAAh////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAI8AAAD5AAAAcwAAAAMAAAAHAAAApQAAAKkAAAAL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAdwAAAOEAAABrAAAAA////wEAAABNAAAA5wAAAFv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAPAAAAMQAAAA3///8B////AQAAAB0AAADhAAAAsf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ANMAAAD5AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAtwAAAP8AAAAz////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAACdAAAA/wAAAF3///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAIcAAAD/AAAAh////wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAcQAAAP8AAACdAAAAA////wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABfAAAA/wAAALsAAAAf////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAYwAAANcAAAD/AAAA9QAA + AN0AAAClAAAAK////wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACQAAAIMAAADRAAAAjQAA + AP8AAADjAAAAYwAAAKcAAADFAAAAMf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABXAAAA2QAA + AC0AAAA1AAAA8wAAAOsAAAAv////AQAAAJUAAADDAAAABf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ALcAAAB7////AQAAACsAAADjAAAA/QAAADv///8BAAAAJwAAAMsAAABB////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAA3QAAAEP///8BAAAAHwAAAM8AAAD/AAAASf///wEAAAAFAAAAsQAAAHH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADfAAAARf///wEAAAAVAAAAvwAAAP8AAABp////AQAAAAUAAACxAAAAbf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAALcAAAB9////AQAAAAsAAACtAAAA/wAAAIH///8BAAAAKwAA + AM0AAAA5////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAATwAAANsAAAAzAAAAAwAAAKEAAAD/AAAAmwAA + AAUAAACXAAAAvwAAAAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAewAAANkAAABrAAAApQAA + AP8AAADRAAAApwAAAL8AAAAt////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAWwAA + AMUAAADrAAAA/wAAAPUAAACVAAAAJ////wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAAwAAAE8AAAD/AAAA2QAAAAX///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAHwAAAP8AAADdAAAAEf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAFAAAA/wAAAOEAAAAd////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAADfAAAA5wAAAC3///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAALcAAADtAAAAQf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAhQAA + APUAAABX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABPAAAA7wAAAHP///8B////AQAAAA0AAAA3AAAAE////wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAABkAAADPAAAAmwAAAAf///8BAAAAZQAAAOcAAACL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAGMAAADjAAAAH////wEAAABdAAAA9QAAAKn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAACwAAAIEAAAChAAAAUwAAAF8AAACpAAAAN/// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAADkAAABXAAAATQAA + ABf///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAwAAAAYAAAAAEA + IAAAAAAAgCUAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAcAAAAPAAAAEwAAABMAAAARAAAACQAAAAP///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAADAAAAHQAAAGMAAACvAAAA0QAAANUAAAC7AAAAdQAA + ACkAAAAF////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAATAAAApQAAANcAAABXAAAACQAA + AA0AAABTAAAAwwAAALsAAAA/AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABHAAAA/wAA + APEAAACNAAAAC////wH///8BAAAATQAAANcAAADBAAAAKQAAAAP///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABtAAAA/wAAAP8AAAC/AAAAG////wH///8BAAAABwAAAKEAAAD5AAAAhQAAAAn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAAA5AAAAxQAAANUAAACBAAAADf///wH///8B////AQAAAGcAAADnAAAA6QAA + ACf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAFAAAAPQAAAEsAAAAb////Af///wH///8B////AQAA + ADUAAADVAAAA/wAAAHX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAA8AAADJAAAA/wAAANH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAC7AAAA/QAAAPsAAAAL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACjAAAA+QAAAP8AAABB////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA8wAA + AP8AAABp////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAB3AAAA7wAAAP8AAACb////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAABnAAAA7QAAAP8AAAC/////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAABNAAAA5wAAAP8AAADf////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAA/AAAA5QAAAP8AAADtAAAAB/// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAxAAAA4QAA + AP8AAADxAAAANQAAAAn///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AB0AAABjAAAA6QAAAP8AAAD5AAAAowAAAG8AAABBAAAAFf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAFAAAAPQAAAJUAAADfAAAA/QAAAP8AAAD9AAAA5wAAAOcAAADRAAAAgwAAACv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAAUAAABNAAAAwwAAANkAAACRAAAA6wAAAP8AAAD5AAAArQAAAGsAAACtAAAA5QAA + AKMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAADkAAAC/AAAA1wAAAGkAAAAVAAAA0QAAAP8AAAD5AAAAmQAA + AAUAAAApAAAAiwAAAOMAAACXAAAAIf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAEwAAAIUAAADjAAAAcwAAAA////8BAAAAtwAA + APsAAAD7AAAAs////wH///8BAAAAHQAAAJkAAADnAAAAWwAAAAX///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAOQAAAMUAAACrAAAAJ/// + /wH///8BAAAAoQAAAPsAAAD/AAAA0f///wH///8BAAAAAwAAAEcAAADNAAAAnQAAAB////8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAA + AOsAAAB1AAAABf///wH///8BAAAAhwAAAPcAAAD/AAAA1////wH///8B////AQAAABcAAACfAAAAzwAA + ADf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAZwAAAPUAAAD/AAAA3QAAABn///8B////AQAA + AAMAAACLAAAA6QAAAEP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAVQAAAPMAAAD/AAAA4wAA + ADf///8B////AQAAAAMAAACLAAAA5wAAAEP///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAAAPEAAAB7AAAABf///wH///8BAAAANwAA + APEAAAD/AAAA5QAAAEX///8B////AQAAABcAAAChAAAAxQAAADP///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAANwAAAMMAAACtAAAAKf// + /wH///8BAAAAGwAAAO0AAAD/AAAA6wAAAF////8BAAAAAwAAAE8AAADVAAAAlQAAABv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAADwAA + AH0AAADnAAAAeQAAABH///8BAAAACwAAAO0AAAD/AAAA7wAAAHEAAAADAAAAIQAAAJ0AAADpAAAAWQAA + AAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAADUAAAC1AAAA2wAAAHUAAAAdAAAAAwAAAN8AAAD/AAAA9QAAAJMAAAArAAAAkQAA + AN8AAACPAAAAHf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAUAAABJAAAAuwAAAOMAAACdAAAAZQAAANsAAAD/AAAA+wAA + ANEAAACtAAAA4QAAAJsAAAAr////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAFAAAAOQAAAIsAAADVAAAA5wAA + APcAAAD/AAAA/wAAAPcAAADDAAAAdQAAACf///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABcAAABFAAAAaQAAALkAAAD/AAAA/wAAANUAAAA5AAAADf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAABQAAAGMAAAD/AAAA/wAAAMcAAAAJ////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////AQAAADcAAAD/AAAA/wAAAMsAAAAV////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAABUAAAD/AAAA/wAA + AM8AAAAh////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AAMAAAD/AAAA/wAAANMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADdAAAA/wAAANkAAAA9////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAACtAAAA/wAAAOEAAABV////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA/wAAAOUAAABl////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABTAAAA/wAA + AO8AAAB9////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAnAAAA8wAAAPcAAACX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAAAPAAAAwQAAAP0AAACtAAAABf///wH///8B////AQAAABsAAABTAAAASwAA + AAf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAHAAAAbQAAAP8AAADBAAAAIf///wH///8BAAAABwAA + AH0AAADbAAAA0wAAAEv///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAADAAAAKwAAANcAAADbAAAAVf// + /wH///8BAAAACwAAALUAAAD/AAAA/wAAAJX///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACwAA + AGkAAADvAAAAmwAAABP///8BAAAABQAAAHEAAADpAAAA/wAAAGv///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAABcAAACDAAAA4QAAAIcAAAAtAAAAGwAAAFMAAADTAAAAsQAAAB3///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAMAAAAVAAAAWwAAAKkAAADFAAAAxwAAAKsAAABjAAAAHwAA + AAP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAAA0AAAATAAAAEwAA + AA8AAAAH////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8= + \ No newline at end of file diff --git a/Samples/Statistics/Classification (MLR)/Accord.dll.config b/Samples/Statistics/Classification (MLR)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Statistics/Classification (MLR)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Statistics/Classification (MLR)/Classification (MLR).csproj b/Samples/Statistics/Classification (MLR)/Classification (MLR).csproj index c68e6bd9c..76f57c812 100644 --- a/Samples/Statistics/Classification (MLR)/Classification (MLR).csproj +++ b/Samples/Statistics/Classification (MLR)/Classification (MLR).csproj @@ -86,19 +86,12 @@ False ..\..\..\Release\net40\Accord.Statistics.dll - - False - ..\..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Math.dll - 3.5 + @@ -139,6 +132,9 @@ + + PreserveNewest + diff --git a/Samples/Statistics/Classification (MLR)/MainForm.resx b/Samples/Statistics/Classification (MLR)/MainForm.resx index 9cb797991..79b10aef6 100644 --- a/Samples/Statistics/Classification (MLR)/MainForm.resx +++ b/Samples/Statistics/Classification (MLR)/MainForm.resx @@ -140,38 +140,6 @@ 665, 17 - - - AAEAAAD/////AQAAAAAAAAAMAgAAAFVBY2NvcmQuU3RhdGlzdGljcywgVmVyc2lvbj0yLjE1LjAuMCwg - Q3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1mYTFhODhlMjk1NTVjY2Y3BQEAAAAqQWNjb3Jk - LlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtBwAAAAliaW5WYWx1ZXMJYmluUmFuZ2Vz - E2luY2x1c2l2ZVVwcGVyQm91bmQNYmluQ29sbGVjdGlvbgpjdW11bGF0aXZlBXRpdGxlBHJ1bGUHBwAE - AAEECAYBN0FjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbkNvbGxlY3Rp - b24CAAAAATJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxpemF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQIA - AAACAAAACQMAAAAJBAAAAAEJBQAAAAAGBgAAAAAF+f///zJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxp - emF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQEAAAAHdmFsdWVfXwAIAgAAAAMAAAAPAwAAAAAAAAAIDwQA - AAABAAAABgAAAAAAAAAABQUAAAA3QWNjb3JkLlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9n - cmFtQmluQ29sbGVjdGlvbgEAAAAZUmVhZE9ubHlDb2xsZWN0aW9uYDErbGlzdAQvQWNjb3JkLlN0YXRp - c3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtQmluW10CAAAAAgAAAAkIAAAABwgAAAAAAQAAAAAA - AAAELUFjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbgIAAAAL - - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAFVBY2NvcmQuU3RhdGlzdGljcywgVmVyc2lvbj0yLjE1LjAuMCwg - Q3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1mYTFhODhlMjk1NTVjY2Y3BQEAAAAqQWNjb3Jk - LlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtBwAAAAliaW5WYWx1ZXMJYmluUmFuZ2Vz - E2luY2x1c2l2ZVVwcGVyQm91bmQNYmluQ29sbGVjdGlvbgpjdW11bGF0aXZlBXRpdGxlBHJ1bGUHBwAE - AAEECAYBN0FjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbkNvbGxlY3Rp - b24CAAAAATJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxpemF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQIA - AAACAAAACQMAAAAJBAAAAAEJBQAAAAAGBgAAAAAF+f///zJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxp - emF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQEAAAAHdmFsdWVfXwAIAgAAAAMAAAAPAwAAAAAAAAAIDwQA - AAABAAAABgAAAAAAAAAABQUAAAA3QWNjb3JkLlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9n - cmFtQmluQ29sbGVjdGlvbgEAAAAZUmVhZE9ubHlDb2xsZWN0aW9uYDErbGlzdAQvQWNjb3JkLlN0YXRp - c3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtQmluW10CAAAAAgAAAAkIAAAABwgAAAAAAQAAAAAA - AAAELUFjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbgIAAAAL - - True diff --git a/Samples/Statistics/Eigenfaces (PCA)/Accord.dll.config b/Samples/Statistics/Eigenfaces (PCA)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Statistics/Eigenfaces (PCA)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Statistics/Eigenfaces (PCA)/Eigenfaces (PCA).csproj b/Samples/Statistics/Eigenfaces (PCA)/Eigenfaces (PCA).csproj index 982bc1f57..e8c25ccd4 100644 --- a/Samples/Statistics/Eigenfaces (PCA)/Eigenfaces (PCA).csproj +++ b/Samples/Statistics/Eigenfaces (PCA)/Eigenfaces (PCA).csproj @@ -40,44 +40,29 @@ - ..\..\packages\Accord.2.14.0\lib\net40\Accord.dll + ..\..\..\Release\net40\Accord.dll - - False - ..\..\packages\Accord.Controls.2.14.0\lib\net40\Accord.Controls.dll + + ..\..\..\Release\net40\Accord.Controls.dll - - False - ..\..\packages\Accord.Imaging.2.14.0\lib\net40\Accord.Imaging.dll + + ..\..\..\Release\net40\Accord.Imaging.dll - - False - ..\..\packages\Accord.MachineLearning.2.14.0\lib\net40\Accord.MachineLearning.dll + + ..\..\..\Release\net40\Accord.MachineLearning.dll - ..\..\packages\Accord.Math.2.14.0\lib\net40\Accord.Math.dll - - - False - ..\..\packages\Accord.Statistics.2.14.0\lib\net40\Accord.Statistics.dll + ..\..\..\Release\net40\Accord.Math.dll - - ..\..\packages\AForge.2.2.5\lib\AForge.dll - - - False - ..\..\packages\AForge.Imaging.2.2.5\lib\AForge.Imaging.dll - - - ..\..\packages\AForge.Math.2.2.5\lib\AForge.Math.dll + + ..\..\..\Release\net40\Accord.Statistics.dll + - - @@ -117,6 +102,9 @@ Resources.resx True + + PreserveNewest + diff --git a/Samples/Statistics/Eigenfaces (PCA)/packages.config b/Samples/Statistics/Eigenfaces (PCA)/packages.config index 6ff72ed1f..a56fe3013 100644 --- a/Samples/Statistics/Eigenfaces (PCA)/packages.config +++ b/Samples/Statistics/Eigenfaces (PCA)/packages.config @@ -1,13 +1,4 @@  - - - - - - - - - \ No newline at end of file diff --git a/Samples/Statistics/Tabular filters/AboutBox.Designer.cs b/Samples/Statistics/Filters (Tables)/AboutBox.Designer.cs similarity index 100% rename from Samples/Statistics/Tabular filters/AboutBox.Designer.cs rename to Samples/Statistics/Filters (Tables)/AboutBox.Designer.cs diff --git a/Samples/Statistics/Tabular filters/AboutBox.cs b/Samples/Statistics/Filters (Tables)/AboutBox.cs similarity index 100% rename from Samples/Statistics/Tabular filters/AboutBox.cs rename to Samples/Statistics/Filters (Tables)/AboutBox.cs diff --git a/Samples/Statistics/Tabular filters/AboutBox.resx b/Samples/Statistics/Filters (Tables)/AboutBox.resx similarity index 100% rename from Samples/Statistics/Tabular filters/AboutBox.resx rename to Samples/Statistics/Filters (Tables)/AboutBox.resx diff --git a/Samples/Statistics/Filters (Tables)/Accord.dll.config b/Samples/Statistics/Filters (Tables)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Statistics/Filters (Tables)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Statistics/Tabular filters/FilterDescriptor.cs b/Samples/Statistics/Filters (Tables)/FilterDescriptor.cs similarity index 100% rename from Samples/Statistics/Tabular filters/FilterDescriptor.cs rename to Samples/Statistics/Filters (Tables)/FilterDescriptor.cs diff --git a/Samples/Statistics/Tabular filters/Tabular Filters.csproj b/Samples/Statistics/Filters (Tables)/Filters (Tables).csproj similarity index 93% rename from Samples/Statistics/Tabular filters/Tabular Filters.csproj rename to Samples/Statistics/Filters (Tables)/Filters (Tables).csproj index 532481e5a..097f79fd4 100644 --- a/Samples/Statistics/Tabular filters/Tabular Filters.csproj +++ b/Samples/Statistics/Filters (Tables)/Filters (Tables).csproj @@ -80,10 +80,6 @@ False ..\..\..\Release\net40\Accord.Statistics.dll - - False - ..\..\..\Externals\AForge.NET\AForge.dll - 3.5 @@ -91,11 +87,7 @@ 3.5 - - 3.5 - - @@ -141,6 +133,9 @@ Resources.resx True + + PreserveNewest + diff --git a/Samples/Imaging/Classification (BoW)/License-LGPL.txt b/Samples/Statistics/Filters (Tables)/License-LGPL.txt similarity index 100% rename from Samples/Imaging/Classification (BoW)/License-LGPL.txt rename to Samples/Statistics/Filters (Tables)/License-LGPL.txt diff --git a/Samples/Statistics/Tabular filters/MainForm.Designer.cs b/Samples/Statistics/Filters (Tables)/MainForm.Designer.cs similarity index 100% rename from Samples/Statistics/Tabular filters/MainForm.Designer.cs rename to Samples/Statistics/Filters (Tables)/MainForm.Designer.cs diff --git a/Samples/Statistics/Tabular filters/MainForm.cs b/Samples/Statistics/Filters (Tables)/MainForm.cs similarity index 100% rename from Samples/Statistics/Tabular filters/MainForm.cs rename to Samples/Statistics/Filters (Tables)/MainForm.cs diff --git a/Samples/Statistics/Filters (Tables)/MainForm.resx b/Samples/Statistics/Filters (Tables)/MainForm.resx new file mode 100644 index 0000000000..bf3b7eeb7 --- /dev/null +++ b/Samples/Statistics/Filters (Tables)/MainForm.resx @@ -0,0 +1,459 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAERSURBVDhPrZDbSgJRGIXnpewd6jXsjSQvIrwoI0RQMChU + 0iiDPCGiE3ZCRkvR8VzTeBhnyR5/ccaZNnPhB4t9sdf6Ln5hb8QeathNJFVFKF5C8DqL4ksDVHWGDf7j + LHyPg6NjviSaFqlu5yQYR+KpupaIkrMknCxT3Y7v/NYYb0ITK1c3BarbWWhLQ7IR0cTKReyZ6lZ0XYei + ztHpK4bAc+h1FgQijzSxMptrGIxVSO0xX3AaStFki7bUMVFmaMm/eJMGfIH/MkGzLep0AXn4h/r3CJV3 + mS9gn2bY4UY/UzQ7E9TqfeTFtnuB+XAfzSHKr11kSl/uBebDiZ89ZCst3OUkdwL28sIVsE83ock+EIQV + 2Mz2wxeg6/UAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAJHSURBVDhPxZBdSNNhFMb/F110ZZEVhVBgeeHNICiiuggp + olAUyyxI0oSaH1QYC3N+tKnp5ubm1JUua5uuqdNKMwr7kApFItTUkWZqVhSVYmao5Nevvy7UoYR3HXh4 + 4XCe33nOKyy3lAY7l9RWMo0O/raWXxEyo5spVYTNvOGyfIRPfW+ptOkXqaPl6T83hcRmExSdgzAz3NVm + YWyoYla/B+1M9JtxWLPpaH22JORIjI6gKAMB0jyEimIdo4OlbuaprwVMOOMovammpDADc34qppwUrmnl + 5Kni3aFlFg2j3y1z5mnRTJccnNIltQhwq0jFry+mOXNtpWZWDx1Z1NhV3C3JwGFOw25SYjVe5oYhiUKd + HKMmwQUrMWUw/CF3NnZvvYKqUh1TvUroS3fXe7HXkwidMngTS2t5KLbregSzMY2f3Wr4qKW6LJvGR1rX + 0MLor8OhKYTJBn/GHvvxrliCTBrsOqXIoOBHh5K+hmSq7FqmexTQHuUytkaKxuNMNgYyVneA4Qd7GKjc + hjLaRzxH7gIU6JIZaEvgtk1D8wsxSWecCDgNzWFMvwxm/PkhRmr3Mli1nW9lvjRdWc0Jf+/5jzRmyWmv + S+GOLQu6U6BFjPvqKOP1AYw88WOoZif9DgmfLVtxaj1RSLdwNvrkPCA3M54KqxrnvRia9MKcGrUrqFOt + 5H7qKsqT1mGO9+Lqhc2ELdw+U/r0i+gVZ8hMiCDx3DHORwZyKnQ/hw/uYt9uCTskPvh6e7Fp41rWr/Fg + g6eHO+A/lyD8ARfG3mk9fv1YAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAGDSURBVDhPrZFNSwJRGIX9NYGbFoUlFElY1EJQKEYhCJsi + LaVsERnRF5iCaSZJO1toCDVGFkgoFpWQWWRR2aIvUxm1BKN1wSnHCFw4TOCzue+9nPNw4eVVnav4Izzb + QfxeGZ5TWaxT/rK3irzmC7CsusvC1G4IkbNLboIiDieF4GGUKeTeClDpppF8eeEu2PIfwfrzizSdw3Hk + EnKlFpkMzV2wH77AosOFTV8A+vkl9CiHuJeLJNNZjM8tYWB0FkTvMAwmy/8ERTR6CwjlGAi1Ccence6C + 1NsXzN4PKIxJLLgeIJ2MoXvmFraNBKK3eXZRIveJPvs7FIYniEkXZENOdE+GIZ2Ko10TwLK7tJmKmL0F + EEYarYM+NMnt0C1sQzpx/lcSEnZ2gcKY/gs0dlmZuWvmjjmpwA1qxVp2AWFIMAF/OAGBzMjMI7ZrtJCb + 4Df3o4Zfxy7QrdxDRFKol5khkpR2H4qmIOzUQNBGwrsXYxccnNOQqNbQ0KGGZ+eEPVwdeLxvqqrf4wGh + TNAAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAHkSURBVDhPvZHfS1NhHIf3p5QypLr2D4goMwoMCi/qIugH + Xe1Cr7qKDIMkZixwNhfWLGWbnuki0kXKzLU023KubBNPJrbRdOzocm6e2dPOO21mMS+CHvjcvOf9PF++ + 79H9M+7RT2iRRsIi9sEAXe43yAvf2LpSHq28G9uAnytNT4jMLewtcQ2Ht2pF8ps/aOt+gccX5lxD694S + +1BQFD1RkN5DSFa4Z3uONKbgHE3h8KZ4OJTC1J8UiSzmfhd2uf1CoJHbyKOsZokl0kKwm+aeJaov+wjO + rpQkVqdXfOz0bWAcVLghfaXxkUz3y2VxvpMGSwL3uMKh+gHezSSLEnNhX23vtYzKUirDfGyFj/Iy1mdx + UWqR8iKhwtQLxjgH659y4EwvVXWPiwJt3/Ws+muywRrlqvkDdx3zQrCN8l1ldnEd3/QqFmkS/akHJYGS + zjLzOUEwEsMf+sLI2zmaOou/93pPGoM5zvk7UU7fnBKxSBPoT7SXBNW1F/9Io2lKCNTCeomUyrS8xnBA + wfUqyf1eP5U1ptJD/o1LzeNCsHPydtqdr6k4aiwvOHvNSya3ibU/QIdrEkvfhJislc32MfYfuV1eUGPw + FF7bIVJVZ0N/soPK421UHGstlFvYd/hWecF/Qqf7CR0A5wwgSQA2AAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAJSSURBVDhPtZJrSJNRGMdf6IN9KbpQn/pUEH2JIoLqQ0Zh + FqYZRmJG1iKmUqKyLB2pqSm6vC1Nm5GXoeatEsVJ0RASR3eNzegikRq5lrV3857Fr/d9ddlICoL+8OfA + Oef/e57zcIT/os7WLMw302muSGJ2689qqi7A44q8IzjtNYzarzHQm8tZtT8FmRqu6LToMxN+B8qhCbGR + KVcDE85ajKUaxoaryEuL4UVXIudPB5Ko2oy98xjDptXERuz3hsgAOTzlqqMk6yjdllzE90UM9Wp5azlB + S1kwkeG+1CSv4mmBQPThfd6Ahqq8GYB4A11yBKmaMLQxoZyLDkGjDiZOFUhUuB+FsWsUQFiArzegtlzH + pFjPpMPA2GA2jucx2KqWK7ZWLqO7dBGP9D5KWLbfto3eAKMhi3FHBeP9GYy9PMXos4OIrYvJrzSRbWjm + wuV6EnVG4tLLiEzSExGf4w0oL05nZEDPaK+akceBuO9v4uPtFUrYo6npbzhdE/QPOQmNSiPouHYOUpaf + gvgqA/dDf9wd63G1r2SgUlAqyyq/1anYUGfG2mdXwne7bOwJUc1AinOS+NxzBpd5HWLbUhyNPvRdF5S2 + v05/54tbqvzBifWNHUvPOwLC4/CXwrv2HsB3+w6EwosJOB5ESeElfGpayGD1AmwlArHSm+W2PR1clToo + MrbT0mFTVtlbN6xFuJQar3wQz5Q9VksD+7XyPctrJdx4p5s605M5gKz8lJPSDwtGFbKboJ1blAN52vKb + PdXm80/AfDokTVu+8DfPXv9XCcIPTvjvLQ8YoakAAAAASUVORK5CYII= + + + + 832, 17 + + + 39 + + + + AAABAAMAEBAAAAAAIABoBAAANgAAACAgAAAAACAAqBAAAJ4EAAAwMAAAAAAgAKglAABGFQAAKAAAABAA + AAAgAAAAAQAgAAAAAABABAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wEAAAA7AAAAVQAA + AF0AAAAJ////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAtwAA + ADkAAAA/AAAAff///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABEAAAADAAAACQAAANcAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADVAAAAJf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAvQAAAEn///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAGwAAAM0AAACrAAAANf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAGQAAAJcAAACtAAAAlwAAAIEAAAA/////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAGUAAAAxAAAAfwAAAJ8AAAALAAAAi////wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAABlAAAAMQAAAGMAAAC7AAAADQAAAIn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAFwAAAJkAAABtAAAA2wAAAIEAAAA9////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAZAAAAgQAAAPMAAAAx////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAAAkAAADvAAAADf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAA2wAA + AB3///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AK8AAAAzAAAAAwAAABP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABTAAAAaQAAADEAAADD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAAwAAAFcAAABVAAAAPf///wH///8B////Af///wEAAP//AAD//wAA//8AAP//AAD//wAA + //8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//KAAAACAAAABAAAAAAQAgAAAA + AACAEAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABcAAABRAAAAYQAAAEcAAAAL////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAvAAAApwAAAF8AAABBAAAAfwAAAKMAAAAh////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAI8AAAD5AAAAcwAAAAMAAAAHAAAApQAAAKkAAAAL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAdwAAAOEAAABrAAAAA////wEAAABNAAAA5wAAAFv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAPAAAAMQAAAA3///8B////AQAAAB0AAADhAAAAsf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ANMAAAD5AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAtwAAAP8AAAAz////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAACdAAAA/wAAAF3///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAIcAAAD/AAAAh////wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAcQAAAP8AAACdAAAAA////wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABfAAAA/wAAALsAAAAf////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAYwAAANcAAAD/AAAA9QAA + AN0AAAClAAAAK////wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACQAAAIMAAADRAAAAjQAA + AP8AAADjAAAAYwAAAKcAAADFAAAAMf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABXAAAA2QAA + AC0AAAA1AAAA8wAAAOsAAAAv////AQAAAJUAAADDAAAABf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ALcAAAB7////AQAAACsAAADjAAAA/QAAADv///8BAAAAJwAAAMsAAABB////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAA3QAAAEP///8BAAAAHwAAAM8AAAD/AAAASf///wEAAAAFAAAAsQAAAHH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADfAAAARf///wEAAAAVAAAAvwAAAP8AAABp////AQAAAAUAAACxAAAAbf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAALcAAAB9////AQAAAAsAAACtAAAA/wAAAIH///8BAAAAKwAA + AM0AAAA5////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAATwAAANsAAAAzAAAAAwAAAKEAAAD/AAAAmwAA + AAUAAACXAAAAvwAAAAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAewAAANkAAABrAAAApQAA + AP8AAADRAAAApwAAAL8AAAAt////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAWwAA + AMUAAADrAAAA/wAAAPUAAACVAAAAJ////wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAAwAAAE8AAAD/AAAA2QAAAAX///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAHwAAAP8AAADdAAAAEf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAFAAAA/wAAAOEAAAAd////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAADfAAAA5wAAAC3///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAALcAAADtAAAAQf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAhQAA + APUAAABX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABPAAAA7wAAAHP///8B////AQAAAA0AAAA3AAAAE////wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAABkAAADPAAAAmwAAAAf///8BAAAAZQAAAOcAAACL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAGMAAADjAAAAH////wEAAABdAAAA9QAAAKn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAACwAAAIEAAAChAAAAUwAAAF8AAACpAAAAN/// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAADkAAABXAAAATQAA + ABf///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAwAAAAYAAAAAEA + IAAAAAAAgCUAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAcAAAAPAAAAEwAAABMAAAARAAAACQAAAAP///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAADAAAAHQAAAGMAAACvAAAA0QAAANUAAAC7AAAAdQAA + ACkAAAAF////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAATAAAApQAAANcAAABXAAAACQAA + AA0AAABTAAAAwwAAALsAAAA/AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABHAAAA/wAA + APEAAACNAAAAC////wH///8BAAAATQAAANcAAADBAAAAKQAAAAP///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABtAAAA/wAAAP8AAAC/AAAAG////wH///8BAAAABwAAAKEAAAD5AAAAhQAAAAn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAAA5AAAAxQAAANUAAACBAAAADf///wH///8B////AQAAAGcAAADnAAAA6QAA + ACf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAFAAAAPQAAAEsAAAAb////Af///wH///8B////AQAA + ADUAAADVAAAA/wAAAHX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAA8AAADJAAAA/wAAANH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAC7AAAA/QAAAPsAAAAL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACjAAAA+QAAAP8AAABB////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA8wAA + AP8AAABp////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAB3AAAA7wAAAP8AAACb////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAABnAAAA7QAAAP8AAAC/////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAABNAAAA5wAAAP8AAADf////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAA/AAAA5QAAAP8AAADtAAAAB/// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAxAAAA4QAA + AP8AAADxAAAANQAAAAn///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AB0AAABjAAAA6QAAAP8AAAD5AAAAowAAAG8AAABBAAAAFf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAFAAAAPQAAAJUAAADfAAAA/QAAAP8AAAD9AAAA5wAAAOcAAADRAAAAgwAAACv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAAUAAABNAAAAwwAAANkAAACRAAAA6wAAAP8AAAD5AAAArQAAAGsAAACtAAAA5QAA + AKMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAADkAAAC/AAAA1wAAAGkAAAAVAAAA0QAAAP8AAAD5AAAAmQAA + AAUAAAApAAAAiwAAAOMAAACXAAAAIf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAEwAAAIUAAADjAAAAcwAAAA////8BAAAAtwAA + APsAAAD7AAAAs////wH///8BAAAAHQAAAJkAAADnAAAAWwAAAAX///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAOQAAAMUAAACrAAAAJ/// + /wH///8BAAAAoQAAAPsAAAD/AAAA0f///wH///8BAAAAAwAAAEcAAADNAAAAnQAAAB////8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAA + AOsAAAB1AAAABf///wH///8BAAAAhwAAAPcAAAD/AAAA1////wH///8B////AQAAABcAAACfAAAAzwAA + ADf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAZwAAAPUAAAD/AAAA3QAAABn///8B////AQAA + AAMAAACLAAAA6QAAAEP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAVQAAAPMAAAD/AAAA4wAA + ADf///8B////AQAAAAMAAACLAAAA5wAAAEP///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAAAPEAAAB7AAAABf///wH///8BAAAANwAA + APEAAAD/AAAA5QAAAEX///8B////AQAAABcAAAChAAAAxQAAADP///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAANwAAAMMAAACtAAAAKf// + /wH///8BAAAAGwAAAO0AAAD/AAAA6wAAAF////8BAAAAAwAAAE8AAADVAAAAlQAAABv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAADwAA + AH0AAADnAAAAeQAAABH///8BAAAACwAAAO0AAAD/AAAA7wAAAHEAAAADAAAAIQAAAJ0AAADpAAAAWQAA + AAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAADUAAAC1AAAA2wAAAHUAAAAdAAAAAwAAAN8AAAD/AAAA9QAAAJMAAAArAAAAkQAA + AN8AAACPAAAAHf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAUAAABJAAAAuwAAAOMAAACdAAAAZQAAANsAAAD/AAAA+wAA + ANEAAACtAAAA4QAAAJsAAAAr////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAFAAAAOQAAAIsAAADVAAAA5wAA + APcAAAD/AAAA/wAAAPcAAADDAAAAdQAAACf///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABcAAABFAAAAaQAAALkAAAD/AAAA/wAAANUAAAA5AAAADf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAABQAAAGMAAAD/AAAA/wAAAMcAAAAJ////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////AQAAADcAAAD/AAAA/wAAAMsAAAAV////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAABUAAAD/AAAA/wAA + AM8AAAAh////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AAMAAAD/AAAA/wAAANMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADdAAAA/wAAANkAAAA9////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAACtAAAA/wAAAOEAAABV////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA/wAAAOUAAABl////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABTAAAA/wAA + AO8AAAB9////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAnAAAA8wAAAPcAAACX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAAAPAAAAwQAAAP0AAACtAAAABf///wH///8B////AQAAABsAAABTAAAASwAA + AAf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAHAAAAbQAAAP8AAADBAAAAIf///wH///8BAAAABwAA + AH0AAADbAAAA0wAAAEv///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAADAAAAKwAAANcAAADbAAAAVf// + /wH///8BAAAACwAAALUAAAD/AAAA/wAAAJX///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACwAA + AGkAAADvAAAAmwAAABP///8BAAAABQAAAHEAAADpAAAA/wAAAGv///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAABcAAACDAAAA4QAAAIcAAAAtAAAAGwAAAFMAAADTAAAAsQAAAB3///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAMAAAAVAAAAWwAAAKkAAADFAAAAxwAAAKsAAABjAAAAHwAA + AAP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAAA0AAAATAAAAEwAA + AA8AAAAH////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8= + + + \ No newline at end of file diff --git a/Samples/Statistics/Tabular filters/Program.cs b/Samples/Statistics/Filters (Tables)/Program.cs similarity index 100% rename from Samples/Statistics/Tabular filters/Program.cs rename to Samples/Statistics/Filters (Tables)/Program.cs diff --git a/Samples/Statistics/Tabular filters/Properties/AssemblyInfo.cs b/Samples/Statistics/Filters (Tables)/Properties/AssemblyInfo.cs similarity index 100% rename from Samples/Statistics/Tabular filters/Properties/AssemblyInfo.cs rename to Samples/Statistics/Filters (Tables)/Properties/AssemblyInfo.cs diff --git a/Samples/Statistics/Tabular filters/Properties/Resources.Designer.cs b/Samples/Statistics/Filters (Tables)/Properties/Resources.Designer.cs similarity index 100% rename from Samples/Statistics/Tabular filters/Properties/Resources.Designer.cs rename to Samples/Statistics/Filters (Tables)/Properties/Resources.Designer.cs diff --git a/Samples/Statistics/Filters (Tables)/Properties/Resources.resx b/Samples/Statistics/Filters (Tables)/Properties/Resources.resx new file mode 100644 index 0000000000..af7dbebba --- /dev/null +++ b/Samples/Statistics/Filters (Tables)/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Statistics/Tabular filters/Properties/Settings.Designer.cs b/Samples/Statistics/Filters (Tables)/Properties/Settings.Designer.cs similarity index 100% rename from Samples/Statistics/Tabular filters/Properties/Settings.Designer.cs rename to Samples/Statistics/Filters (Tables)/Properties/Settings.Designer.cs diff --git a/Samples/Statistics/Filters (Tables)/Properties/Settings.settings b/Samples/Statistics/Filters (Tables)/Properties/Settings.settings new file mode 100644 index 0000000000..39645652a --- /dev/null +++ b/Samples/Statistics/Filters (Tables)/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Samples/Statistics/Tabular filters/Resources/examples.xls b/Samples/Statistics/Filters (Tables)/Resources/examples.xls similarity index 100% rename from Samples/Statistics/Tabular filters/Resources/examples.xls rename to Samples/Statistics/Filters (Tables)/Resources/examples.xls diff --git a/Samples/Statistics/Tabular filters/TableSelectDialog.Designer.cs b/Samples/Statistics/Filters (Tables)/TableSelectDialog.Designer.cs similarity index 100% rename from Samples/Statistics/Tabular filters/TableSelectDialog.Designer.cs rename to Samples/Statistics/Filters (Tables)/TableSelectDialog.Designer.cs diff --git a/Samples/Statistics/Tabular filters/TableSelectDialog.cs b/Samples/Statistics/Filters (Tables)/TableSelectDialog.cs similarity index 100% rename from Samples/Statistics/Tabular filters/TableSelectDialog.cs rename to Samples/Statistics/Filters (Tables)/TableSelectDialog.cs diff --git a/Samples/Statistics/Filters (Tables)/TableSelectDialog.resx b/Samples/Statistics/Filters (Tables)/TableSelectDialog.resx new file mode 100644 index 0000000000..c7e0d4bdf --- /dev/null +++ b/Samples/Statistics/Filters (Tables)/TableSelectDialog.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Statistics/Filters (Tables)/app.config b/Samples/Statistics/Filters (Tables)/app.config new file mode 100644 index 0000000000..dedf16d3c --- /dev/null +++ b/Samples/Statistics/Filters (Tables)/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/Statistics/Filters (Tables)/framework.ico b/Samples/Statistics/Filters (Tables)/framework.ico new file mode 100644 index 0000000000..b7126f00d Binary files /dev/null and b/Samples/Statistics/Filters (Tables)/framework.ico differ diff --git a/Samples/Statistics/Tabular filters/packages.config b/Samples/Statistics/Filters (Tables)/packages.config similarity index 100% rename from Samples/Statistics/Tabular filters/packages.config rename to Samples/Statistics/Filters (Tables)/packages.config diff --git a/Samples/Statistics/Gestures (HMMs)/Accord.dll.config b/Samples/Statistics/Gestures (HMMs)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Statistics/Gestures (HMMs)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Statistics/Gestures (HMMs)/Gestures (HMM).csproj b/Samples/Statistics/Gestures (HMMs)/Gestures (HMM).csproj index a4c6054c5..4a325e1a2 100644 --- a/Samples/Statistics/Gestures (HMMs)/Gestures (HMM).csproj +++ b/Samples/Statistics/Gestures (HMMs)/Gestures (HMM).csproj @@ -93,9 +93,6 @@ False ..\..\..\Release\net40\Accord.Statistics.dll - - ..\..\..\Externals\AForge.NET\AForge.dll - @@ -104,11 +101,7 @@ 3.5 - - 3.5 - - @@ -154,6 +147,9 @@ Resources.resx True + + PreserveNewest + SettingsSingleFileGenerator Settings.Designer.cs diff --git a/Samples/Statistics/Handwriting (KDA)/Accord.dll.config b/Samples/Statistics/Handwriting (KDA)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Statistics/Handwriting (KDA)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Statistics/Handwriting (KDA)/Handwriting (KDA).csproj b/Samples/Statistics/Handwriting (KDA)/Handwriting (KDA).csproj index a090a99db..05fc013eb 100644 --- a/Samples/Statistics/Handwriting (KDA)/Handwriting (KDA).csproj +++ b/Samples/Statistics/Handwriting (KDA)/Handwriting (KDA).csproj @@ -133,6 +133,9 @@ Resources.resx True + + PreserveNewest + diff --git a/Samples/Statistics/Performance (ROC)/Accord.dll.config b/Samples/Statistics/Performance (ROC)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Statistics/Performance (ROC)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Statistics/Performance (ROC)/Performance (ROC).csproj b/Samples/Statistics/Performance (ROC)/Performance (ROC).csproj index ff9b61a68..2c35e1770 100644 --- a/Samples/Statistics/Performance (ROC)/Performance (ROC).csproj +++ b/Samples/Statistics/Performance (ROC)/Performance (ROC).csproj @@ -80,16 +80,11 @@ False ..\..\..\Release\net40\Accord.Statistics.dll - - False - ..\..\..\Externals\AForge.NET\AForge.dll - 3.5 - @@ -134,6 +129,9 @@ Resources.resx True + + PreserveNewest + diff --git a/Samples/Statistics/Regression (Linear and Logistic)/Accord.dll.config b/Samples/Statistics/Regression (Linear and Logistic)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Statistics/Regression (Linear and Logistic)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Statistics/Regression (Linear and Logistic)/MainForm.resx b/Samples/Statistics/Regression (Linear and Logistic)/MainForm.resx index a2f383f14..0281e1a1c 100644 --- a/Samples/Statistics/Regression (Linear and Logistic)/MainForm.resx +++ b/Samples/Statistics/Regression (Linear and Logistic)/MainForm.resx @@ -123,19 +123,19 @@ - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAJHSURBVDhPxZBdSNNhFMb/F110ZZEVhVBgeeHNICiiuggp - olAUyyxI0oSaH1QYC3N+tKnp5ubm1JUua5uuqdNKMwr7kApFItTUkWZqVhSVYmao5Nevvy7UoYR3HXh4 - 4XCe33nOKyy3lAY7l9RWMo0O/raWXxEyo5spVYTNvOGyfIRPfW+ptOkXqaPl6T83hcRmExSdgzAz3NVm - YWyoYla/B+1M9JtxWLPpaH22JORIjI6gKAMB0jyEimIdo4OlbuaprwVMOOMovammpDADc34qppwUrmnl - 5Kni3aFlFg2j3y1z5mnRTJccnNIltQhwq0jFry+mOXNtpWZWDx1Z1NhV3C3JwGFOw25SYjVe5oYhiUKd - HKMmwQUrMWUw/CF3NnZvvYKqUh1TvUroS3fXe7HXkwidMngTS2t5KLbregSzMY2f3Wr4qKW6LJvGR1rX - 0MLor8OhKYTJBn/GHvvxrliCTBrsOqXIoOBHh5K+hmSq7FqmexTQHuUytkaKxuNMNgYyVneA4Qd7GKjc - hjLaRzxH7gIU6JIZaEvgtk1D8wsxSWecCDgNzWFMvwxm/PkhRmr3Mli1nW9lvjRdWc0Jf+/5jzRmyWmv - S+GOLQu6U6BFjPvqKOP1AYw88WOoZif9DgmfLVtxaj1RSLdwNvrkPCA3M54KqxrnvRia9MKcGrUrqFOt - 5H7qKsqT1mGO9+Lqhc2ELdw+U/r0i+gVZ8hMiCDx3DHORwZyKnQ/hw/uYt9uCTskPvh6e7Fp41rWr/Fg - g6eHO+A/lyD8ARfG3mk9fv1YAAAAAElFTkSuQmCC - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAJHSURBVDhPxZBdSNNhFMb/F110ZZEVhVBgeeHNICiiuggp + olAUyyxI0oSaH1QYC3N+tKnp5ubm1JUua5uuqdNKMwr7kApFItTUkWZqVhSVYmao5Nevvy7UoYR3HXh4 + 4XCe33nOKyy3lAY7l9RWMo0O/raWXxEyo5spVYTNvOGyfIRPfW+ptOkXqaPl6T83hcRmExSdgzAz3NVm + YWyoYla/B+1M9JtxWLPpaH22JORIjI6gKAMB0jyEimIdo4OlbuaprwVMOOMovammpDADc34qppwUrmnl + 5Kni3aFlFg2j3y1z5mnRTJccnNIltQhwq0jFry+mOXNtpWZWDx1Z1NhV3C3JwGFOw25SYjVe5oYhiUKd + HKMmwQUrMWUw/CF3NnZvvYKqUh1TvUroS3fXe7HXkwidMngTS2t5KLbregSzMY2f3Wr4qKW6LJvGR1rX + 0MLor8OhKYTJBn/GHvvxrliCTBrsOqXIoOBHh5K+hmSq7FqmexTQHuUytkaKxuNMNgYyVneA4Qd7GKjc + hjLaRzxH7gIU6JIZaEvgtk1D8wsxSWecCDgNzWFMvwxm/PkhRmr3Mli1nW9lvjRdWc0Jf+/5jzRmyWmv + S+GOLQu6U6BFjPvqKOP1AYw88WOoZif9DgmfLVtxaj1RSLdwNvrkPCA3M54KqxrnvRia9MKcGrUrqFOt + 5H7qKsqT1mGO9+Lqhc2ELdw+U/r0i+gVZ8hMiCDx3DHORwZyKnQ/hw/uYt9uCTskPvh6e7Fp41rWr/Fg + g6eHO+A/lyD8ARfG3mk9fv1YAAAAAElFTkSuQmCC + True @@ -194,38 +194,6 @@ True - - - AAEAAAD/////AQAAAAAAAAAMAgAAAFVBY2NvcmQuU3RhdGlzdGljcywgVmVyc2lvbj0yLjE1LjAuMCwg - Q3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1mYTFhODhlMjk1NTVjY2Y3BQEAAAAqQWNjb3Jk - LlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtBwAAAAliaW5WYWx1ZXMJYmluUmFuZ2Vz - E2luY2x1c2l2ZVVwcGVyQm91bmQNYmluQ29sbGVjdGlvbgpjdW11bGF0aXZlBXRpdGxlBHJ1bGUHBwAE - AAEECAYBN0FjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbkNvbGxlY3Rp - b24CAAAAATJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxpemF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQIA - AAACAAAACQMAAAAJBAAAAAEJBQAAAAAGBgAAAAAF+f///zJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxp - emF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQEAAAAHdmFsdWVfXwAIAgAAAAMAAAAPAwAAAAAAAAAIDwQA - AAABAAAABgAAAAAAAAAABQUAAAA3QWNjb3JkLlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9n - cmFtQmluQ29sbGVjdGlvbgEAAAAZUmVhZE9ubHlDb2xsZWN0aW9uYDErbGlzdAQvQWNjb3JkLlN0YXRp - c3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtQmluW10CAAAAAgAAAAkIAAAABwgAAAAAAQAAAAAA - AAAELUFjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbgIAAAAL - - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAFVBY2NvcmQuU3RhdGlzdGljcywgVmVyc2lvbj0yLjE1LjAuMCwg - Q3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1mYTFhODhlMjk1NTVjY2Y3BQEAAAAqQWNjb3Jk - LlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtBwAAAAliaW5WYWx1ZXMJYmluUmFuZ2Vz - E2luY2x1c2l2ZVVwcGVyQm91bmQNYmluQ29sbGVjdGlvbgpjdW11bGF0aXZlBXRpdGxlBHJ1bGUHBwAE - AAEECAYBN0FjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbkNvbGxlY3Rp - b24CAAAAATJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxpemF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQIA - AAACAAAACQMAAAAJBAAAAAEJBQAAAAAGBgAAAAAF+f///zJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxp - emF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQEAAAAHdmFsdWVfXwAIAgAAAAMAAAAPAwAAAAAAAAAIDwQA - AAABAAAABgAAAAAAAAAABQUAAAA3QWNjb3JkLlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9n - cmFtQmluQ29sbGVjdGlvbgEAAAAZUmVhZE9ubHlDb2xsZWN0aW9uYDErbGlzdAQvQWNjb3JkLlN0YXRp - c3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtQmluW10CAAAAAgAAAAkIAAAABwgAAAAAAQAAAAAA - AAAELUFjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbgIAAAAL - - True @@ -276,258 +244,258 @@ - AAABAAMAEBAAAAAAIABoBAAANgAAACAgAAAAACAAqBAAAJ4EAAAwMAAAAAAgAKglAABGFQAAKAAAABAA - AAAgAAAAAQAgAAAAAABABAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wEAAAA7AAAAVQAA - AF0AAAAJ////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAtwAA - ADkAAAA/AAAAff///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ABEAAAADAAAACQAAANcAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAADVAAAAJf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAvQAAAEn///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAGwAAAM0AAACrAAAANf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAGQAAAJcAAACtAAAAlwAAAIEAAAA/////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAGUAAAAxAAAAfwAAAJ8AAAALAAAAi////wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAABlAAAAMQAAAGMAAAC7AAAADQAAAIn///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAFwAAAJkAAABtAAAA2wAAAIEAAAA9////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAZAAAAgQAAAPMAAAAx////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAAAkAAADvAAAADf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAA2wAA - AB3///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - AK8AAAAzAAAAAwAAABP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAABTAAAAaQAAADEAAADD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAAwAAAFcAAABVAAAAPf///wH///8B////Af///wEAAP//AAD//wAA//8AAP//AAD//wAA - //8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//KAAAACAAAABAAAAAAQAgAAAA - AACAEAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ABcAAABRAAAAYQAAAEcAAAAL////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAvAAAApwAAAF8AAABBAAAAfwAAAKMAAAAh////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAAI8AAAD5AAAAcwAAAAMAAAAHAAAApQAAAKkAAAAL////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAdwAAAOEAAABrAAAAA////wEAAABNAAAA5wAAAFv///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAPAAAAMQAAAA3///8B////AQAAAB0AAADhAAAAsf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ANMAAAD5AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAtwAAAP8AAAAz////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAACdAAAA/wAAAF3///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAIcAAAD/AAAAh////wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAcQAAAP8AAACdAAAAA////wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABfAAAA/wAAALsAAAAf////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAYwAAANcAAAD/AAAA9QAA - AN0AAAClAAAAK////wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACQAAAIMAAADRAAAAjQAA - AP8AAADjAAAAYwAAAKcAAADFAAAAMf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABXAAAA2QAA - AC0AAAA1AAAA8wAAAOsAAAAv////AQAAAJUAAADDAAAABf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ALcAAAB7////AQAAACsAAADjAAAA/QAAADv///8BAAAAJwAAAMsAAABB////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAA3QAAAEP///8BAAAAHwAAAM8AAAD/AAAASf///wEAAAAFAAAAsQAAAHH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAADfAAAARf///wEAAAAVAAAAvwAAAP8AAABp////AQAAAAUAAACxAAAAbf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAALcAAAB9////AQAAAAsAAACtAAAA/wAAAIH///8BAAAAKwAA - AM0AAAA5////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAATwAAANsAAAAzAAAAAwAAAKEAAAD/AAAAmwAA - AAUAAACXAAAAvwAAAAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAewAAANkAAABrAAAApQAA - AP8AAADRAAAApwAAAL8AAAAt////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAWwAA - AMUAAADrAAAA/wAAAPUAAACVAAAAJ////wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAAwAAAE8AAAD/AAAA2QAAAAX///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAHwAAAP8AAADdAAAAEf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAFAAAA/wAAAOEAAAAd////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAADfAAAA5wAAAC3///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAALcAAADtAAAAQf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAhQAA - APUAAABX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAABPAAAA7wAAAHP///8B////AQAAAA0AAAA3AAAAE////wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAABkAAADPAAAAmwAAAAf///8BAAAAZQAAAOcAAACL////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAGMAAADjAAAAH////wEAAABdAAAA9QAAAKn///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAACwAAAIEAAAChAAAAUwAAAF8AAACpAAAAN/// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAADkAAABXAAAATQAA - ABf///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAwAAAAYAAAAAEA - IAAAAAAAgCUAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAAcAAAAPAAAAEwAAABMAAAARAAAACQAAAAP///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAADAAAAHQAAAGMAAACvAAAA0QAAANUAAAC7AAAAdQAA - ACkAAAAF////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAATAAAApQAAANcAAABXAAAACQAA - AA0AAABTAAAAwwAAALsAAAA/AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABHAAAA/wAA - APEAAACNAAAAC////wH///8BAAAATQAAANcAAADBAAAAKQAAAAP///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAABtAAAA/wAAAP8AAAC/AAAAG////wH///8BAAAABwAAAKEAAAD5AAAAhQAAAAn///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAAA5AAAAxQAAANUAAACBAAAADf///wH///8B////AQAAAGcAAADnAAAA6QAA - ACf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAFAAAAPQAAAEsAAAAb////Af///wH///8B////AQAA - ADUAAADVAAAA/wAAAHX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAAA8AAADJAAAA/wAAANH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAC7AAAA/QAAAPsAAAAL////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACjAAAA+QAAAP8AAABB////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA8wAA - AP8AAABp////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAB3AAAA7wAAAP8AAACb////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAABnAAAA7QAAAP8AAAC/////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAABNAAAA5wAAAP8AAADf////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAA/AAAA5QAAAP8AAADtAAAAB/// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAxAAAA4QAA - AP8AAADxAAAANQAAAAn///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - AB0AAABjAAAA6QAAAP8AAAD5AAAAowAAAG8AAABBAAAAFf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAFAAAAPQAAAJUAAADfAAAA/QAAAP8AAAD9AAAA5wAAAOcAAADRAAAAgwAAACv///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAAAUAAABNAAAAwwAAANkAAACRAAAA6wAAAP8AAAD5AAAArQAAAGsAAACtAAAA5QAA - AKMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAADkAAAC/AAAA1wAAAGkAAAAVAAAA0QAAAP8AAAD5AAAAmQAA - AAUAAAApAAAAiwAAAOMAAACXAAAAIf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAEwAAAIUAAADjAAAAcwAAAA////8BAAAAtwAA - APsAAAD7AAAAs////wH///8BAAAAHQAAAJkAAADnAAAAWwAAAAX///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAOQAAAMUAAACrAAAAJ/// - /wH///8BAAAAoQAAAPsAAAD/AAAA0f///wH///8BAAAAAwAAAEcAAADNAAAAnQAAAB////8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAA - AOsAAAB1AAAABf///wH///8BAAAAhwAAAPcAAAD/AAAA1////wH///8B////AQAAABcAAACfAAAAzwAA - ADf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAZwAAAPUAAAD/AAAA3QAAABn///8B////AQAA - AAMAAACLAAAA6QAAAEP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAVQAAAPMAAAD/AAAA4wAA - ADf///8B////AQAAAAMAAACLAAAA5wAAAEP///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAAAPEAAAB7AAAABf///wH///8BAAAANwAA - APEAAAD/AAAA5QAAAEX///8B////AQAAABcAAAChAAAAxQAAADP///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAANwAAAMMAAACtAAAAKf// - /wH///8BAAAAGwAAAO0AAAD/AAAA6wAAAF////8BAAAAAwAAAE8AAADVAAAAlQAAABv///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAADwAA - AH0AAADnAAAAeQAAABH///8BAAAACwAAAO0AAAD/AAAA7wAAAHEAAAADAAAAIQAAAJ0AAADpAAAAWQAA - AAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAADUAAAC1AAAA2wAAAHUAAAAdAAAAAwAAAN8AAAD/AAAA9QAAAJMAAAArAAAAkQAA - AN8AAACPAAAAHf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAAUAAABJAAAAuwAAAOMAAACdAAAAZQAAANsAAAD/AAAA+wAA - ANEAAACtAAAA4QAAAJsAAAAr////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAFAAAAOQAAAIsAAADVAAAA5wAA - APcAAAD/AAAA/wAAAPcAAADDAAAAdQAAACf///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ABcAAABFAAAAaQAAALkAAAD/AAAA/wAAANUAAAA5AAAADf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAABQAAAGMAAAD/AAAA/wAAAMcAAAAJ////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////AQAAADcAAAD/AAAA/wAAAMsAAAAV////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAABUAAAD/AAAA/wAA - AM8AAAAh////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - AAMAAAD/AAAA/wAAANMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAADdAAAA/wAAANkAAAA9////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAACtAAAA/wAAAOEAAABV////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA/wAAAOUAAABl////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABTAAAA/wAA - AO8AAAB9////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAnAAAA8wAAAPcAAACX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAAAPAAAAwQAAAP0AAACtAAAABf///wH///8B////AQAAABsAAABTAAAASwAA - AAf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAHAAAAbQAAAP8AAADBAAAAIf///wH///8BAAAABwAA - AH0AAADbAAAA0wAAAEv///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAADAAAAKwAAANcAAADbAAAAVf// - /wH///8BAAAACwAAALUAAAD/AAAA/wAAAJX///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACwAA - AGkAAADvAAAAmwAAABP///8BAAAABQAAAHEAAADpAAAA/wAAAGv///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAABcAAACDAAAA4QAAAIcAAAAtAAAAGwAAAFMAAADTAAAAsQAAAB3///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAAMAAAAVAAAAWwAAAKkAAADFAAAAxwAAAKsAAABjAAAAHwAA - AAP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAAA0AAAATAAAAEwAA - AA8AAAAH////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8= - + AAABAAMAEBAAAAAAIABoBAAANgAAACAgAAAAACAAqBAAAJ4EAAAwMAAAAAAgAKglAABGFQAAKAAAABAA + AAAgAAAAAQAgAAAAAABABAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wEAAAA7AAAAVQAA + AF0AAAAJ////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAtwAA + ADkAAAA/AAAAff///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABEAAAADAAAACQAAANcAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADVAAAAJf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAvQAAAEn///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAGwAAAM0AAACrAAAANf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAGQAAAJcAAACtAAAAlwAAAIEAAAA/////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAGUAAAAxAAAAfwAAAJ8AAAALAAAAi////wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAABlAAAAMQAAAGMAAAC7AAAADQAAAIn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAFwAAAJkAAABtAAAA2wAAAIEAAAA9////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAZAAAAgQAAAPMAAAAx////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAAAkAAADvAAAADf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAA2wAA + AB3///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AK8AAAAzAAAAAwAAABP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABTAAAAaQAAADEAAADD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAAwAAAFcAAABVAAAAPf///wH///8B////Af///wEAAP//AAD//wAA//8AAP//AAD//wAA + //8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//KAAAACAAAABAAAAAAQAgAAAA + AACAEAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABcAAABRAAAAYQAAAEcAAAAL////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAvAAAApwAAAF8AAABBAAAAfwAAAKMAAAAh////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAI8AAAD5AAAAcwAAAAMAAAAHAAAApQAAAKkAAAAL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAdwAAAOEAAABrAAAAA////wEAAABNAAAA5wAAAFv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAPAAAAMQAAAA3///8B////AQAAAB0AAADhAAAAsf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ANMAAAD5AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAtwAAAP8AAAAz////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAACdAAAA/wAAAF3///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAIcAAAD/AAAAh////wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAcQAAAP8AAACdAAAAA////wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABfAAAA/wAAALsAAAAf////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAYwAAANcAAAD/AAAA9QAA + AN0AAAClAAAAK////wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACQAAAIMAAADRAAAAjQAA + AP8AAADjAAAAYwAAAKcAAADFAAAAMf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABXAAAA2QAA + AC0AAAA1AAAA8wAAAOsAAAAv////AQAAAJUAAADDAAAABf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ALcAAAB7////AQAAACsAAADjAAAA/QAAADv///8BAAAAJwAAAMsAAABB////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAA3QAAAEP///8BAAAAHwAAAM8AAAD/AAAASf///wEAAAAFAAAAsQAAAHH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADfAAAARf///wEAAAAVAAAAvwAAAP8AAABp////AQAAAAUAAACxAAAAbf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAALcAAAB9////AQAAAAsAAACtAAAA/wAAAIH///8BAAAAKwAA + AM0AAAA5////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAATwAAANsAAAAzAAAAAwAAAKEAAAD/AAAAmwAA + AAUAAACXAAAAvwAAAAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAewAAANkAAABrAAAApQAA + AP8AAADRAAAApwAAAL8AAAAt////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAWwAA + AMUAAADrAAAA/wAAAPUAAACVAAAAJ////wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAAwAAAE8AAAD/AAAA2QAAAAX///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAHwAAAP8AAADdAAAAEf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAFAAAA/wAAAOEAAAAd////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAADfAAAA5wAAAC3///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAALcAAADtAAAAQf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAhQAA + APUAAABX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABPAAAA7wAAAHP///8B////AQAAAA0AAAA3AAAAE////wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAABkAAADPAAAAmwAAAAf///8BAAAAZQAAAOcAAACL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAGMAAADjAAAAH////wEAAABdAAAA9QAAAKn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAACwAAAIEAAAChAAAAUwAAAF8AAACpAAAAN/// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAADkAAABXAAAATQAA + ABf///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAwAAAAYAAAAAEA + IAAAAAAAgCUAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAcAAAAPAAAAEwAAABMAAAARAAAACQAAAAP///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAADAAAAHQAAAGMAAACvAAAA0QAAANUAAAC7AAAAdQAA + ACkAAAAF////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAATAAAApQAAANcAAABXAAAACQAA + AA0AAABTAAAAwwAAALsAAAA/AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABHAAAA/wAA + APEAAACNAAAAC////wH///8BAAAATQAAANcAAADBAAAAKQAAAAP///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABtAAAA/wAAAP8AAAC/AAAAG////wH///8BAAAABwAAAKEAAAD5AAAAhQAAAAn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAAA5AAAAxQAAANUAAACBAAAADf///wH///8B////AQAAAGcAAADnAAAA6QAA + ACf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAFAAAAPQAAAEsAAAAb////Af///wH///8B////AQAA + ADUAAADVAAAA/wAAAHX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAA8AAADJAAAA/wAAANH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAC7AAAA/QAAAPsAAAAL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACjAAAA+QAAAP8AAABB////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA8wAA + AP8AAABp////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAB3AAAA7wAAAP8AAACb////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAABnAAAA7QAAAP8AAAC/////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAABNAAAA5wAAAP8AAADf////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAA/AAAA5QAAAP8AAADtAAAAB/// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAxAAAA4QAA + AP8AAADxAAAANQAAAAn///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AB0AAABjAAAA6QAAAP8AAAD5AAAAowAAAG8AAABBAAAAFf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAFAAAAPQAAAJUAAADfAAAA/QAAAP8AAAD9AAAA5wAAAOcAAADRAAAAgwAAACv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAAUAAABNAAAAwwAAANkAAACRAAAA6wAAAP8AAAD5AAAArQAAAGsAAACtAAAA5QAA + AKMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAADkAAAC/AAAA1wAAAGkAAAAVAAAA0QAAAP8AAAD5AAAAmQAA + AAUAAAApAAAAiwAAAOMAAACXAAAAIf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAEwAAAIUAAADjAAAAcwAAAA////8BAAAAtwAA + APsAAAD7AAAAs////wH///8BAAAAHQAAAJkAAADnAAAAWwAAAAX///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAOQAAAMUAAACrAAAAJ/// + /wH///8BAAAAoQAAAPsAAAD/AAAA0f///wH///8BAAAAAwAAAEcAAADNAAAAnQAAAB////8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAA + AOsAAAB1AAAABf///wH///8BAAAAhwAAAPcAAAD/AAAA1////wH///8B////AQAAABcAAACfAAAAzwAA + ADf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAZwAAAPUAAAD/AAAA3QAAABn///8B////AQAA + AAMAAACLAAAA6QAAAEP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAVQAAAPMAAAD/AAAA4wAA + ADf///8B////AQAAAAMAAACLAAAA5wAAAEP///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAAAPEAAAB7AAAABf///wH///8BAAAANwAA + APEAAAD/AAAA5QAAAEX///8B////AQAAABcAAAChAAAAxQAAADP///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAANwAAAMMAAACtAAAAKf// + /wH///8BAAAAGwAAAO0AAAD/AAAA6wAAAF////8BAAAAAwAAAE8AAADVAAAAlQAAABv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAADwAA + AH0AAADnAAAAeQAAABH///8BAAAACwAAAO0AAAD/AAAA7wAAAHEAAAADAAAAIQAAAJ0AAADpAAAAWQAA + AAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAADUAAAC1AAAA2wAAAHUAAAAdAAAAAwAAAN8AAAD/AAAA9QAAAJMAAAArAAAAkQAA + AN8AAACPAAAAHf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAUAAABJAAAAuwAAAOMAAACdAAAAZQAAANsAAAD/AAAA+wAA + ANEAAACtAAAA4QAAAJsAAAAr////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAFAAAAOQAAAIsAAADVAAAA5wAA + APcAAAD/AAAA/wAAAPcAAADDAAAAdQAAACf///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABcAAABFAAAAaQAAALkAAAD/AAAA/wAAANUAAAA5AAAADf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAABQAAAGMAAAD/AAAA/wAAAMcAAAAJ////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////AQAAADcAAAD/AAAA/wAAAMsAAAAV////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAABUAAAD/AAAA/wAA + AM8AAAAh////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AAMAAAD/AAAA/wAAANMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADdAAAA/wAAANkAAAA9////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAACtAAAA/wAAAOEAAABV////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA/wAAAOUAAABl////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABTAAAA/wAA + AO8AAAB9////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAnAAAA8wAAAPcAAACX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAAAPAAAAwQAAAP0AAACtAAAABf///wH///8B////AQAAABsAAABTAAAASwAA + AAf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAHAAAAbQAAAP8AAADBAAAAIf///wH///8BAAAABwAA + AH0AAADbAAAA0wAAAEv///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAADAAAAKwAAANcAAADbAAAAVf// + /wH///8BAAAACwAAALUAAAD/AAAA/wAAAJX///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACwAA + AGkAAADvAAAAmwAAABP///8BAAAABQAAAHEAAADpAAAA/wAAAGv///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAABcAAACDAAAA4QAAAIcAAAAtAAAAGwAAAFMAAADTAAAAsQAAAB3///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAMAAAAVAAAAWwAAAKkAAADFAAAAxwAAAKsAAABjAAAAHwAA + AAP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAAA0AAAATAAAAEwAA + AA8AAAAH////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8= + \ No newline at end of file diff --git a/Samples/Statistics/Regression (Linear and Logistic)/Regression (Linear, Logit).csproj b/Samples/Statistics/Regression (Linear and Logistic)/Regression (Linear, Logit).csproj index 8c4fd3c1f..e67bb748a 100644 --- a/Samples/Statistics/Regression (Linear and Logistic)/Regression (Linear, Logit).csproj +++ b/Samples/Statistics/Regression (Linear and Logistic)/Regression (Linear, Logit).csproj @@ -81,23 +81,12 @@ False ..\..\..\Release\net40\Accord.Statistics.dll - - False - ..\..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Controls.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Math.dll - 3.5 + @@ -142,6 +131,9 @@ + + PreserveNewest + diff --git a/Samples/Statistics/Sequences (HMM)/Accord.dll.config b/Samples/Statistics/Sequences (HMM)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Statistics/Sequences (HMM)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Statistics/Sequences (HMM)/Sequences (HMM).csproj b/Samples/Statistics/Sequences (HMM)/Sequences (HMM).csproj index debeb3687..5f9a7a49c 100644 --- a/Samples/Statistics/Sequences (HMM)/Sequences (HMM).csproj +++ b/Samples/Statistics/Sequences (HMM)/Sequences (HMM).csproj @@ -79,12 +79,6 @@ False ..\..\..\Release\net40\Accord.Statistics.dll - - ..\..\..\Externals\AForge.NET\AForge.dll - - - ..\..\..\Externals\AForge.NET\AForge.Math.dll - 3.5 @@ -130,6 +124,9 @@ Resources.resx True + + PreserveNewest + SettingsSingleFileGenerator Settings.Designer.cs diff --git a/Samples/Statistics/Sound demixing (ICA)/Accord.dll.config b/Samples/Statistics/Sound demixing (ICA)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Statistics/Sound demixing (ICA)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Statistics/Sound demixing (ICA)/MainForm.Designer.cs b/Samples/Statistics/Sound demixing (ICA)/MainForm.Designer.cs index 9404fdc27..76cab3f1f 100644 --- a/Samples/Statistics/Sound demixing (ICA)/MainForm.Designer.cs +++ b/Samples/Statistics/Sound demixing (ICA)/MainForm.Designer.cs @@ -1,33 +1,33 @@ -namespace Demixing.ICA -{ - partial class MainForm - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); this.label1 = new System.Windows.Forms.Label(); this.label2 = new System.Windows.Forms.Label(); @@ -69,7 +69,7 @@ private void InitializeComponent() // // btnRunAnalysis // - this.btnRunAnalysis.Image = global::Demixing.ICA.Properties.Resources.gears; + this.btnRunAnalysis.Image = global::SampleApp.Properties.Resources.gears; this.btnRunAnalysis.Location = new System.Drawing.Point(380, 153); this.btnRunAnalysis.Name = "btnRunAnalysis"; this.btnRunAnalysis.Size = new System.Drawing.Size(161, 170); @@ -82,7 +82,7 @@ private void InitializeComponent() // btnSource1 // this.btnSource1.Enabled = false; - this.btnSource1.Image = global::Demixing.ICA.Properties.Resources.sound; + this.btnSource1.Image = global::SampleApp.Properties.Resources.sound; this.btnSource1.Location = new System.Drawing.Point(54, 261); this.btnSource1.Name = "btnSource1"; this.btnSource1.Size = new System.Drawing.Size(139, 166); @@ -94,7 +94,7 @@ private void InitializeComponent() // // btnMic2 // - this.btnMic2.Image = global::Demixing.ICA.Properties.Resources.mic; + this.btnMic2.Image = global::SampleApp.Properties.Resources.mic; this.btnMic2.Location = new System.Drawing.Point(158, 12); this.btnMic2.Name = "btnMic2"; this.btnMic2.Size = new System.Drawing.Size(139, 163); @@ -106,7 +106,7 @@ private void InitializeComponent() // // btnMic1 // - this.btnMic1.Image = global::Demixing.ICA.Properties.Resources.mic; + this.btnMic1.Image = global::SampleApp.Properties.Resources.mic; this.btnMic1.Location = new System.Drawing.Point(13, 12); this.btnMic1.Name = "btnMic1"; this.btnMic1.Size = new System.Drawing.Size(139, 163); @@ -119,7 +119,7 @@ private void InitializeComponent() // btnSource2 // this.btnSource2.Enabled = false; - this.btnSource2.Image = global::Demixing.ICA.Properties.Resources.sound; + this.btnSource2.Image = global::SampleApp.Properties.Resources.sound; this.btnSource2.Location = new System.Drawing.Point(199, 261); this.btnSource2.Name = "btnSource2"; this.btnSource2.Size = new System.Drawing.Size(139, 166); @@ -147,18 +147,18 @@ private void InitializeComponent() this.Text = "Independent Component Analysis"; this.ResumeLayout(false); - } - - #endregion - - private System.Windows.Forms.Button btnMic1; - private System.Windows.Forms.Button btnRunAnalysis; - private System.Windows.Forms.Button btnSource1; - private System.Windows.Forms.Button btnMic2; - private System.Windows.Forms.Label label1; - private System.Windows.Forms.Label label2; - private System.Windows.Forms.Label label3; - private System.Windows.Forms.Button btnSource2; - } -} - + } + + #endregion + + private System.Windows.Forms.Button btnMic1; + private System.Windows.Forms.Button btnRunAnalysis; + private System.Windows.Forms.Button btnSource1; + private System.Windows.Forms.Button btnMic2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Button btnSource2; + } +} + diff --git a/Samples/Statistics/Sound demixing (ICA)/MainForm.cs b/Samples/Statistics/Sound demixing (ICA)/MainForm.cs index a5c17534c..584c9ace6 100644 --- a/Samples/Statistics/Sound demixing (ICA)/MainForm.cs +++ b/Samples/Statistics/Sound demixing (ICA)/MainForm.cs @@ -36,9 +36,9 @@ using Accord.Math; using Accord.Statistics.Analysis; using System; -using System.Windows.Forms; - -namespace Demixing.ICA +using System.Windows.Forms; + +namespace SampleApp { public partial class MainForm : Form { diff --git a/Samples/Statistics/Sound demixing (ICA)/Program.cs b/Samples/Statistics/Sound demixing (ICA)/Program.cs index 3b2aa7bd0..316268492 100644 --- a/Samples/Statistics/Sound demixing (ICA)/Program.cs +++ b/Samples/Statistics/Sound demixing (ICA)/Program.cs @@ -1,7 +1,7 @@ using System; using System.Windows.Forms; -namespace Demixing.ICA +namespace SampleApp { static class Program { diff --git a/Samples/Statistics/Sound demixing (ICA)/Properties/Resources.Designer.cs b/Samples/Statistics/Sound demixing (ICA)/Properties/Resources.Designer.cs index b994e8534..9b6288a65 100644 --- a/Samples/Statistics/Sound demixing (ICA)/Properties/Resources.Designer.cs +++ b/Samples/Statistics/Sound demixing (ICA)/Properties/Resources.Designer.cs @@ -1,93 +1,93 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.18052 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Demixing.ICA.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Demixing.ICA.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap gears { - get { - object obj = ResourceManager.GetObject("gears", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap mic { - get { - object obj = ResourceManager.GetObject("mic", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap sound { - get { - object obj = ResourceManager.GetObject("sound", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap gears { + get { + object obj = ResourceManager.GetObject("gears", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap mic { + get { + object obj = ResourceManager.GetObject("mic", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap sound { + get { + object obj = ResourceManager.GetObject("sound", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/Samples/Statistics/Sound demixing (ICA)/Properties/Settings.Designer.cs b/Samples/Statistics/Sound demixing (ICA)/Properties/Settings.Designer.cs index facc027eb..dbc9e5d22 100644 --- a/Samples/Statistics/Sound demixing (ICA)/Properties/Settings.Designer.cs +++ b/Samples/Statistics/Sound demixing (ICA)/Properties/Settings.Designer.cs @@ -1,26 +1,26 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.18052 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Demixing.ICA.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Samples/Statistics/Sound demixing (ICA)/Sound demixing (ICA).csproj b/Samples/Statistics/Sound demixing (ICA)/Sound demixing (ICA).csproj index 85605b3de..2f168f216 100644 --- a/Samples/Statistics/Sound demixing (ICA)/Sound demixing (ICA).csproj +++ b/Samples/Statistics/Sound demixing (ICA)/Sound demixing (ICA).csproj @@ -8,13 +8,13 @@ {A37A4E8F-3F41-497A-B5C0-E92ABFF9067F} WinExe Properties - Demixing.ICA + SampleApp Sound demixing %28ICA%29 v4.0 512 - true + true 3.5 publish\ @@ -35,7 +35,7 @@ ..\..\ true - 64910c04 + fdbe6615 true @@ -82,46 +82,28 @@ framework.ico - - False - ..\..\packages\Accord.2.14.0\lib\net40\Accord.dll + + ..\..\..\Release\net40\Accord.dll - - False - ..\..\packages\Accord.Audio.2.14.0\lib\net40\Accord.Audio.dll + + ..\..\..\Release\net40\Accord.Audio.dll - - False - ..\..\packages\Accord.Audio.2.14.0\lib\net40\Accord.Audio.Formats.dll + + ..\..\..\Release\net40\Accord.Audio.DirectSound.dll - - False - ..\..\packages\Accord.DirectSound.2.14.0\lib\net40\Accord.DirectSound.dll - - - ..\..\packages\Accord.IO.2.14.0\lib\net40\Accord.IO.dll - - - False - ..\..\packages\Accord.Math.2.14.0\lib\net40\Accord.Math.dll + + ..\..\..\Release\net40\Accord.Math.dll - - False - ..\..\packages\Accord.Statistics.2.14.0\lib\net40\Accord.Statistics.dll + + ..\..\..\Release\net40\Accord.Statistics.dll - + False - ..\..\packages\AForge.2.2.5\lib\AForge.dll + ..\..\..\Externals\SharpDX\net40\SharpDX.dll - + False - ..\..\packages\AForge.Math.2.2.5\lib\AForge.Math.dll - - - $(SharpDXPackageBinDir)\SharpDX.dll - - - $(SharpDXPackageBinDir)\SharpDX.DirectSound.dll + ..\..\..\Externals\SharpDX\net40\SharpDX.DirectSound.dll @@ -130,11 +112,7 @@ 3.5 - - 3.5 - - @@ -162,7 +140,10 @@ Resources.resx True - + + PreserveNewest + + SettingsSingleFileGenerator Settings.Designer.cs @@ -203,15 +184,6 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - + + + + + diff --git a/Samples/Statistics/Survival (Cox)/MainForm.resx b/Samples/Statistics/Survival (Cox)/MainForm.resx index 6098b793a..208ce1985 100644 --- a/Samples/Statistics/Survival (Cox)/MainForm.resx +++ b/Samples/Statistics/Survival (Cox)/MainForm.resx @@ -123,19 +123,19 @@ - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAJHSURBVDhPxZBdSNNhFMb/F110ZZEVhVBgeeHNICiiuggp - olAUyyxI0oSaH1QYC3N+tKnp5ubm1JUua5uuqdNKMwr7kApFItTUkWZqVhSVYmao5Nevvy7UoYR3HXh4 - 4XCe33nOKyy3lAY7l9RWMo0O/raWXxEyo5spVYTNvOGyfIRPfW+ptOkXqaPl6T83hcRmExSdgzAz3NVm - YWyoYla/B+1M9JtxWLPpaH22JORIjI6gKAMB0jyEimIdo4OlbuaprwVMOOMovammpDADc34qppwUrmnl - 5Kni3aFlFg2j3y1z5mnRTJccnNIltQhwq0jFry+mOXNtpWZWDx1Z1NhV3C3JwGFOw25SYjVe5oYhiUKd - HKMmwQUrMWUw/CF3NnZvvYKqUh1TvUroS3fXe7HXkwidMngTS2t5KLbregSzMY2f3Wr4qKW6LJvGR1rX - 0MLor8OhKYTJBn/GHvvxrliCTBrsOqXIoOBHh5K+hmSq7FqmexTQHuUytkaKxuNMNgYyVneA4Qd7GKjc - hjLaRzxH7gIU6JIZaEvgtk1D8wsxSWecCDgNzWFMvwxm/PkhRmr3Mli1nW9lvjRdWc0Jf+/5jzRmyWmv - S+GOLQu6U6BFjPvqKOP1AYw88WOoZif9DgmfLVtxaj1RSLdwNvrkPCA3M54KqxrnvRia9MKcGrUrqFOt - 5H7qKsqT1mGO9+Lqhc2ELdw+U/r0i+gVZ8hMiCDx3DHORwZyKnQ/hw/uYt9uCTskPvh6e7Fp41rWr/Fg - g6eHO+A/lyD8ARfG3mk9fv1YAAAAAElFTkSuQmCC - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAJHSURBVDhPxZBdSNNhFMb/F110ZZEVhVBgeeHNICiiuggp + olAUyyxI0oSaH1QYC3N+tKnp5ubm1JUua5uuqdNKMwr7kApFItTUkWZqVhSVYmao5Nevvy7UoYR3HXh4 + 4XCe33nOKyy3lAY7l9RWMo0O/raWXxEyo5spVYTNvOGyfIRPfW+ptOkXqaPl6T83hcRmExSdgzAz3NVm + YWyoYla/B+1M9JtxWLPpaH22JORIjI6gKAMB0jyEimIdo4OlbuaprwVMOOMovammpDADc34qppwUrmnl + 5Kni3aFlFg2j3y1z5mnRTJccnNIltQhwq0jFry+mOXNtpWZWDx1Z1NhV3C3JwGFOw25SYjVe5oYhiUKd + HKMmwQUrMWUw/CF3NnZvvYKqUh1TvUroS3fXe7HXkwidMngTS2t5KLbregSzMY2f3Wr4qKW6LJvGR1rX + 0MLor8OhKYTJBn/GHvvxrliCTBrsOqXIoOBHh5K+hmSq7FqmexTQHuUytkaKxuNMNgYyVneA4Qd7GKjc + hjLaRzxH7gIU6JIZaEvgtk1D8wsxSWecCDgNzWFMvwxm/PkhRmr3Mli1nW9lvjRdWc0Jf+/5jzRmyWmv + S+GOLQu6U6BFjPvqKOP1AYw88WOoZif9DgmfLVtxaj1RSLdwNvrkPCA3M54KqxrnvRia9MKcGrUrqFOt + 5H7qKsqT1mGO9+Lqhc2ELdw+U/r0i+gVZ8hMiCDx3DHORwZyKnQ/hw/uYt9uCTskPvh6e7Fp41rWr/Fg + g6eHO+A/lyD8ARfG3mk9fv1YAAAAAElFTkSuQmCC + True @@ -194,295 +194,263 @@ True - - - AAEAAAD/////AQAAAAAAAAAMAgAAAFVBY2NvcmQuU3RhdGlzdGljcywgVmVyc2lvbj0yLjE1LjAuMCwg - Q3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1mYTFhODhlMjk1NTVjY2Y3BQEAAAAqQWNjb3Jk - LlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtBwAAAAliaW5WYWx1ZXMJYmluUmFuZ2Vz - E2luY2x1c2l2ZVVwcGVyQm91bmQNYmluQ29sbGVjdGlvbgpjdW11bGF0aXZlBXRpdGxlBHJ1bGUHBwAE - AAEECAYBN0FjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbkNvbGxlY3Rp - b24CAAAAATJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxpemF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQIA - AAACAAAACQMAAAAJBAAAAAEJBQAAAAAGBgAAAAAF+f///zJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxp - emF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQEAAAAHdmFsdWVfXwAIAgAAAAMAAAAPAwAAAAAAAAAIDwQA - AAABAAAABgAAAAAAAAAABQUAAAA3QWNjb3JkLlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9n - cmFtQmluQ29sbGVjdGlvbgEAAAAZUmVhZE9ubHlDb2xsZWN0aW9uYDErbGlzdAQvQWNjb3JkLlN0YXRp - c3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtQmluW10CAAAAAgAAAAkIAAAABwgAAAAAAQAAAAAA - AAAELUFjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbgIAAAAL - - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAFVBY2NvcmQuU3RhdGlzdGljcywgVmVyc2lvbj0yLjE1LjAuMCwg - Q3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1mYTFhODhlMjk1NTVjY2Y3BQEAAAAqQWNjb3Jk - LlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtBwAAAAliaW5WYWx1ZXMJYmluUmFuZ2Vz - E2luY2x1c2l2ZVVwcGVyQm91bmQNYmluQ29sbGVjdGlvbgpjdW11bGF0aXZlBXRpdGxlBHJ1bGUHBwAE - AAEECAYBN0FjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbkNvbGxlY3Rp - b24CAAAAATJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxpemF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQIA - AAACAAAACQMAAAAJBAAAAAEJBQAAAAAGBgAAAAAF+f///zJBY2NvcmQuU3RhdGlzdGljcy5WaXN1YWxp - emF0aW9ucy5CaW5BZGp1c3RtZW50UnVsZQEAAAAHdmFsdWVfXwAIAgAAAAMAAAAPAwAAAAAAAAAIDwQA - AAABAAAABgAAAAAAAAAABQUAAAA3QWNjb3JkLlN0YXRpc3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9n - cmFtQmluQ29sbGVjdGlvbgEAAAAZUmVhZE9ubHlDb2xsZWN0aW9uYDErbGlzdAQvQWNjb3JkLlN0YXRp - c3RpY3MuVmlzdWFsaXphdGlvbnMuSGlzdG9ncmFtQmluW10CAAAAAgAAAAkIAAAABwgAAAAAAQAAAAAA - AAAELUFjY29yZC5TdGF0aXN0aWNzLlZpc3VhbGl6YXRpb25zLkhpc3RvZ3JhbUJpbgIAAAAL - - 937, 17 - AAABAAMAEBAAAAAAIABoBAAANgAAACAgAAAAACAAqBAAAJ4EAAAwMAAAAAAgAKglAABGFQAAKAAAABAA - AAAgAAAAAQAgAAAAAABABAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wEAAAA7AAAAVQAA - AF0AAAAJ////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAtwAA - ADkAAAA/AAAAff///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ABEAAAADAAAACQAAANcAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAADVAAAAJf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAvQAAAEn///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAGwAAAM0AAACrAAAANf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAGQAAAJcAAACtAAAAlwAAAIEAAAA/////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAGUAAAAxAAAAfwAAAJ8AAAALAAAAi////wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAABlAAAAMQAAAGMAAAC7AAAADQAAAIn///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAFwAAAJkAAABtAAAA2wAAAIEAAAA9////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAZAAAAgQAAAPMAAAAx////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAAAkAAADvAAAADf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAA2wAA - AB3///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - AK8AAAAzAAAAAwAAABP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAABTAAAAaQAAADEAAADD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAAwAAAFcAAABVAAAAPf///wH///8B////Af///wEAAP//AAD//wAA//8AAP//AAD//wAA - //8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//KAAAACAAAABAAAAAAQAgAAAA - AACAEAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ABcAAABRAAAAYQAAAEcAAAAL////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAvAAAApwAAAF8AAABBAAAAfwAAAKMAAAAh////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAAI8AAAD5AAAAcwAAAAMAAAAHAAAApQAAAKkAAAAL////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAdwAAAOEAAABrAAAAA////wEAAABNAAAA5wAAAFv///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAPAAAAMQAAAA3///8B////AQAAAB0AAADhAAAAsf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ANMAAAD5AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAtwAAAP8AAAAz////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAACdAAAA/wAAAF3///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAIcAAAD/AAAAh////wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAcQAAAP8AAACdAAAAA////wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABfAAAA/wAAALsAAAAf////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAYwAAANcAAAD/AAAA9QAA - AN0AAAClAAAAK////wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACQAAAIMAAADRAAAAjQAA - AP8AAADjAAAAYwAAAKcAAADFAAAAMf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABXAAAA2QAA - AC0AAAA1AAAA8wAAAOsAAAAv////AQAAAJUAAADDAAAABf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ALcAAAB7////AQAAACsAAADjAAAA/QAAADv///8BAAAAJwAAAMsAAABB////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAA3QAAAEP///8BAAAAHwAAAM8AAAD/AAAASf///wEAAAAFAAAAsQAAAHH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAADfAAAARf///wEAAAAVAAAAvwAAAP8AAABp////AQAAAAUAAACxAAAAbf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAALcAAAB9////AQAAAAsAAACtAAAA/wAAAIH///8BAAAAKwAA - AM0AAAA5////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAATwAAANsAAAAzAAAAAwAAAKEAAAD/AAAAmwAA - AAUAAACXAAAAvwAAAAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAewAAANkAAABrAAAApQAA - AP8AAADRAAAApwAAAL8AAAAt////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAWwAA - AMUAAADrAAAA/wAAAPUAAACVAAAAJ////wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAAwAAAE8AAAD/AAAA2QAAAAX///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAHwAAAP8AAADdAAAAEf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAFAAAA/wAAAOEAAAAd////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAADfAAAA5wAAAC3///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAALcAAADtAAAAQf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAhQAA - APUAAABX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAABPAAAA7wAAAHP///8B////AQAAAA0AAAA3AAAAE////wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAABkAAADPAAAAmwAAAAf///8BAAAAZQAAAOcAAACL////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAGMAAADjAAAAH////wEAAABdAAAA9QAAAKn///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAACwAAAIEAAAChAAAAUwAAAF8AAACpAAAAN/// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAADkAAABXAAAATQAA - ABf///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAwAAAAYAAAAAEA - IAAAAAAAgCUAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAAcAAAAPAAAAEwAAABMAAAARAAAACQAAAAP///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAADAAAAHQAAAGMAAACvAAAA0QAAANUAAAC7AAAAdQAA - ACkAAAAF////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAATAAAApQAAANcAAABXAAAACQAA - AA0AAABTAAAAwwAAALsAAAA/AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABHAAAA/wAA - APEAAACNAAAAC////wH///8BAAAATQAAANcAAADBAAAAKQAAAAP///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAABtAAAA/wAAAP8AAAC/AAAAG////wH///8BAAAABwAAAKEAAAD5AAAAhQAAAAn///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAAA5AAAAxQAAANUAAACBAAAADf///wH///8B////AQAAAGcAAADnAAAA6QAA - ACf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAFAAAAPQAAAEsAAAAb////Af///wH///8B////AQAA - ADUAAADVAAAA/wAAAHX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAAA8AAADJAAAA/wAAANH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAC7AAAA/QAAAPsAAAAL////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACjAAAA+QAAAP8AAABB////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA8wAA - AP8AAABp////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAB3AAAA7wAAAP8AAACb////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAABnAAAA7QAAAP8AAAC/////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAABNAAAA5wAAAP8AAADf////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAA/AAAA5QAAAP8AAADtAAAAB/// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAxAAAA4QAA - AP8AAADxAAAANQAAAAn///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - AB0AAABjAAAA6QAAAP8AAAD5AAAAowAAAG8AAABBAAAAFf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAFAAAAPQAAAJUAAADfAAAA/QAAAP8AAAD9AAAA5wAAAOcAAADRAAAAgwAAACv///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAAAUAAABNAAAAwwAAANkAAACRAAAA6wAAAP8AAAD5AAAArQAAAGsAAACtAAAA5QAA - AKMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAADkAAAC/AAAA1wAAAGkAAAAVAAAA0QAAAP8AAAD5AAAAmQAA - AAUAAAApAAAAiwAAAOMAAACXAAAAIf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAEwAAAIUAAADjAAAAcwAAAA////8BAAAAtwAA - APsAAAD7AAAAs////wH///8BAAAAHQAAAJkAAADnAAAAWwAAAAX///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAOQAAAMUAAACrAAAAJ/// - /wH///8BAAAAoQAAAPsAAAD/AAAA0f///wH///8BAAAAAwAAAEcAAADNAAAAnQAAAB////8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAA - AOsAAAB1AAAABf///wH///8BAAAAhwAAAPcAAAD/AAAA1////wH///8B////AQAAABcAAACfAAAAzwAA - ADf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAZwAAAPUAAAD/AAAA3QAAABn///8B////AQAA - AAMAAACLAAAA6QAAAEP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAVQAAAPMAAAD/AAAA4wAA - ADf///8B////AQAAAAMAAACLAAAA5wAAAEP///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAAAPEAAAB7AAAABf///wH///8BAAAANwAA - APEAAAD/AAAA5QAAAEX///8B////AQAAABcAAAChAAAAxQAAADP///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAANwAAAMMAAACtAAAAKf// - /wH///8BAAAAGwAAAO0AAAD/AAAA6wAAAF////8BAAAAAwAAAE8AAADVAAAAlQAAABv///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAADwAA - AH0AAADnAAAAeQAAABH///8BAAAACwAAAO0AAAD/AAAA7wAAAHEAAAADAAAAIQAAAJ0AAADpAAAAWQAA - AAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAADUAAAC1AAAA2wAAAHUAAAAdAAAAAwAAAN8AAAD/AAAA9QAAAJMAAAArAAAAkQAA - AN8AAACPAAAAHf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAAUAAABJAAAAuwAAAOMAAACdAAAAZQAAANsAAAD/AAAA+wAA - ANEAAACtAAAA4QAAAJsAAAAr////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAFAAAAOQAAAIsAAADVAAAA5wAA - APcAAAD/AAAA/wAAAPcAAADDAAAAdQAAACf///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - ABcAAABFAAAAaQAAALkAAAD/AAAA/wAAANUAAAA5AAAADf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAABQAAAGMAAAD/AAAA/wAAAMcAAAAJ////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////AQAAADcAAAD/AAAA/wAAAMsAAAAV////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAABUAAAD/AAAA/wAA - AM8AAAAh////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA - AAMAAAD/AAAA/wAAANMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAADdAAAA/wAAANkAAAA9////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAACtAAAA/wAAAOEAAABV////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA/wAAAOUAAABl////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABTAAAA/wAA - AO8AAAB9////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAnAAAA8wAAAPcAAACX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wEAAAAPAAAAwQAAAP0AAACtAAAABf///wH///8B////AQAAABsAAABTAAAASwAA - AAf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAHAAAAbQAAAP8AAADBAAAAIf///wH///8BAAAABwAA - AH0AAADbAAAA0wAAAEv///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAADAAAAKwAAANcAAADbAAAAVf// - /wH///8BAAAACwAAALUAAAD/AAAA/wAAAJX///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACwAA - AGkAAADvAAAAmwAAABP///8BAAAABQAAAHEAAADpAAAA/wAAAGv///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AQAAABcAAACDAAAA4QAAAIcAAAAtAAAAGwAAAFMAAADTAAAAsQAAAB3///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AQAAAAMAAAAVAAAAWwAAAKkAAADFAAAAxwAAAKsAAABjAAAAHwAA - AAP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAAA0AAAATAAAAEwAA - AA8AAAAH////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wEAAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8= - + AAABAAMAEBAAAAAAIABoBAAANgAAACAgAAAAACAAqBAAAJ4EAAAwMAAAAAAgAKglAABGFQAAKAAAABAA + AAAgAAAAAQAgAAAAAABABAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wEAAAA7AAAAVQAA + AF0AAAAJ////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAtwAA + ADkAAAA/AAAAff///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABEAAAADAAAACQAAANcAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADVAAAAJf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAvQAAAEn///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAGwAAAM0AAACrAAAANf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAGQAAAJcAAACtAAAAlwAAAIEAAAA/////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAGUAAAAxAAAAfwAAAJ8AAAALAAAAi////wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAABlAAAAMQAAAGMAAAC7AAAADQAAAIn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAFwAAAJkAAABtAAAA2wAAAIEAAAA9////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAZAAAAgQAAAPMAAAAx////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAAAkAAADvAAAADf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAA2wAA + AB3///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AK8AAAAzAAAAAwAAABP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABTAAAAaQAAADEAAADD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAAwAAAFcAAABVAAAAPf///wH///8B////Af///wEAAP//AAD//wAA//8AAP//AAD//wAA + //8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//KAAAACAAAABAAAAAAQAgAAAA + AACAEAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABcAAABRAAAAYQAAAEcAAAAL////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAvAAAApwAAAF8AAABBAAAAfwAAAKMAAAAh////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAI8AAAD5AAAAcwAAAAMAAAAHAAAApQAAAKkAAAAL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAdwAAAOEAAABrAAAAA////wEAAABNAAAA5wAAAFv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAPAAAAMQAAAA3///8B////AQAAAB0AAADhAAAAsf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ANMAAAD5AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAtwAAAP8AAAAz////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAACdAAAA/wAAAF3///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAIcAAAD/AAAAh////wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAcQAAAP8AAACdAAAAA////wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABfAAAA/wAAALsAAAAf////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAYwAAANcAAAD/AAAA9QAA + AN0AAAClAAAAK////wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACQAAAIMAAADRAAAAjQAA + AP8AAADjAAAAYwAAAKcAAADFAAAAMf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABXAAAA2QAA + AC0AAAA1AAAA8wAAAOsAAAAv////AQAAAJUAAADDAAAABf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ALcAAAB7////AQAAACsAAADjAAAA/QAAADv///8BAAAAJwAAAMsAAABB////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAA3QAAAEP///8BAAAAHwAAAM8AAAD/AAAASf///wEAAAAFAAAAsQAAAHH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADfAAAARf///wEAAAAVAAAAvwAAAP8AAABp////AQAAAAUAAACxAAAAbf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAALcAAAB9////AQAAAAsAAACtAAAA/wAAAIH///8BAAAAKwAA + AM0AAAA5////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAATwAAANsAAAAzAAAAAwAAAKEAAAD/AAAAmwAA + AAUAAACXAAAAvwAAAAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAewAAANkAAABrAAAApQAA + AP8AAADRAAAApwAAAL8AAAAt////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAJAAAAWwAA + AMUAAADrAAAA/wAAAPUAAACVAAAAJ////wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAAwAAAE8AAAD/AAAA2QAAAAX///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAHwAAAP8AAADdAAAAEf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAFAAAA/wAAAOEAAAAd////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAADfAAAA5wAAAC3///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAALcAAADtAAAAQf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAhQAA + APUAAABX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABPAAAA7wAAAHP///8B////AQAAAA0AAAA3AAAAE////wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAABkAAADPAAAAmwAAAAf///8BAAAAZQAAAOcAAACL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAGMAAADjAAAAH////wEAAABdAAAA9QAAAKn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAACwAAAIEAAAChAAAAUwAAAF8AAACpAAAAN/// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAADkAAABXAAAATQAA + ABf///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAwAAAAYAAAAAEA + IAAAAAAAgCUAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAcAAAAPAAAAEwAAABMAAAARAAAACQAAAAP///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAADAAAAHQAAAGMAAACvAAAA0QAAANUAAAC7AAAAdQAA + ACkAAAAF////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAATAAAApQAAANcAAABXAAAACQAA + AA0AAABTAAAAwwAAALsAAAA/AAAABf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABHAAAA/wAA + APEAAACNAAAAC////wH///8BAAAATQAAANcAAADBAAAAKQAAAAP///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAABtAAAA/wAAAP8AAAC/AAAAG////wH///8BAAAABwAAAKEAAAD5AAAAhQAAAAn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAAA5AAAAxQAAANUAAACBAAAADf///wH///8B////AQAAAGcAAADnAAAA6QAA + ACf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAFAAAAPQAAAEsAAAAb////Af///wH///8B////AQAA + ADUAAADVAAAA/wAAAHX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAA8AAADJAAAA/wAAANH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAC7AAAA/QAAAPsAAAAL////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACjAAAA+QAAAP8AAABB////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA8wAA + AP8AAABp////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAB3AAAA7wAAAP8AAACb////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAABnAAAA7QAAAP8AAAC/////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAABNAAAA5wAAAP8AAADf////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAA/AAAA5QAAAP8AAADtAAAAB/// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAxAAAA4QAA + AP8AAADxAAAANQAAAAn///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AB0AAABjAAAA6QAAAP8AAAD5AAAAowAAAG8AAABBAAAAFf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAFAAAAPQAAAJUAAADfAAAA/QAAAP8AAAD9AAAA5wAAAOcAAADRAAAAgwAAACv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAAUAAABNAAAAwwAAANkAAACRAAAA6wAAAP8AAAD5AAAArQAAAGsAAACtAAAA5QAA + AKMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAADkAAAC/AAAA1wAAAGkAAAAVAAAA0QAAAP8AAAD5AAAAmQAA + AAUAAAApAAAAiwAAAOMAAACXAAAAIf///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAEwAAAIUAAADjAAAAcwAAAA////8BAAAAtwAA + APsAAAD7AAAAs////wH///8BAAAAHQAAAJkAAADnAAAAWwAAAAX///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAOQAAAMUAAACrAAAAJ/// + /wH///8BAAAAoQAAAPsAAAD/AAAA0f///wH///8BAAAAAwAAAEcAAADNAAAAnQAAAB////8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAA + AOsAAAB1AAAABf///wH///8BAAAAhwAAAPcAAAD/AAAA1////wH///8B////AQAAABcAAACfAAAAzwAA + ADf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAZwAAAPUAAAD/AAAA3QAAABn///8B////AQAA + AAMAAACLAAAA6QAAAEP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAYwAAAOkAAABh////Af///wH///8BAAAAVQAAAPMAAAD/AAAA4wAA + ADf///8B////AQAAAAMAAACLAAAA5wAAAEP///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAWQAAAPEAAAB7AAAABf///wH///8BAAAANwAA + APEAAAD/AAAA5QAAAEX///8B////AQAAABcAAAChAAAAxQAAADP///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAANwAAAMMAAACtAAAAKf// + /wH///8BAAAAGwAAAO0AAAD/AAAA6wAAAF////8BAAAAAwAAAE8AAADVAAAAlQAAABv///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAADwAA + AH0AAADnAAAAeQAAABH///8BAAAACwAAAO0AAAD/AAAA7wAAAHEAAAADAAAAIQAAAJ0AAADpAAAAWQAA + AAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAADUAAAC1AAAA2wAAAHUAAAAdAAAAAwAAAN8AAAD/AAAA9QAAAJMAAAArAAAAkQAA + AN8AAACPAAAAHf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAUAAABJAAAAuwAAAOMAAACdAAAAZQAAANsAAAD/AAAA+wAA + ANEAAACtAAAA4QAAAJsAAAAr////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAAFAAAAOQAAAIsAAADVAAAA5wAA + APcAAAD/AAAA/wAAAPcAAADDAAAAdQAAACf///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + ABcAAABFAAAAaQAAALkAAAD/AAAA/wAAANUAAAA5AAAADf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAABQAAAGMAAAD/AAAA/wAAAMcAAAAJ////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////AQAAADcAAAD/AAAA/wAAAMsAAAAV////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAABUAAAD/AAAA/wAA + AM8AAAAh////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AAMAAAD/AAAA/wAAANMAAAAv////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAADdAAAA/wAAANkAAAA9////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAACtAAAA/wAAAOEAAABV////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAACHAAAA/wAAAOUAAABl////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAABTAAAA/wAA + AO8AAAB9////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAnAAAA8wAAAPcAAACX////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAAAPAAAAwQAAAP0AAACtAAAABf///wH///8B////AQAAABsAAABTAAAASwAA + AAf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAHAAAAbQAAAP8AAADBAAAAIf///wH///8BAAAABwAA + AH0AAADbAAAA0wAAAEv///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAADAAAAKwAAANcAAADbAAAAVf// + /wH///8BAAAACwAAALUAAAD/AAAA/wAAAJX///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAACwAA + AGkAAADvAAAAmwAAABP///8BAAAABQAAAHEAAADpAAAA/wAAAGv///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAABcAAACDAAAA4QAAAIcAAAAtAAAAGwAAAFMAAADTAAAAsQAAAB3///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAMAAAAVAAAAWwAAAKkAAADFAAAAxwAAAKsAAABjAAAAHwAA + AAP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAAAA0AAAATAAAAEwAA + AA8AAAAH////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8= + \ No newline at end of file diff --git a/Samples/Statistics/Survival (Cox)/Survival (Cox).csproj b/Samples/Statistics/Survival (Cox)/Survival (Cox).csproj index 50b8c77cc..3e577b3b0 100644 --- a/Samples/Statistics/Survival (Cox)/Survival (Cox).csproj +++ b/Samples/Statistics/Survival (Cox)/Survival (Cox).csproj @@ -1,175 +1,167 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {3AFDA17A-E489-49A7-827F-18DE4CDC7812} - WinExe - Properties - Survival.Cox - Survival %28Cox%29 - v4.0 - 512 - Survival.Cox.Program - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - - true - bin\x86\Debug\ - DEBUG;TRACE - full - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - bin\x86\Release\ - TRACE - true - pdbonly - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - framework.ico - - - - False - ..\..\..\Release\net40\Accord.dll - - - False - ..\..\..\Release\net40\Accord.Controls.dll - - - ..\..\..\Release\net40\Accord.IO.dll - - - False - ..\..\..\Release\net40\Accord.Math.dll - - - False - ..\..\..\Release\net40\Accord.Statistics.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Controls.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Math.dll - - - - 3.5 - - - - - - - False - ..\..\..\Externals\ZedGraph\ZedGraph.dll - - - - - Form - - - AboutBox.cs - - - Form - - - MainForm.cs - - - - - Form - - - TableSelectDialog.cs - - - - - AboutBox.cs - - - MainForm.cs - Designer - - - TableSelectDialog.cs - Designer - - - - - PreserveNewest - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - - - - + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {3AFDA17A-E489-49A7-827F-18DE4CDC7812} + WinExe + Properties + Survival.Cox + Survival %28Cox%29 + v4.0 + 512 + Survival.Cox.Program + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + framework.ico + + + + False + ..\..\..\Release\net40\Accord.dll + + + False + ..\..\..\Release\net40\Accord.Controls.dll + + + ..\..\..\Release\net40\Accord.IO.dll + + + False + ..\..\..\Release\net40\Accord.Math.dll + + + False + ..\..\..\Release\net40\Accord.Statistics.dll + + + + 3.5 + + + + + + + + False + ..\..\..\Externals\ZedGraph\ZedGraph.dll + + + + + Form + + + AboutBox.cs + + + Form + + + MainForm.cs + + + + + Form + + + TableSelectDialog.cs + + + + + AboutBox.cs + + + MainForm.cs + Designer + + + TableSelectDialog.cs + Designer + + + + + PreserveNewest + + + PreserveNewest + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + --> \ No newline at end of file diff --git a/Samples/Tutorials/Classification/0. Introduction/0. Introduction.csproj b/Samples/Tutorials/Classification/0. Introduction/0. Introduction.csproj index f1e479736..abbaf0eeb 100644 --- a/Samples/Tutorials/Classification/0. Introduction/0. Introduction.csproj +++ b/Samples/Tutorials/Classification/0. Introduction/0. Introduction.csproj @@ -1,112 +1,101 @@ - - - - Debug - x86 - 8.0.30703 - 2.0 - {15A29255-C03A-4757-8093-7873388CE4B9} - Exe - Properties - ClassificationSample - ClassificationSample - v4.0 - Client - 512 - - - x86 - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - x86 - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - False - ..\packages\Accord.2.14.0\lib\net40\Accord.dll - - - False - ..\packages\Accord.Controls.2.14.0\lib\net40\Accord.Controls.dll - - - False - ..\packages\Accord.Imaging.2.14.0\lib\net40\Accord.Imaging.dll - - - False - ..\packages\Accord.IO.2.14.0\lib\net40\Accord.IO.dll - - - False - ..\packages\Accord.MachineLearning.2.14.0\lib\net40\Accord.MachineLearning.dll - - - False - ..\packages\Accord.Math.2.14.0\lib\net40\Accord.Math.dll - - - False - ..\packages\Accord.Neuro.2.14.0\lib\net40\Accord.Neuro.dll - - - False - ..\packages\Accord.Statistics.2.14.0\lib\net40\Accord.Statistics.dll - - - ..\packages\AForge.2.2.5\lib\AForge.dll - - - ..\packages\AForge.Genetic.2.2.5\lib\AForge.Genetic.dll - - - ..\packages\AForge.Imaging.2.2.5\lib\AForge.Imaging.dll - - - ..\packages\AForge.Math.2.2.5\lib\AForge.Math.dll - - - ..\packages\AForge.Neuro.2.2.5\lib\AForge.Neuro.dll - - - - - - - - - - - - - - - - - - PreserveNewest - - - - + + + + Debug + x86 + 8.0.30703 + 2.0 + {15A29255-C03A-4757-8093-7873388CE4B9} + Exe + Properties + ClassificationSample + ClassificationSample + v4.0 + Client + 512 + 2b679e93 + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Accord.3.0.1-alpha\lib\net40\Accord.dll + + + ..\packages\Accord.Controls.3.0.1-alpha\lib\net40\Accord.Controls.dll + + + ..\packages\Accord.IO.3.0.1-alpha\lib\net40\Accord.IO.dll + + + ..\packages\Accord.MachineLearning.3.0.1-alpha\lib\net40\Accord.MachineLearning.dll + + + ..\packages\Accord.Math.3.0.1-alpha\lib\net40\Accord.Math.dll + + + ..\packages\Accord.Neuro.3.0.1-alpha\lib\net40\Accord.Neuro.dll + + + ..\packages\Accord.Statistics.3.0.1-alpha\lib\net40\Accord.Statistics.dll + + + + + + + + + + + + ..\packages\ZedGraph.5.1.6\lib\net35-Client\ZedGraph.dll + + + + + + + + + + PreserveNewest + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + --> \ No newline at end of file diff --git a/Samples/Statistics/Tabular filters/License-LGPL.txt b/Samples/Tutorials/Classification/0. Introduction/License-LGPL.txt similarity index 100% rename from Samples/Statistics/Tabular filters/License-LGPL.txt rename to Samples/Tutorials/Classification/0. Introduction/License-LGPL.txt diff --git a/Samples/Tutorials/Classification/0. Introduction/app.config b/Samples/Tutorials/Classification/0. Introduction/app.config index 87727e1b5..633960991 100644 --- a/Samples/Tutorials/Classification/0. Introduction/app.config +++ b/Samples/Tutorials/Classification/0. Introduction/app.config @@ -1,31 +1,35 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/Tutorials/Classification/0. Introduction/packages.config b/Samples/Tutorials/Classification/0. Introduction/packages.config index f9ac7c3fc..a54cc6bdd 100644 --- a/Samples/Tutorials/Classification/0. Introduction/packages.config +++ b/Samples/Tutorials/Classification/0. Introduction/packages.config @@ -1,16 +1,11 @@ - - - - - - - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/Samples/Tutorials/Classification/1. Linear SVMs/1. Linear SVMs.csproj b/Samples/Tutorials/Classification/1. Linear SVMs/1. Linear SVMs.csproj index 0ec2e0bcb..c88d97bb5 100644 --- a/Samples/Tutorials/Classification/1. Linear SVMs/1. Linear SVMs.csproj +++ b/Samples/Tutorials/Classification/1. Linear SVMs/1. Linear SVMs.csproj @@ -1,115 +1,109 @@ - - - - Debug - x86 - 8.0.30703 - 2.0 - {FA8AEE8F-2478-4342-B628-C09A2D5A6230} - Exe - Properties - ClassificationSample - ClassificationSample - v4.0 - Client - 512 - - - x86 - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - true - - - x86 - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - False - ..\packages\Accord.2.14.0\lib\net40\Accord.dll - - - False - ..\packages\Accord.Controls.2.14.0\lib\net40\Accord.Controls.dll - - - False - ..\packages\Accord.Imaging.2.14.0\lib\net40\Accord.Imaging.dll - - - False - ..\packages\Accord.IO.2.14.0\lib\net40\Accord.IO.dll - - - False - ..\packages\Accord.MachineLearning.2.14.0\lib\net40\Accord.MachineLearning.dll - - - False - ..\packages\Accord.Math.2.14.0\lib\net40\Accord.Math.dll - - - False - ..\packages\Accord.Neuro.2.14.0\lib\net40\Accord.Neuro.dll - - - False - ..\packages\Accord.Statistics.2.14.0\lib\net40\Accord.Statistics.dll - - - ..\packages\AForge.2.2.5\lib\AForge.dll - - - ..\packages\AForge.Genetic.2.2.5\lib\AForge.Genetic.dll - - - ..\packages\AForge.Imaging.2.2.5\lib\AForge.Imaging.dll - - - ..\packages\AForge.Math.2.2.5\lib\AForge.Math.dll - - - ..\packages\AForge.Neuro.2.2.5\lib\AForge.Neuro.dll - - - - - - - - - - - - - - - - - - - - - PreserveNewest - - - + + + + Debug + x86 + 8.0.30703 + 2.0 + {FA8AEE8F-2478-4342-B628-C09A2D5A6230} + Exe + Properties + ClassificationSample + ClassificationSample + v4.0 + Client + 512 + 2be176a1 + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + true + + + x86 + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + False + ..\packages\Accord.3.0.1-alpha\lib\net40\Accord.dll + + + False + ..\packages\Accord.Controls.3.0.1-alpha\lib\net40\Accord.Controls.dll + + + False + ..\packages\Accord.IO.3.0.1-alpha\lib\net40\Accord.IO.dll + + + False + ..\packages\Accord.MachineLearning.3.0.1-alpha\lib\net40\Accord.MachineLearning.dll + + + False + ..\packages\Accord.Math.3.0.1-alpha\lib\net40\Accord.Math.dll + + + False + ..\packages\Accord.Neuro.3.0.1-alpha\lib\net40\Accord.Neuro.dll + + + False + ..\packages\Accord.Statistics.3.0.1-alpha\lib\net40\Accord.Statistics.dll + + + + + + + + + + + + ..\packages\ZedGraph.5.1.6\lib\net35-Client\ZedGraph.dll + + + + + + + + + + + + + PreserveNewest + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + --> \ No newline at end of file diff --git a/Samples/Tutorials/Classification/1. Linear SVMs/License-LGPL.txt b/Samples/Tutorials/Classification/1. Linear SVMs/License-LGPL.txt new file mode 100644 index 0000000000..8ac0cecfb --- /dev/null +++ b/Samples/Tutorials/Classification/1. Linear SVMs/License-LGPL.txt @@ -0,0 +1,506 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + + + diff --git a/Samples/Tutorials/Classification/1. Linear SVMs/app.config b/Samples/Tutorials/Classification/1. Linear SVMs/app.config index 87727e1b5..633960991 100644 --- a/Samples/Tutorials/Classification/1. Linear SVMs/app.config +++ b/Samples/Tutorials/Classification/1. Linear SVMs/app.config @@ -1,31 +1,35 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/Tutorials/Classification/1. Linear SVMs/packages.config b/Samples/Tutorials/Classification/1. Linear SVMs/packages.config index f9ac7c3fc..a54cc6bdd 100644 --- a/Samples/Tutorials/Classification/1. Linear SVMs/packages.config +++ b/Samples/Tutorials/Classification/1. Linear SVMs/packages.config @@ -1,16 +1,11 @@ - - - - - - - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/Samples/Video/Kinect Capture/Accord.dll.config b/Samples/Video/Kinect Capture/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Video/Kinect Capture/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Video/Kinect Capture/Kinect Capture.csproj b/Samples/Video/Kinect Capture/Kinect Capture.csproj new file mode 100644 index 0000000000..3e729d443 --- /dev/null +++ b/Samples/Video/Kinect Capture/Kinect Capture.csproj @@ -0,0 +1,167 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {B4CB129D-51F9-4C86-B520-7AC50537A70B} + WinExe + Properties + SampleApp + Kinect Capture + v4.0 + 512 + + + 3.5 + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + SampleApp.Program + + + + ..\..\..\Release\net40\Accord.dll + + + ..\..\..\Release\net40\Accord.Controls.dll + + + ..\..\..\Release\net40\Accord.Controls.Imaging.dll + + + ..\..\..\Release\net40\Accord.Video.dll + + + ..\..\..\Release\net40\Accord.Video.Kinect.dll + + + + + + + + + Form + + + MainForm.cs + + + + + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + freenect.dll + Always + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + \ No newline at end of file diff --git a/Samples/Video/Kinect Capture/Kinect Capture.sln b/Samples/Video/Kinect Capture/Kinect Capture.sln new file mode 100644 index 0000000000..e5a67a836 --- /dev/null +++ b/Samples/Video/Kinect Capture/Kinect Capture.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C# Express 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kinect Capture", "Kinect Capture.csproj", "{B4CB129D-51F9-4C86-B520-7AC50537A70B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B4CB129D-51F9-4C86-B520-7AC50537A70B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B4CB129D-51F9-4C86-B520-7AC50537A70B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B4CB129D-51F9-4C86-B520-7AC50537A70B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B4CB129D-51F9-4C86-B520-7AC50537A70B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/Video/Kinect Capture/MainForm.Designer.cs b/Samples/Video/Kinect Capture/MainForm.Designer.cs new file mode 100644 index 0000000000..83a50625b --- /dev/null +++ b/Samples/Video/Kinect Capture/MainForm.Designer.cs @@ -0,0 +1,343 @@ +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.components = new System.ComponentModel.Container( ); + this.label1 = new System.Windows.Forms.Label( ); + this.devicesCombo = new System.Windows.Forms.ComboBox( ); + this.connectButton = new System.Windows.Forms.Button( ); + this.disconnectButton = new System.Windows.Forms.Button( ); + this.tableLayoutPanel = new System.Windows.Forms.TableLayoutPanel( ); + this.leftPanel = new System.Windows.Forms.Panel( ); + this.groupBox1 = new System.Windows.Forms.GroupBox( ); + this.videoCameraPlayer = new AForge.Controls.VideoSourcePlayer( ); + this.rightPanel = new System.Windows.Forms.Panel( ); + this.groupBox2 = new System.Windows.Forms.GroupBox( ); + this.depthCameraPlayer = new AForge.Controls.VideoSourcePlayer( ); + this.label2 = new System.Windows.Forms.Label( ); + this.ledColorCombo = new System.Windows.Forms.ComboBox( ); + this.label3 = new System.Windows.Forms.Label( ); + this.tiltUpDown = new System.Windows.Forms.NumericUpDown( ); + this.label4 = new System.Windows.Forms.Label( ); + this.videoModeCombo = new System.Windows.Forms.ComboBox( ); + this.statusStrip = new System.Windows.Forms.StatusStrip( ); + this.accelerometerLabel = new System.Windows.Forms.ToolStripStatusLabel( ); + this.timer = new System.Windows.Forms.Timer( this.components ); + this.tableLayoutPanel.SuspendLayout( ); + this.leftPanel.SuspendLayout( ); + this.groupBox1.SuspendLayout( ); + this.rightPanel.SuspendLayout( ); + this.groupBox2.SuspendLayout( ); + ( (System.ComponentModel.ISupportInitialize) ( this.tiltUpDown ) ).BeginInit( ); + this.statusStrip.SuspendLayout( ); + this.SuspendLayout( ); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point( 10, 13 ); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size( 75, 13 ); + this.label1.TabIndex = 0; + this.label1.Text = "Select device:"; + // + // devicesCombo + // + this.devicesCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.devicesCombo.FormattingEnabled = true; + this.devicesCombo.Location = new System.Drawing.Point( 90, 10 ); + this.devicesCombo.Name = "devicesCombo"; + this.devicesCombo.Size = new System.Drawing.Size( 121, 21 ); + this.devicesCombo.TabIndex = 1; + // + // connectButton + // + this.connectButton.Location = new System.Drawing.Point( 220, 10 ); + this.connectButton.Name = "connectButton"; + this.connectButton.Size = new System.Drawing.Size( 75, 23 ); + this.connectButton.TabIndex = 2; + this.connectButton.Text = "&Connect"; + this.connectButton.UseVisualStyleBackColor = true; + this.connectButton.Click += new System.EventHandler( this.connectButton_Click ); + // + // disconnectButton + // + this.disconnectButton.Location = new System.Drawing.Point( 300, 10 ); + this.disconnectButton.Name = "disconnectButton"; + this.disconnectButton.Size = new System.Drawing.Size( 75, 23 ); + this.disconnectButton.TabIndex = 3; + this.disconnectButton.Text = "&Disconnect"; + this.disconnectButton.UseVisualStyleBackColor = true; + this.disconnectButton.Click += new System.EventHandler( this.disconnectButton_Click ); + // + // tableLayoutPanel + // + this.tableLayoutPanel.Anchor = ( (System.Windows.Forms.AnchorStyles) ( ( ( ( System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom ) + | System.Windows.Forms.AnchorStyles.Left ) + | System.Windows.Forms.AnchorStyles.Right ) ) ); + this.tableLayoutPanel.ColumnCount = 2; + this.tableLayoutPanel.ColumnStyles.Add( new System.Windows.Forms.ColumnStyle( System.Windows.Forms.SizeType.Percent, 50F ) ); + this.tableLayoutPanel.ColumnStyles.Add( new System.Windows.Forms.ColumnStyle( System.Windows.Forms.SizeType.Percent, 50F ) ); + this.tableLayoutPanel.Controls.Add( this.leftPanel, 0, 0 ); + this.tableLayoutPanel.Controls.Add( this.rightPanel, 1, 0 ); + this.tableLayoutPanel.Location = new System.Drawing.Point( 0, 40 ); + this.tableLayoutPanel.Name = "tableLayoutPanel"; + this.tableLayoutPanel.RowCount = 1; + this.tableLayoutPanel.RowStyles.Add( new System.Windows.Forms.RowStyle( System.Windows.Forms.SizeType.Percent, 50F ) ); + this.tableLayoutPanel.Size = new System.Drawing.Size( 826, 295 ); + this.tableLayoutPanel.TabIndex = 4; + // + // leftPanel + // + this.leftPanel.Controls.Add( this.groupBox1 ); + this.leftPanel.Dock = System.Windows.Forms.DockStyle.Fill; + this.leftPanel.Location = new System.Drawing.Point( 3, 3 ); + this.leftPanel.Name = "leftPanel"; + this.leftPanel.Size = new System.Drawing.Size( 407, 289 ); + this.leftPanel.TabIndex = 0; + // + // groupBox1 + // + this.groupBox1.Anchor = ( (System.Windows.Forms.AnchorStyles) ( ( ( ( System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom ) + | System.Windows.Forms.AnchorStyles.Left ) + | System.Windows.Forms.AnchorStyles.Right ) ) ); + this.groupBox1.Controls.Add( this.videoCameraPlayer ); + this.groupBox1.Location = new System.Drawing.Point( 5, 5 ); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size( 396, 277 ); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Video Camera"; + // + // videoCameraPlayer + // + this.videoCameraPlayer.Anchor = ( (System.Windows.Forms.AnchorStyles) ( ( ( ( System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom ) + | System.Windows.Forms.AnchorStyles.Left ) + | System.Windows.Forms.AnchorStyles.Right ) ) ); + this.videoCameraPlayer.BackColor = System.Drawing.SystemColors.ControlDarkDark; + this.videoCameraPlayer.ForeColor = System.Drawing.Color.FromArgb( ( (int) ( ( (byte) ( 192 ) ) ) ), ( (int) ( ( (byte) ( 192 ) ) ) ), ( (int) ( ( (byte) ( 255 ) ) ) ) ); + this.videoCameraPlayer.Location = new System.Drawing.Point( 11, 15 ); + this.videoCameraPlayer.Name = "videoCameraPlayer"; + this.videoCameraPlayer.Size = new System.Drawing.Size( 373, 253 ); + this.videoCameraPlayer.TabIndex = 0; + this.videoCameraPlayer.VideoSource = null; + // + // rightPanel + // + this.rightPanel.Controls.Add( this.groupBox2 ); + this.rightPanel.Dock = System.Windows.Forms.DockStyle.Fill; + this.rightPanel.Location = new System.Drawing.Point( 416, 3 ); + this.rightPanel.Name = "rightPanel"; + this.rightPanel.Size = new System.Drawing.Size( 407, 289 ); + this.rightPanel.TabIndex = 1; + // + // groupBox2 + // + this.groupBox2.Anchor = ( (System.Windows.Forms.AnchorStyles) ( ( ( ( System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom ) + | System.Windows.Forms.AnchorStyles.Left ) + | System.Windows.Forms.AnchorStyles.Right ) ) ); + this.groupBox2.Controls.Add( this.depthCameraPlayer ); + this.groupBox2.Location = new System.Drawing.Point( 6, 6 ); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size( 395, 277 ); + this.groupBox2.TabIndex = 1; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Depth Camera"; + // + // depthCameraPlayer + // + this.depthCameraPlayer.Anchor = ( (System.Windows.Forms.AnchorStyles) ( ( ( ( System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom ) + | System.Windows.Forms.AnchorStyles.Left ) + | System.Windows.Forms.AnchorStyles.Right ) ) ); + this.depthCameraPlayer.BackColor = System.Drawing.SystemColors.ControlDarkDark; + this.depthCameraPlayer.ForeColor = System.Drawing.Color.FromArgb( ( (int) ( ( (byte) ( 192 ) ) ) ), ( (int) ( ( (byte) ( 192 ) ) ) ), ( (int) ( ( (byte) ( 255 ) ) ) ) ); + this.depthCameraPlayer.Location = new System.Drawing.Point( 11, 15 ); + this.depthCameraPlayer.Name = "depthCameraPlayer"; + this.depthCameraPlayer.Size = new System.Drawing.Size( 373, 253 ); + this.depthCameraPlayer.TabIndex = 0; + this.depthCameraPlayer.Text = "videoSourcePlayer2"; + this.depthCameraPlayer.VideoSource = null; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point( 390, 13 ); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size( 31, 13 ); + this.label2.TabIndex = 6; + this.label2.Text = "LED:"; + // + // ledColorCombo + // + this.ledColorCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.ledColorCombo.FormattingEnabled = true; + this.ledColorCombo.Items.AddRange( new object[] { + "Off", + "Green", + "Red", + "Yellow", + "Blinking Green", + "Blinking Red-Yellow"} ); + this.ledColorCombo.Location = new System.Drawing.Point( 425, 10 ); + this.ledColorCombo.Name = "ledColorCombo"; + this.ledColorCombo.Size = new System.Drawing.Size( 95, 21 ); + this.ledColorCombo.TabIndex = 7; + this.ledColorCombo.SelectedIndexChanged += new System.EventHandler( this.ledColorCombo_SelectedIndexChanged ); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point( 530, 13 ); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size( 24, 13 ); + this.label3.TabIndex = 8; + this.label3.Text = "Tilt:"; + // + // tiltUpDown + // + this.tiltUpDown.Location = new System.Drawing.Point( 560, 10 ); + this.tiltUpDown.Maximum = new decimal( new int[] { + 31, + 0, + 0, + 0} ); + this.tiltUpDown.Minimum = new decimal( new int[] { + 31, + 0, + 0, + -2147483648} ); + this.tiltUpDown.Name = "tiltUpDown"; + this.tiltUpDown.Size = new System.Drawing.Size( 62, 20 ); + this.tiltUpDown.TabIndex = 9; + this.tiltUpDown.ValueChanged += new System.EventHandler( this.tiltUpDown_ValueChanged ); + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point( 635, 13 ); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size( 66, 13 ); + this.label4.TabIndex = 10; + this.label4.Text = "Video mode:"; + // + // videoModeCombo + // + this.videoModeCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.videoModeCombo.FormattingEnabled = true; + this.videoModeCombo.Items.AddRange( new object[] { + "Color", + "Bayer", + "InfraRed"} ); + this.videoModeCombo.Location = new System.Drawing.Point( 706, 10 ); + this.videoModeCombo.Name = "videoModeCombo"; + this.videoModeCombo.Size = new System.Drawing.Size( 100, 21 ); + this.videoModeCombo.TabIndex = 11; + // + // statusStrip + // + this.statusStrip.Items.AddRange( new System.Windows.Forms.ToolStripItem[] { + this.accelerometerLabel} ); + this.statusStrip.Location = new System.Drawing.Point( 0, 338 ); + this.statusStrip.Name = "statusStrip"; + this.statusStrip.Size = new System.Drawing.Size( 827, 22 ); + this.statusStrip.TabIndex = 12; + this.statusStrip.Text = "statusStrip1"; + // + // accelerometerLabel + // + this.accelerometerLabel.AutoSize = false; + this.accelerometerLabel.Name = "accelerometerLabel"; + this.accelerometerLabel.Size = new System.Drawing.Size( 781, 17 ); + this.accelerometerLabel.Spring = true; + this.accelerometerLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // timer + // + this.timer.Tick += new System.EventHandler( this.timer_Tick ); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 13F ); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size( 827, 360 ); + this.Controls.Add( this.statusStrip ); + this.Controls.Add( this.videoModeCombo ); + this.Controls.Add( this.label4 ); + this.Controls.Add( this.tiltUpDown ); + this.Controls.Add( this.label3 ); + this.Controls.Add( this.ledColorCombo ); + this.Controls.Add( this.label2 ); + this.Controls.Add( this.tableLayoutPanel ); + this.Controls.Add( this.disconnectButton ); + this.Controls.Add( this.connectButton ); + this.Controls.Add( this.devicesCombo ); + this.Controls.Add( this.label1 ); + this.MinimumSize = new System.Drawing.Size( 840, 390 ); + this.Name = "MainForm"; + this.Text = "Kinect Capture"; + this.Load += new System.EventHandler( this.MainForm_Load ); + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler( this.MainForm_FormClosing ); + this.tableLayoutPanel.ResumeLayout( false ); + this.leftPanel.ResumeLayout( false ); + this.groupBox1.ResumeLayout( false ); + this.rightPanel.ResumeLayout( false ); + this.groupBox2.ResumeLayout( false ); + ( (System.ComponentModel.ISupportInitialize) ( this.tiltUpDown ) ).EndInit( ); + this.statusStrip.ResumeLayout( false ); + this.statusStrip.PerformLayout( ); + this.ResumeLayout( false ); + this.PerformLayout( ); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.ComboBox devicesCombo; + private System.Windows.Forms.Button connectButton; + private System.Windows.Forms.Button disconnectButton; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel; + private System.Windows.Forms.Panel leftPanel; + private System.Windows.Forms.Panel rightPanel; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.GroupBox groupBox2; + private AForge.Controls.VideoSourcePlayer videoCameraPlayer; + private AForge.Controls.VideoSourcePlayer depthCameraPlayer; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.ComboBox ledColorCombo; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.NumericUpDown tiltUpDown; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.ComboBox videoModeCombo; + private System.Windows.Forms.StatusStrip statusStrip; + private System.Windows.Forms.ToolStripStatusLabel accelerometerLabel; + private System.Windows.Forms.Timer timer; + } +} + diff --git a/Samples/Video/Kinect Capture/MainForm.cs b/Samples/Video/Kinect Capture/MainForm.cs new file mode 100644 index 0000000000..7767e2b43 --- /dev/null +++ b/Samples/Video/Kinect Capture/MainForm.cs @@ -0,0 +1,206 @@ +// Kinect Capture sample application +// AForge.NET Framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2009-2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Windows.Forms; + +using AForge.Video; +using AForge.Video.Kinect; + +namespace SampleApp +{ + public partial class MainForm : Form + { + private Kinect kinectDevice = null; + private KinectVideoCamera videoCamera = null; + private KinectDepthCamera depthCamera = null; + + private static readonly LedColorOption[] ledMode = + { + LedColorOption.Off, LedColorOption.Green, LedColorOption.Red, + LedColorOption.Yellow, LedColorOption.BlinkGreen, LedColorOption.BlinkRedYellow + }; + + public MainForm() + { + InitializeComponent(); + } + + // On Main form loaded + private void MainForm_Load(object sender, EventArgs e) + { + if (Kinect.DeviceCount == 0) + { + devicesCombo.Items.Add("No Kinect devices"); + } + else + { + for (int i = 0; i < Kinect.DeviceCount; i++) + { + devicesCombo.Items.Add("Device " + i); + } + } + + devicesCombo.SelectedIndex = 0; + videoModeCombo.SelectedIndex = 0; + EnableConnectionControls(true); + } + + // On closing the main form + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + Disconnect(); + } + + // Enable/disable controls related to connecton/disconnection + private void EnableConnectionControls(bool enable) + { + devicesCombo.Enabled = enable; + videoModeCombo.Enabled = enable; + connectButton.Enabled = enable; + disconnectButton.Enabled = !enable; + ledColorCombo.Enabled = !enable; + tiltUpDown.Enabled = !enable; + } + + // On "Connect" butto clicked + private void connectButton_Click(object sender, EventArgs e) + { + if (Connect()) + { + EnableConnectionControls(false); + } + } + + // On "Disconnect" butto clicked + private void disconnectButton_Click(object sender, EventArgs e) + { + Disconnect(); + EnableConnectionControls(true); + } + + // Connect to Kinect cameras + private bool Connect() + { + bool ret = false; + + Cursor = Cursors.WaitCursor; + + if (Kinect.DeviceCount != 0) + { + int deviceID = devicesCombo.SelectedIndex; + + try + { + kinectDevice = Kinect.GetDevice(deviceID); + + if (videoCamera == null) + { + videoCamera = kinectDevice.GetVideoCamera(); + videoCamera.CameraMode = (videoModeCombo.SelectedIndex == 0) ? VideoCameraMode.Color : + ((videoModeCombo.SelectedIndex == 1) ? VideoCameraMode.Bayer : VideoCameraMode.InfraRed); + videoCameraPlayer.VideoSource = videoCamera; + videoCameraPlayer.Start(); + } + + if (depthCamera == null) + { + depthCamera = kinectDevice.GetDepthCamera(); + depthCameraPlayer.VideoSource = depthCamera; + depthCameraPlayer.Start(); + } + + ledColorCombo.SelectedIndex = 0; + + if (tiltUpDown.Value != 0) + { + tiltUpDown.Value = 0; + } + else + { + kinectDevice.SetMotorTilt((int)tiltUpDown.Value); + } + + timer.Start(); + + ret = true; + } + catch (Exception ex) + { + MessageBox.Show("Failed connecting to Kinect device.\n" + ex.Message, + "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + + Disconnect(); + } + } + + Cursor = Cursors.Default; + + return ret; + } + + // Disconnect from Kinect cameras + private void Disconnect() + { + timer.Stop(); + + if (videoCamera != null) + { + videoCameraPlayer.VideoSource = null; + videoCamera.Stop(); + videoCamera = null; + } + + if (depthCamera != null) + { + depthCameraPlayer.VideoSource = null; + depthCamera.Stop(); + depthCamera = null; + } + + if (kinectDevice != null) + { + kinectDevice.Dispose(); + kinectDevice = null; + } + } + + // Change color of the LED + private void ledColorCombo_SelectedIndexChanged(object sender, EventArgs e) + { + if (kinectDevice != null) + { + kinectDevice.SetLedColor(ledMode[ledColorCombo.SelectedIndex]); + } + } + + // Tilt the camera up/down + private void tiltUpDown_ValueChanged(object sender, EventArgs e) + { + if (kinectDevice != null) + { + kinectDevice.SetMotorTilt((int)tiltUpDown.Value); + } + } + + // Read accelerometer values on timer tick + private void timer_Tick(object sender, EventArgs e) + { + double x, y, z; + + kinectDevice.GetAccelerometerValues(out x, out y, out z); + + accelerometerLabel.Text = string.Format( + "Accelerometer values (m/(s*s)): x = {0:F4}, y = {1:F4}, z = {2:F4}", x, y, z); + } + } +} diff --git a/Samples/Video/Kinect Capture/MainForm.resx b/Samples/Video/Kinect Capture/MainForm.resx new file mode 100644 index 0000000000..6a6d42593 --- /dev/null +++ b/Samples/Video/Kinect Capture/MainForm.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 126, 17 + + \ No newline at end of file diff --git a/Samples/Video/Kinect Capture/Program.cs b/Samples/Video/Kinect Capture/Program.cs new file mode 100644 index 0000000000..3e89ca20f --- /dev/null +++ b/Samples/Video/Kinect Capture/Program.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; + +namespace SampleApp +{ + static class Program + { + + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + } +} diff --git a/Samples/Video/Kinect Capture/Properties/AssemblyInfo.cs b/Samples/Video/Kinect Capture/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..7a28c143a --- /dev/null +++ b/Samples/Video/Kinect Capture/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle( "Kinect Capture" )] +[assembly: AssemblyDescription( "Kinect Capture Sample" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "AForge" )] +[assembly: AssemblyProduct( "AForge.NET" )] +[assembly: AssemblyCopyright( "AForge © 2011" )] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible( false )] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid( "9824d802-a89b-47b2-902a-82d4569f2a9f" )] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion( "1.0.0.0" )] +[assembly: AssemblyFileVersion( "1.0.0.0" )] diff --git a/Samples/Video/Kinect Capture/Properties/Resources.Designer.cs b/Samples/Video/Kinect Capture/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..7b58e53ee --- /dev/null +++ b/Samples/Video/Kinect Capture/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Samples/Video/Kinect Capture/Properties/Resources.resx b/Samples/Video/Kinect Capture/Properties/Resources.resx new file mode 100644 index 0000000000..af7dbebba --- /dev/null +++ b/Samples/Video/Kinect Capture/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Video/Kinect Capture/Properties/Settings.Designer.cs b/Samples/Video/Kinect Capture/Properties/Settings.Designer.cs new file mode 100644 index 0000000000..dbc9e5d22 --- /dev/null +++ b/Samples/Video/Kinect Capture/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Samples/Video/Kinect Capture/Properties/Settings.settings b/Samples/Video/Kinect Capture/Properties/Settings.settings new file mode 100644 index 0000000000..39645652a --- /dev/null +++ b/Samples/Video/Kinect Capture/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Samples/Video/Kinect Capture/app.config b/Samples/Video/Kinect Capture/app.config new file mode 100644 index 0000000000..57c0f2cbc --- /dev/null +++ b/Samples/Video/Kinect Capture/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Samples/Video/Snapshot Maker/Accord.dll.config b/Samples/Video/Snapshot Maker/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Video/Snapshot Maker/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Video/Snapshot Maker/MainForm.Designer.cs b/Samples/Video/Snapshot Maker/MainForm.Designer.cs new file mode 100644 index 0000000000..0205b08bf --- /dev/null +++ b/Samples/Video/Snapshot Maker/MainForm.Designer.cs @@ -0,0 +1,219 @@ +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.components = new System.ComponentModel.Container(); + this.label1 = new System.Windows.Forms.Label(); + this.devicesCombo = new System.Windows.Forms.ComboBox(); + this.label2 = new System.Windows.Forms.Label(); + this.videoResolutionsCombo = new System.Windows.Forms.ComboBox(); + this.snapshotResolutionsCombo = new System.Windows.Forms.ComboBox(); + this.label3 = new System.Windows.Forms.Label(); + this.connectButton = new System.Windows.Forms.Button(); + this.disconnectButton = new System.Windows.Forms.Button(); + this.panel1 = new System.Windows.Forms.Panel(); + this.videoSourcePlayer = new AForge.Controls.VideoSourcePlayer(); + this.toolTip = new System.Windows.Forms.ToolTip(this.components); + this.triggerButton = new System.Windows.Forms.Button(); + this.panel1.SuspendLayout(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(15, 28); + this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(111, 20); + this.label1.TabIndex = 0; + this.label1.Text = "Video devices:"; + // + // devicesCombo + // + this.devicesCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.devicesCombo.FormattingEnabled = true; + this.devicesCombo.Location = new System.Drawing.Point(142, 23); + this.devicesCombo.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.devicesCombo.Name = "devicesCombo"; + this.devicesCombo.Size = new System.Drawing.Size(470, 28); + this.devicesCombo.TabIndex = 1; + this.devicesCombo.SelectedIndexChanged += new System.EventHandler(this.devicesCombo_SelectedIndexChanged); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(15, 74); + this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(124, 20); + this.label2.TabIndex = 2; + this.label2.Text = "Video resoluton:"; + // + // videoResolutionsCombo + // + this.videoResolutionsCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.videoResolutionsCombo.FormattingEnabled = true; + this.videoResolutionsCombo.Location = new System.Drawing.Point(142, 69); + this.videoResolutionsCombo.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.videoResolutionsCombo.Name = "videoResolutionsCombo"; + this.videoResolutionsCombo.Size = new System.Drawing.Size(148, 28); + this.videoResolutionsCombo.TabIndex = 3; + // + // snapshotResolutionsCombo + // + this.snapshotResolutionsCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.snapshotResolutionsCombo.FormattingEnabled = true; + this.snapshotResolutionsCombo.Location = new System.Drawing.Point(465, 69); + this.snapshotResolutionsCombo.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.snapshotResolutionsCombo.Name = "snapshotResolutionsCombo"; + this.snapshotResolutionsCombo.Size = new System.Drawing.Size(148, 28); + this.snapshotResolutionsCombo.TabIndex = 4; + this.toolTip.SetToolTip(this.snapshotResolutionsCombo, "Press shutter button on your camera to make snapshot"); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(308, 74); + this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(152, 20); + this.label3.TabIndex = 5; + this.label3.Text = "Snapshot resoluton:"; + this.toolTip.SetToolTip(this.label3, "Press shutter button on your camera to make snapshot"); + // + // connectButton + // + this.connectButton.Location = new System.Drawing.Point(645, 23); + this.connectButton.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.connectButton.Name = "connectButton"; + this.connectButton.Size = new System.Drawing.Size(112, 35); + this.connectButton.TabIndex = 6; + this.connectButton.Text = "&Connect"; + this.connectButton.UseVisualStyleBackColor = true; + this.connectButton.Click += new System.EventHandler(this.connectButton_Click); + // + // disconnectButton + // + this.disconnectButton.Location = new System.Drawing.Point(645, 69); + this.disconnectButton.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.disconnectButton.Name = "disconnectButton"; + this.disconnectButton.Size = new System.Drawing.Size(112, 35); + this.disconnectButton.TabIndex = 7; + this.disconnectButton.Text = "&Disconnect"; + this.disconnectButton.UseVisualStyleBackColor = true; + this.disconnectButton.Click += new System.EventHandler(this.disconnectButton_Click); + // + // panel1 + // + this.panel1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.panel1.Controls.Add(this.videoSourcePlayer); + this.panel1.Location = new System.Drawing.Point(0, 162); + this.panel1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(780, 463); + this.panel1.TabIndex = 8; + // + // videoSourcePlayer + // + this.videoSourcePlayer.AutoSizeControl = true; + this.videoSourcePlayer.BackColor = System.Drawing.SystemColors.ControlDark; + this.videoSourcePlayer.Dock = System.Windows.Forms.DockStyle.Fill; + this.videoSourcePlayer.ForeColor = System.Drawing.Color.DarkRed; + this.videoSourcePlayer.Location = new System.Drawing.Point(0, 0); + this.videoSourcePlayer.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.videoSourcePlayer.Name = "videoSourcePlayer"; + this.videoSourcePlayer.Size = new System.Drawing.Size(780, 463); + this.videoSourcePlayer.TabIndex = 0; + this.videoSourcePlayer.VideoSource = null; + // + // toolTip + // + this.toolTip.AutoPopDelay = 5000; + this.toolTip.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(255)))), ((int)(((byte)(192))))); + this.toolTip.InitialDelay = 100; + this.toolTip.ReshowDelay = 100; + // + // triggerButton + // + this.triggerButton.Location = new System.Drawing.Point(645, 115); + this.triggerButton.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.triggerButton.Name = "triggerButton"; + this.triggerButton.Size = new System.Drawing.Size(112, 35); + this.triggerButton.TabIndex = 9; + this.triggerButton.Text = "&Trigger"; + this.triggerButton.UseVisualStyleBackColor = true; + this.triggerButton.Click += new System.EventHandler(this.triggerButton_Click); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(778, 622); + this.Controls.Add(this.triggerButton); + this.Controls.Add(this.panel1); + this.Controls.Add(this.disconnectButton); + this.Controls.Add(this.connectButton); + this.Controls.Add(this.label3); + this.Controls.Add(this.snapshotResolutionsCombo); + this.Controls.Add(this.videoResolutionsCombo); + this.Controls.Add(this.label2); + this.Controls.Add(this.devicesCombo); + this.Controls.Add(this.label1); + this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.MinimumSize = new System.Drawing.Size(792, 647); + this.Name = "MainForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Snapshot Maker"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + this.panel1.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.ComboBox devicesCombo; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.ComboBox videoResolutionsCombo; + private System.Windows.Forms.ComboBox snapshotResolutionsCombo; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Button connectButton; + private System.Windows.Forms.Button disconnectButton; + private System.Windows.Forms.Panel panel1; + private AForge.Controls.VideoSourcePlayer videoSourcePlayer; + private System.Windows.Forms.ToolTip toolTip; + private System.Windows.Forms.Button triggerButton; + } +} + diff --git a/Samples/Video/Snapshot Maker/MainForm.cs b/Samples/Video/Snapshot Maker/MainForm.cs new file mode 100644 index 0000000000..6a2460bf2 --- /dev/null +++ b/Samples/Video/Snapshot Maker/MainForm.cs @@ -0,0 +1,220 @@ +// Snapshot Maker sample application +// AForge.NET Framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2009-2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +using AForge.Video; +using AForge.Video.DirectShow; + +namespace SampleApp +{ + public partial class MainForm : Form + { + private FilterInfoCollection videoDevices; + private VideoCaptureDevice videoDevice; + private VideoCapabilities[] videoCapabilities; + private VideoCapabilities[] snapshotCapabilities; + + private SnapshotForm snapshotForm = null; + + public MainForm( ) + { + InitializeComponent( ); + } + + // Main form is loaded + private void MainForm_Load( object sender, EventArgs e ) + { + // enumerate video devices + videoDevices = new FilterInfoCollection( FilterCategory.VideoInputDevice ); + + if ( videoDevices.Count != 0 ) + { + // add all devices to combo + foreach ( FilterInfo device in videoDevices ) + { + devicesCombo.Items.Add( device.Name ); + } + } + else + { + devicesCombo.Items.Add( "No DirectShow devices found" ); + } + + devicesCombo.SelectedIndex = 0; + + EnableConnectionControls( true ); + } + + // Closing the main form + private void MainForm_FormClosing( object sender, FormClosingEventArgs e ) + { + Disconnect( ); + } + + // Enable/disable connection related controls + private void EnableConnectionControls( bool enable ) + { + devicesCombo.Enabled = enable; + videoResolutionsCombo.Enabled = enable; + snapshotResolutionsCombo.Enabled = enable; + connectButton.Enabled = enable; + disconnectButton.Enabled = !enable; + triggerButton.Enabled = ( !enable ) && ( snapshotCapabilities.Length != 0 ); + } + + // New video device is selected + private void devicesCombo_SelectedIndexChanged( object sender, EventArgs e ) + { + if ( videoDevices.Count != 0 ) + { + videoDevice = new VideoCaptureDevice( videoDevices[devicesCombo.SelectedIndex].MonikerString ); + EnumeratedSupportedFrameSizes( videoDevice ); + } + } + + // Collect supported video and snapshot sizes + private void EnumeratedSupportedFrameSizes( VideoCaptureDevice videoDevice ) + { + this.Cursor = Cursors.WaitCursor; + + videoResolutionsCombo.Items.Clear( ); + snapshotResolutionsCombo.Items.Clear( ); + + try + { + videoCapabilities = videoDevice.VideoCapabilities; + snapshotCapabilities = videoDevice.SnapshotCapabilities; + + foreach ( VideoCapabilities capabilty in videoCapabilities ) + { + videoResolutionsCombo.Items.Add( string.Format( "{0} x {1}", + capabilty.FrameSize.Width, capabilty.FrameSize.Height ) ); + } + + foreach ( VideoCapabilities capabilty in snapshotCapabilities ) + { + snapshotResolutionsCombo.Items.Add( string.Format( "{0} x {1}", + capabilty.FrameSize.Width, capabilty.FrameSize.Height ) ); + } + + if ( videoCapabilities.Length == 0 ) + { + videoResolutionsCombo.Items.Add( "Not supported" ); + } + if ( snapshotCapabilities.Length == 0 ) + { + snapshotResolutionsCombo.Items.Add( "Not supported" ); + } + + videoResolutionsCombo.SelectedIndex = 0; + snapshotResolutionsCombo.SelectedIndex = 0; + } + finally + { + this.Cursor = Cursors.Default; + } + } + + // On "Connect" button clicked + private void connectButton_Click( object sender, EventArgs e ) + { + if ( videoDevice != null ) + { + if ( ( videoCapabilities != null ) && ( videoCapabilities.Length != 0 ) ) + { + videoDevice.VideoResolution = videoCapabilities[videoResolutionsCombo.SelectedIndex]; + } + + if ( ( snapshotCapabilities != null ) && ( snapshotCapabilities.Length != 0 ) ) + { + videoDevice.ProvideSnapshots = true; + videoDevice.SnapshotResolution = snapshotCapabilities[snapshotResolutionsCombo.SelectedIndex]; + videoDevice.SnapshotFrame += new NewFrameEventHandler( videoDevice_SnapshotFrame ); + } + + EnableConnectionControls( false ); + + videoSourcePlayer.VideoSource = videoDevice; + videoSourcePlayer.Start( ); + } + } + + // On "Disconnect" button clicked + private void disconnectButton_Click( object sender, EventArgs e ) + { + Disconnect( ); + } + + // Disconnect from video device + private void Disconnect( ) + { + if ( videoSourcePlayer.VideoSource != null ) + { + // stop video device + videoSourcePlayer.SignalToStop( ); + videoSourcePlayer.WaitForStop( ); + videoSourcePlayer.VideoSource = null; + + if ( videoDevice.ProvideSnapshots ) + { + videoDevice.SnapshotFrame -= new NewFrameEventHandler( videoDevice_SnapshotFrame ); + } + + EnableConnectionControls( true ); + } + } + + // Simulate snapshot trigger + private void triggerButton_Click( object sender, EventArgs e ) + { + if ( ( videoDevice != null ) && ( videoDevice.ProvideSnapshots ) ) + { + videoDevice.SimulateTrigger( ); + } + } + + // New snapshot frame is available + private void videoDevice_SnapshotFrame( object sender, NewFrameEventArgs eventArgs ) + { + Console.WriteLine( eventArgs.Frame.Size ); + + ShowSnapshot( (Bitmap) eventArgs.Frame.Clone( ) ); + } + + private void ShowSnapshot( Bitmap snapshot ) + { + if ( InvokeRequired ) + { + Invoke( new Action( ShowSnapshot ), snapshot ); + } + else + { + if ( snapshotForm == null ) + { + snapshotForm = new SnapshotForm( ); + snapshotForm.FormClosed += new FormClosedEventHandler( snapshotForm_FormClosed ); + snapshotForm.Show( ); + } + + snapshotForm.SetImage( snapshot ); + } + } + + private void snapshotForm_FormClosed( object sender, FormClosedEventArgs e ) + { + snapshotForm = null; + } + } +} diff --git a/Samples/Video/Snapshot Maker/MainForm.resx b/Samples/Video/Snapshot Maker/MainForm.resx new file mode 100644 index 0000000000..f587e1de7 --- /dev/null +++ b/Samples/Video/Snapshot Maker/MainForm.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 17, 17 + + \ No newline at end of file diff --git a/Samples/Video/Snapshot Maker/Program.cs b/Samples/Video/Snapshot Maker/Program.cs new file mode 100644 index 0000000000..316268492 --- /dev/null +++ b/Samples/Video/Snapshot Maker/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Windows.Forms; + +namespace SampleApp +{ + static class Program + { + [STAThread] + static void Main() + { + if (Environment.OSVersion.Version.Major >= 6) + SetProcessDPIAware(); + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + + [System.Runtime.InteropServices.DllImport("user32.dll")] + private static extern bool SetProcessDPIAware(); + } +} diff --git a/Samples/Video/Snapshot Maker/Properties/AssemblyInfo.cs b/Samples/Video/Snapshot Maker/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..3c9636d54 --- /dev/null +++ b/Samples/Video/Snapshot Maker/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle( "Snapshot Maker" )] +[assembly: AssemblyDescription( "Snapshot Maker Sample" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "AForge" )] +[assembly: AssemblyProduct( "AForge.NET" )] +[assembly: AssemblyCopyright( "AForge © 2011" )] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible( false )] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid( "089bf173-4722-4311-baeb-fc300f4b344a" )] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion( "1.0.0.0" )] +[assembly: AssemblyFileVersion( "1.0.0.0" )] diff --git a/Samples/Video/Snapshot Maker/Properties/Resources.Designer.cs b/Samples/Video/Snapshot Maker/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..7b58e53ee --- /dev/null +++ b/Samples/Video/Snapshot Maker/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Samples/Video/Snapshot Maker/Properties/Resources.resx b/Samples/Video/Snapshot Maker/Properties/Resources.resx new file mode 100644 index 0000000000..af7dbebba --- /dev/null +++ b/Samples/Video/Snapshot Maker/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Video/Snapshot Maker/Properties/Settings.Designer.cs b/Samples/Video/Snapshot Maker/Properties/Settings.Designer.cs new file mode 100644 index 0000000000..dbc9e5d22 --- /dev/null +++ b/Samples/Video/Snapshot Maker/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Samples/Video/Snapshot Maker/Properties/Settings.settings b/Samples/Video/Snapshot Maker/Properties/Settings.settings new file mode 100644 index 0000000000..39645652a --- /dev/null +++ b/Samples/Video/Snapshot Maker/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Samples/Video/Snapshot Maker/Snapshot Maker.csproj b/Samples/Video/Snapshot Maker/Snapshot Maker.csproj new file mode 100644 index 0000000000..842a54459 --- /dev/null +++ b/Samples/Video/Snapshot Maker/Snapshot Maker.csproj @@ -0,0 +1,170 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {779A59F0-BF3B-4AE5-B323-97D37CD67233} + WinExe + Properties + SampleApp + Snapshot Maker + v4.0 + 512 + + + 3.5 + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + SampleApp.Program + + + + ..\..\..\Release\net40\Accord.dll + + + ..\..\..\Release\net40\Accord.Controls.Imaging.dll + + + ..\..\..\Release\net40\Accord.Imaging.dll + + + ..\..\..\Release\net40\Accord.Video.dll + + + ..\..\..\Release\net40\Accord.Video.DirectShow.dll + + + + + + + + + Form + + + MainForm.cs + + + + + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + SnapshotForm.cs + + + True + Resources.resx + True + + + PreserveNewest + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + Form + + + SnapshotForm.cs + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + \ No newline at end of file diff --git a/Samples/Video/Snapshot Maker/Snapshot Maker.sln b/Samples/Video/Snapshot Maker/Snapshot Maker.sln new file mode 100644 index 0000000000..53b3eef82 --- /dev/null +++ b/Samples/Video/Snapshot Maker/Snapshot Maker.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C# Express 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Snapshot Maker", "Snapshot Maker.csproj", "{779A59F0-BF3B-4AE5-B323-97D37CD67233}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {779A59F0-BF3B-4AE5-B323-97D37CD67233}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {779A59F0-BF3B-4AE5-B323-97D37CD67233}.Debug|Any CPU.Build.0 = Debug|Any CPU + {779A59F0-BF3B-4AE5-B323-97D37CD67233}.Release|Any CPU.ActiveCfg = Release|Any CPU + {779A59F0-BF3B-4AE5-B323-97D37CD67233}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/Video/Snapshot Maker/SnapshotForm.Designer.cs b/Samples/Video/Snapshot Maker/SnapshotForm.Designer.cs new file mode 100644 index 0000000000..912e39736 --- /dev/null +++ b/Samples/Video/Snapshot Maker/SnapshotForm.Designer.cs @@ -0,0 +1,116 @@ +namespace SampleApp +{ + partial class SnapshotForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.pictureBox = new System.Windows.Forms.PictureBox(); + this.saveButton = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.timeBox = new System.Windows.Forms.TextBox(); + this.saveFileDialog = new System.Windows.Forms.SaveFileDialog(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).BeginInit(); + this.SuspendLayout(); + // + // pictureBox + // + this.pictureBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.pictureBox.BackColor = System.Drawing.SystemColors.ControlDark; + this.pictureBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.pictureBox.Location = new System.Drawing.Point(15, 62); + this.pictureBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.pictureBox.Name = "pictureBox"; + this.pictureBox.Size = new System.Drawing.Size(652, 453); + this.pictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; + this.pictureBox.TabIndex = 0; + this.pictureBox.TabStop = false; + // + // saveButton + // + this.saveButton.Location = new System.Drawing.Point(15, 15); + this.saveButton.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.saveButton.Name = "saveButton"; + this.saveButton.Size = new System.Drawing.Size(112, 35); + this.saveButton.TabIndex = 1; + this.saveButton.Text = "&Save"; + this.saveButton.UseVisualStyleBackColor = true; + this.saveButton.Click += new System.EventHandler(this.saveButton_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(165, 23); + this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(116, 20); + this.label1.TabIndex = 2; + this.label1.Text = "Snapshot time:"; + // + // timeBox + // + this.timeBox.Location = new System.Drawing.Point(285, 18); + this.timeBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.timeBox.Name = "timeBox"; + this.timeBox.ReadOnly = true; + this.timeBox.Size = new System.Drawing.Size(223, 26); + this.timeBox.TabIndex = 3; + // + // saveFileDialog + // + this.saveFileDialog.Filter = "JPEG images (*.jpg)|*.jpg|PNG images (*.png)|*.png|BMP images (*.bmp)|*.bmp"; + this.saveFileDialog.Title = "Save snapshot"; + // + // SnapshotForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(681, 529); + this.Controls.Add(this.timeBox); + this.Controls.Add(this.label1); + this.Controls.Add(this.saveButton); + this.Controls.Add(this.pictureBox); + this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.Name = "SnapshotForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Snapshot"; + ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.PictureBox pictureBox; + private System.Windows.Forms.Button saveButton; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox timeBox; + private System.Windows.Forms.SaveFileDialog saveFileDialog; + } +} \ No newline at end of file diff --git a/Samples/Video/Snapshot Maker/SnapshotForm.cs b/Samples/Video/Snapshot Maker/SnapshotForm.cs new file mode 100644 index 0000000000..8771ba8b3 --- /dev/null +++ b/Samples/Video/Snapshot Maker/SnapshotForm.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Drawing.Imaging; +using System.Windows.Forms; +using System.IO; + +namespace SampleApp +{ + public partial class SnapshotForm : Form + { + public SnapshotForm( ) + { + InitializeComponent( ); + } + + public void SetImage( Bitmap bitmap ) + { + timeBox.Text = DateTime.Now.ToLongTimeString( ); + + lock ( this ) + { + Bitmap old = (Bitmap) pictureBox.Image; + pictureBox.Image = bitmap; + + if ( old != null ) + { + old.Dispose( ); + } + } + } + + private void saveButton_Click( object sender, EventArgs e ) + { + if ( saveFileDialog.ShowDialog( ) == DialogResult.OK ) + { + string ext = Path.GetExtension( saveFileDialog.FileName ).ToLower( ); + ImageFormat format = ImageFormat.Jpeg; + + if ( ext == ".bmp" ) + { + format = ImageFormat.Bmp; + } + else if ( ext == ".png" ) + { + format = ImageFormat.Png; + } + + try + { + lock ( this ) + { + Bitmap image = (Bitmap) pictureBox.Image; + + image.Save( saveFileDialog.FileName, format ); + } + } + catch ( Exception ex ) + { + MessageBox.Show( "Failed saving the snapshot.\n" + ex.Message, + "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); + } + } + } + } +} diff --git a/Samples/Video/Snapshot Maker/SnapshotForm.resx b/Samples/Video/Snapshot Maker/SnapshotForm.resx new file mode 100644 index 0000000000..2c9546be6 --- /dev/null +++ b/Samples/Video/Snapshot Maker/SnapshotForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/Samples/Video/Snapshot Maker/app.config b/Samples/Video/Snapshot Maker/app.config new file mode 100644 index 0000000000..57c0f2cbc --- /dev/null +++ b/Samples/Video/Snapshot Maker/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Samples/Video/Two Cameras/Accord.dll.config b/Samples/Video/Two Cameras/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Video/Two Cameras/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Video/Two Cameras/MainForm.Designer.cs b/Samples/Video/Two Cameras/MainForm.Designer.cs new file mode 100644 index 0000000000..a55710740 --- /dev/null +++ b/Samples/Video/Two Cameras/MainForm.Designer.cs @@ -0,0 +1,199 @@ +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.components = new System.ComponentModel.Container(); + this.videoSourcePlayer1 = new AForge.Controls.VideoSourcePlayer(); + this.videoSourcePlayer2 = new AForge.Controls.VideoSourcePlayer(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.camera1FpsLabel = new System.Windows.Forms.Label(); + this.camera1Combo = new System.Windows.Forms.ComboBox(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.camera2FpsLabel = new System.Windows.Forms.Label(); + this.camera2Combo = new System.Windows.Forms.ComboBox(); + this.startButton = new System.Windows.Forms.Button(); + this.stopButton = new System.Windows.Forms.Button(); + this.timer = new System.Windows.Forms.Timer(this.components); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.SuspendLayout(); + // + // videoSourcePlayer1 + // + this.videoSourcePlayer1.BackColor = System.Drawing.SystemColors.ControlDark; + this.videoSourcePlayer1.ForeColor = System.Drawing.Color.White; + this.videoSourcePlayer1.Location = new System.Drawing.Point(15, 77); + this.videoSourcePlayer1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.videoSourcePlayer1.Name = "videoSourcePlayer1"; + this.videoSourcePlayer1.Size = new System.Drawing.Size(483, 372); + this.videoSourcePlayer1.TabIndex = 0; + this.videoSourcePlayer1.VideoSource = null; + // + // videoSourcePlayer2 + // + this.videoSourcePlayer2.BackColor = System.Drawing.SystemColors.ControlDark; + this.videoSourcePlayer2.ForeColor = System.Drawing.Color.White; + this.videoSourcePlayer2.Location = new System.Drawing.Point(15, 77); + this.videoSourcePlayer2.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.videoSourcePlayer2.Name = "videoSourcePlayer2"; + this.videoSourcePlayer2.Size = new System.Drawing.Size(483, 372); + this.videoSourcePlayer2.TabIndex = 1; + this.videoSourcePlayer2.VideoSource = null; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.camera1FpsLabel); + this.groupBox1.Controls.Add(this.camera1Combo); + this.groupBox1.Controls.Add(this.videoSourcePlayer1); + this.groupBox1.Location = new System.Drawing.Point(15, 15); + this.groupBox1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox1.Size = new System.Drawing.Size(513, 485); + this.groupBox1.TabIndex = 2; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Camera 1"; + // + // camera1FpsLabel + // + this.camera1FpsLabel.Location = new System.Drawing.Point(423, 454); + this.camera1FpsLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.camera1FpsLabel.Name = "camera1FpsLabel"; + this.camera1FpsLabel.Size = new System.Drawing.Size(75, 26); + this.camera1FpsLabel.TabIndex = 4; + this.camera1FpsLabel.Text = "label1"; + this.camera1FpsLabel.TextAlign = System.Drawing.ContentAlignment.TopRight; + // + // camera1Combo + // + this.camera1Combo.FormattingEnabled = true; + this.camera1Combo.Location = new System.Drawing.Point(15, 31); + this.camera1Combo.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.camera1Combo.Name = "camera1Combo"; + this.camera1Combo.Size = new System.Drawing.Size(481, 28); + this.camera1Combo.TabIndex = 3; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.camera2FpsLabel); + this.groupBox2.Controls.Add(this.camera2Combo); + this.groupBox2.Controls.Add(this.videoSourcePlayer2); + this.groupBox2.Location = new System.Drawing.Point(540, 15); + this.groupBox2.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox2.Size = new System.Drawing.Size(513, 485); + this.groupBox2.TabIndex = 3; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Camera 2"; + // + // camera2FpsLabel + // + this.camera2FpsLabel.Location = new System.Drawing.Point(423, 454); + this.camera2FpsLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.camera2FpsLabel.Name = "camera2FpsLabel"; + this.camera2FpsLabel.Size = new System.Drawing.Size(75, 26); + this.camera2FpsLabel.TabIndex = 5; + this.camera2FpsLabel.Text = "label2"; + this.camera2FpsLabel.TextAlign = System.Drawing.ContentAlignment.TopRight; + // + // camera2Combo + // + this.camera2Combo.FormattingEnabled = true; + this.camera2Combo.Location = new System.Drawing.Point(15, 31); + this.camera2Combo.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.camera2Combo.Name = "camera2Combo"; + this.camera2Combo.Size = new System.Drawing.Size(481, 28); + this.camera2Combo.TabIndex = 2; + // + // startButton + // + this.startButton.Location = new System.Drawing.Point(818, 515); + this.startButton.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.startButton.Name = "startButton"; + this.startButton.Size = new System.Drawing.Size(112, 35); + this.startButton.TabIndex = 4; + this.startButton.Text = "&Start"; + this.startButton.UseVisualStyleBackColor = true; + this.startButton.Click += new System.EventHandler(this.startButton_Click); + // + // stopButton + // + this.stopButton.Enabled = false; + this.stopButton.Location = new System.Drawing.Point(940, 515); + this.stopButton.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.stopButton.Name = "stopButton"; + this.stopButton.Size = new System.Drawing.Size(112, 35); + this.stopButton.TabIndex = 5; + this.stopButton.Text = "S&top"; + this.stopButton.UseVisualStyleBackColor = true; + this.stopButton.Click += new System.EventHandler(this.stopButton_Click); + // + // timer + // + this.timer.Interval = 1000; + this.timer.Tick += new System.EventHandler(this.timer_Tick); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(1066, 568); + this.Controls.Add(this.stopButton); + this.Controls.Add(this.startButton); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.MaximizeBox = false; + this.Name = "MainForm"; + this.Text = "Two Cameras Test"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.groupBox1.ResumeLayout(false); + this.groupBox2.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private AForge.Controls.VideoSourcePlayer videoSourcePlayer1; + private AForge.Controls.VideoSourcePlayer videoSourcePlayer2; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.ComboBox camera1Combo; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.ComboBox camera2Combo; + private System.Windows.Forms.Button startButton; + private System.Windows.Forms.Button stopButton; + private System.Windows.Forms.Label camera1FpsLabel; + private System.Windows.Forms.Timer timer; + private System.Windows.Forms.Label camera2FpsLabel; + } +} + diff --git a/Samples/Video/Two Cameras/MainForm.cs b/Samples/Video/Two Cameras/MainForm.cs new file mode 100644 index 0000000000..cc97f85eb --- /dev/null +++ b/Samples/Video/Two Cameras/MainForm.cs @@ -0,0 +1,194 @@ +// Two Cameras Test sample application +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; +using System.Diagnostics; + +using AForge.Video; +using AForge.Video.DirectShow; + +namespace SampleApp +{ + public partial class MainForm : Form + { + // list of video devices + FilterInfoCollection videoDevices; + + // stop watch for measuring fps + private Stopwatch stopWatch = null; + + public MainForm() + { + InitializeComponent(); + + camera1FpsLabel.Text = string.Empty; + camera2FpsLabel.Text = string.Empty; + + // show device list + try + { + // enumerate video devices + videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice); + + if (videoDevices.Count == 0) + { + throw new Exception(); + } + + for (int i = 1, n = videoDevices.Count; i <= n; i++) + { + string cameraName = i + " : " + videoDevices[i - 1].Name; + + camera1Combo.Items.Add(cameraName); + camera2Combo.Items.Add(cameraName); + } + + // check cameras count + if (videoDevices.Count == 1) + { + camera2Combo.Items.Clear(); + + camera2Combo.Items.Add("Only one camera found"); + camera2Combo.SelectedIndex = 0; + camera2Combo.Enabled = false; + } + else + { + camera2Combo.SelectedIndex = 1; + } + camera1Combo.SelectedIndex = 0; + } + catch + { + startButton.Enabled = false; + + camera1Combo.Items.Add("No cameras found"); + camera2Combo.Items.Add("No cameras found"); + + camera1Combo.SelectedIndex = 0; + camera2Combo.SelectedIndex = 0; + + camera1Combo.Enabled = false; + camera2Combo.Enabled = false; + } + } + + // On form closing + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + StopCameras(); + } + + // On "Start" button click + private void startButton_Click(object sender, EventArgs e) + { + StartCameras(); + + startButton.Enabled = false; + stopButton.Enabled = true; + } + + // On "Stop" button click + private void stopButton_Click(object sender, EventArgs e) + { + StopCameras(); + + startButton.Enabled = true; + stopButton.Enabled = false; + + camera1FpsLabel.Text = string.Empty; + camera2FpsLabel.Text = string.Empty; + } + + // Start cameras + private void StartCameras() + { + // create first video source + var videoSource1 = new VideoCaptureDevice(videoDevices[camera1Combo.SelectedIndex].MonikerString); + // videoSource1.DesiredFrameRate = 10; + + videoSourcePlayer1.VideoSource = videoSource1; + videoSourcePlayer1.Start(); + + // create second video source + if (camera2Combo.Enabled == true) + { + System.Threading.Thread.Sleep(500); + + var videoSource2 = new VideoCaptureDevice(videoDevices[camera2Combo.SelectedIndex].MonikerString); + // videoSource2.DesiredFrameRate = 10; + + videoSourcePlayer2.VideoSource = videoSource2; + videoSourcePlayer2.Start(); + } + + // reset stop watch + stopWatch = null; + // start timer + timer.Start(); + } + + // Stop cameras + private void StopCameras() + { + timer.Stop(); + + videoSourcePlayer1.SignalToStop(); + videoSourcePlayer2.SignalToStop(); + + videoSourcePlayer1.WaitForStop(); + videoSourcePlayer2.WaitForStop(); + } + + // On times tick - collect statistics + private void timer_Tick(object sender, EventArgs e) + { + IVideoSource videoSource1 = videoSourcePlayer1.VideoSource; + IVideoSource videoSource2 = videoSourcePlayer2.VideoSource; + + int framesReceived1 = 0; + int framesReceived2 = 0; + + // get number of frames for the last second + if (videoSource1 != null) + { + framesReceived1 = videoSource1.FramesReceived; + } + + if (videoSource2 != null) + { + framesReceived2 = videoSource2.FramesReceived; + } + + if (stopWatch == null) + { + stopWatch = new Stopwatch(); + stopWatch.Start(); + } + else + { + stopWatch.Stop(); + + float fps1 = 1000.0f * framesReceived1 / stopWatch.ElapsedMilliseconds; + float fps2 = 1000.0f * framesReceived2 / stopWatch.ElapsedMilliseconds; + + camera1FpsLabel.Text = fps1.ToString("F2") + " fps"; + camera2FpsLabel.Text = fps2.ToString("F2") + " fps"; + + stopWatch.Reset(); + stopWatch.Start(); + } + } + } +} diff --git a/Samples/Video/Two Cameras/MainForm.resx b/Samples/Video/Two Cameras/MainForm.resx new file mode 100644 index 0000000000..a57dc185c --- /dev/null +++ b/Samples/Video/Two Cameras/MainForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/Samples/Video/Two Cameras/Program.cs b/Samples/Video/Two Cameras/Program.cs new file mode 100644 index 0000000000..316268492 --- /dev/null +++ b/Samples/Video/Two Cameras/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Windows.Forms; + +namespace SampleApp +{ + static class Program + { + [STAThread] + static void Main() + { + if (Environment.OSVersion.Version.Major >= 6) + SetProcessDPIAware(); + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + + [System.Runtime.InteropServices.DllImport("user32.dll")] + private static extern bool SetProcessDPIAware(); + } +} diff --git a/Samples/Video/Two Cameras/Properties/AssemblyInfo.cs b/Samples/Video/Two Cameras/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..8f21c2b6b --- /dev/null +++ b/Samples/Video/Two Cameras/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle( "Two Cameras Test" )] +[assembly: AssemblyDescription( "Two Cameras Test sample" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "AForge" )] +[assembly: AssemblyProduct( "AForge.NET" )] +[assembly: AssemblyCopyright( "AForge © 2008" )] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible( false )] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid( "363746cb-53d6-4ca7-9403-f2bde3446147" )] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion( "1.0.0.0" )] +[assembly: AssemblyFileVersion( "1.0.0.0" )] diff --git a/Samples/Video/Two Cameras/Properties/Resources.Designer.cs b/Samples/Video/Two Cameras/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..7b58e53ee --- /dev/null +++ b/Samples/Video/Two Cameras/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Samples/Video/Two Cameras/Properties/Resources.resx b/Samples/Video/Two Cameras/Properties/Resources.resx new file mode 100644 index 0000000000..af7dbebba --- /dev/null +++ b/Samples/Video/Two Cameras/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Video/Two Cameras/Properties/Settings.Designer.cs b/Samples/Video/Two Cameras/Properties/Settings.Designer.cs new file mode 100644 index 0000000000..dbc9e5d22 --- /dev/null +++ b/Samples/Video/Two Cameras/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Samples/Video/Two Cameras/Properties/Settings.settings b/Samples/Video/Two Cameras/Properties/Settings.settings new file mode 100644 index 0000000000..39645652a --- /dev/null +++ b/Samples/Video/Two Cameras/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Samples/Video/Two Cameras/Two Cameras Test.sln b/Samples/Video/Two Cameras/Two Cameras Test.sln new file mode 100644 index 0000000000..17570c565 --- /dev/null +++ b/Samples/Video/Two Cameras/Two Cameras Test.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C# Express 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Two Cameras Test", "Two Cameras Test.csproj", "{AB55ABF6-4AD9-4F8A-9E9D-8B61F89766A6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {AB55ABF6-4AD9-4F8A-9E9D-8B61F89766A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AB55ABF6-4AD9-4F8A-9E9D-8B61F89766A6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AB55ABF6-4AD9-4F8A-9E9D-8B61F89766A6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AB55ABF6-4AD9-4F8A-9E9D-8B61F89766A6}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/Video/Two Cameras/Two Cameras.csproj b/Samples/Video/Two Cameras/Two Cameras.csproj new file mode 100644 index 0000000000..1d58f3290 --- /dev/null +++ b/Samples/Video/Two Cameras/Two Cameras.csproj @@ -0,0 +1,159 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {AB55ABF6-4AD9-4F8A-9E9D-8B61F89766A6} + WinExe + Properties + SampleApp + Two Cameras Test + v4.0 + 512 + + + 3.5 + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + SampleApp.Program + + + + ..\..\..\Release\net40\Accord.Controls.dll + + + ..\..\..\Release\net40\Accord.Controls.Imaging.dll + + + ..\..\..\Release\net40\Accord.Video.dll + + + ..\..\..\Release\net40\Accord.Video.DirectShow.dll + + + + + + + + + + Form + + + MainForm.cs + + + + + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + \ No newline at end of file diff --git a/Samples/Video/Two Cameras/app.config b/Samples/Video/Two Cameras/app.config new file mode 100644 index 0000000000..57c0f2cbc --- /dev/null +++ b/Samples/Video/Two Cameras/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Samples/Video/Video Player/Accord.dll.config b/Samples/Video/Video Player/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Video/Video Player/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Video/Video Player/MainForm.Designer.cs b/Samples/Video/Video Player/MainForm.Designer.cs new file mode 100644 index 0000000000..11320c259 --- /dev/null +++ b/Samples/Video/Video Player/MainForm.Designer.cs @@ -0,0 +1,219 @@ +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.components = new System.ComponentModel.Container(); + this.mainMenuStrip = new System.Windows.Forms.MenuStrip(); + this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.localVideoCaptureDeviceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.openVideofileusingDirectShowToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.openJPEGURLToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.openMJPEGURLToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.capture1stDisplayToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator(); + this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.statusStrip = new System.Windows.Forms.StatusStrip(); + this.fpsLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.mainPanel = new System.Windows.Forms.Panel(); + this.videoSourcePlayer = new AForge.Controls.VideoSourcePlayer(); + this.timer = new System.Windows.Forms.Timer(this.components); + this.openFileDialog = new System.Windows.Forms.OpenFileDialog(); + this.mainMenuStrip.SuspendLayout(); + this.statusStrip.SuspendLayout(); + this.mainPanel.SuspendLayout(); + this.SuspendLayout(); + // + // mainMenuStrip + // + this.mainMenuStrip.ImageScalingSize = new System.Drawing.Size(24, 24); + this.mainMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.fileToolStripMenuItem}); + this.mainMenuStrip.Location = new System.Drawing.Point(0, 0); + this.mainMenuStrip.Name = "mainMenuStrip"; + this.mainMenuStrip.Padding = new System.Windows.Forms.Padding(9, 3, 0, 3); + this.mainMenuStrip.Size = new System.Drawing.Size(651, 35); + this.mainMenuStrip.TabIndex = 0; + this.mainMenuStrip.Text = "menuStrip1"; + // + // fileToolStripMenuItem + // + this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.localVideoCaptureDeviceToolStripMenuItem, + this.openVideofileusingDirectShowToolStripMenuItem, + this.openJPEGURLToolStripMenuItem, + this.openMJPEGURLToolStripMenuItem, + this.capture1stDisplayToolStripMenuItem, + this.toolStripMenuItem1, + this.exitToolStripMenuItem}); + this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; + this.fileToolStripMenuItem.Size = new System.Drawing.Size(50, 29); + this.fileToolStripMenuItem.Text = "&File"; + // + // localVideoCaptureDeviceToolStripMenuItem + // + this.localVideoCaptureDeviceToolStripMenuItem.Name = "localVideoCaptureDeviceToolStripMenuItem"; + this.localVideoCaptureDeviceToolStripMenuItem.Size = new System.Drawing.Size(358, 30); + this.localVideoCaptureDeviceToolStripMenuItem.Text = "Local &Video Capture Device"; + this.localVideoCaptureDeviceToolStripMenuItem.Click += new System.EventHandler(this.localVideoCaptureDeviceToolStripMenuItem_Click); + // + // openVideofileusingDirectShowToolStripMenuItem + // + this.openVideofileusingDirectShowToolStripMenuItem.Name = "openVideofileusingDirectShowToolStripMenuItem"; + this.openVideofileusingDirectShowToolStripMenuItem.Size = new System.Drawing.Size(358, 30); + this.openVideofileusingDirectShowToolStripMenuItem.Text = "Open video &file (using DirectShow)"; + this.openVideofileusingDirectShowToolStripMenuItem.Click += new System.EventHandler(this.openVideofileusingDirectShowToolStripMenuItem_Click); + // + // openJPEGURLToolStripMenuItem + // + this.openJPEGURLToolStripMenuItem.Name = "openJPEGURLToolStripMenuItem"; + this.openJPEGURLToolStripMenuItem.Size = new System.Drawing.Size(358, 30); + this.openJPEGURLToolStripMenuItem.Text = "Open JPEG &URL"; + this.openJPEGURLToolStripMenuItem.Click += new System.EventHandler(this.openJPEGURLToolStripMenuItem_Click); + // + // openMJPEGURLToolStripMenuItem + // + this.openMJPEGURLToolStripMenuItem.Name = "openMJPEGURLToolStripMenuItem"; + this.openMJPEGURLToolStripMenuItem.Size = new System.Drawing.Size(358, 30); + this.openMJPEGURLToolStripMenuItem.Text = "Open &MJPEG URL"; + this.openMJPEGURLToolStripMenuItem.Click += new System.EventHandler(this.openMJPEGURLToolStripMenuItem_Click); + // + // capture1stDisplayToolStripMenuItem + // + this.capture1stDisplayToolStripMenuItem.Name = "capture1stDisplayToolStripMenuItem"; + this.capture1stDisplayToolStripMenuItem.Size = new System.Drawing.Size(358, 30); + this.capture1stDisplayToolStripMenuItem.Text = "Capture 1st display"; + this.capture1stDisplayToolStripMenuItem.Click += new System.EventHandler(this.capture1stDisplayToolStripMenuItem_Click); + // + // toolStripMenuItem1 + // + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + this.toolStripMenuItem1.Size = new System.Drawing.Size(355, 6); + // + // exitToolStripMenuItem + // + this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; + this.exitToolStripMenuItem.Size = new System.Drawing.Size(358, 30); + this.exitToolStripMenuItem.Text = "E&xit"; + this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click); + // + // statusStrip + // + this.statusStrip.ImageScalingSize = new System.Drawing.Size(24, 24); + this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.fpsLabel}); + this.statusStrip.Location = new System.Drawing.Point(0, 523); + this.statusStrip.Name = "statusStrip"; + this.statusStrip.Padding = new System.Windows.Forms.Padding(2, 0, 21, 0); + this.statusStrip.Size = new System.Drawing.Size(651, 22); + this.statusStrip.TabIndex = 1; + this.statusStrip.Text = "statusStrip1"; + // + // fpsLabel + // + this.fpsLabel.Name = "fpsLabel"; + this.fpsLabel.Size = new System.Drawing.Size(628, 17); + this.fpsLabel.Spring = true; + this.fpsLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // mainPanel + // + this.mainPanel.Controls.Add(this.videoSourcePlayer); + this.mainPanel.Dock = System.Windows.Forms.DockStyle.Fill; + this.mainPanel.Location = new System.Drawing.Point(0, 35); + this.mainPanel.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.mainPanel.Name = "mainPanel"; + this.mainPanel.Size = new System.Drawing.Size(651, 488); + this.mainPanel.TabIndex = 2; + // + // videoSourcePlayer + // + this.videoSourcePlayer.AutoSizeControl = true; + this.videoSourcePlayer.BackColor = System.Drawing.SystemColors.ControlDarkDark; + this.videoSourcePlayer.ForeColor = System.Drawing.Color.White; + this.videoSourcePlayer.Location = new System.Drawing.Point(164, 123); + this.videoSourcePlayer.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.videoSourcePlayer.Name = "videoSourcePlayer"; + this.videoSourcePlayer.Size = new System.Drawing.Size(322, 242); + this.videoSourcePlayer.TabIndex = 0; + this.videoSourcePlayer.VideoSource = null; + this.videoSourcePlayer.NewFrame += new AForge.Controls.VideoSourcePlayer.NewFrameHandler(this.videoSourcePlayer_NewFrame); + // + // timer + // + this.timer.Interval = 1000; + this.timer.Tick += new System.EventHandler(this.timer_Tick); + // + // openFileDialog + // + this.openFileDialog.Filter = "AVI files (*.avi)|*.avi|All files (*.*)|*.*"; + this.openFileDialog.Title = "Opem movie"; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(651, 545); + this.Controls.Add(this.mainPanel); + this.Controls.Add(this.statusStrip); + this.Controls.Add(this.mainMenuStrip); + this.MainMenuStrip = this.mainMenuStrip; + this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.Name = "MainForm"; + this.Text = "Simple Player"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.mainMenuStrip.ResumeLayout(false); + this.mainMenuStrip.PerformLayout(); + this.statusStrip.ResumeLayout(false); + this.statusStrip.PerformLayout(); + this.mainPanel.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.MenuStrip mainMenuStrip; + private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; + private System.Windows.Forms.StatusStrip statusStrip; + private System.Windows.Forms.Panel mainPanel; + private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem localVideoCaptureDeviceToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1; + private AForge.Controls.VideoSourcePlayer videoSourcePlayer; + private System.Windows.Forms.Timer timer; + private System.Windows.Forms.ToolStripStatusLabel fpsLabel; + private System.Windows.Forms.ToolStripMenuItem openVideofileusingDirectShowToolStripMenuItem; + private System.Windows.Forms.OpenFileDialog openFileDialog; + private System.Windows.Forms.ToolStripMenuItem openJPEGURLToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem openMJPEGURLToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem capture1stDisplayToolStripMenuItem; + } +} + diff --git a/Samples/Video/Video Player/MainForm.cs b/Samples/Video/Video Player/MainForm.cs new file mode 100644 index 0000000000..6b595dfe9 --- /dev/null +++ b/Samples/Video/Video Player/MainForm.cs @@ -0,0 +1,209 @@ +// Simple Player sample application +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; +using System.Diagnostics; + +using AForge.Video; +using AForge.Video.DirectShow; + +namespace SampleApp +{ + public partial class MainForm : Form + { + private Stopwatch stopWatch = null; + + // Class constructor + public MainForm() + { + InitializeComponent(); + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + CloseCurrentVideoSource(); + } + + // "Exit" menu item clicked + private void exitToolStripMenuItem_Click(object sender, EventArgs e) + { + this.Close(); + } + + // Open local video capture device + private void localVideoCaptureDeviceToolStripMenuItem_Click(object sender, EventArgs e) + { + VideoCaptureDeviceForm form = new VideoCaptureDeviceForm(); + + if (form.ShowDialog(this) == DialogResult.OK) + { + // create video source + VideoCaptureDevice videoSource = form.VideoDevice; + + // open it + OpenVideoSource(videoSource); + } + } + + // Open video file using DirectShow + private void openVideofileusingDirectShowToolStripMenuItem_Click(object sender, EventArgs e) + { + if (openFileDialog.ShowDialog() == DialogResult.OK) + { + // create video source + FileVideoSource fileSource = new FileVideoSource(openFileDialog.FileName); + + // open it + OpenVideoSource(fileSource); + } + } + + // Open JPEG URL + private void openJPEGURLToolStripMenuItem_Click(object sender, EventArgs e) + { + URLForm form = new URLForm(); + + form.Description = "Enter URL of an updating JPEG from a web camera:"; + form.URLs = new string[] + { + "http://195.243.185.195/axis-cgi/jpg/image.cgi?camera=1", + }; + + if (form.ShowDialog(this) == DialogResult.OK) + { + // create video source + JPEGStream jpegSource = new JPEGStream(form.URL); + + // open it + OpenVideoSource(jpegSource); + } + } + + // Open MJPEG URL + private void openMJPEGURLToolStripMenuItem_Click(object sender, EventArgs e) + { + URLForm form = new URLForm(); + + form.Description = "Enter URL of an MJPEG video stream:"; + form.URLs = new string[] + { + "http://195.243.185.195/axis-cgi/mjpg/video.cgi?camera=4", + "http://195.243.185.195/axis-cgi/mjpg/video.cgi?camera=3", + }; + + if (form.ShowDialog(this) == DialogResult.OK) + { + // create video source + MJPEGStream mjpegSource = new MJPEGStream(form.URL); + + // open it + OpenVideoSource(mjpegSource); + } + } + + // Capture 1st display in the system + private void capture1stDisplayToolStripMenuItem_Click(object sender, EventArgs e) + { + OpenVideoSource(new ScreenCaptureStream(Screen.AllScreens[0].Bounds, 100)); + } + + // Open video source + private void OpenVideoSource(IVideoSource source) + { + // set busy cursor + this.Cursor = Cursors.WaitCursor; + + // stop current video source + CloseCurrentVideoSource(); + + // start new video source + videoSourcePlayer.VideoSource = source; + videoSourcePlayer.Start(); + + // reset stop watch + stopWatch = null; + + // start timer + timer.Start(); + + this.Cursor = Cursors.Default; + } + + // Close video source if it is running + private void CloseCurrentVideoSource() + { + if (videoSourcePlayer.VideoSource != null) + { + videoSourcePlayer.SignalToStop(); + + // wait ~ 3 seconds + for (int i = 0; i < 30; i++) + { + if (!videoSourcePlayer.IsRunning) + break; + System.Threading.Thread.Sleep(100); + } + + if (videoSourcePlayer.IsRunning) + { + videoSourcePlayer.Stop(); + } + + videoSourcePlayer.VideoSource = null; + } + } + + // New frame received by the player + private void videoSourcePlayer_NewFrame(object sender, ref Bitmap image) + { + DateTime now = DateTime.Now; + Graphics g = Graphics.FromImage(image); + + // paint current time + SolidBrush brush = new SolidBrush(Color.Red); + g.DrawString(now.ToString(), this.Font, brush, new PointF(5, 5)); + brush.Dispose(); + + g.Dispose(); + } + + // On timer event - gather statistics + private void timer_Tick(object sender, EventArgs e) + { + IVideoSource videoSource = videoSourcePlayer.VideoSource; + + if (videoSource != null) + { + // get number of frames since the last timer tick + int framesReceived = videoSource.FramesReceived; + + if (stopWatch == null) + { + stopWatch = new Stopwatch(); + stopWatch.Start(); + } + else + { + stopWatch.Stop(); + + float fps = 1000.0f * framesReceived / stopWatch.ElapsedMilliseconds; + fpsLabel.Text = fps.ToString("F2") + " fps"; + + stopWatch.Reset(); + stopWatch.Start(); + } + } + } + } +} diff --git a/Samples/Video/Video Player/MainForm.resx b/Samples/Video/Video Player/MainForm.resx new file mode 100644 index 0000000000..d42ef3700 --- /dev/null +++ b/Samples/Video/Video Player/MainForm.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 152, 17 + + + 261, 17 + + + 341, 17 + + \ No newline at end of file diff --git a/Samples/Video/Video Player/Player.sln b/Samples/Video/Video Player/Player.sln new file mode 100644 index 0000000000..29b97b896 --- /dev/null +++ b/Samples/Video/Video Player/Player.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C# Express 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Player", "Player.csproj", "{B31C0650-991B-4B28-9864-AE80C1785A3F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B31C0650-991B-4B28-9864-AE80C1785A3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B31C0650-991B-4B28-9864-AE80C1785A3F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B31C0650-991B-4B28-9864-AE80C1785A3F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B31C0650-991B-4B28-9864-AE80C1785A3F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/Video/Video Player/Program.cs b/Samples/Video/Video Player/Program.cs new file mode 100644 index 0000000000..316268492 --- /dev/null +++ b/Samples/Video/Video Player/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Windows.Forms; + +namespace SampleApp +{ + static class Program + { + [STAThread] + static void Main() + { + if (Environment.OSVersion.Version.Major >= 6) + SetProcessDPIAware(); + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + + [System.Runtime.InteropServices.DllImport("user32.dll")] + private static extern bool SetProcessDPIAware(); + } +} diff --git a/Samples/Video/Video Player/Properties/AssemblyInfo.cs b/Samples/Video/Video Player/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..128d012d1 --- /dev/null +++ b/Samples/Video/Video Player/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle( "SampleApp" )] +[assembly: AssemblyDescription( "SampleApp Sample" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "AForge" )] +[assembly: AssemblyProduct( "AForge.NET" )] +[assembly: AssemblyCopyright( "AForge © 2008" )] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible( false )] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid( "6bb7d3f0-04aa-4442-87cf-c3e05fdca644" )] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion( "1.0.0.0" )] +[assembly: AssemblyFileVersion( "1.0.0.0" )] diff --git a/Samples/Video/Video Player/Properties/Resources.Designer.cs b/Samples/Video/Video Player/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..7b58e53ee --- /dev/null +++ b/Samples/Video/Video Player/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Samples/Video/Video Player/Properties/Resources.resx b/Samples/Video/Video Player/Properties/Resources.resx new file mode 100644 index 0000000000..af7dbebba --- /dev/null +++ b/Samples/Video/Video Player/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Video/Video Player/Properties/Settings.Designer.cs b/Samples/Video/Video Player/Properties/Settings.Designer.cs new file mode 100644 index 0000000000..dbc9e5d22 --- /dev/null +++ b/Samples/Video/Video Player/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Samples/Video/Video Player/Properties/Settings.settings b/Samples/Video/Video Player/Properties/Settings.settings new file mode 100644 index 0000000000..39645652a --- /dev/null +++ b/Samples/Video/Video Player/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Samples/Video/Video Player/URLForm.Designer.cs b/Samples/Video/Video Player/URLForm.Designer.cs new file mode 100644 index 0000000000..3a1e48511 --- /dev/null +++ b/Samples/Video/Video Player/URLForm.Designer.cs @@ -0,0 +1,107 @@ +namespace SampleApp +{ + partial class URLForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.descriptionLabel = new System.Windows.Forms.Label(); + this.cancelButton = new System.Windows.Forms.Button(); + this.okButton = new System.Windows.Forms.Button(); + this.urlBox = new System.Windows.Forms.ComboBox(); + this.SuspendLayout(); + // + // descriptionLabel + // + this.descriptionLabel.Location = new System.Drawing.Point(15, 15); + this.descriptionLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.descriptionLabel.Name = "descriptionLabel"; + this.descriptionLabel.Size = new System.Drawing.Size(488, 20); + this.descriptionLabel.TabIndex = 10; + // + // cancelButton + // + this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.cancelButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.cancelButton.Location = new System.Drawing.Point(270, 123); + this.cancelButton.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.cancelButton.Name = "cancelButton"; + this.cancelButton.Size = new System.Drawing.Size(112, 35); + this.cancelButton.TabIndex = 9; + this.cancelButton.Text = "Cancel"; + // + // okButton + // + this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK; + this.okButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.okButton.Location = new System.Drawing.Point(135, 123); + this.okButton.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.okButton.Name = "okButton"; + this.okButton.Size = new System.Drawing.Size(112, 35); + this.okButton.TabIndex = 8; + this.okButton.Text = "Ok"; + this.okButton.Click += new System.EventHandler(this.okButton_Click); + // + // urlBox + // + this.urlBox.FormattingEnabled = true; + this.urlBox.Location = new System.Drawing.Point(15, 54); + this.urlBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.urlBox.Name = "urlBox"; + this.urlBox.Size = new System.Drawing.Size(486, 28); + this.urlBox.TabIndex = 7; + // + // URLForm + // + this.AcceptButton = this.okButton; + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.CancelButton = this.cancelButton; + this.ClientSize = new System.Drawing.Size(516, 178); + this.Controls.Add(this.descriptionLabel); + this.Controls.Add(this.cancelButton); + this.Controls.Add(this.okButton); + this.Controls.Add(this.urlBox); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; + this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "URLForm"; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Open URL"; + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Label descriptionLabel; + private System.Windows.Forms.Button cancelButton; + private System.Windows.Forms.Button okButton; + private System.Windows.Forms.ComboBox urlBox; + } +} \ No newline at end of file diff --git a/Samples/Video/Video Player/URLForm.cs b/Samples/Video/Video Player/URLForm.cs new file mode 100644 index 0000000000..5f22e9d79 --- /dev/null +++ b/Samples/Video/Video Player/URLForm.cs @@ -0,0 +1,56 @@ +// AForge.NET Framework +// Simple Player sample application +// +// Copyright © Andrew Kirillov, 2008 +// andrew.kirillov@gmail.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace SampleApp +{ + public partial class URLForm : Form + { + private string url; + + // Selected URL + public string URL + { + get { return url; } + } + + // URLs to display in combo box + public string[] URLs + { + set + { + urlBox.Items.AddRange( value ); + } + } + + // Description of the dialog + public string Description + { + get { return descriptionLabel.Text; } + set { descriptionLabel.Text = value; } + } + + // Constructor + public URLForm( ) + { + InitializeComponent( ); + } + + // On "Ok" button clicked + private void okButton_Click( object sender, EventArgs e ) + { + url = urlBox.Text; + } + } +} diff --git a/Samples/Video/Video Player/URLForm.resx b/Samples/Video/Video Player/URLForm.resx new file mode 100644 index 0000000000..c7e0d4bdf --- /dev/null +++ b/Samples/Video/Video Player/URLForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Video/Video Player/Video Player.csproj b/Samples/Video/Video Player/Video Player.csproj new file mode 100644 index 0000000000..1063caf48 --- /dev/null +++ b/Samples/Video/Video Player/Video Player.csproj @@ -0,0 +1,175 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {B31C0650-991B-4B28-9864-AE80C1785A3F} + WinExe + Properties + SampleApp + Video Player + v4.0 + 512 + + + 3.5 + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + SampleApp.Program + + + + ..\..\..\Release\net40\Accord.dll + + + ..\..\..\Release\net40\Accord.Controls.dll + + + ..\..\..\Release\net40\Accord.Controls.Imaging.dll + + + ..\..\..\Release\net40\Accord.Math.dll + + + ..\..\..\Release\net40\Accord.Video.dll + + + ..\..\..\Release\net40\Accord.Video.DirectShow.dll + + + + + + + + + + Form + + + MainForm.cs + + + + + MainForm.cs + Designer + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + URLForm.cs + + + True + Resources.resx + True + + + PreserveNewest + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + Form + + + URLForm.cs + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + \ No newline at end of file diff --git a/Samples/Video/Video Player/app.config b/Samples/Video/Video Player/app.config new file mode 100644 index 0000000000..57c0f2cbc --- /dev/null +++ b/Samples/Video/Video Player/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Samples/Video/Ximea Sample/Accord.dll.config b/Samples/Video/Ximea Sample/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Video/Ximea Sample/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Video/Ximea Sample/MainForm.Designer.cs b/Samples/Video/Ximea Sample/MainForm.Designer.cs new file mode 100644 index 0000000000..565457e60 --- /dev/null +++ b/Samples/Video/Ximea Sample/MainForm.Designer.cs @@ -0,0 +1,486 @@ +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.components = new System.ComponentModel.Container(); + this.videoSourcePlayer = new AForge.Controls.VideoSourcePlayer(); + this.statusStrip = new System.Windows.Forms.StatusStrip(); + this.fpsLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.spareLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.topPanel = new System.Windows.Forms.Panel(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.offsetYUpDown = new System.Windows.Forms.NumericUpDown(); + this.label9 = new System.Windows.Forms.Label(); + this.offsetXUpDown = new System.Windows.Forms.NumericUpDown(); + this.label10 = new System.Windows.Forms.Label(); + this.heightUpDown = new System.Windows.Forms.NumericUpDown(); + this.label8 = new System.Windows.Forms.Label(); + this.widthUpDown = new System.Windows.Forms.NumericUpDown(); + this.label7 = new System.Windows.Forms.Label(); + this.gainUpDown = new System.Windows.Forms.NumericUpDown(); + this.label6 = new System.Windows.Forms.Label(); + this.exposureUpDown = new System.Windows.Forms.NumericUpDown(); + this.label5 = new System.Windows.Forms.Label(); + this.typeBox = new System.Windows.Forms.TextBox(); + this.snBox = new System.Windows.Forms.TextBox(); + this.nameBox = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.disconnectButton = new System.Windows.Forms.Button(); + this.connectButton = new System.Windows.Forms.Button(); + this.deviceCombo = new System.Windows.Forms.ComboBox(); + this.mainPanel = new System.Windows.Forms.Panel(); + this.timer = new System.Windows.Forms.Timer(this.components); + this.statusStrip.SuspendLayout(); + this.topPanel.SuspendLayout(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.offsetYUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.offsetXUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.heightUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.widthUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gainUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.exposureUpDown)).BeginInit(); + this.mainPanel.SuspendLayout(); + this.SuspendLayout(); + // + // videoSourcePlayer + // + this.videoSourcePlayer.AutoSizeControl = true; + this.videoSourcePlayer.BackColor = System.Drawing.SystemColors.ControlDarkDark; + this.videoSourcePlayer.ForeColor = System.Drawing.Color.White; + this.videoSourcePlayer.Location = new System.Drawing.Point(371, 164); + this.videoSourcePlayer.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.videoSourcePlayer.Name = "videoSourcePlayer"; + this.videoSourcePlayer.Size = new System.Drawing.Size(322, 242); + this.videoSourcePlayer.TabIndex = 7; + this.videoSourcePlayer.VideoSource = null; + // + // statusStrip + // + this.statusStrip.ImageScalingSize = new System.Drawing.Size(24, 24); + this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.fpsLabel, + this.spareLabel}); + this.statusStrip.Location = new System.Drawing.Point(0, 793); + this.statusStrip.Name = "statusStrip"; + this.statusStrip.Padding = new System.Windows.Forms.Padding(2, 0, 21, 0); + this.statusStrip.Size = new System.Drawing.Size(1065, 22); + this.statusStrip.TabIndex = 8; + this.statusStrip.Text = "statusStrip1"; + // + // fpsLabel + // + this.fpsLabel.AutoSize = false; + this.fpsLabel.BorderSides = ((System.Windows.Forms.ToolStripStatusLabelBorderSides)((((System.Windows.Forms.ToolStripStatusLabelBorderSides.Left | System.Windows.Forms.ToolStripStatusLabelBorderSides.Top) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Right) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Bottom))); + this.fpsLabel.BorderStyle = System.Windows.Forms.Border3DStyle.SunkenInner; + this.fpsLabel.Name = "fpsLabel"; + this.fpsLabel.Size = new System.Drawing.Size(100, 17); + this.fpsLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // spareLabel + // + this.spareLabel.BorderSides = ((System.Windows.Forms.ToolStripStatusLabelBorderSides)((((System.Windows.Forms.ToolStripStatusLabelBorderSides.Left | System.Windows.Forms.ToolStripStatusLabelBorderSides.Top) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Right) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Bottom))); + this.spareLabel.BorderStyle = System.Windows.Forms.Border3DStyle.SunkenInner; + this.spareLabel.Name = "spareLabel"; + this.spareLabel.Size = new System.Drawing.Size(942, 17); + this.spareLabel.Spring = true; + this.spareLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // topPanel + // + this.topPanel.Controls.Add(this.groupBox1); + this.topPanel.Dock = System.Windows.Forms.DockStyle.Top; + this.topPanel.Location = new System.Drawing.Point(0, 0); + this.topPanel.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.topPanel.Name = "topPanel"; + this.topPanel.Size = new System.Drawing.Size(1065, 223); + this.topPanel.TabIndex = 9; + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.offsetYUpDown); + this.groupBox1.Controls.Add(this.label9); + this.groupBox1.Controls.Add(this.offsetXUpDown); + this.groupBox1.Controls.Add(this.label10); + this.groupBox1.Controls.Add(this.heightUpDown); + this.groupBox1.Controls.Add(this.label8); + this.groupBox1.Controls.Add(this.widthUpDown); + this.groupBox1.Controls.Add(this.label7); + this.groupBox1.Controls.Add(this.gainUpDown); + this.groupBox1.Controls.Add(this.label6); + this.groupBox1.Controls.Add(this.exposureUpDown); + this.groupBox1.Controls.Add(this.label5); + this.groupBox1.Controls.Add(this.typeBox); + this.groupBox1.Controls.Add(this.snBox); + this.groupBox1.Controls.Add(this.nameBox); + this.groupBox1.Controls.Add(this.label4); + this.groupBox1.Controls.Add(this.label3); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.disconnectButton); + this.groupBox1.Controls.Add(this.connectButton); + this.groupBox1.Controls.Add(this.deviceCombo); + this.groupBox1.Location = new System.Drawing.Point(15, 15); + this.groupBox1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox1.Size = new System.Drawing.Size(1034, 198); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Camera parameters:"; + // + // offsetYUpDown + // + this.offsetYUpDown.Increment = new decimal(new int[] { + 10, + 0, + 0, + 0}); + this.offsetYUpDown.Location = new System.Drawing.Point(780, 77); + this.offsetYUpDown.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.offsetYUpDown.Name = "offsetYUpDown"; + this.offsetYUpDown.Size = new System.Drawing.Size(93, 26); + this.offsetYUpDown.TabIndex = 17; + this.offsetYUpDown.ValueChanged += new System.EventHandler(this.offsetYUpDown_ValueChanged); + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Location = new System.Drawing.Point(702, 82); + this.label9.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(72, 20); + this.label9.TabIndex = 16; + this.label9.Text = "Offset Y:"; + // + // offsetXUpDown + // + this.offsetXUpDown.Increment = new decimal(new int[] { + 10, + 0, + 0, + 0}); + this.offsetXUpDown.Location = new System.Drawing.Point(540, 77); + this.offsetXUpDown.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.offsetXUpDown.Name = "offsetXUpDown"; + this.offsetXUpDown.Size = new System.Drawing.Size(93, 26); + this.offsetXUpDown.TabIndex = 15; + this.offsetXUpDown.ValueChanged += new System.EventHandler(this.offsetXUpDown_ValueChanged); + // + // label10 + // + this.label10.AutoSize = true; + this.label10.Location = new System.Drawing.Point(466, 82); + this.label10.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(72, 20); + this.label10.TabIndex = 14; + this.label10.Text = "Offset X:"; + // + // heightUpDown + // + this.heightUpDown.Increment = new decimal(new int[] { + 10, + 0, + 0, + 0}); + this.heightUpDown.Location = new System.Drawing.Point(780, 31); + this.heightUpDown.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.heightUpDown.Name = "heightUpDown"; + this.heightUpDown.Size = new System.Drawing.Size(93, 26); + this.heightUpDown.TabIndex = 13; + this.heightUpDown.ValueChanged += new System.EventHandler(this.heightUpDown_ValueChanged); + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point(712, 35); + this.label8.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(60, 20); + this.label8.TabIndex = 12; + this.label8.Text = "Height:"; + // + // widthUpDown + // + this.widthUpDown.Increment = new decimal(new int[] { + 10, + 0, + 0, + 0}); + this.widthUpDown.Location = new System.Drawing.Point(540, 31); + this.widthUpDown.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.widthUpDown.Name = "widthUpDown"; + this.widthUpDown.Size = new System.Drawing.Size(93, 26); + this.widthUpDown.TabIndex = 11; + this.widthUpDown.ValueChanged += new System.EventHandler(this.widthUpDown_ValueChanged); + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point(482, 35); + this.label7.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(54, 20); + this.label7.TabIndex = 10; + this.label7.Text = "Width:"; + // + // gainUpDown + // + this.gainUpDown.DecimalPlaces = 2; + this.gainUpDown.Location = new System.Drawing.Point(540, 123); + this.gainUpDown.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.gainUpDown.Name = "gainUpDown"; + this.gainUpDown.Size = new System.Drawing.Size(93, 26); + this.gainUpDown.TabIndex = 19; + this.gainUpDown.ValueChanged += new System.EventHandler(this.gainUpDown_ValueChanged); + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(458, 128); + this.label6.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(81, 20); + this.label6.TabIndex = 18; + this.label6.Text = "Gain (dB):"; + // + // exposureUpDown + // + this.exposureUpDown.DecimalPlaces = 2; + this.exposureUpDown.Increment = new decimal(new int[] { + 2, + 0, + 0, + 0}); + this.exposureUpDown.Location = new System.Drawing.Point(780, 123); + this.exposureUpDown.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.exposureUpDown.Name = "exposureUpDown"; + this.exposureUpDown.Size = new System.Drawing.Size(93, 26); + this.exposureUpDown.TabIndex = 21; + this.exposureUpDown.ValueChanged += new System.EventHandler(this.exposureUpDown_ValueChanged); + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(660, 128); + this.label5.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(115, 20); + this.label5.TabIndex = 20; + this.label5.Text = "Exposure (ms):"; + // + // typeBox + // + this.typeBox.Location = new System.Drawing.Point(105, 154); + this.typeBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.typeBox.Name = "typeBox"; + this.typeBox.ReadOnly = true; + this.typeBox.Size = new System.Drawing.Size(313, 26); + this.typeBox.TabIndex = 9; + // + // snBox + // + this.snBox.Location = new System.Drawing.Point(105, 115); + this.snBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.snBox.Name = "snBox"; + this.snBox.ReadOnly = true; + this.snBox.Size = new System.Drawing.Size(313, 26); + this.snBox.TabIndex = 7; + // + // nameBox + // + this.nameBox.Location = new System.Drawing.Point(105, 77); + this.nameBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.nameBox.Name = "nameBox"; + this.nameBox.ReadOnly = true; + this.nameBox.Size = new System.Drawing.Size(313, 26); + this.nameBox.TabIndex = 5; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(15, 158); + this.label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(47, 20); + this.label4.TabIndex = 8; + this.label4.Text = "Type:"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(15, 120); + this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(66, 20); + this.label3.TabIndex = 6; + this.label3.Text = "Serial #:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(15, 82); + this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(55, 20); + this.label2.TabIndex = 4; + this.label2.Text = "Name:"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(15, 35); + this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(82, 20); + this.label1.TabIndex = 0; + this.label1.Text = "Device &ID:"; + // + // disconnectButton + // + this.disconnectButton.Location = new System.Drawing.Point(308, 31); + this.disconnectButton.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.disconnectButton.Name = "disconnectButton"; + this.disconnectButton.Size = new System.Drawing.Size(112, 35); + this.disconnectButton.TabIndex = 3; + this.disconnectButton.Text = "&Disconnect"; + this.disconnectButton.UseVisualStyleBackColor = true; + this.disconnectButton.Click += new System.EventHandler(this.disconnectButton_Click); + // + // connectButton + // + this.connectButton.Location = new System.Drawing.Point(188, 31); + this.connectButton.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.connectButton.Name = "connectButton"; + this.connectButton.Size = new System.Drawing.Size(112, 35); + this.connectButton.TabIndex = 2; + this.connectButton.Text = "&Connect"; + this.connectButton.UseVisualStyleBackColor = true; + this.connectButton.Click += new System.EventHandler(this.connectButton_Click); + // + // deviceCombo + // + this.deviceCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.deviceCombo.FormattingEnabled = true; + this.deviceCombo.Location = new System.Drawing.Point(105, 31); + this.deviceCombo.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.deviceCombo.Name = "deviceCombo"; + this.deviceCombo.Size = new System.Drawing.Size(73, 28); + this.deviceCombo.TabIndex = 1; + // + // mainPanel + // + this.mainPanel.Controls.Add(this.videoSourcePlayer); + this.mainPanel.Dock = System.Windows.Forms.DockStyle.Fill; + this.mainPanel.Location = new System.Drawing.Point(0, 223); + this.mainPanel.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.mainPanel.Name = "mainPanel"; + this.mainPanel.Size = new System.Drawing.Size(1065, 570); + this.mainPanel.TabIndex = 10; + // + // timer + // + this.timer.Interval = 1000; + this.timer.Tick += new System.EventHandler(this.timer_Tick); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(1065, 815); + this.Controls.Add(this.mainPanel); + this.Controls.Add(this.topPanel); + this.Controls.Add(this.statusStrip); + this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.Name = "MainForm"; + this.Text = "Ximea Video Acqusition Sample"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + this.statusStrip.ResumeLayout(false); + this.statusStrip.PerformLayout(); + this.topPanel.ResumeLayout(false); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.offsetYUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.offsetXUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.heightUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.widthUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gainUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.exposureUpDown)).EndInit(); + this.mainPanel.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private AForge.Controls.VideoSourcePlayer videoSourcePlayer; + private System.Windows.Forms.StatusStrip statusStrip; + private System.Windows.Forms.Panel topPanel; + private System.Windows.Forms.Panel mainPanel; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button disconnectButton; + private System.Windows.Forms.Button connectButton; + private System.Windows.Forms.ComboBox deviceCombo; + private System.Windows.Forms.ToolStripStatusLabel fpsLabel; + private System.Windows.Forms.ToolStripStatusLabel spareLabel; + private System.Windows.Forms.Timer timer; + private System.Windows.Forms.TextBox typeBox; + private System.Windows.Forms.TextBox snBox; + private System.Windows.Forms.TextBox nameBox; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.NumericUpDown exposureUpDown; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.NumericUpDown heightUpDown; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.NumericUpDown widthUpDown; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.NumericUpDown gainUpDown; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.NumericUpDown offsetYUpDown; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.NumericUpDown offsetXUpDown; + private System.Windows.Forms.Label label10; + } +} + diff --git a/Samples/Video/Ximea Sample/MainForm.cs b/Samples/Video/Ximea Sample/MainForm.cs new file mode 100644 index 0000000000..5cdf82d04 --- /dev/null +++ b/Samples/Video/Ximea Sample/MainForm.cs @@ -0,0 +1,304 @@ +// XIMEA camera sample application +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Windows.Forms; +using System.Diagnostics; + +using AForge.Video; +using AForge.Video.Ximea; + +namespace SampleApp +{ + public partial class MainForm : Form + { + private XimeaVideoSource videoSource = null; + private Stopwatch stopWatch = null; + + public MainForm( ) + { + InitializeComponent( ); + } + + // On application's form is loaded + private void MainForm_Load( object sender, EventArgs e ) + { + int deviceCount = 0; + + try + { + deviceCount = XimeaCamera.CamerasCount; + } + catch + { + } + + EnableConnectionControls( true ); + + if ( deviceCount != 0 ) + { + for ( int i = 0; i < deviceCount; i++ ) + { + deviceCombo.Items.Add( i.ToString( ) ); + } + } + else + { + deviceCombo.Items.Add( "No cameras" ); + deviceCombo.Enabled = false; + connectButton.Enabled = false; + } + deviceCombo.SelectedIndex = 0; + } + + // On closing the application's window + private void MainForm_FormClosing( object sender, FormClosingEventArgs e ) + { + CloseCamera( ); + } + + // Enable/disable controls related to camera connection/operation + private void EnableConnectionControls( bool enable ) + { + deviceCombo.Enabled = enable; + connectButton.Enabled = enable; + + disconnectButton.Enabled = !enable; + widthUpDown.Enabled = !enable; + heightUpDown.Enabled = !enable; + exposureUpDown.Enabled = !enable; + gainUpDown.Enabled = !enable; + offsetXUpDown.Enabled = !enable; + offsetYUpDown.Enabled = !enable; + } + + // On "Connect" button click + private void connectButton_Click( object sender, EventArgs e ) + { + // set busy cursor + this.Cursor = Cursors.WaitCursor; + + // close whatever is open now + CloseCamera( ); + + if ( videoSource == null ) + { + try + { + videoSource = new XimeaVideoSource( deviceCombo.SelectedIndex ); + + // start the camera + videoSource.Start( ); + + // get some parameters + nameBox.Text = videoSource.GetParamString( CameraParameter.DeviceName ); + snBox.Text = videoSource.GetParamString( CameraParameter.DeviceSerialNumber ); + typeBox.Text = videoSource.GetParamString( CameraParameter.DeviceType); + + // width + widthUpDown.Minimum = videoSource.GetParamInt( CameraParameter.WidthMin ); + widthUpDown.Maximum = videoSource.GetParamInt( CameraParameter.WidthMax ); + widthUpDown.Value = videoSource.GetParamInt( CameraParameter.WidthMax ); + + // height + heightUpDown.Minimum = videoSource.GetParamInt( CameraParameter.HeightMin ); + heightUpDown.Maximum = videoSource.GetParamInt( CameraParameter.HeightMax ); + heightUpDown.Value = videoSource.GetParamInt( CameraParameter.HeightMax ); + + // exposure + exposureUpDown.Minimum = videoSource.GetParamInt( CameraParameter.ExposureMin ) / 1000; + exposureUpDown.Maximum = videoSource.GetParamInt( CameraParameter.ExposureMax ) / 1000; + exposureUpDown.Value = 0; + exposureUpDown.Value = 10; + + // gain + gainUpDown.Minimum = new Decimal( videoSource.GetParamFloat( CameraParameter.GainMin ) ); + gainUpDown.Maximum = new Decimal( videoSource.GetParamFloat( CameraParameter.GainMax ) ); + gainUpDown.Value = new Decimal( videoSource.GetParamFloat( CameraParameter.Gain ) ); + + videoSourcePlayer.VideoSource = videoSource; + + EnableConnectionControls( false ); + + // reset stop watch + stopWatch = null; + + // start timer + timer.Start( ); + } + catch ( Exception ex ) + { + MessageBox.Show( "Failed openning XIMEA camera:\n\n" + ex.Message, "Error", + MessageBoxButtons.OK, MessageBoxIcon.Error ); + CloseCamera( ); + } + } + + this.Cursor = Cursors.Default; + } + + // On "Disconnect" button click + private void disconnectButton_Click( object sender, EventArgs e ) + { + CloseCamera( ); + EnableConnectionControls( true ); + } + + // Close currently open camera if any + private void CloseCamera( ) + { + timer.Stop( ); + + if ( videoSource != null ) + { + videoSourcePlayer.VideoSource = null; + + videoSource.SignalToStop( ); + videoSource.WaitForStop( ); + videoSource = null; + } + } + + // On timer tick - update FPS info + private void timer_Tick( object sender, EventArgs e ) + { + if ( videoSource != null ) + { + // get number of frames since the last timer tick + int framesReceived = videoSource.FramesReceived; + + if ( stopWatch == null ) + { + stopWatch = new Stopwatch( ); + stopWatch.Start( ); + } + else + { + stopWatch.Stop( ); + + float fps = 1000.0f * framesReceived / stopWatch.ElapsedMilliseconds; + fpsLabel.Text = fps.ToString( "F2" ) + " fps"; + + stopWatch.Reset( ); + stopWatch.Start( ); + } + } + } + + // Width need to be changed + private void widthUpDown_ValueChanged( object sender, EventArgs e ) + { + if ( videoSource != null ) + { + try + { + videoSource.SetParam( CameraParameter.Width, (int) widthUpDown.Value ); + + offsetXUpDown.Maximum = widthUpDown.Maximum - widthUpDown.Value; + offsetXUpDown.Value = 0; + } + catch + { + } + } + } + + // Height need to be changed + private void heightUpDown_ValueChanged( object sender, EventArgs e ) + { + if ( videoSource != null ) + { + try + { + videoSource.SetParam( CameraParameter.Height, (int) heightUpDown.Value ); + + offsetYUpDown.Maximum = heightUpDown.Maximum - heightUpDown.Value; + offsetYUpDown.Value = 0; + } + catch + { + } + } + } + + // Exposure need to be changed + private void exposureUpDown_ValueChanged( object sender, EventArgs e ) + { + if ( videoSource != null ) + { + try + { + videoSource.SetParam( CameraParameter.Exposure, (int) ( (float) exposureUpDown.Value * 1000 ) ); + + // set interval between capturing new frames from camera + videoSource.FrameInterval = (int) ( 1000.0f / videoSource.GetParamFloat( CameraParameter.FramerateMax ) ); + + // reset statistics + stopWatch = null; + int bin = videoSource.FramesReceived; + + spareLabel.Text = string.Format( "frame interval = {0} ms, max fps = {1}", + videoSource.FrameInterval, videoSource.GetParamFloat( CameraParameter.FramerateMax ) ); + } + catch + { + } + } + } + + // Gain need to be changed + private void gainUpDown_ValueChanged( object sender, EventArgs e ) + { + if ( videoSource != null ) + { + try + { + videoSource.SetParam( CameraParameter.Gain, (float) gainUpDown.Value ); + } + catch + { + } + } + } + + // X offset need to be changed + private void offsetXUpDown_ValueChanged( object sender, EventArgs e ) + { + if ( videoSource != null ) + { + try + { + videoSource.SetParam( CameraParameter.OffsetX, (int) offsetXUpDown.Value ); + } + catch + { + } + } + } + + // Y offset need to be changed + private void offsetYUpDown_ValueChanged( object sender, EventArgs e ) + { + if ( videoSource != null ) + { + try + { + videoSource.SetParam( CameraParameter.OffsetY, (int) offsetYUpDown.Value ); + } + catch + { + } + } + } + + } +} diff --git a/Samples/Video/Ximea Sample/MainForm.resx b/Samples/Video/Ximea Sample/MainForm.resx new file mode 100644 index 0000000000..b90be258b --- /dev/null +++ b/Samples/Video/Ximea Sample/MainForm.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 341, 17 + + \ No newline at end of file diff --git a/Samples/Video/Ximea Sample/Program.cs b/Samples/Video/Ximea Sample/Program.cs new file mode 100644 index 0000000000..316268492 --- /dev/null +++ b/Samples/Video/Ximea Sample/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Windows.Forms; + +namespace SampleApp +{ + static class Program + { + [STAThread] + static void Main() + { + if (Environment.OSVersion.Version.Major >= 6) + SetProcessDPIAware(); + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + + [System.Runtime.InteropServices.DllImport("user32.dll")] + private static extern bool SetProcessDPIAware(); + } +} diff --git a/Samples/Video/Ximea Sample/Properties/AssemblyInfo.cs b/Samples/Video/Ximea Sample/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..fd7d7ae9b --- /dev/null +++ b/Samples/Video/Ximea Sample/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle( "Ximea Sample" )] +[assembly: AssemblyDescription( "XIMEA camera sample application" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "AForge" )] +[assembly: AssemblyProduct( "AForge.NET" )] +[assembly: AssemblyCopyright( "AForge © 2011" )] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible( false )] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid( "43d3bb5b-a382-4191-a7d0-4b0d6b55098a" )] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion( "1.0.0.0" )] +[assembly: AssemblyFileVersion( "1.0.0.0" )] diff --git a/Samples/Video/Ximea Sample/Properties/Resources.Designer.cs b/Samples/Video/Ximea Sample/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..7b58e53ee --- /dev/null +++ b/Samples/Video/Ximea Sample/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Samples/Video/Ximea Sample/Properties/Resources.resx b/Samples/Video/Ximea Sample/Properties/Resources.resx new file mode 100644 index 0000000000..af7dbebba --- /dev/null +++ b/Samples/Video/Ximea Sample/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Video/Ximea Sample/Properties/Settings.Designer.cs b/Samples/Video/Ximea Sample/Properties/Settings.Designer.cs new file mode 100644 index 0000000000..dbc9e5d22 --- /dev/null +++ b/Samples/Video/Ximea Sample/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Samples/Video/Ximea Sample/Properties/Settings.settings b/Samples/Video/Ximea Sample/Properties/Settings.settings new file mode 100644 index 0000000000..39645652a --- /dev/null +++ b/Samples/Video/Ximea Sample/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Samples/Video/Ximea Sample/Ximea Sample.csproj b/Samples/Video/Ximea Sample/Ximea Sample.csproj new file mode 100644 index 0000000000..eefd763f8 --- /dev/null +++ b/Samples/Video/Ximea Sample/Ximea Sample.csproj @@ -0,0 +1,156 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {40C644F9-5AF9-44BB-9649-02149933E092} + WinExe + Properties + SampleApp + Ximea Sample + v4.0 + 512 + + + 3.5 + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + + ..\..\..\Release\net40\Accord.dll + + + ..\..\..\Release\net40\Accord.Controls.Imaging.dll + + + ..\..\..\Release\net40\Accord.Video.dll + + + ..\..\..\Release\net40\Accord.Video.Ximea.dll + + + + + + + + + + Form + + + MainForm.cs + + + + + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + \ No newline at end of file diff --git a/Samples/Video/Ximea Sample/Ximea Sample.sln b/Samples/Video/Ximea Sample/Ximea Sample.sln new file mode 100644 index 0000000000..f63fd6327 --- /dev/null +++ b/Samples/Video/Ximea Sample/Ximea Sample.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C# Express 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ximea Sample", "Ximea Sample.csproj", "{40C644F9-5AF9-44BB-9649-02149933E092}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {40C644F9-5AF9-44BB-9649-02149933E092}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {40C644F9-5AF9-44BB-9649-02149933E092}.Debug|Any CPU.Build.0 = Debug|Any CPU + {40C644F9-5AF9-44BB-9649-02149933E092}.Release|Any CPU.ActiveCfg = Release|Any CPU + {40C644F9-5AF9-44BB-9649-02149933E092}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/Video/Ximea Sample/app.config b/Samples/Video/Ximea Sample/app.config new file mode 100644 index 0000000000..57c0f2cbc --- /dev/null +++ b/Samples/Video/Ximea Sample/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Samples/Vision/Controller (interface control)/Accord.dll.config b/Samples/Vision/Controller (interface control)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Vision/Controller (interface control)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Vision/Controller (interface control)/Controller (interface control).csproj b/Samples/Vision/Controller (interface control)/Controller (interface control).csproj index 15ef0a618..41bbf3b3b 100644 --- a/Samples/Vision/Controller (interface control)/Controller (interface control).csproj +++ b/Samples/Vision/Controller (interface control)/Controller (interface control).csproj @@ -1,245 +1,237 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {95BDACEA-E8DB-4A87-9472-A37F0879179F} - WinExe - Properties - Controller - Controller %28interface controls%29 - v4.0 - 512 - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - AllRules.ruleset - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - AllRules.ruleset - - - true - bin\x86\Debug\ - DEBUG;TRACE - full - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - bin\x86\Release\ - TRACE - true - pdbonly - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - framework.ico - - - - False - ..\..\..\Release\net40\Accord.dll - - - False - ..\..\..\Release\net40\Accord.Controls.Imaging.dll - - - False - ..\..\..\Release\net40\Accord.Controls.Vision.dll - - - False - ..\..\..\Release\net40\Accord.Imaging.dll - - - False - ..\..\..\Release\net40\Accord.MachineLearning.dll - - - False - ..\..\..\Release\net40\Accord.Math.dll - - - False - ..\..\..\Release\net40\Accord.Statistics.dll - - - False - ..\..\..\Release\net40\Accord.Vision.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Imaging.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Video.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Video.DirectShow.dll - - - - 3.5 - - - 3.5 - - - 3.5 - - - - - - - - - - Form - - - AboutBox.cs - - - Form - - - FaceForm.cs - - - Form - - - MainForm.cs - - - - - AboutBox.cs - - - FaceForm.cs - Designer - - - MainForm.cs - Designer - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - VideoCaptureDeviceForm.cs - Designer - - - VisionForm.cs - Designer - - - True - Resources.resx - True - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - Form - - - VideoCaptureDeviceForm.cs - - - Form - - - VisionForm.cs - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - - - - + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {95BDACEA-E8DB-4A87-9472-A37F0879179F} + WinExe + Properties + Controller + Controller %28interface controls%29 + v4.0 + 512 + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + AllRules.ruleset + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + AllRules.ruleset + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + framework.ico + + + + False + ..\..\..\Release\net40\Accord.dll + + + False + ..\..\..\Release\net40\Accord.Controls.Imaging.dll + + + False + ..\..\..\Release\net40\Accord.Controls.Vision.dll + + + False + ..\..\..\Release\net40\Accord.Imaging.dll + + + False + ..\..\..\Release\net40\Accord.MachineLearning.dll + + + False + ..\..\..\Release\net40\Accord.Math.dll + + + False + ..\..\..\Release\net40\Accord.Statistics.dll + + + ..\..\..\Release\net40\Accord.Video.dll + + + ..\..\..\Release\net40\Accord.Video.DirectShow.dll + + + ..\..\..\Release\net40\Accord.Video.VFW.dll + + + False + ..\..\..\Release\net40\Accord.Vision.dll + + + + 3.5 + + + 3.5 + + + + + + + + + Form + + + AboutBox.cs + + + Form + + + FaceForm.cs + + + Form + + + MainForm.cs + + + + + AboutBox.cs + + + FaceForm.cs + Designer + + + MainForm.cs + Designer + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + VideoCaptureDeviceForm.cs + Designer + + + VisionForm.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + Form + + + VideoCaptureDeviceForm.cs + + + Form + + + VisionForm.cs + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + --> \ No newline at end of file diff --git a/Samples/Vision/Kinect/APACHE20 b/Samples/Vision/Dynamic Virtual Wall (Kinect)/APACHE20 similarity index 100% rename from Samples/Vision/Kinect/APACHE20 rename to Samples/Vision/Dynamic Virtual Wall (Kinect)/APACHE20 diff --git a/Samples/Vision/Kinect/AboutBox.Designer.cs b/Samples/Vision/Dynamic Virtual Wall (Kinect)/AboutBox.Designer.cs similarity index 100% rename from Samples/Vision/Kinect/AboutBox.Designer.cs rename to Samples/Vision/Dynamic Virtual Wall (Kinect)/AboutBox.Designer.cs diff --git a/Samples/Vision/Kinect/AboutBox.cs b/Samples/Vision/Dynamic Virtual Wall (Kinect)/AboutBox.cs similarity index 100% rename from Samples/Vision/Kinect/AboutBox.cs rename to Samples/Vision/Dynamic Virtual Wall (Kinect)/AboutBox.cs diff --git a/Samples/Vision/Kinect/AboutBox.resx b/Samples/Vision/Dynamic Virtual Wall (Kinect)/AboutBox.resx similarity index 100% rename from Samples/Vision/Kinect/AboutBox.resx rename to Samples/Vision/Dynamic Virtual Wall (Kinect)/AboutBox.resx diff --git a/Samples/Vision/Dynamic Virtual Wall (Kinect)/Accord.dll.config b/Samples/Vision/Dynamic Virtual Wall (Kinect)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Vision/Dynamic Virtual Wall (Kinect)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Vision/Kinect/Dynamic Virtual Wall (Kinect).csproj b/Samples/Vision/Dynamic Virtual Wall (Kinect)/Dynamic Virtual Wall (Kinect).csproj similarity index 83% rename from Samples/Vision/Kinect/Dynamic Virtual Wall (Kinect).csproj rename to Samples/Vision/Dynamic Virtual Wall (Kinect)/Dynamic Virtual Wall (Kinect).csproj index 75b57afe3..60997bf5f 100644 --- a/Samples/Vision/Kinect/Dynamic Virtual Wall (Kinect).csproj +++ b/Samples/Vision/Dynamic Virtual Wall (Kinect)/Dynamic Virtual Wall (Kinect).csproj @@ -1,265 +1,245 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {99C1ED90-C4CD-4730-B05C-B99EED60EDD1} - WinExe - Properties - KinectController - Dynamic Virtual Wall %28Kinect%29 - v4.0 - 512 - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - AllRules.ruleset - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - AllRules.ruleset - - - true - bin\x86\Debug\ - DEBUG;TRACE - full - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - bin\x86\Release\ - TRACE - true - pdbonly - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - framework.ico - - - - False - ..\..\..\Release\net40\Accord.dll - - - False - ..\..\..\Release\net40\Accord.Controls.dll - - - False - ..\..\..\Release\net40\Accord.Controls.Imaging.dll - - - False - ..\..\..\Release\net40\Accord.Controls.Vision.dll - - - False - ..\..\..\Release\net40\Accord.Imaging.dll - - - False - ..\..\..\Release\net40\Accord.MachineLearning.dll - - - False - ..\..\..\Release\net40\Accord.Math.dll - - - False - ..\..\..\Release\net40\Accord.Statistics.dll - - - False - ..\..\..\Release\net40\Accord.Vision.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Controls.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Imaging.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Math.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Video.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Video.DirectShow.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Video.Kinect.dll - - - - 3.5 - - - 3.5 - - - 3.5 - - - - - - - - - - Form - - - AboutBox.cs - - - Form - - - FaceForm.cs - - - Form - - - MainForm.cs - - - - - AboutBox.cs - - - FaceForm.cs - Designer - - - MainForm.cs - Designer - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - VideoCaptureDeviceForm.cs - Designer - - - VisionForm.cs - Designer - - - True - Resources.resx - True - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - Form - - - VideoCaptureDeviceForm.cs - - - Form - - - VisionForm.cs - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - - - - PreserveNewest - - - + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {99C1ED90-C4CD-4730-B05C-B99EED60EDD1} + WinExe + Properties + KinectController + Dynamic Virtual Wall %28Kinect%29 + v4.0 + 512 + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + AllRules.ruleset + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + AllRules.ruleset + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + framework.ico + + + + False + ..\..\..\Release\net40\Accord.dll + + + False + ..\..\..\Release\net40\Accord.Controls.dll + + + False + ..\..\..\Release\net40\Accord.Controls.Imaging.dll + + + False + ..\..\..\Release\net40\Accord.Controls.Vision.dll + + + False + ..\..\..\Release\net40\Accord.Imaging.dll + + + False + ..\..\..\Release\net40\Accord.MachineLearning.dll + + + False + ..\..\..\Release\net40\Accord.Math.dll + + + False + ..\..\..\Release\net40\Accord.Statistics.dll + + + ..\..\..\Release\net40\Accord.Video.dll + + + ..\..\..\Release\net40\Accord.Video.DirectShow.dll + + + ..\..\..\Release\net40\Accord.Video.Kinect.dll + + + False + ..\..\..\Release\net40\Accord.Vision.dll + + + + 3.5 + + + 3.5 + + + + + + + + + Form + + + AboutBox.cs + + + Form + + + FaceForm.cs + + + Form + + + MainForm.cs + + + + + AboutBox.cs + + + FaceForm.cs + Designer + + + MainForm.cs + Designer + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + VideoCaptureDeviceForm.cs + Designer + + + VisionForm.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + Form + + + VideoCaptureDeviceForm.cs + + + Form + + + VisionForm.cs + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + PreserveNewest + + + + --> \ No newline at end of file diff --git a/Samples/Vision/Kinect/FaceForm.Designer.cs b/Samples/Vision/Dynamic Virtual Wall (Kinect)/FaceForm.Designer.cs similarity index 100% rename from Samples/Vision/Kinect/FaceForm.Designer.cs rename to Samples/Vision/Dynamic Virtual Wall (Kinect)/FaceForm.Designer.cs diff --git a/Samples/Vision/Kinect/FaceForm.cs b/Samples/Vision/Dynamic Virtual Wall (Kinect)/FaceForm.cs similarity index 100% rename from Samples/Vision/Kinect/FaceForm.cs rename to Samples/Vision/Dynamic Virtual Wall (Kinect)/FaceForm.cs diff --git a/Samples/Vision/Kinect/FaceForm.resx b/Samples/Vision/Dynamic Virtual Wall (Kinect)/FaceForm.resx similarity index 100% rename from Samples/Vision/Kinect/FaceForm.resx rename to Samples/Vision/Dynamic Virtual Wall (Kinect)/FaceForm.resx diff --git a/Samples/Vision/Kinect/MainForm.Designer.cs b/Samples/Vision/Dynamic Virtual Wall (Kinect)/MainForm.Designer.cs similarity index 100% rename from Samples/Vision/Kinect/MainForm.Designer.cs rename to Samples/Vision/Dynamic Virtual Wall (Kinect)/MainForm.Designer.cs diff --git a/Samples/Vision/Kinect/MainForm.cs b/Samples/Vision/Dynamic Virtual Wall (Kinect)/MainForm.cs similarity index 100% rename from Samples/Vision/Kinect/MainForm.cs rename to Samples/Vision/Dynamic Virtual Wall (Kinect)/MainForm.cs diff --git a/Samples/Vision/Kinect/MainForm.resx b/Samples/Vision/Dynamic Virtual Wall (Kinect)/MainForm.resx similarity index 100% rename from Samples/Vision/Kinect/MainForm.resx rename to Samples/Vision/Dynamic Virtual Wall (Kinect)/MainForm.resx diff --git a/Samples/Vision/Kinect/Program.cs b/Samples/Vision/Dynamic Virtual Wall (Kinect)/Program.cs similarity index 100% rename from Samples/Vision/Kinect/Program.cs rename to Samples/Vision/Dynamic Virtual Wall (Kinect)/Program.cs diff --git a/Samples/Vision/Kinect/Properties/AssemblyInfo.cs b/Samples/Vision/Dynamic Virtual Wall (Kinect)/Properties/AssemblyInfo.cs similarity index 100% rename from Samples/Vision/Kinect/Properties/AssemblyInfo.cs rename to Samples/Vision/Dynamic Virtual Wall (Kinect)/Properties/AssemblyInfo.cs diff --git a/Samples/Vision/Kinect/Properties/Resources.Designer.cs b/Samples/Vision/Dynamic Virtual Wall (Kinect)/Properties/Resources.Designer.cs similarity index 100% rename from Samples/Vision/Kinect/Properties/Resources.Designer.cs rename to Samples/Vision/Dynamic Virtual Wall (Kinect)/Properties/Resources.Designer.cs diff --git a/Samples/Vision/Dynamic Virtual Wall (Kinect)/Properties/Resources.resx b/Samples/Vision/Dynamic Virtual Wall (Kinect)/Properties/Resources.resx new file mode 100644 index 0000000000..af7dbebba --- /dev/null +++ b/Samples/Vision/Dynamic Virtual Wall (Kinect)/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Vision/Kinect/Properties/Settings.Designer.cs b/Samples/Vision/Dynamic Virtual Wall (Kinect)/Properties/Settings.Designer.cs similarity index 100% rename from Samples/Vision/Kinect/Properties/Settings.Designer.cs rename to Samples/Vision/Dynamic Virtual Wall (Kinect)/Properties/Settings.Designer.cs diff --git a/Samples/Vision/Kinect/Properties/Settings.settings b/Samples/Vision/Dynamic Virtual Wall (Kinect)/Properties/Settings.settings similarity index 100% rename from Samples/Vision/Kinect/Properties/Settings.settings rename to Samples/Vision/Dynamic Virtual Wall (Kinect)/Properties/Settings.settings diff --git a/Samples/Vision/Kinect/VideoCaptureDeviceForm.cs b/Samples/Vision/Dynamic Virtual Wall (Kinect)/VideoCaptureDeviceForm.cs similarity index 100% rename from Samples/Vision/Kinect/VideoCaptureDeviceForm.cs rename to Samples/Vision/Dynamic Virtual Wall (Kinect)/VideoCaptureDeviceForm.cs diff --git a/Samples/Vision/Kinect/VideoCaptureDeviceForm.designer.cs b/Samples/Vision/Dynamic Virtual Wall (Kinect)/VideoCaptureDeviceForm.designer.cs similarity index 100% rename from Samples/Vision/Kinect/VideoCaptureDeviceForm.designer.cs rename to Samples/Vision/Dynamic Virtual Wall (Kinect)/VideoCaptureDeviceForm.designer.cs diff --git a/Samples/Vision/Dynamic Virtual Wall (Kinect)/VideoCaptureDeviceForm.resx b/Samples/Vision/Dynamic Virtual Wall (Kinect)/VideoCaptureDeviceForm.resx new file mode 100644 index 0000000000..c7e0d4bdf --- /dev/null +++ b/Samples/Vision/Dynamic Virtual Wall (Kinect)/VideoCaptureDeviceForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Vision/Kinect/VisionForm.Designer.cs b/Samples/Vision/Dynamic Virtual Wall (Kinect)/VisionForm.Designer.cs similarity index 100% rename from Samples/Vision/Kinect/VisionForm.Designer.cs rename to Samples/Vision/Dynamic Virtual Wall (Kinect)/VisionForm.Designer.cs diff --git a/Samples/Vision/Kinect/VisionForm.cs b/Samples/Vision/Dynamic Virtual Wall (Kinect)/VisionForm.cs similarity index 100% rename from Samples/Vision/Kinect/VisionForm.cs rename to Samples/Vision/Dynamic Virtual Wall (Kinect)/VisionForm.cs diff --git a/Samples/Vision/Dynamic Virtual Wall (Kinect)/VisionForm.resx b/Samples/Vision/Dynamic Virtual Wall (Kinect)/VisionForm.resx new file mode 100644 index 0000000000..c7e0d4bdf --- /dev/null +++ b/Samples/Vision/Dynamic Virtual Wall (Kinect)/VisionForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Vision/Dynamic Virtual Wall (Kinect)/app.config b/Samples/Vision/Dynamic Virtual Wall (Kinect)/app.config new file mode 100644 index 0000000000..a4ae2ed23 --- /dev/null +++ b/Samples/Vision/Dynamic Virtual Wall (Kinect)/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Samples/Vision/Dynamic Virtual Wall (Kinect)/framework.ico b/Samples/Vision/Dynamic Virtual Wall (Kinect)/framework.ico new file mode 100644 index 0000000000..b7126f00d Binary files /dev/null and b/Samples/Vision/Dynamic Virtual Wall (Kinect)/framework.ico differ diff --git a/Samples/Vision/Dynamic Virtual Wall (Kinect)/freenect.dll b/Samples/Vision/Dynamic Virtual Wall (Kinect)/freenect.dll new file mode 100644 index 0000000000..e3974ca6a Binary files /dev/null and b/Samples/Vision/Dynamic Virtual Wall (Kinect)/freenect.dll differ diff --git a/Samples/Vision/Kinect/freenect.txt b/Samples/Vision/Dynamic Virtual Wall (Kinect)/freenect.txt similarity index 100% rename from Samples/Vision/Kinect/freenect.txt rename to Samples/Vision/Dynamic Virtual Wall (Kinect)/freenect.txt diff --git a/Samples/Vision/Face detection (Viola-Jones)/Accord.dll.config b/Samples/Vision/Face detection (Viola-Jones)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Vision/Face detection (Viola-Jones)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Vision/Face detection (Viola-Jones)/Face detection (Viola-Jones).csproj b/Samples/Vision/Face detection (Viola-Jones)/Face detection (Viola-Jones).csproj index abedd3dc4..6f85dd979 100644 --- a/Samples/Vision/Face detection (Viola-Jones)/Face detection (Viola-Jones).csproj +++ b/Samples/Vision/Face detection (Viola-Jones)/Face detection (Viola-Jones).csproj @@ -1,173 +1,171 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {EF3F6EA1-38F2-4C3C-8079-C06B8B5DDCC0} - WinExe - Properties - FaceDetection - Face detection %28Viola-Jones%29 - v4.0 - 512 - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - - true - bin\x86\Debug\ - DEBUG;TRACE - full - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - bin\x86\Release\ - TRACE - true - pdbonly - x86 - true - GlobalSuppressions.cs - prompt - false - AllRules.ruleset - - - framework.ico - - - - False - ..\..\..\Release\net40\Accord.dll - - - False - ..\..\..\Release\net40\Accord.Controls.Vision.dll - - - False - ..\..\..\Release\net40\Accord.Imaging.dll - - - False - ..\..\..\Release\net40\Accord.MachineLearning.dll - - - False - ..\..\..\Release\net40\Accord.Math.dll - - - False - ..\..\..\Release\net40\Accord.Statistics.dll - - - False - ..\..\..\Release\net40\Accord.Vision.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Imaging.dll - - - - 3.5 - - - - - - - - - - Form - - - MainForm.cs - - - - - MainForm.cs - Designer - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - - - - + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {EF3F6EA1-38F2-4C3C-8079-C06B8B5DDCC0} + WinExe + Properties + FaceDetection + Face detection %28Viola-Jones%29 + v4.0 + 512 + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + true + GlobalSuppressions.cs + prompt + false + AllRules.ruleset + + + framework.ico + + + + False + ..\..\..\Release\net40\Accord.dll + + + False + ..\..\..\Release\net40\Accord.Controls.Vision.dll + + + False + ..\..\..\Release\net40\Accord.Imaging.dll + + + False + ..\..\..\Release\net40\Accord.MachineLearning.dll + + + False + ..\..\..\Release\net40\Accord.Math.dll + + + False + ..\..\..\Release\net40\Accord.Statistics.dll + + + False + ..\..\..\Release\net40\Accord.Vision.dll + + + + 3.5 + + + + + + + + + Form + + + MainForm.cs + + + + + MainForm.cs + Designer + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + --> \ No newline at end of file diff --git a/Samples/Vision/Face tracking (Camshift)/Accord.dll.config b/Samples/Vision/Face tracking (Camshift)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Vision/Face tracking (Camshift)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Vision/Face tracking (Camshift)/Face tracking (Camshift).csproj b/Samples/Vision/Face tracking (Camshift)/Face tracking (Camshift).csproj index 7b5a19da1..4382fc298 100644 --- a/Samples/Vision/Face tracking (Camshift)/Face tracking (Camshift).csproj +++ b/Samples/Vision/Face tracking (Camshift)/Face tracking (Camshift).csproj @@ -1,243 +1,224 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {03CCCD6C-CA56-4CAE-A0A5-1C9660D9424B} - WinExe - Properties - FaceTracking - Face tracking %28Camshift%29 - v4.0 - 512 - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - - true - bin\x86\Debug\ - DEBUG;TRACE - full - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - bin\x86\Release\ - TRACE - true - pdbonly - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - framework.ico - - - - False - ..\..\..\Release\net40\Accord.dll - - - False - ..\..\..\Release\net40\Accord.Controls.Vision.dll - - - False - ..\..\..\Release\net40\Accord.Imaging.dll - - - False - ..\..\..\Release\net40\Accord.Math.dll - - - False - ..\..\..\Release\net40\Accord.Statistics.dll - - - False - ..\..\..\Release\net40\Accord.Vision.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Controls.dll - True - - - False - True - ..\..\..\Externals\AForge.NET\AForge.Imaging.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Imaging.Formats.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Math.dll - - - False - True - ..\..\..\Externals\AForge.NET\AForge.Video.dll - - - False - True - ..\..\..\Externals\AForge.NET\AForge.Video.DirectShow.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Video.VFW.dll - - - - 3.5 - - - 3.5 - - - - - - - - - - Form - - - AboutBox.cs - - - Component - - - DefineRegionsControl.cs - - - - Form - - - MainForm.cs - - - Form - - - MotionRegionsForm.cs - - - - - AboutBox.cs - - - MainForm.cs - Designer - - - MotionRegionsForm.cs - Designer - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - URLForm.cs - Designer - - - VideoCaptureDeviceForm.cs - Designer - - - True - Resources.resx - True - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - Form - - - URLForm.cs - - - Form - - - VideoCaptureDeviceForm.cs - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - - - - + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {03CCCD6C-CA56-4CAE-A0A5-1C9660D9424B} + WinExe + Properties + FaceTracking + Face tracking %28Camshift%29 + v4.0 + 512 + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + framework.ico + + + + False + ..\..\..\Release\net40\Accord.dll + + + ..\..\..\Release\net40\Accord.Controls.dll + + + ..\..\..\Release\net40\Accord.Controls.Imaging.dll + + + False + ..\..\..\Release\net40\Accord.Controls.Vision.dll + + + False + ..\..\..\Release\net40\Accord.Imaging.dll + + + False + ..\..\..\Release\net40\Accord.Math.dll + + + False + ..\..\..\Release\net40\Accord.Statistics.dll + + + ..\..\..\Release\net40\Accord.Video.dll + + + ..\..\..\Release\net40\Accord.Video.DirectShow.dll + + + ..\..\..\Release\net40\Accord.Video.VFW.dll + + + False + ..\..\..\Release\net40\Accord.Vision.dll + + + + 3.5 + + + 3.5 + + + + + + + + + Form + + + AboutBox.cs + + + Component + + + DefineRegionsControl.cs + + + + Form + + + MainForm.cs + + + Form + + + MotionRegionsForm.cs + + + + + AboutBox.cs + + + MainForm.cs + Designer + + + MotionRegionsForm.cs + Designer + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + URLForm.cs + Designer + + + VideoCaptureDeviceForm.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + Form + + + URLForm.cs + + + Form + + + VideoCaptureDeviceForm.cs + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + --> \ No newline at end of file diff --git a/Samples/Vision/Face tracking (Camshift)/app.config b/Samples/Vision/Face tracking (Camshift)/app.config index 1c7622f39..a4ae2ed23 100644 --- a/Samples/Vision/Face tracking (Camshift)/app.config +++ b/Samples/Vision/Face tracking (Camshift)/app.config @@ -1,11 +1,3 @@ - - - - - - - - diff --git a/Samples/Vision/Gloves (Color tracking)/Accord.dll.config b/Samples/Vision/Gloves (Color tracking)/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Vision/Gloves (Color tracking)/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Vision/Gloves (Color tracking)/Gloves (color tracking).csproj b/Samples/Vision/Gloves (Color tracking)/Gloves (color tracking).csproj index d827efdbb..f220516ff 100644 --- a/Samples/Vision/Gloves (Color tracking)/Gloves (color tracking).csproj +++ b/Samples/Vision/Gloves (Color tracking)/Gloves (color tracking).csproj @@ -1,254 +1,221 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {09D9131B-3277-476F-8500-311E69B58AFB} - WinExe - Properties - GloveTracking - Gloves %28Color tracking%29 - v4.0 - 512 - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - AllRules.ruleset - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - AllRules.ruleset - - - true - bin\x86\Debug\ - DEBUG;TRACE - full - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - bin\x86\Release\ - TRACE - true - pdbonly - x86 - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - - - framework.ico - - - - False - ..\..\..\Release\net40\Accord.dll - - - False - ..\..\..\Release\net40\Accord.Controls.Vision.dll - - - False - ..\..\..\Release\net40\Accord.Imaging.dll - - - False - ..\..\..\Release\net40\Accord.Math.dll - - - False - ..\..\..\Release\net40\Accord.Statistics.dll - - - False - ..\..\..\Release\net40\Accord.Vision.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Controls.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Imaging.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Math.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Video.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Video.DirectShow.dll - - - False - ..\..\..\Externals\AForge.NET\AForge.Video.VFW.dll - - - - 3.5 - - - 3.5 - - - 3.5 - - - - - - - - - - Form - - - AboutBox.cs - - - Component - - - Form - - - Form - - - MainForm.cs - - - - - AboutBox.cs - - - FilterPreview.cs - Designer - - - HSLFilteringForm.cs - Designer - - - MainForm.cs - Designer - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - URLForm.cs - Designer - - - VideoCaptureDeviceForm.cs - Designer - - - True - Resources.resx - True - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - Form - - - URLForm.cs - - - Form - - - VideoCaptureDeviceForm.cs - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - - - - + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {09D9131B-3277-476F-8500-311E69B58AFB} + WinExe + Properties + GloveTracking + Gloves %28Color tracking%29 + v4.0 + 512 + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + framework.ico + + + + False + ..\..\..\Release\net40\Accord.dll + + + ..\..\..\Release\net40\Accord.Controls.dll + + + ..\..\..\Release\net40\Accord.Controls.Imaging.dll + + + False + ..\..\..\Release\net40\Accord.Controls.Vision.dll + + + False + ..\..\..\Release\net40\Accord.Imaging.dll + + + False + ..\..\..\Release\net40\Accord.Math.dll + + + False + ..\..\..\Release\net40\Accord.Statistics.dll + + + ..\..\..\Release\net40\Accord.Video.dll + + + ..\..\..\Release\net40\Accord.Video.DirectShow.dll + + + ..\..\..\Release\net40\Accord.Video.VFW.dll + + + False + ..\..\..\Release\net40\Accord.Vision.dll + + + + 3.5 + + + 3.5 + + + + + + + + + Form + + + AboutBox.cs + + + Component + + + Form + + + Form + + + MainForm.cs + + + + + AboutBox.cs + + + FilterPreview.cs + Designer + + + HSLFilteringForm.cs + Designer + + + MainForm.cs + Designer + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + URLForm.cs + Designer + + + VideoCaptureDeviceForm.cs + Designer + + + True + Resources.resx + True + + + PreserveNewest + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + Form + + + URLForm.cs + + + Form + + + VideoCaptureDeviceForm.cs + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + --> \ No newline at end of file diff --git a/Samples/Vision/Gloves (Color tracking)/app.config b/Samples/Vision/Gloves (Color tracking)/app.config index 1c7622f39..a4ae2ed23 100644 --- a/Samples/Vision/Gloves (Color tracking)/app.config +++ b/Samples/Vision/Gloves (Color tracking)/app.config @@ -1,11 +1,3 @@ - - - - - - - - diff --git a/Samples/Vision/Kinect/app.config b/Samples/Vision/Kinect/app.config deleted file mode 100644 index fc49d59c7..0000000000 --- a/Samples/Vision/Kinect/app.config +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/Samples/Vision/Motion detection/AboutForm.Designer.cs b/Samples/Vision/Motion detection/AboutForm.Designer.cs new file mode 100644 index 0000000000..970414504 --- /dev/null +++ b/Samples/Vision/Motion detection/AboutForm.Designer.cs @@ -0,0 +1,182 @@ +namespace SampleApp +{ + partial class AboutForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AboutForm)); + this.pictureBox1 = new System.Windows.Forms.PictureBox(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.panel1 = new System.Windows.Forms.Panel(); + this.emailLabel = new System.Windows.Forms.LinkLabel(); + this.label3 = new System.Windows.Forms.Label(); + this.aforgeLabel = new System.Windows.Forms.LinkLabel(); + this.okButton = new System.Windows.Forms.Button(); + this.pictureBox2 = new System.Windows.Forms.PictureBox(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + this.panel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).BeginInit(); + this.SuspendLayout(); + // + // pictureBox1 + // + this.pictureBox1.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox1.Image"))); + this.pictureBox1.Location = new System.Drawing.Point(22, 31); + this.pictureBox1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.pictureBox1.Name = "pictureBox1"; + this.pictureBox1.Size = new System.Drawing.Size(75, 77); + this.pictureBox1.TabIndex = 0; + this.pictureBox1.TabStop = false; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(144, 31); + this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(162, 20); + this.label1.TabIndex = 1; + this.label1.Text = "Motion Detector 2.4.0"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(58, 69); + this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(335, 20); + this.label2.TabIndex = 2; + this.label2.Text = "Sample application of AForge.NET framework:"; + // + // panel1 + // + this.panel1.Controls.Add(this.emailLabel); + this.panel1.Controls.Add(this.label3); + this.panel1.Controls.Add(this.aforgeLabel); + this.panel1.Controls.Add(this.label2); + this.panel1.Controls.Add(this.label1); + this.panel1.Location = new System.Drawing.Point(106, 0); + this.panel1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(454, 214); + this.panel1.TabIndex = 3; + // + // emailLabel + // + this.emailLabel.AutoSize = true; + this.emailLabel.Location = new System.Drawing.Point(112, 169); + this.emailLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.emailLabel.Name = "emailLabel"; + this.emailLabel.Size = new System.Drawing.Size(225, 20); + this.emailLabel.TabIndex = 5; + this.emailLabel.TabStop = true; + this.emailLabel.Text = "andrew.kirillov@aforgenet.com"; + this.emailLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkClicked); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(82, 146); + this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(281, 20); + this.label3.TabIndex = 4; + this.label3.Text = "Copyright 2005-2009, Andrew Kirillov"; + // + // aforgeLabel + // + this.aforgeLabel.AutoSize = true; + this.aforgeLabel.Location = new System.Drawing.Point(82, 92); + this.aforgeLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.aforgeLabel.Name = "aforgeLabel"; + this.aforgeLabel.Size = new System.Drawing.Size(271, 20); + this.aforgeLabel.TabIndex = 3; + this.aforgeLabel.TabStop = true; + this.aforgeLabel.Text = "http://www.aforgenet.com/framework/"; + this.aforgeLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkClicked); + // + // okButton + // + this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK; + this.okButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.okButton.Location = new System.Drawing.Point(225, 231); + this.okButton.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.okButton.Name = "okButton"; + this.okButton.Size = new System.Drawing.Size(112, 35); + this.okButton.TabIndex = 13; + this.okButton.Text = "Ok"; + // + // pictureBox2 + // + this.pictureBox2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.pictureBox2.Location = new System.Drawing.Point(22, 215); + this.pictureBox2.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.pictureBox2.Name = "pictureBox2"; + this.pictureBox2.Size = new System.Drawing.Size(515, 2); + this.pictureBox2.TabIndex = 12; + this.pictureBox2.TabStop = false; + // + // AboutForm + // + this.AcceptButton = this.okButton; + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(561, 282); + this.Controls.Add(this.okButton); + this.Controls.Add(this.pictureBox2); + this.Controls.Add(this.panel1); + this.Controls.Add(this.pictureBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "AboutForm"; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "About"; + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.LinkLabel aforgeLabel; + private System.Windows.Forms.LinkLabel emailLabel; + private System.Windows.Forms.Button okButton; + private System.Windows.Forms.PictureBox pictureBox2; + } +} \ No newline at end of file diff --git a/Samples/Vision/Motion detection/AboutForm.cs b/Samples/Vision/Motion detection/AboutForm.cs new file mode 100644 index 0000000000..71df6f207 --- /dev/null +++ b/Samples/Vision/Motion detection/AboutForm.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace SampleApp +{ + public partial class AboutForm : Form + { + public AboutForm( ) + { + InitializeComponent( ); + + // initialize links + emailLabel.Links.Add( 0, emailLabel.Text.Length, "mailto:andrew.kirillov@aforgenet.com" ); + aforgeLabel.Links.Add( 0, aforgeLabel.Text.Length, "http://www.aforgenet.com/framework/" ); + } + + // Link clicked + private void LinkClicked( object sender, LinkLabelLinkClickedEventArgs e ) + { + System.Diagnostics.Process.Start( e.Link.LinkData.ToString( ) ); + } + } +} \ No newline at end of file diff --git a/Samples/Vision/Motion detection/AboutForm.resx b/Samples/Vision/Motion detection/AboutForm.resx new file mode 100644 index 0000000000..7f3c7da77 --- /dev/null +++ b/Samples/Vision/Motion detection/AboutForm.resx @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6 + JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAJTklEQVRoQ+2YfWhVdRjHVwS9ERGIkAlF + RUpzpltlZrYwszR1ic7UNTTFMnXuqrUpbr7XEqcuMbXUps03Eu2PlKzZTE1zmiUtTIUkoxcME/8wKCl+ + nc9zz/fw2/Xq7l32IvjAwzn33HPv/Xyft9/v3IzLdtkuIVu3bq1btWqlW758mVu6dHHkCxcutCPXeZ/7 + wo/8dwaED8z51q0fuL17P3VHjhx2J06ccCdPnjT/4Yfv7dpnn+1327fvcJs3b7b7+Rzi+I7way++bdq0 + 0X5MsDjXADl48IA7duwbgwRYDrDcv47r3uPHvzXn83zfvHnzLo4IQSqqtbUfRlH1gXzIplzQwDY0NJhw + siHntX4vxEjfFGVAT58+7c6cOWPOuUohVXju5XPcS5QPHfrSwDkCu3v3TssggeE1TimNHj26eQJIIY6d + PXs2comQEHmiIK7pPq4DTSBw4Kj5xYvr3KxZu93IkfvMhw6tdwMHfuSKizdbFsh637z+Lj+/f/oimBD8 + eFPmi5PxOURQHjhRpplXrPjEgGOxQ66s7Lh5aekxe11U1BBE+4tISH7+JjdnToXr1Ok+8xArNVO9Y6Sf + iGlS4EQxmRFpQRNxoBcsOGiQM2accvPn/2I+d+5PEfzEiUfPEYD367fN5eUVu5ycjukJAJyIAQE0dQoY + tamywnntG1EXOF5RscLNnn0qqOPfXU3Nb0FAfg2unQqEnGgU/fMJIAvZ2aNMQJcunVMTQNMATN3dcls7 + 17PnE27EiBHWTGpkoionMzI1JxkDvrLyjEFv3HjWzoGXAImQADxRAJ6WAOqNyNL1nGulpJw073kfEZoY + uMoJcJUNcNXVfxg8GUCARCQK8LOAAF+EBOTmdr2wAOBKXhxvkICzgJSVldkRMbiWf+5BxK5d9VZGeGL0 + gQZ+yZI/7VwiEgWcv4ziIlIWAPzsWTMNkAx06NCeD7hrrrvJDR48yARMnz4jOpIJYP2Fh9KjB8aOfcfA + qftUBEye/KOJiEf97aB555ojIqtLiQmglOOkSYyIAk2Ep0wpdd26dXNXXN3a5dz/sB1xegKBZKW0tMTu + 1wLki8A3bPjG4AUuZ/o07oNTgdj4pOE3mfU4wEwdAoGArKw2Vh0h7rlGVAFDANEGvPXt2e7ernkGf1WL + TnYEmvtisWJrbDKRmAW8vv6ACVDdywHnSNSLilbGfyuAJdtEuLCw0PXp08eude+ea4sZAvjdEDW5EVFE + UO9EAPh+BeMM3PcWdz1uWSAaCABAq2qiiJqaX84RMHXqYdf1ySKrZz4rWKJNhhFAJlQyCKCUGOshanIj + osADx5cwPkdOe9Vl3PCAy2jZs5GPfH68lRn3IZYvRwTQvpA1a1gH4uUC/Pjxq20UEm3AfViu812I4hxB + Awb0TV0AKUIAJcE50S544eU49C2DGjkRRAAZIGrcrzLSRGLErl3bYHXOQgY8QIAlwiIAIbxW/ZMh7p80 + aVf6GeCcUgEU4Ctue9Zl3PqCy7g9eB34zdnPmQDAiSSpZnxqXairq7Ot9urV9dG08cvFh0WQyoWMcOQ1 + 9U+my8t/Tk0APQA8fQBcm/vzDdTgAW9T4q68u9ycaxLADxItxifQLGDaK7Fpo1klQHCCTVb/fBcTp6Cg + yEqvoGCHCWC4hKjJTeMRAZzTwICagAA+Iyvoh3sq48dWz0ZjlGhSBkQfaO2RWLXnL9ptsx0RRBs4gBOb + VSVFyfTqNcTqnsgDz7Y6JQEsXpQOAnB6wWo+iD5RN/CcN+PHoJyYQggQFKWjBx/WFJwts7YJqn+g+X6A + CAKlwjV6ZNq0o7agsZgBH4/+NvfM0JlNC8BoSgmg5ighlU8kICwljVGgmCpMH6D5HD+G04DapPXu/ajd + S+llTsx010y41t04qoWLVS2yccsWgp0nLng8L+/91AUQdaLCEZBJU6qsXARNCVFSLCwIIO3AA4YAsuh7 + LHbE9jUcKQu+L6f8YfMNB9e74cuHm5Cu5flWbiUln0fglA7eq9cWE9BkE2PaTiCAPqCmbRIxgchCOIXo + DwSQeuA5p3mZYjgZJPralHHEq6u/s6jP/7jCBKzc/4ad3znz1igbPPj4Anr0eDcoqbKm4WXA0wscAWGy + EHHLRCBE0Vf904DcQ8Q1xSZMqDJwf0uM+wIEX/HxFPOey3pYNsgO2eCz1H9u7tpgPzQpdQEYAnCmEk5j + kkayATzvMUkYh5Qcc5/7EE0mKBUfXL506dFIwOt7Kg186raYK60b7mIfFLpRW/pH2WAXwBBAAL8ZoqVu + RBgHkC8QOE7ta/Sx+qpvKEEE8CxAMwKtxsQlAGhEJMIP3/qY+aPr2kTZqHrrXctqiJWeAabJRBYQweID + OCXD6OQ9JoTGpwSoGX33BSj6PvyQLY+4/PdyzPO2tHXXv3KtCaHZ2Z6EWOkZTQkcT188qLDiMnGA14qr + hQunHxYtqrb69eFpSBoUAURd0R/34dON4AGXD6i9O8pG5qzM5gkgqjiPi2zYJILSQQTAEoLTD4w8xp8m + iRwBwEgA0R9dm2cCfHjA8UHbM90zO7PcsD0dXbtlLaNshGipGfAAAa/nXbbOEuE/2Mv5DOOPRch3CQDc + j37h+w9FAnxwwY/Yl+1GfX6vXaes0hIBDDUuAXKJSHyQoVYpKaZHUwIU/YLaYO+fJOoClxc1dLZ7Ws1o + lZ4AGhZoysf/04pzCcF5PtazABswyohMyC8koClwfOKRXDdgZ/v0BGA0smB9lyDfyQgimERkQfCcM9d9 + AWO3946X0I7spPA+OM57aZcQxiKlKPtOxBNFqbnJAtNo2LBVbsiQGvt3gf+QEEDtI6B4z5PuuT1dTADw + 5wOffKy767i+dfPgMbYIjEigibDviaKIvpoZEb4jUBmYeqDABBTtf6RR5H14wHkP8PYL7D+q5pu/2gIj + AWpevSbKjFLfJYb3EUD0EVCy7ykTQBb86CvyivqYt8f8PXgZ04hssJ1QVgCWCBzQRHjWB1ZsxCcKUBZ8 + eBoV8Adff/DigCczGpusIAY4Rifl45cQ2wre0xYdcQiYXv+8uZ8Flc4d1S0N/qU1L/1z8L6xyAmSvRJZ + ItI+eHirGXDAV341xgSYf93bFjHeY1sd3vrvG+sFj4zql/ByI5OA1xpejEQo6uEt/28jwu1X3mUC2MD9 + 51FvjtGcgLetantpgV9cy8j4C1GhZ3Lpsr77AAAAAElFTkSuQmCC + + + \ No newline at end of file diff --git a/Samples/Vision/Motion detection/Accord.dll.config b/Samples/Vision/Motion detection/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Samples/Vision/Motion detection/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/Vision/Motion detection/App.ico b/Samples/Vision/Motion detection/App.ico new file mode 100644 index 0000000000..2ab4a4fb3 Binary files /dev/null and b/Samples/Vision/Motion detection/App.ico differ diff --git a/Samples/Vision/Motion detection/DefineRegionsControl.Designer.cs b/Samples/Vision/Motion detection/DefineRegionsControl.Designer.cs new file mode 100644 index 0000000000..40948e56d --- /dev/null +++ b/Samples/Vision/Motion detection/DefineRegionsControl.Designer.cs @@ -0,0 +1,36 @@ +namespace SampleApp +{ + partial class DefineRegionsControl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + components = new System.ComponentModel.Container( ); + } + + #endregion + } +} diff --git a/Samples/Vision/Motion detection/DefineRegionsControl.cs b/Samples/Vision/Motion detection/DefineRegionsControl.cs new file mode 100644 index 0000000000..626cacb34 --- /dev/null +++ b/Samples/Vision/Motion detection/DefineRegionsControl.cs @@ -0,0 +1,287 @@ +// Motion Detection sample application +// AForge.NET Framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Text; +using System.Windows.Forms; + +namespace SampleApp +{ + // Drawing modes + public enum DrawingMode + { + None, + Rectangular + } + + // Delegate to notify about new rectangle + public delegate void NewRectangleHandler( object sender, Rectangle rect ); + + // Control to define motion regions + public partial class DefineRegionsControl : System.Windows.Forms.Control + { + // border's color + private Color borderColor = Color.Black; + // backgound's color + private Color backColor = Color.FromArgb( 96, 96, 96 ); + // selection rectangle's color + private Color selectionColor = Color.Yellow; + // rectangles' color + private Color rectsColor = Color.FromArgb( 0, 255, 0 ); + // backgroun image + private Bitmap backImage = null; + + // collection of rectangles + private List rectangles = new List( ); + + private DrawingMode drawingMode = DrawingMode.None; + private bool dragging = false; + + private Point startPoint; + private Point endPoint; + + // Background image + public new Bitmap BackgroundImage + { + get { return backImage; } + set { backImage = value; } + } + + // Drawing mode + public DrawingMode DrawingMode + { + get { return drawingMode; } + set + { + drawingMode = value; + + this.Cursor = ( drawingMode == DrawingMode.None ) ? Cursors.Default : Cursors.Cross; + } + } + + // Rectangles array + public Rectangle[] Rectangles + { + get + { + Rectangle[] rects = new Rectangle[rectangles.Count]; + rectangles.CopyTo( rects ); + return rects; + } + set + { + rectangles.Clear( ); + + if ( value != null ) + { + rectangles.AddRange( value ); + } + Invalidate( ); + } + } + + // Event to notify about new rectangle + public event NewRectangleHandler OnNewRectangle; + + // Class constructor + public DefineRegionsControl( ) + { + InitializeComponent( ); + + // update style of the control + SetStyle( ControlStyles.AllPaintingInWmPaint | ControlStyles.DoubleBuffer | + ControlStyles.ResizeRedraw | ControlStyles.UserPaint, true ); + } + + // Remove all regions + public void RemoveAllRegions( ) + { + rectangles.RemoveRange( 0, rectangles.Count ); + this.Invalidate( ); + } + + // Paint the control + protected override void OnPaint( PaintEventArgs pe ) + { + Graphics g = pe.Graphics; + Rectangle rect = this.ClientRectangle; + + // draw rectangle + using ( Pen pen = new Pen( borderColor, 1 ) ) + { + g.DrawRectangle( pen, rect.X, rect.Y, rect.Width - 1, rect.Height - 1 ); + } + + // draw background + if ( backImage != null ) + { + g.DrawImage( backImage, 1, 1, rect.Width - 2, rect.Height - 2 ); + } + else + { + using ( Brush backBrush = new SolidBrush( backColor ) ) + { + g.FillRectangle( backBrush, 1, 1, rect.Width - 2, rect.Height - 2 ); + } + } + + // draw rectangles + using ( Pen pen = new Pen( rectsColor, 1 ) ) + { + foreach ( Rectangle r in rectangles ) + { + g.DrawRectangle( pen, r.X + 1, r.Y + 1, r.Width - 1, r.Height - 1 ); + } + } + + base.OnPaint( pe ); + } + + // On mouse down + protected override void OnMouseDown( MouseEventArgs e ) + { + // check drawing mode + if ( drawingMode == DrawingMode.Rectangular ) + { + // check button type + if ( e.Button == MouseButtons.Left ) + { + // switch to dragging mode + dragging = true; + this.Capture = true; + + // set initial starting and ending points + startPoint.X = endPoint.X = e.X; + startPoint.Y = endPoint.Y = e.Y; + // draw selection rectangle + ControlPaint.DrawReversibleFrame( new Rectangle( e.X, e.Y, 1, 1 ), Color.Green, FrameStyle.Dashed ); + } + else if ( e.Button == MouseButtons.Right ) + { + } + } + } + + // On mouse up + protected override void OnMouseUp( MouseEventArgs e ) + { + // check drawing and dragging mode + if ( ( drawingMode == DrawingMode.Rectangular ) && ( dragging == true ) ) + { + // stop dragging mode + dragging = false; + this.Capture = false; + + // reset drawing mode + drawingMode = DrawingMode.None; + this.Cursor = Cursors.Default; + + // erase selection rectangle + DrawSelectionRectangle( ); + + // get normalized points + NormalizePoints( ref startPoint, ref endPoint ); + + // check that points are inside of the control + CheckPointsInClient( ref startPoint ); + CheckPointsInClient( ref endPoint ); + + // add rectangle to collection + Rectangle rect = new Rectangle( startPoint.X - 1, startPoint.Y - 1, endPoint.X - startPoint.X + 1, endPoint.Y - startPoint.Y + 1 ); + rectangles.Add( rect ); + + // notify clients about new available rectangle + if ( OnNewRectangle != null ) + { + OnNewRectangle( this, rect ); + } + + // redraw the control + this.Invalidate( ); + } + } + + // On mouse move + protected override void OnMouseMove( MouseEventArgs e ) + { + if ( dragging == true ) + { + // erase old rectangle + DrawSelectionRectangle( ); + + endPoint.X = e.X; + endPoint.Y = e.Y; + + // draw new rectangle + DrawSelectionRectangle( ); + } + } + + // Draw reversable selection rectangle + private void DrawSelectionRectangle( ) + { + Point start = startPoint; + Point end = endPoint; + + // do normalization + NormalizePoints( ref start, ref end ); + + // check that points are inside of the control + CheckPointsInClient( ref start ); + CheckPointsInClient( ref end ); + + // convert client coordinates to screen coordinates + Point screenStartPoint = this.PointToScreen( start); + Point screenEndPoint = this.PointToScreen( end ); + + // draw rectangle + ControlPaint.DrawReversibleFrame( + new Rectangle( + screenStartPoint.X, screenStartPoint.Y, + screenEndPoint.X - screenStartPoint.X + 1, screenEndPoint.Y - screenStartPoint.Y + 1 ), + selectionColor, FrameStyle.Dashed ); + } + + // Normalize points, so the first point will keep smaller coordinates + private void NormalizePoints( ref Point point1, ref Point point2 ) + { + Point t1 = point1; + Point t2 = point2; + + point1.X = Math.Min( t1.X, t2.X ); + point1.Y = Math.Min( t1.Y, t2.Y ); + point2.X = Math.Max( t1.X, t2.X ); + point2.Y = Math.Max( t1.Y, t2.Y ); + } + + // Ensure the point is in client area + private void CheckPointsInClient( ref Point point ) + { + if ( point.X < 1 ) + { + point.X = 1; + } + if ( point.Y < 1 ) + { + point.Y = 1; + } + if ( point.X >= ClientRectangle.Width - 1 ) + { + point.X = ClientRectangle.Width - 2; + } + if ( point.Y >= ClientRectangle.Height - 1 ) + { + point.Y = ClientRectangle.Height - 2; + } + } + } +} diff --git a/Samples/Vision/Motion detection/Images/clear.png b/Samples/Vision/Motion detection/Images/clear.png new file mode 100644 index 0000000000..53d350768 Binary files /dev/null and b/Samples/Vision/Motion detection/Images/clear.png differ diff --git a/Samples/Vision/Motion detection/Images/rectangle.png b/Samples/Vision/Motion detection/Images/rectangle.png new file mode 100644 index 0000000000..b296f1746 Binary files /dev/null and b/Samples/Vision/Motion detection/Images/rectangle.png differ diff --git a/Samples/Vision/Motion detection/MainForm.Designer.cs b/Samples/Vision/Motion detection/MainForm.Designer.cs new file mode 100644 index 0000000000..efa281005 --- /dev/null +++ b/Samples/Vision/Motion detection/MainForm.Designer.cs @@ -0,0 +1,443 @@ +namespace SampleApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); + this.menuMenu = new System.Windows.Forms.MenuStrip(); + this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.openVideoFileusingDirectShowToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.localVideoCaptureDeviceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.openJPEGURLToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.openMJPEGURLToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.openToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator(); + this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.motionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.motionDetectionAlgorithmToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.noneToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.twoFramesDifferenceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.simpleBackgroundModelingToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.motionProcessingAlgorithmToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.noneToolStripMenuItem2 = new System.Windows.Forms.ToolStripMenuItem(); + this.motionAreaHighlightingToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.motionBorderHighlightingToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.blobCountingToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridMotionAreaProcessingToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator(); + this.defineMotionregionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripSeparator(); + this.showMotionHistoryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.localVideoCaptureSettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.crossbarVideoSettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.openFileDialog = new System.Windows.Forms.OpenFileDialog(); + this.timer = new System.Windows.Forms.Timer(this.components); + this.statusBar = new System.Windows.Forms.StatusStrip(); + this.fpsLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.objectsCountLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.panel1 = new System.Windows.Forms.Panel(); + this.videoSourcePlayer = new AForge.Controls.VideoSourcePlayer(); + this.alarmTimer = new System.Windows.Forms.Timer(this.components); + this.menuMenu.SuspendLayout(); + this.statusBar.SuspendLayout(); + this.panel1.SuspendLayout(); + this.SuspendLayout(); + // + // menuMenu + // + this.menuMenu.ImageScalingSize = new System.Drawing.Size(24, 24); + this.menuMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.fileToolStripMenuItem, + this.motionToolStripMenuItem, + this.toolsToolStripMenuItem, + this.helpToolStripMenuItem}); + this.menuMenu.Location = new System.Drawing.Point(0, 0); + this.menuMenu.Name = "menuMenu"; + this.menuMenu.Padding = new System.Windows.Forms.Padding(9, 3, 0, 3); + this.menuMenu.Size = new System.Drawing.Size(648, 35); + this.menuMenu.TabIndex = 0; + // + // fileToolStripMenuItem + // + this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.openVideoFileusingDirectShowToolStripMenuItem, + this.localVideoCaptureDeviceToolStripMenuItem, + this.openJPEGURLToolStripMenuItem, + this.openMJPEGURLToolStripMenuItem, + this.openToolStripMenuItem, + this.toolStripMenuItem1, + this.exitToolStripMenuItem}); + this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; + this.fileToolStripMenuItem.Size = new System.Drawing.Size(50, 29); + this.fileToolStripMenuItem.Text = "&File"; + // + // openVideoFileusingDirectShowToolStripMenuItem + // + this.openVideoFileusingDirectShowToolStripMenuItem.Name = "openVideoFileusingDirectShowToolStripMenuItem"; + this.openVideoFileusingDirectShowToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O))); + this.openVideoFileusingDirectShowToolStripMenuItem.Size = new System.Drawing.Size(377, 30); + this.openVideoFileusingDirectShowToolStripMenuItem.Text = "&Open"; + this.openVideoFileusingDirectShowToolStripMenuItem.Click += new System.EventHandler(this.openVideoFileusingDirectShowToolStripMenuItem_Click); + // + // localVideoCaptureDeviceToolStripMenuItem + // + this.localVideoCaptureDeviceToolStripMenuItem.Name = "localVideoCaptureDeviceToolStripMenuItem"; + this.localVideoCaptureDeviceToolStripMenuItem.Size = new System.Drawing.Size(377, 30); + this.localVideoCaptureDeviceToolStripMenuItem.Text = "Local &Video Capture Device"; + this.localVideoCaptureDeviceToolStripMenuItem.Click += new System.EventHandler(this.localVideoCaptureDeviceToolStripMenuItem_Click); + // + // openJPEGURLToolStripMenuItem + // + this.openJPEGURLToolStripMenuItem.Name = "openJPEGURLToolStripMenuItem"; + this.openJPEGURLToolStripMenuItem.Size = new System.Drawing.Size(377, 30); + this.openJPEGURLToolStripMenuItem.Text = "Open JPEG &URL"; + this.openJPEGURLToolStripMenuItem.Click += new System.EventHandler(this.openJPEGURLToolStripMenuItem_Click); + // + // openMJPEGURLToolStripMenuItem + // + this.openMJPEGURLToolStripMenuItem.Name = "openMJPEGURLToolStripMenuItem"; + this.openMJPEGURLToolStripMenuItem.Size = new System.Drawing.Size(377, 30); + this.openMJPEGURLToolStripMenuItem.Text = "Open &MJPEG URL"; + this.openMJPEGURLToolStripMenuItem.Click += new System.EventHandler(this.openMJPEGURLToolStripMenuItem_Click); + // + // openToolStripMenuItem + // + this.openToolStripMenuItem.Name = "openToolStripMenuItem"; + this.openToolStripMenuItem.Size = new System.Drawing.Size(377, 30); + this.openToolStripMenuItem.Text = "Open video file (using VFW interface)"; + this.openToolStripMenuItem.Click += new System.EventHandler(this.openToolStripMenuItem_Click); + // + // toolStripMenuItem1 + // + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + this.toolStripMenuItem1.Size = new System.Drawing.Size(374, 6); + // + // exitToolStripMenuItem + // + this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; + this.exitToolStripMenuItem.Size = new System.Drawing.Size(377, 30); + this.exitToolStripMenuItem.Text = "E&xit"; + this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click); + // + // motionToolStripMenuItem + // + this.motionToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.motionDetectionAlgorithmToolStripMenuItem, + this.motionProcessingAlgorithmToolStripMenuItem, + this.toolStripMenuItem2, + this.defineMotionregionsToolStripMenuItem, + this.toolStripMenuItem3, + this.showMotionHistoryToolStripMenuItem}); + this.motionToolStripMenuItem.Name = "motionToolStripMenuItem"; + this.motionToolStripMenuItem.Size = new System.Drawing.Size(82, 29); + this.motionToolStripMenuItem.Text = "&Motion"; + this.motionToolStripMenuItem.DropDownOpening += new System.EventHandler(this.motionToolStripMenuItem_DropDownOpening); + // + // motionDetectionAlgorithmToolStripMenuItem + // + this.motionDetectionAlgorithmToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.noneToolStripMenuItem1, + this.twoFramesDifferenceToolStripMenuItem, + this.simpleBackgroundModelingToolStripMenuItem}); + this.motionDetectionAlgorithmToolStripMenuItem.Name = "motionDetectionAlgorithmToolStripMenuItem"; + this.motionDetectionAlgorithmToolStripMenuItem.Size = new System.Drawing.Size(317, 30); + this.motionDetectionAlgorithmToolStripMenuItem.Text = "Motion Detection Algorithm"; + // + // noneToolStripMenuItem1 + // + this.noneToolStripMenuItem1.Name = "noneToolStripMenuItem1"; + this.noneToolStripMenuItem1.Size = new System.Drawing.Size(319, 30); + this.noneToolStripMenuItem1.Text = "None"; + this.noneToolStripMenuItem1.Click += new System.EventHandler(this.noneToolStripMenuItem1_Click); + // + // twoFramesDifferenceToolStripMenuItem + // + this.twoFramesDifferenceToolStripMenuItem.Name = "twoFramesDifferenceToolStripMenuItem"; + this.twoFramesDifferenceToolStripMenuItem.Size = new System.Drawing.Size(319, 30); + this.twoFramesDifferenceToolStripMenuItem.Text = "Two Frames Difference"; + this.twoFramesDifferenceToolStripMenuItem.Click += new System.EventHandler(this.twoFramesDifferenceToolStripMenuItem_Click); + // + // simpleBackgroundModelingToolStripMenuItem + // + this.simpleBackgroundModelingToolStripMenuItem.Name = "simpleBackgroundModelingToolStripMenuItem"; + this.simpleBackgroundModelingToolStripMenuItem.Size = new System.Drawing.Size(319, 30); + this.simpleBackgroundModelingToolStripMenuItem.Text = "Simple Background Modeling"; + this.simpleBackgroundModelingToolStripMenuItem.Click += new System.EventHandler(this.simpleBackgroundModelingToolStripMenuItem_Click); + // + // motionProcessingAlgorithmToolStripMenuItem + // + this.motionProcessingAlgorithmToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.noneToolStripMenuItem2, + this.motionAreaHighlightingToolStripMenuItem, + this.motionBorderHighlightingToolStripMenuItem, + this.blobCountingToolStripMenuItem, + this.gridMotionAreaProcessingToolStripMenuItem}); + this.motionProcessingAlgorithmToolStripMenuItem.Name = "motionProcessingAlgorithmToolStripMenuItem"; + this.motionProcessingAlgorithmToolStripMenuItem.Size = new System.Drawing.Size(317, 30); + this.motionProcessingAlgorithmToolStripMenuItem.Text = "Motion Processing Algorithm"; + // + // noneToolStripMenuItem2 + // + this.noneToolStripMenuItem2.Name = "noneToolStripMenuItem2"; + this.noneToolStripMenuItem2.Size = new System.Drawing.Size(311, 30); + this.noneToolStripMenuItem2.Text = "None"; + this.noneToolStripMenuItem2.Click += new System.EventHandler(this.noneToolStripMenuItem2_Click); + // + // motionAreaHighlightingToolStripMenuItem + // + this.motionAreaHighlightingToolStripMenuItem.Name = "motionAreaHighlightingToolStripMenuItem"; + this.motionAreaHighlightingToolStripMenuItem.Size = new System.Drawing.Size(311, 30); + this.motionAreaHighlightingToolStripMenuItem.Text = "Motion Area Highlighting"; + this.motionAreaHighlightingToolStripMenuItem.Click += new System.EventHandler(this.motionAreaHighlightingToolStripMenuItem_Click); + // + // motionBorderHighlightingToolStripMenuItem + // + this.motionBorderHighlightingToolStripMenuItem.Name = "motionBorderHighlightingToolStripMenuItem"; + this.motionBorderHighlightingToolStripMenuItem.Size = new System.Drawing.Size(311, 30); + this.motionBorderHighlightingToolStripMenuItem.Text = "Motion Border Highlighting"; + this.motionBorderHighlightingToolStripMenuItem.Click += new System.EventHandler(this.motionBorderHighlightingToolStripMenuItem_Click); + // + // blobCountingToolStripMenuItem + // + this.blobCountingToolStripMenuItem.Name = "blobCountingToolStripMenuItem"; + this.blobCountingToolStripMenuItem.Size = new System.Drawing.Size(311, 30); + this.blobCountingToolStripMenuItem.Text = "Blob Counting Processing"; + this.blobCountingToolStripMenuItem.Click += new System.EventHandler(this.blobCountingToolStripMenuItem_Click); + // + // gridMotionAreaProcessingToolStripMenuItem + // + this.gridMotionAreaProcessingToolStripMenuItem.Name = "gridMotionAreaProcessingToolStripMenuItem"; + this.gridMotionAreaProcessingToolStripMenuItem.Size = new System.Drawing.Size(311, 30); + this.gridMotionAreaProcessingToolStripMenuItem.Text = "Grid Motion Area Processing"; + this.gridMotionAreaProcessingToolStripMenuItem.Click += new System.EventHandler(this.gridMotionAreaProcessingToolStripMenuItem_Click); + // + // toolStripMenuItem2 + // + this.toolStripMenuItem2.Name = "toolStripMenuItem2"; + this.toolStripMenuItem2.Size = new System.Drawing.Size(314, 6); + // + // defineMotionregionsToolStripMenuItem + // + this.defineMotionregionsToolStripMenuItem.Name = "defineMotionregionsToolStripMenuItem"; + this.defineMotionregionsToolStripMenuItem.Size = new System.Drawing.Size(317, 30); + this.defineMotionregionsToolStripMenuItem.Text = "Define motion ®ions"; + this.defineMotionregionsToolStripMenuItem.Click += new System.EventHandler(this.defineMotionregionsToolStripMenuItem_Click); + // + // toolStripMenuItem3 + // + this.toolStripMenuItem3.Name = "toolStripMenuItem3"; + this.toolStripMenuItem3.Size = new System.Drawing.Size(314, 6); + // + // showMotionHistoryToolStripMenuItem + // + this.showMotionHistoryToolStripMenuItem.Name = "showMotionHistoryToolStripMenuItem"; + this.showMotionHistoryToolStripMenuItem.Size = new System.Drawing.Size(317, 30); + this.showMotionHistoryToolStripMenuItem.Text = "Show motion history"; + this.showMotionHistoryToolStripMenuItem.Click += new System.EventHandler(this.showMotionHistoryToolStripMenuItem_Click); + // + // toolsToolStripMenuItem + // + this.toolsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.localVideoCaptureSettingsToolStripMenuItem, + this.crossbarVideoSettingsToolStripMenuItem}); + this.toolsToolStripMenuItem.Name = "toolsToolStripMenuItem"; + this.toolsToolStripMenuItem.Size = new System.Drawing.Size(67, 29); + this.toolsToolStripMenuItem.Text = "&Tools"; + this.toolsToolStripMenuItem.DropDownOpening += new System.EventHandler(this.toolsToolStripMenuItem_DropDownOpening); + // + // localVideoCaptureSettingsToolStripMenuItem + // + this.localVideoCaptureSettingsToolStripMenuItem.Name = "localVideoCaptureSettingsToolStripMenuItem"; + this.localVideoCaptureSettingsToolStripMenuItem.Size = new System.Drawing.Size(311, 30); + this.localVideoCaptureSettingsToolStripMenuItem.Text = "Local &Video Capture Settings"; + this.localVideoCaptureSettingsToolStripMenuItem.Click += new System.EventHandler(this.localVideoCaptureSettingsToolStripMenuItem_Click); + // + // crossbarVideoSettingsToolStripMenuItem + // + this.crossbarVideoSettingsToolStripMenuItem.Name = "crossbarVideoSettingsToolStripMenuItem"; + this.crossbarVideoSettingsToolStripMenuItem.Size = new System.Drawing.Size(311, 30); + this.crossbarVideoSettingsToolStripMenuItem.Text = "Crossbar Video Settings"; + this.crossbarVideoSettingsToolStripMenuItem.Click += new System.EventHandler(this.crossbarVideoSettingsToolStripMenuItem_Click); + // + // helpToolStripMenuItem + // + this.helpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.aboutToolStripMenuItem}); + this.helpToolStripMenuItem.Name = "helpToolStripMenuItem"; + this.helpToolStripMenuItem.Size = new System.Drawing.Size(61, 29); + this.helpToolStripMenuItem.Text = "&Help"; + // + // aboutToolStripMenuItem + // + this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem"; + this.aboutToolStripMenuItem.Size = new System.Drawing.Size(134, 30); + this.aboutToolStripMenuItem.Text = "&About"; + this.aboutToolStripMenuItem.Click += new System.EventHandler(this.aboutToolStripMenuItem_Click); + // + // openFileDialog + // + this.openFileDialog.Filter = "AVI files (*.avi)|*.avi|All files (*.*)|*.*"; + this.openFileDialog.Title = "Opem movie"; + // + // timer + // + this.timer.Interval = 1000; + this.timer.Tick += new System.EventHandler(this.timer_Tick); + // + // statusBar + // + this.statusBar.ImageScalingSize = new System.Drawing.Size(24, 24); + this.statusBar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.fpsLabel, + this.objectsCountLabel}); + this.statusBar.Location = new System.Drawing.Point(0, 526); + this.statusBar.Name = "statusBar"; + this.statusBar.Padding = new System.Windows.Forms.Padding(2, 0, 21, 0); + this.statusBar.Size = new System.Drawing.Size(648, 22); + this.statusBar.TabIndex = 3; + // + // fpsLabel + // + this.fpsLabel.AutoSize = false; + this.fpsLabel.BorderSides = ((System.Windows.Forms.ToolStripStatusLabelBorderSides)((((System.Windows.Forms.ToolStripStatusLabelBorderSides.Left | System.Windows.Forms.ToolStripStatusLabelBorderSides.Top) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Right) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Bottom))); + this.fpsLabel.BorderStyle = System.Windows.Forms.Border3DStyle.SunkenInner; + this.fpsLabel.Name = "fpsLabel"; + this.fpsLabel.Size = new System.Drawing.Size(150, 17); + this.fpsLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // objectsCountLabel + // + this.objectsCountLabel.BorderSides = ((System.Windows.Forms.ToolStripStatusLabelBorderSides)((((System.Windows.Forms.ToolStripStatusLabelBorderSides.Left | System.Windows.Forms.ToolStripStatusLabelBorderSides.Top) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Right) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Bottom))); + this.objectsCountLabel.BorderStyle = System.Windows.Forms.Border3DStyle.SunkenInner; + this.objectsCountLabel.Name = "objectsCountLabel"; + this.objectsCountLabel.Size = new System.Drawing.Size(475, 17); + this.objectsCountLabel.Spring = true; + this.objectsCountLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // panel1 + // + this.panel1.Controls.Add(this.videoSourcePlayer); + this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.panel1.Location = new System.Drawing.Point(0, 35); + this.panel1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(648, 491); + this.panel1.TabIndex = 4; + // + // videoSourcePlayer + // + this.videoSourcePlayer.AutoSizeControl = true; + this.videoSourcePlayer.BackColor = System.Drawing.SystemColors.ControlDarkDark; + this.videoSourcePlayer.ForeColor = System.Drawing.Color.White; + this.videoSourcePlayer.Location = new System.Drawing.Point(163, 124); + this.videoSourcePlayer.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.videoSourcePlayer.Name = "videoSourcePlayer"; + this.videoSourcePlayer.Size = new System.Drawing.Size(322, 242); + this.videoSourcePlayer.TabIndex = 0; + this.videoSourcePlayer.VideoSource = null; + this.videoSourcePlayer.NewFrame += new AForge.Controls.VideoSourcePlayer.NewFrameHandler(this.videoSourcePlayer_NewFrame); + // + // alarmTimer + // + this.alarmTimer.Interval = 200; + this.alarmTimer.Tick += new System.EventHandler(this.alarmTimer_Tick); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(648, 548); + this.Controls.Add(this.panel1); + this.Controls.Add(this.statusBar); + this.Controls.Add(this.menuMenu); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MainMenuStrip = this.menuMenu; + this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.Name = "MainForm"; + this.Text = "Motion Detector"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.menuMenu.ResumeLayout(false); + this.menuMenu.PerformLayout(); + this.statusBar.ResumeLayout(false); + this.statusBar.PerformLayout(); + this.panel1.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.MenuStrip menuMenu; + private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem openToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem motionToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem; + private System.Windows.Forms.OpenFileDialog openFileDialog; + private System.Windows.Forms.Timer timer; + private System.Windows.Forms.StatusStrip statusBar; + private System.Windows.Forms.ToolStripStatusLabel fpsLabel; + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.ToolStripMenuItem openJPEGURLToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem openMJPEGURLToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripMenuItem2; + private System.Windows.Forms.ToolStripMenuItem localVideoCaptureDeviceToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem openVideoFileusingDirectShowToolStripMenuItem; + private System.Windows.Forms.ToolStripStatusLabel objectsCountLabel; + private System.Windows.Forms.ToolStripMenuItem defineMotionregionsToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem toolsToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem localVideoCaptureSettingsToolStripMenuItem; + private AForge.Controls.VideoSourcePlayer videoSourcePlayer; + private System.Windows.Forms.ToolStripMenuItem motionDetectionAlgorithmToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem noneToolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem twoFramesDifferenceToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem simpleBackgroundModelingToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem motionProcessingAlgorithmToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem noneToolStripMenuItem2; + private System.Windows.Forms.ToolStripMenuItem motionBorderHighlightingToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem blobCountingToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem gridMotionAreaProcessingToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem motionAreaHighlightingToolStripMenuItem; + private System.Windows.Forms.Timer alarmTimer; + private System.Windows.Forms.ToolStripSeparator toolStripMenuItem3; + private System.Windows.Forms.ToolStripMenuItem showMotionHistoryToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem crossbarVideoSettingsToolStripMenuItem; + } +} + diff --git a/Samples/Vision/Motion detection/MainForm.cs b/Samples/Vision/Motion detection/MainForm.cs new file mode 100644 index 0000000000..82a999c52 --- /dev/null +++ b/Samples/Vision/Motion detection/MainForm.cs @@ -0,0 +1,552 @@ +// Motion Detection sample application +// AForge.NET Framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2012 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Drawing.Imaging; +using System.Text; +using System.Windows.Forms; +using System.Threading; + +using AForge; +using AForge.Imaging; +using AForge.Video; +using AForge.Video.VFW; +using AForge.Video.DirectShow; +using AForge.Vision.Motion; + +namespace SampleApp +{ + public partial class MainForm : Form + { + // opened video source + private IVideoSource videoSource = null; + // motion detector + MotionDetector detector = new MotionDetector( + new TwoFramesDifferenceDetector( ), + new MotionAreaHighlighting( ) ); + // motion detection and processing algorithm + private int motionDetectionType = 1; + private int motionProcessingType = 1; + + // statistics length + private const int statLength = 15; + // current statistics index + private int statIndex = 0; + // ready statistics values + private int statReady = 0; + // statistics array + private int[] statCount = new int[statLength]; + + // counter used for flashing + private int flash = 0; + private float motionAlarmLevel = 0.015f; + + private List motionHistory = new List( ); + private int detectedObjectsCount = -1; + + // Constructor + public MainForm( ) + { + InitializeComponent( ); + Application.Idle += new EventHandler( Application_Idle ); + } + + // Application's main form is closing + private void MainForm_FormClosing( object sender, FormClosingEventArgs e ) + { + CloseVideoSource( ); + } + + // "Exit" menu item clicked + private void exitToolStripMenuItem_Click( object sender, EventArgs e ) + { + this.Close( ); + } + + // "About" menu item clicked + private void aboutToolStripMenuItem_Click( object sender, EventArgs e ) + { + AboutForm form = new AboutForm( ); + form.ShowDialog( ); + } + + // "Open" menu item clieck - open AVI file + private void openToolStripMenuItem_Click( object sender, EventArgs e ) + { + if ( openFileDialog.ShowDialog( ) == DialogResult.OK ) + { + // create video source + AVIFileVideoSource fileSource = new AVIFileVideoSource( openFileDialog.FileName ); + + OpenVideoSource( fileSource ); + } + } + + // Open JPEG URL + private void openJPEGURLToolStripMenuItem_Click( object sender, EventArgs e ) + { + URLForm form = new URLForm( ); + + form.Description = "Enter URL of an updating JPEG from a web camera:"; + form.URLs = new string[] + { + "http://195.243.185.195/axis-cgi/jpg/image.cgi?camera=1" + }; + + if ( form.ShowDialog( this ) == DialogResult.OK ) + { + // create video source + JPEGStream jpegSource = new JPEGStream( form.URL ); + + // open it + OpenVideoSource( jpegSource ); + } + } + + // Open MJPEG URL + private void openMJPEGURLToolStripMenuItem_Click( object sender, EventArgs e ) + { + URLForm form = new URLForm( ); + + form.Description = "Enter URL of an MJPEG video stream:"; + form.URLs = new string[] + { + "http://195.243.185.195/axis-cgi/mjpg/video.cgi?camera=3", + "http://195.243.185.195/axis-cgi/mjpg/video.cgi?camera=4", + }; + + if ( form.ShowDialog( this ) == DialogResult.OK ) + { + // create video source + MJPEGStream mjpegSource = new MJPEGStream( form.URL ); + + // open it + OpenVideoSource( mjpegSource ); + } + } + + // Open local video capture device + private void localVideoCaptureDeviceToolStripMenuItem_Click( object sender, EventArgs e ) + { + VideoCaptureDeviceForm form = new VideoCaptureDeviceForm( ); + + if ( form.ShowDialog( this ) == DialogResult.OK ) + { + // create video source + VideoCaptureDevice videoSource = new VideoCaptureDevice( form.VideoDevice ); + + // open it + OpenVideoSource( videoSource ); + } + } + + // Open video file using DirectShow + private void openVideoFileusingDirectShowToolStripMenuItem_Click( object sender, EventArgs e ) + { + if ( openFileDialog.ShowDialog( ) == DialogResult.OK ) + { + // create video source + FileVideoSource fileSource = new FileVideoSource( openFileDialog.FileName ); + + // open it + OpenVideoSource( fileSource ); + } + } + + // Open video source + private void OpenVideoSource( IVideoSource source ) + { + // set busy cursor + this.Cursor = Cursors.WaitCursor; + + // close previous video source + CloseVideoSource( ); + + // start new video source + videoSourcePlayer.VideoSource = new AsyncVideoSource( source ); + videoSourcePlayer.Start( ); + + // reset statistics + statIndex = statReady = 0; + + // start timers + timer.Start( ); + alarmTimer.Start( ); + + videoSource = source; + + this.Cursor = Cursors.Default; + } + + // Close current video source + private void CloseVideoSource( ) + { + // set busy cursor + this.Cursor = Cursors.WaitCursor; + + // stop current video source + videoSourcePlayer.SignalToStop( ); + + // wait 2 seconds until camera stops + for ( int i = 0; ( i < 50 ) && ( videoSourcePlayer.IsRunning ); i++ ) + { + Thread.Sleep( 100 ); + } + if ( videoSourcePlayer.IsRunning ) + videoSourcePlayer.Stop( ); + + // stop timers + timer.Stop( ); + alarmTimer.Stop( ); + + motionHistory.Clear( ); + + // reset motion detector + if ( detector != null ) + detector.Reset( ); + + videoSourcePlayer.BorderColor = Color.Black; + this.Cursor = Cursors.Default; + } + + // New frame received by the player + private void videoSourcePlayer_NewFrame( object sender, ref Bitmap image ) + { + lock ( this ) + { + if ( detector != null ) + { + float motionLevel = detector.ProcessFrame( image ); + + if ( motionLevel > motionAlarmLevel ) + { + // flash for 2 seconds + flash = (int) ( 2 * ( 1000 / alarmTimer.Interval ) ); + } + + // check objects' count + if ( detector.MotionProcessingAlgorithm is BlobCountingObjectsProcessing ) + { + BlobCountingObjectsProcessing countingDetector = (BlobCountingObjectsProcessing) detector.MotionProcessingAlgorithm; + detectedObjectsCount = countingDetector.ObjectsCount; + } + else + { + detectedObjectsCount = -1; + } + + // accumulate history + motionHistory.Add( motionLevel ); + if ( motionHistory.Count > 300 ) + { + motionHistory.RemoveAt( 0 ); + } + + if ( showMotionHistoryToolStripMenuItem.Checked ) + DrawMotionHistory( image ); + } + } + } + + // Update some UI elements + private void Application_Idle( object sender, EventArgs e ) + { + objectsCountLabel.Text = ( detectedObjectsCount < 0 ) ? string.Empty : "Objects: " + detectedObjectsCount; + } + + // Draw motion history + private void DrawMotionHistory( Bitmap image ) + { + Color greenColor = Color.FromArgb( 128, 0, 255, 0); + Color yellowColor = Color.FromArgb( 128, 255, 255, 0 ); + Color redColor = Color.FromArgb( 128, 255, 0, 0 ); + + BitmapData bitmapData = image.LockBits( new Rectangle( 0, 0, image.Width, image.Height ), + ImageLockMode.ReadWrite, image.PixelFormat ); + + int t1 = (int) ( motionAlarmLevel * 500 ); + int t2 = (int) ( 0.075 * 500 ); + + for ( int i = 1, n = motionHistory.Count; i <= n; i++ ) + { + int motionBarLength = (int) ( motionHistory[n - i] * 500 ); + + if ( motionBarLength == 0 ) + continue; + + if ( motionBarLength > 50 ) + motionBarLength = 50; + + Drawing.Line( bitmapData, + new IntPoint( image.Width - i, image.Height - 1 ), + new IntPoint( image.Width - i, image.Height - 1 - motionBarLength ), + greenColor ); + + if ( motionBarLength > t1 ) + { + Drawing.Line( bitmapData, + new IntPoint( image.Width - i, image.Height - 1 - t1 ), + new IntPoint( image.Width - i, image.Height - 1 - motionBarLength ), + yellowColor ); + } + + if ( motionBarLength > t2 ) + { + Drawing.Line( bitmapData, + new IntPoint( image.Width - i, image.Height - 1 - t2 ), + new IntPoint( image.Width - i, image.Height - 1 - motionBarLength ), + redColor ); + } + } + + image.UnlockBits( bitmapData ); + } + + // On timer event - gather statistics + private void timer_Tick( object sender, EventArgs e ) + { + IVideoSource videoSource = videoSourcePlayer.VideoSource; + + if ( videoSource != null ) + { + // get number of frames for the last second + statCount[statIndex] = videoSource.FramesReceived; + + // increment indexes + if ( ++statIndex >= statLength ) + statIndex = 0; + if ( statReady < statLength ) + statReady++; + + float fps = 0; + + // calculate average value + for ( int i = 0; i < statReady; i++ ) + { + fps += statCount[i]; + } + fps /= statReady; + + statCount[statIndex] = 0; + + fpsLabel.Text = fps.ToString( "F2" ) + " fps"; + } + } + + // Turn off motion detection + private void noneToolStripMenuItem1_Click( object sender, EventArgs e ) + { + motionDetectionType = 0; + SetMotionDetectionAlgorithm( null ); + } + + // Set Two Frames Difference motion detection algorithm + private void twoFramesDifferenceToolStripMenuItem_Click( object sender, EventArgs e ) + { + motionDetectionType = 1; + SetMotionDetectionAlgorithm( new TwoFramesDifferenceDetector( ) ); + } + + // Set Simple Background Modeling motion detection algorithm + private void simpleBackgroundModelingToolStripMenuItem_Click( object sender, EventArgs e ) + { + motionDetectionType = 2; + SetMotionDetectionAlgorithm( new SimpleBackgroundModelingDetector( true, true ) ); + } + + // Turn off motion processing + private void noneToolStripMenuItem2_Click( object sender, EventArgs e ) + { + motionProcessingType = 0; + SetMotionProcessingAlgorithm( null ); + } + + // Set motion area highlighting + private void motionAreaHighlightingToolStripMenuItem_Click( object sender, EventArgs e ) + { + motionProcessingType = 1; + SetMotionProcessingAlgorithm( new MotionAreaHighlighting( ) ); + } + + // Set motion borders highlighting + private void motionBorderHighlightingToolStripMenuItem_Click( object sender, EventArgs e ) + { + motionProcessingType = 2; + SetMotionProcessingAlgorithm( new MotionBorderHighlighting( ) ); + } + + // Set objects' counter + private void blobCountingToolStripMenuItem_Click( object sender, EventArgs e ) + { + motionProcessingType = 3; + SetMotionProcessingAlgorithm( new BlobCountingObjectsProcessing( ) ); + } + + // Set grid motion processing + private void gridMotionAreaProcessingToolStripMenuItem_Click( object sender, EventArgs e ) + { + motionProcessingType = 4; + SetMotionProcessingAlgorithm( new GridMotionAreaProcessing( 32, 32 ) ); + } + + // Set new motion detection algorithm + private void SetMotionDetectionAlgorithm( IMotionDetector detectionAlgorithm ) + { + lock ( this ) + { + detector.MotionDetectionAlgorithm = detectionAlgorithm; + motionHistory.Clear( ); + + if ( detectionAlgorithm is TwoFramesDifferenceDetector ) + { + if ( + ( detector.MotionProcessingAlgorithm is MotionBorderHighlighting ) || + ( detector.MotionProcessingAlgorithm is BlobCountingObjectsProcessing ) ) + { + motionProcessingType = 1; + SetMotionProcessingAlgorithm( new MotionAreaHighlighting( ) ); + } + } + } + } + + // Set new motion processing algorithm + private void SetMotionProcessingAlgorithm( IMotionProcessing processingAlgorithm ) + { + lock ( this ) + { + detector.MotionProcessingAlgorithm = processingAlgorithm; + } + } + + // Motion menu is opening + private void motionToolStripMenuItem_DropDownOpening( object sender, EventArgs e ) + { + ToolStripMenuItem[] motionDetectionItems = new ToolStripMenuItem[] + { + noneToolStripMenuItem1, twoFramesDifferenceToolStripMenuItem, + simpleBackgroundModelingToolStripMenuItem + }; + ToolStripMenuItem[] motionProcessingItems = new ToolStripMenuItem[] + { + noneToolStripMenuItem2, motionAreaHighlightingToolStripMenuItem, + motionBorderHighlightingToolStripMenuItem, blobCountingToolStripMenuItem, + gridMotionAreaProcessingToolStripMenuItem + }; + + for ( int i = 0; i < motionDetectionItems.Length; i++ ) + { + motionDetectionItems[i].Checked = ( i == motionDetectionType ); + } + for ( int i = 0; i < motionProcessingItems.Length; i++ ) + { + motionProcessingItems[i].Checked = ( i == motionProcessingType ); + } + + // enable/disable some motion processing algorithm depending on detection algorithm + bool enabled = ( motionDetectionType != 1 ); + motionBorderHighlightingToolStripMenuItem.Enabled = enabled; + blobCountingToolStripMenuItem.Enabled = enabled; + } + + // On "Define motion regions" menu item selected + private void defineMotionregionsToolStripMenuItem_Click( object sender, EventArgs e ) + { + if ( videoSourcePlayer.VideoSource != null ) + { + Bitmap currentVideoFrame = videoSourcePlayer.GetCurrentVideoFrame( ); + + if ( currentVideoFrame != null ) + { + MotionRegionsForm form = new MotionRegionsForm( ); + form.VideoFrame = currentVideoFrame; + form.MotionRectangles = detector.MotionZones; + + // show the dialog + if ( form.ShowDialog( this ) == DialogResult.OK ) + { + Rectangle[] rects = form.MotionRectangles; + + if ( rects.Length == 0 ) + rects = null; + + detector.MotionZones = rects; + } + + return; + } + } + + MessageBox.Show( "It is required to start video source and receive at least first video frame before setting motion zones.", + "Message", MessageBoxButtons.OK, MessageBoxIcon.Information ); + } + + // On opening of Tools menu + private void toolsToolStripMenuItem_DropDownOpening( object sender, EventArgs e ) + { + localVideoCaptureSettingsToolStripMenuItem.Enabled = + ( ( videoSource != null ) && ( videoSource is VideoCaptureDevice ) ); + crossbarVideoSettingsToolStripMenuItem.Enabled = + ( ( videoSource != null ) && ( videoSource is VideoCaptureDevice ) && ( videoSource.IsRunning ) ); + } + + // Display properties of local capture device + private void localVideoCaptureSettingsToolStripMenuItem_Click( object sender, EventArgs e ) + { + if ( ( videoSource != null ) && ( videoSource is VideoCaptureDevice ) ) + { + try + { + ( (VideoCaptureDevice) videoSource ).DisplayPropertyPage( this.Handle ); + } + catch ( NotSupportedException ex ) + { + MessageBox.Show( ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); + } + } + } + + // Display properties of crossbar filter + private void crossbarVideoSettingsToolStripMenuItem_Click( object sender, EventArgs e ) + { + if ( ( videoSource != null ) && ( videoSource is VideoCaptureDevice ) && ( videoSource.IsRunning ) ) + { + Console.WriteLine( "Current input: " + ( (VideoCaptureDevice) videoSource ).CrossbarVideoInput ); + + try + { + ( (VideoCaptureDevice) videoSource ).DisplayCrossbarPropertyPage( this.Handle ); + } + catch ( NotSupportedException ex ) + { + MessageBox.Show( ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); + } + } + } + + // Timer used for flashing in the case if motion is detected + private void alarmTimer_Tick( object sender, EventArgs e ) + { + if ( flash != 0 ) + { + videoSourcePlayer.BorderColor = ( flash % 2 == 1 ) ? Color.Black : Color.Red; + flash--; + } + } + + // Change status of menu item when it is clicked + private void showMotionHistoryToolStripMenuItem_Click( object sender, EventArgs e ) + { + showMotionHistoryToolStripMenuItem.Checked = !showMotionHistoryToolStripMenuItem.Checked; + } + } +} \ No newline at end of file diff --git a/Samples/Vision/Motion detection/MainForm.resx b/Samples/Vision/Motion detection/MainForm.resx new file mode 100644 index 0000000000..ba413acf9 --- /dev/null +++ b/Samples/Vision/Motion detection/MainForm.resx @@ -0,0 +1,585 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 124, 17 + + + 248, 17 + + + 325, 17 + + + 426, 17 + + + + + AAABAAgAEBAAAAEACABoBQAAhgAAABAQAAABACAAaAQAAO4FAAAYGAAAAQAIAMgGAABWCgAAGBgAAAEA + IACICQAAHhEAACAgAAABAAgAqAgAAKYaAAAgIAAAAQAgAKgQAABOIwAAMDAAAAEACACoDgAA9jMAADAw + AAABACAAqCUAAJ5CAAAoAAAAEAAAACAAAAABAAgAAAAAAEABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP// + /wAz1G4A2mlpAIclAAC3uLgAZmprACuKMAA+MDAA/JeXAI6QkQBg6ZQA7svLAGunZgBKGAAAkdKfAGs4 + IQAhGBQATFBSAK9lZQB+UVEA4urqAGHHfQCLeG8APqNIACi8VQDbtrYA2ZmZAM3T0wDsg4MArJmZAGck + AwDFVlYASsFrAFArGQDFd3cAZVlSAJa6lwBUP0EATemEAK3ApACCgoIAqampAD+OQQDFxcUAdnZ2AJmg + oAAtoT4A3NzcAHWidgCYhYUA9PT0AG20cwA5wVoAg82VADI5OQDqm5sA1nZ2AG5jXgCEXFwAyWFhAHYi + AADlvb0ASEdIAFxPTwDhyMgA5Xt7APaJiQC5a2sAl5eXAJJ9fQBFmUgANapEAEbKcgCDd3cA7O/vAN2S + kgDqxMQAiYqKAK+vrwA4izoAur+/AMfMzADccHAA1tbWAHx8fACyp6cA5OTkAPyRkQBP7YsA08/PANNm + ZgBOS0sAaFxYAGdhXgDp6uoAbyIAAKCgoABWUEwASE1NAC6PMwD3+PgAgoaGAC6GMgA10GsAcnN0AN/f + 3wDCwsIAsrKyAKysrACmpqYAnJ2dAI2NjQCId3cA+JOTAOjt7QDj5+cAyMnJANPU1AB4eHkA7sTEADCM + MwCdoKIA0dHRAH5+fgCZmZkAlZWVACe/VgDp7+8A78nJAMbHxwCEhIUAioyMAO7u7gDKysoA25OTALm3 + twB5enoALIgwAC2KMQBBjkIA3d3dAKurqwCdnp4AmpiYAJaWlgCMjo4ASExMAKytrQBydHUAd3h4AKan + pwDo6uoAfX5+AIqKigAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAH18KYZ5izEAAAAAAAAAYZpuhnWYZAs1RwAAAAAAAH5qMI1SQQdJAidI + AAAAAABhhVSCVj6KIX9oWS8AAACRiXpFjx5NZzYWGRglAAAAlRcQEpIygVAPNA0+kAAAVQpgBCRpLgwr + jCh4IEoAAJY6Hz1dg1FMiAVmkxNxAAB3YiIOBk8cOCNcN2NARgAAVS0RXoR2dQlYQ0Q7FCYAAABOmZRr + MHOHch1CUwMIAAAAACwzVwFldBobOVs8PwAAAACObCx7al9LgBVadnAAAAAAAAAAAGFhKmxtl28AAAAA + AAAAAAAAAAAAAAAAAAD//wAA+A8AAOAHAADgAwAA4AEAAMABAADAAQAAgAEAAIABAACAAQAAgAEAAMAB + AADgAQAA4AEAAP4DAAD//wAAKAAAABAAAAAgAAAAAQAgAAAAAABABAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAcnJyB25ublNra2uygoKC98/Pz+QvjTL6I4ko6yuTLm4AAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAhoaGWYmJie2mpqb/ysrK/8jJyf/o6ur/Lo8z/2DplP86w1v+KZUtyACX + AAwAAAAAAAAAAAAAAAAAAAAAAAAAAI+Pj8bf39//3Nzc/93d3f/HzMz/4cjI/yuKMP9GynL/M9Ru/03p + hP80rEP6AIoATAAAAAAAAAAAAAAAAAAAAACfn5/R7u7u/9bW1v/Gx8f/sqen/+W9vf8siDD/SsFr/ye/ + Vv810Gv/T+2L/yyiPfwAAAAAAAAAAAAAAAB6enp0ent7+52gov+Xl5f/nZ6e/6yZmf/qxMT/LoYy/4PN + lf9hx33/KLxV/z6jSP+VvZbnAAAAAAAAAAB2dnZMc3V2/ot4b/9rOCH/TFBS/4yOjv+YhYX/78nJ/ziL + Ov+R0p//bbRz/2unZv/lvb3/lpOTwgAAAAAAAAAAa2trvI6Qkf9vIgD/hyUA/2VZUv9yc3T/maCg/+7L + y/8/jkH/QY5C/63ApP/uxMT/xVZW/3pra8sAAAAAAAAAAHV2dvFuY17/ZyQD/3YiAP9oXFj/hISF/7q/ + v//dkpL/ube3/7e4uP+Chob/SExM/69lZf+BbGzRAAAAAAAAAAB4eHn1VlBM/1ArGf9KGAD/Zmpr/6+v + r//N09P/6pub/8V3d/9OS0v/Mjk5/0hNTf9cT0//jnR00QAAAAAAAAAAbW5uwXZ2dv8hGBT/Z2Fe/4qM + jP/T1NT/yMnJ//yXl//8kZH/9omJ/7lra/+EXFz/flFR/0gxM+AAAAAAAAAAAIaGhkWKi4v8fX5+/6yt + rf/CwsL/3Nzc/+jt7f/bk5P/+JOT/+yDg//le3v/3HBw/9ppaf86KyvyAAAAAAAAAAAAAAAAqampScfH + x/v09PT/5OTk///////3+Pj/4+fn/9u2tv/ZmZn/1nZ2/9NmZv/JYWH/RURF9gAAAAAAAAAAAAAAAAAA + AACnp6dvs7Oz78XFxf/R0dH/39/f/+nq6v/s7+//6e/v/+Lq6v/Tz8//09TU/4SFhcYAAAAAAAAAAAAA + AAAAAAAAAAAAAP///wGRkZEhlpaWTpKSknuampqoqqqq1bS0tPeurq7rpaamzJSVlaWOjo40AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAD//wAA+A8AAOAHAADgAwAA4AEAAMABAADAAQAAgAEAAIABAACAAQAAgAEAAMABAADgAQAA4AEAAP4D + AAD//wAAKAAAABgAAAAwAAAAAQAIAAAAAACgAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AOdNuAOJ1 + dQCLLQAAC40LAGRkZACf0qkALDc3AO28vACfiYkAPpM+AJtHRwBrp2sAPhIAAMzp0gBt0o8A/ZaWAGw9 + JwC1Z2cAvLGxACh6JABMTEwA0ZeXACq0TwBmGQAAen1/ABSlJwCTrosAdVVFAFmLWQDp6uoAyMjIADMk + HQBQt2cAo6OjAFPUfwBcLBUAebd+AOSmpgCP57MAisyZAFVANgDDV1cA74iIALB5eQDUhYUALJMsANJo + aAAYAAAAY7t2AC/GXwA/MisA3NzcAJVWVgA/QEAAHZQcALDGsADPu60AioqKAJSYmABRjkYAPrZdAHFx + cQAOeAwAWVlZAB+sNgBbnlsAReF+ABuBFwB5JwAAzHp6AHdoYABHyW8A/aOjAGJKPgDes7MA1sDAAK1c + XAC+vr4AkKp7AHvJjwCurq4AJ6ZCAPf39wDR0dEAg3lzAHQ4GwCMR0cAbsF/AEgbBQAUlygAWDgrAHSv + dAB215gAZiUGAOaAgAB2UlIAzq6uAKJVVQAliCwAQ75mAPaPjwA3jDYAp39/ABp1GQBmXVsA6J6eAHDJ + iAA0zmgA58PDAGdsbgDGtbUALH4tALK1tQBOREQA2HFxADc5OQCkkJAAKbxWAFBTUwCCg4MA5OTkAEg+ + PgCenp4Adnd3AK1ycgCRkpIAGYsZANaMjADampoAJY8lAF0dAAAxMTEAQdx5AOW3twBdYGIAH4QfANuo + qAC+aWkA8PHxAHzCiQDBxcUATsVrAJhQUADX19cAurq6AKioqAB0IAAA/p2dAN1+fgBpzokAR0dHADC5 + VgDp7+8A+JqaANeUlAA1yWAAP9V0AMrQ0AAjeR4A9omJAN+urgA/RUUAx62tAJyiogCuZmYAzHR0AJRH + RwD6+voA4Xp6ANRtbQBJu2cANjUzAFS5bADNzMwAF4QTAM9lZQBvVUcA8Y+PAJtVVQCXnJ4Aa8qFANnf + 3wAdehoArrKyAEPDaQBlaGkA6oKCAFFWVwCnrKwAq3t7AJSqhwDui4sAgICAAOzs7ADm5uYA39/fAOh9 + fQBWVlYAmZmZAJOUlAB0dHQAjo6OAHp6egCEiIgAfSYAAGpsbABhGgAAQ7pjAHNlYAAtvlgA3nd3AOLm + 5gBxOh4AiouMANLU1ADPzs4AL8JdAMRaWgAwNjYA4rKyAExSUgClpqYALjMzAB6QHAAzODgA6bm5AMbG + xgAwy2UA1WpqANB5eQBLTk8AhYWFAIgrAAA+Pj4A4eHhANnZ2QAdfxkA+IuLAD3XcgC8vLwA2nNzAFRV + VQCwsLAA0GpqAKqqqgCfn58AnJubAG9wcACWlpYA1dXVAMvKygAyyGEAhoeIABiBGAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB5P33IXTgLAAAAAAAAAAAAAAAAAAB/ff6TII7t4SiPBQ0AAAAA + AAAAAAAAAHmTIFVV2U/VgF4knhsvAAAAAAAAAAAAyZKRkZE1kY5NsBBJbYadBUMAAAAAAAAAya/sxe37 + 2HaKRZe6M23wREKDAAAAAAAAyZHE++RPjmii7rZl0zNtAoYC/wAAAAAAyjXk/PT2ub/duGysmXfa5QL9 + iQAAAADP+X2IN8npvi2HuFGuPhh32ltnOQAAAD/M+FcSb+uTzX7joCkyItFTQFCkIwAAycq11s6USHU7 + ycsJFQeNWWQ9Opw2+gAAzP5WGQTqHejMk6VuFQ8maRyHltu0yQAAP9dLX0bOsr15krlMwHEeUs+9c6dj + fwAAP3kqJYTQ0vN8r46CJ9/+x4VBdXgTyQAA+Xk0XA5aGvOv2Z9roUd7veAWmKOmPAAAfX+tITFqfdeR + r6+bZmbvR2E33giQuwAAycJ56wbXO5Eg7RSVEWYsvMYDi04M4gAAAOn6Bun0kZKRqbcuSmYsYKryqzCo + 3AAAAAD3TyAgI9kBAXrZgbPBYNR09bFY4AAAAAAAfAEBAQGpVFSMmtliF+fmsSsKdQAAAAAAAN/ZNR/D + H8R6esMf1bcgcPxyeQAAAAAAAACT3yOTUvGvNR8fw8PDkeTIAAAAAAAAAAAAAAAAAAAjfPgjI/j6+HwA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8A/4D/APwAPwD4AB8A8AAHAPAAAwDwAAEA8AABAOAA + AQDAAAEAgAABAIAAAQCAAAEAgAABAIAAAQCAAAEAgAABAMAAAQDgAAEA8AABAPgAAQD8AAMA//AHAP// + /wAoAAAAGAAAADAAAAABACAAAAAAAGAJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFZWVgNwcHBGbW1tpnBw + cPZ3d3f+lpaW12mxadMTkxLtAIUApACaABYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAACEhIQle3t7hXNzc+KHh4f/qamp/8nJyf/ExMT/2tra/x6QHP+P57P/TsVr/wCM + AO0AnQBiAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIqKijCDg4P5p6en/8nJ + yf/R0dH/0dHR/83Nzf++vr7/4+Xl/xmLGf9215j/U9R//z/VdP8UpSf/AIwAvgCnACUAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAH9/f4O5ubn/2NjY/9bW1v/Y2Nj/29vb/9jY2P++xMT/1sDA/xeE + E/9t0o//R8lv/zTOaP9A23j/Nclg/wmNCfwAjgB6AHYABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIOD + g5nMzMz/4eHh/9/f3//Z2dn/1dXV/9LU1P+kkJD/26io/xuBF/9pzon/Q8Np/y/GX/80z2n/Pddy/0Xh + fv8frDb/HY8d7gCMADAAAAAAAAAAAAAAAAAAAAAAAAAAAIODg5rW1tb/5ubm/9XV1f/Gxsb/v7+//8HE + xP+nf3//366u/x1/Gf9ryoX/Q75m/y2+WP8vxV//M81n/znSbf9B3Hn/OtNt/wB7ANwAAAAAAAAAAAAA + AAAAAAAAi4uLLGpqatfc3Nz/xsbG/8rKyv+wsLD/qqqq/66ysv+re3v/4rKy/xx6Gf9wyYj/Sbtn/zC5 + Vv8pvFb/LsJc/zDLZf841G//Mshh/xiDGPEAAAAAAAAAAAAAAACIiIg2aWlp8W9wcP90d3j/XWBi/z9A + QP+VlZX/hYWF/6esrP+weXn/5re3/x55G/97yY//VLls/z62Xf8qtE//KLtV/y/CXv8Ulyj/N4w2/7LQ + srkAAAAAAAAAAHx8fAtra2vgenp7/52bm/90OBv/bD0n/2dsbv8+Pj7/qamp/4SIiP+tcnL/6bm5/yN5 + Hv+KzJn/Y7t2/1C3Z/9DumP/J6ZC/w54DP+Qqnv/x62t/5WXl2IAAAAAAAAAAHBwcG9zc3T/l5ye/3E6 + Hv98JQD/dCAA/3doYP83ODn/iYmJ/5OUlP+Ojo7/7by8/yh6I/+f0qn/fMKJ/27Bf/8liCz/UY5G/8+7 + rf/XlJT/lVZW/3J2dm0AAAAAAAAAAGpqasOGh4j/g3lz/2YZAP+LLQD/iCsA/3VVRf9LTk//enp6/6mp + qf+coqL/58PD/yh6Jf/M6dL/ebd+/xp1Gf+Trov/47e3/91+fv/EWlr/m1VV/3d7e30AAAAAAAAAAG9v + b/OKjI3/Yko+/2YlBv95JwD/fiYA/29VR/9SVVb/goKC/7q6uv+usrL/3rOz/5Sqh/8sfi3/WYtZ/66u + rv9pbGz/UFdX/05ERP/MdHT/olVV/3d8fIIAAAAAAAAAAHBwcP+ChIX/VUA2/1wsFf9dHQD/YRoA/3Nl + YP9TVVX/nZ2d/8zMzP/Cxsb/2pqa/+Smpv+kp6f/hoiI/1ZWVv8xMTH/WVlZ/zc5Of9QU1P/tWdn/3h9 + fYIAAAAAAAAAAHBwcPuCg4T/PzIr/1g4K/8+EgD/SBsF/3p9f/9UVFT/zMzM/83Nzf/K0ND/6J6e//aJ + if/Me3v/SD4+/1FXV/8uMjL/TExM/0dHR/8/RUX/rmZm/36EhIIAAAAAAAAAAGxsbNORkZH/NjUz/zMk + Hf8YAAD/Zl1b/3Z3d/+Li4v/19fX/8zMzP/Ny8v/+Jqa//eQkP/3jo7/+IuL/8x5ef92UlL/PkBA/0xS + Uv8sNzf/mFBQ/zo/QaAAAAAAAAAAAHR0dHOAgID/gYKC/z49Pv9lZWT/iouM/4qKiv/W1tb/ycnJ/9jZ + 2f+8sbH//p2d//2Wlv/2j4//74mJ/+qCgv/ofX3/4nV1/75paf+tXFz/m0dH/yQqKuEAAAAAAAAAAJWV + lQ1/f3/flpaW/2NjY/+Ghob/r6+v/9fX1/+6urr/1tbW//r6+v/Z3t7/1IWF//2jo//0jo7/7oeH/+aA + gP/henr/2nNz/9Rtbf/SaGj/lEdH/yYsLOoAAAAAAAAAAAAAAACsrKwnnp6e1L29vf/Jycn/yMjI/6Sk + pP/Nzc3////////////j4+P/z83N/9aMjP/xj4//7ouL/+WAgP/ed3f/2HFx/9Bqav/PZWX/jEdH/ygt + LfEAAAAAAAAAAAAAAAAAAAAAjIyMBJ2dneD/////////////////////+vr6//b29v/39/f/8PHx/+nv + 7//Rzs7/zq6u/9GXl//QeXn/1Wpq/89kZP/DV1f/n4mJ/zAyMu4AAAAAAAAAAAAAAAAAAAAAAAAAAKqq + qkinp6fyzs7O/93d3f/q6ur/7e3t/+np6f/m5ub/5OTk/+Pj4//r6+v/6Ovr/+Hm5v/Y39//x8fH/8a1 + tf/Lysr/srW1/15eXoUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACjo6MVn5+fWJ+fn4afn5+0qKio4q+v + r/28vLz/zMzM/93d3f/p6en/6urq/+zs7P/t7e3/6+zs/9fY2P/Fxsb/mpqa+Jqamj8AAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKWlpRKXl5c/lZWVbZWVlZuXl5fJpKSk7qWl + pfSZmZnckJCQvI+Pj5yNjY12l5eXIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA////AP+A/wD8AD8A+AAfAPAABwDwAAMA8AABAPAAAQDgAAEAwAABAIAAAQCAAAEAgAABAIAA + AQCAAAEAgAABAIAAAQDAAAEA4AABAPAAAQD4AAEA/AADAP/wBwD///8AKAAAACAAAABAAAAAAQAIAAAA + AACABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AOdNtAK4+PgD8mZkAGHwYAJLlswCDhIUAZRoAAExN + TQDS09MA1GxsALirkwBKnEoAnDQAAHDIiAAlHxwAcj4jAIRgYAAhtTwA1rOzAG2fbQDDhYUArGdnADuD + LgA5DAAANTY2AOjp6QCam5wAUrdqAOiCggBhY2MAb1BCAI+ccQC0tLQAI5onAFcyMgC9VFQAK79ZAF+H + XgCAKgAAlM6gAFsrFgBP2YEA2J+fAHJzdACheXkAwcXFAHrYmgD+q6sAplNTABkBAAA7KSEAnYqKACp1 + JQCm1K0AYrp1AFuGSACmp6cAxJiYAMSqqgBOGQAAk2pqABWRGgAWExIAhMOOAOu1tQBam1oAzefSANJ7 + ewBAs1wAiVFRAGZZUQBCQkIA6qSkAPSMjADd3d0AS8ZwAI2NjQAxlTEAyV1dAHdrZgD19fUAt6CgADfH + ZABZWVkAKLVPAE4iDQBs2pMAcLx+ALZLSwDNj48A6Hd3AFI8PABb0IEAu2FhAG4gAABoNR0AKTExAF04 + JgCKbmAAHoceAEPefAAepi0A0q2lAKxcXADag4MAe3x8AGprawByT08AMrRVAMrMzAD3o6MAn2ZmAGOd + YwDadHQAdKd0AD8xKgCYk5EA4a+vAC6JMQBZPjEAu7u7AJEvAABRNSgAVKxjAB6TLwAidx4AymVlABOJ + GQBRREQAlnt7AEjkgQDNoKAAE5wfAI6WlgCgoKAA7u/vAJ/PpwA2vF0AwZ+fAJFmZgBKvmkAV7puAE1T + UwCebW0AQklJAHvGiwCsra0AuK+cAM92dgDioKAAI7BGAGUhAgDxgIAAbNCLAPiRkQCHiIgA2dnZANuq + qgDifHwAUMt2AIXKlABdXV0A5OXlAD7MbQA/2XQA+vr6ACiTKADth4cAMcdfADTOaABVGwAAhiwAAD03 + NADCXFwAoHNzAFsxHAB+ZWUA7o2NADw+PwBx1JAAomFhAOt7ewDVcHAARLdhABqDGwDBwMAAKbpTAC+C + LwCwSEgApmpqAHcnAACXl5gAyMjIALy/vwBeMjIASElJAMWTkwB2enoAL8JUANyjowBlX18AgICAABx3 + GgAcjRwAzs/PAOWzswBRUVEAOiUcADI0NAAxyWMALsNdALxQUAC1T08Aa8uHAIpqWwBvb3AAy6qqAOKD + gwA0wWAA0GVlANFqagDNenoAkpOTAItgYADacHAAU1RUABiMGwD4nJwA2KamAD5FRQDdd3cAO7ldAHd3 + dwDf4uIALjAwAKdeXgDPy8sAx8XFALecnABPu2oANxEAAGkeAABfuHEAeWpqAOvs7ADR1tYA/Z2dADk6 + OgBSMTEA8ISEALi4uADohoYATT09ANpsbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAVI6gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfZbAcAAOQGWGcNAAAAAAAA + AAAAAAAAAAAAAAAA4C1rHLt6wdnCPzBeK6o/dAAAAAAAAAAAAAAAAAAAnerBes5v73q7u2+BtaGlAmYT + TwAAAAAAAAAAAAAAAMv8CgoKzgrCuy8vpOSbTVSrAmamhkMAAAAAAAAAAAAcOp4Knp6eTM4vsDIUuteO + 3KqrAqaEyM0AAAAAAAAAAMF6TExMTJ6ezjUDvuYF146LJtOrqwKmZmUAAAAAAAAAwbuk657OwsJvkdbW + nwUP8em8JtTTqwKmZQAAAAAAAADBwhtMb7v8Ii9xJSV3BZOPuW5WvCbTmLoAAAAAAAAAAC3CuzrvOjo6 + w7avr3fMojgdRm5WVoFyAAAAAAAAAIhs2S1s4/mIy8HD7YBQd8wpWfQdjn4YlToAAAAAAAAAbGscZGHZ + VUkiazpp3oDPfzdBk33MISzWawAAAAAAAGtrwdjzYBEt0svBnS7i3kJ/RIp4OWjfJVr1AAAAAAAA2Z12 + CCh7YC1JxXrBh5bigye9NgyXgK+v1bIAAAAAAE5rTiDzKA5gUeP5wjqIFlzQH5TgCT6W/68lsgAAAAAA + a50HsZnArWBRVUkKIpTGt1Ua0NDsxZCC31ASAAAAAAAt4NljrJlgCMdVo567w4WayvlJVRpJo9KS3xIA + AAAAAC3gH3lXPawqa+NOCm9vyfvf5xqjtBqjSbQ+4QAAAAAA6uCjNHzyGUgtVbvOb85KS0vbbZCS7OMJ + 0o2NAAAAAACdBy0QdTPRBy3LTG9v7uWcnEtLHr/+5+NiEsQtAAAAAABswaNArgedy55vb55T+AScS6ke + Hre4F0dfxLQAAAAAAE6IncHgHBwKwrsbG8IeMZxLqR6g6HML3t0k+QAAAAAAAOA641WUpMMingH2pPCc + cEupHqDouAuA3foaAAAAAAAAADrCAZ6UlJ4BAafr6zxqs7P9oHO43oBQXdIAAAAAAAAAAIgBAQEBAaen + UqdSievv2ltF4gvdUF/HGgAAAAAAAAAAADobUlKJifYbpKSk9okb6/e7PDuMCgfqAAAAAAAAAAAAADqI + OiK7zusbGxukpKSk9qRM984K4AAAAAAAAAAAAAAAAAAAAJQ6iDqUesKeG/akns67IsE6AAAAAAAAAAAA + AAAAAAAAAAAAAAAAiIjBwcEciDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////4///+GD//8AAP/8AAB/+AAAH/AAAA/wA + AAH8AAAB/AAAA/wAAAfwAAAH8AAAB+AAAAfgAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAD4AAAA+AA + AAPwAAAD+AAAA/wAAAP+AAAD/wAAB//wAAf//8A///////////8oAAAAIAAAAEAAAAABACAAAAAAAIAQ + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIYAYBmaHesAjQDEAJMANAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAioqKAm9vb0JsbGyiaWlp72hoaO9qamqbb29vIgAAAAAKjA3pkuWz/2za + k/8dpyz8AJAAkgCXAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAg4ODIXh4eIBtbW3eeXl5/5ubm//CwsL/u7u7/5eXl/9vb2/4zs7OzhWQ + Gvx62Jr/W9CB/0/Zgf8yyF3/BJIJ5QCZAFYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAh4eHS3l5eb13d3f9l5eX/7q6uv/Pz8//zMzM/8XFxf+9vb3/wMDA/7+/ + v//MzMz/FIoY/3HUkP9Qy3b/Psxt/zjSbP9D33z/Irc9/gCNALcAogAiAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAIyMjB+BgYH5uLi4/9HR0f/R0dH/0dHR/9DQ0P/T09P/yMjI/7+/ + v//BxcX/wsjI/+Ll5f8Xihv/bNCL/0vGcP83x2T/M8xm/znTbf9D3Xr/Qdpz/w6dG/UAiAB7AJoABgAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgoKCZ6enp//Z2dn/1dXV/9fX1//X19f/2tra/9zc + 3P/Nzc3/v8TE/6Bzc/+mU1P/1rOz/xiDGv9pzIf/ScFr/zTBYP8wxmD/NM5o/zjSbP8/2HT/SOSB/y/C + VP8BiAHWAIoAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACBgYF/urq6/97e3v/e3t7/3t7e/9zc + 3P/Z2dn/2dnZ/87Q0P+dior/rj4+/7BISP/Ypqb/GH8Y/2zJhv9Kvmn/Nrxd/yu/Wf8vx2H/M8xm/zbQ + av861G7/P9l0/0Pfff8DgQHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAISEhIDCwsL/5OTk/+Hh + 4f/Y2Nj/zs7O/8jIyP/Hx8f/x8vL/55tbf+3Tk7/tU9P/9uqqv8XfBj/cMiI/0+7av87uV3/KblS/yu+ + WP8uw13/MMlj/zLNZ/83023/O9h1/wKABNYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhISEgMnJ + yf/q6ur/3t7e/8zMzP/BwcH/uLi4/7a2tv/AxMT/n2Zm/75UVP+6VFT/3q2t/xh6F/95x4z/V7pu/0S3 + Yf8ztVb/JrVO/ym6VP8swVv/M8pl/yOwRv8AfQDXAH4AMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIyM + jElra2vhycnJ/8DAwP+lpaX/xcXF/6ioqP+oqKj/pqam/7q/v/+iYWH/wlxc/8BaWv/hr6//GnYa/4XK + lP9iunX/ULZo/0CzXP8xslP/KrZR/ye0Tv8RiBn/YJ5g8wCCAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AACHh4djaWlp/HBwcP9vcnP/aGxt/1NUVf86Ojr/oKCg/4GBgf+Wlpb/usDA/6deXv/IZGT/xV9f/+Ox + sf8ddhr/lM6g/3C8fv9fuHH/VLdr/0u6Z/8eky//O4Mu/7ivnP+kqKjpAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAj4+POmpqavp5eXn/l5ud/4puYP9oNR3/cXBw/1lZWf9BQUH/tLS0/3p6ev+jqKj/rFxc/89q + av/LZWX/5bOz/yB3Hf+m1K3/hMOO/3zEiv9UrGP/HHgZ/4+ccf/Yn5//s09P/3l6eu4AAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAFycnLNenp6/5SXmf+Kalv/aRsA/20gAP9yPiP/b3R2/zIzM/+AgID/mZmZ/4aJ + if+heXn/129v/9Fqav/rtbX/I3ce/83n0v+fz6f/Lokx/1uGSP/SraX/zX19/7tVVf+2S0v/emtr+3Bx + cQwAAAAAAAAAAAAAAAAAAAAAhoaGQG5ubv6HiIj/mJOR/2QZAP9+KQD/kS8A/28fAP90dHX/QUJC/0hI + SP+6urr/lpaW/46Wlv/Qdnb/3HBw/5Z7e/9fh17/L4Iv/yp1Jf+4q5P/4qCg/8lmZv/DXV3/wFpa/7xQ + UP99Zmb/cHFxIgAAAAAAAAAAAAAAAAAAAABwcHCPe3t7/4yOj/9vUEL/aSAA/4IqAP+cNAD/cSAA/3dq + Zf9SUlP/Ojo6/8nJyf+lpaX/naGh/8OFhf/od3f/UlBQ/2FjY/+sra3/kZSU/0pNTf+SaWn/zXV1/9ps + bP/DXFz/v1RU/39jY/90dXUuAAAAAAAAAAAAAAAAAAAAAGtra8GJiYn/gIOF/1sxHP9lIgP/dycA/4Ys + AP9tHwD/dmxn/1dXV/9ERET/0tLS/7Kysv+tsLD/xZOT/+17e/9cWVn/NDU1/1BQUP9SUlL/Li8v/0dK + Sv9LUlL/UURE/8x6ev/KXFz/gmFh/3h6ejMAAAAAAAAAAAAAAAAAAAAAampq3JCQkP9vcXL/XTgm/1Yc + AP9lIAD/bSMA/2YbAP93eXn/V1hY/19fX//X19f/wMDA/7y/v//NoKD/8YCA/2VfX/85Ozv/RERE/1pa + Wv81NTX/QEBA/11dXf8yNTX/QUlJ/854eP+FX1//eHl5MwAAAAAAAAAAAAAAAAAAAABpaWnflJSU/2Bi + Yv9ZPjH/TiIN/04ZAP9UGgD/WysW/3p+f/9VVVX/jY2N/9TU1P/MzMz/yc3N/9yjo//whIT/zX19/z9F + Rf8yNjb/XF1d/z09Pf82Njb/XFxc/0BAQP87Pz//k2tr/4tgYP99gIAzAAAAAAAAAAAAAAAAAAAAAGxs + bMuTk5P/Xl9f/zspIf9RNSj/NxEA/zkMAP9mWVH/c3R1/1hYWP/CwsL/zc3N/8zMzP/L0ND/6qSk//KL + i//1jIz/4oOD/3JPT/9OVFT/Q0hI/y0wMP9UVFT/TU1N/zI1Nf+RZ2f/kWRk/4SIhzQAAAAAAAAAAAAA + AAAAAAAAcXFxmISEhP9xcnL/JR8c/z8xKv8ZAQD/OiUc/4KFhv9yc3P/f39//97e3v/MzMz/zMzM/8/L + y//4nJz/9pCQ//aQkP/0jIz/9YqK/+qCgv+mamr/TT09/z1FRf9SVlb/KTEx/4VgYP9eMTH/LzM4eQAA + AAAAAAAAAAAAAAAAAACNjY05bW1t/peXl/9bW1z/FhMS/z03NP+DhIT/hoaG/39/f//X19f/y8vL/8vL + y//Y2dn/t6Cg//2dnf/8mZn/+ZKS//ONjf/viYn/6YOD/+l/f//oe3v/0nFx/6xnZ/+JUVH/vWBg/14y + Mv8nKizVAAAAAAAAAAAAAAAAAAAAAAAAAACEhIS7nZ2d/4eHh/+Wlpb/k5SU/5qamv+ampr/1NTU/8nJ + yf/BwcH/6enp/+np6f/Fysr/54OD//6rq//5kZH/842N/+2Hh//ogoL/5H5+/953d//ac3P/1W1t/9Jo + aP/SZWX/VzIy/yksLOEAAAAAAAAAAAAAAAAAAAAAAAAAAK+vryCRkZHlpqam/1NTU/9ZWVn/qqqq/+Tk + 5P++vr7/s7Oz/9jY2P//////7Ozs/+Ll5f+3nJz/+ZCQ//ejo//yjo7/7IaG/+eBgf/ifHz/3HZ2/9dx + cf/SbGz/zGZm/89jY/9SMTH/Ky0t6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+vrx6jo6O0zMzM/v// + ///X19f/q6ur/6qqqv/Z2dn////////////8/Pz/4eHh/97j4//Cq6v/2oOD/++MjP/tjY3/6IaG/+F6 + ev/adHT/1W9v/9Bqav/MZmb/yVtb/1I8PP8qLC3vAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAGenp7f///////////////////////////6+vr/+Pj4//f39//5+fn/8/Pz/+3w8P/d4+P/yMTE/8uq + qv/Nj4//0nt7/9pwcP/Va2v/0Gdn/8peXv+5YmL/dHp6/zExMfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK6urkyqqqr65+fn//f39//19fX/8fHx/+7u7v/r6+v/6Ojo/+bm5v/l5eX/5eXl/+zs + 7P/t7u7/5unp/97j4//Q1tb/w8DA/8Wpqf/EmJj/wZ+f/8/T0/+EhYX/NTU1cgAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK2trTKgoKCboKCgzaampva0tLT+wsLC/9DQ0P/h4eH/6enp/+fn + 5//n5+f/5ubm/+Xl5f/l5eX/5ubm/+vs7P/k5ub/3N7e/9LW1v/O0ND/0tPT/5WVlf2UlJQTAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArq6uBaGhoSqjo6NYoKCghqCg + oLSmpqbirKys/bq6uv/Jycn/29vb/+np6f/s7Oz/5eXl/9ra2v/Nzc3/wcHB/7W1tf+YmJjqoKCgbQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAACbm5sTmJiYP5WVlW2Tk5Obk5OTv5SUlMiRkZG1jo6OlpGRkXWRkZFVjo6ONZqa + mgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////+P///hg///AAD//AAAf/gAAB/wA + AAP8AAAB/AAAAfwAAAP8AAAH8AAAB/AAAAfgAAAH4AAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAA+AA + AAPgAAAD8AAAA/gAAAP8AAAD/gAAA/8AAAf/8AAH///AP///////////KAAAADAAAABgAAAAAQAIAAAA + AACACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AOdNtAKY/PwD9l5cACXIIAJLlswCCg4QAYRoAAE1N + TQDT09MA021tALirkwBGm0kAmjMAAHDIiAAsIBsAdjstAIJfXAAhtTwA1rOzAGuiawDFg4MAtG9vAD59 + MwA4DQAANTc3AOnp6QCbnJwAU7VoAOmBgQBjY2MAbUs9AJSQcAC0tLQAJqAuAFcyMgC9VlYAK79YAF+H + XgB9KgIAmcugAFsrFgBM134A2piYAHF0dgCheXkAwsXFAHrYmgD6ra0ArlVVABwHAQA7KSEAnYeHACtz + KwCo0KsAYr53AFV9PQCmp6cAvpaWAMSqqgBJFgAAkHJyABWRGgARCggAh8COAOu1tQBam1oAzefSANh+ + fgBAtVoAi1FRAG5bUQBCQkIA7aOjAPSMjADd3t4AS8ZvAI2NjQA6lToAyV9fAHFnZQD09PQAt6CgADvG + ZgBYWVkAKLVPAEcmFABs2pMAcLx+ALVKSgDQj48A5nl5AE89NABbzX4AvGxsAG0iAABmMhkAJy0tAF04 + JgCIf2UAH4IkAETeeQAcqDEA0q2lAKxcXADaf38AfHx8AGpqagBvT08AM7NVAMvMzAD4o6MAomVlAGKc + YgDac3MAdaV1AD8xKgCflJQA4a+vAC6PLgBZPjEAuru7AIwvAABVNicAVKxjABabLAAidx4AymVlAAmG + CwBaSkoAkHt4AEjkgQDJpKQAFp8jAI6WlgCgoaEA8PDwAJ/PpwA1u1sAxJ2dAJFmZgBMv2wAV7puAE5U + VACgbW0AQ0xMAHvAhwCtrq4AuK+cAM52dgDin58AJ6dDAGEgAQDugYEAa9SMAPmSkgCHiYkA2NnZAN2r + qwDhfHwAUMp2AIzGlQBdXV0A5OXlAEDLbQA/2XMA+vr6ACiQKADuh4cAMcZgADTOaABYGwAAiC0AAD42 + MwDBW1sApHFxAFsxHAB8ZWUA7Y6OAD0/PwB005EAoWBgAOp9fQDWcHAARbhiABqBGgDBv78AKrtUACuD + KwCvRkYAqmxsAHYnAACWmJgAx8jIAL6+vgBoMjIASElJAMWUjgB3e3sALsJUAOClpQBtW1sAgYCAABRo + DwAcjRwAzdDQAOWzswBTT04AMiIcADEzMwAyymMALcJcALxRUQC3T08AZ8mAAIVpWwBvcHAAy6qqAOKD + gwAywV0Az2VlAM9qagDDeHgAkpKSAItgYADZcHAAU1VVABiMGwD1nJwA06amAD9ERADed3cAPLddAHZ3 + dwDg4eEALjAwAKNaWgDNyckAycPDAK+ekABPu2oANxQEAGkfAABduXAAeGxsAOzs7ADS1tYA/J+fADk7 + OwBSMTEA7oSEALm4uADni4sATT09ANpsbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABPgagAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0jtUaBDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAODH6ssAAAAAAIHXtZtehoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABydbC3B + iJ1sywAAAIHXm15eK1aBDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABO6tmdlMLCu7v8nWzLLwXX116h + pQIChoF0AAAAAAAAAAAAAAAAAAAAAAAAAADBB9kHOu9vb28vw8PDuyKdiAU4XqFNpasCpsiBTwAAAAAA + AAAAAAAAAAAAAAAAAOrLiC/Ozm9vzs7vw8PDw7svzgU4XqGlVKurAqamZ4EVAAAAAAAAAAAAAAAAAAAA + BzoKzs7OzgoKCgrCu7svLy8vngX0Xk2lqtOrAgKmZqqBeAAAAAAAAAAAAAAAAAAAawoKCgoK956enp5v + uy92tu2/7wWPOE1U3KqrqwICpqZmZ4FyAAAAAAAAAAAAAAAATkyenp6eTExMTEzOwjUDvr4DFgX0OI65 + 3NSq06urAgKmptOBcgAAAAAAAAAAAACI4OtMTOvrTJ4KCvfCL0davr6+WwX0OPG5iybUqtOrq6sCAqbI + ugAAAAAAAAAAAACIwaTr6+ueCs5vb2/ClAPW1tbWWwX0OPG5i7y8JtSq06urqwK8ugAAAAAAAAAAAACI + HKTrpJ4Kby+7u7u7iL7W1tbWWwX0OI+56W5WvCbU1KrTqyaBcgAAAAAAAAAAAACIiBukTApvu3oiIiLD + HFolJSUlWwU4WfTxuW5WVry8JtSqfgVyAAAAAAAAAAAAAABOOolMCs67IiKUOjp6dtWvr68lW8w4WTiP + uUZuVlZWvJgFvQAAAAAAAAAAAAAAAOofnTotCePgu53BOoj8Na+vr6+vLMxZk1n0HblGbm5WgQVywgAA + AAAAAAAAAAAAbGzqLS3Z2eP542/qy4j8NVCAUFBQLMxZQVk49B25uZgFGPCdAAAAAAAAAAAAAADZ2Wtr + OhIgLdnQxerDa8v8g4CAgICALMxBopNZOPQdZcxkFgMtAAAAAAAAAAAAAMvZy516EQjzES1stPl64Aed + Pt7egICAl8xBKUGTkw0FGMbe1QP1AAAAAAAAAAAAiGzLByIg88BgYEgtSRot/E5Ond8L3gsLl8xBNylB + ZcwhW68lJb6yAAAAAAAAAAAAy+rLHIMIwCh7mREt4+wazuDg4ODiC+IXgxgYN3IFOcaWr68lJVoSHAAA + AAAAAAAAH52dHGFgwK0OwCgtHxrszogcwcHfc3OSGsc2BcwhSrhQUK+vr9YSwQAAAAAAAADg2Z2dy6xg + KK0OrfMtbLTSuzo6iIgW6OiQGkmdwernSbBqXICvr9USwQAAAAAAAAAHa50HSJmZwK17rQjqbEn5LyKU + lDrG6KDjtNLQo0nS+eOQghe3ryVHwQAAAAAAAADqB53HfGGZYMAoKJnHbMW0Cnr8IiKMoB5VxdLFownS + GtCjtGLKqa9HwQAAAAAAAADZTgfZVyCsmfNgYGHHbAnF6y+7w3qFHh5VCdJJVeMa0sWjxdLnUbdHHAAA + AAAAAABsTsts8tg9rKysrCDHH9BspG/Cwi/mHvuwkBr541X50klV49K0kN9HHAAAAAAAAADZTgejEGQZ + PT09PVHHo+Mcnm/Ob2/JqalLsPnsCaNJ0vnjVfkakBdHHAAAAAAAAADqnU7j0Ujy8vLyVwctH1Wezm9v + b29KS0tLS0UgtFUJ0hrQo0nSxRdHHAAAAAAAAACda8FVrtFdM/IzbGvZH8ukb29vb+5wS0tLS6lLoJFV + 0uzFownS5xcRbAAAAAAAAACIbMHHSTOuMzPQB2vqbPfOb29vb59wnJycnLOpqR6aX21J4+PSGr8RYi0A + AAAAAAAALQfgbOwAQFWdy53LlKRvb28KTL8EcAScnEupHh6goFzogHFHR90R0sUAAAAAAAAAiC2I4E5r + Tp2dweCIie/CwhvrpDWcMQScnEupHh6goOhzuAve3YDE0rQAAAAAAAAAAJ2UbJ3gwYg6iJSJL7u7ngGk + 6/yg+DGcS0upHh6g6OhzuN7egIDE0rQAAAAAAAAAAADgCtAQxR/gnon8/PzOAQEb66Q1S+UxS6mpHh6g + 6HNzC96AgIDE0vkAAAAAAAAAAAAAHPdMuwr2wpSUlMIBAQFSTOvrNfuccOWpHqCg6HO4C96AgFDE0vkA + AAAAAAAAAAAAAIgcAaTOuyIingEBAQEB9kxM6/xb6Jqzs/2g6HO4C96AgNVt0hoAAAAAAAAAAAAAAADB + UgEBAQEBAQEBp6enAQFSG0xM9/yMFrigoOi4C96AUDKdGhoAAAAAAAAAAAAAAACUlAGnp6dSUlKJiYn2 + 9hsbiVJS9uuens4iOxaAgFAlF2+I0OMAAAAAAAAAAAAAAAAAOjqeiVJSifb2GxukpKSkpKSkpPaJG+v3 + CvfOL7vCzs7gbAAAAAAAAAAAAAAAAAAAAACIiBw6esKepBsbpKSkpKSkpKSkpKT2G0wKzm9vb84cOgAA + AAAAAAAAAAAAAAAAAAAAAAAAlDo6iIiUu85M9hsbG6SkpBsbGxv2G+vrTJROAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAOjqIHDr8wp4b9vaknm+7Ijoc4IgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAA6iBzBwcHgwRyIOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////8AAP// + //x//wAA////+B//AAD///D4D/8AAP//gDgD/wAA//4AAAD/AAD/8AAAAH8AAP/gAAAAHwAA/8AAAAAP + AAD/wAAAAAMAAP/AAAAAAQAA/4AAAAABAAD/gAAAAAEAAP+AAAAAAQAA/4AAAAADAAD/gAAAAA8AAP8A + AAAADwAA/gAAAAAfAAD8AAAAAB8AAPgAAAAAHwAA8AAAAAAfAADwAAAAAA8AAPAAAAAADwAA4AAAAAAP + AADgAAAAAA8AAOAAAAAADwAA4AAAAAAPAADgAAAAAA8AAOAAAAAADwAA4AAAAAAPAADgAAAAAA8AAOAA + AAAABwAA8AAAAAAHAADwAAAAAAcAAPgAAAAABwAA/AAAAAAHAAD+AAAAAAcAAP8AAAAABwAA/4AAAAAH + AAD/gAAAAAcAAP/AAAAADwAA//AAAAAPAAD//wAAAB8AAP///AAAPwAA////4AP/AAD///////8AAP// + /////wAA////////AAAoAAAAMAAAAGAAAAABACAAAAAAAIAlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAfwAOAIoApgCHAOwAiQDEAJQAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAhgCdJqAu/3PRjv9EuVj/AYwA/ACRAJEAjQAMAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1tbRtvb291bGxsx2tr + a9ZsbGytcnJyRQAAAAAAAAAAAAAAAAAAAAAAgQDnaMZ9/3XVk/9p1o3/WNJ+/xedIf8AiADfAJcARwAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHx8fAd6enpTdnZ2s2xs + bPl0dHT/mJiY/5+fn/+Hh4f/a2tr/nFxcb94eHg+AAAAAAAAAAAAfgDzasmC/2zRi/9e0IL/VNN//0zX + fv8pukv/AYoB/gCPAJ8AjQASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGDg4Mzenp6knJy + cutwcHD/iYmJ/6urq//IyMj/yMjI/8DAwP/CwsL/ubm5/4qKiv9ra2v+cXFxutra2oIAfQDzZcZ9/2bO + hf9YzX3/TM53/0HRcv86027/OtNs/xShJP8AgwDnAJMAVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDg4MWf39/cHt7 + e89wcHD+hISE/6Wlpf/FxcX/zMzM/8rKyv/Kysr/xMTE/729vf+9vb3/vr6+/8LCwv+2trb/hoaG/6Cg + oP4Hewf9YcR5/2HLgP9Tynj/R8tx/zvNa/82zmn/OtNt/0Hbd/8vw1P/BIoF/gCKAK4AkwAZAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIyM + jEl2dnb2gICA/6CgoP/ExMT/zs7O/83Nzf/MzMz/zMzM/83Nzf/Pz8//xsbG/76+vv++vr7/vr6+/76+ + vv+/v7//w8PD/9DQ0P8Iegj/XsF2/17JfP9Qx3P/Q8hs/zbJZv8zzGb/N9Bq/zrTbf9A2nT/Qtt1/xqm + Lf8AgADuAJIAYgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAX5+ftSpqan/09PT/9DQ0P/Pz8//z8/P/9DQ0P/R0dH/0tLS/9PT0//V1dX/ycnJ/7+/ + v//AwMD/wcPD/8HGxv/Bx8f/wcbG/9ja2v8OfA7/XL1z/1zGef9NxXD/QMVp/zPGYv8xymT/Nc9p/zjR + a/871G7/P9hy/0Teev81yF3/BosJ/gCGALsAjgAiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAjIyMI3t7e/7V1dX/0dHR/9LS0v/T09P/1dXV/9bW1v/X19f/19fX/9jY + 2P/a2tr/zMzM/8DAwP/Dx8f/pJOT/6FgYP+jWlr/qW5u/8++vv8OeQ7/W7tw/1vEd/9Mwm3/P8Jl/zLC + Xv8vxmD/Msxm/zXOaP840Wv/OtNt/z7Xcf9B2nX/Q914/x2qNP8AfgD0AI4AbgAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhISERouLi//d3d3/19fX/9jY2P/Z2dn/2tra/9vb + 2//d3d3/3d3d/93d3f/f39//zs7O/8XHx/+UhYX/oDQ0/61ERP+uRkb/rEND/8aCgv8McQj/XLlv/1vC + dv9Mv2z/P79k/zK/XP8twVv/L8Zg/zLKZP80zWf/N9Bq/znSbP871G7/PdZw/0Hbd/81y2D/BooI/gCH + AG0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhISEUpOTk//i4uL/3d3d/97e + 3v/g4OD/4ODg/93d3f/Y2Nj/1dXV/9TU1P/W1tb/ycnJ/7/Fxf+KQ0P/s0pK/7BKSv+wSkr/sEpK/82M + jP8NcAn/Xblv/13Adv9OvWv/QLxj/zO8W/8rvVf/LcFb/y/HYf8xyWP/M8xm/zXOaP830Gr/ONFr/znS + bP881nH/LcBU/wB7ANgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiIiIUpmZ + mf/m5ub/4ODg/+Li4v/h4eH/2dnZ/9PT0//Ozs7/y8vL/8rKyv/Kysr/x8fH/6qxsf+kQUH/tk9P/7RO + Tv+0Tk7/tE5O/8+Ojv8Nbwn/Xrdv/2C/d/9RvGz/RLpj/ze5W/8ruVT/KrxW/yzAWv8uxF7/MMdh/zLL + Zf8zzWf/NM1n/zXOaP840m3/Kr5T/wB6ANkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAh4eHUp2dnf/m5ub/4uLi/+Pj4//Z2dn/0dHR/8rKyv/ExMT/wMDA/7+/v/+/v7//wcHB/5+l + pf+wRUX/uFFR/7dRUf+3UVH/t1FR/9GQkP8NbAn/YbZw/2S/ev9Vu27/SLll/zy3Xf8wtlX/KLdR/yq7 + Vf8rvlj/LcFb/y7EXv8wxmD/Mslj/zPOaf8rv1j/BYMJ/gB/AHMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAhoaGUqOjo//p6en/5OTk/9/f3//T09P/ysrK/8HBwf+6urr/tbW1/7Oz + s/+0tLT/vb29/5ycnP+2Skr/vVhY/7tVVf+7VVX/u1VV/9STk/8Nagn/ZbZy/2m/ff9bunH/Trho/0K2 + X/82tVj/LLRR/ye1T/8ouFL/KrtV/yu/Wf8twlz/L8Vg/xabLP8AcwD1AIMAcQAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACIiIgRfX19pKSkpP/w8PD/3t7e/9PT0//Ozs7/wcHB/7W1 + tf+zs7P/rKys/6ioqP+pqan/ury8/5qUlP++UFD/v1xc/79ZWf+/WVn/vlhY/9aVlf8NaAr/a7Z3/3C/ + gf9iu3X/Vbhs/0q1Y/8/tFz/NLJV/yuyT/8ms03/J7ZQ/yq6Vf8irUT/BXsJ/wB2AMAAgwAlAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJWVlTdycnLgYmJi/4mJif+mpqb/cnJy/0xM + TP9TU1P/kZGR/8HBwf+Ghob/lZWV/6Wlpf+jo6P/tri4/5iJif/DV1f/w2Fh/8JcXP/CXFz/wlxc/9iW + lv8RZwz/crd7/3nAhv9qvHr/Xrhx/1K2af9ItGH/PrJa/zWxVP8uslH/J7JN/xCMH/8Mcwz/YpZj/fj4 + +FkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj4+PRWxsbPVra2v/dXV1/3Jz + c/9wcnP/cHFy/29vb/9VVVX/OTk5/1VVVf/Ly8v/dnZ2/4CAgP+ioqL/t7m5/5iEhP/IXl7/x2Vl/8Zg + YP/GYGD/xmBg/9qYmP8SZQ3/eLiA/4LDjf9zvYD/Z7p3/1y3b/9StGf/SrRi/0S1YP8roEL/BHMH/zt4 + Kf+vnpD/iYuL/nx8fAsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACampoqbGxs8HFx + cf96enr/fX5+/6KmqP9/Zlr/aU9C/3B0d/9vcHD/UFBQ/0ZGRv93d3f/vb29/3t7e/+AgID/trm5/5l/ + f//MY2P/zGdn/8ljY//JY2P/yWNj/9ybm/8SZQ3/gLuG/4zGlf9+wIj/crx//2e5dv9guHL/VLRo/xqD + Iv8RbAz/holf/82Hh/+kRET/cXd3/3h5eRkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJOT + kwR1dXXMbm5u/35+fv+IiYn/uLu7/3ZFLP9iGQD/aB0A/209Jf9vdHb/aGho/z4+Pv87Ozv/u7u7/5GR + kf+EhIT/hYeH/5Bycv/TaGj/zmpq/81nZ//NZ2f/zWdn/96dnf8SZQ3/ir+O/5fJnv+JxJH/fsCI/3rB + h/9HoFP/A2oE/0h6M//Ckoj/xW9v/7hSUv+rPz//eGxs/4GBgSkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAIyMjGBnZ2f/gICA/4WFhf+us7X/d0o0/2cdAP91JgD/byQA/28fAP9zYFf/cHJz/0RE + RP81NTX/cnJy/7i4uP+NjY3/i4uL/4SIiP++d3f/025u/9Fra//SbGz/02tr/+agoP8XZxH/kcGU/6bQ + qv+bzKH/hcCN/yOAJv8WaQ//lI1q/9OMjP/AXl7/vFZW/7pUVP+xRkb/fGVl/3x+fkkAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAXh4eM93d3f/goKC/5qcnf+MfHX/YRgA/3QmAP+CKwD/jC4A/2Ae + AP9/QSL/b3N2/1VVVf8xMTH/Nzc3/9DQ0P+UlJT/lJSU/5GSkv+UkJD/2XBw/9Rubv/Yb2//smRk/4t1 + df83dDH/PIw//6nPq/9hpWT/AWUB/1V9Pf/NmZL/znZ2/8NdXf/BW1v/vlhY/7tVVf+1S0v/gWBg/36B + gWQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAl5eXMmdnZ/6Hh4f/iIiI/5qeoP9mMRj/ayIA/3oo + AP+LLgD/mzIA/3MnAP96Lgb/cXZ5/2JiYv83Nzf/LCws/83Nzf+enp7/nJyc/5mZmf+TmJj/zXh4/9py + cv/ddHT/Q0xM/zQ4OP92gXj/K3Mr/wZiBv8caxv/k5J1/+2goP/Wb2//yGFh/8ZgYP/DXV3/wFpa/79Z + Wf+4Tk7/glxc/32BgXUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAd3d3enFxcf+JiYn/iYqL/4R+ + ff9YFQD/ayMA/3woAP+LLQD/mTMA/4YsAP9qIAD/cnZ2/2tra/8+Pj7/NDQ0/8LCwv+oqKj/paWl/6Ki + ov+doKD/wYaG/911df/gd3f/TVNT/zc3N/9BQUH/hoaG/5aXl/90dnb/P0VF/0VERP+ecXH/2n9//+Z4 + eP/KYmL/w11d/8BaWv+7UVH/hFlZ/4GFhX0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcHBwr3x8 + fP+Kior/gYOE/2tVSv9cIQP/ZyIA/3YmAP+DLAD/jC8A/4ktAP9hHQD/dHd3/2xsbP9CQkL/OTk5/8TE + xP+xsbH/rq6u/6urq/+nqan/wJGR/+J4eP/jeXn/UVhY/z09Pf80NDT/UFBQ/1xcXP9CQkL/MjIy/zs7 + O/9TVlb/TVVV/1pKSv+4cnL/6X19/8NcXP++VVX/hldX/4GFhYUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAbW1t1YWFhf+IiIj/d3l7/1U2J/9mNR3/Xx4A/20jAP93JgD/fSgA/30oAP9iIQL/dXl8/2tr + a/9JSUn/Pj4+/9HR0f+6urr/t7e3/7W1tf+ytLT/wp2d/+V7e//nfn7/U1pa/0ZGRv8yMjL/SUlJ/11d + Xf9LS0v/MjIy/zY2Nv9RUVH/XFxc/z1AQP8nLi7/bVtb/+yHh//DWFj/h1NT/4OHh4UAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAa2tr7YyMjP+Dg4P/bnBy/0UkE/90Tjv/VBkA/2EfAP9pIgD/bCMA/2si + AP9lMBX/dnt9/2dnZ/9OTk7/RkZG/+Hh4f/ExMT/wcHB/76+vv+6vLz/yaSk/+l/f//sgoL/U1lZ/05P + T/8zMzP/QEBA/1tbW/9UVFT/NjY2/zMzM/9KSkr/XV1d/0lJSf8xMjL/QERE/29kZP/rfHz/iVBQ/4WK + ioUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa2tr8o+Pj/+BgYH/ZWdo/zgZC/+FaVv/RxMA/1Ib + AP9ZHQD/XB4A/1wbAP9oRzb/eHp8/2NjY/9RUVH/aWlp/+Pj4//Ly8v/ycnJ/8jIyP/Ex8f/06am/+qB + gf/uhIT/qnJy/01VVf83ODj/OTk5/1ZWVv9aWlr/Ozs7/zIyMv9BQUH/W1tb/1NTU/80NDT/PT09/09W + Vv+9eHj/j1BQ/4WJiYUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbGxs7Y6Ojv+Dg4P/W1xd/zEa + D/+KdWv/OA0A/0UWAP9KGAD/TRkA/0oSAP9yamb/eXp6/15eXv9VVVX/m5ub/9jY2P/MzMz/zc3N/8vL + y//Lzs7/4KWl/+6Ghv/uh4f/9omJ/6Rxcf81PDz/LjEx/05PT/9dXV3/RERE/zIyMv85OTn/VlZW/1pa + Wv86Ojr/Nzc3/05SUv+2dHT/kFJS/4eMjIUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbm5u1IiI + iP+Ojo7/U1RU/zEjHf9tW1P/OhsM/zYQAP88EwD/PBIA/0knFf9/goT/dHR0/2FhYf9YWFj/19fX/83N + zf/MzMz/zMzM/8zMzP/Lzs7/7KWl//KKiv/yjIz/8YuL//eLi//Yfn7/ZUlJ/ztCQv9YW1v/TE1N/zMz + M/81NTX/UFBQ/11dXf9DQ0P/MjIy/0ZLS/+1cnL/k1VV/4yRkYYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAdnZ2qH19ff+VlZX/WFlZ/zo1NP8yIRr/Tz00/yUJAP8rDgD/KAcA/3Bsaf99fn7/cHBw/2Zm + Zv+CgoL/5eXl/8zMzP/MzMz/zMzM/8zNzf/Nycn/96Gh//SNjf/0jo7/842N//GLi//xiYn/9oqK/919 + ff+gbW3/W1dX/y00NP8sMDD/R0dH/11dXf9MTEz/MjIy/z9ERP+ycXH/ejg4/0VJSa00NDQFAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAh4eHYWlpaf+VlZX/eXp6/0NDQ/8OBgH/Qjcy/xwLBP8TAAD/V01K/4KD + hf98fHz/eHh4/2xsbP/W1tb/z8/P/8zMzP/MzMz/zMzM/8rNzf/dq6v/+qKi//mVlf/5kpL/9pCQ//WP + j//wior/7oeH/+2Fhf/sgoL/7oCA/7xsbP9xTEz/QkFB/1FXV/9QVFT/LzQ0/y85Of+paWn/czIy/ycs + K/85OUiBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArKysDW5ubueFhYX/lJSU/2lpaf8wMDD/AAAA/xEK + CP9bV1X/iImJ/4KCgv+Ghob/gICA/6ysrP/k5OT/y8vL/8zMzP/Ly8v/09PT/9rf3/+sbGz//Zqa//yl + pf/8lZX/+JKS//WPj//zjY3/7oiI/+qEhP/ngYH/5H5+/+R8fP/leXn/4nV1/8Bra/+iZWX/glFR/41S + Uv/OZGT/cjMz/y8zM/8kJCTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJKSknpzc3P/oqKi/5KS + kv+MjIz/fHx8/4yNjf+HiIj/h4eH/5WVlf+QkJD/oaGh/+7u7v/Gxsb/x8fH/8fHx//o6Oj/4uLi/+Hk + 5P+hhob//5KS//2zs//9lpb/+pOT//WPj//yjIz/7oiI/+qEhP/ngYH/4319/+B6ev/cdnb/2nNz/9dw + cP/VbGz/1Glp/89lZf/NYmL/bjEx/y8zM/8mJibPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALGx + sQ+Hh4fir6+v/2xsbP+JiYn/lJSU/5WVlf+hoaH/qKio/56env+wsLD/8PDw/8PDw//AwMD/wMDA/9ra + 2v//////5eXl/+Li4v+2urr/4H9///yfn//7q6v/95CQ//SOjv/xi4v/74mJ/+qEhP/ogoL/4319/995 + ef/cdnb/2HJy/9Vvb//Ra2v/zmho/8pkZP/MYmL/aTEx/zE0NP8nJyfVAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAACurq45lZWV8tLS0v9RUVH/JiYm/0ZGRv9jY2P/kpKS/9ra2v/w8PD/ubm5/7i4 + uP+4uLj/zs7O////////////6urq/+Dg4P/k5+f/oIqK//qLi//4nZ3/96mp//KOjv/viIj/7IaG/+mD + g//mgID/4nx8/995ef/bdXX/2HJy/9Rubv/Ra2v/zWdn/8tlZf/LYWH/ZjEx/zA0NP8pKSnbAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqqqqOJycnOLW1tb/3t7e/7+/v//R0dH/7e3t/8nJ + yf+qqqr/r6+v/66urv/Hx8f/////////////////9fX1/9/f3//h4eH/2+Hh/6qKiv/ug4P/9Y+P//Si + ov/xm5v/64iI/+eBgf/kfn7/4Xt7/954eP/adHT/13Fx/9Ntbf/Qamr/zGZm/8ljY//KX1//YjMz/zAz + M/8rKyvjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKOjow6WlpaImpqa//// + ///k5OT/z8/P/8DAwP+zs7P/s7Oz/9ra2v////////////7+/v///////////+3t7f/f39//3t7e/9/j + 4/+8uLj/xo6O/9x5ef/tgYH/7ZGR/+uOjv/ni4v/4H19/9x2dv/Zc3P/1nBw/9JsbP/PaWn/y2Vl/8lj + Y/+9UVH/bFJS/zAyMv8sLCzpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AACjo6MHlJSU7PX19f/////////////////////////////////+/v7//f39//v7+//4+Pj/+fn5//39 + /f/+/v7/9vb2/+rq6v/e39//2+Dg/8zU1P/BtbX/xZ2d/8aBgf/UcXH/4np6/958fP/bdnb/1nJy/9Nt + bf/Pamr/y2Rk/8hfX/+uVVX/h4yM/zU1Nf8uLi7vAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAApqamdq+vr/7//////Pz8//r6+v/5+fn/9vb2//T09P/y8vL/8fHx//Dw + 8P/v7+//7e3t/+zs7P/q6ur/6urq/+/v7//29vb/9PT0/+3t7f/g4eH/19ra/9Xa2v/K0dH/vrKy/76W + lv/BfX3/xmlp/81hYf/MX1//wVVV/7NsbP/Lysr/nZ6e/1FRUf8uLi6wAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWVlZA6Ojo5yoqKj+2dnZ/+7u7v/29vb/8/Pz/+/v + 7//t7e3/6+vr/+jo6P/n5+f/5eXl/+Tk5P/k5OT/4+Pj/+Pj4//j4+P/4+Pj/+Xl5f/t7e3/7+/v/+np + 6f/i4uL/1dbW/9HU1P/Q1tb/y9LS/8LFxf/Eu7v/ycnJ/8vR0f/Oz8//lJSU/0pKSrAuLi4WAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACsrKxDnp6eo56e + ntOcnJz2q6ur/ru7u//IyMj/19fX/+Tk5P/n5+f/5+fn/+bm5v/l5eX/5OTk/+Pj4//j4+P/5OTk/+Tk + 5P/k5OT/5OTk/+Tk5P/l5eX/7e3t/+fn5//e3t7/1NTU/87Ozv/MzMz/y8vL/8rKyv/Pz8//mpqa/5qa + mlsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAACdnZ0LoaGhMaSkpF+hoaGOoaGhvKCgoOmjo6P+sLCw/7+/v//Q0ND/39/f/+vr + 6//p6en/6enp/+jo6P/m5ub/5ubm/+Xl5f/n5+f/5+fn/+fn5//p6en/7Ozs/+rq6v/h4eH/4ODg/9vb + 2/+urq7/jo6O65ubmx4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACnp6cao6OjSKOj + o3aioqKlnZ2d05ubm/aoqKj+uLi4/8fHx//X19f/5+fn/+zs7P/r6+v/5OTk/9jY2P/Ly8v/wMDA/7S0 + tP+np6f/m5ub/ZGRkeKZmZmKl5eXFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAJOTkwuWlpYxmJiYX5eXl42UlJS6lJSU3ZaWlvGUlJTvkZGR15GR + kbeRkZGXk5OTdpGRkVWVlZU1k5OTF1NTUwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////AAD////8f/8AAP////gf/wAA///w+A// + AAD//4A4A/8AAP/+AAAA/wAA//AAAAB/AAD/4AAAAB8AAP/AAAAADwAA/8AAAAADAAD/wAAAAAEAAP+A + AAAAAQAA/4AAAAABAAD/gAAAAAEAAP+AAAAAAwAA/4AAAAAPAAD/AAAAAA8AAP4AAAAAHwAA/AAAAAAf + AAD4AAAAAB8AAPAAAAAAHwAA8AAAAAAPAADwAAAAAA8AAOAAAAAADwAA4AAAAAAPAADgAAAAAA8AAOAA + AAAADwAA4AAAAAAPAADgAAAAAA8AAOAAAAAADwAA4AAAAAAPAADgAAAAAAcAAPAAAAAABwAA8AAAAAAH + AAD4AAAAAAcAAPwAAAAABwAA/gAAAAAHAAD/AAAAAAcAAP+AAAAABwAA/4AAAAAHAAD/wAAAAA8AAP/w + AAAADwAA//8AAAAfAAD///wAAD8AAP///+AD/wAA////////AAD///////8AAP///////wAA + + + \ No newline at end of file diff --git a/Samples/Vision/Motion detection/Motion detection.csproj b/Samples/Vision/Motion detection/Motion detection.csproj new file mode 100644 index 0000000000..28d033ea8 --- /dev/null +++ b/Samples/Vision/Motion detection/Motion detection.csproj @@ -0,0 +1,231 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {9800A224-0BF0-4D5D-A03C-AA7A4842D3B8} + WinExe + Properties + MotionDetectorSample + MotionDetector + + + 3.5 + v4.0 + + + false + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + + ..\..\..\Release\net40\Accord.dll + + + ..\..\..\Release\net40\Accord.Controls.dll + + + ..\..\..\Release\net40\Accord.Controls.Imaging.dll + + + ..\..\..\Release\net40\Accord.Imaging.dll + + + ..\..\..\Release\net40\Accord.Math.dll + + + ..\..\..\Release\net40\Accord.Video.dll + + + ..\..\..\Release\net40\Accord.Video.DirectShow.dll + + + ..\..\..\Release\net40\Accord.Video.VFW.dll + + + ..\..\..\Release\net40\Accord.Vision.dll + + + + + + + + + + Form + + + AboutForm.cs + + + Component + + + DefineRegionsControl.cs + + + Form + + + MotionRegionsForm.cs + + + Form + + + VideoCaptureDeviceForm.cs + + + Form + + + MainForm.cs + + + + + Designer + AboutForm.cs + + + MotionRegionsForm.cs + Designer + + + Designer + VideoCaptureDeviceForm.cs + + + Designer + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + Designer + URLForm.cs + + + True + Resources.resx + True + + + PreserveNewest + + + + PreserveNewest + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + Form + + + URLForm.cs + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 2.0 %28x86%29 + false + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + \ No newline at end of file diff --git a/Samples/Vision/Motion detection/MotionDetector.exe.config b/Samples/Vision/Motion detection/MotionDetector.exe.config new file mode 100644 index 0000000000..f9f2d4854 --- /dev/null +++ b/Samples/Vision/Motion detection/MotionDetector.exe.config @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Samples/Vision/Motion detection/MotionDetector.sln b/Samples/Vision/Motion detection/MotionDetector.sln new file mode 100644 index 0000000000..f104342f6 --- /dev/null +++ b/Samples/Vision/Motion detection/MotionDetector.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C# Express 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MotionDetector", "MotionDetector.csproj", "{9800A224-0BF0-4D5D-A03C-AA7A4842D3B8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9800A224-0BF0-4D5D-A03C-AA7A4842D3B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9800A224-0BF0-4D5D-A03C-AA7A4842D3B8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9800A224-0BF0-4D5D-A03C-AA7A4842D3B8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9800A224-0BF0-4D5D-A03C-AA7A4842D3B8}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/Vision/Motion detection/MotionRegionsForm.Designer.cs b/Samples/Vision/Motion detection/MotionRegionsForm.Designer.cs new file mode 100644 index 0000000000..853476172 --- /dev/null +++ b/Samples/Vision/Motion detection/MotionRegionsForm.Designer.cs @@ -0,0 +1,151 @@ +namespace SampleApp +{ + partial class MotionRegionsForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MotionRegionsForm)); + this.toolStrip = new System.Windows.Forms.ToolStrip(); + this.rectangleButton = new System.Windows.Forms.ToolStripButton(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.clearButton = new System.Windows.Forms.ToolStripButton(); + this.okButton = new System.Windows.Forms.Button(); + this.cancelButton = new System.Windows.Forms.Button(); + this.defineRegionsControl = new SampleApp.DefineRegionsControl(); + this.toolStrip.SuspendLayout(); + this.SuspendLayout(); + // + // toolStrip + // + this.toolStrip.ImageScalingSize = new System.Drawing.Size(24, 24); + this.toolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.rectangleButton, + this.toolStripSeparator1, + this.clearButton}); + this.toolStrip.Location = new System.Drawing.Point(0, 0); + this.toolStrip.Name = "toolStrip"; + this.toolStrip.Padding = new System.Windows.Forms.Padding(0, 0, 2, 0); + this.toolStrip.Size = new System.Drawing.Size(513, 31); + this.toolStrip.TabIndex = 1; + // + // rectangleButton + // + this.rectangleButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.rectangleButton.Image = ((System.Drawing.Image)(resources.GetObject("rectangleButton.Image"))); + this.rectangleButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.rectangleButton.Name = "rectangleButton"; + this.rectangleButton.RightToLeftAutoMirrorImage = true; + this.rectangleButton.Size = new System.Drawing.Size(28, 28); + this.rectangleButton.ToolTipText = "Draw rectangular region"; + this.rectangleButton.Click += new System.EventHandler(this.rectangleButton_Click); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(6, 31); + // + // clearButton + // + this.clearButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.clearButton.Image = ((System.Drawing.Image)(resources.GetObject("clearButton.Image"))); + this.clearButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.clearButton.Name = "clearButton"; + this.clearButton.Size = new System.Drawing.Size(28, 28); + this.clearButton.ToolTipText = "Clear all regions"; + this.clearButton.Click += new System.EventHandler(this.clearButton_Click); + // + // okButton + // + this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK; + this.okButton.Location = new System.Drawing.Point(261, 463); + this.okButton.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.okButton.Name = "okButton"; + this.okButton.Size = new System.Drawing.Size(112, 35); + this.okButton.TabIndex = 2; + this.okButton.Text = "&Ok"; + this.okButton.UseVisualStyleBackColor = true; + // + // cancelButton + // + this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.cancelButton.Location = new System.Drawing.Point(382, 462); + this.cancelButton.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.cancelButton.Name = "cancelButton"; + this.cancelButton.Size = new System.Drawing.Size(112, 35); + this.cancelButton.TabIndex = 3; + this.cancelButton.Text = "&Cancel"; + this.cancelButton.UseVisualStyleBackColor = true; + // + // defineRegionsControl + // + this.defineRegionsControl.BackgroundImage = null; + this.defineRegionsControl.Cursor = System.Windows.Forms.Cursors.Default; + this.defineRegionsControl.DrawingMode = SampleApp.DrawingMode.None; + this.defineRegionsControl.Location = new System.Drawing.Point(15, 54); + this.defineRegionsControl.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.defineRegionsControl.Name = "defineRegionsControl"; + this.defineRegionsControl.Rectangles = new System.Drawing.Rectangle[0]; + this.defineRegionsControl.Size = new System.Drawing.Size(483, 372); + this.defineRegionsControl.TabIndex = 0; + // + // MotionRegionsForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(513, 517); + this.Controls.Add(this.cancelButton); + this.Controls.Add(this.okButton); + this.Controls.Add(this.toolStrip); + this.Controls.Add(this.defineRegionsControl); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; + this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MotionRegionsForm"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.Text = "Motion Regions"; + this.toolStrip.ResumeLayout(false); + this.toolStrip.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private DefineRegionsControl defineRegionsControl; + private System.Windows.Forms.ToolStrip toolStrip; + private System.Windows.Forms.Button okButton; + private System.Windows.Forms.Button cancelButton; + private System.Windows.Forms.ToolStripButton rectangleButton; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripButton clearButton; + } +} \ No newline at end of file diff --git a/Samples/Vision/Motion detection/MotionRegionsForm.cs b/Samples/Vision/Motion detection/MotionRegionsForm.cs new file mode 100644 index 0000000000..ba018e1ee --- /dev/null +++ b/Samples/Vision/Motion detection/MotionRegionsForm.cs @@ -0,0 +1,85 @@ +// Motion Detection sample application +// AForge.NET Framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace SampleApp +{ + public partial class MotionRegionsForm : Form + { + // Video frame sample to show + public Bitmap VideoFrame + { + set { defineRegionsControl.BackgroundImage = value; } + } + + // Motion rectangles + public Rectangle[] MotionRectangles + { + get { return defineRegionsControl.Rectangles; } + set { defineRegionsControl.Rectangles = value; } + } + + // Class constructor + public MotionRegionsForm( ) + { + InitializeComponent( ); + + defineRegionsControl.OnNewRectangle += new NewRectangleHandler( defineRegionsControl_NewRectangleHandler ); + } + + // On first displaying of the form + protected override void OnLoad( EventArgs e ) + { + // get video frame dimension + if ( defineRegionsControl.BackgroundImage != null ) + { + int imageWidth = defineRegionsControl.BackgroundImage.Width; + int imageHeight = defineRegionsControl.BackgroundImage.Height; + + // resize region definition control + defineRegionsControl.Size = new Size( imageWidth + 2, imageHeight + 2 ); + // resize window + this.Size = new Size( imageWidth + 2 + 26, imageHeight + 2 + 118 ); + } + + base.OnLoad( e ); + } + + // On rectangle button click + private void rectangleButton_Click( object sender, EventArgs e ) + { + DrawingMode currentMode = defineRegionsControl.DrawingMode; + + // change current mode + currentMode = ( currentMode == DrawingMode.Rectangular ) ? DrawingMode.None : DrawingMode.Rectangular; + // update current mode + defineRegionsControl.DrawingMode = currentMode; + // change button status + rectangleButton.Checked = ( currentMode == DrawingMode.Rectangular ); + } + + // New rectangle definition was finished + private void defineRegionsControl_NewRectangleHandler( object sender, Rectangle rect ) + { + rectangleButton.Checked = false; + } + + // On clear button click + private void clearButton_Click( object sender, EventArgs e ) + { + defineRegionsControl.RemoveAllRegions( ); + } + } +} \ No newline at end of file diff --git a/Samples/Vision/Motion detection/MotionRegionsForm.resx b/Samples/Vision/Motion detection/MotionRegionsForm.resx new file mode 100644 index 0000000000..2b59d36a2 --- /dev/null +++ b/Samples/Vision/Motion detection/MotionRegionsForm.resx @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAA0SURBVDhPYxg04D8ZmBGI4eB/Q0MD0RimHqIVAjAECIBR + A4apAaRiDAtBAqRiqNYBBQwMAMvPlKxpfkKOAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAABvSURBVDhP1Y6xDYAwDAQ9BRMwA1OyAg0TeAe2yQopgk6k + SPGxKyR46ZTiclHsF2sKd+dM1+q5SHDPlflkCDiIfiFDwF37Fj4gQ8ARRw/IEHDvxuVYJbgsZjIGXBYz + GQMOoti6nBLG47io6PqTM7sBQAcFDECkw1sAAAAASUVORK5CYII= + + + \ No newline at end of file diff --git a/Samples/Vision/Motion detection/Program.cs b/Samples/Vision/Motion detection/Program.cs new file mode 100644 index 0000000000..d9b26e676 --- /dev/null +++ b/Samples/Vision/Motion detection/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Windows.Forms; + +namespace SampleApp +{ + static class Program + { + [STAThread] + static void Main() + { + if (Environment.OSVersion.Version.Major >= 6) + SetProcessDPIAware(); + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + + [System.Runtime.InteropServices.DllImport("user32.dll")] + private static extern bool SetProcessDPIAware(); + } +} \ No newline at end of file diff --git a/Samples/Vision/Motion detection/Properties/AssemblyInfo.cs b/Samples/Vision/Motion detection/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..9d7b79f22 --- /dev/null +++ b/Samples/Vision/Motion detection/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle( "Motion Detector" )] +[assembly: AssemblyDescription( "Motion Detector sample" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "AForge" )] +[assembly: AssemblyProduct( "AForge.NET" )] +[assembly: AssemblyCopyright( "AForge © 2009" )] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible( false )] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid( "6014b6ce-dcb6-455f-b295-051ea2330ae9" )] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion( "2.4.0.0" )] +[assembly: AssemblyFileVersion( "2.4.0.0" )] diff --git a/Samples/Vision/Motion detection/Properties/Resources.Designer.cs b/Samples/Vision/Motion detection/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..7b58e53ee --- /dev/null +++ b/Samples/Vision/Motion detection/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Samples/Vision/Motion detection/Properties/Resources.resx b/Samples/Vision/Motion detection/Properties/Resources.resx new file mode 100644 index 0000000000..25a61211c --- /dev/null +++ b/Samples/Vision/Motion detection/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Vision/Motion detection/Properties/Settings.Designer.cs b/Samples/Vision/Motion detection/Properties/Settings.Designer.cs new file mode 100644 index 0000000000..dbc9e5d22 --- /dev/null +++ b/Samples/Vision/Motion detection/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleApp.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Samples/Vision/Motion detection/Properties/Settings.settings b/Samples/Vision/Motion detection/Properties/Settings.settings new file mode 100644 index 0000000000..39645652a --- /dev/null +++ b/Samples/Vision/Motion detection/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Samples/Vision/Motion detection/URLForm.Designer.cs b/Samples/Vision/Motion detection/URLForm.Designer.cs new file mode 100644 index 0000000000..cefa0c412 --- /dev/null +++ b/Samples/Vision/Motion detection/URLForm.Designer.cs @@ -0,0 +1,107 @@ +namespace SampleApp +{ + partial class URLForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.urlBox = new System.Windows.Forms.ComboBox(); + this.cancelButton = new System.Windows.Forms.Button(); + this.okButton = new System.Windows.Forms.Button(); + this.descriptionLabel = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // urlBox + // + this.urlBox.FormattingEnabled = true; + this.urlBox.Location = new System.Drawing.Point(15, 54); + this.urlBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.urlBox.Name = "urlBox"; + this.urlBox.Size = new System.Drawing.Size(486, 28); + this.urlBox.TabIndex = 0; + // + // cancelButton + // + this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.cancelButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.cancelButton.Location = new System.Drawing.Point(270, 123); + this.cancelButton.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.cancelButton.Name = "cancelButton"; + this.cancelButton.Size = new System.Drawing.Size(112, 35); + this.cancelButton.TabIndex = 5; + this.cancelButton.Text = "Cancel"; + // + // okButton + // + this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK; + this.okButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.okButton.Location = new System.Drawing.Point(135, 123); + this.okButton.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.okButton.Name = "okButton"; + this.okButton.Size = new System.Drawing.Size(112, 35); + this.okButton.TabIndex = 4; + this.okButton.Text = "Ok"; + this.okButton.Click += new System.EventHandler(this.okButton_Click); + // + // descriptionLabel + // + this.descriptionLabel.Location = new System.Drawing.Point(15, 15); + this.descriptionLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.descriptionLabel.Name = "descriptionLabel"; + this.descriptionLabel.Size = new System.Drawing.Size(488, 20); + this.descriptionLabel.TabIndex = 6; + // + // URLForm + // + this.AcceptButton = this.okButton; + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.CancelButton = this.cancelButton; + this.ClientSize = new System.Drawing.Size(516, 178); + this.Controls.Add(this.descriptionLabel); + this.Controls.Add(this.cancelButton); + this.Controls.Add(this.okButton); + this.Controls.Add(this.urlBox); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; + this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "URLForm"; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Open URL"; + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.ComboBox urlBox; + private System.Windows.Forms.Button cancelButton; + private System.Windows.Forms.Button okButton; + private System.Windows.Forms.Label descriptionLabel; + } +} \ No newline at end of file diff --git a/Samples/Vision/Motion detection/URLForm.cs b/Samples/Vision/Motion detection/URLForm.cs new file mode 100644 index 0000000000..da0c685c4 --- /dev/null +++ b/Samples/Vision/Motion detection/URLForm.cs @@ -0,0 +1,58 @@ +// Motion Detection sample application +// AForge.NET Framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace SampleApp +{ + public partial class URLForm : Form + { + private string url; + + // Selected URL + public string URL + { + get { return url; } + } + + // URLs to display in combo box + public string[] URLs + { + set + { + urlBox.Items.AddRange( value ); + } + } + + // Description of the dialog + public string Description + { + get { return descriptionLabel.Text; } + set { descriptionLabel.Text = value; } + } + + // Constructor + public URLForm( ) + { + InitializeComponent( ); + } + + // On "Ok" button clicked + private void okButton_Click( object sender, EventArgs e ) + { + url = urlBox.Text; + + } + } +} \ No newline at end of file diff --git a/Samples/Vision/Motion detection/URLForm.resx b/Samples/Vision/Motion detection/URLForm.resx new file mode 100644 index 0000000000..c7e0d4bdf --- /dev/null +++ b/Samples/Vision/Motion detection/URLForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Vision/Motion detection/VideoCaptureDeviceForm.Designer.cs b/Samples/Vision/Motion detection/VideoCaptureDeviceForm.Designer.cs new file mode 100644 index 0000000000..018bec67a --- /dev/null +++ b/Samples/Vision/Motion detection/VideoCaptureDeviceForm.Designer.cs @@ -0,0 +1,111 @@ +namespace SampleApp +{ + partial class VideoCaptureDeviceForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.label1 = new System.Windows.Forms.Label(); + this.devicesCombo = new System.Windows.Forms.ComboBox(); + this.cancelButton = new System.Windows.Forms.Button(); + this.okButton = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(15, 15); + this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(242, 20); + this.label1.TabIndex = 0; + this.label1.Text = "Select local video capture device:"; + // + // devicesCombo + // + this.devicesCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.devicesCombo.FormattingEnabled = true; + this.devicesCombo.Location = new System.Drawing.Point(15, 54); + this.devicesCombo.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.devicesCombo.Name = "devicesCombo"; + this.devicesCombo.Size = new System.Drawing.Size(486, 28); + this.devicesCombo.TabIndex = 1; + // + // cancelButton + // + this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.cancelButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.cancelButton.Location = new System.Drawing.Point(270, 123); + this.cancelButton.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.cancelButton.Name = "cancelButton"; + this.cancelButton.Size = new System.Drawing.Size(112, 35); + this.cancelButton.TabIndex = 7; + this.cancelButton.Text = "Cancel"; + // + // okButton + // + this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK; + this.okButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.okButton.Location = new System.Drawing.Point(135, 123); + this.okButton.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.okButton.Name = "okButton"; + this.okButton.Size = new System.Drawing.Size(112, 35); + this.okButton.TabIndex = 6; + this.okButton.Text = "Ok"; + this.okButton.Click += new System.EventHandler(this.okButton_Click); + // + // VideoCaptureDeviceForm + // + this.AcceptButton = this.okButton; + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.CancelButton = this.cancelButton; + this.ClientSize = new System.Drawing.Size(516, 178); + this.Controls.Add(this.cancelButton); + this.Controls.Add(this.okButton); + this.Controls.Add(this.devicesCombo); + this.Controls.Add(this.label1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; + this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "VideoCaptureDeviceForm"; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Open local video capture device"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.ComboBox devicesCombo; + private System.Windows.Forms.Button cancelButton; + private System.Windows.Forms.Button okButton; + } +} \ No newline at end of file diff --git a/Samples/Vision/Motion detection/VideoCaptureDeviceForm.cs b/Samples/Vision/Motion detection/VideoCaptureDeviceForm.cs new file mode 100644 index 0000000000..75a2128a9 --- /dev/null +++ b/Samples/Vision/Motion detection/VideoCaptureDeviceForm.cs @@ -0,0 +1,68 @@ +// Motion Detection sample application +// AForge.NET Framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +using AForge.Video.DirectShow; + +namespace SampleApp +{ + public partial class VideoCaptureDeviceForm : Form + { + FilterInfoCollection videoDevices; + private string device; + + // Video device + public string VideoDevice + { + get { return device; } + } + + // Constructor + public VideoCaptureDeviceForm( ) + { + InitializeComponent( ); + + // show device list + try + { + // enumerate video devices + videoDevices = new FilterInfoCollection( FilterCategory.VideoInputDevice ); + + if ( videoDevices.Count == 0 ) + throw new ApplicationException( ); + + // add all devices to combo + foreach ( FilterInfo device in videoDevices ) + { + devicesCombo.Items.Add( device.Name ); + } + } + catch ( ApplicationException ) + { + devicesCombo.Items.Add( "No local capture devices" ); + devicesCombo.Enabled = false; + okButton.Enabled = false; + } + + devicesCombo.SelectedIndex = 0; + } + + // Ok button clicked + private void okButton_Click( object sender, EventArgs e ) + { + device = videoDevices[devicesCombo.SelectedIndex].MonikerString; + } + } +} \ No newline at end of file diff --git a/Samples/Vision/Motion detection/VideoCaptureDeviceForm.resx b/Samples/Vision/Motion detection/VideoCaptureDeviceForm.resx new file mode 100644 index 0000000000..c7e0d4bdf --- /dev/null +++ b/Samples/Vision/Motion detection/VideoCaptureDeviceForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Vision/Motion detection/app.config b/Samples/Vision/Motion detection/app.config new file mode 100644 index 0000000000..57c0f2cbc --- /dev/null +++ b/Samples/Vision/Motion detection/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Setup/Accord.Setup.csproj b/Setup/Accord.Setup.csproj index 70a71d264..2e6fcca57 100644 --- a/Setup/Accord.Setup.csproj +++ b/Setup/Accord.Setup.csproj @@ -17,7 +17,9 @@ - + + + Designer @@ -34,6 +36,12 @@ + + + + + + @@ -42,6 +50,10 @@ + + PreserveNewest + + diff --git a/Setup/Compile.sh b/Setup/Compile.sh deleted file mode 100644 index f73647979..0000000000 --- a/Setup/Compile.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -########### - -echo -echo Accord.NET Framework all projects configurations builder -echo ========================================================= -echo -echo This Linux bash script will use Mono's xbuild tool to -echo compile the Debug and Release versions of the framework. -echo - - -echo - Building NET40 configuration... -mdtool -v build -c:"NET40" ../Sources/Accord.NET.Mono.sln - -# echo - Building samples... -# mdtool -v build ../Samples/Samples.sln - diff --git a/Setup/Package.cmd b/Setup/CreateRelease.cmd similarity index 91% rename from Setup/Package.cmd rename to Setup/CreateRelease.cmd index a810e0fe6..efb1faea0 100644 --- a/Setup/Package.cmd +++ b/Setup/CreateRelease.cmd @@ -6,8 +6,9 @@ :: Compile sources -cmd /c "Compile.cmd" - +cd .. +cmd /c "Build.cmd" +cd Setup :: Build compressed archive cd Archiver diff --git a/Setup/Installer/Accord.iss b/Setup/Installer/Accord.iss index a87c47b9e..53a5ff736 100644 --- a/Setup/Installer/Accord.iss +++ b/Setup/Installer/Accord.iss @@ -1,6 +1,6 @@ ; Accord.NET setup project -#define VERSION GetStringFileInfo("..\..\Release\net40\Accord.dll", "ProductVersion") +#define VERSION GetStringFileInfo("..\..\Release\net45\Accord.dll", "ProductVersion") #pragma message "Creating package for Accord.NET " + VERSION [Setup] AppName=Accord.NET Framework @@ -10,7 +10,7 @@ AppPublisher=Accord.NET AppPublisherURL=http://accord-framework.net AppSupportURL=http://accord-framework.net AppUpdatesURL=http://accord-framework.net -AppCopyright=Copyright Csar Souza, 2009-2015 +AppCopyright=Copyright Accord.NET authors, 2009-2015 VersionInfoVersion={#VERSION} DefaultDirName={pf}\Accord.NET\Framework DefaultGroupName=Accord.NET\Framework @@ -65,14 +65,17 @@ Source: "..\..\Setup\*"; DestDir: "{app}\Setup"; Components: Source: "..\..\Externals\*"; DestDir: "{app}\Externals"; Components: libs; Flags: recursesubdirs; Excludes: "*.~*,*.pdb" ; Official, supported release: +Source: "..\..\Release\net45\*"; DestDir: "{app}\Release\net45"; Components: libs; Excludes: "*.~*,*.lastcodeanalysissucceeded,*.CodeAnalysisLog.xml,SlimDX.pdb" Source: "..\..\Release\net40\*"; DestDir: "{app}\Release\net40"; Components: libs; Excludes: "*.~*,*.lastcodeanalysissucceeded,*.CodeAnalysisLog.xml,SlimDX.pdb" Source: "..\..\Release\net35\*"; DestDir: "{app}\Release\net35"; Components: libs; Excludes: "*.~*,*.lastcodeanalysissucceeded,*.CodeAnalysisLog.xml,SlimDX.pdb" ; Extra GPL-only libraries: +Source: "..\..\Release\net45\GPL\*"; DestDir: "{app}\Release\net45"; Components: libs/gpl; Flags: recursesubdirs; Excludes: "*.~*,*.lastcodeanalysissucceeded,*.CodeAnalysisLog.xml" Source: "..\..\Release\net40\GPL\*"; DestDir: "{app}\Release\net40"; Components: libs/gpl; Flags: recursesubdirs; Excludes: "*.~*,*.lastcodeanalysissucceeded,*.CodeAnalysisLog.xml" Source: "..\..\Release\net35\GPL\*"; DestDir: "{app}\Release\net35"; Components: libs/gpl; Flags: recursesubdirs; Excludes: "*.~*,*.lastcodeanalysissucceeded,*.CodeAnalysisLog.xml" ; Extra Noncommercial libraries: +Source: "..\..\Release\net45\Noncommercial\*"; DestDir: "{app}\Release\net45\Noncommercial\"; Components: libs/noc; Flags: recursesubdirs; Excludes: "*.~*,*.lastcodeanalysissucceeded,*.CodeAnalysisLog.xml" Source: "..\..\Release\net40\Noncommercial\*"; DestDir: "{app}\Release\net40\Noncommercial\"; Components: libs/noc; Flags: recursesubdirs; Excludes: "*.~*,*.lastcodeanalysissucceeded,*.CodeAnalysisLog.xml" Source: "..\..\Release\net35\Noncommercial\*"; DestDir: "{app}\Release\net35\Noncommercial\"; Components: libs/noc; Flags: recursesubdirs; Excludes: "*.~*,*.lastcodeanalysissucceeded,*.CodeAnalysisLog.xml" diff --git a/Setup/NuGet/Accord.DirectSound.nuspec b/Setup/NuGet/Accord.Audio.DirectSound.nuspec similarity index 52% rename from Setup/NuGet/Accord.DirectSound.nuspec rename to Setup/NuGet/Accord.Audio.DirectSound.nuspec index 744619768..fe1149935 100644 --- a/Setup/NuGet/Accord.DirectSound.nuspec +++ b/Setup/NuGet/Accord.Audio.DirectSound.nuspec @@ -4,35 +4,32 @@ Accord.DirectSound $version$ - Accord.DirectSound + Accord.Audio.DirectSound Accord.NET Accord.NET http://accord-framework.net/license.txt http://accord-framework.net http://accord-framework.net/logo.png true - Play and record audio using DirectSound. This package is part of the Accord.NET Framework. + Play and record audio using DirectSound. This package is part of the Accord.NET Framework. Accord.NET Audio Library from the Accord.NET Framework accord.net aforge.net framework computer audition audio processing wave capture - - + + - - - - - + + - - + + - - + + \ No newline at end of file diff --git a/Setup/NuGet/Accord.Audio.nuspec b/Setup/NuGet/Accord.Audio.nuspec index 4443608cf..9042d8b3e 100644 --- a/Setup/NuGet/Accord.Audio.nuspec +++ b/Setup/NuGet/Accord.Audio.nuspec @@ -11,38 +11,29 @@ http://accord-framework.net http://accord-framework.net/logo.png true - Process, transforms, filters and handle audio signals for machine learning and statistical applications. This package is part of the Accord.NET Framework. + + Process, transforms, filters and handle audio signals for machine learning and statistical applications. This package is part of the Accord.NET Framework. + Accord.NET Audio Library from the Accord.NET Framework accord.net aforge.net framework computer audition audio processing fft spectral classification extraction beat detection - - - - - - - - + - - - + - - diff --git a/Setup/NuGet/Accord.Controls.Audio.nuspec b/Setup/NuGet/Accord.Controls.Audio.nuspec index 3b29bae74..8d817ec2c 100644 --- a/Setup/NuGet/Accord.Controls.Audio.nuspec +++ b/Setup/NuGet/Accord.Controls.Audio.nuspec @@ -11,18 +11,17 @@ http://accord-framework.net http://accord-framework.net/logo.png true - Windows Forms controls to display waveforms and audio-related information. This package is part of the Accord.NET Framework. + + Windows Forms controls to display waveforms and audio-related information. This package is part of the Accord.NET Framework. + Accord.NET Audio Controls Library from the Accord.NET Framework accord.net aforge.net framework winforms controls audio + - - - - diff --git a/Setup/NuGet/Accord.Controls.Imaging.nuspec b/Setup/NuGet/Accord.Controls.Imaging.nuspec index 512fa345c..bafbe6316 100644 --- a/Setup/NuGet/Accord.Controls.Imaging.nuspec +++ b/Setup/NuGet/Accord.Controls.Imaging.nuspec @@ -11,15 +11,15 @@ http://accord-framework.net http://accord-framework.net/logo.png true - Windows Forms controls to show and handle images. Contains a convenient ImageBox control which mimics the traditional MessageBox behavior for quickly displaying or inspecting images. This package is part of the Accord.NET Framework. + + Windows Forms controls to show and handle images. Contains a convenient ImageBox control which mimics the traditional MessageBox behavior for quickly displaying or inspecting images. This package is part of the Accord.NET Framework. + Accord.NET Imaging Controls Library from the Accord.NET Framework accord.net aforge.net framework computer image processing filters winforms controls complex fft - - - - + + diff --git a/Setup/NuGet/Accord.Controls.Vision.nuspec b/Setup/NuGet/Accord.Controls.Vision.nuspec index 406d63620..d2c498f7a 100644 --- a/Setup/NuGet/Accord.Controls.Vision.nuspec +++ b/Setup/NuGet/Accord.Controls.Vision.nuspec @@ -11,7 +11,9 @@ http://accord-framework.net http://accord-framework.net/logo.png true - Windows Forms components and controls to track head, face and hand movements and other computer vision related tasks. This package is part of the Accord.NET Framework. + + Windows Forms components and controls to track head, face and hand movements and other computer vision related tasks. This package is part of the Accord.NET Framework. + Accord.NET Vision Controls Library from the Accord.NET Framework accord.net aforge.net framework computer vision object detection tracking @@ -21,13 +23,6 @@ - - - - - - - diff --git a/Setup/NuGet/Accord.Controls.nuspec b/Setup/NuGet/Accord.Controls.nuspec index cf7ca23b5..043ed06d0 100644 --- a/Setup/NuGet/Accord.Controls.nuspec +++ b/Setup/NuGet/Accord.Controls.nuspec @@ -11,7 +11,9 @@ http://accord-framework.net http://accord-framework.net/logo.png true - Histograms, scatterplots and tabular data viewers for scientific applications. This package is part of the Accord.NET Framework. + + Histograms, scatterplots and tabular data viewers for scientific applications. This package is part of the Accord.NET Framework. + Accord.NET Control Library from the Accord.NET Framework accord.net aforge.net framework statistics data visualization histogram scatterplot boxplot chart @@ -19,9 +21,6 @@ - - - diff --git a/Setup/NuGet/Accord.Fuzzy.nuspec b/Setup/NuGet/Accord.Fuzzy.nuspec new file mode 100644 index 0000000000..3409de7fc --- /dev/null +++ b/Setup/NuGet/Accord.Fuzzy.nuspec @@ -0,0 +1,35 @@ + + + + + Accord.Fuzzy + $version$ + Accord.Fuzzy + Accord.NET + Accord.NET + http://accord-framework.net/license.txt + http://accord-framework.net + http://accord-framework.net/logo.png + true + + Contains Fuzzy logic tools, such as fuzzy sets, linguistic variables and inference systems. This package originated from the AForge.NET Framework and is part of the Accord.NET Framework. + + Accord.NET Machine Learning Library from the Accord.NET framework. + accord.net aforge.net fuzzy logic math + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Setup/NuGet/Accord.Genetic.nuspec b/Setup/NuGet/Accord.Genetic.nuspec new file mode 100644 index 0000000000..bf4f963fd --- /dev/null +++ b/Setup/NuGet/Accord.Genetic.nuspec @@ -0,0 +1,34 @@ + + + + + Accord.Genetic + $version$ + Accord.Genetic + Accord.NET + Accord.NET + http://accord-framework.net/license.txt + http://accord-framework.net + http://accord-framework.net/logo.png + true + + Contains chromosome and selection classes to create Genetic Algorithms (GA), Genetic Programming (GP) and Gene Expression Programming (GEP). This package originated from the AForge.NET Framework and is part of the Accord.NET Framework. + + Accord.NET Genetics Library from the Accord.NET Framework + accord.net aforge.net framework genetic algorithms programming + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Setup/NuGet/Accord.IO.nuspec b/Setup/NuGet/Accord.IO.nuspec index 051c15378..c00281ce9 100644 --- a/Setup/NuGet/Accord.IO.nuspec +++ b/Setup/NuGet/Accord.IO.nuspec @@ -11,7 +11,9 @@ http://accord-framework.net http://accord-framework.net/logo.png true - Contains File and data parsers to load and save data from different file formats. This package is part of the Accord.NET Framework. + + Contains File and data parsers to load and save data from different file formats. This package is part of the Accord.NET Framework. + Accord.NET IO (data formats) Library from the Accord.NET Framework accord.net aforge.net framework statistics mnist libsvm excel mat-file matlab octave matrix diff --git a/Setup/NuGet/Accord.Imaging.nuspec b/Setup/NuGet/Accord.Imaging.nuspec index 472a9d634..9641ffa27 100644 --- a/Setup/NuGet/Accord.Imaging.nuspec +++ b/Setup/NuGet/Accord.Imaging.nuspec @@ -11,18 +11,16 @@ http://accord-framework.net http://accord-framework.net/logo.png true - Contains interest point detectors (SURF and FAST), image matching and image stitching methods. This package is part of the Accord.NET Framework. + + Contains interest point detectors (SURF and FAST), image matching and image stitching methods. This package is part of the Accord.NET Framework. + Accord.NET Framework Imaging library - accord.net aforge.net framework image processing computer vision blur gaussian integral + accord.net aforge.net framework image processing computer vision blur Gaussian integral - + - - - - diff --git a/Setup/NuGet/Accord.MachineLearning.GPL.nuspec b/Setup/NuGet/Accord.MachineLearning.GPL.nuspec index 832dc3e3c..01dbdaeba 100644 --- a/Setup/NuGet/Accord.MachineLearning.GPL.nuspec +++ b/Setup/NuGet/Accord.MachineLearning.GPL.nuspec @@ -12,18 +12,14 @@ http://accord-framework.net/logo.png true - This package contains libraries of the Accord.NET Framework that are NOT available under the LGPL. - It currently includes Accord.MachineLearning.GPL, which contains GPL code and thus can only be used - inside GPL-compliant applications. Please take extra care before including this library in your projects. - + This package contains libraries of the Accord.NET Framework that are NOT available under the LGPL. It currently includes Accord.MachineLearning.GPL, which contains GPL code and thus can only be used inside GPL-compliant applications. Please take extra care before including this library in your projects. + Accord.NET Non-LGPL machine learning libraries from the Accord.NET framework. accord.net aforge.net aforge.net machine learning artificial intelligence smo svm gpl kernel - - diff --git a/Setup/NuGet/Accord.MachineLearning.nuspec b/Setup/NuGet/Accord.MachineLearning.nuspec index 9b090ab3f..005a9d754 100644 --- a/Setup/NuGet/Accord.MachineLearning.nuspec +++ b/Setup/NuGet/Accord.MachineLearning.nuspec @@ -11,15 +11,15 @@ http://accord-framework.net http://accord-framework.net/logo.png true - Contains Support Vector Machines, Decision Trees, Naive Bayesian models, K-means, Gaussian Mixture models and general algorithms such as Ransac, Cross-validation and Grid-Search for machine-learning applications. This package is part of the Accord.NET Framework. + + Contains Support Vector Machines, Decision Trees, Naive Bayesian models, K-means, Gaussian Mixture models and general algorithms such as Ransac, Cross-validation and Grid-Search for machine-learning applications. This package is part of the Accord.NET Framework. + Accord.NET Machine Learning Library from the Accord.NET framework. accord.net aforge.net aforge.net machine learning artificial intelligence svm kmeans kmodes gmm ransac kernel deep learning knn - - diff --git a/Setup/NuGet/Accord.Math.nuspec b/Setup/NuGet/Accord.Math.nuspec index d9bb6c519..24746fa48 100644 --- a/Setup/NuGet/Accord.Math.nuspec +++ b/Setup/NuGet/Accord.Math.nuspec @@ -11,14 +11,13 @@ http://accord-framework.net http://accord-framework.net/logo.png true - Contains a matrix extension library, along with a suite of numerical matrix decomposition methods, numerical optimization algorithms for constrained and unconstrained problems, special functions and other tools for scientific applications. This package is part of the Accord.NET Framework. + + Contains a matrix extension library, along with a suite of numerical matrix decomposition methods, numerical optimization algorithms for constrained and unconstrained problems, special functions and other tools for scientific applications. This package is part of the Accord.NET Framework. + Accord.Math library from the Accord.NET framework accord.net aforge.net framework math decompositions lu qr constrained optimization differentiation numerical matrix algebra svd kernel quadratic programming linear regression - - - diff --git a/Setup/NuGet/Accord.Neuro.nuspec b/Setup/NuGet/Accord.Neuro.nuspec index e003a86a7..9f6ac6e8e 100644 --- a/Setup/NuGet/Accord.Neuro.nuspec +++ b/Setup/NuGet/Accord.Neuro.nuspec @@ -11,16 +11,15 @@ http://accord-framework.net http://accord-framework.net/logo.png true - Contains neural learning algorithms such as Levenberg-Marquardt, Parallel Resilient Backpropagation, initialization procedures such as Nguyen-Widrow and other neural network related methods. This package is part of the Accord.NET Framework. + + Contains neural learning algorithms such as Levenberg-Marquardt, Parallel Resilient Backpropagation, initialization procedures such as Nguyen-Widrow and other neural network related + methods. This package is part of the Accord.NET Framework. + Accord.NET Neuro Library from the Accord.NET Framework accord.net aforge.net framework artificial neural networks levenberg-marquardt nguyen-widrow deep-learning ann neuron - - - - diff --git a/Setup/NuGet/Accord.Statistics.nuspec b/Setup/NuGet/Accord.Statistics.nuspec index d5b962aa8..abbaa022e 100644 --- a/Setup/NuGet/Accord.Statistics.nuspec +++ b/Setup/NuGet/Accord.Statistics.nuspec @@ -11,15 +11,14 @@ http://accord-framework.net http://accord-framework.net/logo.png true - Contains probability distributions, statistical models and methods such as Linear and Logistic regression, Hidden Markov Models, (Hidden) Conditional Random Fields, Principal Component Analysis, Partial Least Squares, Discriminant Analysis, Kernel methods and functions and many other related techniques. This package is part of the Accord.NET Framework. + + Contains probability distributions, statistical models and methods such as Linear and Logistic regression, Hidden Markov Models, (Hidden) Conditional Random Fields, Principal Component Analysis, Partial Least Squares, Discriminant Analysis, Kernel methods and functions and many other related techniques. This package is part of the Accord.NET Framework. + Accord.NET Statistics Library from the Accord.NET Framework accord.net aforge.net framework statistics kernel methods pca kpca least squares markov models conditional random fields hmm crf hcrf logistic linear regression - - - diff --git a/Setup/NuGet/Accord.Video.DirectShow.nuspec b/Setup/NuGet/Accord.Video.DirectShow.nuspec new file mode 100644 index 0000000000..d884d5de5 --- /dev/null +++ b/Setup/NuGet/Accord.Video.DirectShow.nuspec @@ -0,0 +1,34 @@ + + + + + Accord.Video.DirectShow + $version$ + Accord.Video.DirectShow + Accord.NET + Accord.NET + http://accord-framework.net/license.txt + http://accord-framework.net + http://accord-framework.net/logo.png + true + + Contains classes and methods to handle video sources using DirectShow interface (USB web cameras, capture devices, video files). This package originated from the AForge.NET Framework and is part of the Accord.NET Framework. + + Accord.NET Video DirectShow Library from the Accord.NET Framework + accord.net aforge.net framework video capture cameras + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Setup/NuGet/Accord.Video.FFMPEG.nuspec b/Setup/NuGet/Accord.Video.FFMPEG.nuspec new file mode 100644 index 0000000000..215d67986 --- /dev/null +++ b/Setup/NuGet/Accord.Video.FFMPEG.nuspec @@ -0,0 +1,46 @@ + + + + + Accord.Video.FFMPEG + $version$ + Accord.Video.FFMPEG + Accord.NET + Accord.NET + http://accord-framework.net/gpl.txt + http://accord-framework.net + http://accord-framework.net/logo.png + true + + Contains classes and methods to handle video sources using FFMPEG. For this reason, this package is available under the GPL license only. This package originated from the AForge.NET Framework and is part of the Accord.NET Framework. + + Accord.NET Video FFMPEG Library from the Accord.NET Framework + accord.net aforge.net framework ffmpeg video capture decode codec + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Setup/NuGet/Accord.Video.Kinect.nuspec b/Setup/NuGet/Accord.Video.Kinect.nuspec new file mode 100644 index 0000000000..aa3ebc42e --- /dev/null +++ b/Setup/NuGet/Accord.Video.Kinect.nuspec @@ -0,0 +1,38 @@ + + + + + Accord.Video.Kinect + $version$ + Accord.Video.Kinect + Accord.NET + Accord.NET + http://accord-framework.net/license.txt + http://accord-framework.net + http://accord-framework.net/logo.png + true + + Contains an interface to control and capture images from Microsoft Kinect devices. This package originated from the AForge.NET Framework and is part of the Accord.NET Framework. + + Accord.NET Video Kinect Library from the Accord.NET Framework + accord.net aforge.net framework video capture kinect cameras + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Setup/NuGet/Accord.Video.VFW.nuspec b/Setup/NuGet/Accord.Video.VFW.nuspec new file mode 100644 index 0000000000..88e379d30 --- /dev/null +++ b/Setup/NuGet/Accord.Video.VFW.nuspec @@ -0,0 +1,34 @@ + + + + + Accord.Video.VFW + $version$ + Accord.Video.VFW + Accord.NET + Accord.NET + http://accord-framework.net/license.txt + http://accord-framework.net + http://accord-framework.net/logo.png + true + + Contains classes to read and write AVI video files using Video For Windows. This package originated from the AForge.NET Framework and is part of the Accord.NET Framework. + + Accord.NET Video Video For Windows (VFW) Library from the Accord.NET Framework + accord.net aforge.net framework video capture cameras + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Setup/NuGet/Accord.Video.Ximea.nuspec b/Setup/NuGet/Accord.Video.Ximea.nuspec new file mode 100644 index 0000000000..cf9d2c1dd --- /dev/null +++ b/Setup/NuGet/Accord.Video.Ximea.nuspec @@ -0,0 +1,34 @@ + + + + + Accord.Video.Ximea + $version$ + Accord.Video.Ximea + Accord.NET + Accord.NET + http://accord-framework.net/license.txt + http://accord-framework.net + http://accord-framework.net/logo.png + true + + Contains classes which allow capturing images from XIMEA cameras. This package originated from the AForge.NET Framework and is part of the Accord.NET Framework. + + Accord.NET Video XIMEA Library from the Accord.NET Framework + accord.net aforge.net framework video capture ximea cameras + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Setup/NuGet/Accord.Video.nuspec b/Setup/NuGet/Accord.Video.nuspec new file mode 100644 index 0000000000..fd75b8042 --- /dev/null +++ b/Setup/NuGet/Accord.Video.nuspec @@ -0,0 +1,33 @@ + + + + + Accord.Video + $version$ + Accord.Video + Accord.NET + Accord.NET + http://accord-framework.net/license.txt + http://accord-framework.net + http://accord-framework.net/logo.png + true + + Contains interfaces and classes to access different video sources, such as IP video cameras (MJPEG streams). This package originated from the AForge.NET Framework and is part of the Accord.NET Framework. + + Accord.NET Video Library from the Accord.NET Framework + accord.net aforge.net framework video MJPEG cameras + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Setup/NuGet/Accord.Vision.nuspec b/Setup/NuGet/Accord.Vision.nuspec index e294bf118..4f95560fb 100644 --- a/Setup/NuGet/Accord.Vision.nuspec +++ b/Setup/NuGet/Accord.Vision.nuspec @@ -11,7 +11,9 @@ http://accord-framework.net http://accord-framework.net/logo.png true - Real-time face detection and tracking, as well as general methods for detecting, tracking and transforming objects in image streams. Contains Haar cascade definitions, Camshift and Dynamic Template Matching trackers. This package is part of the Accord.NET Framework. + + Real-time face detection and tracking, as well as general methods for detecting, tracking and transforming objects in image streams. Contains Haar cascade definitions, Camshift and Dynamic Template Matching trackers. This package is part of the Accord.NET Framework. + Accord.NET Vision Library from the Accord.NET Framework accord.net aforge.net framework computer vision object detection tracking haar viola-jones camshift @@ -20,12 +22,7 @@ - - - - - - + diff --git a/Setup/NuGet/Accord.nuspec b/Setup/NuGet/Accord.nuspec index 082c6959a..1920d36f4 100644 --- a/Setup/NuGet/Accord.nuspec +++ b/Setup/NuGet/Accord.nuspec @@ -11,7 +11,9 @@ http://accord-framework.net http://accord-framework.net/logo.png true - The core of the Accord.NET Framework. Contains basic classes such as general exceptions and extensions used by other framework libraries. Accord.NET is an extension framework for AForge.NET. + + The core of the Accord.NET Framework. Contains basic classes such as general exceptions and extensions used by other framework libraries. + Accord.NET Framework core library. accord.net aforge.net framework structures machine learning .net c# @@ -24,5 +26,8 @@ + + + \ No newline at end of file diff --git a/Setup/Publish.cmd b/Setup/PublishNuGet.cmd similarity index 100% rename from Setup/Publish.cmd rename to Setup/PublishNuGet.cmd diff --git a/Setup/Scripts/Accord.Video.FFMPEG.targets b/Setup/Scripts/Accord.Video.FFMPEG.targets new file mode 100644 index 0000000000..a236bdc85 --- /dev/null +++ b/Setup/Scripts/Accord.Video.FFMPEG.targets @@ -0,0 +1,29 @@ + + + + + + + + x86 + + + + + $(PrepareForRunDependsOn); + CopyNativeBinaries + + + + + + + + + + + \ No newline at end of file diff --git a/Setup/Scripts/Accord.Video.Kinect.targets b/Setup/Scripts/Accord.Video.Kinect.targets new file mode 100644 index 0000000000..a236bdc85 --- /dev/null +++ b/Setup/Scripts/Accord.Video.Kinect.targets @@ -0,0 +1,29 @@ + + + + + + + + x86 + + + + + $(PrepareForRunDependsOn); + CopyNativeBinaries + + + + + + + + + + + \ No newline at end of file diff --git a/Setup/Scripts/Accord.targets b/Setup/Scripts/Accord.targets new file mode 100644 index 0000000000..47b13b6b5 --- /dev/null +++ b/Setup/Scripts/Accord.targets @@ -0,0 +1,8 @@ + + + + Accord.dll.config + Always + + + \ No newline at end of file diff --git a/Setup/version.cmd b/Setup/version.cmd index f11df80c8..a9adcb830 100644 --- a/Setup/version.cmd +++ b/Setup/version.cmd @@ -1 +1 @@ -set version=2.15.0 \ No newline at end of file +set version=3.0.2 \ No newline at end of file diff --git a/Sources/Accord.DirectSound/Accord.DirectSound.csproj b/Sources/Accord.Audio.DirectSound/Accord.Audio.DirectSound.csproj similarity index 74% rename from Sources/Accord.DirectSound/Accord.DirectSound.csproj rename to Sources/Accord.Audio.DirectSound/Accord.Audio.DirectSound.csproj index 52d6ffb5b..83f8e989f 100644 --- a/Sources/Accord.DirectSound/Accord.DirectSound.csproj +++ b/Sources/Accord.Audio.DirectSound/Accord.Audio.DirectSound.csproj @@ -1,138 +1,130 @@ - - - - {456DB2E8-745A-4F87-A2BD-C43CF8677770} - Accord.DirectSound - Accord.DirectSound - - Debug - AnyCPU - AnyCPU - Library - Properties - True - 4 - True - true - Accord.snk - 3.5 - False - true - ..\Accord.NET.ruleset - false - true - 4096 - true - pdbonly - true - true - true - GlobalSuppressions.cs - - - v4.5 - bin\Debug\ - Full - False - False - True - DEBUG;TRACE - ..\..\Debug\ - - - ..\..\Release\net35 - TRACE;CODE_ANALYSIS;NET35 - v3.5 - true - ..\..\Release\net35\Accord.DirectSound.XML - ..\..\Release\net35\Accord.DirectSound.dll.CodeAnalysisLog.xml - - - ..\..\Release\net40 - TRACE;CODE_ANALYSIS;NET40 - v4.0 - ..\..\Release\net40\Accord.DirectSound.XML - ..\..\Release\net40\Accord.DirectSound.dll.CodeAnalysisLog.xml - - - ..\..\Release\net45 - TRACE;CODE_ANALYSIS;NET45 - v4.5 - ..\..\Release\net45\Accord.DirectSound.XML - ..\..\Release\net45\Accord.DirectSound.dll.CodeAnalysisLog.xml - - - - - - ..\..\Externals\AForge.NET\AForge.Math.dll - False - - - ..\..\Externals\SharpDX\net40\SharpDX.dll - ..\..\Externals\SharpDX\net20\SharpDX.dll - False - - - ..\..\Externals\SharpDX\net40\SharpDX.DirectSound.dll - ..\..\Externals\SharpDX\net20\SharpDX.DirectSound.dll - False - - - - 3.5 - - - - - - - - Properties\VersionInfo.cs - - - - - - - - - - - {EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF} - Accord.Audio.Formats - False - - - {E7B65F08-82F1-438F-847A-2AAC2BEC9AC0} - Accord.Audio - False - - - {F718E9A8-DB62-4785-8C49-4333A60D256A} - Accord.Math - False - - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - + + + + {456DB2E8-745A-4F87-A2BD-C43CF8677770} + Accord.Audio.DirectSound + Accord.Audio.DirectSound + Debug + AnyCPU + AnyCPU + Library + Properties + True + 4 + True + true + Accord.snk + 3.5 + False + true + ..\Accord.NET.ruleset + false + true + 4096 + true + pdbonly + true + true + true + GlobalSuppressions.cs + + + v4.5 + bin\Debug\ + Full + False + False + True + DEBUG;TRACE + $(SolutionDir)..\Debug\ + + + $(SolutionDir)..\Release\net35 + TRACE;CODE_ANALYSIS;NET35 + v3.5 + true + $(SolutionDir)..\Release\net35\Accord.Audio.DirectSound.XML + $(SolutionDir)..\Release\net35\Accord.Audio.DirectSound.dll.CodeAnalysisLog.xml + + + $(SolutionDir)..\Release\net40 + TRACE;CODE_ANALYSIS;NET40 + v4.0 + $(SolutionDir)..\Release\net40\Accord.Audio.DirectSound.XML + $(SolutionDir)..\Release\net40\Accord.Audio.DirectSound.dll.CodeAnalysisLog.xml + + + $(SolutionDir)..\Release\net45 + TRACE;CODE_ANALYSIS;NET45 + v4.5 + $(SolutionDir)..\Release\net45\Accord.Audio.DirectSound.XML + $(SolutionDir)..\Release\net45\Accord.Audio.DirectSound.dll.CodeAnalysisLog.xml + + + + + ..\..\Externals\SharpDX\net40\SharpDX.dll + ..\..\Externals\SharpDX\net20\SharpDX.dll + False + + + ..\..\Externals\SharpDX\net40\SharpDX.DirectSound.dll + ..\..\Externals\SharpDX\net20\SharpDX.DirectSound.dll + False + + + + 3.5 + + + + + + + + Properties\VersionInfo.cs + + + + + + + + + + + + + + {E7B65F08-82F1-438F-847A-2AAC2BEC9AC0} + Accord.Audio + False + + + {F718E9A8-DB62-4785-8C49-4333A60D256A} + Accord.Math + False + + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + \ No newline at end of file diff --git a/Sources/Accord.DirectSound/Accord.DirectSound.cd b/Sources/Accord.Audio.DirectSound/Accord.DirectSound.cd similarity index 100% rename from Sources/Accord.DirectSound/Accord.DirectSound.cd rename to Sources/Accord.Audio.DirectSound/Accord.DirectSound.cd diff --git a/Sources/Accord.Audio.Formats/Accord.snk b/Sources/Accord.Audio.DirectSound/Accord.snk similarity index 100% rename from Sources/Accord.Audio.Formats/Accord.snk rename to Sources/Accord.Audio.DirectSound/Accord.snk diff --git a/Sources/Accord.DirectSound/AudioCaptureDevice.cs b/Sources/Accord.Audio.DirectSound/AudioCaptureDevice.cs similarity index 96% rename from Sources/Accord.DirectSound/AudioCaptureDevice.cs rename to Sources/Accord.Audio.DirectSound/AudioCaptureDevice.cs index f28e1ff2d..f7ca7b2d2 100644 --- a/Sources/Accord.DirectSound/AudioCaptureDevice.cs +++ b/Sources/Accord.Audio.DirectSound/AudioCaptureDevice.cs @@ -1,26 +1,26 @@ -// Accord Audio Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.DirectSound +// Accord Audio Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.DirectSound { using Accord.Audio; using SharpDX.DirectSound; @@ -28,554 +28,550 @@ namespace Accord.DirectSound using System; using System.Threading; - /// - /// Audio source for local audio capture device (i.e. a microphone). - /// - /// - /// - /// This audio source captures audio data - /// obtained from a local audio capture device such as the microphone. The audio - /// is captured using DirectSound through SlimDX. - /// - /// For instructions on how to list capture devices, please see - /// the documentation page. - /// - /// - /// - /// Sample usage: - /// - /// - /// // Create default capture device - /// AudioCaptureDevice source = new AudioCaptureDevice(); - /// - /// // Specify capturing options - /// source.DesiredFrameSize = 4096; - /// source.SampleRate = 22050; - /// - /// // Specify the callback function which will be - /// // called once a sample is completely available - /// source.NewFrame += source_NewFrame; - /// - /// // Start capturing - /// source.Start(); - /// - /// // ... - /// - /// // The callback function should determine what - /// // should be done with the samples being caught - /// private void source_NewFrame(object sender, NewFrameEventArgs eventArgs) - /// { - /// // Read current frame... - /// Signal s = eventArgs.Signal; - /// - /// // Process/play/record it - /// // ... - /// } - /// - /// - /// For more details regarding usage, please check one of - /// the Audio sample applications accompanying the framework. - /// - /// - /// - /// - /// - public class AudioCaptureDevice : IAudioSource, IDisposable - { - - // moniker string of audio capture device - private Guid device = Guid.Empty; - private string sourceName; - - // user data associated with the audio source - private object userData = null; - - // received frames count - private int framesReceived; - - // received byte count - private int bytesReceived; - - // specifies desired capture frame size - private int desiredCaptureSize = 4096; - - // specifies the sample rate used in the source - private int sampleRate = 44100; - - private Thread thread = null; - private ManualResetEvent stopEvent = null; - - private SampleFormat sampleFormat = SampleFormat.Format32BitIeeeFloat; - - /// - /// New frame event. - /// - /// - /// Notifies clients about new available frame from audio source. - /// - /// Since audio source may have multiple clients, each client is responsible for - /// making a copy (cloning) of the passed audio frame, because the audio source disposes its - /// own original copy after notifying of clients. - /// - /// - public event EventHandler NewFrame; - - - /// - /// Audio source error event. - /// - /// - /// This event is used to notify clients about any type of errors occurred in - /// audio source object, for example internal exceptions. - /// - public event EventHandler AudioSourceError; - - /// - /// Audio source. - /// - /// - /// Audio source is represented by Guid of audio capture device. - /// - public virtual string Source - { - get { return sourceName; } - set { sourceName = value; } - } - - /// - /// Gets or sets the sample format used by the device. - /// - /// - public SampleFormat Format - { - get { return sampleFormat; } - set { sampleFormat = value; } - } - - /// - /// Gets or sets the desired frame size. - /// - public int DesiredFrameSize - { - get { return desiredCaptureSize; } - set { desiredCaptureSize = value; } - } - - /// - /// Gets the number of audio channels captured by - /// the device. Currently, only a single channel - /// is supported. - /// - /// - public int Channels - { - get { return 1; } - set { } - } - - /// - /// Received frames count. - /// - /// - /// Number of frames the audio source provided from the moment of the last - /// access to the property. - /// - /// - public int FramesReceived - { - get - { - int frames = framesReceived; - framesReceived = 0; - return frames; - } - } - - /// - /// Received bytes count. - /// - /// - /// Number of bytes the audio source provided from the moment of the last - /// access to the property. - /// - /// - public int BytesReceived - { - get - { - int bytes = bytesReceived; - bytesReceived = 0; - return bytes; - } - } - - /// - /// User data. - /// - /// - /// The property allows to associate user data with audio source object. - /// - public object UserData - { - get { return userData; } - set { userData = value; } - } - - /// - /// State of the audio source. - /// - /// - /// Current state of audio source object - running or not. - /// - public bool IsRunning - { - get - { - if (thread != null) - { - // check thread status - if (thread.Join(0) == false) - return true; - - // the thread is not running, free resources - Free(); - } - return false; - } - } - - /// - /// Initializes a new instance of the class. - /// - /// - public AudioCaptureDevice() - { - this.device = Guid.Empty; - this.sourceName = "Default capture device"; - } - - /// - /// Initializes a new instance of the class. - /// - /// - public AudioCaptureDevice(AudioDeviceInfo device) - { - this.device = device.Guid; - this.sourceName = device.Description; - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// Global identifier of the audio capture device. - /// - public AudioCaptureDevice(Guid device) - { - this.device = device; - this.sourceName = device.ToString(); - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// Global identifier of the audio capture device. - /// The device name or description string. - /// - public AudioCaptureDevice(Guid device, string name) - { - this.device = device; - this.sourceName = name; - } - - /// - /// Start audio source. - /// - /// - /// Starts audio source and return execution to caller. audio source - /// object creates background thread and notifies about new frames with the - /// help of event. - /// - public void Start() - { - if (thread == null) - { - // check source - if (device == Guid.Empty) - throw new ArgumentException("Audio source is not specified"); - - framesReceived = 0; - bytesReceived = 0; - - // create events - stopEvent = new ManualResetEvent(false); - - // create and start new thread - thread = new Thread(WorkerThread); - thread.Name = device.ToString(); - thread.Start(); - } - } - - /// - /// Signals audio source to stop its work. - /// - /// - /// Signals audio source to stop its background thread, stop to - /// provide new frames and free resources. - /// - public void SignalToStop() - { - // stop thread - if (thread != null) - { - // signal to stop - stopEvent.Set(); - } - } - - /// - /// Wait for audio source has stopped. - /// - /// - /// Waits for source stopping after it was signaled to stop using - /// method. - /// - public void WaitForStop() - { - if (thread != null) - { - // wait for thread stop - thread.Join(); - - Free(); - } - } - - /// - /// Stop audio source. - /// - /// - /// Stops audio source aborting its thread. - /// - /// Since the method aborts background thread, its usage is highly not preferred - /// and should be done only if there are no other options. The correct way of stopping camera - /// is signaling it stop and then - /// waiting for background thread's completion. - /// - /// - public void Stop() - { - if (this.IsRunning) - { - thread.Abort(); - WaitForStop(); - } - } - - /// - /// Free resource. - /// - /// - private void Free() - { - thread = null; - - // release events - stopEvent.Close(); - stopEvent = null; - } - - - - /// - /// Worker thread. - /// - /// - private void WorkerThread() - { - // Get the selected capture device - DirectSoundCapture captureDevice = new DirectSoundCapture(device); - - - // Set the capture format - var bitsPerSample = Signal.GetSampleSize(sampleFormat); - WaveFormat format = WaveFormat.CreateCustomFormat(sampleFormat.ToWaveFormat(), sampleRate, 1, - sampleRate * bitsPerSample / 8, bitsPerSample / 8, bitsPerSample); - - // Setup the capture buffer - CaptureBufferDescription captureBufferDescription = new CaptureBufferDescription(); - captureBufferDescription.Format = format; - captureBufferDescription.BufferBytes = 2 * desiredCaptureSize * format.BlockAlign; - captureBufferDescription.Flags |= CaptureBufferCapabilitiesFlags.WaveMapped; - captureBufferDescription.Flags &= ~CaptureBufferCapabilitiesFlags.ControlEffects; - - CaptureBuffer captureBuffer = null; - NotificationPosition[] notifications = new NotificationPosition[2]; - - try - { - captureBuffer = new CaptureBuffer(captureDevice, captureBufferDescription); - - // Setup the notification positions - int bufferPortionSize = captureBuffer.Capabilities.BufferBytes / 2; - notifications[0] = new NotificationPosition(); - notifications[0].Offset = bufferPortionSize - 1; - notifications[0].WaitHandle = new AutoResetEvent(false); - notifications[1] = new NotificationPosition(); - notifications[1].Offset = bufferPortionSize - 1 + bufferPortionSize; - notifications[1].WaitHandle = new AutoResetEvent(false); - captureBuffer.SetNotificationPositions(notifications); - - // Make a copy of the wait handles - WaitHandle[] waitHandles = new WaitHandle[notifications.Length]; - for (int i = 0; i < notifications.Length; i++) - waitHandles[i] = notifications[i].WaitHandle; - - - - // Start capturing - captureBuffer.Start(true); - - - if (sampleFormat == SampleFormat.Format32BitIeeeFloat) - { - float[] currentSample = new float[desiredCaptureSize]; - - while (!stopEvent.WaitOne(0, true)) - { - int bufferPortionIndex = WaitHandle.WaitAny(waitHandles); - captureBuffer.Read(currentSample, 0, currentSample.Length, bufferPortionSize * bufferPortionIndex, LockFlags.None); - OnNewFrame(currentSample); - } - } - else if (sampleFormat == SampleFormat.Format16Bit) - { - short[] currentSample = new short[desiredCaptureSize]; - - while (!stopEvent.WaitOne(0, true)) - { - int bufferPortionIndex = WaitHandle.WaitAny(waitHandles); - captureBuffer.Read(currentSample, 0, currentSample.Length, bufferPortionSize * bufferPortionIndex, LockFlags.None); - OnNewFrame(currentSample); - } - } - } - catch (Exception ex) - { - if (AudioSourceError != null) - AudioSourceError(this, new AudioSourceErrorEventArgs(ex.Message)); - else throw; - } - finally - { - if (captureBuffer != null) - { - captureBuffer.Stop(); - captureBuffer.Dispose(); - } - - if (captureDevice != null) - captureDevice.Dispose(); - - for (int i = 0; i < notifications.Length; i++) - if (notifications[i].WaitHandle != null) - notifications[i].WaitHandle.Close(); - } - } - - - - /// - /// Notifies client about new block of frames. - /// - /// - /// New frame's audio. - /// - protected void OnNewFrame(Array frame) - { - framesReceived++; - - if ((!stopEvent.WaitOne(0, true)) && (NewFrame != null)) - { - NewFrame(this, new NewFrameEventArgs(Signal.FromArray(frame, sampleRate, sampleFormat))); - } - } - - - /// - /// Gets whether this audio source supports seeking. - /// - /// - public bool CanSeek - { - get { return false; } - } - - /// - /// This source does not support seeking. - /// - /// - public void Seek(int frameIndex) - { - throw new NotSupportedException(); - } - - /// - /// Gets or sets the desired sample rate for this capturing device. - /// - /// - public int SampleRate - { - get { return this.sampleRate; } - set { this.sampleRate = value; } - } - - - #region IDisposable members - /// - /// Releases unmanaged resources and performs other cleanup operations before the - /// is reclaimed by garbage collection. - /// - /// - ~AudioCaptureDevice() - { - Dispose(false); - } - - /// - /// Performs application-defined tasks associated with - /// freeing, releasing, or resetting unmanaged resources. - /// - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// Releases unmanaged and - optionally - managed resources - /// - /// - /// - /// true to release both managed and unmanaged resources; - /// false to release only unmanaged resources. - /// - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - // free managed resources - if (stopEvent != null) - { - stopEvent.Close(); - stopEvent = null; - } - } - } - #endregion - - } + /// + /// Audio source for local audio capture device (i.e. a microphone). + /// + /// + /// + /// This audio source captures audio data + /// obtained from a local audio capture device such as the microphone. The audio + /// is captured using DirectSound through SlimDX. + /// + /// For instructions on how to list capture devices, please see + /// the documentation page. + /// + /// + /// + /// Sample usage: + /// + /// + /// // Create default capture device + /// AudioCaptureDevice source = new AudioCaptureDevice(); + /// + /// // Specify capturing options + /// source.DesiredFrameSize = 4096; + /// source.SampleRate = 22050; + /// + /// // Specify the callback function which will be + /// // called once a sample is completely available + /// source.NewFrame += source_NewFrame; + /// + /// // Start capturing + /// source.Start(); + /// + /// // ... + /// + /// // The callback function should determine what + /// // should be done with the samples being caught + /// private void source_NewFrame(object sender, NewFrameEventArgs eventArgs) + /// { + /// // Read current frame... + /// Signal s = eventArgs.Signal; + /// + /// // Process/play/record it + /// // ... + /// } + /// + /// + /// For more details regarding usage, please check one of + /// the Audio sample applications accompanying the framework. + /// + /// + /// + /// + /// + public class AudioCaptureDevice : IAudioSource, IDisposable + { + + // moniker string of audio capture device + private Guid device = Guid.Empty; + private string sourceName; + + // user data associated with the audio source + private object userData = null; + + // received frames count + private int framesReceived; + + // received byte count + private int bytesReceived; + + // specifies desired capture frame size + private int desiredCaptureSize = 4096; + + // specifies the sample rate used in the source + private int sampleRate = 44100; + + private Thread thread = null; + private ManualResetEvent stopEvent = null; + + private SampleFormat sampleFormat = SampleFormat.Format32BitIeeeFloat; + + /// + /// New frame event. + /// + /// + /// Notifies clients about new available frame from audio source. + /// + /// Since audio source may have multiple clients, each client is responsible for + /// making a copy (cloning) of the passed audio frame, because the audio source disposes its + /// own original copy after notifying of clients. + /// + /// + public event EventHandler NewFrame; + + + /// + /// Audio source error event. + /// + /// + /// This event is used to notify clients about any type of errors occurred in + /// audio source object, for example internal exceptions. + /// + public event EventHandler AudioSourceError; + + /// + /// Audio source. + /// + /// + /// Audio source is represented by Guid of audio capture device. + /// + public virtual string Source + { + get { return sourceName; } + set { sourceName = value; } + } + + /// + /// Gets or sets the sample format used by the device. + /// + /// + public SampleFormat Format + { + get { return sampleFormat; } + set { sampleFormat = value; } + } + + /// + /// Gets or sets the desired frame size. + /// + public int DesiredFrameSize + { + get { return desiredCaptureSize; } + set { desiredCaptureSize = value; } + } + + /// + /// Gets the number of audio channels captured by + /// the device. Currently, only a single channel + /// is supported. + /// + /// + public int Channels + { + get { return 1; } + set { } + } + + /// + /// Received frames count. + /// + /// + /// Number of frames the audio source provided from the moment of the last + /// access to the property. + /// + /// + public int FramesReceived + { + get + { + int frames = framesReceived; + framesReceived = 0; + return frames; + } + } + + /// + /// Received bytes count. + /// + /// + /// Number of bytes the audio source provided from the moment of the last + /// access to the property. + /// + /// + public int BytesReceived + { + get + { + int bytes = bytesReceived; + bytesReceived = 0; + return bytes; + } + } + + /// + /// User data. + /// + /// + /// The property allows to associate user data with audio source object. + /// + public object UserData + { + get { return userData; } + set { userData = value; } + } + + /// + /// State of the audio source. + /// + /// + /// Current state of audio source object - running or not. + /// + public bool IsRunning + { + get + { + if (thread != null) + { + // check thread status + if (thread.Join(0) == false) + return true; + + // the thread is not running, free resources + Free(); + } + return false; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public AudioCaptureDevice() + { + this.device = Guid.Empty; + this.sourceName = "Default capture device"; + } + + /// + /// Initializes a new instance of the class. + /// + /// + public AudioCaptureDevice(AudioDeviceInfo device) + { + this.device = device.Guid; + this.sourceName = device.Description; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Global identifier of the audio capture device. + /// + public AudioCaptureDevice(Guid device) + { + this.device = device; + this.sourceName = device.ToString(); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Global identifier of the audio capture device. + /// The device name or description string. + /// + public AudioCaptureDevice(Guid device, string name) + { + this.device = device; + this.sourceName = name; + } + + /// + /// Start audio source. + /// + /// + /// Starts audio source and return execution to caller. audio source + /// object creates background thread and notifies about new frames with the + /// help of event. + /// + public void Start() + { + if (thread == null) + { + framesReceived = 0; + bytesReceived = 0; + + // create events + stopEvent = new ManualResetEvent(false); + + // create and start new thread + thread = new Thread(WorkerThread); + thread.Name = device.ToString(); + thread.Start(); + } + } + + /// + /// Signals audio source to stop its work. + /// + /// + /// Signals audio source to stop its background thread, stop to + /// provide new frames and free resources. + /// + public void SignalToStop() + { + // stop thread + if (thread != null) + { + // signal to stop + stopEvent.Set(); + } + } + + /// + /// Wait for audio source has stopped. + /// + /// + /// Waits for source stopping after it was signaled to stop using + /// method. + /// + public void WaitForStop() + { + if (thread != null) + { + // wait for thread stop + thread.Join(); + + Free(); + } + } + + /// + /// Stop audio source. + /// + /// + /// Stops audio source aborting its thread. + /// + /// Since the method aborts background thread, its usage is highly not preferred + /// and should be done only if there are no other options. The correct way of stopping camera + /// is signaling it stop and then + /// waiting for background thread's completion. + /// + /// + public void Stop() + { + if (this.IsRunning) + { + thread.Abort(); + WaitForStop(); + } + } + + /// + /// Free resource. + /// + /// + private void Free() + { + thread = null; + + // release events + stopEvent.Close(); + stopEvent = null; + } + + + + /// + /// Worker thread. + /// + /// + private void WorkerThread() + { + // Get the selected capture device + DirectSoundCapture captureDevice = new DirectSoundCapture(device); + + + // Set the capture format + var bitsPerSample = Signal.GetSampleSize(sampleFormat); + WaveFormat format = WaveFormat.CreateCustomFormat(sampleFormat.ToWaveFormat(), sampleRate, 1, + sampleRate * bitsPerSample / 8, bitsPerSample / 8, bitsPerSample); + + // Setup the capture buffer + CaptureBufferDescription captureBufferDescription = new CaptureBufferDescription(); + captureBufferDescription.Format = format; + captureBufferDescription.BufferBytes = 2 * desiredCaptureSize * format.BlockAlign; + captureBufferDescription.Flags |= CaptureBufferCapabilitiesFlags.WaveMapped; + captureBufferDescription.Flags &= ~CaptureBufferCapabilitiesFlags.ControlEffects; + + CaptureBuffer captureBuffer = null; + NotificationPosition[] notifications = new NotificationPosition[2]; + + try + { + captureBuffer = new CaptureBuffer(captureDevice, captureBufferDescription); + + // Setup the notification positions + int bufferPortionSize = captureBuffer.Capabilities.BufferBytes / 2; + notifications[0] = new NotificationPosition(); + notifications[0].Offset = bufferPortionSize - 1; + notifications[0].WaitHandle = new AutoResetEvent(false); + notifications[1] = new NotificationPosition(); + notifications[1].Offset = bufferPortionSize - 1 + bufferPortionSize; + notifications[1].WaitHandle = new AutoResetEvent(false); + captureBuffer.SetNotificationPositions(notifications); + + // Make a copy of the wait handles + WaitHandle[] waitHandles = new WaitHandle[notifications.Length]; + for (int i = 0; i < notifications.Length; i++) + waitHandles[i] = notifications[i].WaitHandle; + + + + // Start capturing + captureBuffer.Start(true); + + + if (sampleFormat == SampleFormat.Format32BitIeeeFloat) + { + float[] currentSample = new float[desiredCaptureSize]; + + while (!stopEvent.WaitOne(0, true)) + { + int bufferPortionIndex = WaitHandle.WaitAny(waitHandles); + captureBuffer.Read(currentSample, 0, currentSample.Length, bufferPortionSize * bufferPortionIndex, LockFlags.None); + OnNewFrame(currentSample); + } + } + else if (sampleFormat == SampleFormat.Format16Bit) + { + short[] currentSample = new short[desiredCaptureSize]; + + while (!stopEvent.WaitOne(0, true)) + { + int bufferPortionIndex = WaitHandle.WaitAny(waitHandles); + captureBuffer.Read(currentSample, 0, currentSample.Length, bufferPortionSize * bufferPortionIndex, LockFlags.None); + OnNewFrame(currentSample); + } + } + } + catch (Exception ex) + { + if (AudioSourceError != null) + AudioSourceError(this, new AudioSourceErrorEventArgs(ex.Message)); + else throw; + } + finally + { + if (captureBuffer != null) + { + captureBuffer.Stop(); + captureBuffer.Dispose(); + } + + if (captureDevice != null) + captureDevice.Dispose(); + + for (int i = 0; i < notifications.Length; i++) + if (notifications[i].WaitHandle != null) + notifications[i].WaitHandle.Close(); + } + } + + + + /// + /// Notifies client about new block of frames. + /// + /// + /// New frame's audio. + /// + protected void OnNewFrame(Array frame) + { + framesReceived++; + + if ((!stopEvent.WaitOne(0, true)) && (NewFrame != null)) + { + NewFrame(this, new NewFrameEventArgs(Signal.FromArray(frame, sampleRate, sampleFormat))); + } + } + + + /// + /// Gets whether this audio source supports seeking. + /// + /// + public bool CanSeek + { + get { return false; } + } + + /// + /// This source does not support seeking. + /// + /// + public void Seek(int frameIndex) + { + throw new NotSupportedException(); + } + + /// + /// Gets or sets the desired sample rate for this capturing device. + /// + /// + public int SampleRate + { + get { return this.sampleRate; } + set { this.sampleRate = value; } + } + + + #region IDisposable members + /// + /// Releases unmanaged resources and performs other cleanup operations before the + /// is reclaimed by garbage collection. + /// + /// + ~AudioCaptureDevice() + { + Dispose(false); + } + + /// + /// Performs application-defined tasks associated with + /// freeing, releasing, or resetting unmanaged resources. + /// + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Releases unmanaged and - optionally - managed resources + /// + /// + /// + /// true to release both managed and unmanaged resources; + /// false to release only unmanaged resources. + /// + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + // free managed resources + if (stopEvent != null) + { + stopEvent.Close(); + stopEvent = null; + } + } + } + #endregion + + } } \ No newline at end of file diff --git a/Sources/Accord.DirectSound/AudioDeviceCollection.cs b/Sources/Accord.Audio.DirectSound/AudioDeviceCollection.cs similarity index 100% rename from Sources/Accord.DirectSound/AudioDeviceCollection.cs rename to Sources/Accord.Audio.DirectSound/AudioDeviceCollection.cs diff --git a/Sources/Accord.DirectSound/AudioDeviceInfo.cs b/Sources/Accord.Audio.DirectSound/AudioDeviceInfo.cs similarity index 100% rename from Sources/Accord.DirectSound/AudioDeviceInfo.cs rename to Sources/Accord.Audio.DirectSound/AudioDeviceInfo.cs diff --git a/Sources/Accord.DirectSound/AudioOutputDevice.cs b/Sources/Accord.Audio.DirectSound/AudioOutputDevice.cs similarity index 97% rename from Sources/Accord.DirectSound/AudioOutputDevice.cs rename to Sources/Accord.Audio.DirectSound/AudioOutputDevice.cs index 21cdcafdc..6587b9ca0 100644 --- a/Sources/Accord.DirectSound/AudioOutputDevice.cs +++ b/Sources/Accord.Audio.DirectSound/AudioOutputDevice.cs @@ -1,520 +1,516 @@ -// Accord Audio Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.DirectSound +// Accord Audio Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.DirectSound { using Accord.Audio; using SharpDX.DirectSound; using SharpDX.Multimedia; using System; using System.Collections.Generic; - using System.Threading; - - /// - /// Audio output device for local audio playback (i.e. a sound card port). - /// - /// - /// - /// This audio output sends audio data - /// to a local output device such as a sound card. The audio is reproduced - /// using DirectSound through SlimDX. - /// - /// For instructions on how to list output devices, please see - /// the documentation page. - /// - /// - /// - /// Sample usage: - /// - /// - /// // To create an audio output device, DirectSound requires a handle to - /// // the parent form of the application (or other application handle). In - /// // Windows.Forms, this could be achieved by providing the Handle property - /// // of the currently displayed form. - /// - /// int sampleRate = 22000; // 22kHz - /// int channels = 2; // stereo - /// - /// // Create the audio output device with the desired values - /// AudioOutputDevice output = new AudioOutputDevice(Handle, sampleRate, channels); - /// - /// // The output device works at real time, and as such, forms a queue of audio - /// // samples to be played (more specifically, a buffer). When this buffer starts - /// // to get empty, the output will ask the application for more samples of it - /// // should stop playing. To ask for more samples, the output device will fire - /// // an event which should be handled by the user: - /// - /// output.NewFrameRequested += output_NewFrameRequested; - /// - /// // It is also possible to configure an event to be fired when the device - /// // has stopped playing and when it has just started playing a frame. Those - /// // are mainly used for reporting status to GUI controls. - /// output.Stopped += output_Stopped; - /// output.FramePlayingStarted += output_FramePlayingStarted; - /// - /// // Start playing - /// output.Play(); - /// - /// - /// For more details regarding usage, please check one of - /// the Audio sample applications accompanying the framework. - /// - /// - /// - /// - /// - public class AudioOutputDevice : IAudioOutput, IDisposable - { - private IntPtr owner; - private Guid device = Guid.Empty; - private SecondarySoundBuffer buffer; - private int samplingRate; - private int bufferSize; - private int channels; - - private Thread thread; - - private NotificationPosition[] notifications; - private WaitHandle[] waitHandles; - - private bool isPlaying; - private bool stop; - - int firstHalfBufferIndex; - int secondHalfBufferIndex; - - /// - /// Gets a value indicating whether this instance is playing audio. - /// - /// - /// - /// true if this instance is running; otherwise, false. - /// - /// - public bool IsRunning - { - get { return isPlaying; } - } - - /// - /// Gets the sampling rate for the current output device. - /// - /// - public int SamplingRate - { - get { return samplingRate; } - } - - /// - /// Gets the number of channels for the current output device. - /// - /// - public int Channels - { - get { return channels; } - } - - /// - /// Gets the parent owner form for the device. - /// - /// - public IntPtr Owner - { - get { return owner; } - } - - /// - /// Audio output. - /// - /// - /// Audio output is represented by Guid of audio output device. - /// - public virtual string Output - { - get { return device.ToString(); } - set { device = new Guid(value); } - } - - /// - /// Raised when a frame starts playing. - /// - /// - public event EventHandler FramePlayingStarted; - - /// - /// Raised when a frame starts playing. - /// - /// - public event EventHandler NewFrameRequested; - - /// - /// Indicates all frames have been played and the audio finished. - /// - /// - public event EventHandler Stopped; - - /// - /// Audio output error event. - /// - /// - /// This event is used to notify clients about any type of errors occurred in - /// audio output object, for example internal exceptions. - /// - public event EventHandler AudioOutputError; - - /// - /// Constructs a new Audio Output Device. - /// - /// - /// The owner window handle. - /// The sampling rate of the device. - /// The number of channels of the device. - /// - public AudioOutputDevice(IntPtr owner, int samplingRate, int channels) - : this(Guid.Empty, owner, samplingRate, channels) { } - - /// - /// Constructs a new Audio Output Device. - /// - /// - /// Global identifier of the audio output device. - /// The owner window handle. - /// The sampling rate of the device. - /// The number of channels of the device. - /// - public AudioOutputDevice(Guid device, IntPtr owner, int samplingRate, int channels) - { - this.owner = owner; - this.samplingRate = samplingRate; - this.channels = channels; - this.device = device; - - DirectSound ds = new DirectSound(device); - ds.SetCooperativeLevel(owner, CooperativeLevel.Priority); - - - // Set the output format - WaveFormat waveFormat = WaveFormat.CreateIeeeFloatWaveFormat(samplingRate, channels); - bufferSize = 8 * waveFormat.AverageBytesPerSecond; - - - // Setup the secondary buffer - SoundBufferDescription desc2 = new SoundBufferDescription(); - desc2.Flags = - BufferFlags.GlobalFocus | - BufferFlags.ControlPositionNotify | - BufferFlags.GetCurrentPosition2; - desc2.BufferBytes = bufferSize; - desc2.Format = waveFormat; - - buffer = new SecondarySoundBuffer(ds, desc2); - - - var list = new List(); - int numberOfPositions = 32; - - // Set notification for buffer percentiles - for (int i = 0; i < numberOfPositions; i++) - { - list.Add(new NotificationPosition() - { - WaitHandle = new AutoResetEvent(false), - Offset = i * bufferSize / numberOfPositions + 1, - }); - } - - // Set notification for end of buffer - list.Add(new NotificationPosition() - { - Offset = bufferSize - 1, - WaitHandle = new AutoResetEvent(false) - }); - - firstHalfBufferIndex = numberOfPositions / 2; - secondHalfBufferIndex = numberOfPositions; - - notifications = list.ToArray(); - - System.Diagnostics.Debug.Assert(notifications[firstHalfBufferIndex].Offset == bufferSize / 2 + 1); - System.Diagnostics.Debug.Assert(notifications[secondHalfBufferIndex].Offset == bufferSize - 1); - - // Make a copy of the wait handles - waitHandles = new WaitHandle[notifications.Length]; - for (int i = 0; i < notifications.Length; i++) - waitHandles[i] = notifications[i].WaitHandle; - - // Store all notification positions - buffer.SetNotificationPositions(notifications); - } - - - /// - /// Starts playing the current buffer. - /// - /// - public void Play(float[] samples) - { - if (isPlaying) return; - - // Start playing and exit. - buffer.Write(samples, 0, LockFlags.None); - - new Thread(() => - { - OnFramePlayingStarted(new PlayFrameEventArgs(0, samples.Length)); - - buffer.Play(0, PlayFlags.None); - - waitHandles[secondHalfBufferIndex].WaitOne(); - - OnStopped(EventArgs.Empty); - - }).Start(); - } - - /// - /// Starts playing the current buffer. - /// - /// - public void Play() - { - if (thread == null) - { - // check source - if (device == Guid.Empty) - throw new ArgumentException("Audio output is not specified"); - - isPlaying = true; - - // create events - stop = false; - - // create and start new thread - thread = new Thread(WorkerThread); - thread.Start(); - } - } - - /// - /// Worker thread. - /// - /// - private void WorkerThread() - { - int samples = bufferSize / sizeof(float); - - try - { - - // The first write should fill the entire buffer. - var request = new NewFrameRequestedEventArgs(samples); - NewFrameRequested.Invoke(this, request); - - buffer.Write(request.Buffer, 0, LockFlags.None); - - // The buffer starts playing. - buffer.Play(0, PlayFlags.Looping); - - int framesPlayed = request.FrameIndex; - int lastNotificationLocation = 0; - bool requestedToStop = false; - - while (!stop) - { - int positionIndex = WaitHandle.WaitAny(waitHandles); - - if (stop) break; - - - if (positionIndex == firstHalfBufferIndex || - positionIndex == secondHalfBufferIndex) - { - if (requestedToStop) break; - - // When the first half of the buffer has finished - // playing and we have just started playing the - // second half, we will write the next samples in - // the first half of the buffer again. - - // When the second half of the buffer has finished - // playing, the first half of the buffer will - // start playing again (since this is a circular - // buffer). At this time, we can write the next - // samples in the second half of the buffer. - - request.Frames = samples / 2; - NewFrameRequested(this, request); - requestedToStop = request.Stop; - - int offset = (positionIndex == firstHalfBufferIndex) ? 0 : bufferSize / 2; - - buffer.Write(request.Buffer, 0, request.Frames, offset, LockFlags.None); - } - - if (positionIndex != secondHalfBufferIndex) - { - // Notify progress - int currentBufferLocation = notifications[positionIndex].Offset; - - if (lastNotificationLocation >= currentBufferLocation) - lastNotificationLocation = -(bufferSize - lastNotificationLocation); - - int delta = (currentBufferLocation - lastNotificationLocation); - - framesPlayed += delta / sizeof(float); - - lastNotificationLocation = currentBufferLocation; - - OnFramePlayingStarted(new PlayFrameEventArgs(framesPlayed, delta)); - } - } - } - catch (Exception ex) - { - if (AudioOutputError != null) - AudioOutputError(this, new AudioOutputErrorEventArgs(ex.Message)); - else throw; - } - finally - { - buffer.Stop(); - - OnStopped(EventArgs.Empty); - } - } - - private void OnFramePlayingStarted(PlayFrameEventArgs e) - { - isPlaying = true; - - if (FramePlayingStarted != null) - FramePlayingStarted(this, e); - } - - private void OnStopped(EventArgs e) - { - isPlaying = false; - - if (Stopped != null) - Stopped(this, e); - } - - /// - /// Stops playing the current buffer. - /// - /// - public void Stop() - { - if (this.IsRunning) - { - if (thread != null) - thread.Abort(); - WaitForStop(); - } - } - - /// - /// Signals audio output to stop its work. - /// - /// - /// Signals audio output to stop its background thread, stop to - /// ask for new frames and free resources. - /// - public void SignalToStop() - { - // stop thread - if (thread != null) - { - stop = true; - - for (int i = 0; i < notifications.Length; i++) - (notifications[i].WaitHandle as AutoResetEvent).Set(); - } - } - - /// - /// Wait for audio output has stopped. - /// - /// - /// Waits for output stopping after it was signaled to stop using - /// method. - /// - public void WaitForStop() - { - if (thread != null) - { - for (int i = 0; i < notifications.Length; i++) - (notifications[i].WaitHandle as AutoResetEvent).Set(); - - // wait for thread stop - thread.Join(); - - thread = null; - } - } - - #region IDisposable members - /// - /// Performs application-defined tasks associated with - /// freeing, releasing, or resetting unmanaged resources. - /// - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// Releases unmanaged and - optionally - managed resources - /// - /// - /// true to release both managed and unmanaged - /// resources; false to release only unmanaged resources. - /// - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - // free managed resources - if (buffer != null) - { - buffer.Dispose(); - buffer = null; - } - } - } - - /// - /// Releases unmanaged resources and performs other cleanup operations before the - /// is reclaimed by garbage collection. - /// - /// - ~AudioOutputDevice() - { - Dispose(false); - } - #endregion - - - } -} + using System.Threading; + + /// + /// Audio output device for local audio playback (i.e. a sound card port). + /// + /// + /// + /// This audio output sends audio data + /// to a local output device such as a sound card. The audio is reproduced + /// using DirectSound through SlimDX. + /// + /// For instructions on how to list output devices, please see + /// the documentation page. + /// + /// + /// + /// Sample usage: + /// + /// + /// // To create an audio output device, DirectSound requires a handle to + /// // the parent form of the application (or other application handle). In + /// // Windows.Forms, this could be achieved by providing the Handle property + /// // of the currently displayed form. + /// + /// int sampleRate = 22000; // 22kHz + /// int channels = 2; // stereo + /// + /// // Create the audio output device with the desired values + /// AudioOutputDevice output = new AudioOutputDevice(Handle, sampleRate, channels); + /// + /// // The output device works at real time, and as such, forms a queue of audio + /// // samples to be played (more specifically, a buffer). When this buffer starts + /// // to get empty, the output will ask the application for more samples of it + /// // should stop playing. To ask for more samples, the output device will fire + /// // an event which should be handled by the user: + /// + /// output.NewFrameRequested += output_NewFrameRequested; + /// + /// // It is also possible to configure an event to be fired when the device + /// // has stopped playing and when it has just started playing a frame. Those + /// // are mainly used for reporting status to GUI controls. + /// output.Stopped += output_Stopped; + /// output.FramePlayingStarted += output_FramePlayingStarted; + /// + /// // Start playing + /// output.Play(); + /// + /// + /// For more details regarding usage, please check one of + /// the Audio sample applications accompanying the framework. + /// + /// + /// + /// + /// + public class AudioOutputDevice : IAudioOutput, IDisposable + { + private IntPtr owner; + private Guid device = Guid.Empty; + private SecondarySoundBuffer buffer; + private int samplingRate; + private int bufferSize; + private int channels; + + private Thread thread; + + private NotificationPosition[] notifications; + private WaitHandle[] waitHandles; + + private bool isPlaying; + private bool stop; + + int firstHalfBufferIndex; + int secondHalfBufferIndex; + + /// + /// Gets a value indicating whether this instance is playing audio. + /// + /// + /// + /// true if this instance is running; otherwise, false. + /// + /// + public bool IsRunning + { + get { return isPlaying; } + } + + /// + /// Gets the sampling rate for the current output device. + /// + /// + public int SamplingRate + { + get { return samplingRate; } + } + + /// + /// Gets the number of channels for the current output device. + /// + /// + public int Channels + { + get { return channels; } + } + + /// + /// Gets the parent owner form for the device. + /// + /// + public IntPtr Owner + { + get { return owner; } + } + + /// + /// Audio output. + /// + /// + /// Audio output is represented by Guid of audio output device. + /// + public virtual string Output + { + get { return device.ToString(); } + set { device = new Guid(value); } + } + + /// + /// Raised when a frame starts playing. + /// + /// + public event EventHandler FramePlayingStarted; + + /// + /// Raised when a frame starts playing. + /// + /// + public event EventHandler NewFrameRequested; + + /// + /// Indicates all frames have been played and the audio finished. + /// + /// + public event EventHandler Stopped; + + /// + /// Audio output error event. + /// + /// + /// This event is used to notify clients about any type of errors occurred in + /// audio output object, for example internal exceptions. + /// + public event EventHandler AudioOutputError; + + /// + /// Constructs a new Audio Output Device. + /// + /// + /// The owner window handle. + /// The sampling rate of the device. + /// The number of channels of the device. + /// + public AudioOutputDevice(IntPtr owner, int samplingRate, int channels) + : this(Guid.Empty, owner, samplingRate, channels) { } + + /// + /// Constructs a new Audio Output Device. + /// + /// + /// Global identifier of the audio output device. + /// The owner window handle. + /// The sampling rate of the device. + /// The number of channels of the device. + /// + public AudioOutputDevice(Guid device, IntPtr owner, int samplingRate, int channels) + { + this.owner = owner; + this.samplingRate = samplingRate; + this.channels = channels; + this.device = device; + + DirectSound ds = new DirectSound(device); + ds.SetCooperativeLevel(owner, CooperativeLevel.Priority); + + + // Set the output format + WaveFormat waveFormat = WaveFormat.CreateIeeeFloatWaveFormat(samplingRate, channels); + bufferSize = 8 * waveFormat.AverageBytesPerSecond; + + + // Setup the secondary buffer + SoundBufferDescription desc2 = new SoundBufferDescription(); + desc2.Flags = + BufferFlags.GlobalFocus | + BufferFlags.ControlPositionNotify | + BufferFlags.GetCurrentPosition2; + desc2.BufferBytes = bufferSize; + desc2.Format = waveFormat; + + buffer = new SecondarySoundBuffer(ds, desc2); + + + var list = new List(); + int numberOfPositions = 32; + + // Set notification for buffer percentiles + for (int i = 0; i < numberOfPositions; i++) + { + list.Add(new NotificationPosition() + { + WaitHandle = new AutoResetEvent(false), + Offset = i * bufferSize / numberOfPositions + 1, + }); + } + + // Set notification for end of buffer + list.Add(new NotificationPosition() + { + Offset = bufferSize - 1, + WaitHandle = new AutoResetEvent(false) + }); + + firstHalfBufferIndex = numberOfPositions / 2; + secondHalfBufferIndex = numberOfPositions; + + notifications = list.ToArray(); + + System.Diagnostics.Debug.Assert(notifications[firstHalfBufferIndex].Offset == bufferSize / 2 + 1); + System.Diagnostics.Debug.Assert(notifications[secondHalfBufferIndex].Offset == bufferSize - 1); + + // Make a copy of the wait handles + waitHandles = new WaitHandle[notifications.Length]; + for (int i = 0; i < notifications.Length; i++) + waitHandles[i] = notifications[i].WaitHandle; + + // Store all notification positions + buffer.SetNotificationPositions(notifications); + } + + + /// + /// Starts playing the current buffer. + /// + /// + public void Play(float[] samples) + { + if (isPlaying) return; + + // Start playing and exit. + buffer.Write(samples, 0, LockFlags.None); + + new Thread(() => + { + OnFramePlayingStarted(new PlayFrameEventArgs(0, samples.Length)); + + buffer.Play(0, PlayFlags.None); + + waitHandles[secondHalfBufferIndex].WaitOne(); + + OnStopped(EventArgs.Empty); + + }).Start(); + } + + /// + /// Starts playing the current buffer. + /// + /// + public void Play() + { + if (thread == null) + { + isPlaying = true; + + // create events + stop = false; + + // create and start new thread + thread = new Thread(WorkerThread); + thread.Start(); + } + } + + /// + /// Worker thread. + /// + /// + private void WorkerThread() + { + int samples = bufferSize / sizeof(float); + + try + { + + // The first write should fill the entire buffer. + var request = new NewFrameRequestedEventArgs(samples); + NewFrameRequested.Invoke(this, request); + + buffer.Write(request.Buffer, 0, LockFlags.None); + + // The buffer starts playing. + buffer.Play(0, PlayFlags.Looping); + + int framesPlayed = request.FrameIndex; + int lastNotificationLocation = 0; + bool requestedToStop = false; + + while (!stop) + { + int positionIndex = WaitHandle.WaitAny(waitHandles); + + if (stop) break; + + + if (positionIndex == firstHalfBufferIndex || + positionIndex == secondHalfBufferIndex) + { + if (requestedToStop) break; + + // When the first half of the buffer has finished + // playing and we have just started playing the + // second half, we will write the next samples in + // the first half of the buffer again. + + // When the second half of the buffer has finished + // playing, the first half of the buffer will + // start playing again (since this is a circular + // buffer). At this time, we can write the next + // samples in the second half of the buffer. + + request.Frames = samples / 2; + NewFrameRequested(this, request); + requestedToStop = request.Stop; + + int offset = (positionIndex == firstHalfBufferIndex) ? 0 : bufferSize / 2; + + buffer.Write(request.Buffer, 0, request.Frames, offset, LockFlags.None); + } + + if (positionIndex != secondHalfBufferIndex) + { + // Notify progress + int currentBufferLocation = notifications[positionIndex].Offset; + + if (lastNotificationLocation >= currentBufferLocation) + lastNotificationLocation = -(bufferSize - lastNotificationLocation); + + int delta = (currentBufferLocation - lastNotificationLocation); + + framesPlayed += delta / sizeof(float); + + lastNotificationLocation = currentBufferLocation; + + OnFramePlayingStarted(new PlayFrameEventArgs(framesPlayed, delta)); + } + } + } + catch (Exception ex) + { + if (AudioOutputError != null) + AudioOutputError(this, new AudioOutputErrorEventArgs(ex.Message)); + else throw; + } + finally + { + buffer.Stop(); + + OnStopped(EventArgs.Empty); + } + } + + private void OnFramePlayingStarted(PlayFrameEventArgs e) + { + isPlaying = true; + + if (FramePlayingStarted != null) + FramePlayingStarted(this, e); + } + + private void OnStopped(EventArgs e) + { + isPlaying = false; + + if (Stopped != null) + Stopped(this, e); + } + + /// + /// Stops playing the current buffer. + /// + /// + public void Stop() + { + if (this.IsRunning) + { + if (thread != null) + thread.Abort(); + WaitForStop(); + } + } + + /// + /// Signals audio output to stop its work. + /// + /// + /// Signals audio output to stop its background thread, stop to + /// ask for new frames and free resources. + /// + public void SignalToStop() + { + // stop thread + if (thread != null) + { + stop = true; + + for (int i = 0; i < notifications.Length; i++) + (notifications[i].WaitHandle as AutoResetEvent).Set(); + } + } + + /// + /// Wait for audio output has stopped. + /// + /// + /// Waits for output stopping after it was signaled to stop using + /// method. + /// + public void WaitForStop() + { + if (thread != null) + { + for (int i = 0; i < notifications.Length; i++) + (notifications[i].WaitHandle as AutoResetEvent).Set(); + + // wait for thread stop + thread.Join(); + + thread = null; + } + } + + #region IDisposable members + /// + /// Performs application-defined tasks associated with + /// freeing, releasing, or resetting unmanaged resources. + /// + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Releases unmanaged and - optionally - managed resources + /// + /// + /// true to release both managed and unmanaged + /// resources; false to release only unmanaged resources. + /// + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + // free managed resources + if (buffer != null) + { + buffer.Dispose(); + buffer = null; + } + } + } + + /// + /// Releases unmanaged resources and performs other cleanup operations before the + /// is reclaimed by garbage collection. + /// + /// + ~AudioOutputDevice() + { + Dispose(false); + } + #endregion + + + } +} diff --git a/Sources/Accord.Audio.Formats/Extensions.cs b/Sources/Accord.Audio.DirectSound/Extensions.cs similarity index 100% rename from Sources/Accord.Audio.Formats/Extensions.cs rename to Sources/Accord.Audio.DirectSound/Extensions.cs diff --git a/Sources/Accord.DirectSound/Properties/AssemblyInfo.cs b/Sources/Accord.Audio.DirectSound/Properties/AssemblyInfo.cs similarity index 91% rename from Sources/Accord.DirectSound/Properties/AssemblyInfo.cs rename to Sources/Accord.Audio.DirectSound/Properties/AssemblyInfo.cs index 2c10a6d2f..33788da53 100644 --- a/Sources/Accord.DirectSound/Properties/AssemblyInfo.cs +++ b/Sources/Accord.Audio.DirectSound/Properties/AssemblyInfo.cs @@ -4,7 +4,7 @@ // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("Accord.DirectSound")] +[assembly: AssemblyTitle("Accord.Audio.DirectSound")] [assembly: AssemblyDescription("Accord.NET - Direct Sound Library")] [assembly: AssemblyConfiguration("")] diff --git a/Sources/Accord.Audio.Formats/WaveDecoder.cs b/Sources/Accord.Audio.DirectSound/WaveDecoder.cs similarity index 100% rename from Sources/Accord.Audio.Formats/WaveDecoder.cs rename to Sources/Accord.Audio.DirectSound/WaveDecoder.cs diff --git a/Sources/Accord.Audio.Formats/WaveEncoder.cs b/Sources/Accord.Audio.DirectSound/WaveEncoder.cs similarity index 100% rename from Sources/Accord.Audio.Formats/WaveEncoder.cs rename to Sources/Accord.Audio.DirectSound/WaveEncoder.cs diff --git a/Sources/Accord.DirectSound/WaveFileAudioSource.cs b/Sources/Accord.Audio.DirectSound/WaveFileAudioSource.cs similarity index 100% rename from Sources/Accord.DirectSound/WaveFileAudioSource.cs rename to Sources/Accord.Audio.DirectSound/WaveFileAudioSource.cs diff --git a/Sources/Accord.Audio.Formats/Accord.Audio.Formats.cd b/Sources/Accord.Audio.Formats/Accord.Audio.Formats.cd deleted file mode 100644 index d2082a66b..0000000000 --- a/Sources/Accord.Audio.Formats/Accord.Audio.Formats.cd +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - - - - - AAAAAAAAAAAACAAAAAgBAEACAQBAAgAAAAAQAAAAEBA= - IAudioDecoder.cs - - - - - - - - - - - - BABAAAYAAAAOIIAgCCCAAABCAAAIggggAABYQACAEAE= - WaveDecoder.cs - - - - - - - - - - - - BABAAEYAABBGIIAAACGACABCAAAIAgggAAAYAACAEAE= - WaveEncoder.cs - - - - - - - AAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAQACAAAA= - IAudioDecoder.cs - - - - - - AAAAAAAAAABAIAAAAAAAAAAAAAAAAAAAAAAAAACAAAA= - IAudioEncoder.cs - - - - \ No newline at end of file diff --git a/Sources/Accord.Audio/Accord.Audio.csproj b/Sources/Accord.Audio/Accord.Audio.csproj index 4c5f2539c..436837c3b 100644 --- a/Sources/Accord.Audio/Accord.Audio.csproj +++ b/Sources/Accord.Audio/Accord.Audio.csproj @@ -27,56 +27,51 @@ v4.5 - bin\Debug\ Full False False True DEBUG;TRACE - ..\..\Debug\ + $(SolutionDir)..\Debug\ - ..\..\Release\net35 + $(SolutionDir)..\Release\net35 TRACE;CODE_ANALYSIS;NET35 v3.5 true - ..\..\Release\net35\Accord.Audio.XML - ..\..\Release\net35\Accord.Audio.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net35\Accord.Audio.XML + $(SolutionDir)..\Release\net35\Accord.Audio.dll.CodeAnalysisLog.xml - ..\..\Release\net40 + $(SolutionDir)..\Release\net40 TRACE;CODE_ANALYSIS;NET40 v4.0 - ..\..\Release\net40\Accord.Audio.XML - ..\..\Release\net40\Accord.Audio.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net40\Accord.Audio.XML + $(SolutionDir)..\Release\net40\Accord.Audio.dll.CodeAnalysisLog.xml - ..\..\Release\net45 + $(SolutionDir)..\Release\net45 TRACE;CODE_ANALYSIS;NET45 v4.5 - ..\..\Release\net45\Accord.Audio.XML - ..\..\Release\net45\Accord.Audio.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net45\Accord.Audio.XML + $(SolutionDir)..\Release\net45\Accord.Audio.dll.CodeAnalysisLog.xml - - ..\..\Externals\AForge.NET\AForge.dll - False - - - ..\..\Externals\AForge.NET\AForge.Math.dll - False - 3.5 + Properties\VersionInfo.cs + + + @@ -129,6 +124,10 @@ + + {a177a90c-8207-466a-af70-f2b8452a42ac} + Accord.Core + {F718E9A8-DB62-4785-8C49-4333A60D256A} Accord.Math diff --git a/Sources/Accord.Audio/ComplexFilters/CombFilter.cs b/Sources/Accord.Audio/ComplexFilters/CombFilter.cs index 5c8cadf6b..7ba8ba17f 100644 --- a/Sources/Accord.Audio/ComplexFilters/CombFilter.cs +++ b/Sources/Accord.Audio/ComplexFilters/CombFilter.cs @@ -24,7 +24,8 @@ namespace Accord.Audio.ComplexFilters { using Accord.Audio; using Accord.Audio.Generators; - using AForge.Math; + using AForge.Math; + using System.Numerics; /// /// Comb filter. @@ -121,12 +122,9 @@ protected override void ProcessFilter(ComplexSignal sourceData, ComplexSignal de Complex* dst = (Complex*)destinationData.Data.ToPointer(); Complex* comb = (Complex*)combSignal.Data.ToPointer(); - Complex d = new Complex(); - for (int i = 0; i < samples; i++, src++, dst++, comb++) { - d.Re = (src[0] * comb[0]).Magnitude; - *dst = d; + *dst = new Complex((src[0] * comb[0]).Magnitude, 0); } } } diff --git a/Sources/Accord.Audio/ComplexFilters/DifferentialRectificationFilter.cs b/Sources/Accord.Audio/ComplexFilters/DifferentialRectificationFilter.cs index 6ab52d019..08f180ac9 100644 --- a/Sources/Accord.Audio/ComplexFilters/DifferentialRectificationFilter.cs +++ b/Sources/Accord.Audio/ComplexFilters/DifferentialRectificationFilter.cs @@ -1,71 +1,64 @@ -// Accord Audio Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Audio.ComplexFilters -{ - using AForge.Math; - - /// - /// Differential Rectification filter. - /// - /// - public class DifferentialRectificationFilter : BaseComplexFilter - { - - - - /// - /// Constructs a new Differential Rectification filter. - /// - /// - public DifferentialRectificationFilter() - { - } - - /// - /// Processes the filter. - /// - /// - protected override void ProcessFilter(ComplexSignal sourceData, ComplexSignal destinationData) - { - int length = sourceData.Length; - - unsafe - { - Complex* src = (Complex*)sourceData.Data.ToPointer(); - Complex* dst = (Complex*)destinationData.Data.ToPointer(); - - Complex d = new Complex(); - - for (int i = 0; i < length - 1; i++, src++, dst++) - { - d.Re = src[i + 1].Re - src[i].Re; - - // Retain only if difference is positive - *dst = (d.Re > 0) ? d : Complex.Zero; - } - } - } - - - } -} +// Accord Audio Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Audio.ComplexFilters +{ + using AForge.Math; + using System.Numerics; + + /// + /// Differential Rectification filter. + /// + /// + public class DifferentialRectificationFilter : BaseComplexFilter + { + + /// + /// Constructs a new Differential Rectification filter. + /// + /// + public DifferentialRectificationFilter() + { + } + + /// + /// Processes the filter. + /// + /// + protected unsafe override void ProcessFilter(ComplexSignal sourceData, ComplexSignal destinationData) + { + int length = sourceData.Length; + + Complex* src = (Complex*)sourceData.Data.ToPointer(); + Complex* dst = (Complex*)destinationData.Data.ToPointer(); + + for (int i = 0; i < length - 1; i++, src++, dst++) + { + double re = src[i + 1].Real - src[i].Real; + + // Retain only if difference is positive + *dst = (re > 0) ? new Complex(re, 0) : Complex.Zero; + } + } + + } +} diff --git a/Sources/Accord.Audio/ComplexFilters/EnvelopeFilter.cs b/Sources/Accord.Audio/ComplexFilters/EnvelopeFilter.cs index f2cf1ab24..3c3cc5855 100644 --- a/Sources/Accord.Audio/ComplexFilters/EnvelopeFilter.cs +++ b/Sources/Accord.Audio/ComplexFilters/EnvelopeFilter.cs @@ -1,80 +1,76 @@ -// Accord Audio Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Audio.ComplexFilters -{ - using System; - using Accord.Audio; - using AForge.Math; - - /// - /// Hilbert transform based envelope detector. - /// - /// - /// - /// - /// This method works by creating the analytic signal of the input by - /// using a Hilbert transform. An analytic signal is a complex signal, - /// where the real part is the original signal and the imaginary part - /// is the Hilbert transform of the original signal. - /// - /// The complex envelope of a signal can be found by taking the absolute - /// (magnitude) value of the analytic signal. - /// - /// References: http://en.wikipedia.org/wiki/Hilbert_transform - /// - /// - /// - public class EnvelopeFilter : BaseComplexFilter - { - - /// - /// Constructs a new Envelope filter. - /// - public EnvelopeFilter() - { - } - - /// - /// Processes the filter. - /// - protected unsafe override void ProcessFilter(ComplexSignal sourceData, ComplexSignal destinationData) - { - if (sourceData.Status != ComplexSignalStatus.Analytic) - throw new ArgumentException("Signal must be in analytic form.", "sourceData"); - - int samples = sourceData.Samples; - - Complex d = new Complex(); - - Complex* src = (Complex*)sourceData.Data.ToPointer(); - Complex* dst = (Complex*)destinationData.Data.ToPointer(); - - for (int i = 0; i < samples; i++, src++, dst++) - { - d.Re = (*dst).Magnitude; - *dst = d; - } - } - - } -} +// Accord Audio Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Audio.ComplexFilters +{ + using System; + using Accord.Audio; + using AForge.Math; + using System.Numerics; + + /// + /// Hilbert transform based envelope detector. + /// + /// + /// + /// + /// This method works by creating the analytic signal of the input by + /// using a Hilbert transform. An analytic signal is a complex signal, + /// where the real part is the original signal and the imaginary part + /// is the Hilbert transform of the original signal. + /// + /// The complex envelope of a signal can be found by taking the absolute + /// (magnitude) value of the analytic signal. + /// + /// References: http://en.wikipedia.org/wiki/Hilbert_transform + /// + /// + /// + public class EnvelopeFilter : BaseComplexFilter + { + + /// + /// Constructs a new Envelope filter. + /// + public EnvelopeFilter() + { + } + + /// + /// Processes the filter. + /// + protected unsafe override void ProcessFilter(ComplexSignal sourceData, ComplexSignal destinationData) + { + if (sourceData.Status != ComplexSignalStatus.Analytic) + throw new ArgumentException("Signal must be in analytic form.", "sourceData"); + + int samples = sourceData.Samples; + + Complex* src = (Complex*)sourceData.Data.ToPointer(); + Complex* dst = (Complex*)destinationData.Data.ToPointer(); + + for (int i = 0; i < samples; i++, src++, dst++) + *dst = new Complex((*dst).Magnitude, 0); + } + + } +} diff --git a/Sources/Accord.Audio/Filters/WaveRectifier.cs b/Sources/Accord.Audio/Filters/WaveRectifier.cs index 3f7447990..2b60127aa 100644 --- a/Sources/Accord.Audio/Filters/WaveRectifier.cs +++ b/Sources/Accord.Audio/Filters/WaveRectifier.cs @@ -1,104 +1,102 @@ -// Accord Audio Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Audio.Filters -{ - using System.Collections.Generic; - using AForge.Math; - - /// - /// Wave Rectifier filter. - /// - /// - public class WaveRectifier : BaseFilter - { - - private Dictionary formatTranslations = new Dictionary(); - - /// - /// Format translations dictionary. - /// - /// - /// The format translations. - /// - /// - /// The dictionary defines which sample formats are supported for - /// source signals and which sample format will be used for resulting signal. - /// - /// - public override Dictionary FormatTranslations - { - get { return formatTranslations; } - } - - /// - /// Gets or sets whether half rectification should be performed. - /// - /// - public bool Half { get; set; } - - /// - /// Constructs a new Wave rectifier. - /// - /// - public WaveRectifier(bool halfRectificationOnly) - { - Half = halfRectificationOnly; - - formatTranslations[SampleFormat.Format128BitComplex] = SampleFormat.Format128BitComplex; - formatTranslations[SampleFormat.Format32BitIeeeFloat] = SampleFormat.Format32BitIeeeFloat; - } - - /// - /// Applies the filter to a signal. - /// - /// - protected unsafe override void ProcessFilter(Signal sourceData, Signal destinationData) - { - SampleFormat format = sourceData.SampleFormat; - int samples = sourceData.Samples; - - if (format == SampleFormat.Format32BitIeeeFloat) - { - float* src = (float*)sourceData.Data.ToPointer(); - float* dst = (float*)destinationData.Data.ToPointer(); - - for (int i = 0; i < samples; i++, dst++, src++) - *dst = System.Math.Abs(*src); - } - else if (format == SampleFormat.Format128BitComplex) - { - Complex* src = (Complex*)sourceData.Data.ToPointer(); - Complex* dst = (Complex*)destinationData.Data.ToPointer(); - - Complex c = new Complex(); - - for (int i = 0; i < samples; i++, dst++, src++) - { - c.Re = (*src).Magnitude; - *dst = c; - } - } - } - - } -} +// Accord Audio Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Audio.Filters +{ + using System.Collections.Generic; + using AForge.Math; + using System.Numerics; + + /// + /// Wave Rectifier filter. + /// + /// + public class WaveRectifier : BaseFilter + { + + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + /// + /// The format translations. + /// + /// + /// The dictionary defines which sample formats are supported for + /// source signals and which sample format will be used for resulting signal. + /// + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Gets or sets whether half rectification should be performed. + /// + /// + public bool Half { get; set; } + + /// + /// Constructs a new Wave rectifier. + /// + /// + public WaveRectifier(bool halfRectificationOnly) + { + Half = halfRectificationOnly; + + formatTranslations[SampleFormat.Format128BitComplex] = SampleFormat.Format128BitComplex; + formatTranslations[SampleFormat.Format32BitIeeeFloat] = SampleFormat.Format32BitIeeeFloat; + } + + /// + /// Applies the filter to a signal. + /// + /// + protected unsafe override void ProcessFilter(Signal sourceData, Signal destinationData) + { + SampleFormat format = sourceData.SampleFormat; + int samples = sourceData.Samples; + + if (format == SampleFormat.Format32BitIeeeFloat) + { + float* src = (float*)sourceData.Data.ToPointer(); + float* dst = (float*)destinationData.Data.ToPointer(); + + for (int i = 0; i < samples; i++, dst++, src++) + *dst = System.Math.Abs(*src); + } + else if (format == SampleFormat.Format128BitComplex) + { + Complex* src = (Complex*)sourceData.Data.ToPointer(); + Complex* dst = (Complex*)destinationData.Data.ToPointer(); + + for (int i = 0; i < samples; i++, dst++, src++) + { + *dst = new Complex((*src).Magnitude, 0); + } + } + } + + } +} diff --git a/Sources/Accord.Audio.Formats/FrameInfo.cs b/Sources/Accord.Audio/Formats/FrameInfo.cs similarity index 100% rename from Sources/Accord.Audio.Formats/FrameInfo.cs rename to Sources/Accord.Audio/Formats/FrameInfo.cs diff --git a/Sources/Accord.Audio.Formats/IAudioDecoder.cs b/Sources/Accord.Audio/Formats/IAudioDecoder.cs similarity index 100% rename from Sources/Accord.Audio.Formats/IAudioDecoder.cs rename to Sources/Accord.Audio/Formats/IAudioDecoder.cs diff --git a/Sources/Accord.Audio.Formats/IAudioEncoder.cs b/Sources/Accord.Audio/Formats/IAudioEncoder.cs similarity index 100% rename from Sources/Accord.Audio.Formats/IAudioEncoder.cs rename to Sources/Accord.Audio/Formats/IAudioEncoder.cs diff --git a/Sources/Accord.Audio/Generators/CosineGenerator.cs b/Sources/Accord.Audio/Generators/CosineGenerator.cs index 53bf60430..fdb18b0cc 100644 --- a/Sources/Accord.Audio/Generators/CosineGenerator.cs +++ b/Sources/Accord.Audio/Generators/CosineGenerator.cs @@ -95,27 +95,30 @@ private void init(double frequency, double amplitude, int samplingRate) /// Generates a signal. /// /// - public unsafe Signal Generate(int samples) + public Signal Generate(int samples) { - Signal signal = new Signal(Channels, samples, SamplingRate, Format); - - if (Format == SampleFormat.Format32BitIeeeFloat) - { - var dst = (float*)signal.Data.ToPointer(); - for (int i = 0; i < signal.Samples; i++) - for (int c = 0; c < signal.Channels; c++, dst++) - *dst = (float)(Amplitude * Math.Cos(i * theta)); - } - else if (Format == SampleFormat.Format64BitIeeeFloat) - { - var dst = (double*)signal.Data.ToPointer(); - for (int i = 0; i < signal.Samples; i++) - for (int c = 0; c < signal.Channels; c++, dst++) - *dst = (Amplitude * Math.Cos(i * theta)); - } - else + Signal signal = new Signal(Channels, samples, SamplingRate, Format); + + unsafe { - throw new UnsupportedSampleFormatException("Sample format is not supported by the filter."); + if (Format == SampleFormat.Format32BitIeeeFloat) + { + var dst = (float*)signal.Data.ToPointer(); + for (int i = 0; i < signal.Samples; i++) + for (int c = 0; c < signal.Channels; c++, dst++) + *dst = (float)(Amplitude * Math.Cos(i * theta)); + } + else if (Format == SampleFormat.Format64BitIeeeFloat) + { + var dst = (double*)signal.Data.ToPointer(); + for (int i = 0; i < signal.Samples; i++) + for (int c = 0; c < signal.Channels; c++, dst++) + *dst = (Amplitude * Math.Cos(i * theta)); + } + else + { + throw new UnsupportedSampleFormatException("Sample format is not supported by the filter."); + } } return signal; diff --git a/Sources/Accord.Audio/Generators/ImpulseGenerator.cs b/Sources/Accord.Audio/Generators/ImpulseGenerator.cs index a2ab58145..1a11ce70c 100644 --- a/Sources/Accord.Audio/Generators/ImpulseGenerator.cs +++ b/Sources/Accord.Audio/Generators/ImpulseGenerator.cs @@ -23,7 +23,8 @@ namespace Accord.Audio.Generators { using System; - using AForge.Math; + using AForge.Math; + using System.Numerics; /// /// Impulse train signal generator. @@ -97,47 +98,50 @@ public ImpulseGenerator(int bpm, int pulses, int sampleRate, SampleFormat format /// Generates the given number of samples. /// /// - public unsafe Signal Generate(int samples) + public Signal Generate(int samples) { Signal signal = new Signal(Channels, samples, SamplingRate, Format); int ti = interval * Channels; - if (Format == SampleFormat.Format32BitIeeeFloat) + unsafe { - for (int c = 0; c < Channels; c++) + if (Format == SampleFormat.Format32BitIeeeFloat) { - float* dst = (float*)signal.Data.ToPointer() + c; - - for (int i = 0; i < samples; i += interval, dst += ti) + for (int c = 0; c < Channels; c++) { - *dst = ampMax; + float* dst = (float*)signal.Data.ToPointer() + c; + + for (int i = 0; i < samples; i += interval, dst += ti) + { + *dst = ampMax; - if (Pulses > 0 && i / interval >= Pulses) - break; + if (Pulses > 0 && i / interval >= Pulses) + break; + } } } - } - else if (Format == SampleFormat.Format128BitComplex) - { - Complex campMax = new Complex(ampMax, 0); - - for (int c = 0; c < Channels; c++) + else if (Format == SampleFormat.Format128BitComplex) { - Complex* dst = (Complex*)signal.Data.ToPointer() + c; + Complex campMax = new Complex(ampMax, 0); - for (int i = 0; i < samples; i += interval, dst += ti) + for (int c = 0; c < Channels; c++) { - *dst = campMax; + Complex* dst = (Complex*)signal.Data.ToPointer() + c; - if (Pulses > 0 && i / interval >= Pulses) - break; + for (int i = 0; i < samples; i += interval, dst += ti) + { + *dst = campMax; + + if (Pulses > 0 && i / interval >= Pulses) + break; + } } } - } - else - { - throw new UnsupportedSampleFormatException("Sample format is not supported by the filter."); + else + { + throw new UnsupportedSampleFormatException("Sample format is not supported by the filter."); + } } return signal; diff --git a/Sources/Accord.Audio/Generators/SignalGenerator.cs b/Sources/Accord.Audio/Generators/SignalGenerator.cs index 1612fc491..dea62012e 100644 --- a/Sources/Accord.Audio/Generators/SignalGenerator.cs +++ b/Sources/Accord.Audio/Generators/SignalGenerator.cs @@ -72,27 +72,30 @@ public SignalGenerator(Func func) /// Generates a signal. /// /// - public unsafe Signal Generate(int samples) + public Signal Generate(int samples) { Signal signal = new Signal(Channels, samples, SamplingRate, Format); - if (Format == SampleFormat.Format32BitIeeeFloat) + unsafe { - var dst = (float*)signal.Data.ToPointer(); - for (int i = 0; i < signal.Samples; i++) - for (int c = 0; c < signal.Channels; c++, dst++) - *dst = (float)(Function(i)); - } - else if (Format == SampleFormat.Format64BitIeeeFloat) - { - var dst = (double*)signal.Data.ToPointer(); - for (int i = 0; i < signal.Samples; i++) - for (int c = 0; c < signal.Channels; c++, dst++) - *dst = (double)(Function(i)); - } - else - { - throw new UnsupportedSampleFormatException("Sample format is not supported by the filter."); + if (Format == SampleFormat.Format32BitIeeeFloat) + { + var dst = (float*)signal.Data.ToPointer(); + for (int i = 0; i < signal.Samples; i++) + for (int c = 0; c < signal.Channels; c++, dst++) + *dst = (float)(Function(i)); + } + else if (Format == SampleFormat.Format64BitIeeeFloat) + { + var dst = (double*)signal.Data.ToPointer(); + for (int i = 0; i < signal.Samples; i++) + for (int c = 0; c < signal.Channels; c++, dst++) + *dst = (double)(Function(i)); + } + else + { + throw new UnsupportedSampleFormatException("Sample format is not supported by the filter."); + } } return signal; diff --git a/Sources/Accord.Audio/Generators/SineGenerator.cs b/Sources/Accord.Audio/Generators/SineGenerator.cs index d67157a14..b9219a7e7 100644 --- a/Sources/Accord.Audio/Generators/SineGenerator.cs +++ b/Sources/Accord.Audio/Generators/SineGenerator.cs @@ -95,27 +95,30 @@ private void init(double frequency, double amplitude, int samplingRate) /// Generates a signal. /// /// - public unsafe Signal Generate(int samples) + public Signal Generate(int samples) { Signal signal = new Signal(Channels, samples, SamplingRate, Format); - if (Format == SampleFormat.Format32BitIeeeFloat) + unsafe { - var dst = (float*)signal.Data.ToPointer(); - for (int i = 0; i < signal.Samples; i++) - for (int c = 0; c < signal.Channels; c++, dst++) - *dst = (float)(Amplitude * Math.Sin(i * theta)); - } - else if (Format == SampleFormat.Format64BitIeeeFloat) - { - var dst = (double*)signal.Data.ToPointer(); - for (int i = 0; i < signal.Samples; i++) - for (int c = 0; c < signal.Channels; c++, dst++) - *dst = (Amplitude * Math.Sin(i * theta)); - } - else - { - throw new UnsupportedSampleFormatException("Sample format is not supported by the filter."); + if (Format == SampleFormat.Format32BitIeeeFloat) + { + var dst = (float*)signal.Data.ToPointer(); + for (int i = 0; i < signal.Samples; i++) + for (int c = 0; c < signal.Channels; c++, dst++) + *dst = (float)(Amplitude * Math.Sin(i * theta)); + } + else if (Format == SampleFormat.Format64BitIeeeFloat) + { + var dst = (double*)signal.Data.ToPointer(); + for (int i = 0; i < signal.Samples; i++) + for (int c = 0; c < signal.Channels; c++, dst++) + *dst = (Amplitude * Math.Sin(i * theta)); + } + else + { + throw new UnsupportedSampleFormatException("Sample format is not supported by the filter."); + } } return signal; diff --git a/Sources/Accord.Audio/Signals/ComplexSignal.cs b/Sources/Accord.Audio/Signals/ComplexSignal.cs index ee9845b0e..79f9588aa 100644 --- a/Sources/Accord.Audio/Signals/ComplexSignal.cs +++ b/Sources/Accord.Audio/Signals/ComplexSignal.cs @@ -1,464 +1,465 @@ -// Accord Audio Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Audio -{ - using System; - using System.Runtime.InteropServices; - using Accord.Math; - using AForge.Math; - - /// - /// Complex signal status. - /// - /// - public enum ComplexSignalStatus - { - /// - /// Normal state. - /// - /// - Normal, - - /// - /// Analytic form (Hilbert Transformed) - /// - /// - Analytic, - - /// - /// Frequency form (Fourier transformed) - /// - /// - FourierTransformed - } - - /// - /// Complex audio signal. - /// - /// - /// - /// - /// A complex discrete-time signal is any complex-valued function - /// of integers. This class is used to keep audio signals represented - /// in complex numbers so they are suitable to be converted to and - /// from the frequency domain in either analytic or Fourier transformed - /// forms. - /// - /// - /// References: - /// - /// - /// Wikipedia, The Free Encyclopedia. Analytics Signal. Available on: - /// http://en.wikipedia.org/wiki/Analytic_signal - /// - /// - /// - /// - /// - /// If your signal has a length that is a power of two, you can use the - /// following code directly to create your audio signal and obtain its - /// spectrogram: - /// - /// - /// // Create complex audio signal - /// ComplexSignal complexSignal = ComplexSignal.FromSignal( signal ); - /// - /// // Do forward Fourier transformation - /// complexSignal.ForwardFourierTransform( ); - /// - /// // Generate spectrogram - /// complexSignal.ToBitmap(512,512); - /// - /// - /// - /// However, if your signal is too lengthy, or if your signal is not yet in a power of - /// two size, you can use a temporal window to slice your signal into smaller cuts, as - /// shown below. In the example, an audio file is being read and its contents are being - /// decoded and stored into a Signal object. Afterwards, an audio window is being used - /// to cut the signal into smaller, power-of-two size signals which can then be transformed - /// into the frequency (Fourier) domain. - /// - /// - /// string fileName = "audio.wav"; - /// - /// WaveDecoder sourceDecoder = new WaveDecoder(fileName); - /// - /// // Decode the file and store into a signal - /// Signal sourceSignal = sourceDecoder.Decode(); - /// - /// // Create Hamming window so that signal will fit into power of 2: - /// RaisedCosineWindow window = RaisedCosineWindow.Hamming(1024); - /// - /// // Splits the source signal by walking each 512 samples, then creating - /// // a 1024 sample window. Note that this will result in overlapped windows. - /// Signal[] windows = sourceSignal.Split(window, 512); - /// - /// // You might need to import Accord.Math in order to call this: - /// ComplexSignal[] complex = windows.Apply(ComplexSignal.FromSignal); - /// - /// // Forward to the Fourier domain - /// complex.ForwardFourierTransform(); - /// - /// - /// - /// - public class ComplexSignal : Signal - { - - private ComplexSignalStatus status = ComplexSignalStatus.Normal; - - - /// - /// Gets the status of the signal - Fourier transformed, - /// Hilbert transformed (analytic) or real. - /// - /// - public ComplexSignalStatus Status - { - get { return status; } - } - - - - /// - /// Constructs a new Complex Signal - /// - /// - public ComplexSignal(byte[] data, int channels, int length, int sampleRate) - : this(data, channels, length, sampleRate, ComplexSignalStatus.Normal) - { - } - - /// - /// Constructs a new Complex Signal - /// - /// - public ComplexSignal(byte[] data, int channels, int length, int sampleRate, ComplexSignalStatus status) - : base(data, channels, length, sampleRate, SampleFormat.Format128BitComplex) - { - this.status = status; - } - - /// - /// Constructs a new Complex Signal - /// - /// - public ComplexSignal(int channels, int length, int sampleRate) - : base(channels, length, sampleRate, SampleFormat.Format128BitComplex) - { - } - - - - /// - /// Converts the complex signal to a complex array. - /// - /// - public Complex[,] ToArray() - { - Complex[,] array = new Complex[Length, Channels]; - - GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned); - IntPtr pointer = handle.AddrOfPinnedObject(); - Marshal.Copy(RawData, 0, pointer, array.Length * Marshal.SizeOf(typeof(Complex))); - handle.Free(); - - return array; - } - - /// - /// Extracts a channel from the signal. - /// - /// - public Complex[] GetChannel(int channel) - { - Complex[] array = new Complex[Length]; - int channels = Channels; - int length = Length; - - unsafe - { - fixed (Complex* ptrArray = array) - { - var src = (Complex*)Data + channel; - var dst = ptrArray; - - for (int i = 0; i < length; i++, src += channels, dst++) - *dst = *src; - } - } - - return array; - } - - /// - /// Copies an array of samples to a signal's channel. - /// - /// - private void SetChannel(int channel, Complex[] samples) - { - int channels = Channels; - int length = Length; - - unsafe - { - fixed (Complex* ptrArray = samples) - { - var dst = (Complex*)Data + channel; - var src = ptrArray; - - for (int i = 0; i < length; i++, src++, dst += channels) - *dst = *src; - } - } - } - - - #region Transforms - /// - /// Applies forward fast Fourier transformation to the complex signal. - /// - /// - public void ForwardFourierTransform() - { - if (status == ComplexSignalStatus.Normal || - status == ComplexSignalStatus.Analytic) - { - for (int i = 0; i < Channels; i++) - { - Complex[] channel = GetChannel(i); - FourierTransform.FFT(channel, FourierTransform.Direction.Forward); - SetChannel(i, channel); - } - status = ComplexSignalStatus.FourierTransformed; - } - } - - /// - /// Applies backward fast Fourier transformation to the complex signal. - /// - /// - public void BackwardFourierTransform() - { - if (status == ComplexSignalStatus.FourierTransformed) - { - for (int i = 0; i < Channels; i++) - { - Complex[] channel = GetChannel(i); - FourierTransform.FFT(channel, FourierTransform.Direction.Backward); - SetChannel(i, channel); - } - status = ComplexSignalStatus.Normal; - } - } - - /// - /// Applies forward Hilbert transformation to the complex signal. - /// - public void ForwardHilbertTransform() - { - if (status == ComplexSignalStatus.Normal) - { - for (int c = 0; c < Channels; c++) - { - Complex[] channel = GetChannel(c); - HilbertTransform.FHT(channel, FourierTransform.Direction.Forward); - SetChannel(c, channel); - } - status = ComplexSignalStatus.Analytic; - } - } - - /// - /// Applies backward Hilbert transformation to the complex signal. - /// - public void BackwardHilbertTransform() - { - if (status == ComplexSignalStatus.Analytic) - { - for (int c = 0; c < Channels; c++) - { - Complex[] channel = GetChannel(c); - HilbertTransform.FHT(channel, FourierTransform.Direction.Backward); - SetChannel(c, channel); - } - status = ComplexSignalStatus.Normal; - } - } - #endregion - - - - #region Named constructors - /// - /// Create multichannel complex signal from floating-point matrix. - /// - /// - /// Source multichannel float array (matrix). - /// - /// Returns an instance of complex signal. - /// - public static ComplexSignal FromSignal(Signal signal) - { - if (signal.SampleFormat == SampleFormat.Format32BitIeeeFloat) - { - float[] buffer = new float[signal.Samples]; - Marshal.Copy(signal.Data, buffer, 0, buffer.Length); - - float[,] data = new float[signal.Length, signal.Channels]; - Buffer.BlockCopy(buffer, 0, data, 0, signal.Samples * sizeof(float)); - - return FromArray(data, signal.SampleRate); - } - else if (signal.SampleFormat == SampleFormat.Format128BitComplex) - { - return new ComplexSignal(signal.RawData, signal.Channels, - signal.Length, signal.SampleRate); - } - else - { - throw new NotSupportedException(); - } - } - - /// - /// Create multichannel complex signal from floating-point matrix. - /// - /// - /// Source multichannel float array (matrix). - /// Sampling rate for the signal. - /// - /// Returns an instance of complex signal. - /// - public static ComplexSignal FromArray(float[,] array, int sampleRate) - { - int samples = array.GetLength(0); - int channels = array.GetLength(1); - - // check signal size - if (!AForge.Math.Tools.IsPowerOf2(samples)) - { - throw new InvalidSignalPropertiesException("Signals length should be a power of 2."); - } - - Complex[,] data = new Complex[samples, channels]; - for (int i = 0; i < samples; i++) - for (int j = 0; j < channels; j++) - data[i, j] = new Complex(array[i, j], 0); - - byte[] buffer = new byte[data.Length * Marshal.SizeOf(typeof(Complex))]; - - GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); - Marshal.Copy(handle.AddrOfPinnedObject(), buffer, 0, buffer.Length); - handle.Free(); - - return new ComplexSignal(buffer, channels, samples, sampleRate); - } - - - /// - /// Create complex signal from complex array. - /// - /// - /// Source complex array. - /// Sample rate of the signal. - /// - /// Returns an instance of complex signal. - /// - public static ComplexSignal FromArray(Complex[,] signal, int sampleRate) - { - return ComplexSignal.FromArray(signal, sampleRate, ComplexSignalStatus.Normal); - } - - /// - /// Create complex signal from complex array. - /// - /// - /// Source complex array. - /// Sample rate of the signal. - /// Status of the signal. - /// - /// Returns an instance of complex signal. - /// - public static ComplexSignal FromArray(Complex[,] array, int sampleRate, ComplexSignalStatus status) - { - int samples = array.GetLength(0); - int channels = array.GetLength(1); - - // check signal size - if (!AForge.Math.Tools.IsPowerOf2(samples)) - { - throw new InvalidSignalPropertiesException("Signals length should be a power of 2."); - } - - - byte[] buffer = new byte[array.Length * Marshal.SizeOf(typeof(Complex))]; - - GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned); - Marshal.Copy(handle.AddrOfPinnedObject(), buffer, 0, buffer.Length); - handle.Free(); - - return new ComplexSignal(buffer, channels, samples, sampleRate, status); - } - - #endregion - - - #region Static methods - - /// - /// Combines a set of windows into one full signal. - /// - public static ComplexSignal Combine(params ComplexSignal[] signals) - { - // Compute common data - int length = 0; - int nchannels = signals[0].Channels; - int sampleRate = signals[0].SampleRate; - - // Compute final length - for (int i = 0; i < signals.Length; i++) - { - length += signals[i].Length; - } - - // create channels - ComplexSignal result = new ComplexSignal(nchannels, length, sampleRate); - - int pos = 0; - foreach (ComplexSignal signal in signals) - { - Buffer.BlockCopy(signal.RawData, 0, result.RawData, pos, result.RawData.Length); - pos += signal.RawData.Length; - } - - return result; - } - - #endregion - - - - } -} - +// Accord Audio Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Audio +{ + using System; + using System.Runtime.InteropServices; + using Accord.Math; + using AForge.Math; + using System.Numerics; + + /// + /// Complex signal status. + /// + /// + public enum ComplexSignalStatus + { + /// + /// Normal state. + /// + /// + Normal, + + /// + /// Analytic form (Hilbert Transformed) + /// + /// + Analytic, + + /// + /// Frequency form (Fourier transformed) + /// + /// + FourierTransformed + } + + /// + /// Complex audio signal. + /// + /// + /// + /// + /// A complex discrete-time signal is any complex-valued function + /// of integers. This class is used to keep audio signals represented + /// in complex numbers so they are suitable to be converted to and + /// from the frequency domain in either analytic or Fourier transformed + /// forms. + /// + /// + /// References: + /// + /// + /// Wikipedia, The Free Encyclopedia. Analytics Signal. Available on: + /// http://en.wikipedia.org/wiki/Analytic_signal + /// + /// + /// + /// + /// + /// If your signal has a length that is a power of two, you can use the + /// following code directly to create your audio signal and obtain its + /// spectrogram: + /// + /// + /// // Create complex audio signal + /// ComplexSignal complexSignal = ComplexSignal.FromSignal( signal ); + /// + /// // Do forward Fourier transformation + /// complexSignal.ForwardFourierTransform( ); + /// + /// // Generate spectrogram + /// complexSignal.ToBitmap(512,512); + /// + /// + /// + /// However, if your signal is too lengthy, or if your signal is not yet in a power of + /// two size, you can use a temporal window to slice your signal into smaller cuts, as + /// shown below. In the example, an audio file is being read and its contents are being + /// decoded and stored into a Signal object. Afterwards, an audio window is being used + /// to cut the signal into smaller, power-of-two size signals which can then be transformed + /// into the frequency (Fourier) domain. + /// + /// + /// string fileName = "audio.wav"; + /// + /// WaveDecoder sourceDecoder = new WaveDecoder(fileName); + /// + /// // Decode the file and store into a signal + /// Signal sourceSignal = sourceDecoder.Decode(); + /// + /// // Create Hamming window so that signal will fit into power of 2: + /// RaisedCosineWindow window = RaisedCosineWindow.Hamming(1024); + /// + /// // Splits the source signal by walking each 512 samples, then creating + /// // a 1024 sample window. Note that this will result in overlapped windows. + /// Signal[] windows = sourceSignal.Split(window, 512); + /// + /// // You might need to import Accord.Math in order to call this: + /// ComplexSignal[] complex = windows.Apply(ComplexSignal.FromSignal); + /// + /// // Forward to the Fourier domain + /// complex.ForwardFourierTransform(); + /// + /// + /// + /// + public class ComplexSignal : Signal + { + + private ComplexSignalStatus status = ComplexSignalStatus.Normal; + + + /// + /// Gets the status of the signal - Fourier transformed, + /// Hilbert transformed (analytic) or real. + /// + /// + public ComplexSignalStatus Status + { + get { return status; } + } + + + + /// + /// Constructs a new Complex Signal + /// + /// + public ComplexSignal(byte[] data, int channels, int length, int sampleRate) + : this(data, channels, length, sampleRate, ComplexSignalStatus.Normal) + { + } + + /// + /// Constructs a new Complex Signal + /// + /// + public ComplexSignal(byte[] data, int channels, int length, int sampleRate, ComplexSignalStatus status) + : base(data, channels, length, sampleRate, SampleFormat.Format128BitComplex) + { + this.status = status; + } + + /// + /// Constructs a new Complex Signal + /// + /// + public ComplexSignal(int channels, int length, int sampleRate) + : base(channels, length, sampleRate, SampleFormat.Format128BitComplex) + { + } + + + + /// + /// Converts the complex signal to a complex array. + /// + /// + public Complex[,] ToArray() + { + Complex[,] array = new Complex[Length, Channels]; + + GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned); + IntPtr pointer = handle.AddrOfPinnedObject(); + Marshal.Copy(RawData, 0, pointer, array.Length * Marshal.SizeOf(typeof(Complex))); + handle.Free(); + + return array; + } + + /// + /// Extracts a channel from the signal. + /// + /// + public Complex[] GetChannel(int channel) + { + Complex[] array = new Complex[Length]; + int channels = Channels; + int length = Length; + + unsafe + { + fixed (Complex* ptrArray = array) + { + var src = (Complex*)Data + channel; + var dst = ptrArray; + + for (int i = 0; i < length; i++, src += channels, dst++) + *dst = *src; + } + } + + return array; + } + + /// + /// Copies an array of samples to a signal's channel. + /// + /// + private void SetChannel(int channel, Complex[] samples) + { + int channels = Channels; + int length = Length; + + unsafe + { + fixed (Complex* ptrArray = samples) + { + var dst = (Complex*)Data + channel; + var src = ptrArray; + + for (int i = 0; i < length; i++, src++, dst += channels) + *dst = *src; + } + } + } + + + #region Transforms + /// + /// Applies forward fast Fourier transformation to the complex signal. + /// + /// + public void ForwardFourierTransform() + { + if (status == ComplexSignalStatus.Normal || + status == ComplexSignalStatus.Analytic) + { + for (int i = 0; i < Channels; i++) + { + Complex[] channel = GetChannel(i); + FourierTransform.FFT(channel, FourierTransform.Direction.Forward); + SetChannel(i, channel); + } + status = ComplexSignalStatus.FourierTransformed; + } + } + + /// + /// Applies backward fast Fourier transformation to the complex signal. + /// + /// + public void BackwardFourierTransform() + { + if (status == ComplexSignalStatus.FourierTransformed) + { + for (int i = 0; i < Channels; i++) + { + Complex[] channel = GetChannel(i); + FourierTransform.FFT(channel, FourierTransform.Direction.Backward); + SetChannel(i, channel); + } + status = ComplexSignalStatus.Normal; + } + } + + /// + /// Applies forward Hilbert transformation to the complex signal. + /// + public void ForwardHilbertTransform() + { + if (status == ComplexSignalStatus.Normal) + { + for (int c = 0; c < Channels; c++) + { + Complex[] channel = GetChannel(c); + HilbertTransform.FHT(channel, FourierTransform.Direction.Forward); + SetChannel(c, channel); + } + status = ComplexSignalStatus.Analytic; + } + } + + /// + /// Applies backward Hilbert transformation to the complex signal. + /// + public void BackwardHilbertTransform() + { + if (status == ComplexSignalStatus.Analytic) + { + for (int c = 0; c < Channels; c++) + { + Complex[] channel = GetChannel(c); + HilbertTransform.FHT(channel, FourierTransform.Direction.Backward); + SetChannel(c, channel); + } + status = ComplexSignalStatus.Normal; + } + } + #endregion + + + + #region Named constructors + /// + /// Create multichannel complex signal from floating-point matrix. + /// + /// + /// Source multichannel float array (matrix). + /// + /// Returns an instance of complex signal. + /// + public static ComplexSignal FromSignal(Signal signal) + { + if (signal.SampleFormat == SampleFormat.Format32BitIeeeFloat) + { + float[] buffer = new float[signal.Samples]; + Marshal.Copy(signal.Data, buffer, 0, buffer.Length); + + float[,] data = new float[signal.Length, signal.Channels]; + Buffer.BlockCopy(buffer, 0, data, 0, signal.Samples * sizeof(float)); + + return FromArray(data, signal.SampleRate); + } + else if (signal.SampleFormat == SampleFormat.Format128BitComplex) + { + return new ComplexSignal(signal.RawData, signal.Channels, + signal.Length, signal.SampleRate); + } + else + { + throw new NotSupportedException(); + } + } + + /// + /// Create multichannel complex signal from floating-point matrix. + /// + /// + /// Source multichannel float array (matrix). + /// Sampling rate for the signal. + /// + /// Returns an instance of complex signal. + /// + public static ComplexSignal FromArray(float[,] array, int sampleRate) + { + int samples = array.GetLength(0); + int channels = array.GetLength(1); + + // check signal size + if (!AForge.Math.Tools.IsPowerOf2(samples)) + { + throw new InvalidSignalPropertiesException("Signals length should be a power of 2."); + } + + Complex[,] data = new Complex[samples, channels]; + for (int i = 0; i < samples; i++) + for (int j = 0; j < channels; j++) + data[i, j] = new Complex(array[i, j], 0); + + byte[] buffer = new byte[data.Length * Marshal.SizeOf(typeof(Complex))]; + + GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); + Marshal.Copy(handle.AddrOfPinnedObject(), buffer, 0, buffer.Length); + handle.Free(); + + return new ComplexSignal(buffer, channels, samples, sampleRate); + } + + + /// + /// Create complex signal from complex array. + /// + /// + /// Source complex array. + /// Sample rate of the signal. + /// + /// Returns an instance of complex signal. + /// + public static ComplexSignal FromArray(Complex[,] signal, int sampleRate) + { + return ComplexSignal.FromArray(signal, sampleRate, ComplexSignalStatus.Normal); + } + + /// + /// Create complex signal from complex array. + /// + /// + /// Source complex array. + /// Sample rate of the signal. + /// Status of the signal. + /// + /// Returns an instance of complex signal. + /// + public static ComplexSignal FromArray(Complex[,] array, int sampleRate, ComplexSignalStatus status) + { + int samples = array.GetLength(0); + int channels = array.GetLength(1); + + // check signal size + if (!AForge.Math.Tools.IsPowerOf2(samples)) + { + throw new InvalidSignalPropertiesException("Signals length should be a power of 2."); + } + + + byte[] buffer = new byte[array.Length * Marshal.SizeOf(typeof(Complex))]; + + GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned); + Marshal.Copy(handle.AddrOfPinnedObject(), buffer, 0, buffer.Length); + handle.Free(); + + return new ComplexSignal(buffer, channels, samples, sampleRate, status); + } + + #endregion + + + #region Static methods + + /// + /// Combines a set of windows into one full signal. + /// + public static ComplexSignal Combine(params ComplexSignal[] signals) + { + // Compute common data + int length = 0; + int nchannels = signals[0].Channels; + int sampleRate = signals[0].SampleRate; + + // Compute final length + for (int i = 0; i < signals.Length; i++) + { + length += signals[i].Length; + } + + // create channels + ComplexSignal result = new ComplexSignal(nchannels, length, sampleRate); + + int pos = 0; + foreach (ComplexSignal signal in signals) + { + Buffer.BlockCopy(signal.RawData, 0, result.RawData, pos, result.RawData.Length); + pos += signal.RawData.Length; + } + + return result; + } + + #endregion + + + + } +} + diff --git a/Sources/Accord.Audio/Signals/Signal.cs b/Sources/Accord.Audio/Signals/Signal.cs index 70e3851a6..01a7f6d3a 100644 --- a/Sources/Accord.Audio/Signals/Signal.cs +++ b/Sources/Accord.Audio/Signals/Signal.cs @@ -1,593 +1,610 @@ -// Accord Audio Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Audio -{ - using System; - using System.Runtime.InteropServices; - using AForge.Math; - - /// - /// Specifies the format of each sample in a signal. - /// - /// - public enum SampleFormat - { - /// - /// Specifies the format is 8 bit, unsigned. - /// - /// - Format8BitUnsigned, - - /// - /// Specifies the format is 8 bit, signed. - /// - /// - Format8Bit, - - /// - /// Specifies the format is 16 bit, signed. - /// - /// - Format16Bit, - - /// - /// Specifies the format is 32 bit, signed. - /// - /// - Format32Bit, - - /// - /// Specifies the format is 32 bit, represented by - /// single-precision IEEE floating-point numbers. - /// - /// - Format32BitIeeeFloat, - - /// - /// Specifies the format is 64 bit, represented by - /// double-precision IEEE floating-point numbers. - /// - /// - Format64BitIeeeFloat, - - /// - /// Specifies the format is 128 bit, represented by - /// complex numbers with real and imaginary parts as - /// double-precision IEEE floating-point numbers. - /// - /// - Format128BitComplex, - } - - /// - /// Represents a discrete signal (measured in time). - /// - /// - /// - /// - /// A real discrete-time signal is defined as any real-valued - /// function of the integers. - /// - /// In signal processing, sampling is the reduction of a continuous - /// signal to a discrete signal. A common example is the conversion - /// of a sound wave (a continuous-time signal) to a sequence of samples - /// (a discrete-time signal). - /// - /// - /// A sample refers to a value or set of values at a point in time - /// and/or space. - /// - /// Sample usage: - /// - /// // create an empty audio signal - /// Signal signal = new Signal( channels, length, sampleRate, format ); - /// - /// - /// - /// float[,] data = - /// { - /// { 0.00f, 0.2f }, - /// { 0.32f, 0.1f }, - /// { 0.22f, 0.2f }, - /// { 0.12f, 0.42f }, - /// { -0.12f, 0.1f }, - /// { -0.22f, 0.2f }, - /// }; - /// - /// // or create an audio signal from an array of audio frames - /// Signal target = Signal.FromArray(data, sampleRate: 8000); - /// - /// - /// - /// For an example on how to decode a signal from a Wave file, please - /// take a look on the WaveDecoder and WaveFileAudioSource documentation. - /// - /// - /// - /// - public class Signal : IDisposable - { - private byte[] rawData; - private IntPtr ptrData; - private GCHandle handle; - - private SampleFormat format; - - private int channels; - private int sampleRate; - private int length; - - - - #region Properties - /// - /// Gets the sample format used by this signal. - /// - /// - /// The signal's sample format. - /// - public SampleFormat SampleFormat - { - get { return format; } - } - - /// - /// Gets the signal duration in milliseconds. - /// - /// - public int Duration - { - get { return DurationOfSamples(length, sampleRate); } - } - - /// - /// Gets the number of samples in each channel of this signal, - /// as known as the number of frames in the signal. - /// - /// - public int Length - { - get { return length; } - } - - /// - /// Gets the total number of samples in this signal. - /// - /// - public int Samples - { - get { return length * channels; } - } - - /// - /// Gets the number of samples per second for this signal. - /// - /// - public int SampleRate - { - get { return sampleRate; } - } - - /// - /// Gets the number of channels of this signal. - /// - /// - public int Channels - { - get { return channels; } - } - - /// - /// Gets the raw binary data representing the signal. - /// - /// - public byte[] RawData - { - get { return rawData; } - protected set { rawData = value; } - } - - /// - /// Gets a pointer to the first sample of the signal. - /// - /// - public IntPtr Data - { - get { return ptrData; } - protected set { ptrData = value; } - } - #endregion - - - - /// - /// Constructs a new signal. - /// - /// - /// The raw data for the signal. - /// The number of channels for the signal. - /// The length of the signal. - /// The sample format for the signal. - /// The sample date of the signal. - /// - public Signal(byte[] data, int channels, int length, int sampleRate, SampleFormat format) - { - init(data, channels, length, sampleRate, format); - } - - /// - /// Constructs a new Signal. - /// - /// - /// The number of channels for the signal. - /// The length of the signal. - /// The sample format for the signal. - /// The sample date of the signal. - /// - public Signal(int channels, int length, int sampleRate, SampleFormat format) - { - int sampleSize = GetSampleSize(format) / 8; - byte[] data = new byte[channels * length * sampleSize]; - - init(data, channels, length, sampleRate, format); - } - - private void init(byte[] data, int channels, int length, int sampleRate, SampleFormat format) +// Accord Audio Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Audio +{ + using System; + using System.Runtime.InteropServices; + using AForge.Math; + using System.Numerics; + + /// + /// Specifies the format of each sample in a signal. + /// + /// + public enum SampleFormat + { + /// + /// Specifies the format is 8 bit, unsigned. + /// + /// + Format8BitUnsigned, + + /// + /// Specifies the format is 8 bit, signed. + /// + /// + Format8Bit, + + /// + /// Specifies the format is 16 bit, signed. + /// + /// + Format16Bit, + + /// + /// Specifies the format is 32 bit, signed. + /// + /// + Format32Bit, + + /// + /// Specifies the format is 32 bit, represented by + /// single-precision IEEE floating-point numbers. + /// + /// + Format32BitIeeeFloat, + + /// + /// Specifies the format is 64 bit, represented by + /// double-precision IEEE floating-point numbers. + /// + /// + Format64BitIeeeFloat, + + /// + /// Specifies the format is 128 bit, represented by + /// complex numbers with real and imaginary parts as + /// double-precision IEEE floating-point numbers. + /// + /// + Format128BitComplex, + } + + /// + /// Represents a discrete signal (measured in time). + /// + /// + /// + /// + /// A real discrete-time signal is defined as any real-valued + /// function of the integers. + /// + /// In signal processing, sampling is the reduction of a continuous + /// signal to a discrete signal. A common example is the conversion + /// of a sound wave (a continuous-time signal) to a sequence of samples + /// (a discrete-time signal). + /// + /// + /// A sample refers to a value or set of values at a point in time + /// and/or space. + /// + /// Sample usage: + /// + /// // create an empty audio signal + /// Signal signal = new Signal( channels, length, sampleRate, format ); + /// + /// + /// + /// float[,] data = + /// { + /// { 0.00f, 0.2f }, + /// { 0.32f, 0.1f }, + /// { 0.22f, 0.2f }, + /// { 0.12f, 0.42f }, + /// { -0.12f, 0.1f }, + /// { -0.22f, 0.2f }, + /// }; + /// + /// // or create an audio signal from an array of audio frames + /// Signal target = Signal.FromArray(data, sampleRate: 8000); + /// + /// + /// + /// For an example on how to decode a signal from a Wave file, please + /// take a look on the WaveDecoder and WaveFileAudioSource documentation. + /// + /// + /// + /// + public class Signal : IDisposable + { + private byte[] rawData; + private IntPtr ptrData; + private GCHandle handle; + + private SampleFormat format; + + private int channels; + private int sampleRate; + private int length; + + + + #region Properties + /// + /// Gets the sample format used by this signal. + /// + /// + /// The signal's sample format. + /// + public SampleFormat SampleFormat + { + get { return format; } + } + + /// + /// Gets the signal duration in milliseconds. + /// + /// + public int Duration + { + get { return DurationOfSamples(length, sampleRate); } + } + + /// + /// Gets the number of samples in each channel of this signal, + /// as known as the number of frames in the signal. + /// + /// + public int Length + { + get { return length; } + } + + /// + /// Gets the total number of samples in this signal. + /// + /// + public int Samples + { + get { return length * channels; } + } + + /// + /// Gets the number of samples per second for this signal. + /// + /// + public int SampleRate + { + get { return sampleRate; } + } + + /// + /// Gets the number of channels of this signal. + /// + /// + public int Channels + { + get { return channels; } + } + + /// + /// Gets the raw binary data representing the signal. + /// + /// + public byte[] RawData + { + get { return rawData; } + protected set { rawData = value; } + } + + /// + /// Gets a pointer to the first sample of the signal. + /// + /// + public IntPtr Data + { + get { return ptrData; } + protected set { ptrData = value; } + } + #endregion + + + + /// + /// Constructs a new signal. + /// + /// + /// The raw data for the signal. + /// The number of channels for the signal. + /// The length of the signal. + /// The sample format for the signal. + /// The sample date of the signal. + /// + public Signal(byte[] data, int channels, int length, int sampleRate, SampleFormat format) + { + init(data, channels, length, sampleRate, format); + } + + /// + /// Constructs a new Signal. + /// + /// + /// The number of channels for the signal. + /// The length of the signal. + /// The sample format for the signal. + /// The sample date of the signal. + /// + public Signal(int channels, int length, int sampleRate, SampleFormat format) + { + int sampleSize = GetSampleSize(format) / 8; + byte[] data = new byte[channels * length * sampleSize]; + + init(data, channels, length, sampleRate, format); + } + + private void init(byte[] data, int channels, int length, int sampleRate, SampleFormat format) + { + this.handle = GCHandle.Alloc(data, GCHandleType.Pinned); + this.ptrData = handle.AddrOfPinnedObject(); + + this.rawData = data; + this.sampleRate = sampleRate; + this.format = format; + this.length = length; + this.channels = channels; + } + + + + /// + /// Computes the signal energy. + /// + /// + public double GetEnergy() { - this.handle = GCHandle.Alloc(data, GCHandleType.Pinned); - this.ptrData = handle.AddrOfPinnedObject(); - - this.rawData = data; - this.sampleRate = sampleRate; - this.format = format; - this.length = length; - this.channels = channels; - } - - - - /// - /// Computes the signal energy. - /// - /// - public unsafe double GetEnergy() - { - double e = 0, v; - - if (format != SampleFormat.Format128BitComplex) - { - // Iterate over all samples and compute energy - float* src = (float*)this.ptrData.ToPointer(); - for (int i = 0; i < this.Samples; i++, src++) + double e = 0, v; + + unsafe + { + if (format != SampleFormat.Format128BitComplex) { - v = (*src); - e += v * v; + // Iterate over all samples and compute energy + float* src = (float*)this.ptrData.ToPointer(); + for (int i = 0; i < this.Samples; i++, src++) + { + v = (*src); + e += v * v; + } } - } - else - { - // Iterate over all samples and compute energy - Complex* src = (Complex*)this.Data.ToPointer(); - for (int i = 0; i < this.Samples; i++, src++) - e += (*src).SquaredMagnitude; + else + { + // Iterate over all samples and compute energy + Complex* src = (Complex*)this.Data.ToPointer(); + for (int i = 0; i < this.Samples; i++, src++) + { + double m = (*src).Magnitude; + e += m * m; + } + } } return e; - } - - /// - /// Gets the value of the specified sample in the Signal. - /// - /// - /// The channel's index of the sample to set. - /// The position of the sample to set. - /// A floating-point value ranging from -1 to 1 representing - /// the retrieved value. Conversion is performed automatically from - /// the underlying signal sample format if supported. - /// - public unsafe float GetSample(int channel, int position) - { - void* ptr = ptrData.ToPointer(); - int pos = position * Channels + channel; - - switch (format) - { - case SampleFormat.Format32BitIeeeFloat: - return ((float*)ptr)[pos]; - - default: - throw new NotSupportedException(); - } - } - - /// - /// Sets the value of the specified sample in the Signal. - /// - /// - /// The channel's index of the sample to set. - /// The position of the sample to set. - /// A floating-point value ranging from -1 to 1 - /// specifying the value to set. Conversion will be done automatically - /// to the underlying signal sample format if supported. - /// - public unsafe void SetSample(int channel, int position, float value) - { - void* ptr = ptrData.ToPointer(); - int pos = position * Channels + channel; - - switch (format) - { - case SampleFormat.Format32BitIeeeFloat: - ((float*)ptr)[pos] = value; - break; - - default: - throw new NotSupportedException(); - } - } - - /// - /// Creates a new Signal from a float array. - /// - /// - public static Signal FromArray(Array signal, int sampleRate, - SampleFormat format = SampleFormat.Format32BitIeeeFloat) - { - int channels = signal.Rank == 1 ? 1 : signal.GetLength(1); - return FromArray(signal, channels, sampleRate, format); - } - - /// - /// Converts this signal to a ComplexSignal object. - /// - /// - public ComplexSignal ToComplex() - { - if (format == SampleFormat.Format128BitComplex) - return new ComplexSignal(rawData, channels, length, sampleRate); - else return ComplexSignal.FromSignal(this); - } - - /// - /// Creates a new Signal from a float array. - /// - /// - public static Signal FromArray(Array signal, int channels, int sampleRate, - SampleFormat format = SampleFormat.Format32BitIeeeFloat) - { - return FromArray(signal, signal.Length, channels, sampleRate, format); - } - - /// - /// Creates a new Signal from a float array. - /// - /// - public static Signal FromArray(Array signal, int size, int channels, int sampleRate, - SampleFormat format = SampleFormat.Format32BitIeeeFloat) - { - int sampleSize = GetSampleSize(format) / 8; - - byte[] buffer = new byte[size * sampleSize]; - Buffer.BlockCopy(signal, 0, buffer, 0, buffer.Length); - int samples = size / channels; - - return new Signal(buffer, channels, samples, sampleRate, format); - } - - /// - /// Copies this signal to a given array. - /// - /// - public void CopyTo(Array array) - { - Buffer.BlockCopy(rawData, 0, array, 0, array.Length); - } - - /// - /// Copies this signal to a given array. - /// - /// - public void CopyTo(float[] array) - { - if (format == Audio.SampleFormat.Format32BitIeeeFloat) - { - Buffer.BlockCopy(rawData, 0, array, 0, rawData.Length); - } - - else if (format == Audio.SampleFormat.Format16Bit) - { - short[] source = new short[Samples]; - Buffer.BlockCopy(rawData, 0, source, 0, rawData.Length); - SampleConverter.Convert(source, array); - } - - else - { - throw new InvalidOperationException(); - } - } - - /// - /// Copies this signal to a given array. - /// - /// - public void CopyTo(double[] array) - { - if (format == Audio.SampleFormat.Format64BitIeeeFloat) - { - Buffer.BlockCopy(rawData, 0, array, 0, rawData.Length); - } - else if (format == Audio.SampleFormat.Format32BitIeeeFloat) - { - float[] source = new float[Samples]; - Buffer.BlockCopy(rawData, 0, source, 0, rawData.Length); - for (int i = 0; i < source.Length; i++) - array[i] = source[i]; - } - else if (format == Audio.SampleFormat.Format16Bit) - { - short[] source = new short[Samples]; - Buffer.BlockCopy(rawData, 0, source, 0, rawData.Length); - SampleConverter.Convert(source, array); - } - - else - { - throw new InvalidOperationException(); - } - } - - /// - /// Converts this signal into a array of floating-point samples. - /// - /// - /// An array of single-precision floating-point samples. - /// - public float[] ToFloat() - { - float[] array = new float[Samples]; - CopyTo(array); - return array; - } - - /// - /// Converts this signal into a array of floating-point samples. - /// - /// - /// An array of single-precision floating-point samples. - /// - public double[] ToDouble() - { - double[] array = new double[Samples]; - CopyTo(array); - return array; - } - - - #region Static auxiliary methods - - /// - /// Gets the number of samples contained in a signal of given duration and sampling rate. - /// - /// - public static int NumberOfSamples(int duration, int samplingRate) - { - return (duration / 1000) * samplingRate; - } - - /// - /// Gets the duration of each sample in a signal with the given number of samples and sampling rate. - /// - /// - public static int DurationOfSamples(int samples, int samplingRate) - { - return (int)(samples / (double)samplingRate * 1000.0); - } - - /// - /// Gets the size (in bits) of a sample format. - /// - /// - public static int GetSampleSize(SampleFormat format) - { - switch (format) - { - case SampleFormat.Format128BitComplex: - return 128; - - case SampleFormat.Format32BitIeeeFloat: - return 32; - - case SampleFormat.Format64BitIeeeFloat: - return 64; - - case SampleFormat.Format16Bit: - return 16; - - case SampleFormat.Format32Bit: - return 32; - - case SampleFormat.Format8Bit: - return 8; - - case SampleFormat.Format8BitUnsigned: - return 8; - - default: - throw new NotSupportedException(); - } - } - #endregion - - - #region IDisposable Members - - /// - /// Performs application-defined tasks associated with freeing, - /// releasing, or resetting unmanaged resources. - /// - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// Releases unmanaged resources and performs other cleanup operations - /// before the is reclaimed by garbage collection. - /// - /// - ~Signal() - { - Dispose(false); - } - - /// - /// Releases unmanaged and - optionally - managed resources - /// - /// - /// true to release both managed - /// and unmanaged resources; false to release only unmanaged - /// resources. - /// - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - // free managed resources - } - - // free native resources - if (handle.IsAllocated) - { - handle.Free(); - ptrData = IntPtr.Zero; - } - } - - #endregion - - - } -} + } + + /// + /// Gets the value of the specified sample in the Signal. + /// + /// + /// The channel's index of the sample to set. + /// The position of the sample to set. + /// A floating-point value ranging from -1 to 1 representing + /// the retrieved value. Conversion is performed automatically from + /// the underlying signal sample format if supported. + /// + public float GetSample(int channel, int position) + { + float sample; + + unsafe + { + void* ptr = ptrData.ToPointer(); + int pos = position * Channels + channel; + + switch (format) + { + case SampleFormat.Format32BitIeeeFloat: + sample = ((float*)ptr)[pos]; + break; + default: + throw new NotSupportedException(); + } + } + + return sample; + } + + /// + /// Sets the value of the specified sample in the Signal. + /// + /// + /// The channel's index of the sample to set. + /// The position of the sample to set. + /// A floating-point value ranging from -1 to 1 + /// specifying the value to set. Conversion will be done automatically + /// to the underlying signal sample format if supported. + /// + public void SetSample(int channel, int position, float value) + { + unsafe + { + void* ptr = ptrData.ToPointer(); + int pos = position * Channels + channel; + + switch (format) + { + case SampleFormat.Format32BitIeeeFloat: + ((float*)ptr)[pos] = value; + break; + + default: + throw new NotSupportedException(); + } + } + } + + /// + /// Creates a new Signal from a float array. + /// + /// + public static Signal FromArray(Array signal, int sampleRate, + SampleFormat format = SampleFormat.Format32BitIeeeFloat) + { + int channels = signal.Rank == 1 ? 1 : signal.GetLength(1); + return FromArray(signal, channels, sampleRate, format); + } + + /// + /// Converts this signal to a ComplexSignal object. + /// + /// + public ComplexSignal ToComplex() + { + if (format == SampleFormat.Format128BitComplex) + return new ComplexSignal(rawData, channels, length, sampleRate); + else return ComplexSignal.FromSignal(this); + } + + /// + /// Creates a new Signal from a float array. + /// + /// + public static Signal FromArray(Array signal, int channels, int sampleRate, + SampleFormat format = SampleFormat.Format32BitIeeeFloat) + { + return FromArray(signal, signal.Length, channels, sampleRate, format); + } + + /// + /// Creates a new Signal from a float array. + /// + /// + public static Signal FromArray(Array signal, int size, int channels, int sampleRate, + SampleFormat format = SampleFormat.Format32BitIeeeFloat) + { + int sampleSize = GetSampleSize(format) / 8; + + byte[] buffer = new byte[size * sampleSize]; + Buffer.BlockCopy(signal, 0, buffer, 0, buffer.Length); + int samples = size / channels; + + return new Signal(buffer, channels, samples, sampleRate, format); + } + + /// + /// Copies this signal to a given array. + /// + /// + public void CopyTo(Array array) + { + Buffer.BlockCopy(rawData, 0, array, 0, array.Length); + } + + /// + /// Copies this signal to a given array. + /// + /// + public void CopyTo(float[] array) + { + if (format == Audio.SampleFormat.Format32BitIeeeFloat) + { + Buffer.BlockCopy(rawData, 0, array, 0, rawData.Length); + } + + else if (format == Audio.SampleFormat.Format16Bit) + { + short[] source = new short[Samples]; + Buffer.BlockCopy(rawData, 0, source, 0, rawData.Length); + SampleConverter.Convert(source, array); + } + + else + { + throw new InvalidOperationException(); + } + } + + /// + /// Copies this signal to a given array. + /// + /// + public void CopyTo(double[] array) + { + if (format == Audio.SampleFormat.Format64BitIeeeFloat) + { + Buffer.BlockCopy(rawData, 0, array, 0, rawData.Length); + } + else if (format == Audio.SampleFormat.Format32BitIeeeFloat) + { + float[] source = new float[Samples]; + Buffer.BlockCopy(rawData, 0, source, 0, rawData.Length); + for (int i = 0; i < source.Length; i++) + array[i] = source[i]; + } + else if (format == Audio.SampleFormat.Format16Bit) + { + short[] source = new short[Samples]; + Buffer.BlockCopy(rawData, 0, source, 0, rawData.Length); + SampleConverter.Convert(source, array); + } + + else + { + throw new InvalidOperationException(); + } + } + + /// + /// Converts this signal into a array of floating-point samples. + /// + /// + /// An array of single-precision floating-point samples. + /// + public float[] ToFloat() + { + float[] array = new float[Samples]; + CopyTo(array); + return array; + } + + /// + /// Converts this signal into a array of floating-point samples. + /// + /// + /// An array of single-precision floating-point samples. + /// + public double[] ToDouble() + { + double[] array = new double[Samples]; + CopyTo(array); + return array; + } + + + #region Static auxiliary methods + + /// + /// Gets the number of samples contained in a signal of given duration and sampling rate. + /// + /// + public static int NumberOfSamples(int duration, int samplingRate) + { + return (duration / 1000) * samplingRate; + } + + /// + /// Gets the duration of each sample in a signal with the given number of samples and sampling rate. + /// + /// + public static int DurationOfSamples(int samples, int samplingRate) + { + return (int)(samples / (double)samplingRate * 1000.0); + } + + /// + /// Gets the size (in bits) of a sample format. + /// + /// + public static int GetSampleSize(SampleFormat format) + { + switch (format) + { + case SampleFormat.Format128BitComplex: + return 128; + + case SampleFormat.Format32BitIeeeFloat: + return 32; + + case SampleFormat.Format64BitIeeeFloat: + return 64; + + case SampleFormat.Format16Bit: + return 16; + + case SampleFormat.Format32Bit: + return 32; + + case SampleFormat.Format8Bit: + return 8; + + case SampleFormat.Format8BitUnsigned: + return 8; + + default: + throw new NotSupportedException(); + } + } + #endregion + + + #region IDisposable Members + + /// + /// Performs application-defined tasks associated with freeing, + /// releasing, or resetting unmanaged resources. + /// + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Releases unmanaged resources and performs other cleanup operations + /// before the is reclaimed by garbage collection. + /// + /// + ~Signal() + { + Dispose(false); + } + + /// + /// Releases unmanaged and - optionally - managed resources + /// + /// + /// true to release both managed + /// and unmanaged resources; false to release only unmanaged + /// resources. + /// + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + // free managed resources + } + + // free native resources + if (handle.IsAllocated) + { + handle.Free(); + ptrData = IntPtr.Zero; + } + } + + #endregion + + + } +} diff --git a/Sources/Accord.Audio/Tools.cs b/Sources/Accord.Audio/Tools.cs index 424223804..9bbfdd7a0 100644 --- a/Sources/Accord.Audio/Tools.cs +++ b/Sources/Accord.Audio/Tools.cs @@ -27,6 +27,7 @@ namespace Accord.Audio using AForge.Math; using Accord.Math; using System.Collections.Generic; + using System.Numerics; /// /// Tool functions for audio processing. @@ -100,16 +101,17 @@ public static double[] GetMagnitudeSpectrum(Complex[] fft) /// public static double[] GetPowerSpectrum(Complex[] fft) { - if (fft == null) throw new ArgumentNullException("fft"); + if (fft == null) + throw new ArgumentNullException("fft"); int n = (int)System.Math.Ceiling((fft.Length + 1) / 2.0); double[] mx = new double[n]; - mx[0] = fft[0].SquaredMagnitude / fft.Length; + mx[0] = fft[0].SquaredMagnitude() / fft.Length; for (int i = 1; i < n; i++) - mx[i] = fft[i].SquaredMagnitude * 2.0 / fft.Length; + mx[i] = fft[i].SquaredMagnitude() * 2.0 / fft.Length; return mx; } @@ -162,13 +164,14 @@ public static double GetSpectralResolution(int samplingRate, int samples) /// public static double[] GetPowerCepstrum(Complex[] signal) { - if (signal == null) throw new ArgumentNullException("signal"); + if (signal == null) + throw new ArgumentNullException("signal"); FourierTransform.FFT(signal, FourierTransform.Direction.Backward); Complex[] logabs = new Complex[signal.Length]; for (int i = 0; i < logabs.Length; i++) - logabs[i].Re = System.Math.Log(signal[i].Magnitude); + logabs[i] = new Complex(System.Math.Log(signal[i].Magnitude), 0); FourierTransform.FFT(logabs, FourierTransform.Direction.Forward); diff --git a/Sources/Accord.Audio/Windows/RectangularWindow.cs b/Sources/Accord.Audio/Windows/RectangularWindow.cs index 8e12f939a..f18d5d37b 100644 --- a/Sources/Accord.Audio/Windows/RectangularWindow.cs +++ b/Sources/Accord.Audio/Windows/RectangularWindow.cs @@ -1,197 +1,204 @@ -// Accord Audio Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Audio.Windows -{ - using AForge.Math; - - /// - /// Rectangular Window. - /// - /// - /// - /// - /// The rectangular window (sometimes known as the boxcar or Dirichlet window) - /// is the simplest window, equivalent to replacing all but N values of a data - /// sequence by zeros, making it appear as though the waveform suddenly turns - /// on and off. - /// - /// - /// References: - /// - /// - /// Wikipedia, The Free Encyclopedia. Window function. Available on: - /// http://en.wikipedia.org/wiki/Window_function - /// - /// - /// - public class RectangularWindow : IWindow - { - private int length; - private int sampleRate; - - /// - /// Gets the Window's length. - /// - /// - public int Length - { - get { return length; } - } - - /// - /// Gets the Window's duration. - /// - /// - public double Duration - { - get { return sampleRate * length; } - } - - /// - /// Constructs a new Rectangular Window. - /// - /// - public RectangularWindow(int length) - { - this.length = length; - } - - /// - /// Constructs a new Rectangular Window. - /// - /// - public RectangularWindow(int length, int sampleRate) - { - this.length = length; - this.sampleRate = sampleRate; - } - - - /// - /// Splits a signal using the current window. - /// - /// - public unsafe Signal Apply(Signal signal, int sampleIndex) - { - int channels = signal.Channels; - int samples = signal.Length; - - int minLength = System.Math.Min(samples - sampleIndex, Length); - - Signal result = new Signal(channels, Length, signal.SampleRate, signal.SampleFormat); - - if (signal.SampleFormat == SampleFormat.Format32BitIeeeFloat) - { - for (int c = 0; c < channels; c++) - { - float* dst = (float*)result.Data.ToPointer() + c; - float* src = (float*)signal.Data.ToPointer() + c + channels * sampleIndex; - - for (int i = 0; i < minLength; i++, dst += channels, src += channels) - { - *dst = *src; - } - } - } - else - { - throw new UnsupportedSampleFormatException("Sample format is not supported by the filter."); - } - - return result; - } - - /// - /// Splits a complex signal using the current window. - /// - /// - public ComplexSignal Apply(ComplexSignal complexSignal, int sampleIndex) - { - Complex[,] resultData = new Complex[Length, complexSignal.Channels]; - ComplexSignal result = ComplexSignal.FromArray(resultData, complexSignal.SampleRate); - - int channels = result.Channels; - int minLength = System.Math.Min(complexSignal.Length - sampleIndex, Length); - - unsafe - { - for (int c = 0; c < complexSignal.Channels; c++) - { - Complex* dst = (Complex*)result.Data.ToPointer() + c; - Complex* src = (Complex*)complexSignal.Data.ToPointer() + c + channels * sampleIndex; - - for (int i = 0; i < minLength; i++, dst += channels, src += channels) - { - *dst = *src; - } - } - } - - return result; - } - - /// - /// Splits a signal using the window. - /// - /// - public unsafe virtual double[] Apply(double[] signal, int sampleIndex) - { - int minLength = System.Math.Min(signal.Length - sampleIndex, Length); - - double[] result = new double[Length]; - - fixed (double* R = result) - fixed (double* S = signal) - { - double* dst = R; - double* src = S + sampleIndex; - - for (int i = 0; i < minLength; i++, dst++, src++) - *dst = *src; - } - - return result; - } - - /// - /// Splits a signal using the window. - /// - /// - public unsafe virtual double[][] Apply(double[][] signal, int sampleIndex) - { - int channels = signal[0].Length; - - int minLength = System.Math.Min(signal.Length - sampleIndex, Length); - - double[][] result = new double[signal.Length][]; - for (int i = 0; i < result.Length; i++) - result[i] = new double[signal[i].Length]; - - for (int c = 0; c < channels; c++) - for (int i = 0; i < minLength; i++) - result[i][c] = signal[i + sampleIndex][c]; - - return result; - } - } -} +// Accord Audio Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Audio.Windows +{ + using AForge.Math; + using System.Numerics; + + /// + /// Rectangular Window. + /// + /// + /// + /// + /// The rectangular window (sometimes known as the boxcar or Dirichlet window) + /// is the simplest window, equivalent to replacing all but N values of a data + /// sequence by zeros, making it appear as though the waveform suddenly turns + /// on and off. + /// + /// + /// References: + /// + /// + /// Wikipedia, The Free Encyclopedia. Window function. Available on: + /// http://en.wikipedia.org/wiki/Window_function + /// + /// + /// + public class RectangularWindow : IWindow + { + private int length; + private int sampleRate; + + /// + /// Gets the Window's length. + /// + /// + public int Length + { + get { return length; } + } + + /// + /// Gets the Window's duration. + /// + /// + public double Duration + { + get { return sampleRate * length; } + } + + /// + /// Constructs a new Rectangular Window. + /// + /// + public RectangularWindow(int length) + { + this.length = length; + } + + /// + /// Constructs a new Rectangular Window. + /// + /// + public RectangularWindow(int length, int sampleRate) + { + this.length = length; + this.sampleRate = sampleRate; + } + + + /// + /// Splits a signal using the current window. + /// + /// + public Signal Apply(Signal signal, int sampleIndex) + { + int channels = signal.Channels; + int samples = signal.Length; + + int minLength = System.Math.Min(samples - sampleIndex, Length); + + Signal result = new Signal(channels, Length, signal.SampleRate, signal.SampleFormat); + + if (signal.SampleFormat == SampleFormat.Format32BitIeeeFloat) + { + for (int c = 0; c < channels; c++) + { + unsafe + { + float* dst = (float*)result.Data.ToPointer() + c; + float* src = (float*)signal.Data.ToPointer() + c + channels * sampleIndex; + + for (int i = 0; i < minLength; i++, dst += channels, src += channels) + { + *dst = *src; + } + } + } + } + else + { + throw new UnsupportedSampleFormatException("Sample format is not supported by the filter."); + } + + return result; + } + + /// + /// Splits a complex signal using the current window. + /// + /// + public ComplexSignal Apply(ComplexSignal complexSignal, int sampleIndex) + { + Complex[,] resultData = new Complex[Length, complexSignal.Channels]; + ComplexSignal result = ComplexSignal.FromArray(resultData, complexSignal.SampleRate); + + int channels = result.Channels; + int minLength = System.Math.Min(complexSignal.Length - sampleIndex, Length); + + unsafe + { + for (int c = 0; c < complexSignal.Channels; c++) + { + Complex* dst = (Complex*)result.Data.ToPointer() + c; + Complex* src = (Complex*)complexSignal.Data.ToPointer() + c + channels * sampleIndex; + + for (int i = 0; i < minLength; i++, dst += channels, src += channels) + { + *dst = *src; + } + } + } + + return result; + } + + /// + /// Splits a signal using the window. + /// + /// + public virtual double[] Apply(double[] signal, int sampleIndex) + { + int minLength = System.Math.Min(signal.Length - sampleIndex, Length); + + double[] result = new double[Length]; + + unsafe + { + fixed (double* R = result) + fixed (double* S = signal) + { + double* dst = R; + double* src = S + sampleIndex; + + for (int i = 0; i < minLength; i++, dst++, src++) + *dst = *src; + } + } + + return result; + } + + /// + /// Splits a signal using the window. + /// + /// + public virtual double[][] Apply(double[][] signal, int sampleIndex) + { + int channels = signal[0].Length; + + int minLength = System.Math.Min(signal.Length - sampleIndex, Length); + + double[][] result = new double[signal.Length][]; + for (int i = 0; i < result.Length; i++) + result[i] = new double[signal[i].Length]; + + for (int c = 0; c < channels; c++) + for (int i = 0; i < minLength; i++) + result[i][c] = signal[i + sampleIndex][c]; + + return result; + } + } +} diff --git a/Sources/Accord.Audio/Windows/WindowBase.cs b/Sources/Accord.Audio/Windows/WindowBase.cs index df7af2ed3..a07c071ff 100644 --- a/Sources/Accord.Audio/Windows/WindowBase.cs +++ b/Sources/Accord.Audio/Windows/WindowBase.cs @@ -22,7 +22,8 @@ namespace Accord.Audio.Windows { - using AForge.Math; + using AForge.Math; + using System.Numerics; /// /// Base abstract class for signal windows. @@ -94,7 +95,7 @@ public float this[int index] /// Splits a signal using the window. /// /// - public unsafe virtual Signal Apply(Signal signal, int sampleIndex) + public virtual Signal Apply(Signal signal, int sampleIndex) { int channels = signal.Channels; @@ -106,13 +107,16 @@ public unsafe virtual Signal Apply(Signal signal, int sampleIndex) { for (int c = 0; c < channels; c++) { - float* dst = (float*)result.Data.ToPointer() + c; - float* src = (float*)signal.Data.ToPointer() + c + channels * sampleIndex; - - for (int i = 0; i < minLength; i++, dst += channels, src += channels) + unsafe { - *dst = window[i] * (*src); - } + float* dst = (float*)result.Data.ToPointer() + c; + float* src = (float*)signal.Data.ToPointer() + c + channels * sampleIndex; + + for (int i = 0; i < minLength; i++, dst += channels, src += channels) + { + *dst = window[i] * (*src); + } + } } } else @@ -153,22 +157,25 @@ public virtual unsafe ComplexSignal Apply(ComplexSignal complexSignal, int sampl /// Splits a signal using the window. /// /// - public unsafe virtual double[] Apply(double[] signal, int sampleIndex) + public virtual double[] Apply(double[] signal, int sampleIndex) { int minLength = System.Math.Min(signal.Length - sampleIndex, Length); double[] result = new double[Length]; - fixed (double* R = result) - fixed (double* S = signal) + unsafe { - double* dst = R; - double* src = S + sampleIndex; - - for (int i = 0; i < minLength; i++, dst++, src++) + fixed (double* R = result) + fixed (double* S = signal) { - *dst = window[i] * (*src); - } + double* dst = R; + double* src = S + sampleIndex; + + for (int i = 0; i < minLength; i++, dst++, src++) + { + *dst = window[i] * (*src); + } + } } return result; @@ -178,7 +185,7 @@ public unsafe virtual double[] Apply(double[] signal, int sampleIndex) /// Splits a signal using the window. /// /// - public unsafe virtual double[][] Apply(double[][] signal, int sampleIndex) + public virtual double[][] Apply(double[][] signal, int sampleIndex) { int channels = signal[0].Length; diff --git a/Sources/Accord.Audition/Accord.Audition.csproj b/Sources/Accord.Audition/Accord.Audition.csproj index 716bdcb9b..a992f1e41 100644 --- a/Sources/Accord.Audition/Accord.Audition.csproj +++ b/Sources/Accord.Audition/Accord.Audition.csproj @@ -1,125 +1,116 @@ - - - - {CDBEFB1A-10BC-49EC-9833-D2CF6D4F6131} - Accord.Audition - Accord.Audition - - Debug - AnyCPU - AnyCPU - Library - Properties - True - 4 - True - true - Accord.snk - 3.5 - False - true - ..\Accord.NET.ruleset - false - true - 4096 - true - pdbonly - true - true - true - GlobalSuppressions.cs - - - v4.5 - bin\Debug\ - Full - False - False - True - DEBUG;TRACE - ..\..\Debug\ - - - ..\..\Release\net35 - TRACE;CODE_ANALYSIS;NET35 - v3.5 - ..\..\Release\net35\Accord.Audition.XML - ..\..\Release\net35\Accord.Audition.dll.CodeAnalysisLog.xml - - - ..\..\Release\net40 - TRACE;CODE_ANALYSIS;NET40 - v4.0 - ..\..\Release\net40\Accord.Audition.XML - ..\..\Release\net40\Accord.Audition.dll.CodeAnalysisLog.xml - - - ..\..\Release\net45 - TRACE;CODE_ANALYSIS;NET45 - v4.5 - ..\..\Release\net45\Accord.Audition.XML - ..\..\Release\net45\Accord.Audition.dll.CodeAnalysisLog.xml - - - - - ..\..\Externals\AForge.NET\AForge.dll - False - - - ..\..\Externals\AForge.NET\AForge.Math.dll - False - - - - 3.5 - - - - - Properties\VersionInfo.cs - - - - - - - - {E7B65F08-82F1-438F-847A-2AAC2BEC9AC0} - Accord.Audio - False - - - {F718E9A8-DB62-4785-8C49-4333A60D256A} - Accord.Math - False - - - - - - - - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - \ No newline at end of file + + + + {CDBEFB1A-10BC-49EC-9833-D2CF6D4F6131} + Accord.Audition + Accord.Audition + Debug + AnyCPU + AnyCPU + Library + Properties + True + 4 + True + true + Accord.snk + 3.5 + False + true + ..\Accord.NET.ruleset + false + true + 4096 + true + pdbonly + true + true + true + GlobalSuppressions.cs + + + v4.5 + bin\Debug\ + Full + False + False + True + DEBUG;TRACE + $(SolutionDir)..\Debug\ + + + $(SolutionDir)..\Release\net35 + TRACE;CODE_ANALYSIS;NET35 + v3.5 + $(SolutionDir)..\Release\net35\Accord.Audition.XML + $(SolutionDir)..\Release\net35\Accord.Audition.dll.CodeAnalysisLog.xml + + + $(SolutionDir)..\Release\net40 + TRACE;CODE_ANALYSIS;NET40 + v4.0 + $(SolutionDir)..\Release\net40\Accord.Audition.XML + $(SolutionDir)..\Release\net40\Accord.Audition.dll.CodeAnalysisLog.xml + + + $(SolutionDir)..\Release\net45 + TRACE;CODE_ANALYSIS;NET45 + v4.5 + $(SolutionDir)..\Release\net45\Accord.Audition.XML + $(SolutionDir)..\Release\net45\Accord.Audition.dll.CodeAnalysisLog.xml + + + + + + 3.5 + + + + + Properties\VersionInfo.cs + + + + + + + + {E7B65F08-82F1-438F-847A-2AAC2BEC9AC0} + Accord.Audio + False + + + {F718E9A8-DB62-4785-8C49-4333A60D256A} + Accord.Math + False + + + + + + + + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + diff --git a/Sources/Accord.Controls.Audio/Accord.Controls.Audio.csproj b/Sources/Accord.Controls.Audio/Accord.Controls.Audio.csproj index b08230a8e..147b81ae2 100644 --- a/Sources/Accord.Controls.Audio/Accord.Controls.Audio.csproj +++ b/Sources/Accord.Controls.Audio/Accord.Controls.Audio.csproj @@ -1,159 +1,145 @@ - - - - {E0B826AC-2A51-41EC-9F09-561CA14A82BB} - Accord.Controls.Audio - Accord.Controls.Audio - Debug - AnyCPU - AnyCPU - Library - Properties - True - 4 - True - true - Accord.snk - 3.5 - False - true - ..\Accord.NET.ruleset - false - true - 4096 - true - pdbonly - true - true - true - GlobalSuppressions.cs - - - v4.5 - bin\Debug\ - Full - False - False - True - DEBUG;TRACE - ..\..\Debug\ - - - ..\..\Release\net35 - TRACE;CODE_ANALYSIS;NET35 - v3.5 - ..\..\Release\net35\Accord.Controls.Audio.XML - ..\..\Release\net35\Accord.Controls.Audio.dll.CodeAnalysisLog.xml - - - ..\..\Release\net40 - TRACE;CODE_ANALYSIS;NET40 - v4.0 - ..\..\Release\net40\Accord.Controls.Audio.XML - ..\..\Release\net40\Accord.Controls.Audio.dll.CodeAnalysisLog.xml - - - ..\..\Release\net45 - TRACE;CODE_ANALYSIS;NET45 - v4.5 - ..\..\Release\net45\Accord.Controls.Audio.XML - ..\..\Release\net45\Accord.Controls.Audio.dll.CodeAnalysisLog.xml - - - - - False - ..\..\Externals\AForge.NET\AForge.dll - False - - - False - ..\..\Externals\AForge.NET\AForge.Controls.dll - False - - - False - ..\..\Externals\AForge.NET\AForge.Math.dll - False - - - - 3.5 - - - - - - False - ..\..\Externals\ZedGraph\ZedGraph.dll - - - - - Properties\VersionInfo.cs - - - Form - - - WavechartBox.cs - - - - Component - - - - - {E7B65F08-82F1-438F-847A-2AAC2BEC9AC0} - Accord.Audio - False - - - {0AB27A20-925C-4556-9FA4-6E2C109E448E} - Accord.Controls - - - {a177a90c-8207-466a-af70-f2b8452a42ac} - Accord.Core - - - {F718E9A8-DB62-4785-8C49-4333A60D256A} - Accord.Math - False - - - {FD8101DD-C95D-42D6-AD44-AE01C25F2811} - Accord.Statistics - False - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - - - WavechartBox.cs - - - - - - \ No newline at end of file + + + + {E0B826AC-2A51-41EC-9F09-561CA14A82BB} + Accord.Controls.Audio + Accord.Controls.Audio + Debug + AnyCPU + AnyCPU + Library + Properties + True + 4 + True + true + Accord.snk + 3.5 + False + true + ..\Accord.NET.ruleset + false + true + 4096 + true + pdbonly + true + true + true + GlobalSuppressions.cs + + + v4.5 + bin\Debug\ + Full + False + False + True + DEBUG;TRACE + $(SolutionDir)..\Debug\ + + + $(SolutionDir)..\Release\net35 + TRACE;CODE_ANALYSIS;NET35 + v3.5 + $(SolutionDir)..\Release\net35\Accord.Controls.Audio.XML + $(SolutionDir)..\Release\net35\Accord.Controls.Audio.dll.CodeAnalysisLog.xml + + + $(SolutionDir)..\Release\net40 + TRACE;CODE_ANALYSIS;NET40 + v4.0 + $(SolutionDir)..\Release\net40\Accord.Controls.Audio.XML + $(SolutionDir)..\Release\net40\Accord.Controls.Audio.dll.CodeAnalysisLog.xml + + + $(SolutionDir)..\Release\net45 + TRACE;CODE_ANALYSIS;NET45 + v4.5 + $(SolutionDir)..\Release\net45\Accord.Controls.Audio.XML + $(SolutionDir)..\Release\net45\Accord.Controls.Audio.dll.CodeAnalysisLog.xml + + + + + + 3.5 + + + + + + + False + ..\..\Externals\ZedGraph\ZedGraph.dll + + + + + Properties\VersionInfo.cs + + + Form + + + WavechartBox.cs + + + + Component + + + + + {E7B65F08-82F1-438F-847A-2AAC2BEC9AC0} + Accord.Audio + False + + + {0AB27A20-925C-4556-9FA4-6E2C109E448E} + Accord.Controls + + + {a177a90c-8207-466a-af70-f2b8452a42ac} + Accord.Core + + + {F718E9A8-DB62-4785-8C49-4333A60D256A} + Accord.Math + False + + + {FD8101DD-C95D-42D6-AD44-AE01C25F2811} + Accord.Statistics + False + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + WavechartBox.cs + + + + + + diff --git a/Sources/Accord.Controls.Audio/WavechartBox.cs b/Sources/Accord.Controls.Audio/WavechartBox.cs index 366231f8f..314f26e0f 100644 --- a/Sources/Accord.Controls.Audio/WavechartBox.cs +++ b/Sources/Accord.Controls.Audio/WavechartBox.cs @@ -1,224 +1,223 @@ -// Accord Statistics Controls Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Controls -{ - using System; - using System.Data; - using System.Threading; - using System.Windows.Forms; - using System.Drawing; - using Accord.Audio; - using Accord.Math; - using AForge.Math; - using ZedGraph; - using Accord.Audio.Filters; - - /// - /// Wavechart Box. - /// - /// - public partial class WavechartBox : Form - { - - private Thread formThread; - - private CurveList series; - - private WavechartBox() - { - InitializeComponent(); - - series = new CurveList(); - - zedGraphControl.GraphPane.Title.IsVisible = false; - - zedGraphControl.BorderStyle = System.Windows.Forms.BorderStyle.None; - zedGraphControl.GraphPane.Border.IsVisible = false; - zedGraphControl.GraphPane.Border.Color = Color.White; - zedGraphControl.GraphPane.Border.Width = 0; - - // zedGraphControl.IsAntiAlias = true; - zedGraphControl.GraphPane.Fill = new Fill(Color.White); - zedGraphControl.GraphPane.Chart.Fill = new Fill(Color.GhostWhite); - zedGraphControl.GraphPane.CurveList = series; - - zedGraphControl.GraphPane.Legend.IsVisible = true; - zedGraphControl.GraphPane.Legend.Position = LegendPos.Right; - zedGraphControl.GraphPane.Legend.IsShowLegendSymbols = false; - - zedGraphControl.GraphPane.XAxis.MajorGrid.IsVisible = true; - zedGraphControl.GraphPane.XAxis.MinorGrid.IsVisible = false; - zedGraphControl.GraphPane.XAxis.MajorGrid.Color = Color.LightGray; - zedGraphControl.GraphPane.XAxis.MajorGrid.IsZeroLine = false; - zedGraphControl.GraphPane.XAxis.Scale.MaxGrace = 0; - zedGraphControl.GraphPane.XAxis.Scale.MinGrace = 0; - - zedGraphControl.GraphPane.YAxis.MinorGrid.IsVisible = false; - zedGraphControl.GraphPane.YAxis.MajorGrid.IsVisible = true; - zedGraphControl.GraphPane.YAxis.MajorGrid.Color = Color.LightGray; - zedGraphControl.GraphPane.YAxis.MajorGrid.IsZeroLine = false; - zedGraphControl.GraphPane.YAxis.Scale.MaxGrace = 0; - zedGraphControl.GraphPane.YAxis.Scale.MinGrace = 0; - } - - /// - /// Blocks the caller until the form is closed. - /// - /// - public void WaitForClose() - { - if (Thread.CurrentThread != formThread) - formThread.Join(); - } - - - - - /// - /// Displays a Wavechart with the specified signal. - /// - /// - /// The signal object to display. - /// The channel to be displayed. - /// If set to true, the caller will continue - /// executing while the form is shown on screen. If set to false, - /// the caller will be blocked until the user closes the form. Default - /// is false. - /// The title for the data window. - /// - /// The Data Grid Box being shown. - /// - public static WavechartBox Show(Signal signal, int channel = 0, - string title = "Wavechart", bool nonBlocking = false) - { - var tuple = Tuple.Create(signal, channel); - return show(title, nonBlocking, tuple); - } - - /// - /// Displays a Wavechart with the specified signal. - /// - /// - /// If set to true, the caller will continue - /// executing while the form is shown on screen. If set to false, - /// the caller will be blocked until the user closes the form. Default - /// is false. - /// - /// The signal to be displayed. - /// The title for the data window. - /// - /// The Data Grid Box being shown. - /// - public static WavechartBox Show(float[] array, String title, bool nonBlocking = false) - { - var signal = Signal.FromArray(array, 0, SampleFormat.Format32BitIeeeFloat); - var tuple = Tuple.Create(signal, 0); - return show(title, nonBlocking, tuple); - } - - private static WavechartBox show(String title, bool hold, params Tuple[] series) - { - WavechartBox form = null; - Thread formThread = null; - - AutoResetEvent stopWaitHandle = new AutoResetEvent(false); - - formThread = new Thread(() => - { - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); - - // Show control in a form - form = new WavechartBox(); - form.Text = title; - form.formThread = formThread; - - if (!String.IsNullOrEmpty(title)) - { - form.zedGraphControl.GraphPane.Title.IsVisible = true; - form.zedGraphControl.GraphPane.Title.Text = title; - } - - var sequence = new ColorSequenceCollection(series.Length); - - for (int i = 0; i < series.Length; i++) - { - var signal = series[i].Item1; - int channel = series[i].Item2; - - ComplexSignal complex = signal as ComplexSignal; - - if (complex != null && complex.Status != ComplexSignalStatus.Normal) - { - double[] spectrum = Accord.Audio.Tools - .GetPowerSpectrum(complex.GetChannel(channel)); - double[] frequencies = Accord.Audio.Tools.GetFrequencyVector(signal.Length, signal.SampleRate); - - form.series.Add(new LineItem(i.ToString(), frequencies, - spectrum, sequence.GetColor(i), SymbolType.None)); - - form.zedGraphControl.GraphPane.XAxis.Title.Text = "Frequency"; - form.zedGraphControl.GraphPane.YAxis.Title.Text = "Power"; - } - else - { - double[] values; - if (signal.Channels == 1) - { - values = signal.ToDouble(); - } - else - { - ExtractChannel extract = new ExtractChannel(channel); - values = extract.Apply(signal).ToDouble(); - } - - form.series.Add(new LineItem(i.ToString(), Matrix.Indices(0, signal.Length).ToDouble(), - values, sequence.GetColor(i), SymbolType.None)); - - form.zedGraphControl.GraphPane.XAxis.Title.Text = "Time"; - form.zedGraphControl.GraphPane.YAxis.Title.Text = "Amplitude"; - } - } - - form.zedGraphControl.GraphPane.AxisChange(); - - stopWaitHandle.Set(); - - Application.Run(form); - }); - - formThread.SetApartmentState(ApartmentState.STA); - - formThread.Start(); - - stopWaitHandle.WaitOne(); - - if (!hold) - formThread.Join(); - - return form; - } - - } -} +// Accord Statistics Controls Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Controls +{ + using System; + using System.Data; + using System.Threading; + using System.Windows.Forms; + using System.Drawing; + using Accord.Audio; + using Accord.Math; + using AForge.Math; + using ZedGraph; + using Accord.Audio.Filters; + + /// + /// Wavechart Box. + /// + /// + public partial class WavechartBox : Form + { + + private Thread formThread; + + private CurveList series; + + private WavechartBox() + { + InitializeComponent(); + + series = new CurveList(); + + zedGraphControl.GraphPane.Title.IsVisible = false; + + zedGraphControl.BorderStyle = System.Windows.Forms.BorderStyle.None; + zedGraphControl.GraphPane.Border.IsVisible = false; + zedGraphControl.GraphPane.Border.Color = Color.White; + zedGraphControl.GraphPane.Border.Width = 0; + + // zedGraphControl.IsAntiAlias = true; + zedGraphControl.GraphPane.Fill = new Fill(Color.White); + zedGraphControl.GraphPane.Chart.Fill = new Fill(Color.GhostWhite); + zedGraphControl.GraphPane.CurveList = series; + + zedGraphControl.GraphPane.Legend.IsVisible = true; + zedGraphControl.GraphPane.Legend.Position = LegendPos.Right; + zedGraphControl.GraphPane.Legend.IsShowLegendSymbols = false; + + zedGraphControl.GraphPane.XAxis.MajorGrid.IsVisible = true; + zedGraphControl.GraphPane.XAxis.MinorGrid.IsVisible = false; + zedGraphControl.GraphPane.XAxis.MajorGrid.Color = Color.LightGray; + zedGraphControl.GraphPane.XAxis.MajorGrid.IsZeroLine = false; + zedGraphControl.GraphPane.XAxis.Scale.MaxGrace = 0; + zedGraphControl.GraphPane.XAxis.Scale.MinGrace = 0; + + zedGraphControl.GraphPane.YAxis.MinorGrid.IsVisible = false; + zedGraphControl.GraphPane.YAxis.MajorGrid.IsVisible = true; + zedGraphControl.GraphPane.YAxis.MajorGrid.Color = Color.LightGray; + zedGraphControl.GraphPane.YAxis.MajorGrid.IsZeroLine = false; + zedGraphControl.GraphPane.YAxis.Scale.MaxGrace = 0; + zedGraphControl.GraphPane.YAxis.Scale.MinGrace = 0; + } + + /// + /// Blocks the caller until the form is closed. + /// + /// + public void WaitForClose() + { + if (Thread.CurrentThread != formThread) + formThread.Join(); + } + + + + + /// + /// Displays a Wavechart with the specified signal. + /// + /// + /// The signal object to display. + /// The channel to be displayed. + /// If set to true, the caller will continue + /// executing while the form is shown on screen. If set to false, + /// the caller will be blocked until the user closes the form. Default + /// is false. + /// The title for the data window. + /// + /// The Data Grid Box being shown. + /// + public static WavechartBox Show(Signal signal, int channel = 0, + string title = "Wavechart", bool nonBlocking = false) + { + var tuple = Tuple.Create(signal, channel); + return show(title, nonBlocking, tuple); + } + + /// + /// Displays a Wavechart with the specified signal. + /// + /// + /// If set to true, the caller will continue + /// executing while the form is shown on screen. If set to false, + /// the caller will be blocked until the user closes the form. Default + /// is false. + /// + /// The signal to be displayed. + /// The title for the data window. + /// + /// The Data Grid Box being shown. + /// + public static WavechartBox Show(float[] array, String title, bool nonBlocking = false) + { + var signal = Signal.FromArray(array, 0, SampleFormat.Format32BitIeeeFloat); + var tuple = Tuple.Create(signal, 0); + return show(title, nonBlocking, tuple); + } + + private static WavechartBox show(String title, bool hold, params Tuple[] series) + { + WavechartBox form = null; + Thread formThread = null; + + AutoResetEvent stopWaitHandle = new AutoResetEvent(false); + + formThread = new Thread(() => + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + + // Show control in a form + form = new WavechartBox(); + form.Text = title; + form.formThread = formThread; + + if (!String.IsNullOrEmpty(title)) + { + form.zedGraphControl.GraphPane.Title.IsVisible = true; + form.zedGraphControl.GraphPane.Title.Text = title; + } + + var sequence = new ColorSequenceCollection(series.Length); + + for (int i = 0; i < series.Length; i++) + { + var signal = series[i].Item1; + int channel = series[i].Item2; + + ComplexSignal complex = signal as ComplexSignal; + + if (complex != null && complex.Status != ComplexSignalStatus.Normal) + { + double[] spectrum = Accord.Audio.Tools.GetPowerSpectrum(complex.GetChannel(channel)); + double[] frequencies = Accord.Audio.Tools.GetFrequencyVector(signal.Length, signal.SampleRate); + + form.series.Add(new LineItem(i.ToString(), frequencies, + spectrum, sequence.GetColor(i), SymbolType.None)); + + form.zedGraphControl.GraphPane.XAxis.Title.Text = "Frequency"; + form.zedGraphControl.GraphPane.YAxis.Title.Text = "Power"; + } + else + { + double[] values; + if (signal.Channels == 1) + { + values = signal.ToDouble(); + } + else + { + ExtractChannel extract = new ExtractChannel(channel); + values = extract.Apply(signal).ToDouble(); + } + + form.series.Add(new LineItem(i.ToString(), Matrix.Indices(0, signal.Length).ToDouble(), + values, sequence.GetColor(i), SymbolType.None)); + + form.zedGraphControl.GraphPane.XAxis.Title.Text = "Time"; + form.zedGraphControl.GraphPane.YAxis.Title.Text = "Amplitude"; + } + } + + form.zedGraphControl.GraphPane.AxisChange(); + + stopWaitHandle.Set(); + + Application.Run(form); + }); + + formThread.SetApartmentState(ApartmentState.STA); + + formThread.Start(); + + stopWaitHandle.WaitOne(); + + if (!hold) + formThread.Join(); + + return form; + } + + } +} diff --git a/Sources/Accord.Controls.Imaging/AForge/ColorSlider.cs b/Sources/Accord.Controls.Imaging/AForge/ColorSlider.cs new file mode 100644 index 0000000000..2a3da134d --- /dev/null +++ b/Sources/Accord.Controls.Imaging/AForge/ColorSlider.cs @@ -0,0 +1,452 @@ +// AForge Controls Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections; +using System.ComponentModel; +using System.Drawing; +using System.Drawing.Imaging; +using System.Drawing.Drawing2D; +using System.Data; +using System.Windows.Forms; +using System.Resources; +using System.Reflection; + +namespace AForge.Controls +{ + using Point = System.Drawing.Point; + + /// + /// Color slider control. + /// + /// + /// The control represent a color slider, which allows selecting + /// one or two values in the [0, 255] range. The application of this control + /// includes mostly areas of image processing and computer vision, where it is required + /// to select color threshold or ranges for different type of color filtering. + /// + /// Depending on the control's , it has different look and may suite + /// different tasks. See documentation to for information + /// about available type and possible control's looks. + /// + /// + public class ColorSlider : System.Windows.Forms.Control + { + private Pen blackPen = new Pen( Color.Black, 1 ); + private Color startColor = Color.Black; + private Color endColor = Color.White; + private Color fillColor = Color.Black; + private ColorSliderType type = ColorSliderType.Gradient; + private bool doubleArrow = true; + private Bitmap arrow; + private int min = 0, max = 255; + private int width = 256, height = 10; + private int trackMode = 0; + private int dx; + + /// + /// An event, to notify about changes of or properties. + /// + /// + /// The event is fired after changes of or property, + /// which is caused by user dragging the corresponding controls arrow (slider). + /// + /// + public event EventHandler ValuesChanged; + + /// + /// Enumeration of color slider types. + /// + /// + /// + /// The slider's type supposes the control's + /// background filled with gradient startting from color and ending + /// with color. The color does not have + /// impact on control's look. + /// + /// This type allows as one-arrow, as two-arrows control. + /// + /// Sample control's look: + /// + /// + /// The slider's type supposes the control's + /// background filled with gradient startting from color and ending + /// with color. In addition the areas, which are outside of + /// [, ] range, are filled with color. + /// + /// This type allows only two-arrows control. + /// + /// Sample control's look: + /// + /// + /// The slider's type supposes the + /// control's background filled with gradient startting from color + /// and ending with color. In addition the area, which is inside of + /// [, ] range, is filled with color. + /// + /// This type allows only two-arrows control. + /// + /// Sample control's look: + /// + /// + /// The slider's type supposes filling areas + /// outside of [, ] range with and + /// inside the range with . The color does not + /// have impact on control's look. + /// + /// This type allows as one-arrow, as two-arrows control. + /// + /// Sample control's look: + /// + /// + /// + public enum ColorSliderType + { + /// + /// Gradient color slider type. + /// + Gradient, + + /// + /// Inner gradient color slider type. + /// + InnerGradient, + + /// + /// Outer gradient color slider type. + /// + OuterGradient, + + /// + /// Threshold color slider type. + /// + Threshold + } + + /// + /// Start color for gradient filling. + /// + /// + /// See documentation to enumeration for information about + /// the usage of this property. + /// + [DefaultValue( typeof( Color ), "Black" )] + public Color StartColor + { + get { return startColor; } + set + { + startColor = value; + Invalidate( ); + } + } + + /// + /// End color for gradient filling. + /// + /// + /// See documentation to enumeration for information about + /// the usage of this property. + /// + [DefaultValue( typeof( Color ), "White" )] + public Color EndColor + { + get { return endColor; } + set + { + endColor = value; + Invalidate( ); + } + } + + /// + /// Color to fill control's background in filtered zones. + /// + /// + /// See documentation to enumeration for information about + /// the usage of this property. + /// + [DefaultValue( typeof( Color ), "Black" )] + public Color FillColor + { + get { return fillColor; } + set + { + fillColor = value; + Invalidate( ); + } + } + + /// + /// Specifies control's type. + /// + /// + /// See documentation to enumeration for information about + /// the usage of this property. + /// + [DefaultValue( ColorSliderType.Gradient )] + public ColorSliderType Type + { + get { return type; } + set + { + type = value; + if ( ( type != ColorSliderType.Gradient ) && ( type != ColorSliderType.Threshold ) ) + DoubleArrow = true; + Invalidate( ); + } + } + + /// + /// Minimum selected value, [0, 255]. + /// + /// + [DefaultValue( 0 )] + public int Min + { + get { return min; } + set + { + min = value; + Invalidate( ); + } + } + + /// + /// Maximum selected value, [0, 255]. + /// + /// + [DefaultValue( 255 )] + public int Max + { + get { return max; } + set + { + max = value; + Invalidate( ); + } + } + + /// + /// Single or Double arrow slider control. + /// + /// + /// The property specifies if the slider has one or two selection arrows (sliders). + /// + /// The single arrow allows only to specify one value, which is set by + /// property. The single arrow slider is useful for applications, where it is required to select + /// color threshold, for example. + /// + /// The double arrow allows to specify two values, which are set by + /// and properties. The double arrow slider is useful for applications, where it is + /// required to select filtering color range, for example. + /// + /// + [DefaultValue( true )] + public bool DoubleArrow + { + get { return doubleArrow; } + set + { + doubleArrow = value; + if ( ( !doubleArrow ) && ( type != ColorSliderType.Threshold ) ) + { + Type = ColorSliderType.Gradient; + } + Invalidate( ); + } + } + + + /// + /// Initializes a new instance of the class. + /// + /// + public ColorSlider( ) + { + InitializeComponent( ); + + SetStyle( ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | + ControlStyles.DoubleBuffer | ControlStyles.UserPaint, true ); + + // load arrow bitmap + Assembly assembly = this.GetType( ).Assembly; + arrow = new Bitmap( assembly.GetManifestResourceStream( "AForge.Controls.Resources.arrow.bmp" ) ); + arrow.MakeTransparent( Color.FromArgb( 255, 255, 255 ) ); + } + + /// + /// Dispose the object. + /// + /// + /// Specifies if disposing was invoked by user's code. + /// + protected override void Dispose( bool disposing ) + { + if ( disposing ) + { + blackPen.Dispose( ); + arrow.Dispose( ); + } + base.Dispose( disposing ); + } + + // Init component + private void InitializeComponent( ) + { + this.SuspendLayout( ); + // + // ColorSlider + // + this.Paint += new System.Windows.Forms.PaintEventHandler( this.ColorSlider_Paint ); + this.MouseMove += new System.Windows.Forms.MouseEventHandler( this.ColorSlider_MouseMove ); + this.MouseDown += new System.Windows.Forms.MouseEventHandler( this.ColorSlider_MouseDown ); + this.MouseUp += new System.Windows.Forms.MouseEventHandler( this.ColorSlider_MouseUp ); + this.ResumeLayout( false ); + + } + + // Paint control + private void ColorSlider_Paint( object sender, PaintEventArgs e ) + { + Graphics g = e.Graphics; + Rectangle rc = this.ClientRectangle; + Brush brush; + int x = ( rc.Right - width ) / 2; + int y = 2; + + // draw rectangle around the control + g.DrawRectangle( blackPen, x - 1, y - 1, width + 1, height + 1 ); + + switch ( type ) + { + case ColorSliderType.Gradient: + case ColorSliderType.InnerGradient: + case ColorSliderType.OuterGradient: + + // create gradient brush + brush = new LinearGradientBrush( new Point( x, 0 ), new Point( x + width, 0 ), startColor, endColor ); + g.FillRectangle( brush, x, y, width, height ); + brush.Dispose( ); + + // check type + if ( type == ColorSliderType.InnerGradient ) + { + // inner gradient + brush = new SolidBrush( fillColor ); + + if ( min != 0 ) + { + g.FillRectangle( brush, x, y, min, height ); + } + if ( max != 255 ) + { + g.FillRectangle( brush, x + max + 1, y, 255 - max, height ); + } + brush.Dispose( ); + } + else if ( type == ColorSliderType.OuterGradient ) + { + // outer gradient + brush = new SolidBrush( fillColor ); + // fill space between min & max with color 3 + g.FillRectangle( brush, x + min, y, max - min + 1, height ); + brush.Dispose( ); + } + break; + case ColorSliderType.Threshold: + // 1 - fill with color 1 + brush = new SolidBrush( startColor ); + g.FillRectangle( brush, x, y, width, height ); + brush.Dispose( ); + // 2 - fill space between min & max with color 2 + brush = new SolidBrush( endColor ); + g.FillRectangle( brush, x + min, y, max - min + 1, height ); + brush.Dispose( ); + break; + } + + + // draw arrows + x -= 4; + y += 1 + height; + + g.DrawImage( arrow, x + min, y, 9, 6 ); + if ( doubleArrow ) + g.DrawImage( arrow, x + max, y, 9, 6 ); + } + + // On mouse down + private void ColorSlider_MouseDown( object sender, System.Windows.Forms.MouseEventArgs e ) + { + int x = ( ClientRectangle.Right - width ) / 2 - 4; + int y = 3 + height; + + // check Y coordinate + if ( ( e.Y >= y ) && ( e.Y < y + 6 ) ) + { + // check X coordinate + if ( ( e.X >= x + min ) && ( e.X < x + min + 9 ) ) + { + // left arrow + trackMode = 1; + dx = e.X - min; + } + if ( ( doubleArrow ) && ( e.X >= x + max ) && ( e.X < x + max + 9 ) ) + { + // right arrow + trackMode = 2; + dx = e.X - max; + } + + if ( trackMode != 0 ) + this.Capture = true; + } + } + + // On mouse up + private void ColorSlider_MouseUp( object sender, System.Windows.Forms.MouseEventArgs e ) + { + if ( trackMode != 0 ) + { + // release capture + this.Capture = false; + trackMode = 0; + + // notify client + if ( ValuesChanged != null ) + ValuesChanged( this, new EventArgs( ) ); + } + } + + // On mouse move + private void ColorSlider_MouseMove( object sender, System.Windows.Forms.MouseEventArgs e ) + { + if ( trackMode != 0 ) + { + if ( trackMode == 1 ) + { + // left arrow tracking + min = e.X - dx; + min = Math.Max( min, 0 ); + min = Math.Min( min, max ); + } + if ( trackMode == 2 ) + { + // right arrow tracking + max = e.X - dx; + max = Math.Max( max, min ); + max = Math.Min( max, 255 ); + } + + // repaint control + Invalidate( ); + } + } + } +} diff --git a/Sources/Accord.Controls.Imaging/AForge/ColorSlider.resx b/Sources/Accord.Controls.Imaging/AForge/ColorSlider.resx new file mode 100644 index 0000000000..52a9ad3e7 --- /dev/null +++ b/Sources/Accord.Controls.Imaging/AForge/ColorSlider.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + False + + \ No newline at end of file diff --git a/Sources/Accord.Controls.Imaging/AForge/Histogram.cs b/Sources/Accord.Controls.Imaging/AForge/Histogram.cs new file mode 100644 index 0000000000..189ea069b --- /dev/null +++ b/Sources/Accord.Controls.Imaging/AForge/Histogram.cs @@ -0,0 +1,495 @@ +// AForge Controls Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Controls +{ + using System; + using System.Collections; + using System.ComponentModel; + using System.Drawing; + using System.Data; + using System.Windows.Forms; + + /// + /// Arguments of histogram events. + /// + public class HistogramEventArgs : EventArgs + { + private int min, max; + + /// + /// Initializes a new instance of the class. + /// + /// + /// Histogram's index under mouse pointer. + /// + public HistogramEventArgs(int pos) + { + this.min = pos; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Min histogram's index in selection. + /// Max histogram's index in selection. + /// + public HistogramEventArgs(int min, int max) + { + this.min = min; + this.max = max; + } + + /// + /// Min histogram's index in selection. + /// + public int Min + { + get { return min; } + } + + /// + /// Max histogram's index in selection. + /// + public int Max + { + get { return max; } + } + + /// + /// Histogram's index under mouse pointer. + /// + public int Position + { + get { return min; } + } + } + + /// + /// Delegate for histogram events handlers. + /// + /// + /// Sender object. + /// Event arguments. + /// + public delegate void HistogramEventHandler(object sender, HistogramEventArgs e); + + + /// + /// Histogram control. + /// + /// + /// The control displays histograms represented with integer arrays, + /// where each array's element keeps occurrence number of the corresponding element. + /// + /// + /// Sample usage: + /// + /// // create array with histogram values + /// int[] histogramValues = new int[] { 3, 8, 53, 57, 79, 69, ... }; + /// // set values to histogram control + /// histogram.Values = histogramValues; + /// + /// + /// Sample control's look: + /// + /// + /// + public class Histogram : System.Windows.Forms.Control + { + // color used to paing histogram + private Color color = Color.Black; + // logarithmic view or not + private bool logarithmic = false; + // histogram's values + private int[] values; + // max histogram's values + private int max; + private double maxLogarithmic; + // allow mouse selection in histogram or not + private bool allowSelection = false; + // vertical histogram or not + private bool vertical = false; + + // set of pens + private Pen blackPen = new Pen(Color.Black, 1); + private Pen whitePen = new Pen(Color.White, 1); + private Pen drawPen = new Pen(Color.Black); + + // width and height of histogram's area + private int width; + private int height; + + // mouse dragging with pressed button + private bool tracking = false; + // determines if mouse is over histogram area + private bool over = false; + // selection's start and stop positions + private int start, stop; + + /// + /// Histogram's color. + /// + /// + [DefaultValue(typeof(Color), "Black")] + public Color Color + { + get { return color; } + set + { + color = value; + + drawPen.Dispose(); + drawPen = new Pen(color); + Invalidate(); + } + } + + /// + /// Allow mouse selection or not. + /// + /// + /// In the case if mouse selection is allowed, the control will + /// fire and events + /// and provide information about the selection. + /// + [DefaultValue(false)] + public bool AllowSelection + { + get { return allowSelection; } + set { allowSelection = value; } + } + + /// + /// Logarithmic view or not. + /// + /// + /// In the case if logarihmic view is selected, then the control + /// will display base 10 logarithm of values. + /// + /// By default the property is set to false - none logarithmic view. + /// + [DefaultValue(false)] + public bool IsLogarithmicView + { + get { return logarithmic; } + set + { + logarithmic = value; + Invalidate(); + } + } + + /// + /// Vertical view or not. + /// + /// + /// The property determines if histogram should be displayed vertically or + /// not (horizontally). + /// + /// By default the property is set to false - horizontal view. + /// + [DefaultValue(false)] + public bool IsVertical + { + get { return vertical; } + set + { + vertical = value; + Invalidate(); + } + } + + /// + /// Histogram values. + /// + /// + /// Non-negative histogram values. + /// + /// Histogram values should be non-negative. + /// + [Browsable(false)] + public int[] Values + { + get { return values; } + set + { + values = value; + + if (values != null) + { + // check values and find maximum + max = 0; + foreach (int v in values) + { + // value chould non-negative + if (v < 0) + { + throw new ArgumentException("Histogram values should be non-negative."); + } + + if (v > max) + { + max = v; + maxLogarithmic = Math.Log10(max); + } + } + } + Invalidate(); + } + } + + /// + /// Mouse position changed event. + /// + /// + /// The event is fired only if the property is set + /// to true. The passed to event handler class is initialized + /// with property only, which is histogram value's + /// index pointed by mouse. + /// + public event HistogramEventHandler PositionChanged; + + /// + /// Mouse selection changed event. + /// + /// + /// The event is fired only if the property is set + /// to true. The passed to event handler class is initialized + /// with and properties + /// only, which represent selection range - min and max indexes. + /// + public event HistogramEventHandler SelectionChanged; + + /// + /// Initializes a new instance of the class. + /// + /// + public Histogram() + { + InitializeComponent(); + SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | + ControlStyles.DoubleBuffer | ControlStyles.UserPaint, true); + } + + /// + /// Dispose the object. + /// + /// + /// Indicates if disposing was initiated manually. + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + blackPen.Dispose(); + whitePen.Dispose(); + drawPen.Dispose(); + } + base.Dispose(disposing); + } + + // Init component + private void InitializeComponent() + { + // + // Histogram + // + this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.Histogram_MouseUp); + this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.Histogram_MouseMove); + this.MouseLeave += new System.EventHandler(this.Histogram_MouseLeave); + this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Histogram_MouseDown); + } + + /// + /// Paint the control. + /// + /// + /// Data for Paint event. + /// + protected override void OnPaint(PaintEventArgs e) + { + Graphics g = e.Graphics; + + // drawing area's width and height + width = ((values == null) || (vertical == true)) ? + ClientRectangle.Width - 2 : + Math.Min(values.Length, ClientRectangle.Width - 2); + + height = ((values == null) || (vertical == false)) ? + ClientRectangle.Height - 2 : + Math.Min(values.Length, ClientRectangle.Height - 2); + + int x = 1; + int y = 1; + int value; + + // draw rectangle around the image + g.DrawRectangle(blackPen, x - 1, y - 1, width + 1, height + 1); + + if (values != null) + { + int start = Math.Min(this.start, this.stop); + int stop = Math.Max(this.start, this.stop); + + if (tracking) + { + // fill region of selection + Brush brush = new SolidBrush(Color.FromArgb(92, 92, 92)); + + if (vertical) + { + g.FillRectangle(brush, x, y + start, width, Math.Abs(start - stop) + 1); + } + else + { + g.FillRectangle(brush, x + start, y, Math.Abs(start - stop) + 1, height); + } + brush.Dispose(); + } + + if (max != 0) + { + // scaling factor + double factor = (double)((vertical) ? width : height) / + ((logarithmic) ? maxLogarithmic : max); + + // draw histogram + for (int i = 0, len = (vertical) ? height : width; i < len; i++) + { + if (logarithmic) + { + value = (values[i] == 0) ? 0 : (int)(Math.Log10(values[i]) * factor); + } + else + { + value = (int)(values[i] * factor); + } + + if (value != 0) + { + if (vertical) + { + g.DrawLine(((tracking) && (i >= start) && (i <= stop)) ? whitePen : drawPen, + new Point(x, y + i), + new Point(x + value, y + i) + ); + } + else + { + g.DrawLine(((tracking) && (i >= start) && (i <= stop)) ? whitePen : drawPen, + new Point(x + i, y + height - 1), + new Point(x + i, y + height - value) + ); + } + } + } + } + } + + // Calling the base class OnPaint + base.OnPaint(e); + } + + // On mouse down + private void Histogram_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) + { + if ((allowSelection) && (values != null)) + { + int x = 1; + int y = 1; + + if ((e.X >= x) && (e.Y >= y) && (e.X < x + width) && (e.Y < y + height)) + { + // start selection + tracking = true; + start = (vertical) ? (e.Y - y) : (e.X - x); + this.Capture = true; + } + } + } + + // On mouse up + private void Histogram_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) + { + if (tracking) + { + // stop selection + tracking = false; + this.Capture = false; + Invalidate(); + } + } + + // On mouse move + private void Histogram_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) + { + if ((allowSelection) && (values != null)) + { + int x = 1; + int y = 1; + + if (!tracking) + { + if ((e.X >= x) && (e.Y >= y) && (e.X < x + width) && (e.Y < y + height)) + { + over = true; + + // moving over + this.Cursor = Cursors.Cross; + + // notify parent + if (PositionChanged != null) + { + PositionChanged(this, new HistogramEventArgs( + (vertical) ? (e.Y - y) : (e.X - x))); + } + } + else + { + this.Cursor = Cursors.Default; + + if (over) + { + over = false; + + // notify parent + if (PositionChanged != null) + PositionChanged(this, new HistogramEventArgs(-1)); + } + } + } + else + { + // selecting region + stop = (vertical) ? (e.Y - y) : (e.X - x); + + stop = Math.Min(stop, ((vertical) ? height : width) - 1); + stop = Math.Max(stop, 0); + + Invalidate(); + + // notify parent + if (SelectionChanged != null) + SelectionChanged(this, new HistogramEventArgs(Math.Min(start, stop), Math.Max(start, stop))); + } + } + } + + // On mouse leave + private void Histogram_MouseLeave(object sender, System.EventArgs e) + { + if ((allowSelection) && (values != null) && (!tracking)) + { + // notify parent + if (PositionChanged != null) + PositionChanged(this, new HistogramEventArgs(-1)); + } + } + } +} diff --git a/Sources/Accord.Controls.Imaging/AForge/Histogram.resx b/Sources/Accord.Controls.Imaging/AForge/Histogram.resx new file mode 100644 index 0000000000..085ebfbfa --- /dev/null +++ b/Sources/Accord.Controls.Imaging/AForge/Histogram.resx @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Histogram + + + False + + \ No newline at end of file diff --git a/Sources/Accord.Controls.Imaging/AForge/HuePicker.cs b/Sources/Accord.Controls.Imaging/AForge/HuePicker.cs new file mode 100644 index 0000000000..55795a81a --- /dev/null +++ b/Sources/Accord.Controls.Imaging/AForge/HuePicker.cs @@ -0,0 +1,410 @@ +// AForge Controls Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Windows.Forms; + +using AForge.Imaging; + +namespace AForge.Controls +{ + /// + /// Hue picker control. + /// + /// + /// The control allows selecting hue value (or range) from HSL color space. Hue values + /// are integer values in the [0, 359] range. + /// + /// If control's type is set to , then it allows selecting single + /// hue value and looks like this:
+ /// + ///
+ /// + /// If control's type is set to , then it allows selecting range + /// of hue values and looks like this:
+ /// + ///
+ ///
+ /// + public class HuePicker : System.Windows.Forms.Control + { + private HuePickerType type = HuePickerType.Value; + + private Pen blackPen; + private Brush blackBrush; + private Pen whitePen; + private Brush whiteBrush; + + private System.Drawing.Point ptCenter = new System.Drawing.Point(0, 0); + private System.Drawing.Point ptMin = new System.Drawing.Point(0, 0); + private System.Drawing.Point ptMax = new System.Drawing.Point(0, 0); + private int trackMode = 0; + + private int min = 0; + private int max = 359; + + /// + /// An event, to notify about changes of or properties. + /// + /// + /// The event is fired after changes of its , or + /// properties, which is caused by user dragging the corresponding hue picker's bullets. + /// + /// + public event EventHandler ValuesChanged; + + /// + /// Enumeration of hue picker types. + /// + /// + /// + /// The type provides single bullet to drag, which allows + /// selecting single hue value. The value is accessible through property. + /// + /// The type provides two bullets to drag, which correspond + /// to minimum and maximum values of the hue range. These values are accessible through + /// and properties. + /// + /// + public enum HuePickerType + { + /// + /// Selecting single hue value. + /// + Value, + /// + /// Selecting hue values range. + /// + Range + } + + /// + /// Selected value of the hue picker control in mode. + /// + [DefaultValue(0)] + public int Value + { + get { return min; } + set + { + if (type == HuePickerType.Value) + { + min = Math.Max(0, Math.Min(359, value)); + Invalidate(); + } + } + } + + /// + /// Minimum selected value of the hue picker control in mode. + /// + [DefaultValue(0)] + public int Min + { + get { return min; } + set + { + if (type == HuePickerType.Range) + { + min = Math.Max(0, Math.Min(359, value)); + Invalidate(); + } + } + } + + /// + /// Maximum selected value of the hue picker control in mode. + /// + [DefaultValue(359)] + public int Max + { + get { return max; } + set + { + if (type == HuePickerType.Range) + { + max = Math.Max(0, Math.Min(359, value)); + Invalidate(); + } + } + } + + /// + /// Current type of the hue picker control. + /// + /// + /// See enumeration for description of the available types. + /// + [DefaultValue(HuePickerType.Value)] + public HuePickerType Type + { + get { return type; } + set + { + type = value; + Invalidate(); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public HuePicker() + { + InitializeComponent(); + + SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | + ControlStyles.DoubleBuffer | ControlStyles.UserPaint, true); + + blackPen = new Pen(Color.Black, 1); + blackBrush = new SolidBrush(Color.Black); + whitePen = new Pen(Color.White, 1); + whiteBrush = new SolidBrush(Color.White); + } + + /// + /// Dispose the object. + /// + /// + /// Specifies if disposing was invoked by user's code. + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + blackPen.Dispose(); + blackBrush.Dispose(); + whitePen.Dispose(); + whiteBrush.Dispose(); + } + base.Dispose(disposing); + } + + // Init component + private void InitializeComponent() + { + // + // HSLPicker + // + this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.HSLPicker_MouseUp); + this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.HSLPicker_MouseMove); + this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.HSLPicker_MouseDown); + + } + + /// + /// Paint the controls. + /// + /// + /// Paint event arguments. + /// + protected override void OnPaint(PaintEventArgs e) + { + Graphics g = e.Graphics; + Rectangle rc = this.ClientRectangle; + Rectangle rcPie; + Brush brush; + RGB rgb = new RGB(); + HSL hsl = new HSL(); + + // get pie rectangle + rcPie = new Rectangle(4, 4, Math.Min(rc.Right, rc.Bottom) - 8, Math.Min(rc.Right, rc.Bottom) - 8); + + // init HSL value + hsl.Luminance = 0.5f; + hsl.Saturation = 1.0f; + + if (type == HuePickerType.Value) + { + // draw HSL pie + for (int i = 0; i < 360; i++) + { + hsl.Hue = i; + // convert from HSL to RGB + AForge.Imaging.HSL.ToRGB(hsl, rgb); + // create brush + brush = new SolidBrush(rgb.Color); + // draw one hue value + g.FillPie(brush, rcPie, -i, -1); + + brush.Dispose(); + } + } + else + { + // draw HSL pie + for (int i = 0; i < 360; i++) + { + if ( + ((min < max) && (i >= min) && (i <= max)) || + ((min > max) && ((i >= min) || (i <= max)))) + { + hsl.Hue = i; + // convert from HSL to RGB + AForge.Imaging.HSL.ToRGB(hsl, rgb); + // create brush + brush = new SolidBrush(rgb.Color); + } + else + { + brush = new SolidBrush(Color.FromArgb(128, 128, 128)); + } + + // draw one hue value + g.FillPie(brush, rcPie, -i, -1); + + brush.Dispose(); + } + } + + // + double halfWidth = (double)rcPie.Width / 2; + double angleRad = -min * Math.PI / 180; + double angleCos = Math.Cos(angleRad); + double angleSin = Math.Sin(angleRad); + + double x = halfWidth * angleCos; + double y = halfWidth * angleSin; + + ptCenter.X = rcPie.Left + (int)(halfWidth); + ptCenter.Y = rcPie.Top + (int)(halfWidth); + ptMin.X = rcPie.Left + (int)(halfWidth + x); + ptMin.Y = rcPie.Top + (int)(halfWidth + y); + + // draw MIN pointer + g.FillEllipse(blackBrush, + rcPie.Left + (int)(halfWidth + x) - 4, + rcPie.Top + (int)(halfWidth + y) - 4, + 8, 8); + g.DrawLine(blackPen, ptCenter, ptMin); + + // check picker type + if (type == HuePickerType.Range) + { + angleRad = -max * Math.PI / 180; + angleCos = Math.Cos(angleRad); + angleSin = Math.Sin(angleRad); + + x = halfWidth * angleCos; + y = halfWidth * angleSin; + + ptMax.X = rcPie.Left + (int)(halfWidth + x); + ptMax.Y = rcPie.Top + (int)(halfWidth + y); + + // draw MAX pointer + g.FillEllipse(whiteBrush, + rcPie.Left + (int)(halfWidth + x) - 4, + rcPie.Top + (int)(halfWidth + y) - 4, + 8, 8); + g.DrawLine(whitePen, ptCenter, ptMax); + } + + base.OnPaint(e); + } + + // On mouse down + private void HSLPicker_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) + { + // check coordinates of MIN pointer + if ((e.X >= ptMin.X - 4) && (e.Y >= ptMin.Y - 4) && + (e.X < ptMin.X + 4) && (e.Y < ptMin.Y + 4)) + { + trackMode = 1; + } + if (type == HuePickerType.Range) + { + // check coordinates of MAX pointer + if ((e.X >= ptMax.X - 4) && (e.Y >= ptMax.Y - 4) && + (e.X < ptMax.X + 4) && (e.Y < ptMax.Y + 4)) + { + trackMode = 2; + } + } + + if (trackMode != 0) + this.Capture = true; + } + + // On mouse up + private void HSLPicker_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) + { + if (trackMode != 0) + { + // release capture + this.Capture = false; + trackMode = 0; + + // notify client + if (ValuesChanged != null) + ValuesChanged(this, new EventArgs()); + } + } + + // On mouse move + private void HSLPicker_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) + { + Cursor cursor = Cursors.Default; + + if (trackMode != 0) + { + cursor = Cursors.Hand; + + int dy = e.Y - ptCenter.Y; + int dx = e.X - ptCenter.X; + + if (trackMode == 1) + { + // MIN pointer tracking + min = (int)(Math.Atan2(-dy, dx) * 180 / Math.PI); + if (min < 0) + { + min = 360 + min; + } + } + else + { + // MAX pointer tracking + max = (int)(Math.Atan2(-dy, dx) * 180 / Math.PI); + if (max < 0) + { + max = 360 + max; + } + } + + // repaint control + Invalidate(); + } + else + { + // check coordinates of MIN pointer + if ((e.X >= ptMin.X - 4) && (e.Y >= ptMin.Y - 4) && + (e.X < ptMin.X + 4) && (e.Y < ptMin.Y + 4)) + { + cursor = Cursors.Hand; + } + if (type == HuePickerType.Range) + { + // check coordinates of MAX pointer + if ((e.X >= ptMax.X - 4) && (e.Y >= ptMax.Y - 4) && + (e.X < ptMax.X + 4) && (e.Y < ptMax.Y + 4)) + { + cursor = Cursors.Hand; + } + } + + } + + this.Cursor = cursor; + } + } +} diff --git a/Sources/Accord.Controls.Imaging/AForge/HuePicker.resx b/Sources/Accord.Controls.Imaging/AForge/HuePicker.resx new file mode 100644 index 0000000000..0219f9f1b --- /dev/null +++ b/Sources/Accord.Controls.Imaging/AForge/HuePicker.resx @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + False + + + HSLPicker + + \ No newline at end of file diff --git a/Sources/Accord.Controls.Imaging/AForge/ManipulatorControl.Designer.cs b/Sources/Accord.Controls.Imaging/AForge/ManipulatorControl.Designer.cs new file mode 100644 index 0000000000..16fc5c312 --- /dev/null +++ b/Sources/Accord.Controls.Imaging/AForge/ManipulatorControl.Designer.cs @@ -0,0 +1,51 @@ +namespace AForge.Controls +{ + partial class ManipulatorControl + { + /// + /// Clean up any resources being used. + /// + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.timer = new System.Windows.Forms.Timer(this.components); + this.SuspendLayout(); + // + // timer + // + this.timer.Interval = 10; + this.timer.Tick += new System.EventHandler(this.timer_Tick); + // + // ManipulatorControl + // + this.Paint += new System.Windows.Forms.PaintEventHandler(this.ManipulatorControl_Paint); + this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.ManipulatorControl_MouseMove); + this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.ManipulatorControl_MouseDown); + this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.ManipulatorControl_MouseUp); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Timer timer; + private System.ComponentModel.IContainer components; + } +} diff --git a/Sources/Accord.Controls.Imaging/AForge/ManipulatorControl.cs b/Sources/Accord.Controls.Imaging/AForge/ManipulatorControl.cs new file mode 100644 index 0000000000..030cfe3e4 --- /dev/null +++ b/Sources/Accord.Controls.Imaging/AForge/ManipulatorControl.cs @@ -0,0 +1,617 @@ +// AForge Controls Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2010 +// andrew.kirillov@aforgenet.com +// + +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; + +namespace AForge.Controls +{ + /// + /// Manipulator control. + /// + /// + /// + /// The manipulator control can be used to mimic behaviour of analogue joystick using + /// regular mouse. By dragging manipulator away from control's centre, it fires + /// event notifying about its X/Y coordinates (or about R/Theta coordinates in Polar coordinates system). + /// + /// + /// For example, in robotics applications the control can be used to drive robots. If user drags manipulator + /// further from centre (increasing distance between centre and manipulator), then higher power (speed) should be + /// set for robot's motors. But dragging it in different directions away from centre should result in changing + /// robot's direction: straight forward, backward, turning right or left, etc.
+ /// + ///
+ /// + /// Another possible application of the control is to control position of some device, etc. + /// For example, the control could be used with pan-tilt camera - by dragging control away from centre, + /// the camera may rotate in one of the directions.
+ /// + ///
+ ///
+ /// + public partial class ManipulatorControl : Control + { + private bool isSquareLook = false; + private bool drawHorizontalAxis = true; + private bool drawVerticalAxis = false; + + private bool resetPositionOnMouseRelease = true; + + // pens and brushes for drawing + private Pen borderPen = new Pen(Color.Black); + private SolidBrush topLeftBackgroundBrush = new SolidBrush(Color.White); + private SolidBrush topRightBackgroundBrush = new SolidBrush(Color.White); + private SolidBrush bottomLeftBackgroundBrush = new SolidBrush(Color.LightGray); + private SolidBrush bottomRightBackgroundBrush = new SolidBrush(Color.LightGray); + private SolidBrush manipulatorBrush = new SolidBrush(Color.LightSeaGreen); + private SolidBrush disabledBrash = new SolidBrush(Color.FromArgb(240, 240, 240)); + + // manipulator's position + private float manipulatatorX = 0; + private float manipulatatorY = 0; + + // manipulator's size + private const int manipulatorSize = 21; + private const int manipulatorRadius = manipulatorSize / 2; + + // size (width and height) of manipulator's area + private int areaSize = 0; + private int areaRadius = 0; + private int areaMargin = manipulatorSize / 2 + 2; + + // tracking information + private bool tracking = false; + + // number of timer ticks before notifying user (-1 means no notification) + private int ticksBeforeNotificiation = -1; + + /// + /// Determines if the control has square or round look. + /// + /// + /// + /// The control has a square look if the property is set to , + /// otherwise it has round look. + /// + /// Default value is set to . + /// + /// + [DefaultValue(false)] + [Description("Determines if the control has square or round look.")] + public bool IsSquareLook + { + get { return isSquareLook; } + set + { + isSquareLook = value; + Invalidate(); + } + } + + /// + /// Determines if horizontal axis should be drawn or not. + /// + /// + /// + /// Default value is set to . + /// + /// + [DefaultValue(true)] + [Description("Determines if horizontal axis should be drawn or not.")] + public bool DrawHorizontalAxis + { + get { return drawHorizontalAxis; } + set + { + drawHorizontalAxis = value; + Invalidate(); + } + } + + /// + /// Determines if vertical axis should be drawn or not. + /// + /// + /// + /// Default value is set to . + /// + /// + [DefaultValue(false)] + [Description("Determines if vertical axis should be drawn or not.")] + public bool DrawVerticalAxis + { + get { return drawVerticalAxis; } + set + { + drawVerticalAxis = value; + Invalidate(); + } + } + + /// + /// Determines behaviour of manipulator, when mouse button is released. + /// + /// + /// + /// The property controls behaviour of manipulator on releasing mouse button. If + /// the property is set to , then position of manipulator is reset + /// to (0, 0), when mouse button is released. Otherwise manipulator stays on the place, + /// where it was left. + /// + /// Default value is set to . + /// + /// + [DefaultValue(true)] + [Description("Determines behaviour of manipulator, when mouse button is released.")] + public bool ResetPositionOnMouseRelease + { + get { return resetPositionOnMouseRelease; } + set { resetPositionOnMouseRelease = value; } + } + + /// + /// Color used for drawing borders and axis's. + /// + /// + /// + /// Default value is set to . + /// + /// + [DefaultValue(typeof(Color), "Black")] + [Description("Color used for drawing borders and axis's.")] + public Color BorderColor + { + get { return borderPen.Color; } + set + { + borderPen = new Pen(value); + Invalidate(); + } + } + + /// + /// Background color used for filling top left quarter of the control. + /// + /// + /// + /// Default value is set to . + /// + /// + [DefaultValue(typeof(Color), "White")] + [Description("Background color used for filling top left quarter of the control.")] + public Color TopLeftBackgroundColor + { + get { return topLeftBackgroundBrush.Color; } + set + { + topLeftBackgroundBrush = new SolidBrush(value); + Invalidate(); + } + } + + /// + /// Background color used for filling top right quarter of the control. + /// + /// + /// + /// Default value is set to . + /// + /// + [DefaultValue(typeof(Color), "White")] + [Description("Background color used for filling top right quarter of the control.")] + public Color TopRightBackgroundColor + { + get { return topRightBackgroundBrush.Color; } + set + { + topRightBackgroundBrush = new SolidBrush(value); + Invalidate(); + } + } + + /// + /// Background color used for filling bottom left quarter of the control. + /// + /// + /// + /// Default value is set to . + /// + /// + [DefaultValue(typeof(Color), "LightGray")] + [Description("Background color used for filling bottom left quarter of the control.")] + public Color BottomLeftBackgroundColor + { + get { return bottomLeftBackgroundBrush.Color; } + set + { + bottomLeftBackgroundBrush = new SolidBrush(value); + Invalidate(); + } + } + + /// + /// Background color used for filling bottom right quarter of the control. + /// + /// + /// + /// Default value is set to . + /// + /// + [DefaultValue(typeof(Color), "LightGray")] + [Description("Background color used for filling bottom right quarter of the control.")] + public Color BottomRightBackgroundColor + { + get { return bottomRightBackgroundBrush.Color; } + set + { + bottomRightBackgroundBrush = new SolidBrush(value); + Invalidate(); + } + } + + /// + /// Color used for filling manipulator. + /// + /// + /// + /// Default value is set to . + /// + /// + [DefaultValue(typeof(Color), "LightSeaGreen")] + [Description("Color used for filling manipulator.")] + public Color ManipulatorColor + { + get { return manipulatorBrush.Color; } + set + { + manipulatorBrush = new SolidBrush(value); + Invalidate(); + } + } + + /// + /// Class, which summarizes arguments of manipulator's position change event. + /// + /// + /// Properties of this class allow to get: + /// + /// X/Y coordinates of manipulator in + /// Cartesian coordinate system, + /// where X axis is directed from center of the control to the right and Y axis is directed from + /// center to the top. Both coordinates are measured in [-1, 1] range. + /// Theta and R coordinates of manipulator in + /// Polar coordinate system. + /// + /// + /// + public class PositionEventArgs : EventArgs + { + private float x, y; + + /// + /// X coordinate of manipulator, [-1, 1]. + /// + public float X + { + get { return x; } + } + + /// + /// Y coordinate of manipulator, [-1, 1]. + /// + public float Y + { + get { return y; } + } + + /// + /// Theta coordinate of manipulator in Polar coordinate system, [0, 359]. + /// + public float Theta + { + get + { + if (x != 0) + { + double t = Math.Atan(y / x); + t = t / Math.PI * 180; + + if (t < 0) + { + t += 180; + } + if (y < 0) + { + t += 180; + } + + return (float)t; + } + + return ((y > 0) ? 90 : ((y < 0) ? 270 : 0)); + } + } + + /// + /// R (radius) coordinate of manipulator in Polar coordinate system, [0, 1]. + /// + public float R + { + get { return (float)Math.Sqrt(x * x + y * y); } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// X coordinate of manipulator, [-1, 1]. + /// Y coordinate of manipulator, [-1, 1]. + /// + public PositionEventArgs(float x, float y) + { + this.x = x; + this.y = y; + } + } + + /// + /// Current manipulator's position. + /// + /// + /// The property equals to current manipulator's position. Both X and Y values + /// are in the [-1, 1] range and represented in + /// Cartesian coordinate system. + /// + /// + [Browsable(false)] + public PointF ManipulatorPosition + { + get { return new PointF(manipulatatorX, manipulatatorY); } + set + { + manipulatatorX = Math.Max(-1.0f, Math.Min(1.0f, value.X)); + manipulatatorY = Math.Max(-1.0f, Math.Min(1.0f, value.Y)); + + if (!isSquareLook) + { + // get distance from center + double cR = Math.Sqrt(manipulatatorX * manipulatatorX + manipulatatorY * manipulatatorY); + + // correct point if it is too far away + if (cR > 1) + { + double coef = (double)1 / cR; + manipulatatorX = (float)(coef * manipulatatorX); + manipulatatorY = (float)(coef * manipulatatorY); + } + } + Invalidate(); + NotifyClients(); + } + } + + /// + /// Delegate used for notification about manipulator's position changes. + /// + /// + /// Event sender - object sending the event. + /// Event arguments - current manipulator's position. + /// + public delegate void PositionChangedHandler(object sender, PositionEventArgs eventArgs); + + /// + /// Event used for notification about manipulator's position changes. + /// + [Description("Occurs when manipulator's position is changed.")] + public event PositionChangedHandler PositionChanged; + + /// + /// Initializes a new instance of the class. + /// + public ManipulatorControl() + { + InitializeComponent(); + + // update control style + SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | + ControlStyles.DoubleBuffer | ControlStyles.UserPaint, true); + } + + // Paint the control + private void ManipulatorControl_Paint(object sender, PaintEventArgs e) + { + Graphics g = e.Graphics; + + // calculate size of the manipulator's ares + areaSize = Math.Min(ClientRectangle.Width, ClientRectangle.Height) - areaMargin * 2; + areaRadius = areaSize / 2; + + // draw area + if (areaSize > 1) + { + if (isSquareLook) + { + // square looking control + int halfAreaSize = areaSize / 2; + + g.FillRectangle((!this.Enabled) ? disabledBrash : topLeftBackgroundBrush, areaMargin, areaMargin, halfAreaSize, halfAreaSize); + g.FillRectangle((!this.Enabled) ? disabledBrash : topRightBackgroundBrush, areaMargin + halfAreaSize, areaMargin, areaSize - halfAreaSize, halfAreaSize); + g.FillRectangle((!this.Enabled) ? disabledBrash : bottomLeftBackgroundBrush, areaMargin, areaMargin + halfAreaSize, halfAreaSize, areaSize - halfAreaSize); + g.FillRectangle((!this.Enabled) ? disabledBrash : bottomRightBackgroundBrush, areaMargin + halfAreaSize, areaMargin + halfAreaSize, + areaSize - halfAreaSize, areaSize - halfAreaSize); + + g.DrawRectangle(borderPen, areaMargin, areaMargin, areaSize - 1, areaSize - 1); + } + else + { + // round looking control + g.FillPie((this.Enabled) ? topRightBackgroundBrush : disabledBrash, areaMargin, areaMargin, areaSize - 1, areaSize - 1, 0, -90); + g.FillPie((this.Enabled) ? topLeftBackgroundBrush : disabledBrash, areaMargin, areaMargin, areaSize - 1, areaSize - 1, -90, -90); + g.FillPie((this.Enabled) ? bottomRightBackgroundBrush : disabledBrash, areaMargin, areaMargin, areaSize - 1, areaSize - 1, 0, 90); + g.FillPie((this.Enabled) ? bottomLeftBackgroundBrush : disabledBrash, areaMargin, areaMargin, areaSize - 1, areaSize - 1, 90, 90); + g.DrawEllipse(borderPen, areaMargin, areaMargin, areaSize - 1, areaSize - 1); + } + } + + // draw axis or not ? + if (drawHorizontalAxis) + { + g.DrawLine(borderPen, areaMargin, areaMargin + areaRadius, areaMargin + areaSize - 1, areaMargin + areaRadius); + } + if (drawVerticalAxis) + { + g.DrawLine(borderPen, areaMargin + areaRadius, areaMargin, areaMargin + areaRadius, areaMargin + areaSize - 1); + } + + // calculate manipulator's center point + int ctrlManipulatorX = (int)(manipulatatorX * areaRadius) + areaMargin + areaRadius; + int ctrlManipulatorY = (int)(-manipulatatorY * areaRadius) + areaMargin + areaRadius; + + // draw manipulator + g.FillEllipse((this.Enabled) ? manipulatorBrush : disabledBrash, + ctrlManipulatorX - manipulatorRadius, ctrlManipulatorY - manipulatorRadius, + manipulatorSize, manipulatorSize); + g.DrawEllipse(borderPen, + ctrlManipulatorX - manipulatorRadius, ctrlManipulatorY - manipulatorRadius, + manipulatorSize, manipulatorSize); + } + + // On mouse down event + private void ManipulatorControl_MouseDown(object sender, MouseEventArgs e) + { + if (e.Button == MouseButtons.Left) + { + // get click point relatively to manipulation area's center + int cX = e.X - areaMargin - areaRadius; + int cY = e.Y - areaMargin - areaRadius; + + if (isSquareLook) + { + if ( + (cX <= areaRadius) && (cX >= -areaRadius) && + (cY <= areaRadius) && (cY >= -areaRadius)) + { + tracking = true; + } + } + else + { + // check if the point is inside of manipulator + if (Math.Sqrt(cX * cX + cY * cY) <= areaRadius) + { + tracking = true; + } + } + + if (tracking) + { + manipulatatorX = (float)cX / areaRadius; + manipulatatorY = (float)-cY / areaRadius; + + this.Capture = true; + this.Cursor = Cursors.Hand; + + NotifyClients(); + // start timer, which is used to notify + // about manipulator's position change + ticksBeforeNotificiation = -1; + timer.Start(); + } + } + } + + // On mouse up event + private void ManipulatorControl_MouseUp(object sender, MouseEventArgs e) + { + if ((e.Button == MouseButtons.Left) && (tracking)) + { + tracking = false; + this.Capture = false; + this.Cursor = Cursors.Arrow; + + timer.Stop(); + + if (resetPositionOnMouseRelease) + { + manipulatatorX = 0; + manipulatatorY = 0; + } + + NotifyClients(); + + Invalidate(); + } + } + + // On mouse move event + private void ManipulatorControl_MouseMove(object sender, MouseEventArgs e) + { + if (tracking) + { + // get mouse point relatively to manipulation area's center + int cX = e.X - areaMargin - areaRadius; + int cY = e.Y - areaMargin - areaRadius; + + if (isSquareLook) + { + cX = Math.Min(areaRadius, Math.Max(-areaRadius, cX)); + cY = Math.Min(areaRadius, Math.Max(-areaRadius, cY)); + } + else + { + // get distance from center + int cR = (int)Math.Sqrt(cX * cX + cY * cY); + + // correct point if it is too far away + if (cR > areaRadius) + { + double coef = (double)areaRadius / cR; + cX = (int)(coef * cX); + cY = (int)(coef * cY); + } + } + + manipulatatorX = (float)cX / areaRadius; + manipulatatorY = (float)-cY / areaRadius; + + Invalidate(); + + // notify user after 5 timer ticks + ticksBeforeNotificiation = 5; + } + } + + // Timer handler, which is used to notify clients about manipulator's changes + private void timer_Tick(object sender, EventArgs e) + { + if (ticksBeforeNotificiation != -1) + { + // time to notify + if (ticksBeforeNotificiation == 0) + { + // notify users + NotifyClients(); + } + + ticksBeforeNotificiation--; + } + } + + // Notify client about changes of manipulator's position + private void NotifyClients() + { + if (PositionChanged != null) + { + PositionChanged(this, new PositionEventArgs(manipulatatorX, manipulatatorY)); + } + } + } +} diff --git a/Sources/Accord.Controls.Imaging/AForge/ManipulatorControl.resx b/Sources/Accord.Controls.Imaging/AForge/ManipulatorControl.resx new file mode 100644 index 0000000000..2c946ec6d --- /dev/null +++ b/Sources/Accord.Controls.Imaging/AForge/ManipulatorControl.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + False + + \ No newline at end of file diff --git a/Sources/Accord.Controls.Imaging/AForge/PictureBox.cs b/Sources/Accord.Controls.Imaging/AForge/PictureBox.cs new file mode 100644 index 0000000000..af97a546e --- /dev/null +++ b/Sources/Accord.Controls.Imaging/AForge/PictureBox.cs @@ -0,0 +1,91 @@ +// AForge Controls Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +using System; +using System.Drawing; +using System.Drawing.Imaging; + +namespace AForge.Controls +{ + /// + /// Picture box control for displaying an image. + /// + /// + /// This control is inherited from System.Windows.Forms.PictureBox and is + /// aimed to resolve one of its issues - inability to display images with high color depth, + /// like 16 bpp grayscale, 48 bpp and 64 bpp color images. .NET framework does not handle + /// 16 bpp grayscale images at all, throwing exception when user tries to display them. Color + /// images with 48 bpp and 64 bpp are "kind of" supported, but only maximum of 13 bits for each + /// color plane are allowed. Therefore this control is created, which allows to display as + /// 16 bpp grayscale images, as 48 bpp and 64 bpp color images. + /// + /// To display high color depth images, the control does internal conversion of them + /// to lower color depth images - 8 bpp grayscale, 24 bpp and 32 bpp color images respectively. In + /// the case source image already has low color depth, it is displayed without any conversions. + /// + /// + /// + public class PictureBox : System.Windows.Forms.PictureBox + { + private Image sourceImage = null; + private Image convertedImage = null; + + /// + /// Gets or sets the image that the PictureBox displays. + /// + /// + /// The property is used to set image to be displayed or to get currently + /// displayed image. + /// + /// In the case if source image has high color depth, like 16 bpp grayscale image, + /// 48 bpp or 64 bpp color image, it is converted to lower color depth before displaying - + /// to 8 bpp grayscale, 24 bpp or 32 bpp color image respectively. + /// + /// During color conversion the original source image is kept unmodified, but internal + /// converted copy is created. The property always returns original source image. + /// + /// + public new Image Image + { + get { return sourceImage; } + set + { + Bitmap bmp = value as Bitmap; + + // check source image format + if ((bmp != null) && + ((value.PixelFormat == PixelFormat.Format16bppGrayScale) || + (value.PixelFormat == PixelFormat.Format48bppRgb) || + (value.PixelFormat == PixelFormat.Format64bppArgb))) + { + // convert and display image + Image tempImage = AForge.Imaging.Image.Convert16bppTo8bpp(bmp); + + base.Image = tempImage; + + // dispose previous image if required + if (convertedImage != null) + { + convertedImage.Dispose(); + } + + convertedImage = tempImage; + } + else + { + // display source image as it is + base.Image = value; + } + + sourceImage = value; + } + } + + + } +} diff --git a/Sources/Accord.Controls.Imaging/AForge/Resources/arrow.bmp b/Sources/Accord.Controls.Imaging/AForge/Resources/arrow.bmp new file mode 100644 index 0000000000..4a1d9a68d Binary files /dev/null and b/Sources/Accord.Controls.Imaging/AForge/Resources/arrow.bmp differ diff --git a/Sources/Accord.Controls.Imaging/AForge/SliderControl.Designer.cs b/Sources/Accord.Controls.Imaging/AForge/SliderControl.Designer.cs new file mode 100644 index 0000000000..a9362143d --- /dev/null +++ b/Sources/Accord.Controls.Imaging/AForge/SliderControl.Designer.cs @@ -0,0 +1,54 @@ +namespace AForge.Controls +{ + partial class SliderControl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.timer = new System.Windows.Forms.Timer(this.components); + this.SuspendLayout(); + // + // timer + // + this.timer.Interval = 10; + this.timer.Tick += new System.EventHandler(this.timer_Tick); + // + // TurnControl + // + this.Paint += new System.Windows.Forms.PaintEventHandler(this.TurnControl_Paint); + this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.TurnControl_MouseMove); + this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.TurnControl_MouseDown); + this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.TurnControl_MouseUp); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Timer timer; + } +} diff --git a/Sources/Accord.Controls.Imaging/AForge/SliderControl.cs b/Sources/Accord.Controls.Imaging/AForge/SliderControl.cs new file mode 100644 index 0000000000..236f621d6 --- /dev/null +++ b/Sources/Accord.Controls.Imaging/AForge/SliderControl.cs @@ -0,0 +1,407 @@ +// AForge Controls Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2010 +// andrew.kirillov@aforgenet.com +// + +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; + +namespace AForge.Controls +{ + /// + /// Slider control. + /// + /// + /// + /// The control represents a slider, which can be dragged in the [-1, 1] range. + /// Default position of the slider is set 0, which corresponds to center of the control.
+ /// + ///
+ ///
+ /// + public partial class SliderControl : Control + { + // horizontal or vertical configuration + private bool isHorizontal = true; + + private bool resetPositionOnMouseRelease = true; + + // pens and brushes for drawing + private Pen borderPen = new Pen(Color.Black); + private SolidBrush positiveAreaBrush = new SolidBrush(Color.White); + private SolidBrush negativeAreaBrush = new SolidBrush(Color.LightGray); + private SolidBrush manipulatorBrush = new SolidBrush(Color.LightSeaGreen); + private SolidBrush disabledBrash = new SolidBrush(Color.FromArgb(240, 240, 240)); + + // manipulator's size + private const int manipulatorWidth = 11; + private const int manipulatorHeight = 20; + + // margins + private int leftMargin; + private int topMargin; + + // manipulator's position + private float manipulatatorPosition = 0; + + // tracking information + private bool tracking = false; + + // number of timer ticks before notifying user (-1 means no notification) + private int ticksBeforeNotificiation = -1; + + /// + /// Determines behaviour of manipulator, when mouse button is released. + /// + /// + /// + /// The property controls behaviour of manipulator on releasing mouse button. If + /// the property is set to , then position of manipulator is reset + /// to 0, when mouse button is released. Otherwise manipulator stays on the place, + /// where it was left. + /// + /// Default value is set to . + /// + /// + [DefaultValue(true)] + [Description("Determines behaviour of manipulator, when mouse button is released.")] + public bool ResetPositionOnMouseRelease + { + get { return resetPositionOnMouseRelease; } + set { resetPositionOnMouseRelease = value; } + } + + /// + /// Color used for drawing borders. + /// + /// + /// + /// Default value is set to . + /// + /// + [DefaultValue(typeof(Color), "Black")] + [Description("Color used for drawing borders.")] + public Color BorderColor + { + get { return borderPen.Color; } + set + { + borderPen = new Pen(value); + Invalidate(); + } + } + + /// + /// Background color used for filling area corresponding to positive values. + /// + /// + /// + /// Default value is set to . + /// + /// + [DefaultValue(typeof(Color), "White")] + [Description("Background color used for filling area corresponding to positive values.")] + public Color PositiveAreaBrush + { + get { return positiveAreaBrush.Color; } + set + { + positiveAreaBrush = new SolidBrush(value); + Invalidate(); + } + } + + /// + /// Background color used for filling area corresponding to negative values. + /// + /// + /// + /// Default value is set to . + /// + /// + [DefaultValue(typeof(Color), "LightGray")] + [Description("Background color used for filling top right quarter of the control.")] + public Color NegativeAreaBrush + { + get { return negativeAreaBrush.Color; } + set + { + negativeAreaBrush = new SolidBrush(value); + Invalidate(); + } + } + + /// + /// Color used for filling manipulator. + /// + /// + /// + /// Default value is set to . + /// + /// + [DefaultValue(typeof(Color), "LightSeaGreen")] + [Description("Color used for filling manipulator.")] + public Color ManipulatorColor + { + get { return manipulatorBrush.Color; } + set + { + manipulatorBrush = new SolidBrush(value); + Invalidate(); + } + } + + /// + /// Defines if control has horizontal or vertical look. + /// + /// + /// + /// Default value is set to . + /// + /// + [DefaultValue(true)] + [Description("Defines if control has horizontal or vertical look.")] + public bool IsHorizontal + { + get { return isHorizontal; } + set + { + isHorizontal = value; + + if (value) + { + leftMargin = manipulatorWidth / 2 + 2; + topMargin = manipulatorHeight / 4; + } + else + { + leftMargin = manipulatorHeight / 4; + topMargin = manipulatorWidth / 2 + 2; + } + + Invalidate(); + } + } + + /// + /// Current manipulator's position, [-1, 1]. + /// + /// + /// The property equals to current manipulator's position. + /// + /// + [Browsable(false)] + public float ManipulatorPosition + { + get { return manipulatatorPosition; } + set + { + manipulatatorPosition = Math.Max(-1.0f, Math.Min(1.0f, value)); + Invalidate(); + NotifyClients(); + } + } + + /// + /// Delegate used for notification about manipulator's position changes. + /// + /// + /// Event sender - object sending the event. + /// Current position of manipulator. + /// + public delegate void PositionChangedHandler(object sender, float position); + + /// + /// Event used for notification about manipulator's position changes. + /// + [Description("Occurs when manipulator's position is changed.")] + public event PositionChangedHandler PositionChanged; + + /// + /// Initializes a new instance of the class. + /// + public SliderControl() + { + InitializeComponent(); + + // update control style + SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | + ControlStyles.DoubleBuffer | ControlStyles.UserPaint, true); + + IsHorizontal = true; + } + + // Paint the control + private void TurnControl_Paint(object sender, PaintEventArgs e) + { + Graphics g = e.Graphics; + + int clientWidth = ClientRectangle.Width; + int clientHeight = ClientRectangle.Height; + + if (isHorizontal) + { + // draw area + g.FillRectangle((this.Enabled) ? negativeAreaBrush : disabledBrash, leftMargin, topMargin, + clientWidth / 2 - leftMargin, manipulatorHeight / 2); + g.FillRectangle((this.Enabled) ? positiveAreaBrush : disabledBrash, clientWidth / 2, topMargin, + clientWidth / 2 - leftMargin, manipulatorHeight / 2); + g.DrawRectangle(borderPen, leftMargin, topMargin, + clientWidth - 1 - leftMargin * 2, manipulatorHeight / 2); + g.DrawLine(borderPen, clientWidth / 2, topMargin, clientWidth / 2, topMargin + manipulatorHeight / 2); + + // calculate manipulator's center point + int ctrlManipulatorX = (int)(manipulatatorPosition * (clientWidth / 2 - leftMargin) + clientWidth / 2); + + // draw manipulator + g.FillRectangle((this.Enabled) ? manipulatorBrush : disabledBrash, ctrlManipulatorX - manipulatorWidth / 2, 0, + manipulatorWidth, manipulatorHeight); + g.DrawRectangle(borderPen, ctrlManipulatorX - manipulatorWidth / 2, 0, + manipulatorWidth, manipulatorHeight); + } + else + { + // draw area + g.FillRectangle((this.Enabled) ? positiveAreaBrush : disabledBrash, leftMargin, topMargin, + manipulatorHeight / 2, clientHeight / 2 - topMargin); + g.FillRectangle((this.Enabled) ? negativeAreaBrush : disabledBrash, leftMargin, clientHeight / 2, + manipulatorHeight / 2, clientHeight / 2 - topMargin); + g.DrawRectangle(borderPen, leftMargin, topMargin, + manipulatorHeight / 2, clientHeight - 1 - topMargin * 2); + g.DrawLine(borderPen, leftMargin, clientHeight / 2, leftMargin + manipulatorHeight / 2, clientHeight / 2); + + + // calculate manipulator's center point + int ctrlManipulatorY = (int)(-manipulatatorPosition * (clientHeight / 2 - topMargin) + clientHeight / 2); + + // draw manipulator + g.FillRectangle((this.Enabled) ? manipulatorBrush : disabledBrash, 0, ctrlManipulatorY - manipulatorWidth / 2, + manipulatorHeight, manipulatorWidth); + g.DrawRectangle(borderPen, 0, ctrlManipulatorY - manipulatorWidth / 2, + manipulatorHeight, manipulatorWidth); + } + } + + // On mouse down event + private void TurnControl_MouseDown(object sender, MouseEventArgs e) + { + if (e.Button == MouseButtons.Left) + { + if (isHorizontal) + { + if ( + (e.X >= leftMargin) && + (e.X < ClientRectangle.Width - leftMargin) && + (e.Y >= topMargin) && + (e.Y < ClientRectangle.Height - topMargin)) + { + int cx = e.X - ClientRectangle.Width / 2; + manipulatatorPosition = (float)cx / (ClientRectangle.Width / 2 - leftMargin); + tracking = true; + } + } + else + { + if ( + (e.X >= leftMargin) && + (e.X < ClientRectangle.Width - leftMargin) && + (e.Y >= topMargin) && + (e.Y < ClientRectangle.Height - topMargin)) + { + int cy = ClientRectangle.Height / 2 - e.Y; + manipulatatorPosition = (float)cy / (ClientRectangle.Height / 2 - topMargin); + tracking = true; + } + } + + if (tracking) + { + this.Capture = true; + this.Cursor = Cursors.Hand; + + NotifyClients(); + // start time, which is used to notify + // about manipulator's position change + ticksBeforeNotificiation = -1; + timer.Start(); + } + } + } + + // On mouse up event + private void TurnControl_MouseUp(object sender, MouseEventArgs e) + { + if ((e.Button == MouseButtons.Left) && (tracking)) + { + tracking = false; + this.Capture = false; + this.Cursor = Cursors.Arrow; + + if (resetPositionOnMouseRelease) + { + manipulatatorPosition = 0; + } + + Invalidate(); + timer.Stop(); + + NotifyClients(); + } + } + + // On mouse move event + private void TurnControl_MouseMove(object sender, MouseEventArgs e) + { + if (tracking) + { + if (isHorizontal) + { + int cx = e.X - ClientRectangle.Width / 2; + manipulatatorPosition = (float)cx / (ClientRectangle.Width / 2 - leftMargin); + } + else + { + int cy = ClientRectangle.Height / 2 - e.Y; + manipulatatorPosition = (float)cy / (ClientRectangle.Height / 2 - topMargin); + } + + manipulatatorPosition = Math.Max(Math.Min(1, manipulatatorPosition), -1); + Invalidate(); + + // notify user after 10 timer ticks + ticksBeforeNotificiation = 5; + } + } + + // Timer handler, which is used to notify clients about manipulator's changes + private void timer_Tick(object sender, EventArgs e) + { + if (ticksBeforeNotificiation != -1) + { + // time to notify + if (ticksBeforeNotificiation == 0) + { + // notify users + NotifyClients(); + } + + ticksBeforeNotificiation--; + } + } + + // Notify client about changes of manipulator's position + private void NotifyClients() + { + if (PositionChanged != null) + { + PositionChanged(this, manipulatatorPosition); + } + } + + } +} diff --git a/Sources/Accord.Controls.Imaging/AForge/SliderControl.resx b/Sources/Accord.Controls.Imaging/AForge/SliderControl.resx new file mode 100644 index 0000000000..2c946ec6d --- /dev/null +++ b/Sources/Accord.Controls.Imaging/AForge/SliderControl.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + False + + \ No newline at end of file diff --git a/Sources/Accord.Controls.Imaging/AForge/VideoSourcePlayer.Designer.cs b/Sources/Accord.Controls.Imaging/AForge/VideoSourcePlayer.Designer.cs new file mode 100644 index 0000000000..fe57aef16 --- /dev/null +++ b/Sources/Accord.Controls.Imaging/AForge/VideoSourcePlayer.Designer.cs @@ -0,0 +1,50 @@ +// AForge Controls Library +// AForge.NET framework +// +// Copyright © Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Controls +{ + partial class VideoSourcePlayer + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.SuspendLayout( ); + // + // VideoSourcePlayer + // + this.Paint += new System.Windows.Forms.PaintEventHandler( this.VideoSourcePlayer_Paint ); + this.ParentChanged += new System.EventHandler( this.VideoSourcePlayer_ParentChanged ); + this.ResumeLayout( false ); + + } + + #endregion + } +} diff --git a/Sources/Accord.Controls.Imaging/AForge/VideoSourcePlayer.cs b/Sources/Accord.Controls.Imaging/AForge/VideoSourcePlayer.cs new file mode 100644 index 0000000000..6484c434a --- /dev/null +++ b/Sources/Accord.Controls.Imaging/AForge/VideoSourcePlayer.cs @@ -0,0 +1,607 @@ +// AForge Controls Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2012 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Drawing.Imaging; +using System.Data; +using System.Text; +using System.Threading; +using System.Windows.Forms; + +using AForge.Video; + +namespace AForge.Controls +{ + using Point = System.Drawing.Point; + + /// + /// Video source player control. + /// + /// + /// The control is aimed to play video sources, which implement + /// interface. To start playing a video + /// the property should be initialized first and then + /// method should be called. In the case if user needs to + /// perform some sort of image processing with video frames before they are displayed, + /// the event may be used. + /// + /// Sample usage: + /// + /// // set new frame event handler if we need processing of new frames + /// playerControl.NewFrame += new VideoSourcePlayer.NewFrameHandler( this.playerControl_NewFrame ); + /// + /// // create video source + /// IVideoSource videoSource = new ... + /// // start playing it + /// playerControl.VideoSource = videoSource; + /// playerControl.Start( ); + /// ... + /// + /// // new frame event handler + /// private void playerControl_NewFrame( object sender, ref Bitmap image ) + /// { + /// // process new frame somehow ... + /// + /// // Note: it may be even changed, so the control will display the result + /// // of image processing done here + /// } + /// + /// + /// + public partial class VideoSourcePlayer : Control + { + // video source to play + private IVideoSource videoSource = null; + // last received frame from the video source + private Bitmap currentFrame = null; + // converted version of the current frame (in the case if current frame is a 16 bpp + // per color plane image, then the converted image is its 8 bpp version for rendering) + private Bitmap convertedFrame = null; + // last error message provided by video source + private string lastMessage = null; + // controls border color + private Color borderColor = Color.Black; + + private Size frameSize = new Size(320, 240); + private bool autosize = false; + private bool keepRatio = false; + private bool needSizeUpdate = false; + private bool firstFrameNotProcessed = true; + private volatile bool requestedToStop = false; + + // parent of the control + private Control parent = null; + + // dummy object to lock for synchronization + private object sync = new object(); + + /// + /// Auto size control or not. + /// + /// + /// The property specifies if the control should be autosized or not. + /// If the property is set to , then the control will change its size according to + /// video size and control will change its position automatically to be in the center + /// of parent's control. + /// + /// Setting the property to has no effect if + /// property is set to . + /// + /// + [DefaultValue(false)] + public bool AutoSizeControl + { + get { return autosize; } + set + { + autosize = value; + UpdatePosition(); + } + } + + /// + /// Gets or sets whether the player should keep the aspect ratio of the images being shown. + /// + /// + [DefaultValue(false)] + public bool KeepAspectRatio + { + get { return keepRatio; } + set + { + keepRatio = value; + Invalidate(); + } + } + + /// + /// Control's border color. + /// + /// + /// Specifies color of the border drawn around video frame. + /// + [DefaultValue(typeof(Color), "Black")] + public Color BorderColor + { + get { return borderColor; } + set + { + borderColor = value; + Invalidate(); + } + } + + /// + /// Video source to play. + /// + /// + /// The property sets the video source to play. After setting the property the + /// method should be used to start playing the video source. + /// + /// Trying to change video source while currently set video source is still playing + /// will generate an exception. Use property to check if current video + /// source is still playing or or and + /// methods to stop current video source. + /// + /// + /// Video source can not be changed while current video source is still running. + /// + [Browsable(false)] + public IVideoSource VideoSource + { + get { return videoSource; } + set + { + CheckForCrossThreadAccess(); + + // detach events + if (videoSource != null) + { + videoSource.NewFrame -= new NewFrameEventHandler(videoSource_NewFrame); + videoSource.VideoSourceError -= new VideoSourceErrorEventHandler(videoSource_VideoSourceError); + videoSource.PlayingFinished -= new PlayingFinishedEventHandler(videoSource_PlayingFinished); + } + + lock (sync) + { + if (currentFrame != null) + { + currentFrame.Dispose(); + currentFrame = null; + } + } + + videoSource = value; + + // atach events + if (videoSource != null) + { + videoSource.NewFrame += new NewFrameEventHandler(videoSource_NewFrame); + videoSource.VideoSourceError += new VideoSourceErrorEventHandler(videoSource_VideoSourceError); + videoSource.PlayingFinished += new PlayingFinishedEventHandler(videoSource_PlayingFinished); + } + else + { + frameSize = new Size(320, 240); + } + + lastMessage = null; + needSizeUpdate = true; + firstFrameNotProcessed = true; + // update the control + Invalidate(); + } + } + + /// + /// State of the current video source. + /// + /// + /// Current state of the current video source object - running or not. + /// + [Browsable(false)] + public bool IsRunning + { + get + { + CheckForCrossThreadAccess(); + + return (videoSource != null) ? videoSource.IsRunning : false; + } + } + + /// + /// Delegate to notify about new frame. + /// + /// + /// Event sender. + /// New frame. + /// + public delegate void NewFrameHandler(object sender, ref Bitmap image); + + /// + /// New frame event. + /// + /// + /// The event is fired on each new frame received from video source. The + /// event is fired right after receiving and before displaying, what gives user a chance to + /// perform some image processing on the new frame and/or update it. + /// + /// Users should not keep references of the passed to the event handler image. + /// If user needs to keep the image, it should be cloned, since the original image will be disposed + /// by the control when it is required. + /// + /// + public event NewFrameHandler NewFrame; + + /// + /// Playing finished event. + /// + /// + /// The event is fired when/if video playing finishes. The reason of video + /// stopping is provided as an argument to the event handler. + /// + public event PlayingFinishedEventHandler PlayingFinished; + + /// + /// Initializes a new instance of the class. + /// + public VideoSourcePlayer() + { + InitializeComponent(); + + // update control style + SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | + ControlStyles.DoubleBuffer | ControlStyles.UserPaint, true); + } + + // Check if the control is accessed from a none UI thread + private void CheckForCrossThreadAccess() + { + // force handle creation, so InvokeRequired() will use it instead of searching through parent's chain + if (!IsHandleCreated) + { + CreateControl(); + + // if the control is not Visible, then CreateControl() will not be enough + if (!IsHandleCreated) + { + CreateHandle(); + } + } + + if (InvokeRequired) + { + throw new InvalidOperationException("Cross thread access to the control is not allowed."); + } + } + + /// + /// Start video source and displaying its frames. + /// + public void Start() + { + CheckForCrossThreadAccess(); + + requestedToStop = false; + + if (videoSource != null) + { + firstFrameNotProcessed = true; + + videoSource.Start(); + Invalidate(); + } + } + + /// + /// Stop video source. + /// + /// + /// The method stops video source by calling its + /// method, which abourts internal video source's thread. Use and + /// for more polite video source stopping, which gives a chance for + /// video source to perform proper shut down and clean up. + /// + /// + public void Stop() + { + CheckForCrossThreadAccess(); + + requestedToStop = true; + + if (videoSource != null) + { + videoSource.Stop(); + + if (currentFrame != null) + { + currentFrame.Dispose(); + currentFrame = null; + } + + Invalidate(); + } + } + + /// + /// Signal video source to stop. + /// + /// + /// Use method to wait until video source + /// stops. + /// + public void SignalToStop() + { + CheckForCrossThreadAccess(); + + requestedToStop = true; + + if (videoSource != null) + { + videoSource.SignalToStop(); + } + } + + /// + /// Wait for video source has stopped. + /// + /// + /// Waits for video source stopping after it was signaled to stop using + /// method. If was not called, then + /// it will be called automatically. + /// + public void WaitForStop() + { + CheckForCrossThreadAccess(); + + if (!requestedToStop) + { + SignalToStop(); + } + + if (videoSource != null) + { + videoSource.WaitForStop(); + + if (currentFrame != null) + { + currentFrame.Dispose(); + currentFrame = null; + } + + Invalidate(); + } + } + + /// + /// Get clone of current video frame displayed by the control. + /// + /// + /// Returns copy of the video frame, which is currently displayed + /// by the control - the last video frame received from video source. If the + /// control did not receive any video frames yet, then the method returns + /// . + /// + public Bitmap GetCurrentVideoFrame() + { + lock (sync) + { + return (currentFrame == null) ? null : AForge.Imaging.Image.Clone(currentFrame); + } + } + + // Paint control + private void VideoSourcePlayer_Paint(object sender, PaintEventArgs e) + { + if (!Visible) + { + return; + } + + // is it required to update control's size/position + if ((needSizeUpdate) || (firstFrameNotProcessed)) + { + UpdatePosition(); + needSizeUpdate = false; + } + + lock (sync) + { + Graphics g = e.Graphics; + Rectangle rect = this.ClientRectangle; + Pen borderPen = new Pen(borderColor, 1); + + // draw rectangle + g.DrawRectangle(borderPen, rect.X, rect.Y, rect.Width - 1, rect.Height - 1); + + if (videoSource != null) + { + if ((currentFrame != null) && (lastMessage == null)) + { + Bitmap frame = (convertedFrame != null) ? convertedFrame : currentFrame; + + if (keepRatio) + { + double ratio = (double)frame.Width / frame.Height; + Rectangle newRect = rect; + + if (rect.Width < rect.Height * ratio) + { + newRect.Height = (int)(rect.Width / ratio); + } + else + { + newRect.Width = (int)(rect.Height * ratio); + } + + newRect.X = (rect.Width - newRect.Width) / 2; + newRect.Y = (rect.Height - newRect.Height) / 2; + + g.DrawImage(frame, newRect.X + 1, newRect.Y + 1, newRect.Width - 2, newRect.Height - 2); + } + else + { + // draw current frame + g.DrawImage(frame, rect.X + 1, rect.Y + 1, rect.Width - 2, rect.Height - 2); + } + + firstFrameNotProcessed = false; + } + else + { + // create font and brush + SolidBrush drawBrush = new SolidBrush(this.ForeColor); + + g.DrawString((lastMessage == null) ? "Connecting ..." : lastMessage, + this.Font, drawBrush, new PointF(5, 5)); + + drawBrush.Dispose(); + } + } + + borderPen.Dispose(); + } + } + + // Update controls size and position + private void UpdatePosition() + { + if ((autosize) && (this.Dock != DockStyle.Fill) && (this.Parent != null)) + { + Rectangle rc = this.Parent.ClientRectangle; + int width = frameSize.Width; + int height = frameSize.Height; + + // update controls size and location + this.SuspendLayout(); + this.Location = new Point((rc.Width - width - 2) / 2, (rc.Height - height - 2) / 2); + this.Size = new Size(width + 2, height + 2); + this.ResumeLayout(); + } + } + + // On new frame ready + private void videoSource_NewFrame(object sender, NewFrameEventArgs eventArgs) + { + if (!requestedToStop) + { + Bitmap newFrame = (Bitmap)eventArgs.Frame.Clone(); + + // let user process the frame first + if (NewFrame != null) + { + NewFrame(this, ref newFrame); + } + + // now update current frame of the control + lock (sync) + { + // dispose previous frame + if (currentFrame != null) + { + if (currentFrame.Size != eventArgs.Frame.Size) + { + needSizeUpdate = true; + } + + currentFrame.Dispose(); + currentFrame = null; + } + if (convertedFrame != null) + { + convertedFrame.Dispose(); + convertedFrame = null; + } + + currentFrame = newFrame; + frameSize = currentFrame.Size; + lastMessage = null; + + // check if conversion is required to lower bpp rate + if ((currentFrame.PixelFormat == PixelFormat.Format16bppGrayScale) || + (currentFrame.PixelFormat == PixelFormat.Format48bppRgb) || + (currentFrame.PixelFormat == PixelFormat.Format64bppArgb)) + { + convertedFrame = AForge.Imaging.Image.Convert16bppTo8bpp(currentFrame); + } + } + + // update control + Invalidate(); + } + } + + // Error occured in video source + private void videoSource_VideoSourceError(object sender, VideoSourceErrorEventArgs eventArgs) + { + lastMessage = eventArgs.Description; + Invalidate(); + } + + // Video source has finished playing video + private void videoSource_PlayingFinished(object sender, ReasonToFinishPlaying reason) + { + switch (reason) + { + case ReasonToFinishPlaying.EndOfStreamReached: + lastMessage = "Video has finished"; + break; + + case ReasonToFinishPlaying.StoppedByUser: + lastMessage = "Video was stopped"; + break; + + case ReasonToFinishPlaying.DeviceLost: + lastMessage = "Video device was unplugged"; + break; + + case ReasonToFinishPlaying.VideoSourceError: + lastMessage = "Video has finished because of error in video source"; + break; + + default: + lastMessage = "Video has finished for unknown reason"; + break; + } + Invalidate(); + + // notify users + if (PlayingFinished != null) + { + PlayingFinished(this, reason); + } + } + + // Parent Changed event handler + private void VideoSourcePlayer_ParentChanged(object sender, EventArgs e) + { + if (parent != null) + { + parent.SizeChanged -= new EventHandler(parent_SizeChanged); + } + + parent = this.Parent; + + // set handler for Size Changed parent's event + if (parent != null) + { + parent.SizeChanged += new EventHandler(parent_SizeChanged); + } + } + + // Parent control has changed its size + private void parent_SizeChanged(object sender, EventArgs e) + { + UpdatePosition(); + } + } +} diff --git a/Sources/Accord.Controls.Imaging/AForge/VideoSourcePlayer.resx b/Sources/Accord.Controls.Imaging/AForge/VideoSourcePlayer.resx new file mode 100644 index 0000000000..52a9ad3e7 --- /dev/null +++ b/Sources/Accord.Controls.Imaging/AForge/VideoSourcePlayer.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + False + + \ No newline at end of file diff --git a/Sources/Accord.Controls.Imaging/Accord.Controls.Imaging.csproj b/Sources/Accord.Controls.Imaging/Accord.Controls.Imaging.csproj index 793c89b22..4dd95925a 100644 --- a/Sources/Accord.Controls.Imaging/Accord.Controls.Imaging.csproj +++ b/Sources/Accord.Controls.Imaging/Accord.Controls.Imaging.csproj @@ -1,173 +1,213 @@ - - - - {E1089999-EAED-4E55-AC47-B6A196DF84FC} - Accord.Controls - Accord.Controls.Imaging - - Debug - AnyCPU - AnyCPU - Library - Properties - True - 4 - True - true - Accord.snk - 3.5 - False - true - ..\Accord.NET.ruleset - false - true - 4096 - true - pdbonly - true - true - true - GlobalSuppressions.cs - - - v4.5 - bin\Debug\ - Full - False - False - True - DEBUG;TRACE - ..\..\Debug\ - - - ..\..\Release\net35 - TRACE;CODE_ANALYSIS;NET35 - v3.5 - ..\..\Release\net35\Accord.Controls.Imaging.XML - ..\..\Release\net35\Accord.Controls.Imaging.dll.CodeAnalysisLog.xml - - - ..\..\Release\net40 - TRACE;CODE_ANALYSIS;NET40 - v4.0 - ..\..\Release\net40\Accord.Controls.Imaging.XML - ..\..\Release\net40\Accord.Controls.Imaging.dll.CodeAnalysisLog.xml - - - ..\..\Release\net45 - TRACE;CODE_ANALYSIS;NET45 - v4.5 - ..\..\Release\net45\Accord.Controls.Imaging.XML - ..\..\Release\net45\Accord.Controls.Imaging.dll.CodeAnalysisLog.xml - - - - - False - ..\..\Externals\AForge.NET\AForge.dll - False - - - ..\..\Externals\AForge.NET\AForge.Controls.dll - False - - - False - ..\..\Externals\AForge.NET\AForge.Imaging.dll - False - - - - 3.5 - - - - - - - - - Properties\VersionInfo.cs - - - UserControl - - - AngleBox.cs - - - - UserControl - - - PointBox.cs - - - Form - - - ImageBox.cs - - - - ImageBox.cs - Designer - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - - - {A177A90C-8207-466A-AF70-F2B8452A42AC} - Accord.Core - False - - - {4959A83D-F78F-439E-80A5-41583ECEAAC6} - Accord.Imaging - - - - + + + + {E1089999-EAED-4E55-AC47-B6A196DF84FC} + Accord.Controls + Accord.Controls.Imaging + Debug + AnyCPU + AnyCPU + Library + Properties + True + 4 + True + true + Accord.snk + 3.5 + False + true + ..\Accord.NET.ruleset + false + true + 4096 + true + pdbonly + true + true + true + GlobalSuppressions.cs + + + v4.5 + bin\Debug\ + Full + False + False + True + DEBUG;TRACE + $(SolutionDir)..\Debug\ + + + $(SolutionDir)..\Release\net35 + TRACE;CODE_ANALYSIS;NET35 + v3.5 + $(SolutionDir)..\Release\net35\Accord.Controls.Imaging.XML + $(SolutionDir)..\Release\net35\Accord.Controls.Imaging.dll.CodeAnalysisLog.xml + + + $(SolutionDir)..\Release\net40 + TRACE;CODE_ANALYSIS;NET40 + v4.0 + $(SolutionDir)..\Release\net40\Accord.Controls.Imaging.XML + $(SolutionDir)..\Release\net40\Accord.Controls.Imaging.dll.CodeAnalysisLog.xml + + + $(SolutionDir)..\Release\net45 + TRACE;CODE_ANALYSIS;NET45 + v4.5 + $(SolutionDir)..\Release\net45\Accord.Controls.Imaging.XML + $(SolutionDir)..\Release\net45\Accord.Controls.Imaging.dll.CodeAnalysisLog.xml + + + + + 3.5 + + + + + + + + + Properties\VersionInfo.cs + + + Component + + + Component + + + Component + + + Component + + + ManipulatorControl.cs + + + Component + + + Component + + + SliderControl.cs + + + Component + + + VideoSourcePlayer.cs + + + UserControl + + + AngleBox.cs + + + + UserControl + + + PointBox.cs + + + Form + + + ImageBox.cs + + + + ColorSlider.cs + + + Histogram.cs + + + HuePicker.cs + + + ManipulatorControl.cs + + + SliderControl.cs + + + VideoSourcePlayer.cs + Designer + + + ImageBox.cs + Designer + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + {A177A90C-8207-466A-AF70-F2B8452A42AC} + Accord.Core + False + + + {4959A83D-F78F-439E-80A5-41583ECEAAC6} + Accord.Imaging + + + {809725dc-6502-4732-a51c-deb7fea12975} + Accord.Video + + + + + + + \ No newline at end of file diff --git a/Sources/Accord.Controls.Statistics/AForge/Chart.cs b/Sources/Accord.Controls.Statistics/AForge/Chart.cs new file mode 100644 index 0000000000..52e8dfa20 --- /dev/null +++ b/Sources/Accord.Controls.Statistics/AForge/Chart.cs @@ -0,0 +1,440 @@ +// AForge Controls Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Controls +{ + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Drawing; + using System.Data; + using System.Windows.Forms; + using AForge; + + /// + /// Chart control. + /// + /// + /// The chart control allows to display multiple charts at time + /// of different types: dots, lines, connected dots. + /// + /// Sample usage: + /// + /// // create data series array + /// double[,] testValues = new double[10, 2]; + /// // fill data series + /// for ( int i = 0; i < 10; i++ ) + /// { + /// testValues[i, 0] = i; // X values + /// testValues[i, 1] = Math.Sin( i / 18.0 * Math.PI ); // Y values + /// } + /// // add new data series to the chart + /// chart.AddDataSeries( "Test", Color.DarkGreen, Chart.SeriesType.ConnectedDots, 3 ); + /// // set X range to display + /// chart.RangeX = new AForge.Range( 0, 9 ); + /// // update the chart + /// chart.UpdateDataSeries( "Test", testValues ); + /// + /// + /// + public class Chart : System.Windows.Forms.Control + { + /// + /// Chart series type enumeration. + /// + public enum SeriesType + { + /// + /// Line style. + /// + Line, + /// + /// Dots style. + /// + Dots, + /// + /// Connected dots style. + /// + ConnectedDots + } + + // series data + private class DataSeries + { + public double[,] data = null; + public Color color = Color.Blue; + public SeriesType type = SeriesType.Line; + public int width = 1; + public bool updateYRange = true; + } + + // data series table + private Dictionary seriesTable = new Dictionary(); + + private Pen blackPen = new Pen(Color.Black); + + private AForge.Range rangeX = new Range(0, 1); + private AForge.Range rangeY = new Range(0, 1); + + /// + /// Chart's X range. + /// + /// + /// The value sets the X range of data to be displayed on the chart. + /// + [Browsable(false)] + public AForge.Range RangeX + { + get { return rangeX; } + set + { + rangeX = value; + UpdateYRange(); + Invalidate(); + } + } + + /// + /// Chart's Y range. + /// + /// + /// The value sets the Y range of data to be displayed on the chart. + /// + [Browsable(false)] + public AForge.Range RangeY + { + get { return rangeY; } + set + { + rangeY = value; + Invalidate(); + } + } + + /// + /// Required designer variable. + /// + private System.ComponentModel.Container components = null; + + /// + /// Initializes a new instance of the class. + /// + /// + public Chart() + { + // This call is required by the Windows.Forms Form Designer. + InitializeComponent(); + + // update control style + SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | + ControlStyles.DoubleBuffer | ControlStyles.UserPaint, true); + } + + /// + /// Dispose the object. + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (components != null) + components.Dispose(); + + // free graphics resources + blackPen.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.SuspendLayout(); + // + // Chart + // + this.Paint += new System.Windows.Forms.PaintEventHandler(this.Chart_Paint); + this.ResumeLayout(false); + + } + #endregion + + // Paint the control. + private void Chart_Paint(object sender, PaintEventArgs e) + { + Graphics g = e.Graphics; + int clientWidth = ClientRectangle.Width; + int clientHeight = ClientRectangle.Height; + + // fill with white background + Brush backgroundBrush = new SolidBrush(BackColor); + g.FillRectangle(backgroundBrush, 0, 0, clientWidth - 1, clientHeight - 1); + backgroundBrush.Dispose(); + + // draw a black rectangle + g.DrawRectangle(blackPen, 0, 0, clientWidth - 1, clientHeight - 1); + + // set clipping rectangle + g.SetClip(new Rectangle(2, 2, clientWidth - 4, clientHeight - 4)); + + // check if there are any data series + if (rangeX.Length != 0) + { + double xFactor = (double)(clientWidth - 10) / (rangeX.Length); + double yFactor = (double)(clientHeight - 10) / ((rangeY.Length != 0) ? rangeY.Length : 1); + + // walk through all data series + foreach (KeyValuePair kvp in seriesTable) + { + DataSeries series = kvp.Value; + // get data of the series + double[,] data = series.data; + + // check for available data + if (data == null) + continue; + + // check series type + if (series.type == SeriesType.Dots) + { + // draw dots + Brush brush = new SolidBrush(series.color); + int width = series.width; + int r = width >> 1; + + // draw all points + for (int i = 0, n = data.GetLength(0); i < n; i++) + { + int x = (int)((data[i, 0] - rangeX.Min) * xFactor); + int y = (int)((data[i, 1] - rangeY.Min) * yFactor); + + x += 5; + y = clientHeight - 6 - y; + + g.FillRectangle(brush, x - r, y - r, width, width); + } + brush.Dispose(); + } + else if (series.type == SeriesType.ConnectedDots) + { + // draw dots connected with 1-pixel width line + Brush brush = new SolidBrush(series.color); + Pen pen = new Pen(series.color, 1); + int width = series.width; + int r = width >> 1; + + int x1 = (int)((data[0, 0] - rangeX.Min) * xFactor); + int y1 = (int)((data[0, 1] - rangeY.Min) * yFactor); + + x1 += 5; + y1 = clientHeight - 6 - y1; + g.FillRectangle(brush, x1 - r, y1 - r, width, width); + + // draw all lines + for (int i = 1, n = data.GetLength(0); i < n; i++) + { + int x2 = (int)((data[i, 0] - rangeX.Min) * xFactor); + int y2 = (int)((data[i, 1] - rangeY.Min) * yFactor); + + x2 += 5; + y2 = clientHeight - 6 - y2; + + g.FillRectangle(brush, x2 - r, y2 - r, width, width); + g.DrawLine(pen, x1, y1, x2, y2); + + x1 = x2; + y1 = y2; + } + + pen.Dispose(); + brush.Dispose(); + } + else if (series.type == SeriesType.Line) + { + // draw line + Pen pen = new Pen(series.color, series.width); + + int x1 = (int)((data[0, 0] - rangeX.Min) * xFactor); + int y1 = (int)((data[0, 1] - rangeY.Min) * yFactor); + + x1 += 5; + y1 = clientHeight - 6 - y1; + + // draw all lines + for (int i = 1, n = data.GetLength(0); i < n; i++) + { + int x2 = (int)((data[i, 0] - rangeX.Min) * xFactor); + int y2 = (int)((data[i, 1] - rangeY.Min) * yFactor); + + x2 += 5; + y2 = clientHeight - 6 - y2; + + g.DrawLine(pen, x1, y1, x2, y2); + + x1 = x2; + y1 = y2; + } + pen.Dispose(); + } + } + } + } + + /// + /// Add data series to the chart. + /// + /// + /// Data series name. + /// Data series color. + /// Data series type. + /// Width (depends on the data series type, see remarks). + /// + /// Adds new empty data series to the collection of data series. To update this + /// series the method should be used. + /// + /// The meaning of the width parameter depends on the data series type: + /// + /// Line - width of the line; + /// Dots - size of dots (rectangular dots with specified width and the same height); + /// Connected dots - size of dots (dots are connected with one pixel width line). + /// + /// + /// + /// + public void AddDataSeries(string name, Color color, SeriesType type, int width) + { + AddDataSeries(name, color, type, width, true); + } + + /// + /// Add data series to the chart. + /// + /// + /// Data series name. + /// Data series color. + /// Data series type. + /// Width (depends on the data series type, see remarks). + /// Specifies if should be updated. + /// + /// Adds new empty data series to the collection of data series. + /// + /// The updateYRange parameter specifies if the data series may affect displayable + /// Y range. If the value is set to false, then displayable Y range is not updated, but used the + /// range, which was specified by user (see property). In the case if the + /// value is set to true, the displayable Y range is recalculated to fully fit the new data + /// series. + /// + /// + public void AddDataSeries(string name, Color color, SeriesType type, int width, bool updateYRange) + { + // create new series definition ... + DataSeries series = new DataSeries(); + // ... add fill it + series.color = color; + series.type = type; + series.width = width; + series.updateYRange = updateYRange; + // add to series table + seriesTable.Add(name, series); + } + + /// + /// Update data series on the chart. + /// + /// + /// Data series name to update. + /// Data series values. + /// + public void UpdateDataSeries(string name, double[,] data) + { + if (!seriesTable.ContainsKey(name)) + throw new ArgumentException("The chart does not contain data series with name: " + name); + + // get data series + DataSeries series = seriesTable[name]; + // update data + series.data = (data != null) ? (double[,])data.Clone() : null; + + // update Y range + if (series.updateYRange) + UpdateYRange(); + // invalidate the control + Invalidate(); + } + + /// + /// Remove data series from the chart. + /// + /// + /// Data series name to remove. + /// + public void RemoveDataSeries(string name) + { + // remove data series from table + seriesTable.Remove(name); + // invalidate the control + Invalidate(); + } + + /// + /// Remove all data series from the chart. + /// + public void RemoveAllDataSeries() + { + // remove all data series from table + seriesTable.Clear(); + // invalidate the control + Invalidate(); + } + + /// + /// Update Y range. + /// + private void UpdateYRange() + { + float minY = float.MaxValue; + float maxY = float.MinValue; + + // walk through all data series + foreach (KeyValuePair kvp in seriesTable) + { + DataSeries series = kvp.Value; + // get data of the series + double[,] data = series.data; + + if ((series.updateYRange) && (data != null)) + { + for (int i = 0, n = data.GetLength(0); i < n; i++) + { + if (rangeX.IsInside((float)data[i, 0])) + { + float v = (float)data[i, 1]; + + // check for max + if (v > maxY) + maxY = v; + // check for min + if (v < minY) + minY = v; + } + } + } + } + + // update Y range, if there are any data + if ((minY != double.MaxValue) || (maxY != double.MinValue)) + { + rangeY = new Range(minY, maxY); + } + } + } +} diff --git a/Sources/Accord.Controls.Statistics/AForge/Chart.resx b/Sources/Accord.Controls.Statistics/AForge/Chart.resx new file mode 100644 index 0000000000..52a9ad3e7 --- /dev/null +++ b/Sources/Accord.Controls.Statistics/AForge/Chart.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + False + + \ No newline at end of file diff --git a/Sources/Accord.Controls.Statistics/AForge/Joystick.cs b/Sources/Accord.Controls.Statistics/AForge/Joystick.cs new file mode 100644 index 0000000000..43281a4dc --- /dev/null +++ b/Sources/Accord.Controls.Statistics/AForge/Joystick.cs @@ -0,0 +1,435 @@ +// AForge Controls Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2010 +// andrew.kirillov@aforgenet.com +// + +using System; +using System.Collections.Generic; +using AForge; + +namespace AForge.Controls +{ + /// + /// The class provides simple API for enumerating available joysticks and checking their + /// current status. + /// + /// + /// The class provides simple access to joysticks (game controllers) through using + /// Win32 API, which allows to enumerate available devices and query their status (state of all buttons, + /// axes, etc). + /// + /// Sample usage: + /// + /// // enumerate available devices + /// List<Joystick.DeviceInfo> devices = Joystick.GetAvailableDevices( ); + /// + /// foreach ( Joystick.DeviceInfo di in devices ) + /// { + /// System.Diagnostics.Debug.WriteLine( + /// string.Format( "{0} : {1} ({2} axes, {3} buttons)", + /// di.ID, di.Name, di.Axes, di.Buttons ) ); + /// } + /// + /// + /// // create new joystick and initialize it + /// Joystick joystick = new Joystick( 0 ); + /// // get its current status + /// Joystick.Status status = joystick.GetCurrentStatus( ); + /// // check if 1st button is pressed + /// if ( status.IsButtonPressed( Joystick.Buttons.Button1 ) ) + /// { + /// // 1st button is pressed + /// } + /// + /// + /// + public class Joystick + { + // information of the initialized joystick + private DeviceInfo info = null; + + /// + /// Information about initialized joystick. + /// + /// + /// The property keeps information about joystick, which was + /// initialized using method. If no joystick was initialized, + /// then accessing this property will generate + /// exception. + /// + /// Joystick was not initialized. + /// + public DeviceInfo Info + { + get + { + if (info == null) + throw new InvalidOperationException("Joystick was not initialized."); + + return info; + } + } + + /// + /// Information about joystick connected to the system. + /// + /// + public class DeviceInfo + { + /// + /// Joystick ID, [0..15]. + /// + public readonly int ID; + + internal readonly JoystickAPI.JOYCAPS capabilities; + + /// + /// Joystick name. + /// + public string Name + { + get { return capabilities.name; } + } + + /// + /// Number of joystick axes. + /// + public int Axes + { + get { return capabilities.axesNumber; } + } + + /// + /// Number of joystick buttons. + /// + public int Buttons + { + get { return capabilities.buttonsNumber; } + } + + internal DeviceInfo(int id, JoystickAPI.JOYCAPS joyCaps) + { + ID = id; + capabilities = joyCaps; + } + } + + /// + /// Get list of available joysticks connected to the system. + /// + /// + /// Returns list containing information about available joysticks connected to + /// the system. + /// + public static List GetAvailableDevices() + { + List devices = new List(); + int joyCapsSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(JoystickAPI.JOYCAPS)); + + // get number of devices + int devicesCount = JoystickAPI.joyGetNumDevs(); + // check all devices + for (int i = 0; i < devicesCount; i++) + { + JoystickAPI.JOYCAPS joyCaps = new JoystickAPI.JOYCAPS(); + + if (JoystickAPI.joyGetDevCapsW(i, joyCaps, joyCapsSize) == JoystickAPI.ResultCode.NoError) + { + devices.Add(new DeviceInfo(i, joyCaps)); + } + } + + return devices; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// This constructor does not make initialization of any joystick + /// device, so method should be used before querying joystick + /// status or properties. + /// + public Joystick() { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Joystick ID to initialize, [0, 15]. + /// + /// This constructor initializes joystick with specified ID using + /// method, so the object becomes ready for querying joystick's + /// status. + /// + public Joystick(int id) + { + Init(id); + } + + /// + /// Initialize joystick with the specified ID. + /// + /// + /// Joystick's ID to initialize, [0, 15]. + /// + /// + /// + /// Invalid joystick ID was specified. It must be in [0, 15] range. + /// The requested joystick is not connected to the system. + /// + public void Init(int id) + { + if ((id < 0) || (id > 15)) + { + throw new ArgumentException("Invalid joystick ID was specified."); + } + + JoystickAPI.JOYCAPS joyCaps = new JoystickAPI.JOYCAPS(); + + if (JoystickAPI.joyGetDevCapsW(id, joyCaps, + System.Runtime.InteropServices.Marshal.SizeOf(joyCaps)) != JoystickAPI.ResultCode.NoError) + { + throw new NotConnectedException("The requested joystick is not connected to the system."); + } + + info = new DeviceInfo(id, joyCaps); + } + + private static JoystickAPI.JoyPosFlags[] requestFlags = new JoystickAPI.JoyPosFlags[] + { + JoystickAPI.JoyPosFlags.ReturnPov | JoystickAPI.JoyPosFlags.ReturnButtons, + JoystickAPI.JoyPosFlags.ReturnPov | JoystickAPI.JoyPosFlags.ReturnButtons | JoystickAPI.JoyPosFlags.ReturnX, + JoystickAPI.JoyPosFlags.ReturnPov | JoystickAPI.JoyPosFlags.ReturnButtons | JoystickAPI.JoyPosFlags.ReturnXY, + JoystickAPI.JoyPosFlags.ReturnPov | JoystickAPI.JoyPosFlags.ReturnButtons | JoystickAPI.JoyPosFlags.ReturnXYZ, + JoystickAPI.JoyPosFlags.ReturnPov | JoystickAPI.JoyPosFlags.ReturnButtons | JoystickAPI.JoyPosFlags.ReturnXYZR, + JoystickAPI.JoyPosFlags.ReturnPov | JoystickAPI.JoyPosFlags.ReturnButtons | JoystickAPI.JoyPosFlags.ReturnXYZRU, + }; + + /// + /// Get joystick's status. + /// + /// + /// Returns current status of initialized joystick, which provides information + /// about current state of all axes, buttons and point of view. + /// + /// Before using this method the joystick object needs to be initialized + /// using method or constructor. + /// + /// The requested joystick is not connected to the system. + /// Joystick was not initialized. + /// + public Status GetCurrentStatus() + { + JoystickAPI.JOYINFOEX ji = new JoystickAPI.JOYINFOEX(); + + ji.size = System.Runtime.InteropServices.Marshal.SizeOf(ji); + ji.flags = (Info.capabilities.axesNumber > 5) ? JoystickAPI.JoyPosFlags.ReturnAll : + requestFlags[Info.capabilities.axesNumber]; + + if (JoystickAPI.joyGetPosEx(Info.ID, ji) != JoystickAPI.ResultCode.NoError) + { + throw new NotConnectedException("The requested joystick is not connected to the system."); + } + + return new Status(ji, Info.capabilities); + } + + /// + /// Class describing current joystick's status. + /// + /// + /// All joystick axes' positions are measured in [-1, 1] range, where + /// 0 corresponds to center position - axis is not deflected (directed) to any side. + /// + public class Status + { + private JoystickAPI.JOYINFOEX status; + private JoystickAPI.JOYCAPS capabilities; + + internal Status(JoystickAPI.JOYINFOEX status, JoystickAPI.JOYCAPS capabilities) + { + this.status = status; + this.capabilities = capabilities; + } + + /// + /// Position of X axis, [-1, 1]. + /// + public float XAxis + { + get + { + return (((status.flags & JoystickAPI.JoyPosFlags.ReturnX) == 0) ? 0 : + (float)(status.xPos - capabilities.xMin) / capabilities.xMax * 2 - 1); + } + } + + /// + /// Position of Y axis, [-1, 1]. + /// + public float YAxis + { + get + { + return (((status.flags & JoystickAPI.JoyPosFlags.ReturnY) == 0) ? 0 : + (float)(status.yPos - capabilities.yMin) / capabilities.yMax * 2 - 1); + } + } + + /// + /// Position of Z axis, [-1, 1]. + /// + public float ZAxis + { + get + { + return (((status.flags & JoystickAPI.JoyPosFlags.ReturnZ) == 0) ? 0 : + (float)(status.zPos - capabilities.zMin) / capabilities.zMax * 2 - 1); + } + } + + /// + /// Position of R axis - 4th joystick's axes, [-1, 1]. + /// + public float RAxis + { + get + { + return (((status.flags & JoystickAPI.JoyPosFlags.ReturnR) == 0) ? 0 : + (float)(status.rPos - capabilities.rMin) / capabilities.rMax * 2 - 1); + } + } + + /// + /// Position of U axis - 5th joystick's axes, [-1, 1]. + /// + public float UAxis + { + get + { + return (((status.flags & JoystickAPI.JoyPosFlags.ReturnU) == 0) ? 0 : + (float)(status.uPos - capabilities.uMin) / capabilities.uMax * 2 - 1); + } + } + + /// + /// Position of V axis - 6th joystick's axes, [-1, 1]. + /// + public float VAxis + { + get + { + return (((status.flags & JoystickAPI.JoyPosFlags.ReturnV) == 0) ? 0 : + (float)(status.vPos - capabilities.vMin) / capabilities.vMax * 2 - 1); + } + } + + /// + /// Joystick buttons' state. + /// + public Buttons Buttons + { + get { return (Buttons)status.buttons; } + } + + /// + /// Current point of view state, [0, 359]. + /// + /// + public float PointOfView + { + get { return (status.pov > 35900) ? -1 : (float)status.pov / 100; } + } + + /// + /// Check if certain button (or combination of buttons) is pressed. + /// + /// + /// Button to check state of. + /// + /// Returns if the specified button is pressed or + /// otherwise. + /// + public bool IsButtonPressed(Buttons button) + { + return ((((Buttons)status.buttons) & button) != 0); + } + } + + /// + /// Flags enumeration of joystick buttons. + /// + [Flags] + public enum Buttons + { + /// + /// 1st button. + /// + Button1 = 0x0001, + /// + /// 2nd button. + /// + Button2 = 0x0002, + /// + /// 3rd button. + /// + Button3 = 0x0004, + /// + /// 4th button. + /// + Button4 = 0x0008, + /// + /// 5th button. + /// + Button5 = 0x0010, + /// + /// 6th button. + /// + Button6 = 0x0020, + /// + /// 7th button. + /// + Button7 = 0x0040, + /// + /// 8th button. + /// + Button8 = 0x0080, + /// + /// 9th button. + /// + Button9 = 0x0100, + /// + /// 10th button. + /// + Button10 = 0x0200, + /// + /// 11th button. + /// + Button11 = 0x0400, + /// + /// 12th button. + /// + Button12 = 0x0800, + /// + /// 13th button. + /// + Button13 = 0x1000, + /// + /// 14th button. + /// + Button14 = 0x2000, + /// + /// 15th button. + /// + Button15 = 0x4000, + /// + /// 16th button. + /// + Button16 = 0x8000, + } + } +} diff --git a/Sources/Accord.Controls.Statistics/AForge/JoystickAPI.cs b/Sources/Accord.Controls.Statistics/AForge/JoystickAPI.cs new file mode 100644 index 0000000000..dd5e0a2fe --- /dev/null +++ b/Sources/Accord.Controls.Statistics/AForge/JoystickAPI.cs @@ -0,0 +1,159 @@ +// AForge Controls Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2010 +// andrew.kirillov@aforgenet.com +// + +using System; +using System.Runtime.InteropServices; + +namespace AForge.Controls +{ + internal static class JoystickAPI + { + [DllImport("winmm.dll")] + public static extern int joyGetNumDevs(); + + [DllImport("winmm.dll")] + public static extern ResultCode joyGetDevCapsW(int uJoyID, + [In, Out, MarshalAs(UnmanagedType.LPStruct)] JOYCAPS pjc, + int cbjc); + + [DllImport("winmm.dll")] + public static extern ResultCode joyGetPos(int uJoyID, JOYINFO pji); + + [DllImport("winmm.dll")] + public static extern ResultCode joyGetPosEx(int uJoyID, JOYINFOEX pji); + + [DllImport("winmm.dll")] + public static extern ResultCode joyReleaseCapture(int uJoyID); + + [DllImport("winmm.dll")] + public static extern ResultCode joySetCapture( + IntPtr hwnd, + int uJoyID, + int uPeriod, + [MarshalAs(UnmanagedType.Bool)] bool fChanged); + + // Information about current state of joystick's axes and buttons + [StructLayout(LayoutKind.Sequential)] + public class JOYINFO + { + public int xPos; + public int yPos; + public int zPos; + public int buttons; + } + + // Extended information about current state of joystick's axes and buttons + [StructLayout(LayoutKind.Sequential)] + public class JOYINFOEX + { + public int size; + public JoyPosFlags flags; + public int xPos; + public int yPos; + public int zPos; + public int rPos; + public int uPos; + public int vPos; + public int buttons; + public int buttonNumber; + public int pov; + public int reserved1; + public int reserved2; + } + + // Joystick capabilities + [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode)] + public class JOYCAPS + { + public short mid; + public short pid; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] + public string name; + public int xMin; + public int xMax; + public int yMin; + public int yMax; + public int zMin; + public int zMax; + public int buttonsNumber; + public int minPeriod; + public int maxPeriod; + public int rMin; + public int rMax; + public int uMin; + public int uMax; + public int vMin; + public int vMax; + public int caps; + public int axesMax; + public int axesNumber; + public int buttonsMax; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] + public string regKey; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] + public string oemVxD; + } + + // Some result codes + public enum ResultCode : uint + { + NoError = 0, + Error = 1, + BadDeviceID = 2, + NoDriver = 6, + InvalidParam = 11, + + JoystickInvalidParam = 165, + JoystickRequestNotCompleted = 166, + JoystickUnplugged = 167 + } + + [Flags] + public enum JoyPosFlags + { + ReturnX = 0x01, + ReturnY = 0x02, + ReturnZ = 0x04, + ReturnR = 0x08, + ReturnU = 0x10, + ReturnV = 0x20, + ReturnPov = 0x40, + ReturnButtons = 0x80, + + ReturnXY = 0x03, + ReturnXYZ = 0x07, + ReturnXYZR = 0x0F, + ReturnXYZRU = 0x1F, + ReturnXYZRUV = 0x3F, + + ReturnAll = 0xFF + } + + [Flags] + public enum JoyButtons + { + Button1 = 0x001, + Button2 = 0x002, + Button3 = 0x004, + Button4 = 0x008, + Button5 = 0x010, + Button6 = 0x020, + Button7 = 0x040, + Button8 = 0x080 + } + + public const int MM_JOY1MOVE = 0x3A0; + public const int MM_JOY2MOVE = 0x3A1; + public const int MM_JOY1ZMOVE = 0x3A2; + public const int MM_JOY2ZMOVE = 0x3A3; + public const int MM_JOY1BUTTONDOWN = 0x3B5; + public const int MM_JOY2BUTTONDOWN = 0x3B6; + public const int MM_JOY1BUTTONUP = 0x3B7; + public const int MM_JOY2BUTTONUP = 0x3B8; + } +} diff --git a/Sources/Accord.Controls.Statistics/Accord.Controls.csproj b/Sources/Accord.Controls.Statistics/Accord.Controls.csproj index 8e0350bda..2c15f48b0 100644 --- a/Sources/Accord.Controls.Statistics/Accord.Controls.csproj +++ b/Sources/Accord.Controls.Statistics/Accord.Controls.csproj @@ -1,266 +1,259 @@ - - - - {0AB27A20-925C-4556-9FA4-6E2C109E448E} - Accord.Controls - Accord.Controls - - Debug - AnyCPU - AnyCPU - Library - Properties - True - 4 - True - true - Accord.snk - 3.5 - False - true - ..\Accord.NET.ruleset - false - true - 4096 - true - pdbonly - true - true - true - GlobalSuppressions.cs - - - v4.5 - bin\Debug\ - Full - False - False - True - DEBUG;TRACE - ..\..\Debug\ - - - ..\..\Release\net35 - TRACE;CODE_ANALYSIS;NET35 - v3.5 - ..\..\Release\net35\Accord.Controls.XML - ..\..\Release\net35\Accord.Controls.dll.CodeAnalysisLog.xml - - - ..\..\Release\net40 - TRACE;CODE_ANALYSIS;NET40 - v4.0 - ..\..\Release\net40\Accord.Controls.XML - ..\..\Release\net40\Accord.Controls.dll.CodeAnalysisLog.xml - - - ..\..\Release\net45 - TRACE;CODE_ANALYSIS;NET45 - v4.5 - ..\..\Release\net45\Accord.Controls.XML - ..\..\Release\net45\Accord.Controls.dll.CodeAnalysisLog.xml - - - - - False - ..\..\Externals\AForge.NET\AForge.dll - False - - - False - ..\..\Externals\AForge.NET\AForge.Controls.dll - False - - - False - ..\..\Externals\AForge.NET\AForge.Math.dll - False - - - - - 3.5 - - - - - - - - False - ..\..\Externals\ZedGraph\ZedGraph.dll - - - - - Properties\VersionInfo.cs - - - - - - - - - - Form - - - DataBarBox.cs - - - Form - - - HistogramBox.cs - - - - - Form - - - DataSeriesBox.cs - - - Form - - - DataGridBox.cs - - - - - Form - - - NumericCollectionEditorForm.cs - - - - UserControl - - - ComponentView.cs - - - UserControl - - - DecisionTreeView.cs - - - - UserControl - - - HistogramView.cs - - - Form - - - ScatterplotBox.cs - - - UserControl - - - ScatterplotView.cs - - - - - - - - - DataBarBox.cs - - - HistogramBox.cs - Designer - - - DataSeriesBox.cs - - - DataGridBox.cs - - - NumericCollectionEditorForm.cs - - - ComponentView.cs - - - DecisionTreeView.cs - - - HistogramView.cs - Designer - - - ScatterplotBox.cs - Designer - - - ScatterplotView.cs - - - - - {A177A90C-8207-466A-AF70-F2B8452A42AC} - Accord.Core - False - - - {7AB4BBCC-6222-423D-9FF9-BA9CB7C09199} - Accord.MachineLearning - - - {F718E9A8-DB62-4785-8C49-4333A60D256A} - Accord.Math - False - - - {FD8101DD-C95D-42D6-AD44-AE01C25F2811} - Accord.Statistics - False - - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - - - - - - + + + + {0AB27A20-925C-4556-9FA4-6E2C109E448E} + Accord.Controls + Accord.Controls + Debug + AnyCPU + AnyCPU + Library + Properties + True + 4 + True + true + Accord.snk + 3.5 + False + true + ..\Accord.NET.ruleset + false + true + 4096 + true + pdbonly + true + true + true + GlobalSuppressions.cs + + + v4.5 + bin\Debug\ + Full + False + False + True + DEBUG;TRACE + $(SolutionDir)..\Debug\ + + + $(SolutionDir)..\Release\net35 + TRACE;CODE_ANALYSIS;NET35 + v3.5 + $(SolutionDir)..\Release\net35\Accord.Controls.XML + $(SolutionDir)..\Release\net35\Accord.Controls.dll.CodeAnalysisLog.xml + + + $(SolutionDir)..\Release\net40 + TRACE;CODE_ANALYSIS;NET40 + v4.0 + $(SolutionDir)..\Release\net40\Accord.Controls.XML + $(SolutionDir)..\Release\net40\Accord.Controls.dll.CodeAnalysisLog.xml + + + $(SolutionDir)..\Release\net45 + TRACE;CODE_ANALYSIS;NET45 + v4.5 + $(SolutionDir)..\Release\net45\Accord.Controls.XML + $(SolutionDir)..\Release\net45\Accord.Controls.dll.CodeAnalysisLog.xml + + + + + + 3.5 + + + + + + + + + False + ..\..\Externals\ZedGraph\ZedGraph.dll + + + + + Properties\VersionInfo.cs + + + Component + + + + + + + + + + + + Form + + + DataBarBox.cs + + + Form + + + HistogramBox.cs + + + + + + Form + + + DataSeriesBox.cs + + + Form + + + DataGridBox.cs + + + + + Form + + + NumericCollectionEditorForm.cs + + + + UserControl + + + ComponentView.cs + + + UserControl + + + DecisionTreeView.cs + + + + UserControl + + + HistogramView.cs + + + Form + + + ScatterplotBox.cs + + + UserControl + + + ScatterplotView.cs + + + + + + + + + Chart.cs + + + DataBarBox.cs + + + HistogramBox.cs + Designer + + + DataSeriesBox.cs + + + DataGridBox.cs + + + NumericCollectionEditorForm.cs + + + ComponentView.cs + + + DecisionTreeView.cs + + + HistogramView.cs + Designer + + + ScatterplotBox.cs + Designer + + + ScatterplotView.cs + + + + + {A177A90C-8207-466A-AF70-F2B8452A42AC} + Accord.Core + False + + + {7AB4BBCC-6222-423D-9FF9-BA9CB7C09199} + Accord.MachineLearning + + + {F718E9A8-DB62-4785-8C49-4333A60D256A} + Accord.Math + False + + + {FD8101DD-C95D-42D6-AD44-AE01C25F2811} + Accord.Statistics + False + + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + + \ No newline at end of file diff --git a/Sources/Accord.Controls.Statistics/Boxes/DataBarBox.cs b/Sources/Accord.Controls.Statistics/Boxes/DataBarBox.cs index 65c10ea86..b8b69ab9a 100644 --- a/Sources/Accord.Controls.Statistics/Boxes/DataBarBox.cs +++ b/Sources/Accord.Controls.Statistics/Boxes/DataBarBox.cs @@ -162,9 +162,8 @@ private static DataBarBox show(string title, string[] labels, double[][] series) AutoResetEvent stopWaitHandle = new AutoResetEvent(false); formThread = new Thread(() => - { - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); + { + Accord.Controls.Tools.ConfigureWindowsFormsApplication(); // Show control in a form form = new DataBarBox(); diff --git a/Sources/Accord.Controls.Statistics/Boxes/DataGridBox.cs b/Sources/Accord.Controls.Statistics/Boxes/DataGridBox.cs index 546a70b64..6f5a1c202 100644 --- a/Sources/Accord.Controls.Statistics/Boxes/DataGridBox.cs +++ b/Sources/Accord.Controls.Statistics/Boxes/DataGridBox.cs @@ -252,9 +252,8 @@ private static DataGridBox show(object source, string title) AutoResetEvent stopWaitHandle = new AutoResetEvent(false); formThread = new Thread(() => - { - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); + { + Accord.Controls.Tools.ConfigureWindowsFormsApplication(); // Show control in a form form = new DataGridBox(); diff --git a/Sources/Accord.Controls.Statistics/Boxes/DataSeriesBox.cs b/Sources/Accord.Controls.Statistics/Boxes/DataSeriesBox.cs index 46c7c40a2..aa241db9a 100644 --- a/Sources/Accord.Controls.Statistics/Boxes/DataSeriesBox.cs +++ b/Sources/Accord.Controls.Statistics/Boxes/DataSeriesBox.cs @@ -316,9 +316,8 @@ private static DataSeriesBox show(String title, double[] x, double[][] series, AutoResetEvent stopWaitHandle = new AutoResetEvent(false); formThread = new Thread(() => - { - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); + { + Accord.Controls.Tools.ConfigureWindowsFormsApplication(); // Show control in a form form = new DataSeriesBox(); diff --git a/Sources/Accord.Controls.Statistics/Boxes/HistogramBox.cs b/Sources/Accord.Controls.Statistics/Boxes/HistogramBox.cs index 736862c02..aaff8f9f7 100644 --- a/Sources/Accord.Controls.Statistics/Boxes/HistogramBox.cs +++ b/Sources/Accord.Controls.Statistics/Boxes/HistogramBox.cs @@ -211,9 +211,8 @@ private static HistogramBox show(string title, double[] values) AutoResetEvent stopWaitHandle = new AutoResetEvent(false); formThread = new Thread(() => - { - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); + { + Accord.Controls.Tools.ConfigureWindowsFormsApplication(); // Show control in a form form = new HistogramBox(); diff --git a/Sources/Accord.Controls.Statistics/Boxes/ScatterplotBox.cs b/Sources/Accord.Controls.Statistics/Boxes/ScatterplotBox.cs index 429a81eca..104804567 100644 --- a/Sources/Accord.Controls.Statistics/Boxes/ScatterplotBox.cs +++ b/Sources/Accord.Controls.Statistics/Boxes/ScatterplotBox.cs @@ -540,9 +540,8 @@ private static ScatterplotBox show(Scatterplot scatterplot) AutoResetEvent stopWaitHandle = new AutoResetEvent(false); formThread = new Thread(() => - { - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); + { + Accord.Controls.Tools.ConfigureWindowsFormsApplication(); // Show control in a form form = new ScatterplotBox(); diff --git a/Sources/Accord.Controls.Statistics/GlobalSuppressions.cs b/Sources/Accord.Controls.Statistics/GlobalSuppressions.cs index 50c2a16da..4613b4ab5 100644 --- a/Sources/Accord.Controls.Statistics/GlobalSuppressions.cs +++ b/Sources/Accord.Controls.Statistics/GlobalSuppressions.cs @@ -18,4 +18,7 @@ [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix", Scope = "type", Target = "Accord.Controls.ArrayDataView")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1039:ListsAreStronglyTyped", Scope = "type", Target = "Accord.Controls.ArrayDataView")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1035:ICollectionImplementationsHaveStronglyTypedMembers", Scope = "type", Target = "Accord.Controls.ArrayDataView")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Portability", "CA1903:UseOnlyApiFromTargetedFramework", MessageId = "System.ComponentModel.DataAnnotations, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Portability", "CA1903:UseOnlyApiFromTargetedFramework", MessageId = "System.ComponentModel.DataAnnotations, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA2101:SpecifyMarshalingForPInvokeStringArguments", MessageId = "JOYCAPS.name", Scope = "member", Target = "AForge.Controls.JoystickAPI.#joyGetDevCapsW(System.Int32,AForge.Controls.JoystickAPI+JOYCAPS,System.Int32)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA2101:SpecifyMarshalingForPInvokeStringArguments", MessageId = "JOYCAPS.oemVxD", Scope = "member", Target = "AForge.Controls.JoystickAPI.#joyGetDevCapsW(System.Int32,AForge.Controls.JoystickAPI+JOYCAPS,System.Int32)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA2101:SpecifyMarshalingForPInvokeStringArguments", MessageId = "JOYCAPS.regKey", Scope = "member", Target = "AForge.Controls.JoystickAPI.#joyGetDevCapsW(System.Int32,AForge.Controls.JoystickAPI+JOYCAPS,System.Int32)")] diff --git a/Sources/Accord.Controls.Statistics/Tools.cs b/Sources/Accord.Controls.Statistics/Tools.cs new file mode 100644 index 0000000000..05714dbe4 --- /dev/null +++ b/Sources/Accord.Controls.Statistics/Tools.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace Accord.Controls +{ + internal static class Tools + { + static readonly bool IsRunningOnMono = (Type.GetType("Mono.Runtime") != null); + + + public static void ConfigureWindowsFormsApplication() + { + if (!IsRunningOnMono && Environment.OSVersion.Version.Major >= 6) + SetProcessDPIAware(); + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + } + + [System.Runtime.InteropServices.DllImport("user32.dll")] + private static extern bool SetProcessDPIAware(); + } +} diff --git a/Sources/Accord.Controls.Vision/Accord.Controls.Vision.csproj b/Sources/Accord.Controls.Vision/Accord.Controls.Vision.csproj index ad0eefbf1..faf176a9a 100644 --- a/Sources/Accord.Controls.Vision/Accord.Controls.Vision.csproj +++ b/Sources/Accord.Controls.Vision/Accord.Controls.Vision.csproj @@ -36,58 +36,31 @@ False True DEBUG;TRACE - ..\..\Debug\ + $(SolutionDir)..\Debug\ - ..\..\Release\net35 + $(SolutionDir)..\Release\net35 TRACE;CODE_ANALYSIS;NET35 v3.5 true - ..\..\Release\net35\Accord.Controls.Vision.XML - ..\..\Release\net35\Accord.Controls.Vision.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net35\Accord.Controls.Vision.XML + $(SolutionDir)..\Release\net35\Accord.Controls.Vision.dll.CodeAnalysisLog.xml - ..\..\Release\net40 + $(SolutionDir)..\Release\net40 TRACE;CODE_ANALYSIS;NET40 v4.0 - ..\..\Release\net40\Accord.Controls.Vision.XML - ..\..\Release\net40\Accord.Controls.Vision.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net40\Accord.Controls.Vision.XML + $(SolutionDir)..\Release\net40\Accord.Controls.Vision.dll.CodeAnalysisLog.xml - ..\..\Release\net45 + $(SolutionDir)..\Release\net45 TRACE;CODE_ANALYSIS;NET45 v4.5 - ..\..\Release\net45\Accord.Controls.Vision.XML - ..\..\Release\net45\Accord.Controls.Vision.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net45\Accord.Controls.Vision.XML + $(SolutionDir)..\Release\net45\Accord.Controls.Vision.dll.CodeAnalysisLog.xml - - ..\..\Externals\AForge.NET\AForge.dll - False - - - ..\..\Externals\AForge.NET\AForge.Controls.dll - - - ..\..\Externals\AForge.NET\AForge.Imaging.dll - False - - - ..\..\Externals\AForge.NET\AForge.Math.dll - False - - - ..\..\Externals\AForge.NET\AForge.Video.dll - False - - - ..\..\Externals\AForge.NET\AForge.Video.DirectShow.dll - False - - - ..\..\Externals\AForge.NET\AForge.Vision.dll - False - 3.5 @@ -152,6 +125,10 @@ Accord.Statistics False + + {809725dc-6502-4732-a51c-deb7fea12975} + Accord.Video + {C70A159D-74A4-405F-9A7F-C17ACF451CCA} Accord.Vision @@ -187,11 +164,11 @@ - \ No newline at end of file diff --git a/Sources/Accord.Controls.Vision/HeadController.cs b/Sources/Accord.Controls.Vision/HeadController.cs index 5cfd8d96c..5eb9ad603 100644 --- a/Sources/Accord.Controls.Vision/HeadController.cs +++ b/Sources/Accord.Controls.Vision/HeadController.cs @@ -30,7 +30,6 @@ namespace Accord.Controls.Vision using AForge.Imaging; using AForge.Imaging.Filters; using AForge.Video; - using AForge.Video.DirectShow; using System; using System.ComponentModel; using System.ComponentModel.Design; @@ -299,7 +298,7 @@ public ISynchronizeInvoke SynchronizingObject /// Gets or sets the video device used to track objects. ///
/// - /// The used to track objects. + /// The used to track objects. /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public IVideoSource Device @@ -320,27 +319,29 @@ public IVideoSource Device videoSource.NewFrame += source_NewFrame; videoSource.PlayingFinished += videoSource_PlayingFinished; videoSource.VideoSourceError += videoSource_VideoSourceError; + /* + VideoCaptureDevice captureDevice = videoSource as VideoCaptureDevice; - VideoCaptureDevice captureDevice = videoSource as VideoCaptureDevice; - - if (captureDevice != null) - captureDevice.VideoResolution = selectResolution(captureDevice); + if (captureDevice != null) + captureDevice.VideoResolution = selectResolution(captureDevice); + */ } } } + /* + private static VideoCapabilities selectResolution(VideoCaptureDevice device) + { + foreach (var cap in device.VideoCapabilities) + { + if (cap.FrameSize.Height == 240) + return cap; + if (cap.FrameSize.Width == 320) + return cap; + } - private static VideoCapabilities selectResolution(VideoCaptureDevice device) - { - foreach (var cap in device.VideoCapabilities) - { - if (cap.FrameSize.Height == 240) - return cap; - if (cap.FrameSize.Width == 320) - return cap; - } - - return device.VideoCapabilities.Last(); - } + return device.VideoCapabilities.Last(); + } + */ /// /// Gets a value indicating whether this instance is diff --git a/Sources/Accord.Core/AForge/Delegates.cs b/Sources/Accord.Core/AForge/Delegates.cs new file mode 100644 index 0000000000..2ec87cf24 --- /dev/null +++ b/Sources/Accord.Core/AForge/Delegates.cs @@ -0,0 +1,21 @@ +// AForge Core Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge +{ + using System; + + /// + /// A delegate which is used by events notifying abount sent/received message. + /// + /// + /// Event sender. + /// Event arguments containing details about the transferred message. + /// + public delegate void MessageTransferHandler( object sender, CommunicationBufferEventArgs eventArgs ); +} diff --git a/Sources/Accord.Core/AForge/DoublePoint.cs b/Sources/Accord.Core/AForge/DoublePoint.cs new file mode 100644 index 0000000000..88affeb05 --- /dev/null +++ b/Sources/Accord.Core/AForge/DoublePoint.cs @@ -0,0 +1,394 @@ +// AForge Core Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge +{ + using System; + + /// + /// Structure for representing a pair of coordinates of double type. + /// + /// + /// The structure is used to store a pair of floating point + /// coordinates with double precision. + /// + /// Sample usage: + /// + /// // assigning coordinates in the constructor + /// DoublePoint p1 = new DoublePoint( 10, 20 ); + /// // creating a point and assigning coordinates later + /// DoublePoint p2; + /// p2.X = 30; + /// p2.Y = 40; + /// // calculating distance between two points + /// double distance = p1.DistanceTo( p2 ); + /// + /// + /// + [Serializable] + public struct DoublePoint + { + /// + /// X coordinate. + /// + /// + public double X; + + /// + /// Y coordinate. + /// + /// + public double Y; + + /// + /// Initializes a new instance of the structure. + /// + /// + /// X axis coordinate. + /// Y axis coordinate. + /// + public DoublePoint(double x, double y) + { + this.X = x; + this.Y = y; + } + + /// + /// Calculate Euclidean distance between two points. + /// + /// + /// Point to calculate distance to. + /// + /// Returns Euclidean distance between this point and + /// points. + /// + public double DistanceTo(DoublePoint anotherPoint) + { + double dx = X - anotherPoint.X; + double dy = Y - anotherPoint.Y; + + return System.Math.Sqrt(dx * dx + dy * dy); + } + + /// + /// Calculate squared Euclidean distance between two points. + /// + /// + /// Point to calculate distance to. + /// + /// Returns squared Euclidean distance between this point and + /// points. + /// + public double SquaredDistanceTo(DoublePoint anotherPoint) + { + double dx = X - anotherPoint.X; + double dy = Y - anotherPoint.Y; + + return dx * dx + dy * dy; + } + + /// + /// Addition operator - adds values of two points. + /// + /// + /// First point for addition. + /// Second point for addition. + /// + /// Returns new point which coordinates equal to sum of corresponding + /// coordinates of specified points. + /// + public static DoublePoint operator +(DoublePoint point1, DoublePoint point2) + { + return new DoublePoint(point1.X + point2.X, point1.Y + point2.Y); + } + + /// + /// Addition operator - adds values of two points. + /// + /// + /// First point for addition. + /// Second point for addition. + /// + /// Returns new point which coordinates equal to sum of corresponding + /// coordinates of specified points. + /// + public static DoublePoint Add(DoublePoint point1, DoublePoint point2) + { + return new DoublePoint(point1.X + point2.X, point1.Y + point2.Y); + } + + /// + /// Subtraction operator - subtracts values of two points. + /// + /// + /// Point to subtract from. + /// Point to subtract. + /// + /// Returns new point which coordinates equal to difference of corresponding + /// coordinates of specified points. + /// + public static DoublePoint operator -(DoublePoint point1, DoublePoint point2) + { + return new DoublePoint(point1.X - point2.X, point1.Y - point2.Y); + } + + /// + /// Subtraction operator - subtracts values of two points. + /// + /// + /// Point to subtract from. + /// Point to subtract. + /// + /// Returns new point which coordinates equal to difference of corresponding + /// coordinates of specified points. + /// + public static DoublePoint Subtract(DoublePoint point1, DoublePoint point2) + { + return new DoublePoint(point1.X - point2.X, point1.Y - point2.Y); + } + + /// + /// Addition operator - adds scalar to the specified point. + /// + /// + /// Point to increase coordinates of. + /// Value to add to coordinates of the specified point. + /// + /// Returns new point which coordinates equal to coordinates of + /// the specified point increased by specified value. + /// + public static DoublePoint operator +(DoublePoint point, double valueToAdd) + { + return new DoublePoint(point.X + valueToAdd, point.Y + valueToAdd); + } + + /// + /// Addition operator - adds scalar to the specified point. + /// + /// + /// Point to increase coordinates of. + /// Value to add to coordinates of the specified point. + /// + /// Returns new point which coordinates equal to coordinates of + /// the specified point increased by specified value. + /// + public static DoublePoint Add(DoublePoint point, double valueToAdd) + { + return new DoublePoint(point.X + valueToAdd, point.Y + valueToAdd); + } + + /// + /// Subtraction operator - subtracts scalar from the specified point. + /// + /// + /// Point to decrease coordinates of. + /// Value to subtract from coordinates of the specified point. + /// + /// Returns new point which coordinates equal to coordinates of + /// the specified point decreased by specified value. + /// + public static DoublePoint operator -(DoublePoint point, double valueToSubtract) + { + return new DoublePoint(point.X - valueToSubtract, point.Y - valueToSubtract); + } + + /// + /// Subtraction operator - subtracts scalar from the specified point. + /// + /// + /// Point to decrease coordinates of. + /// Value to subtract from coordinates of the specified point. + /// + /// Returns new point which coordinates equal to coordinates of + /// the specified point decreased by specified value. + /// + public static DoublePoint Subtract(DoublePoint point, double valueToSubtract) + { + return new DoublePoint(point.X - valueToSubtract, point.Y - valueToSubtract); + } + + /// + /// Multiplication operator - multiplies coordinates of the specified point by scalar value. + /// + /// + /// Point to multiply coordinates of. + /// Multiplication factor. + /// + /// Returns new point which coordinates equal to coordinates of + /// the specified point multiplied by specified value. + /// + public static DoublePoint operator *(DoublePoint point, double factor) + { + return new DoublePoint(point.X * factor, point.Y * factor); + } + + /// + /// Multiplication operator - multiplies coordinates of the specified point by scalar value. + /// + /// + /// Point to multiply coordinates of. + /// Multiplication factor. + /// + /// Returns new point which coordinates equal to coordinates of + /// the specified point multiplied by specified value. + /// + public static DoublePoint Multiply(DoublePoint point, double factor) + { + return new DoublePoint(point.X * factor, point.Y * factor); + } + + /// + /// Division operator - divides coordinates of the specified point by scalar value. + /// + /// + /// Point to divide coordinates of. + /// Division factor. + /// + /// Returns new point which coordinates equal to coordinates of + /// the specified point divided by specified value. + /// + public static DoublePoint operator /(DoublePoint point, double factor) + { + return new DoublePoint(point.X / factor, point.Y / factor); + } + + /// + /// Division operator - divides coordinates of the specified point by scalar value. + /// + /// + /// Point to divide coordinates of. + /// Division factor. + /// + /// Returns new point which coordinates equal to coordinates of + /// the specified point divided by specified value. + /// + public static DoublePoint Divide(DoublePoint point, double factor) + { + return new DoublePoint(point.X / factor, point.Y / factor); + } + + /// + /// Equality operator - checks if two points have equal coordinates. + /// + /// + /// First point to check. + /// Second point to check. + /// + /// Returns if coordinates of specified + /// points are equal. + /// + public static bool operator ==(DoublePoint point1, DoublePoint point2) + { + return ((point1.X == point2.X) && (point1.Y == point2.Y)); + } + + /// + /// Inequality operator - checks if two points have different coordinates. + /// + /// + /// First point to check. + /// Second point to check. + /// + /// Returns if coordinates of specified + /// points are not equal. + /// + public static bool operator !=(DoublePoint point1, DoublePoint point2) + { + return ((point1.X != point2.X) || (point1.Y != point2.Y)); + } + + /// + /// Check if this instance of equal to the specified one. + /// + /// + /// Another point to check equalty to. + /// + /// Return if objects are equal. + /// + public override bool Equals(object obj) + { + return (obj is DoublePoint) ? (this == (DoublePoint)obj) : false; + } + + /// + /// Get hash code for this instance. + /// + /// + /// Returns the hash code for this instance. + /// + public override int GetHashCode() + { + return X.GetHashCode() + Y.GetHashCode(); + } + + /// + /// Explicit conversion to . + /// + /// + /// Double precision point to convert to integer point. + /// + /// Returns new integer point which coordinates are explicitly converted + /// to integers from coordinates of the specified double precision point by + /// casting double values to integers value. + /// + public static explicit operator IntPoint(DoublePoint point) + { + return new IntPoint((int)point.X, (int)point.Y); + } + + /// + /// Explicit conversion to . + /// + /// + /// Double precision point to convert to single precision point. + /// + /// Returns new single precision point which coordinates are explicitly converted + /// to floats from coordinates of the specified double precision point by + /// casting double values to float value. + /// + public static explicit operator Point(DoublePoint point) + { + return new Point((float)point.X, (float)point.Y); + } + + /// + /// Rounds the double precision point. + /// + /// + /// Returns new integer point, which coordinates equal to whole numbers + /// nearest to the corresponding coordinates of the double precision point. + /// + public IntPoint Round() + { + return new IntPoint((int)Math.Round(X), (int)Math.Round(Y)); + } + + /// + /// Get string representation of the class. + /// + /// + /// Returns string, which contains values of the point in readable form. + /// + public override string ToString() + { + return string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}, {1}", X, Y); + } + + /// + /// Calculate Euclidean norm of the vector comprised of the point's + /// coordinates - distance from (0, 0) in other words. + /// + /// + /// Returns point's distance from (0, 0) point. + /// + public double EuclideanNorm() + { + return System.Math.Sqrt(X * X + Y * Y); + } + } +} diff --git a/Sources/Accord.Core/AForge/DoubleRange.cs b/Sources/Accord.Core/AForge/DoubleRange.cs new file mode 100644 index 0000000000..7bdb4a18e --- /dev/null +++ b/Sources/Accord.Core/AForge/DoubleRange.cs @@ -0,0 +1,239 @@ +// AForge Core Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge +{ + using System; + + /// + /// Represents a double range with minimum and maximum values. + /// + /// + /// + /// The class represents a double range with inclusive limits - + /// both minimum and maximum values of the range are included into it. + /// Mathematical notation of such range is [min, max]. + /// + /// Sample usage: + /// + /// // create [0.25, 1.5] range + /// DoubleRange range1 = new DoubleRange( 0.25, 1.5 ); + /// // create [1.00, 2.25] range + /// DoubleRange range2 = new DoubleRange( 1.00, 2.25 ); + /// // check if values is inside of the first range + /// if ( range1.IsInside( 0.75 ) ) + /// { + /// // ... + /// } + /// // check if the second range is inside of the first range + /// if ( range1.IsInside( range2 ) ) + /// { + /// // ... + /// } + /// // check if two ranges overlap + /// if ( range1.IsOverlapping( range2 ) ) + /// { + /// // ... + /// } + /// + /// + /// + [Serializable] + public struct DoubleRange + { + private double min, max; + + /// + /// Minimum value of the range. + /// + /// + /// The property represents minimum value (left side limit) or the range - + /// [min, max]. + /// + public double Min + { + get { return min; } + set { min = value; } + } + + /// + /// Maximum value of the range. + /// + /// + /// The property represents maximum value (right side limit) or the range - + /// [min, max]. + /// + public double Max + { + get { return max; } + set { max = value; } + } + + /// + /// Length of the range (deffirence between maximum and minimum values). + /// + public double Length + { + get { return max - min; } + } + + + /// + /// Initializes a new instance of the class. + /// + /// + /// Minimum value of the range. + /// Maximum value of the range. + /// + public DoubleRange( double min, double max ) + { + this.min = min; + this.max = max; + } + + /// + /// Check if the specified value is inside of the range. + /// + /// + /// Value to check. + /// + /// True if the specified value is inside of the range or + /// false otherwise. + /// + public bool IsInside( double x ) + { + return ( ( x >= min ) && ( x <= max ) ); + } + + /// + /// Check if the specified range is inside of the range. + /// + /// + /// Range to check. + /// + /// True if the specified range is inside of the range or + /// false otherwise. + /// + public bool IsInside( DoubleRange range ) + { + return ( ( IsInside( range.min ) ) && ( IsInside( range.max ) ) ); + } + + /// + /// Check if the specified range overlaps with the range. + /// + /// + /// Range to check for overlapping. + /// + /// True if the specified range overlaps with the range or + /// false otherwise. + /// + public bool IsOverlapping( DoubleRange range ) + { + return ( ( IsInside( range.min ) ) || ( IsInside( range.max ) ) || + ( range.IsInside( min ) ) || ( range.IsInside( max ) ) ); + } + + /// + /// Convert the signle precision range to integer range. + /// + /// + /// Specifies if inner integer range must be returned or outer range. + /// + /// Returns integer version of the range. + /// + /// If is set to , then the + /// returned integer range will always fit inside of the current single precision range. + /// If it is set to , then current single precision range will always + /// fit into the returned integer range. + /// + public IntRange ToIntRange( bool provideInnerRange ) + { + int iMin, iMax; + + if ( provideInnerRange ) + { + iMin = (int) Math.Ceiling( min ); + iMax = (int) Math.Floor( max ); + } + else + { + iMin = (int) Math.Floor( min ); + iMax = (int) Math.Ceiling( max ); + } + + return new IntRange( iMin, iMax ); + } + + /// + /// Equality operator - checks if two ranges have equal min/max values. + /// + /// + /// First range to check. + /// Second range to check. + /// + /// Returns if min/max values of specified + /// ranges are equal. + /// + public static bool operator ==( DoubleRange range1, DoubleRange range2 ) + { + return ( ( range1.min == range2.min ) && ( range1.max == range2.max ) ); + } + + /// + /// Inequality operator - checks if two ranges have different min/max values. + /// + /// + /// First range to check. + /// Second range to check. + /// + /// Returns if min/max values of specified + /// ranges are not equal. + /// + public static bool operator !=( DoubleRange range1, DoubleRange range2 ) + { + return ( ( range1.min != range2.min ) || ( range1.max != range2.max ) ); + + } + + /// + /// Check if this instance of equal to the specified one. + /// + /// + /// Another range to check equalty to. + /// + /// Return if objects are equal. + /// + public override bool Equals( object obj ) + { + return ( obj is Range ) ? ( this == (DoubleRange) obj ) : false; + } + + /// + /// Get hash code for this instance. + /// + /// + /// Returns the hash code for this instance. + /// + public override int GetHashCode( ) + { + return min.GetHashCode( ) + max.GetHashCode( ); + } + + /// + /// Get string representation of the class. + /// + /// + /// Returns string, which contains min/max values of the range in readable form. + /// + public override string ToString( ) + { + return string.Format( System.Globalization.CultureInfo.InvariantCulture, "{0}, {1}", min, max ); + } + } +} diff --git a/Sources/Accord.Core/AForge/EventArgs.cs b/Sources/Accord.Core/AForge/EventArgs.cs new file mode 100644 index 0000000000..ccfc907db --- /dev/null +++ b/Sources/Accord.Core/AForge/EventArgs.cs @@ -0,0 +1,82 @@ +// AForge Core Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge +{ + using System; + + /// + /// Event arguments holding a buffer sent or received during some communication process. + /// + public class CommunicationBufferEventArgs : EventArgs + { + private readonly byte[] message; + private readonly int index; + private readonly int length; + + /// + /// Length of the transfered message. + /// + public int MessageLength + { + get { return length; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Message being transfered during communication process. + /// + public CommunicationBufferEventArgs(byte[] message) + { + this.message = message; + this.index = 0; + this.length = message.Length; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Buffer containing the message being transferred during communication process. + /// Starting index of the message within the buffer. + /// Length of the message within the buffer. + /// + public CommunicationBufferEventArgs(byte[] buffer, int index, int length) + { + this.message = buffer; + this.index = index; + this.length = length; + } + + /// + /// Get the transfered message. + /// + /// + /// Returns copy of the transfered message. + /// + public byte[] GetMessage() + { + byte[] ret = new byte[length]; + Array.Copy(message, index, ret, 0, length); + return ret; + } + + /// + /// Get the transferred message as string. + /// + /// + /// Returns string encoding the transferred message. + /// + public string GetMessageString() + { + return BitConverter.ToString(message, index, length); + } + } +} diff --git a/Sources/Accord.Core/AForge/Exceptions.cs b/Sources/Accord.Core/AForge/Exceptions.cs new file mode 100644 index 0000000000..a3791190e --- /dev/null +++ b/Sources/Accord.Core/AForge/Exceptions.cs @@ -0,0 +1,243 @@ +// AForge Core Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2007-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge +{ + using System; + using System.Runtime.Serialization; + + /// + /// Connection failed exception. + /// + /// + /// The exception is thrown in the case if connection to device + /// has failed. + /// + /// + [Serializable] + public class ConnectionFailedException : Exception + { + /// + /// Initializes a new instance of the class. + /// + /// + public ConnectionFailedException() + : base() { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Exception's message. + /// + public ConnectionFailedException(string message) + : base(message) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + /// + public ConnectionFailedException(string message, Exception innerException) + : base(message, innerException) { } + } + + /// + /// Connection lost exception. + /// + /// + /// The exception is thrown in the case if connection to device + /// is lost. When the exception is caught, user may need to reconnect to the device. + /// + /// + [Serializable] + public class ConnectionLostException : Exception + { + /// + /// Initializes a new instance of the class. + /// + /// + public ConnectionLostException() : + base() { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Exception's message. + /// + public ConnectionLostException(string message) : + base(message) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + /// + public ConnectionLostException(string message, Exception innerException) + : base(message, innerException) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. + /// + public ConnectionLostException(SerializationInfo info, StreamingContext context) + : base(info, context) { } + } + + /// + /// Not connected exception. + /// + /// + /// The exception is thrown in the case if connection to device + /// is not established, but user requests for its services. + /// + /// + [Serializable] + public class NotConnectedException : Exception + { + /// + /// Initializes a new instance of the class. + /// + /// + public NotConnectedException() : + base() { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Exception's message. + /// + public NotConnectedException(string message) : + base(message) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + /// + public NotConnectedException(string message, Exception innerException) + : base(message, innerException) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. + /// + public NotConnectedException(SerializationInfo info, StreamingContext context) + : base(info, context) { } + + } + + /// + /// Device busy exception. + /// + /// + /// The exception is thrown in the case if access to certain device + /// is not available due to the fact that it is currently busy handling other request/connection. + /// + /// + [Serializable] + public class DeviceBusyException : Exception + { + /// + /// Initializes a new instance of the class. + /// + /// + public DeviceBusyException() : + base() { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Exception's message. + /// + public DeviceBusyException(string message) : + base(message) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + /// + public DeviceBusyException(string message, Exception innerException) + : base(message, innerException) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. + /// + public DeviceBusyException(SerializationInfo info, StreamingContext context) + : base(info, context) { } + } + + /// + /// Device error exception. + /// + /// + /// The exception is thrown in the case if some error happens with a device, which + /// may need to be reported to user. + /// + [Serializable] + public class DeviceErrorException : Exception + { + /// + /// Initializes a new instance of the class. + /// + /// + public DeviceErrorException() : + base() { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Exception's message. + /// + public DeviceErrorException(string message) : + base(message) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + /// + public DeviceErrorException(string message, Exception innerException) + : base(message, innerException) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. + /// + public DeviceErrorException(SerializationInfo info, StreamingContext context) + : base(info, context) { } + } +} diff --git a/Sources/Accord.Core/AForge/IntPoint.cs b/Sources/Accord.Core/AForge/IntPoint.cs new file mode 100644 index 0000000000..a4e30a955 --- /dev/null +++ b/Sources/Accord.Core/AForge/IntPoint.cs @@ -0,0 +1,380 @@ +// AForge Core Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge +{ + using System; + using System.ComponentModel; + + /// + /// Structure for representing a pair of coordinates of integer type. + /// + /// + /// The structure is used to store a pair of integer coordinates. + /// + /// Sample usage: + /// + /// // assigning coordinates in the constructor + /// IntPoint p1 = new IntPoint( 10, 20 ); + /// // creating a point and assigning coordinates later + /// IntPoint p2; + /// p2.X = 30; + /// p2.Y = 40; + /// // calculating distance between two points + /// float distance = p1.DistanceTo( p2 ); + /// + /// + /// + [Serializable] + public struct IntPoint + { + /// + /// X coordinate. + /// + /// + public int X; + + /// + /// Y coordinate. + /// + /// + public int Y; + + /// + /// Initializes a new instance of the structure. + /// + /// + /// X axis coordinate. + /// Y axis coordinate. + /// + public IntPoint( int x, int y ) + { + this.X = x; + this.Y = y; + } + + /// + /// Calculate Euclidean distance between two points. + /// + /// + /// Point to calculate distance to. + /// + /// Returns Euclidean distance between this point and + /// points. + /// + public float DistanceTo( IntPoint anotherPoint ) + { + int dx = X - anotherPoint.X; + int dy = Y - anotherPoint.Y; + + return (float) System.Math.Sqrt( dx * dx + dy * dy ); + } + + /// + /// Calculate squared Euclidean distance between two points. + /// + /// + /// Point to calculate distance to. + /// + /// Returns squared Euclidean distance between this point and + /// points. + /// + public float SquaredDistanceTo( Point anotherPoint ) + { + float dx = X - anotherPoint.X; + float dy = Y - anotherPoint.Y; + + return dx * dx + dy * dy; + } + + /// + /// Addition operator - adds values of two points. + /// + /// + /// First point for addition. + /// Second point for addition. + /// + /// Returns new point which coordinates equal to sum of corresponding + /// coordinates of specified points. + /// + public static IntPoint operator +( IntPoint point1, IntPoint point2 ) + { + return new IntPoint( point1.X + point2.X, point1.Y + point2.Y ); + } + + /// + /// Addition operator - adds values of two points. + /// + /// + /// First point for addition. + /// Second point for addition. + /// + /// Returns new point which coordinates equal to sum of corresponding + /// coordinates of specified points. + /// + public static IntPoint Add( IntPoint point1, IntPoint point2 ) + { + return new IntPoint( point1.X + point2.X, point1.Y + point2.Y ); + } + + /// + /// Subtraction operator - subtracts values of two points. + /// + /// + /// Point to subtract from. + /// Point to subtract. + /// + /// Returns new point which coordinates equal to difference of corresponding + /// coordinates of specified points. + /// + public static IntPoint operator -( IntPoint point1, IntPoint point2 ) + { + return new IntPoint( point1.X - point2.X, point1.Y - point2.Y ); + } + + /// + /// Subtraction operator - subtracts values of two points. + /// + /// + /// Point to subtract from. + /// Point to subtract. + /// + /// Returns new point which coordinates equal to difference of corresponding + /// coordinates of specified points. + /// + public static IntPoint Subtract( IntPoint point1, IntPoint point2 ) + { + return new IntPoint( point1.X - point2.X, point1.Y - point2.Y ); + } + + /// + /// Addition operator - adds scalar to the specified point. + /// + /// + /// Point to increase coordinates of. + /// Value to add to coordinates of the specified point. + /// + /// Returns new point which coordinates equal to coordinates of + /// the specified point increased by specified value. + /// + public static IntPoint operator +( IntPoint point, int valueToAdd ) + { + return new IntPoint( point.X + valueToAdd, point.Y + valueToAdd ); + } + + /// + /// Addition operator - adds scalar to the specified point. + /// + /// + /// Point to increase coordinates of. + /// Value to add to coordinates of the specified point. + /// + /// Returns new point which coordinates equal to coordinates of + /// the specified point increased by specified value. + /// + public static IntPoint Add( IntPoint point, int valueToAdd ) + { + return new IntPoint( point.X + valueToAdd, point.Y + valueToAdd ); + } + + /// + /// Subtraction operator - subtracts scalar from the specified point. + /// + /// + /// Point to decrease coordinates of. + /// Value to subtract from coordinates of the specified point. + /// + /// Returns new point which coordinates equal to coordinates of + /// the specified point decreased by specified value. + /// + public static IntPoint operator -( IntPoint point, int valueToSubtract ) + { + return new IntPoint( point.X - valueToSubtract, point.Y - valueToSubtract ); + } + + /// + /// Subtraction operator - subtracts scalar from the specified point. + /// + /// + /// Point to decrease coordinates of. + /// Value to subtract from coordinates of the specified point. + /// + /// Returns new point which coordinates equal to coordinates of + /// the specified point decreased by specified value. + /// + public static IntPoint Subtract( IntPoint point, int valueToSubtract ) + { + return new IntPoint( point.X - valueToSubtract, point.Y - valueToSubtract ); + } + + /// + /// Multiplication operator - multiplies coordinates of the specified point by scalar value. + /// + /// + /// Point to multiply coordinates of. + /// Multiplication factor. + /// + /// Returns new point which coordinates equal to coordinates of + /// the specified point multiplied by specified value. + /// + public static IntPoint operator *( IntPoint point, int factor ) + { + return new IntPoint( point.X * factor, point.Y * factor ); + } + + /// + /// Multiplication operator - multiplies coordinates of the specified point by scalar value. + /// + /// + /// Point to multiply coordinates of. + /// Multiplication factor. + /// + /// Returns new point which coordinates equal to coordinates of + /// the specified point multiplied by specified value. + /// + public static IntPoint Multiply( IntPoint point, int factor ) + { + return new IntPoint( point.X * factor, point.Y * factor ); + } + + /// + /// Division operator - divides coordinates of the specified point by scalar value. + /// + /// + /// Point to divide coordinates of. + /// Division factor. + /// + /// Returns new point which coordinates equal to coordinates of + /// the specified point divided by specified value. + /// + public static IntPoint operator /( IntPoint point, int factor ) + { + return new IntPoint( point.X / factor, point.Y / factor ); + } + + /// + /// Division operator - divides coordinates of the specified point by scalar value. + /// + /// + /// Point to divide coordinates of. + /// Division factor. + /// + /// Returns new point which coordinates equal to coordinates of + /// the specified point divided by specified value. + /// + public static IntPoint Divide( IntPoint point, int factor ) + { + return new IntPoint( point.X / factor, point.Y / factor ); + } + + /// + /// Equality operator - checks if two points have equal coordinates. + /// + /// + /// First point to check. + /// Second point to check. + /// + /// Returns if coordinates of specified + /// points are equal. + /// + public static bool operator ==( IntPoint point1, IntPoint point2 ) + { + return ( ( point1.X == point2.X ) && ( point1.Y == point2.Y ) ); + } + + /// + /// Inequality operator - checks if two points have different coordinates. + /// + /// + /// First point to check. + /// Second point to check. + /// + /// Returns if coordinates of specified + /// points are not equal. + /// + public static bool operator !=( IntPoint point1, IntPoint point2 ) + { + return ( ( point1.X != point2.X ) || ( point1.Y != point2.Y ) ); + } + + /// + /// Check if this instance of equal to the specified one. + /// + /// + /// Another point to check equalty to. + /// + /// Return if objects are equal. + /// + public override bool Equals( object obj ) + { + return ( obj is IntPoint ) ? ( this == (IntPoint) obj ) : false; + } + + /// + /// Get hash code for this instance. + /// + /// + /// Returns the hash code for this instance. + /// + public override int GetHashCode( ) + { + return X.GetHashCode( ) + Y.GetHashCode( ); + } + + /// + /// Implicit conversion to . + /// + /// + /// Integer point to convert to single precision point. + /// + /// Returns new single precision point which coordinates are implicitly converted + /// to floats from coordinates of the specified integer point. + /// + public static implicit operator Point( IntPoint point ) + { + return new Point( point.X, point.Y ); + } + + /// + /// Implicit conversion to . + /// + /// + /// Integer point to convert to double precision point. + /// + /// Returns new double precision point which coordinates are implicitly converted + /// to doubles from coordinates of the specified integer point. + /// + public static implicit operator DoublePoint( IntPoint point ) + { + return new DoublePoint( point.X, point.Y ); + } + + /// + /// Get string representation of the class. + /// + /// + /// Returns string, which contains values of the point in readable form. + /// + public override string ToString( ) + { + return string.Format( System.Globalization.CultureInfo.InvariantCulture, "{0}, {1}", X, Y ); + } + + /// + /// Calculate Euclidean norm of the vector comprised of the point's + /// coordinates - distance from (0, 0) in other words. + /// + /// + /// Returns point's distance from (0, 0) point. + /// + public float EuclideanNorm( ) + { + return (float) System.Math.Sqrt( X * X + Y * Y ); + } + } +} diff --git a/Sources/Accord.Core/AForge/IntRange.cs b/Sources/Accord.Core/AForge/IntRange.cs new file mode 100644 index 0000000000..bf7c3ff1c --- /dev/null +++ b/Sources/Accord.Core/AForge/IntRange.cs @@ -0,0 +1,221 @@ +// AForge Core Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2007-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge +{ + using System; + + /// + /// Represents an integer range with minimum and maximum values. + /// + /// + /// + /// The class represents an integer range with inclusive limits - + /// both minimum and maximum values of the range are included into it. + /// Mathematical notation of such range is [min, max]. + /// + /// Sample usage: + /// + /// // create [1, 10] range + /// IntRange range1 = new IntRange( 1, 10 ); + /// // create [5, 15] range + /// IntRange range2 = new IntRange( 5, 15 ); + /// // check if values is inside of the first range + /// if ( range1.IsInside( 7 ) ) + /// { + /// // ... + /// } + /// // check if the second range is inside of the first range + /// if ( range1.IsInside( range2 ) ) + /// { + /// // ... + /// } + /// // check if two ranges overlap + /// if ( range1.IsOverlapping( range2 ) ) + /// { + /// // ... + /// } + /// + /// + /// + [Serializable] + public struct IntRange + { + private int min, max; + + /// + /// Minimum value of the range. + /// + /// + /// The property represents minimum value (left side limit) or the range - + /// [min, max]. + /// + public int Min + { + get { return min; } + set { min = value; } + } + + /// + /// Maximum value of the range. + /// + /// + /// The property represents maximum value (right side limit) or the range - + /// [min, max]. + /// + public int Max + { + get { return max; } + set { max = value; } + } + + /// + /// Length of the range (deffirence between maximum and minimum values). + /// + public int Length + { + get { return max - min; } + } + + /// + /// Initializes a new instance of the structure. + /// + /// + /// Minimum value of the range. + /// Maximum value of the range. + /// + public IntRange( int min, int max ) + { + this.min = min; + this.max = max; + } + + /// + /// Check if the specified value is inside of the range. + /// + /// + /// Value to check. + /// + /// True if the specified value is inside of the range or + /// false otherwise. + /// + public bool IsInside( int x ) + { + return ( ( x >= min ) && ( x <= max ) ); + } + + /// + /// Check if the specified range is inside of the range. + /// + /// + /// Range to check. + /// + /// True if the specified range is inside of the range or + /// false otherwise. + /// + public bool IsInside( IntRange range ) + { + return ( ( IsInside( range.min ) ) && ( IsInside( range.max ) ) ); + } + + /// + /// Check if the specified range overlaps with the range. + /// + /// + /// Range to check for overlapping. + /// + /// True if the specified range overlaps with the range or + /// false otherwise. + /// + public bool IsOverlapping( IntRange range ) + { + return ( ( IsInside( range.min ) ) || ( IsInside( range.max ) ) || + ( range.IsInside( min ) ) || ( range.IsInside( max ) ) ); + } + + /// + /// Implicit conversion to . + /// + /// + /// Integer range to convert to single precision range. + /// + /// Returns new single precision range which min/max values are implicitly converted + /// to floats from min/max values of the specified integer range. + /// + public static implicit operator Range( IntRange range ) + { + return new Range( range.Min, range.Max ); + } + + /// + /// Equality operator - checks if two ranges have equal min/max values. + /// + /// + /// First range to check. + /// Second range to check. + /// + /// Returns if min/max values of specified + /// ranges are equal. + /// + public static bool operator ==( IntRange range1, IntRange range2 ) + { + return ( ( range1.min == range2.min ) && ( range1.max == range2.max ) ); + } + + /// + /// Inequality operator - checks if two ranges have different min/max values. + /// + /// + /// First range to check. + /// Second range to check. + /// + /// Returns if min/max values of specified + /// ranges are not equal. + /// + public static bool operator !=( IntRange range1, IntRange range2 ) + { + return ( ( range1.min != range2.min ) || ( range1.max != range2.max ) ); + + } + + /// + /// Check if this instance of equal to the specified one. + /// + /// + /// Another range to check equalty to. + /// + /// Return if objects are equal. + /// + public override bool Equals( object obj ) + { + return ( obj is IntRange ) ? ( this == (IntRange) obj ) : false; + } + + /// + /// Get hash code for this instance. + /// + /// + /// Returns the hash code for this instance. + /// + public override int GetHashCode( ) + { + return min.GetHashCode( ) + max.GetHashCode( ); + } + + /// + /// Get string representation of the class. + /// + /// + /// Returns string, which contains min/max values of the range in readable form. + /// + public override string ToString( ) + { + return string.Format( System.Globalization.CultureInfo.InvariantCulture, "{0}, {1}", min, max ); + } + } +} diff --git a/Sources/Accord.Core/AForge/Parallel.cs b/Sources/Accord.Core/AForge/Parallel.cs new file mode 100644 index 0000000000..068f6c66d --- /dev/null +++ b/Sources/Accord.Core/AForge/Parallel.cs @@ -0,0 +1,237 @@ +// AForge Core Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2007-2009 +// andrew.kirillov@aforgenet.com +// +// Copyright © Israel Lot, 2008 +// israel.lot@gmail.com +// + +namespace AForge +{ + using System; + using System.Threading; + + /// + /// The class provides support for parallel computations, paralleling loop's iterations. + /// + /// + /// The class allows to parallel loop's iteration computing them in separate threads, + /// what allows their simultaneous execution on multiple CPUs/cores. + /// + /// + public sealed class Parallel + { + /// + /// Delegate defining for-loop's body. + /// + /// + /// Loop's index. + /// + public delegate void ForLoopBody( int index ); + + // number of threads for parallel computations + private static int threadsCount = System.Environment.ProcessorCount; + // object used for synchronization + private static object sync = new Object( ); + + // single instance of the class to implement singleton pattern + private static volatile Parallel instance = null; + // background threads for parallel computation + private Thread[] threads = null; + + // events to signal about job availability and thread availability + private AutoResetEvent[] jobAvailable = null; + private ManualResetEvent[] threadIdle = null; + + // loop's body and its current and stop index + private int currentIndex; + private int stopIndex; + private ForLoopBody loopBody; + + /// + /// Number of threads used for parallel computations. + /// + /// + /// The property sets how many worker threads are created for paralleling + /// loops' computations. + /// + /// By default the property is set to number of CPU's in the system + /// (see ). + /// + /// + public static int ThreadsCount + { + get { return threadsCount; } + set + { + lock ( sync ) + { + threadsCount = Math.Max( 1, value ); + } + } + } + + /// + /// Executes a for-loop in which iterations may run in parallel. + /// + /// + /// Loop's start index. + /// Loop's stop index. + /// Loop's body. + /// + /// The method is used to parallel for-loop running its iterations in + /// different threads. The start and stop parameters define loop's + /// starting and ending loop's indexes. The number of iterations is equal to stop - start. + /// + /// + /// Sample usage: + /// + /// Parallel.For( 0, 20, delegate( int i ) + /// // which is equivalent to + /// // for ( int i = 0; i < 20; i++ ) + /// { + /// System.Diagnostics.Debug.WriteLine( "Iteration: " + i ); + /// // ... + /// } ); + /// + /// + /// + public static void For( int start, int stop, ForLoopBody loopBody ) + { + lock ( sync ) + { + // get instance of parallel computation manager + Parallel instance = Instance; + + instance.currentIndex = start - 1; + instance.stopIndex = stop; + instance.loopBody = loopBody; + + // signal about available job for all threads and mark them busy + for ( int i = 0; i < threadsCount; i++ ) + { + instance.threadIdle[i].Reset( ); + instance.jobAvailable[i].Set( ); + } + + // wait until all threads become idle + for ( int i = 0; i < threadsCount; i++ ) + { + instance.threadIdle[i].WaitOne( ); + } + + instance.loopBody = null; + } + } + + // Private constructor to avoid class instantiation + private Parallel( ) { } + + // Get instace of the Parallel class + private static Parallel Instance + { + get + { + if ( instance == null ) + { + instance = new Parallel( ); + instance.Initialize( ); + } + else + { + if ( instance.threads.Length != threadsCount ) + { + // terminate old threads + instance.Terminate( ); + // reinitialize + instance.Initialize( ); + + // TODO: change reinitialization to reuse already created objects + } + } + return instance; + } + } + + // Initialize Parallel class's instance creating required number of threads + // and synchronization objects + private void Initialize( ) + { + // array of events, which signal about available job + jobAvailable = new AutoResetEvent[threadsCount]; + // array of events, which signal about available thread + threadIdle = new ManualResetEvent[threadsCount]; + // array of threads + threads = new Thread[threadsCount]; + + for ( int i = 0; i < threadsCount; i++ ) + { + jobAvailable[i] = new AutoResetEvent( false ); + threadIdle[i] = new ManualResetEvent( true ); + + threads[i] = new Thread( new ParameterizedThreadStart( WorkerThread ) ); + threads[i].Name = "AForge.Parallel"; + threads[i].IsBackground = true; + threads[i].Start( i ); + } + } + + // Terminate all worker threads used for parallel computations and close all + // synchronization objects + private void Terminate( ) + { + // finish thread by setting null loop body and signaling about available work + loopBody = null; + for ( int i = 0, threadsCount = threads.Length ; i < threadsCount; i++ ) + { + jobAvailable[i].Set( ); + // wait for thread termination + threads[i].Join( ); + + // close events + jobAvailable[i].Close( ); + threadIdle[i].Close( ); + } + + // clean all array references + jobAvailable = null; + threadIdle = null; + threads = null; + } + + // Worker thread performing parallel computations in loop + private void WorkerThread( object index ) + { + int threadIndex = (int) index; + int localIndex = 0; + + while ( true ) + { + // wait until there is job to do + jobAvailable[threadIndex].WaitOne( ); + + // exit on null body + if ( loopBody == null ) + break; + + while ( true ) + { + // get local index incrementing global loop's current index + localIndex = Interlocked.Increment( ref currentIndex ); + + if ( localIndex >= stopIndex ) + break; + + // run loop's body + loopBody( localIndex ); + } + + // signal about thread availability + threadIdle[threadIndex].Set( ); + } + } + } +} diff --git a/Sources/Accord.Core/AForge/Point.cs b/Sources/Accord.Core/AForge/Point.cs new file mode 100644 index 0000000000..dabb9e585 --- /dev/null +++ b/Sources/Accord.Core/AForge/Point.cs @@ -0,0 +1,393 @@ +// AForge Core Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge +{ + using System; + + /// + /// Structure for representing a pair of coordinates of float type. + /// + /// + /// The structure is used to store a pair of floating point + /// coordinates with single precision. + /// + /// Sample usage: + /// + /// // assigning coordinates in the constructor + /// Point p1 = new Point( 10, 20 ); + /// // creating a point and assigning coordinates later + /// Point p2; + /// p2.X = 30; + /// p2.Y = 40; + /// // calculating distance between two points + /// float distance = p1.DistanceTo( p2 ); + /// + /// + /// + [Serializable] + public struct Point + { + /// + /// X coordinate. + /// + /// + public float X; + + /// + /// Y coordinate. + /// + /// + public float Y; + + /// + /// Initializes a new instance of the structure. + /// + /// + /// X axis coordinate. + /// Y axis coordinate. + /// + public Point( float x, float y ) + { + this.X = x; + this.Y = y; + } + + /// + /// Calculate Euclidean distance between two points. + /// + /// + /// Point to calculate distance to. + /// + /// Returns Euclidean distance between this point and + /// points. + /// + public float DistanceTo( Point anotherPoint ) + { + float dx = X - anotherPoint.X; + float dy = Y - anotherPoint.Y; + + return (float) System.Math.Sqrt( dx * dx + dy * dy ); + } + + /// + /// Calculate squared Euclidean distance between two points. + /// + /// + /// Point to calculate distance to. + /// + /// Returns squared Euclidean distance between this point and + /// points. + /// + public float SquaredDistanceTo( Point anotherPoint ) + { + float dx = X - anotherPoint.X; + float dy = Y - anotherPoint.Y; + + return dx * dx + dy * dy; + } + + /// + /// Addition operator - adds values of two points. + /// + /// + /// First point for addition. + /// Second point for addition. + /// + /// Returns new point which coordinates equal to sum of corresponding + /// coordinates of specified points. + /// + public static Point operator +( Point point1, Point point2 ) + { + return new Point( point1.X + point2.X, point1.Y + point2.Y ); + } + + /// + /// Addition operator - adds values of two points. + /// + /// + /// First point for addition. + /// Second point for addition. + /// + /// Returns new point which coordinates equal to sum of corresponding + /// coordinates of specified points. + /// + public static Point Add( Point point1, Point point2 ) + { + return new Point( point1.X + point2.X, point1.Y + point2.Y ); + } + + /// + /// Subtraction operator - subtracts values of two points. + /// + /// + /// Point to subtract from. + /// Point to subtract. + /// + /// Returns new point which coordinates equal to difference of corresponding + /// coordinates of specified points. + /// + public static Point operator -( Point point1, Point point2 ) + { + return new Point( point1.X - point2.X, point1.Y - point2.Y ); + } + + /// + /// Subtraction operator - subtracts values of two points. + /// + /// + /// Point to subtract from. + /// Point to subtract. + /// + /// Returns new point which coordinates equal to difference of corresponding + /// coordinates of specified points. + /// + public static Point Subtract( Point point1, Point point2 ) + { + return new Point( point1.X - point2.X, point1.Y - point2.Y ); + } + + /// + /// Addition operator - adds scalar to the specified point. + /// + /// + /// Point to increase coordinates of. + /// Value to add to coordinates of the specified point. + /// + /// Returns new point which coordinates equal to coordinates of + /// the specified point increased by specified value. + /// + public static Point operator +( Point point, float valueToAdd ) + { + return new Point( point.X + valueToAdd, point.Y + valueToAdd ); + } + + /// + /// Addition operator - adds scalar to the specified point. + /// + /// + /// Point to increase coordinates of. + /// Value to add to coordinates of the specified point. + /// + /// Returns new point which coordinates equal to coordinates of + /// the specified point increased by specified value. + /// + public static Point Add( Point point, float valueToAdd ) + { + return new Point( point.X + valueToAdd, point.Y + valueToAdd ); + } + + /// + /// Subtraction operator - subtracts scalar from the specified point. + /// + /// + /// Point to decrease coordinates of. + /// Value to subtract from coordinates of the specified point. + /// + /// Returns new point which coordinates equal to coordinates of + /// the specified point decreased by specified value. + /// + public static Point operator -( Point point, float valueToSubtract ) + { + return new Point( point.X - valueToSubtract, point.Y - valueToSubtract ); + } + + /// + /// Subtraction operator - subtracts scalar from the specified point. + /// + /// + /// Point to decrease coordinates of. + /// Value to subtract from coordinates of the specified point. + /// + /// Returns new point which coordinates equal to coordinates of + /// the specified point decreased by specified value. + /// + public static Point Subtract( Point point, float valueToSubtract ) + { + return new Point( point.X - valueToSubtract, point.Y - valueToSubtract ); + } + + /// + /// Multiplication operator - multiplies coordinates of the specified point by scalar value. + /// + /// + /// Point to multiply coordinates of. + /// Multiplication factor. + /// + /// Returns new point which coordinates equal to coordinates of + /// the specified point multiplied by specified value. + /// + public static Point operator *( Point point, float factor ) + { + return new Point( point.X * factor, point.Y * factor ); + } + + /// + /// Multiplication operator - multiplies coordinates of the specified point by scalar value. + /// + /// + /// Point to multiply coordinates of. + /// Multiplication factor. + /// + /// Returns new point which coordinates equal to coordinates of + /// the specified point multiplied by specified value. + /// + public static Point Multiply( Point point, float factor ) + { + return new Point( point.X * factor, point.Y * factor ); + } + + /// + /// Division operator - divides coordinates of the specified point by scalar value. + /// + /// + /// Point to divide coordinates of. + /// Division factor. + /// + /// Returns new point which coordinates equal to coordinates of + /// the specified point divided by specified value. + /// + public static Point operator /( Point point, float factor ) + { + return new Point( point.X / factor, point.Y / factor ); + } + + /// + /// Division operator - divides coordinates of the specified point by scalar value. + /// + /// + /// Point to divide coordinates of. + /// Division factor. + /// + /// Returns new point which coordinates equal to coordinates of + /// the specified point divided by specified value. + /// + public static Point Divide( Point point, float factor ) + { + return new Point( point.X / factor, point.Y / factor ); + } + + /// + /// Equality operator - checks if two points have equal coordinates. + /// + /// + /// First point to check. + /// Second point to check. + /// + /// Returns if coordinates of specified + /// points are equal. + /// + public static bool operator ==( Point point1, Point point2 ) + { + return ( ( point1.X == point2.X ) && ( point1.Y == point2.Y ) ); + } + + /// + /// Inequality operator - checks if two points have different coordinates. + /// + /// + /// First point to check. + /// Second point to check. + /// + /// Returns if coordinates of specified + /// points are not equal. + /// + public static bool operator !=( Point point1, Point point2 ) + { + return ( ( point1.X != point2.X ) || ( point1.Y != point2.Y ) ); + } + + /// + /// Check if this instance of equal to the specified one. + /// + /// + /// Another point to check equalty to. + /// + /// Return if objects are equal. + /// + public override bool Equals( object obj ) + { + return ( obj is Point ) ? ( this == (Point) obj ) : false; + } + + /// + /// Get hash code for this instance. + /// + /// + /// Returns the hash code for this instance. + /// + public override int GetHashCode( ) + { + return X.GetHashCode( ) + Y.GetHashCode( ); + } + + /// + /// Explicit conversion to . + /// + /// + /// Single precision point to convert to integer point. + /// + /// Returns new integer point which coordinates are explicitly converted + /// to integers from coordinates of the specified single precision point by + /// casting float values to integers value. + /// + public static explicit operator IntPoint( Point point ) + { + return new IntPoint( (int) point.X, (int) point.Y ); + } + + /// + /// Implicit conversion to . + /// + /// + /// Single precision point to convert to double precision point. + /// + /// Returns new double precision point which coordinates are implicitly converted + /// to doubles from coordinates of the specified single precision point. + /// + public static implicit operator DoublePoint( Point point ) + { + return new DoublePoint( point.X, point.Y ); + } + + /// + /// Rounds the single precision point. + /// + /// + /// Returns new integer point, which coordinates equal to whole numbers + /// nearest to the corresponding coordinates of the single precision point. + /// + public IntPoint Round( ) + { + return new IntPoint( (int) Math.Round( X ), (int) Math.Round( Y ) ); + } + + /// + /// Get string representation of the class. + /// + /// + /// Returns string, which contains values of the point in readable form. + /// + public override string ToString( ) + { + return string.Format( System.Globalization.CultureInfo.InvariantCulture, "{0}, {1}", X, Y ); + } + + /// + /// Calculate Euclidean norm of the vector comprised of the point's + /// coordinates - distance from (0, 0) in other words. + /// + /// + /// Returns point's distance from (0, 0) point. + /// + public float EuclideanNorm( ) + { + return (float) System.Math.Sqrt( X * X + Y * Y ); + } + } +} diff --git a/Sources/Accord.Core/AForge/PolishExpression.cs b/Sources/Accord.Core/AForge/PolishExpression.cs new file mode 100644 index 0000000000..a17545444 --- /dev/null +++ b/Sources/Accord.Core/AForge/PolishExpression.cs @@ -0,0 +1,144 @@ +// AForge Core Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2007-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge +{ + using System; + using System.Collections.Generic; + + // Quick and dirty implementation of polish expression evaluator + + /// + /// Evaluator of expressions written in reverse polish notation. + /// + /// + /// The class evaluates expressions writen in reverse postfix polish notation. + /// + /// The list of supported functuins is: + /// + /// Arithmetic functions: +, -, *, /; + /// sin - sine; + /// cos - cosine; + /// ln - natural logarithm; + /// exp - exponent; + /// sqrt - square root. + /// + /// + /// Arguments for these functions could be as usual constants, written as numbers, as variables, + /// writen as $<var_number> ($2, for example). The variable number is zero based index + /// of variables array. + /// + /// Sample usage: + /// + /// // expression written in polish notation + /// string expression = "2 $0 / 3 $1 * +"; + /// // variables for the expression + /// double[] vars = new double[] { 3, 4 }; + /// // expression evaluation + /// double result = PolishExpression.Evaluate( expression, vars ); + /// + /// + /// + public static class PolishExpression + { + /// + /// Evaluates specified expression. + /// + /// + /// Expression written in postfix polish notation. + /// Variables for the expression. + /// + /// Evaluated value of the expression. + /// + /// Unsupported function is used in the expression. + /// Incorrect postfix polish expression. + /// + public static double Evaluate( string expression, double[] variables ) + { + // split expression to separate tokens, which represent functions ans variables + string[] tokens = expression.Trim( ).Split( ' ' ); + // arguments stack + Stack arguments = new Stack(); + + // walk through all tokens + foreach ( string token in tokens ) + { + // check for token type + if ( char.IsDigit( token[0] ) ) + { + // the token in numeric argument + arguments.Push( double.Parse( token ) ); + } + else if ( token[0] == '$' ) + { + // the token is variable + arguments.Push( variables[int.Parse( token.Substring( 1 ) )] ); + } + else + { + // each function has at least one argument, so let's get the top one + // argument from stack + double v = (double) arguments.Pop( ); + + // check for function + switch ( token ) + { + case "+": // addition + arguments.Push( (double) arguments.Pop( ) + v ); + break; + + case "-": // subtraction + arguments.Push( (double) arguments.Pop( ) - v ); + break; + + case "*": // multiplication + arguments.Push( (double) arguments.Pop( ) * v ); + break; + + case "/": // division + arguments.Push( (double) arguments.Pop( ) / v ); + break; + + case "sin": // sine + arguments.Push( Math.Sin( v ) ); + break; + + case "cos": // cosine + arguments.Push( Math.Cos( v ) ); + break; + + case "ln": // natural logarithm + arguments.Push( Math.Log( v ) ); + break; + + case "exp": // exponent + arguments.Push( Math.Exp( v ) ); + break; + + case "sqrt": // square root + arguments.Push( Math.Sqrt( v ) ); + break; + + default: + // throw exception informing about undefined function + throw new ArgumentException( "Unsupported function: " + token ); + } + } + } + + // check stack size + if ( arguments.Count != 1 ) + { + throw new ArgumentException( "Incorrect expression." ); + } + + // return the only value from stack + return (double) arguments.Pop( ); + } + } +} diff --git a/Sources/Accord.Core/AForge/Range.cs b/Sources/Accord.Core/AForge/Range.cs new file mode 100644 index 0000000000..3a5716e54 --- /dev/null +++ b/Sources/Accord.Core/AForge/Range.cs @@ -0,0 +1,239 @@ +// AForge Core Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge +{ + using System; + + /// + /// Represents a range with minimum and maximum values, which are single precision numbers (floats). + /// + /// + /// + /// The class represents a single precision range with inclusive limits - + /// both minimum and maximum values of the range are included into it. + /// Mathematical notation of such range is [min, max]. + /// + /// Sample usage: + /// + /// // create [0.25, 1.5] range + /// Range range1 = new Range( 0.25f, 1.5f ); + /// // create [1.00, 2.25] range + /// Range range2 = new Range( 1.00f, 2.25f ); + /// // check if values is inside of the first range + /// if ( range1.IsInside( 0.75f ) ) + /// { + /// // ... + /// } + /// // check if the second range is inside of the first range + /// if ( range1.IsInside( range2 ) ) + /// { + /// // ... + /// } + /// // check if two ranges overlap + /// if ( range1.IsOverlapping( range2 ) ) + /// { + /// // ... + /// } + /// + /// + /// + [Serializable] + public struct Range + { + private float min, max; + + /// + /// Minimum value of the range. + /// + /// + /// The property represents minimum value (left side limit) or the range - + /// [min, max]. + /// + public float Min + { + get { return min; } + set { min = value; } + } + + /// + /// Maximum value of the range. + /// + /// + /// The property represents maximum value (right side limit) or the range - + /// [min, max]. + /// + public float Max + { + get { return max; } + set { max = value; } + } + + /// + /// Length of the range (deffirence between maximum and minimum values). + /// + public float Length + { + get { return max - min; } + } + + + /// + /// Initializes a new instance of the structure. + /// + /// + /// Minimum value of the range. + /// Maximum value of the range. + /// + public Range( float min, float max ) + { + this.min = min; + this.max = max; + } + + /// + /// Check if the specified value is inside of the range. + /// + /// + /// Value to check. + /// + /// True if the specified value is inside of the range or + /// false otherwise. + /// + public bool IsInside( float x ) + { + return ( ( x >= min ) && ( x <= max ) ); + } + + /// + /// Check if the specified range is inside of the range. + /// + /// + /// Range to check. + /// + /// True if the specified range is inside of the range or + /// false otherwise. + /// + public bool IsInside( Range range ) + { + return ( ( IsInside( range.min ) ) && ( IsInside( range.max ) ) ); + } + + /// + /// Check if the specified range overlaps with the range. + /// + /// + /// Range to check for overlapping. + /// + /// True if the specified range overlaps with the range or + /// false otherwise. + /// + public bool IsOverlapping( Range range ) + { + return ( ( IsInside( range.min ) ) || ( IsInside( range.max ) ) || + ( range.IsInside( min ) ) || ( range.IsInside( max ) ) ); + } + + /// + /// Convert the signle precision range to integer range. + /// + /// + /// Specifies if inner integer range must be returned or outer range. + /// + /// Returns integer version of the range. + /// + /// If is set to , then the + /// returned integer range will always fit inside of the current single precision range. + /// If it is set to , then current single precision range will always + /// fit into the returned integer range. + /// + public IntRange ToIntRange( bool provideInnerRange ) + { + int iMin, iMax; + + if ( provideInnerRange ) + { + iMin = (int) Math.Ceiling( min ); + iMax = (int) Math.Floor( max ); + } + else + { + iMin = (int) Math.Floor( min ); + iMax = (int) Math.Ceiling( max ); + } + + return new IntRange( iMin, iMax ); + } + + /// + /// Equality operator - checks if two ranges have equal min/max values. + /// + /// + /// First range to check. + /// Second range to check. + /// + /// Returns if min/max values of specified + /// ranges are equal. + /// + public static bool operator ==( Range range1, Range range2 ) + { + return ( ( range1.min == range2.min ) && ( range1.max == range2.max ) ); + } + + /// + /// Inequality operator - checks if two ranges have different min/max values. + /// + /// + /// First range to check. + /// Second range to check. + /// + /// Returns if min/max values of specified + /// ranges are not equal. + /// + public static bool operator !=( Range range1, Range range2 ) + { + return ( ( range1.min != range2.min ) || ( range1.max != range2.max ) ); + + } + + /// + /// Check if this instance of equal to the specified one. + /// + /// + /// Another range to check equalty to. + /// + /// Return if objects are equal. + /// + public override bool Equals( object obj ) + { + return ( obj is Range ) ? ( this == (Range) obj ) : false; + } + + /// + /// Get hash code for this instance. + /// + /// + /// Returns the hash code for this instance. + /// + public override int GetHashCode( ) + { + return min.GetHashCode( ) + max.GetHashCode( ); + } + + /// + /// Get string representation of the class. + /// + /// + /// Returns string, which contains min/max values of the range in readable form. + /// + public override string ToString( ) + { + return string.Format( System.Globalization.CultureInfo.InvariantCulture, "{0}, {1}", min, max ); + } + } +} diff --git a/Sources/Accord.Core/AForge/SystemTools.cs b/Sources/Accord.Core/AForge/SystemTools.cs new file mode 100644 index 0000000000..660ef687e --- /dev/null +++ b/Sources/Accord.Core/AForge/SystemTools.cs @@ -0,0 +1,111 @@ +// AForge Core Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge +{ + using System; + using System.Runtime.InteropServices; + + /// + /// Set of systems tools. + /// + /// + /// The class is a container of different system tools, which are used + /// across the framework. Some of these tools are platform specific, so their + /// implementation is different on different platform, like .NET and Mono. + /// + /// + public static class SystemTools + { + /// + /// Copy block of unmanaged memory. + /// + /// + /// Destination pointer. + /// Source pointer. + /// Memory block's length to copy. + /// + /// Return's value of - pointer to destination. + /// + /// This function is required because of the fact that .NET does + /// not provide any way to copy unmanaged blocks, but provides only methods to + /// copy from unmanaged memory to managed memory and vise versa. + /// + public static IntPtr CopyUnmanagedMemory(IntPtr dst, IntPtr src, int count) + { + unsafe + { + CopyUnmanagedMemory((byte*)dst.ToPointer(), (byte*)src.ToPointer(), count); + } + return dst; + } + + /// + /// Copy block of unmanaged memory. + /// + /// + /// Destination pointer. + /// Source pointer. + /// Memory block's length to copy. + /// + /// Return's value of - pointer to destination. + /// + /// This function is required because of the fact that .NET does + /// not provide any way to copy unmanaged blocks, but provides only methods to + /// copy from unmanaged memory to managed memory and vise versa. + /// + public static unsafe byte* CopyUnmanagedMemory(byte* dst, byte* src, int count) + { + return memcpy(dst, src, count); + } + + /// + /// Fill memory region with specified value. + /// + /// + /// Destination pointer. + /// Filler byte's value. + /// Memory block's length to fill. + /// + /// Return's value of - pointer to destination. + /// + public static IntPtr SetUnmanagedMemory(IntPtr dst, int filler, int count) + { + unsafe + { + SetUnmanagedMemory((byte*)dst.ToPointer(), filler, count); + } + return dst; + } + + /// + /// Fill memory region with specified value. + /// + /// + /// Destination pointer. + /// Filler byte's value. + /// Memory block's length to fill. + /// + /// Return's value of - pointer to destination. + /// + public static unsafe byte* SetUnmanagedMemory(byte* dst, int filler, int count) + { + return memset(dst, filler, count); + } + + + // Win32 memory copy function + [DllImport("ntdll.dll", CallingConvention = CallingConvention.Cdecl)] + private static unsafe extern byte* memcpy(byte* dst, byte* src, int count); + + // Win32 memory set function + [DllImport("ntdll.dll", CallingConvention = CallingConvention.Cdecl)] + private static unsafe extern byte* memset(byte* dst, int filler, int count); + + } +} diff --git a/Sources/Accord.Core/AForge/ThreadSafeRandom.cs b/Sources/Accord.Core/AForge/ThreadSafeRandom.cs new file mode 100644 index 0000000000..00577c3b2 --- /dev/null +++ b/Sources/Accord.Core/AForge/ThreadSafeRandom.cs @@ -0,0 +1,128 @@ +// AForge Core Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2011 +// contacts@aforgenet.com +// + +namespace AForge +{ + using System; + + /// + /// Thread safe version of the class. + /// + /// + /// The class inherits the and overrides + /// its random numbers generation methods providing thread safety by guarding call + /// to the base class with a lock. See documentation to for + /// additional information about the base class. + /// + public sealed class ThreadSafeRandom : Random + { + private object sync = new object( ); + + /// + /// Initializes a new instance of the class. + /// + /// + /// See for more information. + /// + public ThreadSafeRandom( ) + : base( ) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// A number used to calculate a starting value for the pseudo-random number sequence. + /// If a negative number is specified, the absolute value of the number is used. + /// + /// + /// See for more information. + /// + public ThreadSafeRandom( int seed ) + : base( seed ) + { + } + + /// + /// Returns a nonnegative random number. + /// + /// + /// Returns a 32-bit signed integer greater than or equal to zero and less than + /// . + /// + /// See for more information. + /// + public override int Next( ) + { + lock ( sync ) return base.Next( ); + } + + /// + /// Returns a nonnegative random number less than the specified maximum. + /// + /// + /// The exclusive upper bound of the random number to be generated. + /// must be greater than or equal to zero. + /// + /// Returns a 32-bit signed integer greater than or equal to zero, and less than ; + /// that is, the range of return values ordinarily includes zero but not . + /// + /// See for more information. + /// + public override int Next( int maxValue ) + { + lock ( sync ) return base.Next( maxValue ); + } + + /// + /// Returns a random number within a specified range. + /// + /// + /// The inclusive lower bound of the random number returned. + /// The exclusive upper bound of the random number returned. + /// must be greater than or equal to . + /// + /// Returns a 32-bit signed integer greater than or equal to and less + /// than ; that is, the range of return values includes + /// but not . + /// + /// See for more information. + /// + public override int Next( int minValue, int maxValue ) + { + lock ( sync ) return base.Next( minValue, maxValue ); + } + + /// + /// Fills the elements of a specified array of bytes with random numbers. + /// + /// + /// An array of bytes to contain random numbers. + /// + /// See for more information. + /// + public override void NextBytes( byte[] buffer ) + { + lock ( sync ) base.NextBytes( buffer ); + } + + /// + /// Returns a random number between 0.0 and 1.0. + /// + /// + /// Returns a double-precision floating point number greater than or equal to 0.0, and less than 1.0. + /// + /// See for more information. + /// + public override double NextDouble( ) + { + lock ( sync ) return base.NextDouble( ); + } + } +} diff --git a/Sources/Accord.Core/Accord.Core.csproj b/Sources/Accord.Core/Accord.Core.csproj index 077e478ed..628ec0ab1 100644 --- a/Sources/Accord.Core/Accord.Core.csproj +++ b/Sources/Accord.Core/Accord.Core.csproj @@ -36,28 +36,28 @@ False True DEBUG;TRACE - ..\..\Debug\ + $(SolutionDir)..\Debug\ - ..\..\Release\net35 + $(SolutionDir)..\Release\net35 TRACE;CODE_ANALYSIS;NET35 v3.5 - ..\..\Release\net35\Accord.XML - ..\..\Release\net35\Accord.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net35\Accord.XML + $(SolutionDir)..\Release\net35\Accord.dll.CodeAnalysisLog.xml - ..\..\Release\net40 + $(SolutionDir)..\Release\net40 TRACE;CODE_ANALYSIS;NET40 v4.0 - ..\..\Release\net40\Accord.XML - ..\..\Release\net40\Accord.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net40\Accord.XML + $(SolutionDir)..\Release\net40\Accord.dll.CodeAnalysisLog.xml - ..\..\Release\net45 + $(SolutionDir)..\Release\net45 TRACE;CODE_ANALYSIS;NET45 v4.5 - ..\..\Release\net45\Accord.XML - ..\..\Release\net45\Accord.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net45\Accord.XML + $(SolutionDir)..\Release\net45\Accord.dll.CodeAnalysisLog.xml @@ -67,6 +67,19 @@ + + + + + + + + + + + + + @@ -74,6 +87,8 @@ + + @@ -105,6 +120,9 @@ + + PreserveNewest + diff --git a/Sources/Accord.Core/Accord.dll.config b/Sources/Accord.Core/Accord.dll.config new file mode 100644 index 0000000000..3ec0d20b5 --- /dev/null +++ b/Sources/Accord.Core/Accord.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Sources/Accord.Core/Compatibility/AggregateException.cs b/Sources/Accord.Core/Compatibility/AggregateException.cs index 9405e4125..c2c967182 100644 --- a/Sources/Accord.Core/Compatibility/AggregateException.cs +++ b/Sources/Accord.Core/Compatibility/AggregateException.cs @@ -1,84 +1,109 @@ -// Accord Core Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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 -// - -#if NET35 -namespace Accord +// Accord Core Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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 +// + +#if NET35 +namespace Accord { using System; - using System.Runtime.Serialization; - - /// - /// Minimum AggregateException implementation for .NET 3.5 to - /// make Accord.NET work. This is not a complete implementation. - /// - /// - [Serializable] - public class AggregateException : Exception - { - - /// - /// Initializes a new instance of the class. - /// - /// - public AggregateException() { } - - /// - /// Initializes a new instance of the class. - /// - /// - /// Message providing some additional information. - /// - public AggregateException(string message) : - base(message) { } - - /// - /// Initializes a new instance of the class. - /// - /// - /// Message providing some additional information. - /// The exception that is the cause of the current exception. - /// - public AggregateException(string message, Exception innerException) : - base(message, innerException) { } - - - /// - /// Initializes a new instance of the class. - /// - /// - /// The - /// that holds the serialized object data about the exception being thrown. - /// The - /// that contains contextual information about the source or destination. - /// - /// The parameter is null. - /// - /// - /// The class name is null or is zero (0). - /// - /// - protected AggregateException(SerializationInfo info, StreamingContext context) : - base(info, context) { } - - } -} + using System.Collections.Generic; + using System.Runtime.Serialization; + + /// + /// Minimum AggregateException implementation for .NET 3.5 to + /// make Accord.NET work. This is not a complete implementation. + /// + /// + [Serializable] + public class AggregateException : Exception + { + + List exceptions; + + /// + /// Initializes a new instance of the class. + /// + /// + public AggregateException() + { + exceptions = new List(); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Message providing some additional information. + /// + public AggregateException(string message) : + base(message) + { + exceptions = new List(); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Message providing some additional information. + /// The exception that is the cause of the current exception. + /// + public AggregateException(string message, Exception innerException) : + base(message, innerException) + { + exceptions = new List() { innerException }; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Message providing some additional information. + /// The exceptions that are the cause of the current exception. + /// + public AggregateException(string message, IEnumerable innerExceptions) : + base(message, innerExceptions.GetEnumerator().Current) + { + exceptions = new List(innerExceptions); + } + + + /// + /// Initializes a new instance of the class. + /// + /// + /// The + /// that holds the serialized object data about the exception being thrown. + /// The + /// that contains contextual information about the source or destination. + /// + /// The parameter is null. + /// + /// + /// The class name is null or is zero (0). + /// + /// + protected AggregateException(SerializationInfo info, StreamingContext context) : + base(info, context) { } + + } +} #endif \ No newline at end of file diff --git a/Sources/Accord.Core/Compatibility/Complex.cs b/Sources/Accord.Core/Compatibility/Complex.cs new file mode 100644 index 0000000000..c47610ade --- /dev/null +++ b/Sources/Accord.Core/Compatibility/Complex.cs @@ -0,0 +1,1086 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// +// Copyright © Israel Lot, 2008 +// israel.lot@gmail.com +// + +#if NET35 +namespace System.Numerics +{ + using System; + using System.Text.RegularExpressions; + using System.Runtime.Serialization; + + /// + /// Complex number wrapper class. + /// + /// + /// The class encapsulates complex number and provides + /// set of different operators to manipulate it, like adding, subtraction, + /// multiplication, etc. + /// + /// Sample usage: + /// + /// // define two complex numbers + /// Complex c1 = new Complex( 3, 9 ); + /// Complex c2 = new Complex( 8, 3 ); + /// // sum + /// Complex s1 = Complex.Add( c1, c2 ); + /// Complex s2 = c1 + c2; + /// Complex s3 = c1 + 5; + /// // difference + /// Complex d1 = Complex.Subtract( c1, c2 ); + /// Complex d2 = c1 - c2; + /// Complex d3 = c1 - 2; + /// + /// + /// + public struct Complex : ICloneable, ISerializable + { + /// + /// Real part of the complex number. + /// + public double Real; + + /// + /// Imaginary part of the complex number. + /// + public double Imaginary; + + /// + /// A double-precision complex number that represents zero. + /// + public static readonly Complex Zero = new Complex(0, 0); + + /// + /// A double-precision complex number that represents one. + /// + public static readonly Complex One = new Complex(1, 0); + + /// + /// A double-precision complex number that represents the squere root of (-1). + /// + public static readonly Complex I = new Complex(0, 1); + + /// + /// Magnitude value of the complex number. + /// + /// + /// Magnitude of the complex number, which equals to Sqrt( Re * Re + Im * Im ). + /// + public double Magnitude + { + get { return System.Math.Sqrt(Real * Real + Imaginary * Imaginary); } + } + + /// + /// Phase value of the complex number. + /// + /// + /// Phase of the complex number, which equals to Atan( Im / Re ). + /// + public double Phase + { + get { return System.Math.Atan2(Imaginary, Real); } + } + + /// + /// Squared magnitude value of the complex number. + /// + public double SquaredMagnitude + { + get { return (Real * Real + Imaginary * Imaginary); } + } + + + /// + /// Initializes a new instance of the class. + /// + /// + /// Real part. + /// Imaginary part. + /// + public Complex(double re, double im) + { + this.Real = re; + this.Imaginary = im; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Source complex number. + /// + public Complex(Complex c) + { + this.Real = c.Real; + this.Imaginary = c.Imaginary; + } + + /// + /// Adds two complex numbers. + /// + /// + /// A instance. + /// A instance. + /// + /// Returns new instance containing the sum of specified + /// complex numbers. + /// + public static Complex Add(Complex a, Complex b) + { + return new Complex(a.Real + b.Real, a.Imaginary + b.Imaginary); + } + + /// + /// Adds scalar value to a complex number. + /// + /// + /// A instance. + /// A scalar value. + /// + /// Returns new instance containing the sum of specified + /// complex number and scalar value. + /// + public static Complex Add(Complex a, double s) + { + return new Complex(a.Real + s, a.Imaginary); + } + + /// + /// Adds two complex numbers and puts the result into the third complex number. + /// + /// + /// A instance. + /// A instance. + /// A instance to hold the result. + /// + public static void Add(Complex a, Complex b, ref Complex result) + { + result.Real = a.Real + b.Real; + result.Imaginary = a.Imaginary + b.Imaginary; + } + + /// + /// Adds scalar value to a complex number and puts the result into another complex number. + /// + /// + /// A instance. + /// A scalar value. + /// A instance to hold the result. + /// + public static void Add(Complex a, double s, ref Complex result) + { + result.Real = a.Real + s; + result.Imaginary = a.Imaginary; + } + + /// + /// Subtracts one complex number from another. + /// + /// + /// A instance to subtract from. + /// A instance to be subtracted. + /// + /// Returns new instance containing the subtraction result (a - b). + /// + public static Complex Subtract(Complex a, Complex b) + { + return new Complex(a.Real - b.Real, a.Imaginary - b.Imaginary); + } + + /// + /// Subtracts a scalar from a complex number. + /// + /// + /// A instance to subtract from. + /// A scalar value to be subtracted. + /// + /// Returns new instance containing the subtraction result (a - s). + /// + public static Complex Subtract(Complex a, double s) + { + return new Complex(a.Real - s, a.Imaginary); + } + + /// + /// Subtracts a complex number from a scalar value. + /// + /// + /// A scalar value to subtract from. + /// A instance to be subtracted. + /// + /// Returns new instance containing the subtraction result (s - a). + /// + public static Complex Subtract(double s, Complex a) + { + return new Complex(s - a.Real, a.Imaginary); + } + + /// + /// Subtracts one complex number from another and puts the result in the third complex number. + /// + /// + /// A instance to subtract from. + /// A instance to be subtracted. + /// A instance to hold the result. + /// + public static void Subtract(Complex a, Complex b, ref Complex result) + { + result.Real = a.Real - b.Real; + result.Imaginary = a.Imaginary - b.Imaginary; + } + + /// + /// Subtracts a scalar value from a complex number and puts the result into another complex number. + /// + /// + /// A instance to subtract from. + /// A scalar value to be subtracted. + /// A instance to hold the result. + /// + public static void Subtract(Complex a, double s, ref Complex result) + { + result.Real = a.Real - s; + result.Imaginary = a.Imaginary; + } + + /// + /// Subtracts a complex number from a scalar value and puts the result into another complex number. + /// + /// + /// A scalar value to subtract from. + /// A instance to be subtracted. + /// A instance to hold the result. + /// + public static void Subtract(double s, Complex a, ref Complex result) + { + result.Real = s - a.Real; + result.Imaginary = a.Imaginary; + } + + /// + /// Multiplies two complex numbers. + /// + /// + /// A instance. + /// A instance. + /// + /// Returns new instance containing the result of multiplication. + /// + public static Complex Multiply(Complex a, Complex b) + { + // (x + yi)(u + vi) = (xu – yv) + (xv + yu)i. + double aRe = a.Real, aIm = a.Imaginary; + double bRe = b.Real, bIm = b.Imaginary; + + return new Complex(aRe * bRe - aIm * bIm, aRe * bIm + aIm * bRe); + } + + /// + /// Multiplies a complex number by a scalar value. + /// + /// + /// A instance. + /// A scalar value. + /// + /// Returns new instance containing the result of multiplication. + /// + public static Complex Multiply(Complex a, double s) + { + return new Complex(a.Real * s, a.Imaginary * s); + } + + /// + /// Multiplies two complex numbers and puts the result in a third complex number. + /// + /// + /// A instance. + /// A instance. + /// A instance to hold the result. + /// + public static void Multiply(Complex a, Complex b, ref Complex result) + { + // (x + yi)(u + vi) = (xu – yv) + (xv + yu)i. + double aRe = a.Real, aIm = a.Imaginary; + double bRe = b.Real, bIm = b.Imaginary; + + result.Real = aRe * bRe - aIm * bIm; + result.Imaginary = aRe * bIm + aIm * bRe; + } + + /// + /// Multiplies a complex number by a scalar value and puts the result into another complex number. + /// + /// + /// A instance. + /// A scalar value. + /// A instance to hold the result. + /// + public static void Multiply(Complex a, double s, ref Complex result) + { + result.Real = a.Real * s; + result.Imaginary = a.Imaginary * s; + } + + /// + /// Divides one complex number by another complex number. + /// + /// + /// A instance. + /// A instance. + /// + /// Returns new instance containing the result. + /// + /// Can not divide by zero. + /// + public static Complex Divide(Complex a, Complex b) + { + double aRe = a.Real, aIm = a.Imaginary; + double bRe = b.Real, bIm = b.Imaginary; + double modulusSquared = bRe * bRe + bIm * bIm; + + if (modulusSquared == 0) + { + throw new DivideByZeroException("Can not divide by zero."); + } + + double invModulusSquared = 1 / modulusSquared; + + return new Complex( + (aRe * bRe + aIm * bIm) * invModulusSquared, + (aIm * bRe - aRe * bIm) * invModulusSquared); + } + + /// + /// Divides a complex number by a scalar value. + /// + /// + /// A instance. + /// A scalar value. + /// + /// Returns new instance containing the result. + /// + /// Can not divide by zero. + /// + public static Complex Divide(Complex a, double s) + { + if (s == 0) + { + throw new DivideByZeroException("Can not divide by zero."); + } + + return new Complex(a.Real / s, a.Imaginary / s); + } + + /// + /// Divides a scalar value by a complex number. + /// + /// + /// A scalar value. + /// A instance. + /// + /// Returns new instance containing the result. + /// + /// Can not divide by zero. + /// + public static Complex Divide(double s, Complex a) + { + if ((a.Real == 0) || (a.Imaginary == 0)) + { + throw new DivideByZeroException("Can not divide by zero."); + } + return new Complex(s / a.Real, s / a.Imaginary); + } + + /// + /// Divides one complex number by another complex number and puts the result in a third complex number. + /// + /// + /// A instance. + /// A instance. + /// A instance to hold the result. + /// + /// Can not divide by zero. + /// + public static void Divide(Complex a, Complex b, ref Complex result) + { + double aRe = a.Real, aIm = a.Imaginary; + double bRe = b.Real, bIm = b.Imaginary; + double modulusSquared = bRe * bRe + bIm * bIm; + + if (modulusSquared == 0) + { + throw new DivideByZeroException("Can not divide by zero."); + } + + double invModulusSquared = 1 / modulusSquared; + + result.Real = (aRe * bRe + aIm * bIm) * invModulusSquared; + result.Imaginary = (aIm * bRe - aRe * bIm) * invModulusSquared; + } + + /// + /// Divides a complex number by a scalar value and puts the result into another complex number. + /// + /// + /// A instance. + /// A scalar value. + /// A instance to hold the result. + /// + /// Can not divide by zero. + /// + public static void Divide(Complex a, double s, ref Complex result) + { + if (s == 0) + { + throw new DivideByZeroException("Can not divide by zero."); + } + + result.Real = a.Real / s; + result.Imaginary = a.Imaginary / s; + } + + /// + /// Divides a scalar value by a complex number and puts the result into another complex number. + /// + /// + /// A instance. + /// A scalar value. + /// A instance to hold the result. + /// + /// Can not divide by zero. + /// + public static void Divide(double s, Complex a, ref Complex result) + { + if ((a.Real == 0) || (a.Imaginary == 0)) + { + throw new DivideByZeroException("Can not divide by zero."); + } + + result.Real = s / a.Real; + result.Imaginary = s / a.Imaginary; + } + + /// + /// Negates a complex number. + /// + /// + /// A instance. + /// + /// Returns new instance containing the negated values. + /// + public static Complex Negate(Complex a) + { + return new Complex(-a.Real, -a.Imaginary); + } + + /// + /// Tests whether two complex numbers are approximately equal using default tolerance value. + /// + /// + /// A instance. + /// A instance. + /// + /// Return if the two vectors are approximately equal or otherwise. + /// + /// The default tolerance value, which is used for the test, equals to 8.8817841970012523233891E-16. + /// + public static bool ApproxEqual(Complex a, Complex b) + { + return ApproxEqual(a, b, 8.8817841970012523233891E-16); + } + + + /// + /// Tests whether two complex numbers are approximately equal given a tolerance value. + /// + /// + /// A instance. + /// A instance. + /// The tolerance value used to test approximate equality. + /// + /// The default tolerance value, which is used for the test, equals to 8.8817841970012523233891E-16. + /// + public static bool ApproxEqual(Complex a, Complex b, double tolerance) + { + return + ( + (System.Math.Abs(a.Real - b.Real) <= tolerance) && + (System.Math.Abs(a.Imaginary - b.Imaginary) <= tolerance) + ); + } + + #region Public Static Parse Methods + /// + /// Converts the specified string to its equivalent. + /// + /// + /// A string representation of a complex number. + /// + /// Returns new instance that represents the complex number + /// specified by the parameter. + /// + /// String representation of the complex number is not correctly formatted. + /// + public static Complex Parse(string s) + { + Regex r = new Regex(@"\((?.*),(?.*)\)", RegexOptions.None); + Match m = r.Match(s); + + if (m.Success) + { + return new Complex( + double.Parse(m.Result("${real}")), + double.Parse(m.Result("${imaginary}")) + ); + } + else + { + throw new FormatException("String representation of the complex number is not correctly formatted."); + } + } + + /// + /// Try to convert the specified string to its equivalent. + /// + /// + /// A string representation of a complex number. + /// + /// instance to output the result to. + /// + /// Returns boolean value that indicates if the parse was successful or not. + /// + public static bool TryParse(string s, out Complex result) + { + try + { + Complex newComplex = Complex.Parse(s); + result = newComplex; + return true; + + } + catch (FormatException) + { + + result = new Complex(); + return false; + } + } + + #endregion + + #region Public Static Complex Special Functions + + /// + /// Calculates square root of a complex number. + /// + /// + /// A instance. + /// + /// Returns new instance containing the square root of the specified + /// complex number. + /// + public static Complex Sqrt(Complex a) + { + Complex result = Complex.Zero; + + if ((a.Real == 0.0) && (a.Imaginary == 0.0)) + { + return result; + } + else if (a.Imaginary == 0.0) + { + result.Real = (a.Real > 0) ? System.Math.Sqrt(a.Real) : System.Math.Sqrt(-a.Real); + result.Imaginary = 0.0; + } + else + { + double modulus = a.Magnitude; + + result.Real = System.Math.Sqrt(0.5 * (modulus + a.Real)); + result.Imaginary = System.Math.Sqrt(0.5 * (modulus - a.Real)); + if (a.Imaginary < 0.0) + result.Imaginary = -result.Imaginary; + } + + return result; + } + + /// + /// Calculates natural (base e) logarithm of a complex number. + /// + /// + /// A instance. + /// + /// Returns new instance containing the natural logarithm of the specified + /// complex number. + /// + public static Complex Log(Complex a) + { + Complex result = Complex.Zero; + + if ((a.Real > 0.0) && (a.Imaginary == 0.0)) + { + result.Real = System.Math.Log(a.Real); + result.Imaginary = 0.0; + } + else if (a.Real == 0.0) + { + if (a.Imaginary > 0.0) + { + result.Real = System.Math.Log(a.Imaginary); + result.Imaginary = System.Math.PI / 2.0; + } + else + { + result.Real = System.Math.Log(-(a.Imaginary)); + result.Imaginary = -System.Math.PI / 2.0; + } + } + else + { + result.Real = System.Math.Log(a.Magnitude); + result.Imaginary = System.Math.Atan2(a.Imaginary, a.Real); + } + + return result; + } + + /// + /// Calculates exponent (e raised to the specified power) of a complex number. + /// + /// + /// A instance. + /// + /// Returns new instance containing the exponent of the specified + /// complex number. + /// + public static Complex Exp(Complex a) + { + Complex result = Complex.Zero; + double r = System.Math.Exp(a.Real); + result.Real = r * System.Math.Cos(a.Imaginary); + result.Imaginary = r * System.Math.Sin(a.Imaginary); + + return result; + } + #endregion + + #region Public Static Complex Trigonometry + + /// + /// Calculates Sine value of the complex number. + /// + /// + /// A instance. + /// + /// Returns new instance containing the Sine value of the specified + /// complex number. + /// + public static Complex Sin(Complex a) + { + Complex result = Complex.Zero; + + if (a.Imaginary == 0.0) + { + result.Real = System.Math.Sin(a.Real); + result.Imaginary = 0.0; + } + else + { + result.Real = System.Math.Sin(a.Real) * System.Math.Cosh(a.Imaginary); + result.Imaginary = System.Math.Cos(a.Real) * System.Math.Sinh(a.Imaginary); + } + + return result; + } + + /// + /// Calculates Cosine value of the complex number. + /// + /// + /// A instance. + /// + /// Returns new instance containing the Cosine value of the specified + /// complex number. + /// + public static Complex Cos(Complex a) + { + Complex result = Complex.Zero; + + if (a.Imaginary == 0.0) + { + result.Real = System.Math.Cos(a.Real); + result.Imaginary = 0.0; + } + else + { + result.Real = System.Math.Cos(a.Real) * System.Math.Cosh(a.Imaginary); + result.Imaginary = -System.Math.Sin(a.Real) * System.Math.Sinh(a.Imaginary); + } + + return result; + } + + /// + /// Calculates Tangent value of the complex number. + /// + /// + /// A instance. + /// + /// Returns new instance containing the Tangent value of the specified + /// complex number. + /// + public static Complex Tan(Complex a) + { + Complex result = Complex.Zero; + + if (a.Imaginary == 0.0) + { + result.Real = System.Math.Tan(a.Real); + result.Imaginary = 0.0; + } + else + { + double real2 = 2 * a.Real; + double imag2 = 2 * a.Imaginary; + double denom = System.Math.Cos(real2) + System.Math.Cosh(real2); + + result.Real = System.Math.Sin(real2) / denom; + result.Imaginary = System.Math.Sinh(imag2) / denom; + } + + return result; + } + #endregion + + #region Overrides + /// + /// Returns the hashcode for this instance. + /// + /// + /// A 32-bit signed integer hash code. + public override int GetHashCode() + { + return Real.GetHashCode() ^ Imaginary.GetHashCode(); + } + + /// + /// Returns a value indicating whether this instance is equal to the specified object. + /// + /// + /// An object to compare to this instance. + /// + /// Returns if is a and has the same values as this instance or otherwise. + /// + public override bool Equals(object obj) + { + return (obj is Complex) ? (this == (Complex)obj) : false; + } + + /// + /// Returns a string representation of this object. + /// + /// + /// A string representation of this object. + /// + public override string ToString() + { + return string.Format("({0}, {1})", Real, Imaginary); + } + #endregion + + #region Comparison Operators + /// + /// Tests whether two specified complex numbers are equal. + /// + /// + /// The left-hand complex number. + /// The right-hand complex number. + /// + /// Returns if the two complex numbers are equal or otherwise. + /// + public static bool operator ==(Complex u, Complex v) + { + return ((u.Real == v.Real) && (u.Imaginary == v.Imaginary)); + } + + /// + /// Tests whether two specified complex numbers are not equal. + /// + /// + /// The left-hand complex number. + /// The right-hand complex number. + /// + /// Returns if the two complex numbers are not equal or otherwise. + /// + public static bool operator !=(Complex u, Complex v) + { + return !(u == v); + } + #endregion + + #region Unary Operators + /// + /// Negates the complex number. + /// + /// + /// A instance. + /// + /// Returns new instance containing the negated values. + /// + public static Complex operator -(Complex a) + { + return Complex.Negate(a); + } + #endregion + + #region Binary Operators + /// + /// Adds two complex numbers. + /// + /// + /// A instance. + /// A instance. + /// + /// Returns new instance containing the sum. + /// + public static Complex operator +(Complex a, Complex b) + { + return Complex.Add(a, b); + } + + /// + /// Adds a complex number and a scalar value. + /// + /// + /// A instance. + /// A scalar value. + /// + /// Returns new instance containing the sum. + /// + public static Complex operator +(Complex a, double s) + { + return Complex.Add(a, s); + } + + /// + /// Adds a complex number and a scalar value. + /// + /// + /// A instance. + /// A scalar value. + /// + /// Returns new instance containing the sum. + /// + public static Complex operator +(double s, Complex a) + { + return Complex.Add(a, s); + } + + /// + /// Subtracts one complex number from another complex number. + /// + /// + /// A instance. + /// A instance. + /// + /// Returns new instance containing the difference. + /// + public static Complex operator -(Complex a, Complex b) + { + return Complex.Subtract(a, b); + } + + /// + /// Subtracts a scalar value from a complex number. + /// + /// + /// A instance. + /// A scalar value. + /// + /// Returns new instance containing the difference. + /// + public static Complex operator -(Complex a, double s) + { + return Complex.Subtract(a, s); + } + + /// + /// Subtracts a complex number from a scalar value. + /// + /// + /// A scalar value. + /// A instance. + /// + /// Returns new instance containing the difference. + /// + public static Complex operator -(double s, Complex a) + { + return Complex.Subtract(s, a); + } + + /// + /// Multiplies two complex numbers. + /// + /// + /// A instance. + /// A instance. + /// + /// Returns new instance containing the result of multiplication. + /// + public static Complex operator *(Complex a, Complex b) + { + return Complex.Multiply(a, b); + } + + /// + /// Multiplies a complex number by a scalar value. + /// + /// + /// A scalar value. + /// A instance. + /// + /// Returns new instance containing the result of multiplication. + /// + public static Complex operator *(double s, Complex a) + { + return Complex.Multiply(a, s); + } + + /// + /// Multiplies a complex number by a scalar value. + /// + /// + /// A instance. + /// A scalar value. + /// + /// Returns new instance containing the result of multiplication. + /// + public static Complex operator *(Complex a, double s) + { + return Complex.Multiply(a, s); + } + + /// + /// Divides one complex number by another complex number. + /// + /// + /// A instance. + /// A instance. + /// + /// A new Complex instance containing the result. + /// Returns new instance containing the result of division. + /// + public static Complex operator /(Complex a, Complex b) + { + return Complex.Divide(a, b); + } + + /// + /// Divides a complex number by a scalar value. + /// + /// + /// A instance. + /// A scalar value. + /// + /// Returns new instance containing the result of division. + /// + public static Complex operator /(Complex a, double s) + { + return Complex.Divide(a, s); + } + + /// + /// Divides a scalar value by a complex number. + /// + /// + /// A instance. + /// A scalar value. + /// + /// Returns new instance containing the result of division. + /// + public static Complex operator /(double s, Complex a) + { + return Complex.Divide(s, a); + } + #endregion + + #region Conversion Operators + /// + /// Converts from a single-precision real number to a complex number. + /// + /// + /// Single-precision real number to convert to complex number. + /// + /// Returns new instance containing complex number with + /// real part initialized to the specified value. + /// + public static explicit operator Complex(float value) + { + return new Complex((double)value, 0); + } + + /// + /// Converts from a double-precision real number to a complex number. + /// + /// + /// Double-precision real number to convert to complex number. + /// + /// Returns new instance containing complex number with + /// real part initialized to the specified value. + /// + public static explicit operator Complex(double value) + { + return new Complex(value, 0); + } + #endregion + + #region ICloneable Members + /// + /// Creates an exact copy of this object. + /// + /// + /// Returns clone of the complex number. + /// + object ICloneable.Clone() + { + return new Complex(this); + } + + /// + /// Creates an exact copy of this object. + /// + /// + /// Returns clone of the complex number. + /// + public Complex Clone() + { + return new Complex(this); + } + #endregion + + #region ISerializable Members + /// + /// Populates a with the data needed to serialize the target object. + /// + /// + /// The to populate with data. + /// The destination (see ) for this serialization. + /// + public void GetObjectData(SerializationInfo info, StreamingContext context) + { + info.AddValue("Real", this.Real); + info.AddValue("Imaginary", this.Imaginary); + } + #endregion + } +} +#endif \ No newline at end of file diff --git a/Sources/Accord.Core/Compatibility/ConcurrentBag.cs b/Sources/Accord.Core/Compatibility/ConcurrentBag.cs new file mode 100644 index 0000000000..845f7395b --- /dev/null +++ b/Sources/Accord.Core/Compatibility/ConcurrentBag.cs @@ -0,0 +1,85 @@ +// Accord Core Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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 +// + +#if NET35 +namespace Accord +{ + using System; + using System.Collections.Generic; + + /// + /// Minimum Lazy implementation for .NET 3.5 to make + /// Accord.NET work. This is not a complete implementation. + /// + /// + public class ConcurrentBag : IEnumerable + { + private LinkedList list; + + /// + /// Initializes a new instance of the class. + /// + /// + public ConcurrentBag() + { + list = new LinkedList(); + } + + /// + /// Adds the specified item. + /// + /// + public void Add(T item) + { + lock (list) + list.AddLast(item); + } + + /// + /// Counts this instance. + /// + /// + public int Count + { + get { return list.Count; } + } + + /// + /// Gets the enumerator. + /// + /// + public IEnumerator GetEnumerator() + { + return list.GetEnumerator(); + } + + /// + /// Gets the enumerator. + /// + /// + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return list.GetEnumerator(); + } + } +} +#endif diff --git a/Sources/Accord.Core/ExtensionMethods.cs b/Sources/Accord.Core/ExtensionMethods.cs index b2adc732a..1a6bcbfec 100644 --- a/Sources/Accord.Core/ExtensionMethods.cs +++ b/Sources/Accord.Core/ExtensionMethods.cs @@ -23,6 +23,7 @@ namespace Accord { using System; + using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Globalization; @@ -38,6 +39,24 @@ namespace Accord public static class ExtensionMethods { + /// + /// Copies a collection by calling the ICloneable.Clone method for each element inside it. + /// + /// + /// + /// The collection to be cloned. + /// + /// A copy of the collection where each element has also been copied. + /// + public static T DeepClone(this T list) + where T : IList, ICloneable + { + T clone = (T)list.Clone(); + for (int i = 0; i < clone.Count; i++) + clone[i] = (ICloneable)list[i].Clone(); + return clone; + } + /// /// Creates and adds multiple /// objects with the given names at once. @@ -109,23 +128,6 @@ public static bool Read(this BinaryReader stream, out T structure) where T : return true; } - /// - /// Converts an object into another type, irrespective of whether - /// the conversion can be done at compile time or not. This can be - /// used to convert generic types to numeric types during runtime. - /// - /// - /// The destination type. - /// - /// The value to be converted. - /// - /// The result of the conversion. - /// - public static T To(this object value) - { - return (T)System.Convert.ChangeType(value, typeof(T)); - } - /// /// Gets the underlying buffer position for a StreamReader. /// diff --git a/Sources/Accord.Core/Properties/VersionInfo.cs b/Sources/Accord.Core/Properties/VersionInfo.cs index d49158ffc..43fd198d9 100644 --- a/Sources/Accord.Core/Properties/VersionInfo.cs +++ b/Sources/Accord.Core/Properties/VersionInfo.cs @@ -7,11 +7,11 @@ using System.Reflection; [assembly: AssemblyProduct("Accord.NET Framework")] -[assembly: AssemblyCopyright("Copyright © César Souza, 2009-2015")] +[assembly: AssemblyCopyright("Copyright © Accord.NET authors, 2009-2015")] [assembly: AssemblyCompany("Accord.NET")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -[assembly: AssemblyVersion("2.15.0")] -[assembly: AssemblyInformationalVersion("2.15.0")] -[assembly: AssemblyFileVersion("2.15.0.5233")] +[assembly: AssemblyVersion("3.0.2")] +[assembly: AssemblyInformationalVersion("3.0.2")] +[assembly: AssemblyFileVersion("3.0.2.5339")] diff --git a/Sources/Accord.Core/Properties/VersionInfo.tt b/Sources/Accord.Core/Properties/VersionInfo.tt index f968f9efc..6638b4bae 100644 --- a/Sources/Accord.Core/Properties/VersionInfo.tt +++ b/Sources/Accord.Core/Properties/VersionInfo.tt @@ -7,7 +7,7 @@ using System.Reflection; [assembly: AssemblyProduct("Accord.NET Framework")] -[assembly: AssemblyCopyright("Copyright © César Souza, 2009-2015")] +[assembly: AssemblyCopyright("Copyright © Accord.NET authors, 2009-2015")] [assembly: AssemblyCompany("Accord.NET")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -16,7 +16,7 @@ using System.Reflection; [assembly: AssemblyInformationalVersion("<#= this.version #>")] [assembly: AssemblyFileVersion("<#= this.version #>.<#= this.build #>")] <#+ - string version = "2.15.0"; + string version = "3.0.2"; int build = (int)(DateTime.UtcNow - new DateTime(2001, 1, 1)).TotalDays; int revision = (int)(DateTime.UtcNow.TimeOfDay.TotalSeconds / 2); #> \ No newline at end of file diff --git a/Sources/Accord.Docs/Accord.Documentation/Accord.Documentation.shfbproj b/Sources/Accord.Docs/Accord.Documentation/Accord.Documentation.shfbproj index c36ad6aac..49a98c83c 100644 --- a/Sources/Accord.Docs/Accord.Documentation/Accord.Documentation.shfbproj +++ b/Sources/Accord.Docs/Accord.Documentation/Accord.Documentation.shfbproj @@ -18,44 +18,60 @@ ..\..\..\Docs\ Accord.NET - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Accord.NET Framework &#169%3b 2009-2015. All documentation is licensed under the Creative Commons Attribution/Share-Alike License. feedback%40accord-framework.net @@ -73,7 +89,7 @@ Contains audio devices to reproduce and capture sounds exposed through DirectSound. - Contains Interest point detectors (i.e. Harris, SURF and FAST), image matching and image stitching methods. + Contains the image processing filters such as the Wavelet transform, stereo rectification, image blending and point markers. @@ -151,6 +167,7 @@ + Contains collections such as Lists, Dictionaries, Trees and other useful structures. &lt%3bpara&gt%3b Accord.NET provides statistical analysis, machine learning, image processing and computer vision methods for .NET applications. The Accord.NET Framework extends the popular AForge.NET with new features, adding to a more complete environment for scientific computing in .NET. &lt%3b/para&gt%3b @@ -267,7 +284,7 @@ VS2013 C#, Visual Basic MemberName - 2.15.0.0 + 3.0.0.0 .NET Framework 4.5 Attributes, ExplicitInterfaceImplementations, InheritedMembers, InheritedFrameworkMembers, Protected, SealedProtected ms.vsipcc+, ms.vsexpresscc+ @@ -293,7 +310,7 @@ 2 - True + False OnlyWarningsAndErrors False False @@ -743,72 +760,40 @@ grid-step-size grid-step-size + + Accord.Fuzzy + Accord.Fuzzy + + + Accord.Genetic + Accord.Genetic + + + Accord.Video.DirectShow + Accord.Video.Direct Show + + + Accord.Video.Kinect + Accord.Video.Kinect + + + Accord.Video + Accord.Video + + + Accord.Video.VFW + Accord.Video.VFW + + + Accord.Video.Ximea + Accord.Video.Ximea + True Accord.NET - - ..\..\..\Externals\AForge.NET\AForge.dll - True - - - ..\..\..\Externals\AForge.NET\AForge.Controls.dll - True - - - ..\..\..\Externals\AForge.NET\AForge.Fuzzy.dll - True - - - ..\..\..\Externals\AForge.NET\AForge.Genetic.dll - True - - - ..\..\..\Externals\AForge.NET\AForge.Imaging.dll - True - - - ..\..\..\Externals\AForge.NET\AForge.Imaging.Formats.dll - True - - - ..\..\..\Externals\AForge.NET\AForge.MachineLearning.dll - True - - - ..\..\..\Externals\AForge.NET\AForge.Math.dll - True - - - ..\..\..\Externals\AForge.NET\AForge.Neuro.dll - True - - - ..\..\..\Externals\AForge.NET\AForge.Video.dll - True - - - ..\..\..\Externals\AForge.NET\AForge.Video.DirectShow.dll - True - - - ..\..\..\Externals\AForge.NET\AForge.Video.FFMPEG.dll - True - - - ..\..\..\Externals\AForge.NET\AForge.Video.Kinect.dll - True - - - ..\..\..\Externals\AForge.NET\AForge.Video.VFW.dll - True - - - ..\..\..\Externals\AForge.NET\AForge.Vision.dll - True - ..\..\..\Externals\SharpDX\net40\SharpDX.dll diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Audio.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Audio.png index 1f20bfb52..5619615b9 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Audio.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Audio.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Audition.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Audition.png index 1bf27a20c..fa2e94b05 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Audition.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Audition.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Controls.Vision.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Controls.Vision.png index f610d01d4..ed21ea038 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Controls.Vision.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Controls.Vision.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Controls.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Controls.png index 688a28869..ddbce3e57 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Controls.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Controls.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Core.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Core.png index 5de206657..44f310160 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Core.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Core.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.DirectSound.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.DirectSound.png index ce841ead9..360e1d313 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.DirectSound.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.DirectSound.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Fuzzy.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Fuzzy.png new file mode 100644 index 0000000000..874dfe6b7 Binary files /dev/null and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Fuzzy.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Genetic.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Genetic.png new file mode 100644 index 0000000000..e6e38940a Binary files /dev/null and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Genetic.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.IO.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.IO.png index b74cbd46d..62229f946 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.IO.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.IO.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Imaging.Converters.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Imaging.Converters.png index 3d20e7e6d..3398a9dc3 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Imaging.Converters.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Imaging.Converters.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Imaging.Filters.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Imaging.Filters.png index 9e6d7e4b4..d42bdc316 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Imaging.Filters.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Imaging.Filters.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Imaging.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Imaging.png index e6e9dcc0a..decd275b2 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Imaging.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Imaging.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.Boosting.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.Boosting.png index 4f78ed8f9..7302b912d 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.Boosting.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.Boosting.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.Clustering.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.Clustering.png index bfebed0da..88e8992f5 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.Clustering.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.Clustering.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.DecisionTrees.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.DecisionTrees.png index 630392326..1d47f4eb5 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.DecisionTrees.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.DecisionTrees.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.GPL.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.GPL.png index 7733b4b20..723b4c8c3 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.GPL.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.GPL.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.Structures.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.Structures.png index 678312a18..f3e153d5f 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.Structures.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.Structures.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.VectorMachines.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.VectorMachines.png index 1ea8838bc..9e1729da3 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.VectorMachines.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.VectorMachines.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.png index 736973dcb..2bf644a2c 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.MachineLearning.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Math.Comparers.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Math.Comparers.png index 49d445e9d..3f08f426d 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Math.Comparers.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Math.Comparers.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Math.Decompositions.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Math.Decompositions.png index 8a5ce88cc..8247b9427 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Math.Decompositions.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Math.Decompositions.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Math.Integration.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Math.Integration.png index f71866282..1bb62631d 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Math.Integration.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Math.Integration.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Math.Optimization.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Math.Optimization.png index dd0c1a766..6229df73d 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Math.Optimization.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Math.Optimization.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Math.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Math.png index e0251c8a3..9f85753a2 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Math.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Math.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Neuro.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Neuro.png index fcd168011..6ac7ac17b 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Neuro.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Neuro.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Analysis.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Analysis.png index c67d437bc..2788d0dfc 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Analysis.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Analysis.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Distributions.Multivariate.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Distributions.Multivariate.png index c461ddf01..9bf63015d 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Distributions.Multivariate.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Distributions.Multivariate.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Distributions.Univariate.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Distributions.Univariate.png index ed7b00008..f9b64cc81 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Distributions.Univariate.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Distributions.Univariate.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Distributions.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Distributions.png index 786e1e5d6..b0747a6f0 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Distributions.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Distributions.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Kernels.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Kernels.png index 793a93bb5..faf70efd8 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Kernels.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Kernels.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Models.Fields.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Models.Fields.png index 94893f50b..3e8f17687 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Models.Fields.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Models.Fields.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Models.Markov.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Models.Markov.png index 181fb68c2..1c34f3b22 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Models.Markov.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Models.Markov.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Models.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Models.png index 22fe6c663..bc07f6574 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Models.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Models.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Testing.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Testing.png index d11cce40f..78fc63ead 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Testing.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.Testing.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.png index 842dbce60..b9e228887 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Statistics.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Video.DirectShow.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Video.DirectShow.png new file mode 100644 index 0000000000..0251a93dc Binary files /dev/null and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Video.DirectShow.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Video.Kinect.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Video.Kinect.png new file mode 100644 index 0000000000..5439ffcb4 Binary files /dev/null and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Video.Kinect.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Video.VFW.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Video.VFW.png new file mode 100644 index 0000000000..ff70a6b2e Binary files /dev/null and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Video.VFW.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Video.Ximea.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Video.Ximea.png new file mode 100644 index 0000000000..b47dece5e Binary files /dev/null and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Video.Ximea.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Video.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Video.png new file mode 100644 index 0000000000..3587c8ff4 Binary files /dev/null and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Video.png differ diff --git a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Vision.png b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Vision.png index fd784dc29..adfc4d3a5 100644 Binary files a/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Vision.png and b/Sources/Accord.Docs/Accord.Documentation/Diagrams/Classes/Accord.Vision.png differ diff --git a/Sources/Accord.Docs/Namespaces/Accord.Fuzzy.cs b/Sources/Accord.Docs/Namespaces/Accord.Fuzzy.cs new file mode 100644 index 0000000000..0ddc0d116 --- /dev/null +++ b/Sources/Accord.Docs/Namespaces/Accord.Fuzzy.cs @@ -0,0 +1,48 @@ +// Accord Statistics Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Fuzzy +{ + using AForge.Fuzzy; + using System.Runtime.CompilerServices; + + /// + /// Fuzzy logic, fuzzy sets and inference systems. + /// + /// + /// + /// + /// The AForge.Fuzzy namespace contains set of interfaces and classes to operate + /// with fuzzy sets, such as Fuzzy Fuzzy Databases, + /// Linguistic Variables and . + /// + /// + /// + /// The namespace class diagram is shown below. + /// + /// + /// + [CompilerGenerated] + class NamespaceDoc + { + } +} diff --git a/Sources/Accord.Docs/Namespaces/Accord.Genetic.cs b/Sources/Accord.Docs/Namespaces/Accord.Genetic.cs new file mode 100644 index 0000000000..0f071c3f6 --- /dev/null +++ b/Sources/Accord.Docs/Namespaces/Accord.Genetic.cs @@ -0,0 +1,120 @@ +// Accord Statistics Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// cesarsouza at gmail.com +// +// Copyright © Andrew Kirillov, 2006-2015 +// http://www.aforgenet.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.Genetic +{ + using System.Runtime.CompilerServices; + + /// + /// Genetic algorithms, genetic programming and evolutionary learning namespace. + /// + /// + /// + /// + /// The Accord.Genetics namespace framework provides classes and functions related to + /// genetic algorithms. Those classes have been originated from the AForge.NET Framework + /// and can be used to solve many different problems with the help of evolutionary computations + /// based on Genetic Algorithms (GA), Genetic Programming (GP) and Gene Expression Programming (GEP). + /// The following documentation has been based on the original AForge.NET description of the + /// AForge.Genetics namespace: + /// + /// + /// The library consists of 3 main sets of classes: + /// + /// + /// Collection of different chromosomes' classes implementing IChromosome interface suiting different common problems. These classes implement such operators like crossover and mutation, which are used for driving search through solutions' space by creating new chromosomes representing new solutions. + /// + /// Collection of fitness functions' classes implementing IFitnessFunction interface, which are used to evaluate chromosomes by calculating their fitness values for different tasks; + /// + /// Collection of selection algorithms' classes implementing ISelectionMethod interface, which are used to perform selection of population members (chromosomes). + /// + /// + /// + /// + /// The main class of the library is Population class, which organizes the work of genetic algorithm + /// (GA/GP/GEP) creating initial population of random members, creating new members with the help of + /// crossover and mutations operators, calculating fitness values of new members and performing selection + /// of members to keep basing on members' usefulness (fitness). Creating population object it is required + /// to specify which chromosomes, fitness function and selection algorithm to use. Once this is done, the + /// population object is ready to be used for searching of problem's solution: + /// + /// + /// // create genetic population + /// var population = new Population(40, baseChromosome, fitnessFunction, selectionAlgorithm); + /// + /// while (true) + /// { + /// // run one epoch of the population + /// population.RunEpoch(); + /// + /// // check current best fitness + /// if (population.FitnessMax > limit) + /// { + /// // ... + /// } + /// } + /// + /// + /// + /// As an example, below is small a sample code, which demonstrates usage of Population class for solving + /// quite simple problem - searching function's maximum value. + /// + /// + /// // define optimization function + /// public class UserFunction : OptimizationFunction1D + /// { + /// public UserFunction() : + /// base(new DoubleRange(0, 255)) { } + /// + /// public override double OptimizationFunction(double x) + /// { + /// return Math.Cos(x / 23) * Math.Sin(x / 50) + 2; + /// } + /// } + /// ... + /// // create genetic population + /// var population = new Population(40, new BinaryChromosome(32), new UserFunction(), new EliteSelection()); + /// + /// // run one epoch of the population + /// population.RunEpoch( ); + /// + /// + /// + /// The Population class also supports migration of members from one population to another, + /// which allows to exchange by good solutions between populations. Also this feature allows + /// to run several populations simultaneously in different threads (distributing computations + /// on multiple cores/CPUs if they are available) and exchange by good solutions from time to + /// time bringing "fresh blood" to populations. + /// + /// + /// The namespace class diagram is shown below. + /// + /// + /// + [CompilerGenerated] + class NamespaceDoc + { + } +} diff --git a/Sources/Accord.Docs/Namespaces/Accord.Imaging.cs b/Sources/Accord.Docs/Namespaces/Accord.Imaging.cs new file mode 100644 index 0000000000..93660e253 --- /dev/null +++ b/Sources/Accord.Docs/Namespaces/Accord.Imaging.cs @@ -0,0 +1,62 @@ +// Accord Statistics Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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 +{ + using System.Runtime.CompilerServices; + using Accord.Imaging.Converters; + using Accord.Imaging.Filters; + using Accord.Imaging.Moments; + + /// + /// Contains Interest point detectors (i.e. Harris, SURF and FAST), image matching and image stitching methods. + /// + /// + /// + /// + /// This namespace contains several image processing methods, from corner detectors such as + /// Harris and FAST, + /// as well as feature detectors like SURF, + /// LBP, and texture feature extractors such as + /// , to essential image classification tools such as , + /// and computer vision tools like + /// and . + /// + /// + /// It also includes several image filters like Gabor filters, + /// Wolf-Jolion and Niblack + /// thresholding, and Gray World. + /// + /// + /// The namespace class diagram is shown below. + /// + /// + /// + /// + /// + /// + /// + [CompilerGenerated] + class NamespaceDoc + { + } +} diff --git a/Sources/Accord.Docs/Namespaces/Accord.Namespaces.csproj b/Sources/Accord.Docs/Namespaces/Accord.Namespaces.csproj index 1358118be..d74ede351 100644 --- a/Sources/Accord.Docs/Namespaces/Accord.Namespaces.csproj +++ b/Sources/Accord.Docs/Namespaces/Accord.Namespaces.csproj @@ -35,10 +35,6 @@ - - False - ..\..\..\Externals\AForge.NET\AForge.Neuro.dll - @@ -51,12 +47,20 @@ + + + + + + + + @@ -64,10 +68,6 @@ - - {ec70c2a7-2b49-40d3-ae82-4c2f6e1724af} - Accord.Audio.Formats - {e7b65f08-82f1-438f-847a-2aac2bec9ac0} Accord.Audio @@ -96,9 +96,17 @@ {a177a90c-8207-466a-af70-f2b8452a42ac} Accord.Core - + {456db2e8-745a-4f87-a2bd-c43cf8677770} - Accord.DirectSound + Accord.Audio.DirectSound + + + {b631038f-e12c-4d0d-8b25-ff7f62fe62d1} + Accord.Fuzzy + + + {2efaa327-1789-4438-b9f5-e83acae12db2} + Accord.Genetic {63184EBD-6B28-4066-AAEE-5B99431E31F4} @@ -124,17 +132,37 @@ {fd8101dd-c95d-42d6-ad44-ae01c25f2811} Accord.Statistics + + {26cd2ce7-ff63-4669-83b0-7d9c8f3408ee} + Accord.Video.DirectShow + + + {9da8e727-4038-4e6b-90bd-853730fdfa49} + Accord.Video.Kinect + + + {22e852c0-17ff-4106-9df6-41eabb8c0613} + Accord.Video.VFW + + + {aedd6cfb-747b-4077-9288-9cd2a86090f1} + Accord.Video.Ximea + + + {809725dc-6502-4732-a51c-deb7fea12975} + Accord.Video + {c70a159d-74a4-405f-9a7f-c17acf451cca} Accord.Vision - \ No newline at end of file diff --git a/Sources/Accord.Docs/Namespaces/Accord.Video.DirectShow.cs b/Sources/Accord.Docs/Namespaces/Accord.Video.DirectShow.cs new file mode 100644 index 0000000000..c149eb53c --- /dev/null +++ b/Sources/Accord.Docs/Namespaces/Accord.Video.DirectShow.cs @@ -0,0 +1,52 @@ +// Accord Core Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Video.DirectShow +{ + using System.Runtime.CompilerServices; + using Accord.Vision.Detection; + using Accord.Vision.Detection.Cascades; + using Accord.Vision.Tracking; + + /// + /// Access video files (.avi, .wmv) and capturing devices (webcam) using DirectShow. + /// + /// + /// + /// + /// The Accord.Video.DirectShow namespace contains classes to access video sources + /// using DirectShow interface (USB web cameras, capture devices, video files). Those classes + /// have been originated from the AForge.NET Framework. + /// + /// + /// The namespace class diagram is shown below. + /// + /// + /// + /// + /// + /// + [CompilerGenerated] + class NamespaceDoc + { + } +} diff --git a/Sources/Accord.Docs/Namespaces/Accord.Video.Kinect.cs b/Sources/Accord.Docs/Namespaces/Accord.Video.Kinect.cs new file mode 100644 index 0000000000..032c4f839 --- /dev/null +++ b/Sources/Accord.Docs/Namespaces/Accord.Video.Kinect.cs @@ -0,0 +1,53 @@ +// Accord Core Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Video.Kinect +{ + using System.Runtime.CompilerServices; + using Accord.Vision.Detection; + using Accord.Vision.Detection.Cascades; + using Accord.Vision.Tracking; + + /// + /// Access and control RGB and Depth cameras from Microsoft Kinect devices. + /// + /// + /// + /// + /// The Accord.Video.Kinect namespace contains classes to control and capture + /// images from the RGB and Depth cameras in a Microsoft Kinect device. It is also + /// possible to control the device's inner rotation motors and LED lights. Those classes + /// have been originated from the AForge.NET Framework. + /// + /// + /// The namespace class diagram is shown below. + /// + /// + /// + /// + /// + /// + [CompilerGenerated] + class NamespaceDoc + { + } +} diff --git a/Sources/Accord.Docs/Namespaces/Accord.Video.VFW.cs b/Sources/Accord.Docs/Namespaces/Accord.Video.VFW.cs new file mode 100644 index 0000000000..794d174f2 --- /dev/null +++ b/Sources/Accord.Docs/Namespaces/Accord.Video.VFW.cs @@ -0,0 +1,52 @@ +// Accord Core Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Video.VFW +{ + using System.Runtime.CompilerServices; + using Accord.Vision.Detection; + using Accord.Vision.Detection.Cascades; + using Accord.Vision.Tracking; + + /// + /// Access video files (.avi, .wmv) using Video For Windows (VFW). + /// + /// + /// + /// + /// The Accord.Video.VFW namespace contains classes to read and write video + /// files through the VFW interface. Those classes have been originated from the + /// AForge.NET Framework. + /// + /// + /// The namespace class diagram is shown below. + /// + /// + /// + /// + /// + /// + [CompilerGenerated] + class NamespaceDoc + { + } +} diff --git a/Sources/Accord.Docs/Namespaces/Accord.Video.Ximea.cs b/Sources/Accord.Docs/Namespaces/Accord.Video.Ximea.cs new file mode 100644 index 0000000000..fce0e8b93 --- /dev/null +++ b/Sources/Accord.Docs/Namespaces/Accord.Video.Ximea.cs @@ -0,0 +1,52 @@ +// Accord Core Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Video.Ximea +{ + using System.Runtime.CompilerServices; + using Accord.Vision.Detection; + using Accord.Vision.Detection.Cascades; + using Accord.Vision.Tracking; + + /// + /// Capture images from XIMEA cameras. + /// + /// + /// + /// + /// The Accord.Video.Ximea namespace contains classes capture images from + /// XIMEA cameras. Those classes have been + /// originated from the AForge.NET Framework. + /// + /// + /// The namespace class diagram is shown below. + /// + /// + /// + /// + /// + /// + [CompilerGenerated] + class NamespaceDoc + { + } +} diff --git a/Sources/Accord.Docs/Namespaces/Accord.Video.cs b/Sources/Accord.Docs/Namespaces/Accord.Video.cs new file mode 100644 index 0000000000..19f35c938 --- /dev/null +++ b/Sources/Accord.Docs/Namespaces/Accord.Video.cs @@ -0,0 +1,56 @@ +// Accord Core Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Video +{ + using System.Runtime.CompilerServices; + using Accord.Vision.Detection; + using Accord.Vision.Detection.Cascades; + using Accord.Vision.Tracking; + + /// + /// Access and process video using files, streams and image sequences. + /// + /// + /// + /// + /// The Accord.Video namespace contains interfaces and classes to access different + /// video sources, such as IP video cameras (MJPEG streams). Those classes have been + /// originated from the AForge.NET Framework and defines types used by other + /// video related libraries from the framework. + /// + /// + /// The namespace class diagram is shown below. + /// + /// + /// + /// + /// + /// + /// + /// + /// + [CompilerGenerated] + class NamespaceDoc + { + } +} diff --git a/Sources/Accord.Fuzzy/Accord.Fuzzy.cd b/Sources/Accord.Fuzzy/Accord.Fuzzy.cd new file mode 100644 index 0000000000..ffe252bd6 --- /dev/null +++ b/Sources/Accord.Fuzzy/Accord.Fuzzy.cd @@ -0,0 +1,224 @@ + + + + + + + + AAAAAAAAEAAAABAEAAAAAgAAAAAAAAAAAAQAAAAEAAA= + Clause.cs + + + + + + + + + + + AAAAAAAAAAAAAAAEAAAgAAAAAAAAAAAAAAAAAAAEQAA= + Database.cs + + + + + + + + + + FuzzyOutput.cs + + + + + AEAAAAAAAAABAIAAAAAAAAAAAAAAAAAABAAAAAUAAAA= + FuzzyOutput.cs + + + + + + + + + + + AAAAAAAAAAAACgAAAgAAAAQEAAAEAAAAAAAAAAAAAAA= + FuzzySet.cs + + + + + + + + ABAAAABAAAAAAABAAAAAQgAAAAAAAAAAIAACQAAQAQA= + InferenceSystem.cs + + + + + + + + AAIIAAACCCAAABAgEAAAAAQQgAAEAAAAAABAAAAAAAA= + LinguisticVariable.cs + + + + + + + + AAAAQAAAAIAAAABEEJAIAAQACAAEAAAAAAACAABAAAQ= + Rule.cs + + + + + + + + ABAIAAIAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAgAA= + Rulebase.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAA= + Operators\MaximumCoNorm.cs + + + + + + + AAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAA= + Operators\MinimumNorm.cs + + + + + + + AAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAA= + Operators\NotOperator.cs + + + + + + + AAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAA= + Operators\ProductNorm.cs + + + + + + + AAAAAAACAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAA= + Defuzzification\CentroidDefuzzifier.cs + + + + + + + + + AAAAAACAAAAACgAAAAAAAAAEAAAAAAAAAAAAAAAAAAA= + Membership Functions\PiecewiseLinearFunction.cs + + + + + + + AAAAAAAAAAAACgAAAAAAAAAEAAAAAAAAAAAIAAAAAAA= + Membership Functions\SingletonFunction.cs + + + + + + + + + Membership Functions\TrapezoidalFunction.cs + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + Membership Functions\TrapezoidalFunction.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAA= + Operators\ICoNorm.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAA= + Operators\INorm.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAA= + Operators\IUnaryOperator.cs + + + + + + AAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + Defuzzification\IDefuzzifier.cs + + + + + + AAAAAAAAAAAACgAAAAAAAAAEAAAAAAAAAAAAAAAAAAA= + Membership Functions\IMembershipFunction.cs + + + + \ No newline at end of file diff --git a/Sources/Accord.Fuzzy/Accord.Fuzzy.csproj b/Sources/Accord.Fuzzy/Accord.Fuzzy.csproj new file mode 100644 index 0000000000..d3f6c49cf --- /dev/null +++ b/Sources/Accord.Fuzzy/Accord.Fuzzy.csproj @@ -0,0 +1,130 @@ + + + + {B631038F-E12C-4D0D-8B25-FF7F62FE62D1} + Accord.Fuzzy + Accord.Fuzzy + Debug + AnyCPU + AnyCPU + Library + Properties + True + 4 + True + true + Accord.snk + 3.5 + False + true + ..\Accord.NET.ruleset + false + true + 4096 + true + pdbonly + true + + + v4.5 + Full + False + true + False + True + DEBUG;TRACE + $(SolutionDir)..\Debug\ + + + $(SolutionDir)..\Release\net35 + TRACE;CODE_ANALYSIS;NET35 + v3.5 + $(SolutionDir)..\Release\net35\Accord.Fuzzy.XML + $(SolutionDir)..\Release\net35\Accord.Fuzzy.dll.CodeAnalysisLog.xml + + + $(SolutionDir)..\Release\net40 + TRACE;CODE_ANALYSIS;NET40 + v4.0 + $(SolutionDir)..\Release\net40\Accord.Fuzzy.XML + $(SolutionDir)..\Release\net40\Accord.Fuzzy.dll.CodeAnalysisLog.xml + + + $(SolutionDir)..\Release\net45 + TRACE;CODE_ANALYSIS;NET45 + v4.5 + $(SolutionDir)..\Release\net45\Accord.Fuzzy.XML + $(SolutionDir)..\Release\net45\Accord.Fuzzy.dll.CodeAnalysisLog.xml + + + + + + + + + Properties\VersionInfo.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + {a177a90c-8207-466a-af70-f2b8452a42ac} + Accord.Core + + + + + + + + \ No newline at end of file diff --git a/Sources/Accord.DirectSound/Accord.snk b/Sources/Accord.Fuzzy/Accord.snk similarity index 100% rename from Sources/Accord.DirectSound/Accord.snk rename to Sources/Accord.Fuzzy/Accord.snk diff --git a/Sources/Accord.Fuzzy/Clause.cs b/Sources/Accord.Fuzzy/Clause.cs new file mode 100644 index 0000000000..32a6a5580 --- /dev/null +++ b/Sources/Accord.Fuzzy/Clause.cs @@ -0,0 +1,125 @@ +// AForge Fuzzy Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Fuzzy +{ + using System; + using System.Collections.Generic; + + /// + /// This class represents a fuzzy clause, a linguistic expression of the type "Variable IS Value". + /// + /// + /// A Fuzzy Clause is used to verify if a linguistic variable can be considered + /// as a specific value at a specific moment. Linguistic variables can only assume value of + /// their linguistic labels. Because of the nature of the Fuzzy Logic, a Variable can be + /// several of its labels at the same time, with different membership values. + /// + /// For example, a linguistic variable "temperature" can be "hot" with a membership 0.3 + /// and "warm" with a membership 0.7 at the same time. To obtain those memberships, Fuzzy Clauses + /// "temperature is hot" and "temperature is war" can be built. + /// + /// Typically Fuzzy Clauses are used to build Fuzzy Rules (). + /// + /// Sample usage: + /// + /// // create a linguistic variable to represent temperature + /// LinguisticVariable lvTemperature = new LinguisticVariable("Temperature", 0, 80 ); + /// + /// // create the linguistic labels (fuzzy sets) that compose the temperature + /// TrapezoidalFunction function1 = new TrapezoidalFunction(10, 15, TrapezoidalFunction.EdgeType.Right); + /// FuzzySet fsCold = new FuzzySet("Cold", function1); + /// TrapezoidalFunction function2 = new TrapezoidalFunction(10, 15, 20, 25); + /// FuzzySet fsCool = new FuzzySet("Cool", function2); + /// TrapezoidalFunction function3 = new TrapezoidalFunction(20, 25, 30, 35); + /// FuzzySet fsWarm = new FuzzySet("Warm", function3); + /// TrapezoidalFunction function4 = new TrapezoidalFunction(30, 35, TrapezoidalFunction.EdgeType.Left); + /// FuzzySet fsHot = new FuzzySet("Hot", function4); + /// + /// // adding labels to the variable + /// lvTemperature.AddLabel(fsCold); + /// lvTemperature.AddLabel(fsCool); + /// lvTemperature.AddLabel(fsWarm); + /// lvTemperature.AddLabel(fsHot); + /// + /// // creating the Clause + /// Clause fuzzyClause = new Clause(lvTemperature, fsHot); + /// // setting the numerical input of the variable to evaluate the Clause + /// lvTemperature.NumericInput = 35; + /// float result = fuzzyClause.Evaluate(); + /// Console.WriteLine(result.ToString()); + /// + /// + /// + public class Clause + { + // the linguistic var of the clause + private LinguisticVariable variable; + + // the label of the clause + private FuzzySet label; + + /// + /// Gets the of the . + /// + public LinguisticVariable Variable + { + get { return variable; } + } + + /// + /// Gets the of the . + /// + public FuzzySet Label + { + get { return label; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Linguistic variable of the clause. + /// + /// Label of the linguistic variable, a fuzzy set used as label into the linguistic variable. + /// + /// The label indicated was not found in the linguistic variable. + /// + public Clause( LinguisticVariable variable, FuzzySet label ) + { + // check if label belongs to var. + variable.GetLabel( label.Name ); + + // initializing attributes + this.label = label; + this.variable = variable; + } + + /// + /// Evaluates the fuzzy clause. + /// + /// + /// Degree of membership [0..1] of the clause. + /// + public float Evaluate( ) + { + return label.GetMembership( variable.NumericInput ); + } + + /// + /// Returns the fuzzy clause in its linguistic representation. + /// + /// + /// A string representing the fuzzy clause. + /// + public override string ToString( ) + { + return this.variable.Name + " IS " + this.label.Name; + } + } +} diff --git a/Sources/Accord.Fuzzy/Database.cs b/Sources/Accord.Fuzzy/Database.cs new file mode 100644 index 0000000000..c5b7d7608 --- /dev/null +++ b/Sources/Accord.Fuzzy/Database.cs @@ -0,0 +1,80 @@ +// AForge Fuzzy Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2008-2009 +// andrew.kirillov@aforgenet.com +// +// Copyright © Fabio L. Caversan, 2008-2009 +// fabio.caversan@gmail.com +// + +namespace AForge.Fuzzy +{ + using System; + using System.Collections.Generic; + + /// + /// The class represents a fuzzy database, a set of linguistic variables used in a Fuzzy + /// Inference System. + /// + /// + public class Database + { + // the linguistic variables repository + private Dictionary variables; + + /// + /// Initializes a new instance of the class. + /// + /// + public Database( ) + { + // instance of the variables list + this.variables = new Dictionary( 10 ); + } + + /// + /// Adds a linguistic variable to the database. + /// + /// + /// A linguistic variable to add. + /// + /// The linguistic variable was not initialized. + /// The linguistic variable name already exists in the database. + /// + public void AddVariable( LinguisticVariable variable ) + { + // checking for existing name + if ( this.variables.ContainsKey( variable.Name ) ) + throw new ArgumentException( "The linguistic variable name already exists in the database." ); + + // adding label + this.variables.Add( variable.Name, variable ); + } + + /// + /// Removes all the linguistic variables of the database. + /// + /// + public void ClearVariables( ) + { + this.variables.Clear( ); + } + + /// + /// Returns an existing linguistic variable from the database. + /// + /// + /// Name of the linguistic variable to retrieve. + /// + /// Reference to named . + /// + /// The variable indicated was not found in the database. + /// + public LinguisticVariable GetVariable( string variableName ) + { + return variables [variableName]; + } + } +} diff --git a/Sources/Accord.Fuzzy/Defuzzification/CentroidDefuzzifier.cs b/Sources/Accord.Fuzzy/Defuzzification/CentroidDefuzzifier.cs new file mode 100644 index 0000000000..790ec8ce9 --- /dev/null +++ b/Sources/Accord.Fuzzy/Defuzzification/CentroidDefuzzifier.cs @@ -0,0 +1,107 @@ +// AForge Fuzzy Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Fuzzy +{ + using System; + using System.Collections.Generic; + + /// + /// This class implements the centroid defuzzification method. + /// + /// + /// In many applications, a Fuzzy Inference System is used to perform linguistic + /// computation, but at the end of the inference process, a numerical value is needed. It does + /// not mean that the system needs precision, but simply that a numerical value is required, + /// most of the times because it will be used to control another system that needs the number. + /// To obtain this numer, a defuzzification method is performed. + /// + /// This class implements the centroid defuzzification method. The output of a Fuzzy + /// Inference System is a set of rules (see ) with firing strength greater + /// than zero. Those firing strength apply a constraint to the consequent fuzzy sets + /// (see ) of the rules. Putting all those fuzzy sets togheter results + /// in a a shape that is the linguistic output meaning. + /// + /// + /// The centroid method calculates the center of the area of this shape to obtain the + /// numerical representation of the output. It uses a numerical approximation, so a number + /// of intervals must be choosen. As the number of intervals grow, the precision of the + /// numerical ouput grows. + /// + /// + /// For a sample usage of the see + /// class. + /// + /// + public class CentroidDefuzzifier : IDefuzzifier + { + // number of intervals to use in numerical approximation + private int intervals; + + /// + /// Initializes a new instance of the class. + /// + /// + /// Number of segments that the speech universe will be splited + /// to perform the numerical approximation of the center of area. + /// + public CentroidDefuzzifier( int intervals ) + { + this.intervals = intervals; + } + + /// + /// Centroid method to obtain the numerical representation of a fuzzy output. The numerical + /// value will be the center of the shape formed by the several fuzzy labels with their + /// constraints. + /// + /// + /// A containing the output of several + /// rules of a Fuzzy Inference System. + /// A operator to be used when constraining + /// the label to the firing strength. + /// + /// The numerical representation of the fuzzy output. + /// + /// The numerical output is unavaliable. All memberships are zero. + /// + public float Defuzzify( FuzzyOutput fuzzyOutput, INorm normOperator ) + { + // results and accumulators + float weightSum = 0, membershipSum = 0; + + // speech universe + float start = fuzzyOutput.OutputVariable.Start; + float end = fuzzyOutput.OutputVariable.End; + + // increment + float increment = ( end - start ) / this.intervals; + + // running through the speech universe and evaluating the labels at each point + for ( float x = start; x < end; x += increment ) + { + // we must evaluate x membership to each one of the output labels + foreach ( FuzzyOutput.OutputConstraint oc in fuzzyOutput.OutputList ) + { + // getting the membership for X and constraining it with the firing strength + float membership = fuzzyOutput.OutputVariable.GetLabelMembership( oc.Label, x ); + float constrainedMembership = normOperator.Evaluate( membership, oc.FiringStrength ); + + weightSum += x * constrainedMembership; + membershipSum += constrainedMembership; + } + } + + // if no membership was found, then the membershipSum is zero and the numerical output is unknown. + if ( membershipSum == 0 ) + throw new Exception( "The numerical output in unavaliable. All memberships are zero." ); + + return weightSum / membershipSum; + } + } +} diff --git a/Sources/Accord.Fuzzy/Defuzzification/IDefuzzifier.cs b/Sources/Accord.Fuzzy/Defuzzification/IDefuzzifier.cs new file mode 100644 index 0000000000..f7705a9ab --- /dev/null +++ b/Sources/Accord.Fuzzy/Defuzzification/IDefuzzifier.cs @@ -0,0 +1,42 @@ +// AForge Fuzzy Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Fuzzy +{ + using System; + using System.Collections.Generic; + + /// + /// Interface which specifies set of methods required to be implemented by all defuzzification methods + /// that can be used in Fuzzy Inference Systems. + /// + /// + /// In many applications, a Fuzzy Inference System is used to perform linguistic computation, + /// but at the end of the inference process, a numerical value is needed. It does not mean that the system + /// needs precision, but simply that a numerical value is required, most of the times because it will be used to + /// control another system that needs the number. To obtain this numer, a defuzzification method is performed. + /// + /// Several deffuzification methods were proposed, and they can be created as classes that + /// implements this interface. + /// + public interface IDefuzzifier + { + /// + /// Defuzzification method to obtain the numerical representation of a fuzzy output. + /// + /// + /// A containing the output of + /// several rules of a Fuzzy Inference System. + /// A operator to be used when constraining + /// the label to the firing strength. + /// + /// The numerical representation of the fuzzy output. + /// + float Defuzzify( FuzzyOutput fuzzyOutput, INorm normOperator ); + } +} diff --git a/Sources/Accord.Fuzzy/FuzzyOutput.cs b/Sources/Accord.Fuzzy/FuzzyOutput.cs new file mode 100644 index 0000000000..e85aa8cf0 --- /dev/null +++ b/Sources/Accord.Fuzzy/FuzzyOutput.cs @@ -0,0 +1,208 @@ +// AForge Fuzzy Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Fuzzy +{ + using System; + using System.Collections.Generic; + + /// + /// The class represents the output of a Fuzzy Inference System. + /// + /// + /// The class keeps set of rule's output - pairs with the output fuzzy label + /// and the rule's firing strength. + /// + /// + /// + /// Sample usage: + /// + /// // linguistic labels (fuzzy sets) that compose the distances + /// FuzzySet fsNear = new FuzzySet( "Near", + /// new TrapezoidalFunction( 15, 50, TrapezoidalFunction.EdgeType.Right ) ); + /// FuzzySet fsMedium = new FuzzySet( "Medium", + /// new TrapezoidalFunction( 15, 50, 60, 100 ) ); + /// FuzzySet fsFar = new FuzzySet( "Far", + /// new TrapezoidalFunction( 60, 100, TrapezoidalFunction.EdgeType.Left ) ); + /// + /// // front distance (input) + /// LinguisticVariable lvFront = new LinguisticVariable( "FrontalDistance", 0, 120 ); + /// lvFront.AddLabel( fsNear ); + /// lvFront.AddLabel( fsMedium ); + /// lvFront.AddLabel( fsFar ); + /// + /// // linguistic labels (fuzzy sets) that compose the angle + /// FuzzySet fsZero = new FuzzySet( "Zero", + /// new TrapezoidalFunction( -10, 5, 5, 10 ) ); + /// FuzzySet fsLP = new FuzzySet( "LittlePositive", + /// new TrapezoidalFunction( 5, 10, 20, 25 ) ); + /// FuzzySet fsP = new FuzzySet( "Positive", + /// new TrapezoidalFunction( 20, 25, 35, 40 ) ); + /// FuzzySet fsVP = new FuzzySet( "VeryPositive", + /// new TrapezoidalFunction( 35, 40, TrapezoidalFunction.EdgeType.Left ) ); + /// + /// // angle + /// LinguisticVariable lvAngle = new LinguisticVariable( "Angle", -10, 50 ); + /// lvAngle.AddLabel( fsZero ); + /// lvAngle.AddLabel( fsLP ); + /// lvAngle.AddLabel( fsP ); + /// lvAngle.AddLabel( fsVP ); + /// + /// // the database + /// Database fuzzyDB = new Database( ); + /// fuzzyDB.AddVariable( lvFront ); + /// fuzzyDB.AddVariable( lvAngle ); + /// + /// // creating the inference system + /// InferenceSystem IS = new InferenceSystem( fuzzyDB, new CentroidDefuzzifier( 1000 ) ); + /// + /// // going straight + /// IS.NewRule( "Rule 1", "IF FrontalDistance IS Far THEN Angle IS Zero" ); + /// // turning left + /// IS.NewRule( "Rule 2", "IF FrontalDistance IS Near THEN Angle IS Positive" ); + /// + /// ... + /// // inference section + /// + /// // setting inputs + /// IS.SetInput( "FrontalDistance", 20 ); + /// + /// // getting outputs + /// try + /// { + /// FuzzyOutput fuzzyOutput = IS.ExecuteInference ( "Angle" ); + /// + /// // showing the fuzzy output + /// foreach ( FuzzyOutput.OutputConstraint oc in fuzzyOutput.OutputList ) + /// { + /// Console.WriteLine( oc.Label + " - " + oc.FiringStrength.ToString( ) ); + /// } + /// } + /// catch ( Exception ) + /// { + /// ... + /// } + /// + /// + /// + public class FuzzyOutput + { + /// + /// Inner class to store the pair fuzzy label / firing strength of + /// a fuzzy output. + /// + public class OutputConstraint + { + // The label of a fuzzy output + private string label; + // The firing strength of a fuzzy rule, to be applied to the label + private float firingStrength; + + /// + /// Initializes a new instance of the class. + /// + /// + /// A string representing the output label of a . + /// The firing strength of a , to be applied to its output label. + /// + internal OutputConstraint( string label, float firingStrength ) + { + this.label = label; + this.firingStrength = firingStrength; + } + + /// + /// The representing the output label of a . + /// + /// + public string Label + { + get { return label; } + } + + /// + /// The firing strength of a , to be applied to its output label. + /// + /// + public float FiringStrength + { + get { return firingStrength; } + } + + } + + // the linguistic variables repository + private List outputList; + + // the output linguistic variable + private LinguisticVariable outputVar; + + /// + /// A list with of a Fuzzy Inference System's output. + /// + /// + public List OutputList + { + get + { + return outputList; + } + } + + /// + /// Gets the acting as a Fuzzy Inference System Output. + /// + /// + public LinguisticVariable OutputVariable + { + get { return outputVar; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// A representing a Fuzzy Inference System's output. + /// + internal FuzzyOutput( LinguisticVariable outputVar ) + { + // instance of the constraints list + this.outputList = new List( 20 ); + + // output linguistic variable + this.outputVar = outputVar; + } + + /// + /// Adds an output to the Fuzzy Output. + /// + /// + /// The name of a label representing a fuzzy rule's output. + /// The firing strength [0..1] of a fuzzy rule. + /// + /// The label indicated was not found in the linguistic variable. + /// + internal void AddOutput( string labelName, float firingStrength ) + { + // check if the label exists in the linguistic variable + this.outputVar.GetLabel( labelName ); + + // adding label + this.outputList.Add( new OutputConstraint( labelName, firingStrength ) ); + } + + /// + /// Removes all the linguistic variables of the database. + /// + /// + internal void ClearOutput( ) + { + this.outputList.Clear( ); + } + } +} diff --git a/Sources/Accord.Fuzzy/FuzzySet.cs b/Sources/Accord.Fuzzy/FuzzySet.cs new file mode 100644 index 0000000000..08df2f09f --- /dev/null +++ b/Sources/Accord.Fuzzy/FuzzySet.cs @@ -0,0 +1,115 @@ +// AForge Fuzzy Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Fuzzy +{ + using System; + + /// + /// The class represents a fuzzy set. + /// + /// + /// The fuzzy sets are the base for all fuzzy applications. In a classical set, the membership of + /// a given value to the set can always be defined as true (1) or false (0). In fuzzy sets, this membership can be + /// a value in the range [0..1], representing the imprecision existent in many real world applications. + /// + /// Let us consider, for example, fuzzy sets representing some temperature. In a given application, there is the + /// need to represent a cool and warm temperature. Like in real life, the precise point when the temperature changes from + /// cool to warm is not easy to find, and does not makes sense. If we consider the cool around 20 degrees and warm around + /// 30 degrees, it is not simple to find a break point. If we take the mean, we can consider values greater than or equal + /// 25 to be warm. But we can still consider 25 a bit cool. And a bit warm at the same time. This is where fuzzy sets can + /// help. + /// + /// Fuzzy sets are often used to compose Linguistic Variables, used in Fuzzy Inference Systems. + /// + /// Sample usage: + /// + /// // creating 2 fuzzy sets to represent Cool and Warm + /// TrapezoidalFunction function1 = new TrapezoidalFunction( 13, 18, 23, 28 ); + /// FuzzySet fsCool = new FuzzySet( "Cool", function1 ); + /// TrapezoidalFunction function2 = new TrapezoidalFunction( 23, 28, 33, 38 ); + /// FuzzySet fsWarm = new FuzzySet( "Warm", function2 ); + /// + /// // show membership to the Cool set for some values + /// Console.WriteLine( "COOL" ); + /// for ( int i = 13; i <= 28; i++ ) + /// Console.WriteLine( fsCool.GetMembership( i ) ); + /// + /// // show membership to the Warm set for some values + /// Console.WriteLine( "WARM" ); + /// for ( int i = 23; i <= 38; i++ ) + /// Console.WriteLine( fsWarm.GetMembership( i ) ); + /// + /// + /// + public class FuzzySet + { + // name of the fuzzy set + private string name; + // membership functions that defines the shape of the fuzzy set + private IMembershipFunction function; + + /// + /// Name of the fuzzy set. + /// + public string Name + { + get { return name; } + } + + /// + /// The leftmost x value of the fuzzy set's membership function. + /// + /// + public float LeftLimit + { + get + { + return function.LeftLimit; + } + } + + /// + /// The rightmost x value of the fuzzy set's membership function. + /// + /// + public float RightLimit + { + get + { + return function.RightLimit; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Name of the fuzzy set. + /// Membership function that will define the shape of the fuzzy set. + /// + public FuzzySet( string name, IMembershipFunction function ) + { + this.name = name; + this.function = function; + } + + /// + /// Calculate membership of a given value to the fuzzy set. + /// + /// + /// Value which membership needs to be calculated. + /// + /// Degree of membership [0..1] of the value to the fuzzy set. + /// + public float GetMembership( float x ) + { + return function.GetMembership( x ); + } + } +} diff --git a/Sources/Accord.Fuzzy/InferenceSystem.cs b/Sources/Accord.Fuzzy/InferenceSystem.cs new file mode 100644 index 0000000000..bd27c4fe3 --- /dev/null +++ b/Sources/Accord.Fuzzy/InferenceSystem.cs @@ -0,0 +1,264 @@ +// AForge Fuzzy Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Fuzzy +{ + using System; + using System.Collections.Generic; + + /// + /// This class represents a Fuzzy Inference System. + /// + /// + /// A Fuzzy Inference System is a model capable of executing fuzzy computing. + /// It is mainly composed by a with the linguistic variables + /// (see ) and a + /// with the fuzzy rules (see ) that represent the behavior of the system. + /// The typical operation of a Fuzzy Inference System is: + /// + /// Get the numeric inputs; + /// Use the with the linguistic variables + /// (see ) to obtain linguistic meaning for each + /// numerical input; + /// Verify which rules (see ) of the are + /// activated by the input; + /// Combine the consequent of the activated rules to obtain a ; + /// Use some defuzzifier (see ) to obtain a numerical output. + /// + /// + /// + /// The following sample usage is a Fuzzy Inference System that controls an + /// auto guided vehicle avoing frontal collisions: + /// + /// // linguistic labels (fuzzy sets) that compose the distances + /// FuzzySet fsNear = new FuzzySet( "Near", + /// new TrapezoidalFunction( 15, 50, TrapezoidalFunction.EdgeType.Right ) ); + /// FuzzySet fsMedium = new FuzzySet( "Medium", + /// new TrapezoidalFunction( 15, 50, 60, 100 ) ); + /// FuzzySet fsFar = new FuzzySet( "Far", + /// new TrapezoidalFunction( 60, 100, TrapezoidalFunction.EdgeType.Left ) ); + /// + /// // front distance (input) + /// LinguisticVariable lvFront = new LinguisticVariable( "FrontalDistance", 0, 120 ); + /// lvFront.AddLabel( fsNear ); + /// lvFront.AddLabel( fsMedium ); + /// lvFront.AddLabel( fsFar ); + /// + /// // linguistic labels (fuzzy sets) that compose the angle + /// FuzzySet fsZero = new FuzzySet( "Zero", + /// new TrapezoidalFunction( -10, 5, 5, 10 ) ); + /// FuzzySet fsLP = new FuzzySet( "LittlePositive", + /// new TrapezoidalFunction( 5, 10, 20, 25 ) ); + /// FuzzySet fsP = new FuzzySet( "Positive", + /// new TrapezoidalFunction( 20, 25, 35, 40 ) ); + /// FuzzySet fsVP = new FuzzySet( "VeryPositive", + /// new TrapezoidalFunction( 35, 40, TrapezoidalFunction.EdgeType.Left ) ); + /// + /// // angle + /// LinguisticVariable lvAngle = new LinguisticVariable( "Angle", -10, 50 ); + /// lvAngle.AddLabel( fsZero ); + /// lvAngle.AddLabel( fsLP ); + /// lvAngle.AddLabel( fsP ); + /// lvAngle.AddLabel( fsVP ); + /// + /// // the database + /// Database fuzzyDB = new Database( ); + /// fuzzyDB.AddVariable( lvFront ); + /// fuzzyDB.AddVariable( lvAngle ); + /// + /// // creating the inference system + /// InferenceSystem IS = new InferenceSystem( fuzzyDB, new CentroidDefuzzifier( 1000 ) ); + /// + /// // going Straight + /// IS.NewRule( "Rule 1", "IF FrontalDistance IS Far THEN Angle IS Zero" ); + /// // Turning Left + /// IS.NewRule( "Rule 2", "IF FrontalDistance IS Near THEN Angle IS Positive" ); + /// + /// ... + /// // inference section + /// + /// // setting inputs + /// IS.SetInput( "FrontalDistance", 20 ); + /// + /// // getting outputs + /// try + /// { + /// float newAngle = IS.Evaluate( "Angle" ); + /// } + /// catch ( Exception ) + /// { + /// ... + /// } + /// + /// + /// + public class InferenceSystem + { + // The linguistic variables of this system + private Database database; + // The fuzzy rules of this system + private Rulebase rulebase; + // The defuzzifier method choosen + private IDefuzzifier defuzzifier; + // Norm operator used in rules and deffuzification + private INorm normOperator; + // CoNorm operator used in rules + private ICoNorm conormOperator; + + + /// + /// Initializes a new Fuzzy . + /// + /// + /// A fuzzy containing the system linguistic variables. + /// A defuzzyfier method used to evaluate the numeric uotput of the system. + /// + public InferenceSystem( Database database, IDefuzzifier defuzzifier ) + : this( database, defuzzifier, new MinimumNorm( ), new MaximumCoNorm( ) ) + { + } + + /// + /// Initializes a new Fuzzy . + /// + /// + /// A fuzzy containing the system linguistic + /// variables. + /// A defuzzyfier method used to evaluate the numeric otput + /// of the system. + /// A operator used to evaluate the norms + /// in the . For more information of the norm evaluation see . + /// A operator used to evaluate the + /// conorms in the . For more information of the conorm evaluation see . + /// + public InferenceSystem( Database database, IDefuzzifier defuzzifier, INorm normOperator, ICoNorm conormOperator ) + { + this.database = database; + this.defuzzifier = defuzzifier; + this.normOperator = normOperator; + this.conormOperator = conormOperator; + this.rulebase = new Rulebase( ); + } + + /// + /// Creates a new and add it to the of the + /// . + /// + /// + /// Name of the to create. + /// A string representing the fuzzy rule. + /// + /// The new reference. + /// + public Rule NewRule( string name, string rule ) + { + Rule r = new Rule( database, name, rule, normOperator, conormOperator ); + this.rulebase.AddRule( r ); + return r; + } + + /// + /// Sets a numerical input for one of the linguistic variables of the . + /// + /// + /// Name of the . + /// Numeric value to be used as input. + /// + /// The variable indicated in + /// was not found in the database. + /// + public void SetInput( string variableName, float value ) + { + this.database.GetVariable( variableName ).NumericInput = value; + } + + /// + /// Gets one of the of the . + /// + /// + /// Name of the to get. + /// + /// The variable indicated in + /// was not found in the database. + /// + public LinguisticVariable GetLinguisticVariable( string variableName ) + { + return this.database.GetVariable( variableName ); + } + + /// + /// Gets one of the Rules of the . + /// + /// + /// Name of the to get. + /// + /// The rule indicated in + /// was not found in the rulebase. + /// + public Rule GetRule( string ruleName ) + { + return this.rulebase.GetRule ( ruleName ); + } + + /// + /// Executes the fuzzy inference, obtaining a numerical output for a choosen output + /// linguistic variable. + /// + /// + /// Name of the to evaluate. + /// + /// The numerical output of the Fuzzy Inference System for the choosen variable. + /// + /// The variable indicated was not found in the database. + /// + public float Evaluate( string variableName ) + { + // call the defuzzification on fuzzy output + FuzzyOutput fuzzyOutput = ExecuteInference( variableName ); + float res = defuzzifier.Defuzzify( fuzzyOutput, normOperator ); + return res; + } + + /// + /// Executes the fuzzy inference, obtaining the of the system for the required + /// . + /// + /// + /// Name of the to evaluate. + /// + /// A containing the fuzzy output of the system for the + /// specified in . + /// + /// The variable indicated was not found in the database. + /// + public FuzzyOutput ExecuteInference( string variableName ) + { + // gets the variable + LinguisticVariable lingVar = database.GetVariable( variableName ); + + // object to store the fuzzy output + FuzzyOutput fuzzyOutput = new FuzzyOutput( lingVar ); + + // select only rules with the variable as output + Rule[] rules = rulebase.GetRules( ); + foreach ( Rule r in rules ) + { + if ( r.Output.Variable.Name == variableName ) + { + string labelName = r.Output.Label.Name; + float firingStrength = r.EvaluateFiringStrength( ); + if ( firingStrength > 0 ) + fuzzyOutput.AddOutput( labelName, firingStrength ); + } + } + + // returns the fuzzy output obtained + return fuzzyOutput; + } + } +} diff --git a/Sources/Accord.Fuzzy/LinguisticVariable.cs b/Sources/Accord.Fuzzy/LinguisticVariable.cs new file mode 100644 index 0000000000..23538e769 --- /dev/null +++ b/Sources/Accord.Fuzzy/LinguisticVariable.cs @@ -0,0 +1,204 @@ +// AForge Fuzzy Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Fuzzy +{ + using System; + using System.Collections.Generic; + + /// + /// The class represents a linguistic variable. + /// + /// + /// Linguistic variables are variables that store linguistic values (labels). Fuzzy Inference Systems (FIS) + /// use a set of linguistic variables, called the FIS database, to execute fuzzy computation (computing with words). A linguistic + /// variable has a name and is composed by a set of called its linguistic labels. When declaring fuzzy + /// statements in a FIS, a linguistic variable can be only assigned or compared to one of its labels. + /// + /// Let us consider, for example, a linguistic variable temperature. In a given application, temperature can be + /// cold, cool, warm or hot. Those will be the variable's linguistic labels, each one a fuzzy set with its own membership + /// function. Ideally, the labels will represent concepts related to the variable's meaning. Futhermore, fuzzy statements like + /// "temperature is warm" or "temperature is not cold" can be used to build a Fuzzy Inference Systems. + /// + /// + /// Sample usage: + /// + /// // create a linguistic variable to represent temperature + /// LinguisticVariable lvTemperature = new LinguisticVariable( "Temperature", 0, 80 ); + /// + /// // create the linguistic labels (fuzzy sets) that compose the temperature + /// TrapezoidalFunction function1 = new TrapezoidalFunction( 10, 15, TrapezoidalFunction.EdgeType.Right ); + /// FuzzySet fsCold = new FuzzySet( "Cold", function1 ); + /// TrapezoidalFunction function2 = new TrapezoidalFunction( 10, 15, 20, 25 ); + /// FuzzySet fsCool = new FuzzySet( "Cool", function2 ); + /// TrapezoidalFunction function3 = new TrapezoidalFunction( 20, 25, 30, 35 ); + /// FuzzySet fsWarm = new FuzzySet( "Warm", function3 ); + /// TrapezoidalFunction function4 = new TrapezoidalFunction( 30, 35, TrapezoidalFunction.EdgeType.Left ); + /// FuzzySet fsHot = new FuzzySet( "Hot" , function4 ); + /// + /// // adding labels to the variable + /// lvTemperature.AddLabel( fsCold ); + /// lvTemperature.AddLabel( fsCool ); + /// lvTemperature.AddLabel( fsWarm ); + /// lvTemperature.AddLabel( fsHot ); + /// + /// // showing the shape of the linguistic variable - the shape of its labels memberships from start to end + /// Console.WriteLine( "Cold; Cool; Warm; Hot" ); + /// for ( float x = 0; x < 80; x += 0.2 ) + /// { + /// float y1 = lvTemperature.GetLabelMembership( "Cold", x ); + /// float y2 = lvTemperature.GetLabelMembership( "Cool", x ); + /// float y3 = lvTemperature.GetLabelMembership( "Warm", x ); + /// float y4 = lvTemperature.GetLabelMembership( "Hot" , x ); + /// + /// Console.WriteLine( String.Format( "{0:N}; {1:N}; {2:N}; {3:N}", y1, y2, y3, y4 ) ); + /// } + /// + /// + /// + public class LinguisticVariable + { + // name of the linguistic variable + private string name; + // right limit within the lingusitic variable works + private float start; + // left limit within the lingusitic variable works + private float end; + // the linguistic labels of the linguistic variable + private Dictionary labels; + // the numeric input of this variable + private float numericInput; + + /// + /// Numerical value of the input of this linguistic variable. + /// + public float NumericInput + { + get { return numericInput; } + set { numericInput = value; } + } + + /// + /// Name of the linguistic variable. + /// + public string Name + { + get { return name; } + } + + /// + /// Left limit of the valid variable range. + /// + public float Start + { + get { return start; } + } + + /// + /// Right limit of the valid variable range. + /// + public float End + { + get { return end; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Name of the linguistic variable. + /// + /// Left limit of the valid variable range. + /// + /// Right limit of the valid variable range. + /// + public LinguisticVariable( string name, float start, float end ) + { + this.name = name; + this.start = start; + this.end = end; + + // instance of the labels list - usually a linguistic variable has no more than 10 labels + this.labels = new Dictionary( 10 ); + } + + /// + /// Adds a linguistic label to the variable. + /// + /// + /// A that will be a linguistic label of the linguistic variable. + /// + /// Linguistic labels are fuzzy sets (). Each + /// label of the variable must have a unique name. The range of the label + /// (left and right limits) cannot be greater than + /// the linguistic variable range (start/end). + /// + /// The fuzzy set was not initialized. + /// The linguistic label name already exists in the linguistic variable. + /// The left limit of the fuzzy set can not be lower than the linguistic variable's starting point. + /// "The right limit of the fuzzy set can not be greater than the linguistic variable's ending point." + /// + public void AddLabel( FuzzySet label ) + { + // checking for existing name + if ( this.labels.ContainsKey( label.Name ) ) + throw new ArgumentException( "The linguistic label name already exists in the linguistic variable." ); + + // checking ranges + if ( label.LeftLimit < this.start ) + throw new ArgumentException( "The left limit of the fuzzy set can not be lower than the linguistic variable's starting point." ); + if ( label.RightLimit > this.end ) + throw new ArgumentException( "The right limit of the fuzzy set can not be greater than the linguistic variable's ending point." ); + + // adding label + this.labels.Add( label.Name, label ); + } + + /// + /// Removes all the linguistic labels of the linguistic variable. + /// + /// + public void ClearLabels( ) + { + this.labels.Clear( ); + } + + /// + /// Returns an existing label from the linguistic variable. + /// + /// + /// Name of the label to retrieve. + /// + /// Reference to named label (). + /// + /// The label indicated was not found in the linguistic variable. + /// + public FuzzySet GetLabel( string labelName ) + { + return labels[labelName]; + } + + /// + /// Calculate the membership of a given value to a given label. Used to evaluate linguistics clauses like + /// "X IS A", where X is a value and A is a linguistic label. + /// + /// + /// Label (fuzzy set) to evaluate value's membership. + /// Value which label's membership will to be calculated. + /// + /// Degree of membership [0..1] of the value to the label (fuzzy set). + /// + /// The label indicated in labelName was not found in the linguistic variable. + /// + public float GetLabelMembership( string labelName, float value ) + { + FuzzySet fs = labels[labelName]; + return fs.GetMembership( value ); + } + } +} diff --git a/Sources/Accord.Fuzzy/Membership Functions/IMembershipFunction.cs b/Sources/Accord.Fuzzy/Membership Functions/IMembershipFunction.cs new file mode 100644 index 0000000000..04674b87a --- /dev/null +++ b/Sources/Accord.Fuzzy/Membership Functions/IMembershipFunction.cs @@ -0,0 +1,45 @@ +// AForge Fuzzy Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Fuzzy +{ + using System; + + /// + /// Interface which specifies set of methods required to be implemented by all membership + /// functions. + /// + /// + /// All membership functions must implement this interface, which is used by + /// class to calculate value's membership to a particular fuzzy set. + /// + /// + public interface IMembershipFunction + { + /// + /// Calculate membership of a given value to the fuzzy set. + /// + /// + /// Value which membership will to be calculated. + /// + /// Degree of membership [0..1] of the value to the fuzzy set. + /// + float GetMembership( float x ); + + /// + /// The leftmost x value of the membership function. + /// + float LeftLimit { get; } + + /// + /// The rightmost x value of the membership function. + /// + float RightLimit { get; } + } +} + diff --git a/Sources/Accord.Fuzzy/Membership Functions/PiecewiseLinearFunction.cs b/Sources/Accord.Fuzzy/Membership Functions/PiecewiseLinearFunction.cs new file mode 100644 index 0000000000..5d540b8cd --- /dev/null +++ b/Sources/Accord.Fuzzy/Membership Functions/PiecewiseLinearFunction.cs @@ -0,0 +1,167 @@ +// AForge Fuzzy Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// +namespace AForge.Fuzzy +{ + using System; + using AForge; + + /// + /// Membership function composed by several connected linear functions. + /// + /// + /// The piecewise linear is a generic function used by many specific fuzzy membership + /// functions, like the trappezoidal function. This class must + /// be instantiated with a sequence of points representing the edges of each one of the lines composing the + /// piecewise function. + /// + /// The x-axis points must be ordered (crescent), so the function will use each X value + /// as an ending point for one line and starting point of the next. + /// + /// While trapezoidal and half trapezoidal are classic functions used in fuzzy functions, this class supports any function + /// or approximation that can be represented as a sequence of lines. + /// + /// Sample usage: + /// + /// // creating an array of points representing a typical trapezoidal function /-\ + /// Point [] points = new Point[4]; + /// // point where membership starts to rise + /// points[0] = new Point( 10, 0 ); + /// // maximum membership (1) reached at the second point + /// points[1] = new Point( 20, 1 ); + /// // membership starts to fall at the third point + /// points[2] = new Point( 30, 1 ); + /// // membership gets to zero at the last point + /// points[3] = new Point( 40, 0 ); + /// // creating the instance + /// PiecewiseLinearFunction membershipFunction = new PiecewiseLinearFunction( points ); + /// // getting membership for several points + /// for ( int i = 5; i < 45; i++ ) + /// Console.WriteLine( membershipFunction.GetMembership( i ) ); + /// + /// + /// + public class PiecewiseLinearFunction : IMembershipFunction + { + /// + /// Vector of (X,Y) coordinates for end/start of each line. + /// + protected Point[] points; + + /// + /// The leftmost x value of the membership function, given by the first (X,Y) coordinate. + /// + /// + /// Points of the membership function are not initialized. + /// + public float LeftLimit + { + get + { + return points[0].X; + } + } + + /// + /// The rightmost x value of the membership function, given by the last (X,Y) coordinate. + /// + /// + /// Points of the membership function are not initialized. + /// + public float RightLimit + { + get + { + return points[points.Length - 1].X; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// This constructor must be used only by inherited classes to create the + /// points vector after the instantiation. + /// + protected PiecewiseLinearFunction( ) + { + points = null; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Array of (X,Y) coordinates of each start/end of the lines. + /// + /// Specified point must be in crescent order on X axis and their Y value + /// must be in the range of [0, 1]. + /// + /// Points must be in crescent order on X axis. + /// Y value of points must be in the range of [0, 1]. + /// + public PiecewiseLinearFunction( Point[] points ) + { + this.points = points; + + // check if X points are in a sequence and if Y values are in [0..1] range + for ( int i = 0, n = points.Length; i < n; i++ ) + { + if ( ( points[i].Y < 0 ) || ( points[i].Y > 1 ) ) + throw new ArgumentException( "Y value of points must be in the range of [0, 1]." ); + + if ( i == 0 ) + continue; + + if ( points[i - 1].X > points[i].X ) + throw new ArgumentException( "Points must be in crescent order on X axis." ); + } + } + + /// + /// Calculate membership of a given value to the piecewise function. + /// + /// + /// Value which membership will to be calculated. + /// + /// Degree of membership [0..1] of the value to the fuzzy set. + /// + /// Points of the membership function are not initialized. + /// + public float GetMembership( float x ) + { + // no values belong to the fuzzy set, if there are no points in the piecewise function + if ( points.Length == 0 ) + return 0.0f; + + // if X value is less than the first point, so first point's Y will be returned as membership + if ( x < points[0].X ) + return points[0].Y; + + // looking for the line that contais the X value + for ( int i = 1, n = points.Length; i < n; i++ ) + { + // the line with X value starts in points[i-1].X and ends at points[i].X + if ( x < points[i].X ) + { + // points to calculate line's equation + float y1 = points[i].Y; + float y0 = points[i - 1].Y; + float x1 = points[i].X; + float x0 = points[i - 1].X; + // angular coefficient + float m = ( y1 - y0 ) / ( x1 - x0 ); + // returning the membership - the Y value for this X + return m * ( x - x0 ) + y0; + } + } + + // X value is more than last point, so last point Y will be returned as membership + return points[points.Length - 1].Y; + } + } +} diff --git a/Sources/Accord.Fuzzy/Membership Functions/SingletonFunction.cs b/Sources/Accord.Fuzzy/Membership Functions/SingletonFunction.cs new file mode 100644 index 0000000000..b821b468b --- /dev/null +++ b/Sources/Accord.Fuzzy/Membership Functions/SingletonFunction.cs @@ -0,0 +1,91 @@ +// AForge Fuzzy Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Fuzzy +{ + using System; + using AForge; + + /// + /// Membership function used in fuzzy singletons: fuzzy sets that have just one point with membership value 1. + /// + /// + /// Sometimes it is needed to represent crisp (classical) number in the fuzzy domain. Several approaches + /// can be used, like adding some uncertain (fuzziness) in the original number (the number one, for instance, can be seen as a + /// with -0.5, 1.0 and 0.5 parameters). Another approach is to declare fuzzy singletons: fuzzy sets with only one point returning a none zero membership. + /// + /// While trapezoidal and half trapezoidal are classic functions used in fuzzy functions, this class supports any function + /// or approximation that can be represented as a sequence of lines. + /// + /// Sample usage: + /// + /// // creating the instance + /// SingletonFunction membershipFunction = new SingletonFunction( 10 ); + /// // getting membership for several points + /// for ( int i = 0; i < 20; i++ ) + /// Console.WriteLine( membershipFunction.GetMembership( i ) ); + /// + /// + /// + public class SingletonFunction : IMembershipFunction + { + /// + /// The unique point where the membership value is 1. + /// + protected float support; + + /// + /// The leftmost x value of the membership function, the same value of the support. + /// + /// + public float LeftLimit + { + get + { + return support; + } + } + + /// + /// The rightmost x value of the membership function, the same value of the support. + /// + /// + public float RightLimit + { + get + { + return support; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Support is the only value of x where the membership function is 1. + /// + public SingletonFunction( float support ) + { + this.support = support; + } + + /// + /// Calculate membership of a given value to the singleton function. + /// + /// + /// Value which membership will to be calculated. + /// + /// Degree of membership {0,1} since singletons do not admit memberships different from 0 and 1. + /// + public float GetMembership( float x ) + { + // if x is the support, returns 1, otherwise, returns 0 + return ( support == x ) ? 1 : 0; + } + } +} diff --git a/Sources/Accord.Fuzzy/Membership Functions/TrapezoidalFunction.cs b/Sources/Accord.Fuzzy/Membership Functions/TrapezoidalFunction.cs new file mode 100644 index 0000000000..be091a42b --- /dev/null +++ b/Sources/Accord.Fuzzy/Membership Functions/TrapezoidalFunction.cs @@ -0,0 +1,198 @@ +// AForge Fuzzy Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Fuzzy +{ + using System; + using AForge; + + /// + /// Membership function in the shape of a trapezoid. Can be a half trapzoid if the left or the right side is missing. + /// + /// + /// Since the can represent any piece wise linear + /// function, it can represent trapezoids too. But as trapezoids are largely used in the creation of + /// Linguistic Variables, this class simplifies the creation of them. + /// + /// Sample usage: + /// + /// // creating a typical triangular fuzzy set /\ + /// TrapezoidalFunction function1 = new TrapezoidalFunction( 10, 20, 30 ); + /// // creating a right fuzzy set, the rigth side of the set is fuzzy but the left is opened + /// TrapezoidalFunction function2 = new TrapezoidalFunction( 10, 20, 30, TrapezoidalFunction.EdgeType.Right ); + /// + /// + /// + public class TrapezoidalFunction : PiecewiseLinearFunction + { + /// + /// Enumeration used to create trapezoidal membership functions with half trapezoids. + /// + /// + /// If the value is Left, the trapezoid has the left edge, but right + /// is open (/--). If the value is Right, the trapezoid has the right edge, but left + /// is open (--\). + /// + public enum EdgeType + { + /// + /// The fuzzy side of the trapezoid is at the left side. + /// + Left, + /// + /// The fuzzy side of the trapezoid is at the right side. + /// + Right + }; + + + /// + /// A private constructor used only to reuse code inside of this default constructor. + /// + /// + /// Size of points vector to create. This size depends of the shape of the + /// trapezoid. + /// + private TrapezoidalFunction( int size ) + { + points = new Point[size]; + } + + /// + /// Initializes a new instance of the class. + /// + /// With four points the shape is known as flat fuzzy number or fuzzy interval (/--\). + /// + /// + /// X value where the degree of membership starts to raise. + /// X value where the degree of membership reaches the maximum value. + /// X value where the degree of membership starts to fall. + /// X value where the degree of membership reaches the minimum value. + /// The maximum value that the membership will reach, [0, 1]. + /// The minimum value that the membership will reach, [0, 1]. + /// + public TrapezoidalFunction( float m1, float m2, float m3, float m4, float max, float min ) + : this( 4 ) + { + points[0] = new Point( m1, min ); + points[1] = new Point( m2, max ); + points[2] = new Point( m3, max ); + points[3] = new Point( m4, min ); + } + + /// + /// Initializes a new instance of the class. + /// + /// With four points the shape is known as flat fuzzy number or fuzzy interval (/--\). + /// + /// + /// X value where the degree of membership starts to raise. + /// X value where the degree of membership reaches the maximum value. + /// X value where the degree of membership starts to fall. + /// X value where the degree of membership reaches the minimum value. + /// + /// + /// Maximum membership value is set to 1.0 and the minimum is set to 0.0. + /// + /// + public TrapezoidalFunction( float m1, float m2, float m3, float m4 ) + : this( m1, m2, m3, m4, 1.0f, 0.0f ) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// With three points the shape is known as triangular fuzzy number or just fuzzy number (/\). + /// + /// + /// X value where the degree of membership starts to raise. + /// X value where the degree of membership reaches the maximum value and starts to fall. + /// X value where the degree of membership reaches the minimum value. + /// The maximum value that the membership will reach, [0, 1]. + /// The minimum value that the membership will reach, [0, 1]. + /// + public TrapezoidalFunction( float m1, float m2, float m3, float max, float min ) + : this( 3 ) + { + points[0] = new Point( m1, min ); + points[1] = new Point( m2, max ); + points[2] = new Point( m3, min ); + } + + /// + /// Initializes a new instance of the class. + /// + /// With three points the shape is known as triangular fuzzy number or just fuzzy number (/\). + /// + /// + /// X value where the degree of membership starts to raise. + /// X value where the degree of membership reaches the maximum value and starts to fall. + /// X value where the degree of membership reaches the minimum value. + /// + /// + /// Maximum membership value is set to 1.0 and the minimum is set to 0.0. + /// + /// + public TrapezoidalFunction( float m1, float m2, float m3 ) + : this( m1, m2, m3, 1.0f, 0.0f ) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// With two points and an edge this shape can be a left fuzzy number (/) or a right fuzzy number (\). + /// + /// + /// Edge = Left: X value where the degree of membership starts to raise. + /// Edge = Right: X value where the function starts, with maximum degree of membership. + /// Edge = Left: X value where the degree of membership reaches the maximum. + /// Edge = Right: X value where the degree of membership reaches minimum value. + /// The maximum value that the membership will reach, [0, 1]. + /// The minimum value that the membership will reach, [0, 1]. + /// Trapezoid's . + /// + public TrapezoidalFunction( float m1, float m2, float max, float min, EdgeType edge ) + : this( 2 ) + { + if ( edge == EdgeType.Left ) + { + points[0] = new Point( m1, min ); + points[1] = new Point( m2, max ); + } + else + { + points[0] = new Point( m1, max ); + points[1] = new Point( m2, min ); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// With three points and an edge this shape can be a left fuzzy number (/--) or a right fuzzy number (--\). + /// + /// + /// Edge = Left: X value where the degree of membership starts to raise. + /// Edge = Right: X value where the function starts, with maximum degree of membership. + /// Edge = Left: X value where the degree of membership reaches the maximum. + /// Edge = Right: X value where the degree of membership reaches minimum value. + /// Trapezoid's . + /// + /// + /// Maximum membership value is set to 1.0 and the minimum is set to 0.0. + /// + /// + public TrapezoidalFunction( float m1, float m2, EdgeType edge ) + : this( m1, m2, 1.0f, 0.0f, edge ) + { + } + } +} + diff --git a/Sources/Accord.Fuzzy/Operators/ICoNorm.cs b/Sources/Accord.Fuzzy/Operators/ICoNorm.cs new file mode 100644 index 0000000000..ab1c5b606 --- /dev/null +++ b/Sources/Accord.Fuzzy/Operators/ICoNorm.cs @@ -0,0 +1,36 @@ +// AForge Fuzzy Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Fuzzy +{ + using System; + + /// + /// Interface with the common methods of a Fuzzy CoNorm. + /// + /// + /// All fuzzy operators that act as a CoNorm must implement this interface. + /// + /// + public interface ICoNorm + { + /// + /// Calculates the numerical result of a CoNorm (OR) operation applied to + /// two fuzzy membership values. + /// + /// + /// A fuzzy membership value, [0..1]. + /// A fuzzy membership value, [0..1]. + /// + /// The numerical result the operation OR applied to + /// and . + /// + float Evaluate( float membershipA, float membershipB ); + } +} + diff --git a/Sources/Accord.Fuzzy/Operators/INorm.cs b/Sources/Accord.Fuzzy/Operators/INorm.cs new file mode 100644 index 0000000000..f348275bb --- /dev/null +++ b/Sources/Accord.Fuzzy/Operators/INorm.cs @@ -0,0 +1,37 @@ +// AForge Fuzzy Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Fuzzy +{ + using System; + + /// + /// Interface with the common methods of a Fuzzy Norm. + /// + /// + /// All fuzzy operators that act as a Norm must implement this interface. + /// + /// + public interface INorm + { + /// + /// Calculates the numerical result of a Norm (AND) operation applied to + /// two fuzzy membership values. + /// + /// + /// A fuzzy membership value, [0..1]. + /// A fuzzy membership value, [0..1]. + /// + /// The numerical result the operation AND applied to + /// and . + /// + float Evaluate( float membershipA, float membershipB ); + } +} + + diff --git a/Sources/Accord.Fuzzy/Operators/IUnaryOperator.cs b/Sources/Accord.Fuzzy/Operators/IUnaryOperator.cs new file mode 100644 index 0000000000..4d133ce19 --- /dev/null +++ b/Sources/Accord.Fuzzy/Operators/IUnaryOperator.cs @@ -0,0 +1,35 @@ +// AForge Fuzzy Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Fuzzy +{ + using System; + + /// + /// Interface with the common methods of Fuzzy Unary Operator. + /// + /// + /// All fuzzy operators that act as a Unary Operator (NOT, VERY, LITTLE) must implement this interface. + /// + /// + public interface IUnaryOperator + { + /// + /// Calculates the numerical result of a Unary operation applied to one + /// fuzzy membership value. + /// + /// + /// A fuzzy membership value, [0..1]. + /// + /// The numerical result of the operation applied to . + /// + float Evaluate( float membership ); + } +} + + diff --git a/Sources/Accord.Fuzzy/Operators/MaximumCoNorm.cs b/Sources/Accord.Fuzzy/Operators/MaximumCoNorm.cs new file mode 100644 index 0000000000..57e9be036 --- /dev/null +++ b/Sources/Accord.Fuzzy/Operators/MaximumCoNorm.cs @@ -0,0 +1,63 @@ +// AForge Fuzzy Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Fuzzy +{ + using System; + using AForge; + + /// + /// Maximum CoNorm, used to calculate the linguistic value of a OR operation. + /// + /// + /// The maximum CoNorm uses a maximum operator to compute the OR + /// among two fuzzy memberships. + /// + /// Sample usage: + /// + /// // creating 2 fuzzy sets to represent Cool (Temperature) and Near (Distance) + /// TrapezoidalFunction function1 = new TrapezoidalFunction( 13, 18, 23, 28 ); + /// FuzzySet fsCool = new FuzzySet( "Cool", function1 ); + /// TrapezoidalFunction function2 = new TrapezoidalFunction( 23, 28, 33, 38 ); + /// FuzzySet fsNear = new FuzzySet( "Near", function2 ); + /// + /// // getting memberships + /// float m1 = fsCool.GetMembership( 15 ); + /// float m2 = fsNear.GetMembership( 35 ); + /// + /// // computing the membership of "Cool OR Near" + /// MaximumCoNorm OR = new MaximumCoNorm( ); + /// float result = OR.Evaluate( m1, m2 ); + /// + /// // show result + /// Console.WriteLine( result ); + /// + /// + /// + /// + /// + public class MaximumCoNorm : ICoNorm + { + /// + /// Calculates the numerical result of the OR operation applied to + /// two fuzzy membership values. + /// + /// + /// A fuzzy membership value, [0..1]. + /// A fuzzy membership value, [0..1]. + /// + /// The numerical result of the binary operation OR applied to + /// and . + /// + public float Evaluate( float membershipA, float membershipB ) + { + return Math.Max( membershipA, membershipB ); + } + } +} + diff --git a/Sources/Accord.Fuzzy/Operators/MinimumNorm.cs b/Sources/Accord.Fuzzy/Operators/MinimumNorm.cs new file mode 100644 index 0000000000..518e36a59 --- /dev/null +++ b/Sources/Accord.Fuzzy/Operators/MinimumNorm.cs @@ -0,0 +1,64 @@ +// AForge Fuzzy Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Fuzzy +{ + using System; + using AForge; + + /// + /// Minimum Norm, used to calculate the linguistic value of a AND operation. + /// + /// + /// The minimum Norm uses a minimum operator to compute the AND + /// among two fuzzy memberships. + /// + /// Sample usage: + /// + /// // creating 2 fuzzy sets to represent Cool (Temperature) and Near (Distance) + /// TrapezoidalFunction function1 = new TrapezoidalFunction( 13, 18, 23, 28 ); + /// FuzzySet fsCool = new FuzzySet( "Cool", function1 ); + /// TrapezoidalFunction function2 = new TrapezoidalFunction( 23, 28, 33, 38 ); + /// FuzzySet fsNear = new FuzzySet( "Near", function2 ); + /// + /// // getting memberships + /// float m1 = fsCool.GetMembership( 15 ); + /// float m2 = fsNear.GetMembership( 35 ); + /// + /// // computing the membership of "Cool AND Near" + /// MinimumNorm AND = new MinimumNorm( ); + /// float result = AND.Evaluate( m1, m2 ); + /// + /// // show result + /// Console.WriteLine( result ); + /// + /// + /// + /// + /// + public class MinimumNorm : INorm + { + /// + /// Calculates the numerical result of the AND operation applied to + /// two fuzzy membership values using the minimum rule. + /// + /// + /// A fuzzy membership value, [0..1]. + /// + /// A fuzzy membership value, [0..1]. + /// + /// The numerical result of the AND operation applied to + /// and . + /// + public float Evaluate( float membershipA, float membershipB ) + { + return Math.Min( membershipA, membershipB ); + } + } +} + diff --git a/Sources/Accord.Fuzzy/Operators/NotOperator.cs b/Sources/Accord.Fuzzy/Operators/NotOperator.cs new file mode 100644 index 0000000000..eb593d6bb --- /dev/null +++ b/Sources/Accord.Fuzzy/Operators/NotOperator.cs @@ -0,0 +1,57 @@ +// AForge Fuzzy Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Fuzzy +{ + using System; + using AForge; + + /// + /// NOT operator, used to calculate the complement of a fuzzy set. + /// + /// + /// The NOT operator definition is (1 - m) for all the values of membership m of the fuzzy set. + /// + /// Sample usage: + /// + /// // creating a fuzzy sets to represent Cool (Temperature) + /// TrapezoidalFunction function1 = new TrapezoidalFunction( 13, 18, 23, 28 ); + /// FuzzySet fsCool = new FuzzySet( "Cool", function1 ); + /// + /// // getting membership + /// float m1 = fsCool.GetMembership( 15 ); + /// + /// // computing the membership of "NOT Cool" + /// NotOperator NOT = new NotOperator( ); + /// float result = NOT.Evaluate( m1 ); + /// + /// // show result + /// Console.WriteLine( result ); + /// + /// + /// + /// + /// + public class NotOperator : IUnaryOperator + { + /// + /// Calculates the numerical result of the NOT operation applied to + /// a fuzzy membership value. + /// + /// + /// A fuzzy membership value, [0..1]. + /// + /// The numerical result of the unary operation NOT applied to . + /// + public float Evaluate( float membership ) + { + return ( 1 - membership ); + } + } +} + diff --git a/Sources/Accord.Fuzzy/Operators/ProductNorm.cs b/Sources/Accord.Fuzzy/Operators/ProductNorm.cs new file mode 100644 index 0000000000..e1fb4628c --- /dev/null +++ b/Sources/Accord.Fuzzy/Operators/ProductNorm.cs @@ -0,0 +1,62 @@ +// AForge Fuzzy Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// +namespace AForge.Fuzzy +{ + using System; + using AForge; + + /// + /// Product Norm, used to calculate the linguistic value of a AND operation. + /// + /// + /// The product Norm uses a multiplication operator to compute the + /// AND among two fuzzy memberships. + /// + /// Sample usage: + /// + /// // creating 2 fuzzy sets to represent Cool (Temperature) and Near (Distance) + /// TrapezoidalFunction function1 = new TrapezoidalFunction( 13, 18, 23, 28 ); + /// FuzzySet fsCool = new FuzzySet( "Cool", function1 ); + /// TrapezoidalFunction function2 = new TrapezoidalFunction( 23, 28, 33, 38 ); + /// FuzzySet fsNear = new FuzzySet( "Near", function2 ); + /// + /// // getting memberships + /// float m1 = fsCool.GetMembership( 15 ); + /// float m2 = fsNear.GetMembership( 35 ); + /// + /// // computing the membership of "Cool AND Near" + /// ProductNorm AND = new ProductNorm( ); + /// float result = AND.Evaluate( m1, m2 ); + /// + /// // show result + /// Console.WriteLine( result ); + /// + /// + /// + /// + /// + public class ProductNorm : INorm + { + /// + /// Calculates the numerical result of the AND operation applied to + /// two fuzzy membership values using the product rule. + /// + /// + /// A fuzzy membership value, [0..1]. + /// A fuzzy membership value, [0..1]. + /// + /// The numerical result of the AND operation applied to + /// and . + /// + public float Evaluate( float membershipA, float membershipB ) + { + return membershipA * membershipB; + } + } +} + diff --git a/Sources/Accord.Audio.Formats/Properties/AssemblyInfo.cs b/Sources/Accord.Fuzzy/Properties/AssemblyInfo.cs similarity index 81% rename from Sources/Accord.Audio.Formats/Properties/AssemblyInfo.cs rename to Sources/Accord.Fuzzy/Properties/AssemblyInfo.cs index dc266de7a..f4f42a858 100644 --- a/Sources/Accord.Audio.Formats/Properties/AssemblyInfo.cs +++ b/Sources/Accord.Fuzzy/Properties/AssemblyInfo.cs @@ -4,8 +4,8 @@ // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("Accord.Audio.Formats")] -[assembly: AssemblyDescription("Accord.NET - Audio Library")] +[assembly: AssemblyTitle("Accord.Fuzzy")] +[assembly: AssemblyDescription("Accord.NET - Fuzzy Logic Library")] [assembly: AssemblyConfiguration("")] // This sets the default COM visibility of types in the assembly to invisible. diff --git a/Sources/Accord.Fuzzy/Rule.cs b/Sources/Accord.Fuzzy/Rule.cs new file mode 100644 index 0000000000..4b90a8a70 --- /dev/null +++ b/Sources/Accord.Fuzzy/Rule.cs @@ -0,0 +1,483 @@ +// AForge Fuzzy Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Fuzzy +{ + using System; + using System.Collections.Generic; + + /// + /// This class represents a Fuzzy Rule, a linguistic expression representing some behavioral + /// aspect of a Fuzzy Inference System. + /// + /// + /// + /// A Fuzzy Rule is a fuzzy linguistic instruction that can be executed by a fuzzy system. + /// The format of the Fuzzy Rule is: + /// + /// + /// IF antecedent THEN consequent + /// + /// The antecedent is composed by a set of fuzzy clauses (see ) connected + /// by fuzzy operations, like AND or OR. The operator NOT can be used to negate expressions: + /// + /// ...Clause1 AND (Clause2 OR Clause3) AND NOT Clause4 ... + /// + /// Fuzzy clauses are written in form Variable IS Value. The NOT operator can be used to negate linguistic values as well:
+ /// ...Variable1 IS Value1 AND Variable2 IS NOT Value2 ...
+ /// + /// The consequent is a single of fuzzy clauses (). To perform the + /// linguistic computing, the evaluates the clauses and then applies the fuzzy + /// operators. Once this is done a value representing the confidence in the antecedent being + /// true is obtained, and this is called firing strength of the . + /// + /// The firing strength is used to discover with how much confidence the consequent + /// of a rule is true. + /// + /// Sample usage: + /// + /// // create the linguistic labels (fuzzy sets) that compose the temperature + /// TrapezoidalFunction function1 = new TrapezoidalFunction( + /// 10, 15, TrapezoidalFunction.EdgeType.Right ); + /// FuzzySet fsCold = new FuzzySet( "Cold", function1 ); + /// TrapezoidalFunction function2 = new TrapezoidalFunction( 10, 15, 20, 25 ); + /// FuzzySet fsCool = new FuzzySet( "Cool", function2 ); + /// TrapezoidalFunction function3 = new TrapezoidalFunction( 20, 25, 30, 35 ); + /// FuzzySet fsWarm = new FuzzySet( "Warm", function3 ); + /// TrapezoidalFunction function4 = new TrapezoidalFunction( + /// 30, 35, TrapezoidalFunction.EdgeType.Left ); + /// FuzzySet fsHot = new FuzzySet( "Hot", function4 ); + /// + /// // create a linguistic variable to represent steel temperature + /// LinguisticVariable lvSteel = new LinguisticVariable( "Steel", 0, 80 ); + /// // adding labels to the variable + /// lvSteel.AddLabel( fsCold ); + /// lvSteel.AddLabel( fsCool ); + /// lvSteel.AddLabel( fsWarm ); + /// lvSteel.AddLabel( fsHot ); + /// + /// // create a linguistic variable to represent stove temperature + /// LinguisticVariable lvStove = new LinguisticVariable( "Stove", 0, 80 ); + /// // adding labels to the variable + /// lvStove.AddLabel( fsCold ); + /// lvStove.AddLabel( fsCool ); + /// lvStove.AddLabel( fsWarm ); + /// lvStove.AddLabel( fsHot ); + /// + /// // create the linguistic labels (fuzzy sets) that compose the pressure + /// TrapezoidalFunction function5 = new TrapezoidalFunction( + /// 20, 40, TrapezoidalFunction.EdgeType.Right ); + /// FuzzySet fsLow = new FuzzySet( "Low", function5 ); + /// TrapezoidalFunction function6 = new TrapezoidalFunction( 20, 40, 60, 80 ); + /// FuzzySet fsMedium = new FuzzySet( "Medium", function6 ); + /// TrapezoidalFunction function7 = new TrapezoidalFunction( + /// 60, 80, TrapezoidalFunction.EdgeType.Left ); + /// FuzzySet fsHigh = new FuzzySet( "High", function7 ); + /// // create a linguistic variable to represent pressure + /// LinguisticVariable lvPressure = new LinguisticVariable( "Pressure", 0, 100 ); + /// // adding labels to the variable + /// lvPressure.AddLabel( fsLow ); + /// lvPressure.AddLabel( fsMedium ); + /// lvPressure.AddLabel( fsHigh ); + /// + /// // create a linguistic variable database + /// Database db = new Database( ); + /// db.AddVariable( lvSteel ); + /// db.AddVariable( lvStove ); + /// db.AddVariable( lvPressure ); + /// + /// // sample rules just to test the expression parsing + /// Rule r1 = new Rule( db, "Test1", "IF Steel is not Cold and Stove is Hot then Pressure is Low" ); + /// Rule r2 = new Rule( db, "Test2", "IF Steel is Cold and not (Stove is Warm or Stove is Hot) then Pressure is Medium" ); + /// Rule r3 = new Rule( db, "Test3", "IF Steel is Cold and Stove is Warm or Stove is Hot then Pressure is High" ); + /// + /// // testing the firing strength + /// lvSteel.NumericInput = 12; + /// lvStove.NumericInput = 35; + /// float result = r1.EvaluateFiringStrength( ); + /// Console.WriteLine( result.ToString( ) ); + /// + ///
+ /// + public class Rule + { + // name of the rule + private string name; + // the original expression + private string rule; + // the parsed RPN (reverse polish notation) expression + private List rpnTokenList; + // the consequento (output) of the rule + private Clause output; + // the database with the linguistic variables + private Database database; + // the norm operator + private INorm normOperator; + // the conorm operator + private ICoNorm conormOperator; + // the complement operator + private IUnaryOperator notOperator; + // the unary operators that the rule parser supports + private string unaryOperators = "NOT;VERY"; + + /// + /// The name of the fuzzy rule. + /// + /// + public string Name + { + get { return name; } + set { name = value; } + } + + /// + /// The fuzzy that represents the consequent of the . + /// + /// + public Clause Output + { + get { return output; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// A fuzzy containig the linguistic variables + /// (see ) that will be used in the Rule. + /// + /// Name of this . + /// + /// A string representing the . It must be a "IF..THEN" statement. + /// For a more detailed description see class. + /// + /// A class that implements a interface to + /// evaluate the AND operations of the Rule. + /// + /// A class that implements a interface + /// to evaluate the OR operations of the Rule. + /// + public Rule( Database fuzzyDatabase, string name, string rule, INorm normOperator, ICoNorm coNormOperator ) + { + // the list with the RPN expression + rpnTokenList = new List( ); + + // setting attributes + this.name = name; + this.rule = rule; + this.database = fuzzyDatabase; + this.normOperator = normOperator; + this.conormOperator = coNormOperator; + this.notOperator = new NotOperator( ); + + // parsing the rule to obtain RPN of the expression + ParseRule( ); + } + + /// + /// Initializes a new instance of the class using as + /// CoNorm the and as Norm the . + /// + /// + /// A fuzzy containig the linguistic variables + /// (see ) that will be used in the . + /// + /// Name of this . + /// + /// A string representing the . It must be a "IF..THEN" + /// statement. For a more detailed description see class. + /// + public Rule( Database fuzzyDatabase, string name, string rule ) : + this( fuzzyDatabase, name, rule, new MinimumNorm( ), new MaximumCoNorm( ) ) + { + } + + /// + /// Converts the RPN fuzzy expression into a string representation. + /// + /// + /// String representation of the RPN fuzzy expression. + /// + public string GetRPNExpression( ) + { + string result = ""; + foreach ( object o in rpnTokenList ) + { + // if its a fuzzy clause we can call clause's ToString() + if ( o.GetType( ) == typeof( Clause ) ) + { + Clause c = o as Clause; + result += c.ToString( ); + } + else + result += o.ToString( ); + result += ", "; + } + result += "#"; + result = result.Replace( ", #", "" ); + return result; + } + + /// + /// Defines the priority of the fuzzy operators. + /// + /// + /// A fuzzy operator or openning parenthesis. + /// + /// A number indicating the priority of the operator, and zero for openning + /// parenthesis. + /// + private int Priority( string Operator ) + { + // if its unary + if ( unaryOperators.IndexOf( Operator ) >= 0 ) + return 4; + + switch ( Operator ) + { + case "(": return 1; + case "OR": return 2; + case "AND": return 3; + } + return 0; + } + + /// + /// Converts the Fuzzy Rule to RPN (Reverse Polish Notation). For debug proposes, the string representation of the + /// RPN expression can be acessed by calling method. + /// + /// + private void ParseRule( ) + { + // flag to incicate we are on consequent state + bool consequent = false; + + // tokens like IF and THEN will be searched always in upper case + string upRule = rule.ToUpper( ); + + // the rule must start with IF, and must have a THEN somewhere + if ( !upRule.StartsWith( "IF" ) ) + throw new ArgumentException( "A Fuzzy Rule must start with an IF statement." ); + if ( upRule.IndexOf( "THEN" ) < 0 ) + throw new ArgumentException( "Missing the consequent (THEN) statement." ); + + // building a list with all the expression (rule) string tokens + string spacedRule = rule.Replace( "(", " ( " ).Replace( ")", " ) " ); + // getting the tokens list + string[] tokensList = GetRuleTokens( spacedRule ); + + // stack to convert to RPN + Stack s = new Stack( ); + // storing the last token + string lastToken = "IF"; + // linguistic var read, used to build clause + LinguisticVariable lingVar = null; + + // verifying each token + for ( int i = 0; i < tokensList.Length; i++ ) + { + // removing spaces + string token = tokensList[i].Trim( ); + // getting upper case + string upToken = token.ToUpper( ); + + // ignoring these tokens + if ( upToken == "" || upToken == "IF" ) continue; + + // if the THEN is found, the rule is now on consequent + if ( upToken == "THEN" ) + { + lastToken = upToken; + consequent = true; + continue; + } + + // if we got a linguistic variable, an IS statement and a label is needed + if ( lastToken == "VAR" ) + { + if ( upToken == "IS" ) + lastToken = upToken; + else + throw new ArgumentException( "An IS statement is expected after a linguistic variable." ); + } + // if we got an IS statement, a label must follow it + else if ( lastToken == "IS" ) + { + try + { + FuzzySet fs = lingVar.GetLabel( token ); + Clause c = new Clause( lingVar, fs ); + if ( consequent ) + output = c; + else + rpnTokenList.Add( c ); + lastToken = "LAB"; + } + catch ( KeyNotFoundException ) + { + throw new ArgumentException( "Linguistic label " + token + " was not found on the variable " + lingVar.Name + "." ); + } + } + // not VAR and not IS statement + else + { + // openning new scope + if ( upToken == "(" ) + { + // if we are on consequent, only variables can be found + if ( consequent ) + throw new ArgumentException( "Linguistic variable expected after a THEN statement." ); + // if its a (, just push it + s.Push( upToken ); + lastToken = upToken; + } + // operators + else if ( upToken == "AND" || upToken == "OR" || unaryOperators.IndexOf( upToken ) >= 0 ) + { + // if we are on consequent, only variables can be found + if ( consequent ) + throw new ArgumentException( "Linguistic variable expected after a THEN statement." ); + + // pop all the higher priority operators until the stack is empty + while ( ( s.Count > 0 ) && ( Priority( s.Peek( ) ) > Priority( upToken ) ) ) + rpnTokenList.Add( s.Pop( ) ); + + // pushing the operator + s.Push( upToken ); + lastToken = upToken; + } + // closing the scope + else if ( upToken == ")" ) + { + // if we are on consequent, only variables can be found + if ( consequent ) + throw new ArgumentException( "Linguistic variable expected after a THEN statement." ); + + // if there is nothing on the stack, an oppening parenthesis is missing. + if ( s.Count == 0 ) + throw new ArgumentException( "Openning parenthesis missing." ); + + // pop the tokens and copy to output until openning is found + while ( s.Peek( ) != "(" ) + { + rpnTokenList.Add( s.Pop( ) ); + if ( s.Count == 0 ) + throw new ArgumentException( "Openning parenthesis missing." ); + } + s.Pop( ); + + // saving last token... + lastToken = upToken; + } + // finally, the token is a variable + else + { + // find the variable + try + { + lingVar = database.GetVariable( token ); + lastToken = "VAR"; + } + catch ( KeyNotFoundException ) + { + throw new ArgumentException( "Linguistic variable " + token + " was not found on the database." ); + } + } + } + } + + // popping all operators left in stack + while ( s.Count > 0 ) + rpnTokenList.Add( s.Pop( ) ); + } + + /// + /// Performs a preprocessing on the rule, placing unary operators in proper position and breaking the string + /// space separated tokens. + /// + /// + /// Rule in string format. + /// + /// An array of strings with tokens of the rule. + /// + private string[] GetRuleTokens( string rule ) + { + // breaking in tokens + string[] tokens = rule.Split( ' ' ); + + // looking for unary operators + for ( int i = 0; i < tokens.Length; i++ ) + { + // if its unary and there is an "IS" token before, we must change positions + if ( ( unaryOperators.IndexOf( tokens[i].ToUpper( ) ) >= 0 ) && + ( i > 1 ) && ( tokens[i - 1].ToUpper( ) == "IS" ) ) + { + // placing VAR name + tokens[i - 1] = tokens[i - 2]; + tokens[i - 2] = tokens[i]; + tokens[i] = "IS"; + } + } + + return tokens; + } + + /// + /// Evaluates the firing strength of the Rule, the degree of confidence that the consequent of this Rule + /// must be executed. + /// + /// + /// The firing strength [0..1] of the Rule. + /// + public float EvaluateFiringStrength( ) + { + // Stack to store the operand values + Stack s = new Stack( ); + + // Logic to calculate the firing strength + foreach ( object o in rpnTokenList ) + { + // if its a clause, then its value must be calculated and pushed + if ( o.GetType( ) == typeof( Clause ) ) + { + Clause c = o as Clause; + s.Push( c.Evaluate( ) ); + } + // if its an operator (AND / OR) the operation is performed and the result + // returns to the stack + else + { + float y = s.Pop( ); + float x = 0; + + // unary pops only one value + if ( unaryOperators.IndexOf( o.ToString( ) ) < 0 ) + x = s.Pop( ); + + // operation + switch ( o.ToString( ) ) + { + case "AND": + s.Push( normOperator.Evaluate( x, y ) ); + break; + case "OR": + s.Push( conormOperator.Evaluate( x, y ) ); + break; + case "NOT": + s.Push( notOperator.Evaluate( y ) ); + break; + } + } + } + + // result on the top of stack + return s.Pop( ); + } + } +} + diff --git a/Sources/Accord.Fuzzy/Rulebase.cs b/Sources/Accord.Fuzzy/Rulebase.cs new file mode 100644 index 0000000000..f9d9e3e7c --- /dev/null +++ b/Sources/Accord.Fuzzy/Rulebase.cs @@ -0,0 +1,96 @@ +// AForge Fuzzy Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2008-2009 +// andrew.kirillov@aforgenet.com +// +// Copyright © Fabio L. Caversan, 2008-2009 +// fabio.caversan@gmail.com +// + +namespace AForge.Fuzzy +{ + using System; + using System.Collections.Generic; + + /// + /// The class represents a fuzzy rulebase, a set of fuzzy rules used in a Fuzzy Inference System. + /// + /// + public class Rulebase + { + // the fuzzy rules repository + private Dictionary rules; + + /// + /// Initializes a new instance of the class. + /// + /// + public Rulebase( ) + { + // instance of the rules list + this.rules = new Dictionary( 20 ); + } + + /// + /// Adds a fuzzy rule to the database. + /// + /// + /// A fuzzy to add to the database. + /// + /// The fuzzy rule was not initialized. + /// The fuzzy rule name already exists in the rulebase. + /// + public void AddRule( Rule rule ) + { + // checking for existing name + if ( this.rules.ContainsKey( rule.Name ) ) + throw new ArgumentException( "The fuzzy rule name already exists in the rulebase." ); + + // adding rule + this.rules.Add( rule.Name, rule ); + } + + /// + /// Removes all the fuzzy rules of the database. + /// + /// + public void ClearRules( ) + { + this.rules.Clear( ); + } + + /// + /// Returns an existing fuzzy rule from the rulebase. + /// + /// + /// Name of the fuzzy to retrieve. + /// + /// Reference to named . + /// + /// The rule indicated in ruleName was not found in the rulebase. + /// + public Rule GetRule( string ruleName ) + { + return rules [ruleName]; + } + + /// + /// Gets all the rules of the rulebase. + /// + /// + /// An array with all the rulebase rules. + /// + public Rule[] GetRules( ) + { + Rule[] r = new Rule[rules.Count]; + + int i = 0; + foreach ( KeyValuePair kvp in rules ) + r[i++] = kvp.Value; + + return r; + } + } +} diff --git a/Sources/Accord.Genetic/Accord.Genetic.cd b/Sources/Accord.Genetic/Accord.Genetic.cd new file mode 100644 index 0000000000..c012aedaf --- /dev/null +++ b/Sources/Accord.Genetic/Accord.Genetic.cd @@ -0,0 +1,220 @@ + + + + + + AAEAAIAAAAAAAAAEAEAAAgBAAAAAAAAACAAwAEAAABA= + Chromosomes\BinaryChromosome.cs + + + + + + AAEgAAAAIAAAAAQAAAAAAgAAAAAAAAAACAAAAEAAABA= + Chromosomes\ChromosomeBase.cs + + + + + + + AAECAIAAAAAAAAAUAEAQAgBAEIAAAAAECIAwAEAAABA= + Chromosomes\DoubleArrayChromosome.cs + + + + + + + + + + Chromosomes\GP\ExtendedGeneFunction.cs + + + + + IAAAAKAAAAAAAAAEBAIAAgAAACABAAAAAAAAAEAQABA= + Chromosomes\GP\ExtendedGeneFunction.cs + + + + + + + + + + QEEAAIAAAAAAIAAEAWAAAkAgAQAEAAAACAAEAEAAABA= + Chromosomes\GP\GEPChromosome.cs + + + + + + AAEAAIAAAAAAgAAEEAAgAgAAAAAAAAAACAAAwEAAANA= + Chromosomes\GP\GPTreeChromosome.cs + + + + + + AAAAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAABI= + Chromosomes\GP\GPTreeNode.cs + + + + + + + + + + + + + + + Chromosomes\GP\SimpleGeneFunction.cs + + + + + AAAAAKAAAAAAAAAEBAIAAgAAACABAAAAAAAAAEAQABA= + Chromosomes\GP\SimpleGeneFunction.cs + + + + + + + + + + + + + AAEAgAAAAAAAQAAAAAAAAgAAAAAAAAAACAAAAEAAABA= + Chromosomes\PermutationChromosome.cs + + + + + + AAEAAIAAAAAAAAAEAEAAAgBAAAAAACAACAAwAEAAABA= + Chromosomes\ShortArrayChromosome.cs + + + + + + + + Fitness Functions\OptimizationFunction1D.cs + + + + + AACAAAAIAIAACACAAAAAAgAAAAAAAAAAAAAEAAAAAAA= + Fitness Functions\OptimizationFunction1D.cs + + + + + + + + + Fitness Functions\OptimizationFunction2D.cs + + + + + AACAAAAIAIAACACAAAAAAgAAAAAAAAAAAAAEAAAAAAA= + Fitness Functions\OptimizationFunction2D.cs + + + + + + + AAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAUAAAEAAA= + Fitness Functions\SymbolicRegressionFitness.cs + + + + + + + AAAAAAAEAAAAAAAAAAAAAgAAAAAAAAQAAAAUAAAEAAA= + Fitness Functions\TimeSeriesPredictionFitness.cs + + + + + + + AAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAA= + Selection Algorithms\EliteSelection.cs + + + + + + + AAAAAIAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAA= + Selection Algorithms\RankSelection.cs + + + + + + + AAAAAIAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAA= + Selection Algorithms\RouletteWheelSelection.cs + + + + + + + AAAAACAAAAAAAAAAAAAAAgAAACAAAAAAAAAAAEAQABA= + Chromosomes\GP\IGPGene.cs + + + + + + AAEgAAAAAAAAAAAAAAAAAgAAAAAAAAAACAAAAEAAABA= + Chromosomes\IChromosome.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAA= + Fitness Functions\IFitnessFunction.cs + + + + + + AAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAA= + Selection Algorithms\ISelectionMethod.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAIAAAAAAAAAA= + Chromosomes\GP\IGPGene.cs + + + + \ No newline at end of file diff --git a/Sources/Accord.Genetic/Accord.Genetic.csproj b/Sources/Accord.Genetic/Accord.Genetic.csproj new file mode 100644 index 0000000000..8eeff5c82 --- /dev/null +++ b/Sources/Accord.Genetic/Accord.Genetic.csproj @@ -0,0 +1,135 @@ + + + + {2EFAA327-1789-4438-B9F5-E83ACAE12DB2} + Accord.Genetic + Accord.Genetic + Debug + AnyCPU + AnyCPU + Library + Properties + True + 4 + True + true + Accord.snk + 3.5 + False + true + ..\Accord.NET.ruleset + false + true + 4096 + true + pdbonly + true + + + v4.5 + $(SolutionDir)..\Debug\ + Full + False + true + False + True + DEBUG;TRACE + + + $(SolutionDir)..\Release\net35 + TRACE;CODE_ANALYSIS;NET35 + v3.5 + $(SolutionDir)..\Release\net35\Accord.Genetic.XML + $(SolutionDir)..\Release\net35\Accord.Genetic.dll.CodeAnalysisLog.xml + + + $(SolutionDir)..\Release\net40 + TRACE;CODE_ANALYSIS;NET40 + v4.0 + $(SolutionDir)..\Release\net40\Accord.Genetic.XML + $(SolutionDir)..\Release\net40\Accord.Genetic.dll.CodeAnalysisLog.xml + + + $(SolutionDir)..\Release\net45 + TRACE;CODE_ANALYSIS;NET45 + v4.5 + $(SolutionDir)..\Release\net45\Accord.Genetic.XML + $(SolutionDir)..\Release\net45\Accord.Genetic.dll.CodeAnalysisLog.xml + + + + + + + + + Properties\VersionInfo.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + {a177a90c-8207-466a-af70-f2b8452a42ac} + Accord.Core + + + {f718e9a8-db62-4785-8c49-4333a60d256a} + Accord.Math + + + + + + + + \ No newline at end of file diff --git a/Sources/Accord.Genetic/Accord.snk b/Sources/Accord.Genetic/Accord.snk new file mode 100644 index 0000000000..ed97b4edd Binary files /dev/null and b/Sources/Accord.Genetic/Accord.snk differ diff --git a/Sources/Accord.Genetic/Chromosomes/BinaryChromosome.cs b/Sources/Accord.Genetic/Chromosomes/BinaryChromosome.cs new file mode 100644 index 0000000000..6f2f08e39 --- /dev/null +++ b/Sources/Accord.Genetic/Chromosomes/BinaryChromosome.cs @@ -0,0 +1,216 @@ +// AForge Genetic Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +namespace AForge.Genetic +{ + using System; + using AForge; + + /// + /// Binary chromosome, which supports length from 2 till 64. + /// + /// + /// The binary chromosome is the simplest type of chromosomes, + /// which is represented by a set of bits. Maximum number of bits comprising + /// the chromosome is 64. + /// + public class BinaryChromosome : ChromosomeBase + { + /// + /// Chromosome's length in bits. + /// + protected int length; + + /// + /// Numerical chromosome's value. + /// + protected ulong val = 0; + + /// + /// Random number generator for chromosoms generation, crossover, mutation, etc. + /// + protected static ThreadSafeRandom rand = new ThreadSafeRandom( ); + + /// + /// Chromosome's maximum length. + /// + /// + /// Maxim chromosome's length in bits, which is supported + /// by the class + /// + public const int MaxLength = 64; + + /// + /// Chromosome's length. + /// + /// + /// Length of the chromosome in bits. + /// + public int Length + { + get { return length; } + } + + /// + /// Chromosome's value. + /// + /// + /// Current numerical value of the chromosome. + /// + public ulong Value + { + get { return val & ( 0xFFFFFFFFFFFFFFFF >> ( 64 - length ) ); } + } + + /// + /// Max possible chromosome's value. + /// + /// + /// Maximum possible numerical value, which may be represented + /// by the chromosome of current length. + /// + public ulong MaxValue + { + get { return 0xFFFFFFFFFFFFFFFF >> ( 64 - length ); } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Chromosome's length in bits, [2, ]. + /// + public BinaryChromosome( int length ) + { + this.length = Math.Max( 2, Math.Min( MaxLength, length ) ); + // randomize the chromosome + Generate( ); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Source chromosome to copy. + /// + /// This is a copy constructor, which creates the exact copy + /// of specified chromosome. + /// + protected BinaryChromosome( BinaryChromosome source ) + { + length = source.length; + val = source.val; + fitness = source.fitness; + } + + /// + /// Get string representation of the chromosome. + /// + /// + /// Returns string representation of the chromosome. + /// + public override string ToString( ) + { + ulong tval = val; + char[] chars = new char[length]; + + for ( int i = length - 1; i >= 0; i-- ) + { + chars[i] = (char) ( ( tval & 1 ) + '0' ); + tval >>= 1; + } + + // return the result string + return new string( chars ); + } + + /// + /// Generate random chromosome value. + /// + /// + /// Regenerates chromosome's value using random number generator. + /// + /// + public override void Generate( ) + { + byte[] bytes = new byte[8]; + + // generate value + rand.NextBytes( bytes ); + val = BitConverter.ToUInt64( bytes, 0 ); + } + + /// + /// Create new random chromosome with same parameters (factory method). + /// + /// + /// The method creates new chromosome of the same type, but randomly + /// initialized. The method is useful as factory method for those classes, which work + /// with chromosome's interface, but not with particular chromosome type. + /// + public override IChromosome CreateNew( ) + { + return new BinaryChromosome( length ); + } + + /// + /// Clone the chromosome. + /// + /// + /// Return's clone of the chromosome. + /// + /// The method clones the chromosome returning the exact copy of it. + /// + /// + public override IChromosome Clone( ) + { + return new BinaryChromosome( this ); + } + + /// + /// Mutation operator. + /// + /// + /// The method performs chromosome's mutation, changing randomly + /// one of its bits. + /// + public override void Mutate( ) + { + val ^= ( (ulong) 1 << rand.Next( length ) ); + } + + /// + /// Crossover operator. + /// + /// + /// Pair chromosome to crossover with. + /// + /// The method performs crossover between two chromosomes interchanging + /// range of bits between these chromosomes. + /// + public override void Crossover( IChromosome pair ) + { + BinaryChromosome p = (BinaryChromosome) pair; + + // check for correct pair + if ( ( p != null ) && ( p.length == length ) ) + { + int crossOverPoint = 63 - rand.Next( length - 1 ); + ulong mask1 = 0xFFFFFFFFFFFFFFFF >> crossOverPoint; + ulong mask2 = ~mask1; + + ulong v1 = val; + ulong v2 = p.val; + + // calculate new values + val = ( v1 & mask1 ) | ( v2 & mask2 ); + p.val = ( v2 & mask1 ) | ( v1 & mask2 ); + } + } + } +} diff --git a/Sources/Accord.Genetic/Chromosomes/ChromosomeBase.cs b/Sources/Accord.Genetic/Chromosomes/ChromosomeBase.cs new file mode 100644 index 0000000000..97fe1fb64 --- /dev/null +++ b/Sources/Accord.Genetic/Chromosomes/ChromosomeBase.cs @@ -0,0 +1,116 @@ +// AForge Genetic Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2006-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Genetic +{ + using System; + + /// + /// Chromosomes' base class. + /// + /// + /// The base class provides implementation of some + /// methods and properties, which are identical to all types of chromosomes. + /// + public abstract class ChromosomeBase : IChromosome + { + /// + /// Chromosome's fintess value. + /// + protected double fitness = 0; + + /// + /// Chromosome's fintess value. + /// + /// + /// Fitness value (usefulness) of the chromosome calculate by calling + /// method. The greater the value, the more useful the chromosome. + /// + /// + public double Fitness + { + get { return fitness; } + } + + /// + /// Generate random chromosome value. + /// + /// + /// Regenerates chromosome's value using random number generator. + /// + /// + public abstract void Generate( ); + + /// + /// Create new random chromosome with same parameters (factory method). + /// + /// + /// The method creates new chromosome of the same type, but randomly + /// initialized. The method is useful as factory method for those classes, which work + /// with chromosome's interface, but not with particular chromosome class. + /// + public abstract IChromosome CreateNew( ); + + /// + /// Clone the chromosome. + /// + /// + /// The method clones the chromosome returning the exact copy of it. + /// + /// + public abstract IChromosome Clone( ); + + /// + /// Mutation operator. + /// + /// + /// The method performs chromosome's mutation, changing its part randomly. + /// + public abstract void Mutate( ); + + /// + /// Crossover operator. + /// + /// + /// Pair chromosome to crossover with. + /// + /// The method performs crossover between two chromosomes – interchanging some parts of chromosomes. + /// + public abstract void Crossover( IChromosome pair ); + + /// + /// Evaluate chromosome with specified fitness function. + /// + /// + /// Fitness function to use for evaluation of the chromosome. + /// + /// Calculates chromosome's fitness using the specifed fitness function. + /// + public void Evaluate( IFitnessFunction function ) + { + fitness = function.Evaluate( this ); + } + + /// + /// Compare two chromosomes. + /// + /// + /// Binary chromosome to compare to. + /// + /// Returns comparison result, which equals to 0 if fitness values + /// of both chromosomes are equal, 1 if fitness value of this chromosome + /// is less than fitness value of the specified chromosome, -1 otherwise. + /// + public int CompareTo( object o ) + { + double f = ( (ChromosomeBase) o ).fitness; + + return ( fitness == f ) ? 0 : ( fitness < f ) ? 1 : -1; + } + } +} diff --git a/Sources/Accord.Genetic/Chromosomes/DoubleArrayChromosome.cs b/Sources/Accord.Genetic/Chromosomes/DoubleArrayChromosome.cs new file mode 100644 index 0000000000..660ed4836 --- /dev/null +++ b/Sources/Accord.Genetic/Chromosomes/DoubleArrayChromosome.cs @@ -0,0 +1,417 @@ +// AForge Genetic Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +namespace AForge.Genetic +{ + using System; + using System.Text; + using AForge; + using AForge.Math.Random; + + /// + /// Double array chromosome. + /// + /// + /// Double array chromosome represents array of double values. + /// Array length is in the range of [2, 65536]. + /// + /// + /// See documentation to and methods + /// for information regarding implemented mutation and crossover operators. + /// + /// + public class DoubleArrayChromosome : ChromosomeBase + { + /// + /// Chromosome generator. + /// + /// + /// This random number generator is used to initialize chromosome's genes, + /// which is done by calling method. + /// + protected IRandomNumberGenerator chromosomeGenerator; + + /// + /// Mutation multiplier generator. + /// + /// + /// This random number generator is used to generate random multiplier values, + /// which are used to multiply chromosome's genes during mutation. + /// + protected IRandomNumberGenerator mutationMultiplierGenerator; + + /// + /// Mutation addition generator. + /// + /// + /// This random number generator is used to generate random addition values, + /// which are used to add to chromosome's genes during mutation. + /// + protected IRandomNumberGenerator mutationAdditionGenerator; + + /// + /// Random number generator for crossover and mutation points selection. + /// + /// + /// This random number generator is used to select crossover + /// and mutation points. + /// + protected static ThreadSafeRandom rand = new ThreadSafeRandom( ); + + /// + /// Chromosome's maximum length. + /// + /// + /// Maxim chromosome's length in array elements. + /// + public const int MaxLength = 65536; + + /// + /// Chromosome's length in number of elements. + /// + private int length; + + /// + /// Chromosome's value. + /// + protected double[] val = null; + + // balancers to control type of mutation and crossover + private double mutationBalancer = 0.5; + private double crossoverBalancer = 0.5; + + /// + /// Chromosome's length. + /// + /// + /// Length of the chromosome in array elements. + /// + public int Length + { + get { return length; } + } + + /// + /// Chromosome's value. + /// + /// + /// Current value of the chromosome. + /// + public double[] Value + { + get { return val; } + } + + /// + /// Mutation balancer to control mutation type, [0, 1]. + /// + /// + /// The property controls type of mutation, which is used more + /// frequently. A radnom number is generated each time before doing mutation - + /// if the random number is smaller than the specified balance value, then one + /// mutation type is used, otherwse another. See method + /// for more information. + /// + /// Default value is set to 0.5. + /// + /// + public double MutationBalancer + { + get { return mutationBalancer; } + set { mutationBalancer = Math.Max( 0.0, Math.Min( 1.0, value ) ); } + } + + /// + /// Crossover balancer to control crossover type, [0, 1]. + /// + /// + /// The property controls type of crossover, which is used more + /// frequently. A radnom number is generated each time before doing crossover - + /// if the random number is smaller than the specified balance value, then one + /// crossover type is used, otherwse another. See method + /// for more information. + /// + /// Default value is set to 0.5. + /// + /// + public double CrossoverBalancer + { + get { return crossoverBalancer; } + set { crossoverBalancer = Math.Max( 0.0, Math.Min( 1.0, value ) ); } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Chromosome generator - random number generator, which is + /// used to initialize chromosome's genes, which is done by calling method + /// or in class constructor. + /// Mutation multiplier generator - random number + /// generator, which is used to generate random multiplier values, which are used to + /// multiply chromosome's genes during mutation. + /// Mutation addition generator - random number + /// generator, which is used to generate random addition values, which are used to + /// add to chromosome's genes during mutation. + /// Chromosome's length in array elements, [2, ]. + /// + /// The constructor initializes the new chromosome randomly by calling + /// method. + /// + public DoubleArrayChromosome( + IRandomNumberGenerator chromosomeGenerator, + IRandomNumberGenerator mutationMultiplierGenerator, + IRandomNumberGenerator mutationAdditionGenerator, + int length ) + { + + // save parameters + this.chromosomeGenerator = chromosomeGenerator; + this.mutationMultiplierGenerator = mutationMultiplierGenerator; + this.mutationAdditionGenerator = mutationAdditionGenerator; + this.length = Math.Max( 2, Math.Min( MaxLength, length ) ); ; + + // allocate array + val = new double[length]; + + // generate random chromosome + Generate( ); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Chromosome generator - random number generator, which is + /// used to initialize chromosome's genes, which is done by calling method + /// or in class constructor. + /// Mutation multiplier generator - random number + /// generator, which is used to generate random multiplier values, which are used to + /// multiply chromosome's genes during mutation. + /// Mutation addition generator - random number + /// generator, which is used to generate random addition values, which are used to + /// add to chromosome's genes during mutation. + /// Values used to initialize the chromosome. + /// + /// The constructor initializes the new chromosome with specified values. + /// + /// + /// Invalid length of values array. + /// + public DoubleArrayChromosome( + IRandomNumberGenerator chromosomeGenerator, + IRandomNumberGenerator mutationMultiplierGenerator, + IRandomNumberGenerator mutationAdditionGenerator, + double[] values ) + { + if ( ( values.Length < 2 ) || ( values.Length > MaxLength ) ) + throw new ArgumentOutOfRangeException( "Invalid length of values array." ); + + // save parameters + this.chromosomeGenerator = chromosomeGenerator; + this.mutationMultiplierGenerator = mutationMultiplierGenerator; + this.mutationAdditionGenerator = mutationAdditionGenerator; + this.length = values.Length; + + // copy specified values + val = (double[]) values.Clone( ); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Source chromosome to copy. + /// + /// This is a copy constructor, which creates the exact copy + /// of specified chromosome. + /// + public DoubleArrayChromosome( DoubleArrayChromosome source ) + { + this.chromosomeGenerator = source.chromosomeGenerator; + this.mutationMultiplierGenerator = source.mutationMultiplierGenerator; + this.mutationAdditionGenerator = source.mutationAdditionGenerator; + this.length = source.length; + this.fitness = source.fitness; + this.mutationBalancer = source.mutationBalancer; + this.crossoverBalancer = source.crossoverBalancer; + + // copy genes + val = (double[]) source.val.Clone( ); + } + + /// + /// Get string representation of the chromosome. + /// + /// + /// Returns string representation of the chromosome. + /// + public override string ToString( ) + { + StringBuilder sb = new StringBuilder( ); + + // append first gene + sb.Append( val[0] ); + // append all other genes + for ( int i = 1; i < length; i++ ) + { + sb.Append( ' ' ); + sb.Append( val[i] ); + } + + return sb.ToString( ); + } + + /// + /// Generate random chromosome value. + /// + /// + /// Regenerates chromosome's value using random number generator. + /// + /// + public override void Generate( ) + { + for ( int i = 0; i < length; i++ ) + { + // generate next value + val[i] = chromosomeGenerator.Next( ); + } + } + + /// + /// Create new random chromosome with same parameters (factory method). + /// + /// + /// The method creates new chromosome of the same type, but randomly + /// initialized. The method is useful as factory method for those classes, which work + /// with chromosome's interface, but not with particular chromosome type. + /// + public override IChromosome CreateNew( ) + { + return new DoubleArrayChromosome( chromosomeGenerator, mutationMultiplierGenerator, mutationAdditionGenerator, length ); + } + + /// + /// Clone the chromosome. + /// + /// + /// Return's clone of the chromosome. + /// + /// The method clones the chromosome returning the exact copy of it. + /// + /// + public override IChromosome Clone( ) + { + return new DoubleArrayChromosome( this ); + } + + /// + /// Mutation operator. + /// + /// + /// The method performs chromosome's mutation, adding random number + /// to chromosome's gene or multiplying the gene by random number. These random + /// numbers are generated with help of mutation + /// multiplier and mutation + /// addition generators. + /// + /// The exact type of mutation applied to the particular gene + /// is selected randomly each time and depends on . + /// Before mutation is done a random number is generated in [0, 1] range - if the + /// random number is smaller than , then multiplication + /// mutation is done, otherwise addition mutation. + /// + /// + public override void Mutate( ) + { + int mutationGene = rand.Next( length ); + + if ( rand.NextDouble( ) < mutationBalancer ) + { + val[mutationGene] *= mutationMultiplierGenerator.Next( ); + } + else + { + val[mutationGene] += mutationAdditionGenerator.Next( ); + } + } + + /// + /// Crossover operator. + /// + /// + /// Pair chromosome to crossover with. + /// + /// The method performs crossover between two chromosomes, selecting + /// randomly the exact type of crossover to perform, which depends on . + /// Before crossover is done a random number is generated in [0, 1] range - if the + /// random number is smaller than , then the first crossover + /// type is used, otherwise second type is used. + /// + /// The first crossover type is based on interchanging + /// range of genes (array elements) between these chromosomes and is known + /// as one point crossover. A crossover point is selected randomly and chromosomes + /// interchange genes, which start from the selected point. + /// + /// The second crossover type is aimed to produce one child, which genes' + /// values are between corresponding genes of parents, and another child, which genes' + /// values are outside of the range formed by corresponding genes of parents. + /// Let take, for example, two genes with 1.0 and 3.0 value (of course chromosomes have + /// more genes, but for simplicity lets think about one). First of all we randomly choose + /// a factor in the [0, 1] range, let's take 0.4. Then, for each pair of genes (we have + /// one pair) we calculate difference value, which is 2.0 in our case. In the result well + /// have two children one between and one outside of the range formed by parents genes' values. + /// We may have 1.8 and 3.8 children, or we may have 0.2 and 2.2 children. As we can see + /// we add/subtract (chosen randomly) difference * factor. So, this gives us exploration + /// in between and in near outside. The randomly chosen factor is applied to all genes + /// of the chromosomes participating in crossover. + /// + /// + public override void Crossover( IChromosome pair ) + { + DoubleArrayChromosome p = (DoubleArrayChromosome) pair; + + // check for correct pair + if ( ( p != null ) && ( p.length == length ) ) + { + if ( rand.NextDouble( ) < crossoverBalancer ) + { + // crossover point + int crossOverPoint = rand.Next( length - 1 ) + 1; + // length of chromosome to be crossed + int crossOverLength = length - crossOverPoint; + // temporary array + double[] temp = new double[crossOverLength]; + + // copy part of first (this) chromosome to temp + Array.Copy( val, crossOverPoint, temp, 0, crossOverLength ); + // copy part of second (pair) chromosome to the first + Array.Copy( p.val, crossOverPoint, val, crossOverPoint, crossOverLength ); + // copy temp to the second + Array.Copy( temp, 0, p.val, crossOverPoint, crossOverLength ); + } + else + { + double[] pairVal = p.val; + + double factor = rand.NextDouble( ); + if ( rand.Next( 2 ) == 0 ) + factor = -factor; + + for ( int i = 0; i < length; i++ ) + { + double portion = ( val[i] - pairVal[i] ) * factor; + + val[i] -= portion; + pairVal[i] += portion; + } + } + } + } + } +} diff --git a/Sources/Accord.Genetic/Chromosomes/GP/ExtendedGeneFunction.cs b/Sources/Accord.Genetic/Chromosomes/GP/ExtendedGeneFunction.cs new file mode 100644 index 0000000000..e0ab45414 --- /dev/null +++ b/Sources/Accord.Genetic/Chromosomes/GP/ExtendedGeneFunction.cs @@ -0,0 +1,290 @@ +// AForge Genetic Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +namespace AForge.Genetic +{ + using System; + using AForge; + + /// + /// Genetic programming gene, which represents arithmetic functions, common mathematical functions + /// and arguments. + /// + /// + /// Extended gene function may represent arithmetic functions (+, -, *, /), + /// some common mathematical functions (sin, cos, ln, exp, sqrt) or an argument to functions. + /// This class is used by Genetic Programming (or Gene Expression Programming) + /// chromosomes to build arbitrary expressions with help of genetic operators. + /// + /// + public class ExtendedGeneFunction : IGPGene + { + /// + /// Enumeration of supported functions. + /// + protected enum Functions + { + /// + /// Addition operator. + /// + Add, + /// + /// Suntraction operator. + /// + Subtract, + /// + /// Multiplication operator. + /// + Multiply, + /// + /// Division operator. + /// + Divide, + /// + /// Sine function. + /// + Sin, + /// + /// Cosine function. + /// + Cos, + /// + /// Natural logarithm function. + /// + Ln, + /// + /// Exponent function. + /// + Exp, + /// + /// Square root function. + /// + Sqrt + } + + /// + /// Number of different functions supported by the class. + /// + protected const int FunctionsCount = 9; + + // gene type + private GPGeneType type; + // total amount of variables in the task which is supposed to be solved + private int variablesCount; + // + private int val; + // arguments count + private int argumentsCount = 0; + + /// + /// Random number generator for chromosoms generation. + /// + protected static ThreadSafeRandom rand = new ThreadSafeRandom( ); + + /// + /// Gene type. + /// + /// + /// The property represents type of a gene - function, argument, etc. + /// + /// + public GPGeneType GeneType + { + get { return type; } + } + + /// + /// Arguments count. + /// + /// + /// Arguments count of a particular function gene. + /// + public int ArgumentsCount + { + get { return argumentsCount; } + } + + /// + /// Maximum arguments count. + /// + /// + /// Maximum arguments count of a function gene supported by the class. + /// The property may be used by chromosomes' classes to allocate correctly memory for + /// functions' arguments, for example. + /// + public int MaxArgumentsCount + { + get { return 2; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Total amount of variables in the task which is supposed + /// to be solved. + /// + /// The constructor creates randomly initialized gene with random type + /// and value by calling method. + /// + public ExtendedGeneFunction( int variablesCount ) : this( variablesCount, true ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Total amount of variables in the task which is supposed + /// to be solved. + /// Gene type to set. + /// + /// The constructor creates randomly initialized gene with random + /// value and preset gene type. + /// + public ExtendedGeneFunction( int variablesCount, GPGeneType type ) + { + this.variablesCount = variablesCount; + // generate the gene value + Generate( type ); + } + + // Private constructor + private ExtendedGeneFunction( int variablesCount, bool random ) + { + this.variablesCount = variablesCount; + // generate the gene value + if ( random ) + Generate( ); + } + + /// + /// Get string representation of the gene. + /// + /// + /// Returns string representation of the gene. + /// + public override string ToString( ) + { + if ( type == GPGeneType.Function ) + { + // get function string representation + switch ( (Functions) val ) + { + case Functions.Add: // addition + return "+"; + + case Functions.Subtract: // subtraction + return "-"; + + case Functions.Multiply: // multiplication + return "*"; + + case Functions.Divide: // division + return "/"; + + case Functions.Sin: // sine + return "sin"; + + case Functions.Cos: // cosine + return "cos"; + + case Functions.Ln: // natural logarithm + return "ln"; + + case Functions.Exp: // exponent + return "exp"; + + case Functions.Sqrt: // square root + return "sqrt"; + } + } + + // get argument string representation + return string.Format( "${0}", val ); + } + + /// + /// Clone the gene. + /// + /// + /// The method clones the chromosome returning the exact copy of it. + /// + public IGPGene Clone( ) + { + // create new gene ... + ExtendedGeneFunction clone = new ExtendedGeneFunction( variablesCount, false ); + // ... with the same type and value + clone.type = type; + clone.val = val; + clone.argumentsCount = argumentsCount; + + return clone; + } + + /// + /// Randomize gene with random type and value. + /// + /// + /// The method randomizes the gene, setting its type and value randomly. + /// + public void Generate( ) + { + // give more chance to function + Generate( ( rand.Next( 4 ) == 3 ) ? GPGeneType.Argument : GPGeneType.Function ); + } + + /// + /// Randomize gene with random value. + /// + /// + /// Gene type to set. + /// + /// The method randomizes a gene, setting its value randomly, but type + /// is set to the specified one. + /// + public void Generate( GPGeneType type ) + { + // gene type + this.type = type; + // gene value + val = rand.Next( ( type == GPGeneType.Function ) ? FunctionsCount : variablesCount ); + // arguments count + argumentsCount = ( type == GPGeneType.Argument ) ? 0 : + ( val <= (int) Functions.Divide ) ? 2 : 1; + } + + /// + /// Creates new gene with random type and value. + /// + /// + /// The method creates new randomly initialized gene . + /// The method is useful as factory method for those classes, which work with gene's interface, + /// but not with particular gene class. + /// + /// + public IGPGene CreateNew( ) + { + return new ExtendedGeneFunction( variablesCount ); + } + + /// + /// Creates new gene with certain type and random value. + /// + /// + /// Gene type to create. + /// + /// The method creates new gene with specified type, but random value. + /// The method is useful as factory method for those classes, which work with gene's interface, + /// but not with particular gene class. + /// + /// + public IGPGene CreateNew( GPGeneType type ) + { + return new ExtendedGeneFunction( variablesCount, type ); + } + } +} diff --git a/Sources/Accord.Genetic/Chromosomes/GP/GEPChromosome.cs b/Sources/Accord.Genetic/Chromosomes/GP/GEPChromosome.cs new file mode 100644 index 0000000000..d54e0b0af --- /dev/null +++ b/Sources/Accord.Genetic/Chromosomes/GP/GEPChromosome.cs @@ -0,0 +1,497 @@ +// AForge Genetic Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +namespace AForge.Genetic +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Text; + using AForge; + + /// + /// The chromosome represents a Gene Expression, which is used for + /// different tasks of Genetic Expression Programming (GEP). + /// + /// + /// This type of chromosome represents combination of ideas taken from + /// Genetic Algorithms (GA), where chromosomes are linear structures of fixed length, and + /// Genetic Programming (GP), where chromosomes are expression trees. The GEP chromosome + /// is also a fixed length linear structure, but with some additional features which + /// make it possible to generate valid expression tree from any GEP chromosome. + /// + /// The theory of Gene Expression Programming is well described in the next paper: + /// Ferreira, C., 2001. Gene Expression Programming: A New Adaptive Algorithm for Solving + /// Problems. Complex Systems, Vol. 13, issue 2: 87-129. A copy of the paper may be + /// obtained on the + /// gene expression programming web site. + /// + /// + public class GEPChromosome : ChromosomeBase + { + /// + /// Length of GEP chromosome's head. + /// + /// + /// GEP chromosome's head is a part of chromosome, which may contain both + /// functions' and arguments' nodes. The rest of chromosome (tail) may contain only arguments' nodes. + /// + /// + protected int headLength; + + /// + /// GEP chromosome's length. + /// + /// + /// The variable keeps chromosome's length, but not expression length represented by the + /// chromosome. + /// + protected int length; + + /// + /// Array of chromosome's genes. + /// + protected IGPGene[] genes; + + /// + /// Random generator used for chromosoms' generation. + /// + protected static ThreadSafeRandom rand = new ThreadSafeRandom( ); + + /// + /// Initializes a new instance of the class. + /// + /// + /// A gene, which is used as generator for the genetic tree. + /// Length of GEP chromosome's head (see ). + /// + /// This constructor creates a randomly generated GEP chromosome, + /// which has all genes of the same type and properties as the specified . + /// + /// + public GEPChromosome( IGPGene ancestor, int headLength ) + { + // store head length + this.headLength = headLength; + // calculate chromosome's length + length = headLength + headLength * ( ancestor.MaxArgumentsCount - 1 ) + 1; + // allocate genes array + genes = new IGPGene[length]; + // save ancestor as a temporary head + genes[0] = ancestor; + // generate the chromosome + Generate( ); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Source GEP chromosome to clone from. + /// + protected GEPChromosome( GEPChromosome source ) + { + headLength = source.headLength; + length = source.length; + fitness = source.fitness; + // allocate genes array + genes = new IGPGene[length]; + // copy genes + for ( int i = 0; i < length; i++ ) + genes[i] = source.genes[i].Clone( ); + } + + /// + /// Get string representation of the chromosome by providing its expression in + /// reverse polish notation (postfix notation). + /// + /// + /// Returns string representation of the expression represented by the GEP + /// chromosome. + /// + public override string ToString( ) + { + // return string representation of the chromosomes tree + return GetTree( ).ToString( ); + } + + /// + /// Get string representation of the chromosome. + /// + /// + /// Returns the chromosome in native linear representation. + /// + /// The method is used for debugging mostly. + /// + public string ToStringNative( ) + { + StringBuilder sb = new StringBuilder( ); + + foreach ( IGPGene gene in genes ) + { + sb.Append( gene.ToString( ) ); + sb.Append( " " ); + } + return sb.ToString( ); + } + + /// + /// Generate random chromosome value. + /// + /// + /// Regenerates chromosome's value using random number generator. + /// + /// + public override void Generate( ) + { + // randomize the root + genes[0].Generate( ); + // generate the rest of the head + for ( int i = 1; i < headLength; i++ ) + { + genes[i] = genes[0].CreateNew( ); + } + // generate the tail + for ( int i = headLength; i < length; i++ ) + { + genes[i] = genes[0].CreateNew( GPGeneType.Argument ); + } + } + + /// + /// Get tree representation of the chromosome. + /// + /// + /// Returns expression's tree represented by the chromosome. + /// + /// The method builds expression's tree for the native linear representation + /// of the GEP chromosome. + /// + protected GPTreeNode GetTree( ) + { + // function node queue. the queue contains function node, + // which requires children. when a function node receives + // all children, it will be removed from the queue + Queue functionNodes = new Queue(); + + // create root node + GPTreeNode root = new GPTreeNode( genes[0] ); + + // check children amount of the root node + if ( root.Gene.ArgumentsCount != 0 ) + { + root.Children = new List( ); + // place the root to the queue + functionNodes.Enqueue( root ); + + // go through genes + for ( int i = 1; i < length; i++ ) + { + // create new node + GPTreeNode node = new GPTreeNode( genes[i] ); + + // if next gene represents function, place it to the queue + if ( genes[i].GeneType == GPGeneType.Function ) + { + node.Children = new List( ); + functionNodes.Enqueue( node ); + } + + // get function node from the top of the queue + GPTreeNode parent = (GPTreeNode) functionNodes.Peek( ); + + // add new node to children of the parent node + parent.Children.Add( node ); + + // remove the parent node from the queue, if it is + // already complete + if ( parent.Children.Count == parent.Gene.ArgumentsCount ) + { + functionNodes.Dequeue( ); + + // check the queue if it is empty + if ( functionNodes.Count == 0 ) + break; + } + } + } + // return formed tree + return root; + } + + /// + /// Create new random chromosome with same parameters (factory method). + /// + /// + /// The method creates new chromosome of the same type, but randomly + /// initialized. The method is useful as factory method for those classes, which work + /// with chromosome's interface, but not with particular chromosome type. + /// + public override IChromosome CreateNew( ) + { + return new GEPChromosome( genes[0].Clone( ), headLength ); + } + + /// + /// Clone the chromosome. + /// + /// + /// Return's clone of the chromosome. + /// + /// The method clones the chromosome returning the exact copy of it. + /// + /// + public override IChromosome Clone( ) + { + return new GEPChromosome( this ); + } + + /// + /// Mutation operator. + /// + /// + /// The method performs chromosome's mutation by calling on of the methods + /// randomly: , , . + /// + /// + public override void Mutate( ) + { + // randomly choose mutation method + switch ( rand.Next( 3 ) ) + { + case 0: // ordinary gene mutation + MutateGene( ); + break; + + case 1: // IS transposition + TransposeIS( ); + break; + + case 2: // root transposition + TransposeRoot( ); + break; + } + } + + /// + /// Usual gene mutation. + /// + /// + /// The method performs usual gene mutation by randomly changing randomly selected + /// gene. + /// + protected void MutateGene( ) + { + // select random point of mutation + int mutationPoint = rand.Next( length ); + + if ( mutationPoint < headLength ) + { + // genes from head can be randomized freely (type may change) + genes[mutationPoint].Generate( ); + } + else + { + // genes from tail cannot change their type - they + // should be always arguments + genes[mutationPoint].Generate( GPGeneType.Argument ); + } + } + + /// + /// Transposition of IS elements (insertion sequence). + /// + /// + /// The method performs transposition of IS elements by copying randomly selected region + /// of genes into chromosome's head (into randomly selected position). First gene of the chromosome's head + /// is not affected - can not be selected as target point. + /// + protected void TransposeIS( ) + { + // select source point (may be any point of the chromosome) + int sourcePoint = rand.Next( length ); + // calculate maxim source length + int maxSourceLength = length - sourcePoint; + // select tartget insertion point in the head (except first position) + int targetPoint = rand.Next( headLength - 1 ) + 1; + // calculate maximum target length + int maxTargetLength = headLength - targetPoint; + // select randomly transposon length + int transposonLength = rand.Next( Math.Min( maxTargetLength, maxSourceLength ) ) + 1; + // genes copy + IGPGene[] genesCopy = new IGPGene[transposonLength]; + + // copy genes from source point + for ( int i = sourcePoint, j = 0; j < transposonLength; i++, j++ ) + { + genesCopy[j] = genes[i].Clone( ); + } + + // copy genes to target point + for ( int i = targetPoint, j = 0; j < transposonLength; i++, j++ ) + { + genes[i] = genesCopy[j]; + } + } + + /// + /// Root transposition. + /// + /// + /// The method performs root transposition of the GEP chromosome - inserting + /// new root of the chromosome and shifting existing one. The method first of all randomly selects + /// a function gene in chromosome's head - starting point of the sequence to put into chromosome's + /// head. Then it randomly selects the length of the sequence making sure that the entire sequence is + /// located within head. Once the starting point and the length of the sequence are known, it is copied + /// into chromosome's head shifting existing elements in the head. + /// + /// + protected void TransposeRoot( ) + { + // select source point (may be any point in the head of the chromosome) + int sourcePoint = rand.Next( headLength ); + // scan downsrteam the head searching for function gene + while ( ( genes[sourcePoint].GeneType != GPGeneType.Function ) && ( sourcePoint < headLength ) ) + { + sourcePoint++; + } + // return (do nothing) if function gene was not found + if ( sourcePoint == headLength ) + return; + + // calculate maxim source length + int maxSourceLength = headLength - sourcePoint; + // select randomly transposon length + int transposonLength = rand.Next( maxSourceLength ) + 1; + // genes copy + IGPGene[] genesCopy = new IGPGene[transposonLength]; + + // copy genes from source point + for ( int i = sourcePoint, j = 0; j < transposonLength; i++, j++ ) + { + genesCopy[j] = genes[i].Clone( ); + } + + // shift the head + for ( int i = headLength - 1; i >= transposonLength; i-- ) + { + genes[i] = genes[i - transposonLength]; + } + + // put new root + for ( int i = 0; i < transposonLength; i++ ) + { + genes[i] = genesCopy[i]; + } + } + + /// + /// Crossover operator. + /// + /// + /// Pair chromosome to crossover with. + /// + /// The method performs one-point or two-point crossover selecting + /// them randomly with equal probability. + /// + public override void Crossover( IChromosome pair ) + { + GEPChromosome p = (GEPChromosome) pair; + + // check for correct chromosome + if ( p != null ) + { + // choose recombination method + if ( rand.Next( 2 ) == 0 ) + { + RecombinationOnePoint( p ); + } + else + { + RecombinationTwoPoint( p ); + } + } + } + + /// + /// One-point recombination (crossover). + /// + /// + /// Pair chromosome to crossover with. + /// + public void RecombinationOnePoint( GEPChromosome pair ) + { + // check for correct pair + if ( ( pair.length == length ) ) + { + // crossover point + int crossOverPoint = rand.Next( length - 1 ) + 1; + // length of chromosome to be crossed + int crossOverLength = length - crossOverPoint; + + // swap parts of chromosomes + Recombine( genes, pair.genes, crossOverPoint, crossOverLength ); + } + } + + /// + /// Two point recombination (crossover). + /// + /// + /// Pair chromosome to crossover with. + /// + public void RecombinationTwoPoint( GEPChromosome pair ) + { + // check for correct pair + if ( ( pair.length == length ) ) + { + // crossover point + int crossOverPoint = rand.Next( length - 1 ) + 1; + // length of chromosome to be crossed + int crossOverLength = length - crossOverPoint; + + // if crossover length already equals to 1, then it becomes + // usual one point crossover. otherwise crossover length + // also randomly chosen + if ( crossOverLength != 1 ) + { + crossOverLength = rand.Next( crossOverLength - 1 ) + 1; + } + + // swap parts of chromosomes + Recombine( genes, pair.genes, crossOverPoint, crossOverLength ); + } + } + + /// + /// Swap parts of two chromosomes. + /// + /// + /// First chromosome participating in genes' interchange. + /// Second chromosome participating in genes' interchange. + /// Index of the first gene in the interchange sequence. + /// Length of the interchange sequence - number of genes + /// to interchange. + /// + /// The method performs interchanging of genes between two chromosomes + /// starting from the position. + /// + protected static void Recombine( IGPGene[] src1, IGPGene[] src2, int point, int length ) + { + // temporary array + IGPGene[] temp = new IGPGene[length]; + + // copy part of first chromosome to temp + Array.Copy( src1, point, temp, 0, length ); + // copy part of second chromosome to the first + Array.Copy( src2, point, src1, point, length ); + // copy temp to the second + Array.Copy( temp, 0, src2, point, length ); + } + } +} diff --git a/Sources/Accord.Genetic/Chromosomes/GP/GPTreeChromosome.cs b/Sources/Accord.Genetic/Chromosomes/GP/GPTreeChromosome.cs new file mode 100644 index 0000000000..62ec74d20 --- /dev/null +++ b/Sources/Accord.Genetic/Chromosomes/GP/GPTreeChromosome.cs @@ -0,0 +1,423 @@ +// AForge Genetic Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +namespace AForge.Genetic +{ + using System; + using System.Collections; + using System.Collections.Generic; + using AForge; + + /// + /// Tree chromosome represents a tree of genes, which is is used for + /// different tasks of Genetic Programming (GP). + /// + /// + /// This type of chromosome represents a tree, where each node + /// is represented by containing . + /// Depending on type of genes used to build the tree, it may represent different + /// types of expressions aimed to solve different type of tasks. For example, a + /// particular implementation of interface may represent + /// simple algebraic operations and their arguments. + /// + /// + /// See documentation to implementations for additional + /// information about possible Genetic Programming trees. + /// + /// + public class GPTreeChromosome : ChromosomeBase + { + // tree root + private GPTreeNode root = new GPTreeNode( ); + + // maximum initial level of the tree + private static int maxInitialLevel = 3; + // maximum level of the tree + private static int maxLevel = 5; + + /// + /// Random generator used for chromosoms' generation. + /// + protected static ThreadSafeRandom rand = new ThreadSafeRandom( ); + + /// + /// Maximum initial level of genetic trees, [1, 25]. + /// + /// + /// The property sets maximum possible initial depth of new + /// genetic programming tree. For example, if it is set to 1, then largest initial + /// tree may have a root and one level of children. + /// + /// Default value is set to 3. + /// + /// + public static int MaxInitialLevel + { + get { return maxInitialLevel; } + set { maxInitialLevel = Math.Max( 1, Math.Min( 25, value ) ); } + } + + /// + /// Maximum level of genetic trees, [1, 50]. + /// + /// + /// The property sets maximum possible depth of + /// genetic programming tree, which may be created with mutation and crossover operators. + /// This property guarantees that genetic programmin tree will never have + /// higher depth, than the specified value. + /// + /// Default value is set to 5. + /// + /// + public static int MaxLevel + { + get { return maxLevel; } + set { maxLevel = Math.Max( 1, Math.Min( 50, value ) ); } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// A gene, which is used as generator for the genetic tree. + /// + /// This constructor creates a randomly generated genetic tree, + /// which has all genes of the same type and properties as the specified . + /// + /// + public GPTreeChromosome( IGPGene ancestor ) + { + // make the ancestor gene to be as temporary root of the tree + root.Gene = ancestor.Clone( ); + // call tree regeneration function + Generate( ); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Source genetic tree to clone from. + /// + /// This constructor creates new genetic tree as a copy of the + /// specified tree. + /// + protected GPTreeChromosome( GPTreeChromosome source ) + { + root = (GPTreeNode) source.root.Clone( ); + fitness = source.fitness; + } + + /// + /// Get string representation of the chromosome by providing its expression in + /// reverse polish notation (postfix notation). + /// + /// + /// Returns string representation of the genetic tree. + /// + /// The method returns string representation of the tree's root node + /// (see ). + /// + public override string ToString( ) + { + return root.ToString( ); + } + + /// + /// Generate random chromosome value. + /// + /// + /// Regenerates chromosome's value using random number generator. + /// + /// + public override void Generate( ) + { + // randomize the root + root.Gene.Generate( ); + // create children + if ( root.Gene.ArgumentsCount != 0 ) + { + root.Children = new List( ); + for ( int i = 0; i < root.Gene.ArgumentsCount; i++ ) + { + // create new child + GPTreeNode child = new GPTreeNode( ); + Generate( child, rand.Next( maxInitialLevel ) ); + // add the new child + root.Children.Add( child ); + } + } + } + + /// + /// Generate chromosome's subtree of specified level. + /// + /// + /// Sub tree's node to generate. + /// Sub tree's level to generate. + /// + protected void Generate( GPTreeNode node, int level ) + { + // create gene for the node + if ( level == 0 ) + { + // the gene should be an argument + node.Gene = root.Gene.CreateNew( GPGeneType.Argument ); + } + else + { + // the gene can be function or argument + node.Gene = root.Gene.CreateNew( ); + } + + // add children + if ( node.Gene.ArgumentsCount != 0 ) + { + node.Children = new List( ); + for ( int i = 0; i < node.Gene.ArgumentsCount; i++ ) + { + // create new child + GPTreeNode child = new GPTreeNode( ); + Generate( child, level - 1 ); + // add the new child + node.Children.Add( child ); + } + } + } + + /// + /// Create new random chromosome with same parameters (factory method). + /// + /// + /// The method creates new chromosome of the same type, but randomly + /// initialized. The method is useful as factory method for those classes, which work + /// with chromosome's interface, but not with particular chromosome type. + /// + public override IChromosome CreateNew( ) + { + return new GPTreeChromosome( root.Gene.Clone( ) ); + } + + /// + /// Clone the chromosome. + /// + /// + /// Return's clone of the chromosome. + /// + /// The method clones the chromosome returning the exact copy of it. + /// + /// + public override IChromosome Clone( ) + { + return new GPTreeChromosome( this ); + } + + /// + /// Mutation operator. + /// + /// + /// The method performs chromosome's mutation by regenerating tree's + /// randomly selected node. + /// + public override void Mutate( ) + { + // current tree level + int currentLevel = 0; + // current node + GPTreeNode node = root; + + for ( ; ; ) + { + // regenerate node if it does not have children + if ( node.Children == null ) + { + if ( currentLevel == maxLevel ) + { + // we reached maximum possible level, so the gene + // can be an argument only + node.Gene.Generate( GPGeneType.Argument ); + } + else + { + // generate subtree + Generate( node, rand.Next( maxLevel - currentLevel ) ); + } + break; + } + + // if it is a function node, than we need to get a decision, about + // mutation point - the node itself or one of its children + int r = rand.Next( node.Gene.ArgumentsCount + 1 ); + + if ( r == node.Gene.ArgumentsCount ) + { + // node itself should be regenerated + node.Gene.Generate( ); + + // check current type + if ( node.Gene.GeneType == GPGeneType.Argument ) + { + node.Children = null; + } + else + { + // create children's list if it was absent + if ( node.Children == null ) + node.Children = new List( ); + + // check for missing or extra children + if ( node.Children.Count != node.Gene.ArgumentsCount ) + { + if ( node.Children.Count > node.Gene.ArgumentsCount ) + { + // remove extra children + node.Children.RemoveRange( node.Gene.ArgumentsCount, node.Children.Count - node.Gene.ArgumentsCount ); + } + else + { + // add missing children + for ( int i = node.Children.Count; i < node.Gene.ArgumentsCount; i++ ) + { + // create new child + GPTreeNode child = new GPTreeNode( ); + Generate( child, rand.Next( maxLevel - currentLevel ) ); + // add the new child + node.Children.Add( child ); + } + } + } + } + break; + } + + // mutation goes further to one of the children + node = (GPTreeNode) node.Children[r]; + currentLevel++; + } + } + + /// + /// Crossover operator. + /// + /// + /// Pair chromosome to crossover with. + /// + /// The method performs crossover between two chromosomes interchanging + /// randomly selected sub trees. + /// + public override void Crossover( IChromosome pair ) + { + GPTreeChromosome p = (GPTreeChromosome) pair; + + // check for correct pair + if ( p != null ) + { + // do we need to use root node for crossover ? + if ( ( root.Children == null ) || ( rand.Next( maxLevel ) == 0 ) ) + { + // give the root to the pair and use pair's part as a new root + root = p.RandomSwap( root ); + } + else + { + GPTreeNode node = root; + + for ( ; ; ) + { + // choose random child + int r = rand.Next( node.Gene.ArgumentsCount ); + GPTreeNode child = (GPTreeNode) node.Children[r]; + + // swap the random node, if it is an end node or + // random generator "selected" this node + if ( ( child.Children == null ) || ( rand.Next( maxLevel ) == 0 ) ) + { + // swap the node with pair's one + node.Children[r] = p.RandomSwap( child ); + break; + } + + // go further by tree + node = child; + } + } + // trim both of them + Trim( root, maxLevel ); + Trim( p.root, maxLevel ); + } + } + + /// + /// Crossover helper routine - selects random node of chromosomes tree and + /// swaps it with specified node. + /// + private GPTreeNode RandomSwap( GPTreeNode source ) + { + GPTreeNode retNode = null; + + // swap root node ? + if ( ( root.Children == null ) || ( rand.Next( maxLevel ) == 0 ) ) + { + // replace current root and return it + retNode = root; + root = source; + } + else + { + GPTreeNode node = root; + + for ( ; ; ) + { + // choose random child + int r = rand.Next( node.Gene.ArgumentsCount ); + GPTreeNode child = (GPTreeNode) node.Children[r]; + + // swap the random node, if it is an end node or + // random generator "selected" this node + if ( ( child.Children == null ) || ( rand.Next( maxLevel ) == 0 ) ) + { + // swap the node with pair's one + retNode = child; + node.Children[r] = source; + break; + } + + // go further by tree + node = child; + } + } + return retNode; + } + + /// + /// Trim tree node, so its depth does not exceed specified level. + /// + private static void Trim( GPTreeNode node, int level ) + { + // check if the node has children + if ( node.Children != null ) + { + if ( level == 0 ) + { + // remove all children + node.Children = null; + // and make the node of argument type + node.Gene.Generate( GPGeneType.Argument ); + } + else + { + // go further to children + foreach ( GPTreeNode n in node.Children ) + { + Trim( n, level - 1 ); + } + } + } + } + } +} diff --git a/Sources/Accord.Genetic/Chromosomes/GP/GPTreeNode.cs b/Sources/Accord.Genetic/Chromosomes/GP/GPTreeNode.cs new file mode 100644 index 0000000000..49629f075 --- /dev/null +++ b/Sources/Accord.Genetic/Chromosomes/GP/GPTreeNode.cs @@ -0,0 +1,114 @@ +// AForge Genetic Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2006-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Genetic +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Text; + + /// + /// Represents tree node of genetic programming tree. + /// + /// + /// In genetic programming a chromosome is represented by a tree, which + /// is represented by class. The + /// class represents single node of such genetic programming tree. + /// + /// Each node may or may not have children. This means that particular node of a genetic + /// programming tree may represent its sub tree or even entire tree. + /// + /// + public class GPTreeNode : ICloneable + { + /// + /// Gene represented by the chromosome. + /// + public IGPGene Gene; + + /// + /// List of node's children. + /// + public List Children; + + /// + /// Initializes a new instance of the class. + /// + /// + internal GPTreeNode( ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + public GPTreeNode( IGPGene gene ) + { + Gene = gene; + } + + /// + /// Get string representation of the node. + /// + /// + /// Returns string representation of the node. + /// + /// String representation of the node lists all node's children and + /// then the node itself. Such node's string representations equals to + /// its reverse polish notation. + /// + /// For example, if nodes value is '+' and its children are '3' and '5', then + /// nodes string representation is "3 5 +". + /// + /// + public override string ToString( ) + { + StringBuilder sb = new StringBuilder( ); + + if ( Children != null ) + { + // walk through all nodes + foreach ( GPTreeNode node in Children ) + { + sb.Append( node.ToString( ) ); + } + } + + // add gene value + sb.Append( Gene.ToString( ) ); + sb.Append( " " ); + + return sb.ToString( ); + } + + /// + /// Clone the tree node. + /// + /// + /// Returns exact clone of the node. + /// + public object Clone( ) + { + GPTreeNode clone = new GPTreeNode( ); + + // clone gene + clone.Gene = this.Gene.Clone( ); + // clone its children + if ( this.Children != null ) + { + clone.Children = new List( ); + // clone each child gene + foreach ( GPTreeNode node in Children ) + { + clone.Children.Add( (GPTreeNode) node.Clone( ) ); + } + } + return clone; + } + } +} diff --git a/Sources/Accord.Genetic/Chromosomes/GP/IGPGene.cs b/Sources/Accord.Genetic/Chromosomes/GP/IGPGene.cs new file mode 100644 index 0000000000..85389ddde --- /dev/null +++ b/Sources/Accord.Genetic/Chromosomes/GP/IGPGene.cs @@ -0,0 +1,117 @@ +// AForge Genetic Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2006-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Genetic +{ + using System; + + /// + /// Types of genes in Genetic Programming. + /// + public enum GPGeneType + { + /// + /// Function gene - represents function to be executed. + /// + Function, + /// + /// Argument gene - represents argument of function. + /// + Argument + } + + + /// + /// Genetic Programming's gene interface. + /// + /// + /// This is a gene interface, which is used for building chromosomes + /// in Genetic Programming (GP) and Gene Expression Programming (GEP). + /// + /// + public interface IGPGene + { + /// + /// Gene type. + /// + /// + /// The property represents type of a gene - function, argument, etc. + /// + /// + GPGeneType GeneType { get; } + + /// + /// Arguments count. + /// + /// + /// Arguments count of a particular function gene. + /// + int ArgumentsCount { get; } + + /// + /// Maximum arguments count. + /// + /// + /// Maximum arguments count of a function gene. The property may be used + /// by chromosomes' classes to allocate correctly memory for functions' arguments, + /// for example. + /// + int MaxArgumentsCount { get; } + + /// + /// Clone gene. + /// + /// + /// The method clones gene returning the exact copy of it. + /// + IGPGene Clone( ); + + /// + /// Randomize gene with random type and value. + /// + /// + /// The method randomizes a gene, setting its type and value randomly. + /// + void Generate( ); + + /// + /// Randomize gene with random value. + /// + /// + /// Gene type to set. + /// + /// The method randomizes a gene, setting its value randomly, but type + /// is set to the specified one. + /// + void Generate( GPGeneType type ); + + /// + /// Creates new gene with random type and value. + /// + /// + /// The method creates new randomly initialized gene . + /// The method is useful as factory method for those classes, which work with gene's interface, + /// but not with particular gene class. + /// + /// + IGPGene CreateNew( ); + + /// + /// Creates new gene with certain type and random value. + /// + /// + /// Gene type to create. + /// + /// The method creates new gene with specified type, but random value. + /// The method is useful as factory method for those classes, which work with gene's interface, + /// but not with particular gene class. + /// + /// + IGPGene CreateNew( GPGeneType type ); + } +} diff --git a/Sources/Accord.Genetic/Chromosomes/GP/SimpleGeneFunction.cs b/Sources/Accord.Genetic/Chromosomes/GP/SimpleGeneFunction.cs new file mode 100644 index 0000000000..21f99ff47 --- /dev/null +++ b/Sources/Accord.Genetic/Chromosomes/GP/SimpleGeneFunction.cs @@ -0,0 +1,248 @@ +// AForge Genetic Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +namespace AForge.Genetic +{ + using System; + using AForge; + + /// + /// Genetic programming gene, which represents simple arithmetic functions and arguments. + /// + /// + /// Simple gene function may represent an arithmetic function (+, -, *, /) or + /// an argument to function. This class is used by Genetic Programming (or Gene Expression Programming) + /// chromosomes to build arbitrary expressions with help of genetic operators. + /// + /// + public class SimpleGeneFunction : IGPGene + { + /// + /// Enumeration of supported functions. + /// + protected enum Functions + { + /// + /// Addition operator. + /// + Add, + /// + /// Suntraction operator. + /// + Subtract, + /// + /// Multiplication operator. + /// + Multiply, + /// + /// Division operator. + /// + Divide, + } + + /// + /// Number of different functions supported by the class. + /// + protected const int FunctionsCount = 4; + + // gene type + private GPGeneType type; + // total amount of variables in the task which is supposed to be solved + private int variablesCount; + // + private int val; + + /// + /// Random number generator for chromosoms generation. + /// + protected static ThreadSafeRandom rand = new ThreadSafeRandom( ); + + /// + /// Gene type. + /// + /// + /// The property represents type of a gene - function, argument, etc. + /// + /// + public GPGeneType GeneType + { + get { return type; } + } + + /// + /// Arguments count. + /// + /// + /// Arguments count of a particular function gene. + /// + public int ArgumentsCount + { + get { return ( type == GPGeneType.Argument ) ? 0 : 2; } + } + + /// + /// Maximum arguments count. + /// + /// + /// Maximum arguments count of a function gene supported by the class. + /// The property may be used by chromosomes' classes to allocate correctly memory for + /// functions' arguments, for example. + /// + public int MaxArgumentsCount + { + get { return 2; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Total amount of variables in the task which is supposed + /// to be solved. + /// + /// The constructor creates randomly initialized gene with random type + /// and value by calling method. + /// + public SimpleGeneFunction( int variablesCount ) : this( variablesCount, true ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Total amount of variables in the task which is supposed + /// to be solved. + /// Gene type to set. + /// + /// The constructor creates randomly initialized gene with random + /// value and preset gene type. + /// + public SimpleGeneFunction( int variablesCount, GPGeneType type ) + { + this.variablesCount = variablesCount; + // generate the gene value + Generate( type ); + } + + // Private constructor + private SimpleGeneFunction( int variablesCount, bool random ) + { + this.variablesCount = variablesCount; + // generate the gene value + if ( random ) + Generate( ); + } + + /// + /// Get string representation of the gene. + /// + /// + /// Returns string representation of the gene. + /// + public override string ToString( ) + { + if ( type == GPGeneType.Function ) + { + // get function string representation + switch ( (Functions) val ) + { + case Functions.Add: // addition + return "+"; + + case Functions.Subtract: // subtraction + return "-"; + + case Functions.Multiply: // multiplication + return "*"; + + case Functions.Divide: // division + return "/"; + } + } + + // get argument string representation + return string.Format( "${0}", val ); + } + + /// + /// Clone the gene. + /// + /// + /// The method clones the chromosome returning the exact copy of it. + /// + public IGPGene Clone( ) + { + // create new gene ... + SimpleGeneFunction clone = new SimpleGeneFunction( variablesCount, false ); + // ... with the same type and value + clone.type = type; + clone.val = val; + + return clone; + } + + /// + /// Randomize gene with random type and value. + /// + /// + /// The method randomizes the gene, setting its type and value randomly. + /// + public void Generate( ) + { + // give more chance to function + Generate( ( rand.Next( 4 ) == 3 ) ? GPGeneType.Argument : GPGeneType.Function ); + } + + /// + /// Randomize gene with random value. + /// + /// + /// Gene type to set. + /// + /// The method randomizes a gene, setting its value randomly, but type + /// is set to the specified one. + /// + public void Generate( GPGeneType type ) + { + // gene type + this.type = type; + // gene value + val = rand.Next( ( type == GPGeneType.Function ) ? FunctionsCount : variablesCount ); + + } + + /// + /// Creates new gene with random type and value. + /// + /// + /// The method creates new randomly initialized gene . + /// The method is useful as factory method for those classes, which work with gene's interface, + /// but not with particular gene class. + /// + /// + public IGPGene CreateNew( ) + { + return new SimpleGeneFunction( variablesCount ); + } + + /// + /// Creates new gene with certain type and random value. + /// + /// + /// Gene type to create. + /// + /// The method creates new gene with specified type, but random value. + /// The method is useful as factory method for those classes, which work with gene's interface, + /// but not with particular gene class. + /// + /// + public IGPGene CreateNew( GPGeneType type ) + { + return new SimpleGeneFunction( variablesCount, type ); + } + } +} diff --git a/Sources/Accord.Genetic/Chromosomes/IChromosome.cs b/Sources/Accord.Genetic/Chromosomes/IChromosome.cs new file mode 100644 index 0000000000..0ea894920 --- /dev/null +++ b/Sources/Accord.Genetic/Chromosomes/IChromosome.cs @@ -0,0 +1,87 @@ +// AForge Genetic Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2006-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Genetic +{ + using System; + + /// + /// Chromosome interface. + /// + /// + /// The interfase should be implemented by all classes, which implement + /// particular chromosome type. + /// + public interface IChromosome : IComparable + { + /// + /// Chromosome's fintess value. + /// + /// + /// The fitness value represents chromosome's usefulness - the greater the + /// value, the more useful it. + /// + double Fitness { get; } + + /// + /// Generate random chromosome value. + /// + /// + /// Regenerates chromosome's value using random number generator. + /// + /// + void Generate( ); + + /// + /// Create new random chromosome with same parameters (factory method). + /// + /// + /// The method creates new chromosome of the same type, but randomly + /// initialized. The method is useful as factory method for those classes, which work + /// with chromosome's interface, but not with particular chromosome class. + /// + IChromosome CreateNew( ); + + /// + /// Clone the chromosome. + /// + /// + /// The method clones the chromosome returning the exact copy of it. + /// + /// + IChromosome Clone( ); + + /// + /// Mutation operator. + /// + /// + /// The method performs chromosome's mutation, changing its part randomly. + /// + void Mutate( ); + + /// + /// Crossover operator. + /// + /// + /// Pair chromosome to crossover with. + /// + /// The method performs crossover between two chromosomes interchanging some parts of chromosomes. + /// + void Crossover( IChromosome pair ); + + /// + /// Evaluate chromosome with specified fitness function. + /// + /// + /// Fitness function to use for evaluation of the chromosome. + /// + /// Calculates chromosome's fitness using the specifed fitness function. + /// + void Evaluate( IFitnessFunction function ); + } +} diff --git a/Sources/Accord.Genetic/Chromosomes/PermutationChromosome.cs b/Sources/Accord.Genetic/Chromosomes/PermutationChromosome.cs new file mode 100644 index 0000000000..33369ddd5 --- /dev/null +++ b/Sources/Accord.Genetic/Chromosomes/PermutationChromosome.cs @@ -0,0 +1,234 @@ +// AForge Genetic Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2010 +// contacts@aforgenet.com +// + +namespace AForge.Genetic +{ + using System; + using System.Collections.Generic; + + /// + /// Permutation chromosome. + /// + /// + /// Permutation chromosome is based on short array chromosome, + /// but has two features: + /// + /// all genes are unique within chromosome, i.e. there are no two genes + /// with the same value; + /// maximum value of each gene is equal to chromosome length minus 1. + /// + /// + /// + public class PermutationChromosome : ShortArrayChromosome + { + /// + /// Initializes a new instance of the class. + /// + public PermutationChromosome( int length ) : base( length, length - 1 ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Source chromosome to copy. + /// + /// This is a copy constructor, which creates the exact copy + /// of specified chromosome. + /// + protected PermutationChromosome( PermutationChromosome source ) : base( source ) { } + + /// + /// Generate random chromosome value. + /// + /// + /// Regenerates chromosome's value using random number generator. + /// + /// + public override void Generate( ) + { + // create ascending permutation initially + for ( int i = 0; i < length; i++ ) + { + val[i] = (ushort) i; + } + + // shufle the permutation + for ( int i = 0, n = length >> 1; i < n; i++ ) + { + ushort t; + int j1 = rand.Next( length ); + int j2 = rand.Next( length ); + + // swap values + t = val[j1]; + val[j1] = val[j2]; + val[j2] = t; + } + } + + /// + /// Create new random chromosome with same parameters (factory method). + /// + /// + /// The method creates new chromosome of the same type, but randomly + /// initialized. The method is useful as factory method for those classes, which work + /// with chromosome's interface, but not with particular chromosome type. + /// + public override IChromosome CreateNew( ) + { + return new PermutationChromosome( length ); + } + + /// + /// Clone the chromosome. + /// + /// + /// Return's clone of the chromosome. + /// + /// The method clones the chromosome returning the exact copy of it. + /// + /// + public override IChromosome Clone( ) + { + return new PermutationChromosome( this ); + } + + /// + /// Mutation operator. + /// + /// + /// The method performs chromosome's mutation, swapping two randomly + /// chosen genes (array elements). + /// + public override void Mutate( ) + { + ushort t; + int j1 = rand.Next( length ); + int j2 = rand.Next( length ); + + // swap values + t = val[j1]; + val[j1] = val[j2]; + val[j2] = t; + } + + /// + /// Crossover operator. + /// + /// + /// Pair chromosome to crossover with. + /// + /// The method performs crossover between two chromosomes interchanging + /// some parts between these chromosomes. + /// + public override void Crossover( IChromosome pair ) + { + PermutationChromosome p = (PermutationChromosome) pair; + + // check for correct pair + if ( ( p != null ) && ( p.length == length ) ) + { + ushort[] child1 = new ushort[length]; + ushort[] child2 = new ushort[length]; + + // create two children + CreateChildUsingCrossover( this.val, p.val, child1 ); + CreateChildUsingCrossover( p.val, this.val, child2 ); + + // replace parents with children + this.val = child1; + p.val = child2; + } + } + + // Produce new child applying crossover to two parents + private void CreateChildUsingCrossover( ushort[] parent1, ushort[] parent2, ushort[] child ) + { + ushort[] indexDictionary1 = CreateIndexDictionary( parent1 ); + ushort[] indexDictionary2 = CreateIndexDictionary( parent2 ); + + // temporary array to specify if certain gene already + // present in the child + bool[] geneIsBusy = new bool[length]; + // previous gene in the child and two next candidates + ushort prev, next1, next2; + // candidates validness - candidate is valid, if it is not + // yet in the child + bool valid1, valid2; + + int j, k = length - 1; + + // first gene of the child is taken from the second parent + prev = child[0] = parent2[0]; + geneIsBusy[prev] = true; + + // resolve all other genes of the child + for ( int i = 1; i < length; i++ ) + { + // find the next gene after PREV in both parents + // 1 + j = indexDictionary1[prev]; + next1 = ( j == k ) ? parent1[0] : parent1[j + 1]; + // 2 + j = indexDictionary2[prev]; + next2 = ( j == k ) ? parent2[0] : parent2[j + 1]; + + // check candidate genes for validness + valid1 = !geneIsBusy[next1]; + valid2 = !geneIsBusy[next2]; + + // select gene + if ( valid1 && valid2 ) + { + // both candidates are valid + // select one of theme randomly + prev = ( rand.Next( 2 ) == 0 ) ? next1 : next2; + } + else if ( !( valid1 || valid2 ) ) + { + // none of candidates is valid, so + // select random gene which is not in the child yet + int r = j = rand.Next( length ); + + // go down first + while ( ( r < length ) && ( geneIsBusy[r] == true ) ) + r++; + if ( r == length ) + { + // not found, try to go up + r = j - 1; + while ( geneIsBusy[r] == true ) // && ( r >= 0 ) + r--; + } + prev = (ushort) r; + } + else + { + // one of candidates is valid + prev = ( valid1 ) ? next1 : next2; + } + + child[i] = prev; + geneIsBusy[prev] = true; + } + } + + // Create dictionary for fast lookup of genes' indexes + private static ushort[] CreateIndexDictionary( ushort[] genes ) + { + ushort[] indexDictionary = new ushort[genes.Length]; + + for ( int i = 0, n = genes.Length; i < n; i++ ) + { + indexDictionary[genes[i]] = (ushort) i; + } + + return indexDictionary; + } + } +} diff --git a/Sources/Accord.Genetic/Chromosomes/ShortArrayChromosome.cs b/Sources/Accord.Genetic/Chromosomes/ShortArrayChromosome.cs new file mode 100644 index 0000000000..2210dae7e --- /dev/null +++ b/Sources/Accord.Genetic/Chromosomes/ShortArrayChromosome.cs @@ -0,0 +1,250 @@ +// AForge Genetic Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +namespace AForge.Genetic +{ + using System; + using System.Text; + using AForge; + + /// + /// Short array chromosome. + /// + /// + /// Short array chromosome represents array of unsigned short values. + /// Array length is in the range of [2, 65536]. + /// + // + public class ShortArrayChromosome : ChromosomeBase + { + /// + /// Chromosome's length in number of elements. + /// + protected int length; + + /// + /// Maximum value of chromosome's gene (element). + /// + protected int maxValue; + + /// + /// Chromosome's value. + /// + protected ushort[] val = null; + + /// + /// Random number generator for chromosoms generation, crossover, mutation, etc. + /// + protected static ThreadSafeRandom rand = new ThreadSafeRandom( ); + + /// + /// Chromosome's maximum length. + /// + /// + /// Maxim chromosome's length in array elements. + /// + public const int MaxLength = 65536; + + /// + /// Chromosome's length. + /// + /// + /// Length of the chromosome in array elements. + /// + public int Length + { + get { return length; } + } + + /// + /// Chromosome's value. + /// + /// + /// Current value of the chromosome. + /// + public ushort[] Value + { + get { return val; } + } + + /// + /// Max possible value of single chromosomes element - gene. + /// + /// + /// Maximum possible numerical value, which may be represented + /// by single chromosome's gene (array element). + /// + public int MaxValue + { + get { return maxValue; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Chromosome's length in array elements, [2, ]. + /// + /// This constructor initializes chromosome setting genes' maximum value to + /// maximum posible value of type. + /// + public ShortArrayChromosome( int length ) : this( length, ushort.MaxValue ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Chromosome's length in array elements, [2, ]. + /// Maximum value of chromosome's gene (array element). + /// + public ShortArrayChromosome( int length, int maxValue ) + { + // save parameters + this.length = Math.Max( 2, Math.Min( MaxLength, length ) ); + this.maxValue = Math.Max( 1, Math.Min( ushort.MaxValue, maxValue ) ); + + // allocate array + val = new ushort[this.length]; + + // generate random chromosome + Generate( ); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Source chromosome to copy. + /// + /// This is a copy constructor, which creates the exact copy + /// of specified chromosome. + /// + protected ShortArrayChromosome( ShortArrayChromosome source ) + { + // copy all properties + length = source.length; + maxValue = source.maxValue; + val = (ushort[]) source.val.Clone( ); + fitness = source.fitness; + } + + /// + /// Get string representation of the chromosome. + /// + /// + /// Returns string representation of the chromosome. + /// + public override string ToString( ) + { + StringBuilder sb = new StringBuilder( ); + + // append first gene + sb.Append( val[0] ); + // append all other genes + for ( int i = 1; i < length; i++ ) + { + sb.Append( ' ' ); + sb.Append( val[i] ); + } + + return sb.ToString( ); + } + + /// + /// Generate random chromosome value. + /// + /// + /// Regenerates chromosome's value using random number generator. + /// + /// + public override void Generate( ) + { + int max = maxValue + 1; + + for ( int i = 0; i < length; i++ ) + { + // generate next value + val[i] = (ushort) rand.Next( max ); + } + } + + /// + /// Create new random chromosome with same parameters (factory method). + /// + /// + /// The method creates new chromosome of the same type, but randomly + /// initialized. The method is useful as factory method for those classes, which work + /// with chromosome's interface, but not with particular chromosome type. + /// + public override IChromosome CreateNew( ) + { + return new ShortArrayChromosome( length, maxValue ); + } + + /// + /// Clone the chromosome. + /// + /// + /// Return's clone of the chromosome. + /// + /// The method clones the chromosome returning the exact copy of it. + /// + /// + public override IChromosome Clone( ) + { + return new ShortArrayChromosome( this ); + } + + /// + /// Mutation operator. + /// + /// + /// The method performs chromosome's mutation, changing randomly + /// one of its genes (array elements). + /// + public override void Mutate( ) + { + // get random index + int i = rand.Next( length ); + // randomize the gene + val[i] = (ushort) rand.Next( maxValue + 1 ); + } + + /// + /// Crossover operator. + /// + /// + /// Pair chromosome to crossover with. + /// + /// The method performs crossover between two chromosomes interchanging + /// range of genes (array elements) between these chromosomes. + /// + public override void Crossover( IChromosome pair ) + { + ShortArrayChromosome p = (ShortArrayChromosome) pair; + + // check for correct pair + if ( ( p != null ) && ( p.length == length ) ) + { + // crossover point + int crossOverPoint = rand.Next( length - 1 ) + 1; + // length of chromosome to be crossed + int crossOverLength = length - crossOverPoint; + // temporary array + ushort[] temp = new ushort[crossOverLength]; + + // copy part of first (this) chromosome to temp + Array.Copy( val, crossOverPoint, temp, 0, crossOverLength ); + // copy part of second (pair) chromosome to the first + Array.Copy( p.val, crossOverPoint, val, crossOverPoint, crossOverLength ); + // copy temp to the second + Array.Copy( temp, 0, p.val, crossOverPoint, crossOverLength ); + } + } + } +} diff --git a/Sources/Accord.Genetic/Fitness Functions/IFitnessFunction.cs b/Sources/Accord.Genetic/Fitness Functions/IFitnessFunction.cs new file mode 100644 index 0000000000..07fd7f334 --- /dev/null +++ b/Sources/Accord.Genetic/Fitness Functions/IFitnessFunction.cs @@ -0,0 +1,38 @@ +// AForge Genetic Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2006-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Genetic +{ + using System; + + /// + /// Fitness function interface. + /// + /// + /// The interface should be implemented by all fitness function + /// classes, which are supposed to be used for calculation of chromosomes + /// fitness values. All fitness functions should return positive (greater + /// then zero) value, which indicates how good is the evaluated chromosome - + /// the greater the value, the better the chromosome. + /// + public interface IFitnessFunction + { + /// + /// Evaluates chromosome. + /// + /// + /// Chromosome to evaluate. + /// + /// Returns chromosome's fitness value. + /// + /// The method calculates fitness value of the specified + /// chromosome. + /// + double Evaluate( IChromosome chromosome ); + } +} \ No newline at end of file diff --git a/Sources/Accord.Genetic/Fitness Functions/OptimizationFunction1D.cs b/Sources/Accord.Genetic/Fitness Functions/OptimizationFunction1D.cs new file mode 100644 index 0000000000..a920b0ded --- /dev/null +++ b/Sources/Accord.Genetic/Fitness Functions/OptimizationFunction1D.cs @@ -0,0 +1,174 @@ +// AForge Genetic Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Genetic +{ + using System; + using AForge; + + /// Base class for one dimensional function optimizations. + /// + /// The class is aimed to be used for one dimensional function + /// optimization problems. It implements all methods of + /// interface and requires overriding only one method - + /// , which represents the + /// function to optimize. + /// + /// The optimization function should be greater + /// than 0 on the specified optimization range. + /// + /// The class works only with binary chromosomes (). + /// + /// Sample usage: + /// + /// // define optimization function + /// public class UserFunction : OptimizationFunction1D + /// { + /// public UserFunction( ) : + /// base( new Range( 0, 255 ) ) { } + /// + /// public override double OptimizationFunction( double x ) + /// { + /// return Math.Cos( x / 23 ) * Math.Sin( x / 50 ) + 2; + /// } + /// } + /// ... + /// // create genetic population + /// Population population = new Population( 40, + /// new BinaryChromosome( 32 ), + /// new UserFunction( ), + /// new EliteSelection( ) ); + /// + /// while ( true ) + /// { + /// // run one epoch of the population + /// population.RunEpoch( ); + /// // ... + /// } + /// + /// + /// + public abstract class OptimizationFunction1D : IFitnessFunction + { + /// + /// Optimization modes. + /// + /// + /// The enumeration defines optimization modes for + /// the one dimensional function optimization. + /// + public enum Modes + { + /// + /// Search for function's maximum value. + /// + Maximization, + /// + /// Search for function's minimum value. + /// + Minimization + } + + // optimization range + private AForge.Range range = new Range(0, 1); + + // optimization mode + private Modes mode = Modes.Maximization; + + /// + /// Optimization range. + /// + /// + /// Defines function's input range. The function's extreme point will + /// be searched in this range only. + /// + /// + public Range Range + { + get { return range; } + set { range = value; } + } + + /// + /// Optimization mode. + /// + /// + /// Defines optimization mode - what kind of extreme point to search. + /// + public Modes Mode + { + get { return mode; } + set { mode = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Specifies range for optimization. + /// + public OptimizationFunction1D( Range range ) + { + this.range = range; + } + + /// + /// Evaluates chromosome. + /// + /// + /// Chromosome to evaluate. + /// + /// Returns chromosome's fitness value. + /// + /// The method calculates fitness value of the specified + /// chromosome. + /// + public double Evaluate( IChromosome chromosome ) + { + double functionValue = OptimizationFunction( Translate( chromosome ) ); + // fitness value + return ( mode == Modes.Maximization ) ? functionValue : 1 / functionValue; + } + + /// + /// Translates genotype to phenotype. + /// + /// + /// Chromosome, which genoteype should be + /// translated to phenotype. + /// + /// Returns chromosome's fenotype - the actual solution + /// encoded by the chromosome. + /// + /// The method returns double value, which represents function's + /// input point encoded by the specified chromosome. + /// + public double Translate( IChromosome chromosome ) + { + // get chromosome's value and max value + double val = ( (BinaryChromosome) chromosome ).Value; + double max = ( (BinaryChromosome) chromosome ).MaxValue; + + // translate to optimization's funtion space + return val * range.Length / max + range.Min; + } + + /// + /// Function to optimize. + /// + /// + /// Function's input value. + /// + /// Returns function output value. + /// + /// The method should be overloaded by inherited class to + /// specify the optimization function. + /// + public abstract double OptimizationFunction( double x ); + } +} diff --git a/Sources/Accord.Genetic/Fitness Functions/OptimizationFunction2D.cs b/Sources/Accord.Genetic/Fitness Functions/OptimizationFunction2D.cs new file mode 100644 index 0000000000..0c883afcc --- /dev/null +++ b/Sources/Accord.Genetic/Fitness Functions/OptimizationFunction2D.cs @@ -0,0 +1,212 @@ +// AForge Genetic Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Genetic +{ + using System; + using AForge; + + /// Base class for two dimenstional function optimization. + /// + /// The class is aimed to be used for two dimensional function + /// optimization problems. It implements all methods of + /// interface and requires overriding only one method - + /// , which represents the + /// function to optimize. + /// + /// The optimization function should be greater + /// than 0 on the specified optimization range. + /// + /// The class works only with binary chromosomes (). + /// + /// Sample usage: + /// + /// // define optimization function + /// public class UserFunction : OptimizationFunction2D + /// { + /// public UserFunction( ) : + /// base( new Range( -4, 4 ), new Range( -4, 4 ) ) { } + /// + /// public override double OptimizationFunction( double x, double y ) + /// { + /// return ( Math.Cos( y ) * x * y ) / ( 2 - Math.Sin( x ) ); + /// } + /// } + /// ... + /// // create genetic population + /// Population population = new Population( 40, + /// new BinaryChromosome( 32 ), + /// new UserFunction( ), + /// new EliteSelection( ) ); + /// // run one epoch of the population + /// population.RunEpoch( ); + /// + /// + /// + public abstract class OptimizationFunction2D : IFitnessFunction + { + /// + /// Optimization modes. + /// + /// + /// The enumeration defines optimization modes for + /// the two dimensional function optimization. + /// + public enum Modes + { + /// + /// Search for function's maximum value. + /// + Maximization, + /// + /// Search for function's minimum value. + /// + Minimization + } + + // optimization ranges + private AForge.Range rangeX = new Range(0, 1); + private AForge.Range rangeY = new Range(0, 1); + + // optimization mode + private Modes mode = Modes.Maximization; + + /// + /// X variable's optimization range. + /// + /// + /// Defines function's X range. The function's extreme will + /// be searched in this range only. + /// + /// + public Range RangeX + { + get { return rangeX; } + set { rangeX = value; } + } + + /// + /// Y variable's optimization range. + /// + /// + /// Defines function's Y range. The function's extreme will + /// be searched in this range only. + /// + /// + public Range RangeY + { + get { return rangeY; } + set { rangeY = value; } + } + + /// + /// Optimization mode. + /// + /// + /// Defines optimization mode - what kind of extreme to search. + /// + public Modes Mode + { + get { return mode; } + set { mode = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Specifies X variable's range. + /// Specifies Y variable's range. + /// + public OptimizationFunction2D(Range rangeX, Range rangeY) + { + this.rangeX = rangeX; + this.rangeY = rangeY; + } + + + /// + /// Evaluates chromosome. + /// + /// + /// Chromosome to evaluate. + /// + /// Returns chromosome's fitness value. + /// + /// The method calculates fitness value of the specified + /// chromosome. + /// + public double Evaluate(IChromosome chromosome) + { + double[] xy; + + // do native translation first + xy = Translate(chromosome); + // get function value + double functionValue = OptimizationFunction(xy[0], xy[1]); + // return fitness value + return (mode == Modes.Maximization) ? functionValue : 1 / functionValue; + } + + /// + /// Translates genotype to phenotype + /// + /// + /// Chromosome, which genoteype should be + /// translated to phenotype + /// + /// Returns chromosome's fenotype - the actual solution + /// encoded by the chromosome + /// + /// The method returns array of two double values, which + /// represent function's input point (X and Y) encoded by the specified + /// chromosome. + /// + public double[] Translate(IChromosome chromosome) + { + // get chromosome's value + ulong val = ((BinaryChromosome)chromosome).Value; + // chromosome's length + int length = ((BinaryChromosome)chromosome).Length; + // length of X component + int xLength = length / 2; + // length of Y component + int yLength = length - xLength; + // X maximum value - equal to X mask + ulong xMax = 0xFFFFFFFFFFFFFFFF >> (64 - xLength); + // Y maximum value + ulong yMax = 0xFFFFFFFFFFFFFFFF >> (64 - yLength); + // X component + double xPart = val & xMax; + // Y component; + double yPart = val >> xLength; + + // translate to optimization's funtion space + double[] ret = new double[2]; + + ret[0] = xPart * rangeX.Length / xMax + rangeX.Min; + ret[1] = yPart * rangeY.Length / yMax + rangeY.Min; + + return ret; + } + + /// + /// Function to optimize. + /// + /// + /// Function X input value. + /// Function Y input value. + /// + /// Returns function output value. + /// + /// The method should be overloaded by inherited class to + /// specify the optimization function. + /// + public abstract double OptimizationFunction(double x, double y); + } +} diff --git a/Sources/Accord.Genetic/Fitness Functions/SymbolicRegressionFitness.cs b/Sources/Accord.Genetic/Fitness Functions/SymbolicRegressionFitness.cs new file mode 100644 index 0000000000..81954bf96 --- /dev/null +++ b/Sources/Accord.Genetic/Fitness Functions/SymbolicRegressionFitness.cs @@ -0,0 +1,137 @@ +// AForge Genetic Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2006-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Genetic +{ + using System; + using AForge; + + /// + /// Fitness function for symbolic regression (function approximation) problem + /// + /// + /// The fitness function calculates fitness value of + /// GP and GEP + /// chromosomes with the aim of solving symbolic regression problem. The fitness function's + /// value is computed as: + /// 100.0 / ( error + 1 ) + /// where error equals to the sum of absolute differences between function values (computed using + /// the function encoded by chromosome) and input values (function to be approximated). + /// + /// Sample usage: + /// + /// // constants + /// double[] constants = new double[5] { 1, 2, 3, 5, 7 }; + /// // function to be approximated + /// double[,] data = new double[5, 2] { + /// {1, 1}, {2, 3}, {3, 6}, {4, 10}, {5, 15} }; + /// // create population + /// Population population = new Population( 100, + /// new GPTreeChromosome( new SimpleGeneFunction( 1 + constants.Length ) ), + /// new SymbolicRegressionFitness( data, constants ), + /// new EliteSelection( ) ); + /// // run one epoch of the population + /// population.RunEpoch( ); + /// + /// + /// + public class SymbolicRegressionFitness : IFitnessFunction + { + // regression data + private double[,] data; + // varibles + private double[] variables; + + /// + /// Initializes a new instance of the class. + /// + /// + /// Function to be approximated. + /// Array of constants to be used as additional + /// paramters for genetic expression. + /// + /// The parameter defines the function to be approximated and + /// represents a two dimensional array of (x, y) points. + /// + /// The parameter is an array of constants, which can be used as + /// additional variables for a genetic expression. The actual amount of variables for + /// genetic expression equals to the amount of constants plus one - the x variable. + /// + /// + public SymbolicRegressionFitness( double[,] data, double[] constants ) + { + this.data = data; + // copy constants + variables = new double[constants.Length + 1]; + Array.Copy( constants, 0, variables, 1, constants.Length ); + } + + /// + /// Evaluates chromosome. + /// + /// + /// Chromosome to evaluate. + /// + /// Returns chromosome's fitness value. + /// + /// The method calculates fitness value of the specified + /// chromosome. + /// + public double Evaluate( IChromosome chromosome ) + { + // get function in polish notation + string function = chromosome.ToString( ); + + // go through all the data + double error = 0.0; + for ( int i = 0, n = data.GetLength( 0 ); i < n; i++ ) + { + // put next X value to variables list + variables[0] = data[i, 0]; + // avoid evaluation errors + try + { + // evalue the function + double y = PolishExpression.Evaluate( function, variables ); + // check for correct numeric value + if ( double.IsNaN( y ) ) + return 0; + // get the difference between evaluated Y and real Y + // and sum error + error += Math.Abs( y - data[i, 1] ); + } + catch + { + return 0; + } + } + + // return optimization function value + return 100.0 / ( error + 1 ); + } + + /// + /// Translates genotype to phenotype . + /// + /// + /// Chromosome, which genoteype should be + /// translated to phenotype. + /// + /// Returns chromosome's fenotype - the actual solution + /// encoded by the chromosome. + /// + /// The method returns string value, which represents approximation + /// expression written in polish postfix notation. + /// + public string Translate( IChromosome chromosome ) + { + // return polish notation for now ... + return chromosome.ToString( ); + } + } +} diff --git a/Sources/Accord.Genetic/Fitness Functions/TimeSeriesPredictionFitness.cs b/Sources/Accord.Genetic/Fitness Functions/TimeSeriesPredictionFitness.cs new file mode 100644 index 0000000000..52e902801 --- /dev/null +++ b/Sources/Accord.Genetic/Fitness Functions/TimeSeriesPredictionFitness.cs @@ -0,0 +1,171 @@ +// AForge Genetic Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2006-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Genetic +{ + using System; + using AForge; + + /// + /// Fitness function for times series prediction problem + /// + /// + /// The fitness function calculates fitness value of + /// GP and GEP + /// chromosomes with the aim of solving times series prediction problem using + /// sliding window method. The fitness function's value is computed as: + /// 100.0 / ( error + 1 ) + /// where error equals to the sum of absolute differences between predicted value + /// and actual future value. + /// + /// Sample usage: + /// + /// // number of points from the past used to predict new one + /// int windowSize = 5; + /// // time series to predict + /// double[] data = new double[13] { 1, 2, 4, 7, 11, 16, 22, 29, 37, 46, 56, 67, 79 }; + /// // constants + /// double[] constants = new double[10] { 1, 2, 3, 5, 7, 11, 13, 17, 19, 23 }; + /// // create population + /// Population population = new Population( 100, + /// new GPTreeChromosome( new SimpleGeneFunction( windowSize + constants.Length ) ), + /// new TimeSeriesPredictionFitness( data, windowSize, 1, constants ), + /// new EliteSelection( ) ); + /// // run one epoch of the population + /// population.RunEpoch( ); + /// + /// + /// + public class TimeSeriesPredictionFitness : IFitnessFunction + { + // time series data + private double[] data; + // varibles + private double[] variables; + // window size + private int windowSize; + // prediction size + private int predictionSize; + + /// + /// Initializes a new instance of the class. + /// + /// + /// Time series to be predicted. + /// Window size - number of past samples used + /// to predict future value. + /// Prediction size - number of values to be predicted. These + /// values are excluded from training set. + /// Array of constants to be used as additional + /// paramters for genetic expression. + /// + /// The parameter is a one dimensional array, which defines times + /// series to predict. The amount of learning samples is equal to the number of samples + /// in the provided time series, minus window size, minus prediction size. + /// + /// The parameter specifies the amount of samples, which should + /// be excluded from training set. This set of samples may be used for future verification + /// of the prediction model. + /// + /// The parameter is an array of constants, which can be used as + /// additional variables for a genetic expression. The actual amount of variables for + /// genetic expression equals to the amount of constants plus the window size. + /// + /// + public TimeSeriesPredictionFitness( double[] data, int windowSize, int predictionSize, double[] constants ) + { + // check for correct parameters + if ( windowSize >= data.Length ) + throw new ArgumentException( "Window size should be less then data amount" ); + if ( data.Length - windowSize - predictionSize < 1 ) + throw new ArgumentException( "Data size should be enough for window and prediction" ); + // save parameters + this.data = data; + this.windowSize = windowSize; + this.predictionSize = predictionSize; + // copy constants + variables = new double[constants.Length + windowSize]; + Array.Copy( constants, 0, variables, windowSize, constants.Length ); + } + + /// + /// Evaluates chromosome. + /// + /// + /// Chromosome to evaluate. + /// + /// Returns chromosome's fitness value. + /// + /// The method calculates fitness value of the specified + /// chromosome. + /// + public double Evaluate( IChromosome chromosome ) + { + // get function in polish notation + string function = chromosome.ToString( ); + + // go through all the data + double error = 0.0; + for ( int i = 0, n = data.Length - windowSize - predictionSize; i < n; i++ ) + { + // put values from current window as variables + for ( int j = 0, b = i + windowSize - 1; j < windowSize; j++ ) + { + variables[j] = data[b - j]; + } + + // avoid evaluation errors + try + { + // evaluate the function + double y = PolishExpression.Evaluate( function, variables ); + // check for correct numeric value + if ( double.IsNaN( y ) ) + return 0; + // get the difference between evaluated value and + // next value after the window, and sum error + error += Math.Abs( y - data[i + windowSize] ); + } + catch + { + return 0; + } + } + + // return optimization function value + return 100.0 / ( error + 1 ); + } + + /// + /// Translates genotype to phenotype. + /// + /// + /// Chromosome, which genoteype should be + /// translated to phenotype. + /// + /// Returns chromosome's fenotype - the actual solution + /// encoded by the chromosome. + /// + /// The method returns string value, which represents prediction + /// expression written in polish postfix notation. + /// + /// The interpretation of the prediction expression is very simple. For example, let's + /// take a look at sample expression, which was received with window size equal to 5: + /// $0 $1 - $5 / $2 * + /// The above expression in postfix polish notation should be interpreted as a next expression: + /// ( ( x[t - 1] - x[t - 2] ) / const1 ) * x[t - 3] + /// + /// + /// + public string Translate( IChromosome chromosome ) + { + // return polish notation for now ... + return chromosome.ToString( ); + } + } +} diff --git a/Sources/Accord.Genetic/Population.cs b/Sources/Accord.Genetic/Population.cs new file mode 100644 index 0000000000..2cdbf7ba9 --- /dev/null +++ b/Sources/Accord.Genetic/Population.cs @@ -0,0 +1,638 @@ +// AForge Genetic Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +namespace AForge.Genetic +{ + using System; + using System.Collections; + using System.Collections.Generic; + + /// + /// Population of chromosomes. + /// + /// + /// The class represents population - collection of individuals (chromosomes) + /// and provides functionality for common population's life cycle - population growing + /// with help of genetic operators and selection of chromosomes to new generation + /// with help of selection algorithm. The class may work with any type of chromosomes + /// implementing interface, use any type of fitness functions + /// implementing interface and use any type of selection + /// algorithms implementing interface. + /// + /// + public class Population + { + private IFitnessFunction fitnessFunction; + private ISelectionMethod selectionMethod; + private List population = new List( ); + private int size; + private double randomSelectionPortion = 0.0; + private bool autoShuffling = false; + + // population parameters + private double crossoverRate = 0.75; + private double mutationRate = 0.10; + + // random number generator + private static ThreadSafeRandom rand = new ThreadSafeRandom( ); + + // + private double fitnessMax = 0; + private double fitnessSum = 0; + private double fitnessAvg = 0; + private IChromosome bestChromosome = null; + + /// + /// Crossover rate, [0.1, 1]. + /// + /// + /// The value determines the amount of chromosomes which participate + /// in crossover. + /// + /// Default value is set to 0.75. + /// + /// + public double CrossoverRate + { + get { return crossoverRate; } + set + { + crossoverRate = Math.Max( 0.1, Math.Min( 1.0, value ) ); + } + } + + /// + /// Mutation rate, [0.1, 1]. + /// + /// + /// The value determines the amount of chromosomes which participate + /// in mutation. + /// + /// Defaul value is set to 0.1. + /// + public double MutationRate + { + get { return mutationRate; } + set + { + mutationRate = Math.Max( 0.1, Math.Min( 1.0, value ) ); + } + } + + /// + /// Random selection portion, [0, 0.9]. + /// + /// + /// The value determines the amount of chromosomes which will be + /// randomly generated for the new population. The property controls the amount + /// of chromosomes, which are selected to a new population using + /// selection operator, and amount of random + /// chromosomes added to the new population. + /// + /// Default value is set to 0. + /// + public double RandomSelectionPortion + { + get { return randomSelectionPortion; } + set + { + randomSelectionPortion = Math.Max( 0, Math.Min( 0.9, value ) ); + } + } + + /// + /// Determines of auto shuffling is on or off. + /// + /// + /// The property specifies if automatic shuffling needs to be done + /// on each epoch by calling + /// method. + /// + /// Default value is set to . + /// + public bool AutoShuffling + { + get { return autoShuffling; } + set { autoShuffling = value; } + } + + /// + /// Selection method to use with the population. + /// + /// + /// The property sets selection method which is used to select + /// population members for a new population - filter population after reproduction + /// was done with operators like crossover and mutations. + /// + public ISelectionMethod SelectionMethod + { + get { return selectionMethod; } + set { selectionMethod = value; } + } + + /// + /// Fitness function to apply to the population. + /// + /// + /// The property sets fitness function, which is used to evaluate + /// usefulness of population's chromosomes. Setting new fitness function causes recalculation + /// of fitness values for all population's members and new best member will be found. + /// + /// + public IFitnessFunction FitnessFunction + { + get { return fitnessFunction; } + set + { + fitnessFunction = value; + + foreach ( IChromosome member in population ) + { + member.Evaluate( fitnessFunction ); + } + + FindBestChromosome( ); + } + } + + /// + /// Maximum fitness of the population. + /// + /// + /// The property keeps maximum fitness of chromosomes currently existing + /// in the population. + /// + /// The property is recalculate only after selection + /// or migration was done. + /// + /// + public double FitnessMax + { + get { return fitnessMax; } + } + + /// + /// Summary fitness of the population. + /// + /// + /// The property keeps summary fitness of all chromosome existing in the + /// population. + /// + /// The property is recalculate only after selection + /// or migration was done. + /// + /// + public double FitnessSum + { + get { return fitnessSum; } + } + + /// + /// Average fitness of the population. + /// + /// + /// The property keeps average fitness of all chromosome existing in the + /// population. + /// + /// The property is recalculate only after selection + /// or migration was done. + /// + /// + public double FitnessAvg + { + get { return fitnessAvg; } + } + + /// + /// Best chromosome of the population. + /// + /// + /// The property keeps the best chromosome existing in the population + /// or if all chromosomes have 0 fitness. + /// + /// The property is recalculate only after selection + /// or migration was done. + /// + /// + public IChromosome BestChromosome + { + get { return bestChromosome; } + } + + /// + /// Size of the population. + /// + /// + /// The property keeps initial (minimal) size of population. + /// Population always returns to this size after selection operator was applied, + /// which happens after or methods + /// call. + /// + public int Size + { + get { return size; } + } + + /// + /// Get chromosome with specified index. + /// + /// + /// Chromosome's index to retrieve. + /// + /// Allows to access individuals of the population. + /// + public IChromosome this[int index] + { + get { return population[index]; } + } + + + /// + /// Initializes a new instance of the class. + /// + /// + /// Initial size of population. + /// Ancestor chromosome to use for population creatioin. + /// Fitness function to use for calculating + /// chromosome's fitness values. + /// Selection algorithm to use for selection + /// chromosome's to new generation. + /// + /// Creates new population of specified size. The specified ancestor + /// becomes first member of the population and is used to create other members + /// with same parameters, which were used for ancestor's creation. + /// + /// Too small population's size was specified. The + /// exception is thrown in the case if is smaller than 2. + /// + public Population( int size, + IChromosome ancestor, + IFitnessFunction fitnessFunction, + ISelectionMethod selectionMethod ) + { + if ( size < 2 ) + throw new ArgumentException( "Too small population's size was specified." ); + + this.fitnessFunction = fitnessFunction; + this.selectionMethod = selectionMethod; + this.size = size; + + // add ancestor to the population + ancestor.Evaluate( fitnessFunction ); + population.Add( ancestor.Clone( ) ); + // add more chromosomes to the population + for ( int i = 1; i < size; i++ ) + { + // create new chromosome + IChromosome c = ancestor.CreateNew( ); + // calculate it's fitness + c.Evaluate( fitnessFunction ); + // add it to population + population.Add( c ); + } + } + + /// + /// Regenerate population. + /// + /// + /// The method regenerates population filling it with random chromosomes. + /// + public void Regenerate( ) + { + IChromosome ancestor = population[0]; + + // clear population + population.Clear( ); + // add chromosomes to the population + for ( int i = 0; i < size; i++ ) + { + // create new chromosome + IChromosome c = ancestor.CreateNew( ); + // calculate it's fitness + c.Evaluate( fitnessFunction ); + // add it to population + population.Add( c ); + } + } + + /// + /// Do crossover in the population. + /// + /// + /// The method walks through the population and performs crossover operator + /// taking each two chromosomes in the order of their presence in the population. + /// The total amount of paired chromosomes is determined by + /// crossover rate. + /// + public virtual void Crossover( ) + { + // crossover + for ( int i = 1; i < size; i += 2 ) + { + // generate next random number and check if we need to do crossover + if ( rand.NextDouble( ) <= crossoverRate ) + { + // clone both ancestors + IChromosome c1 = population[i - 1].Clone( ); + IChromosome c2 = population[i].Clone( ); + + // do crossover + c1.Crossover( c2 ); + + // calculate fitness of these two offsprings + c1.Evaluate( fitnessFunction ); + c2.Evaluate( fitnessFunction ); + + // add two new offsprings to the population + population.Add( c1 ); + population.Add( c2 ); + } + } + } + + /// + /// Do mutation in the population. + /// + /// + /// The method walks through the population and performs mutation operator + /// taking each chromosome one by one. The total amount of mutated chromosomes is + /// determined by mutation rate. + /// + public virtual void Mutate( ) + { + // mutate + for ( int i = 0; i < size; i++ ) + { + // generate next random number and check if we need to do mutation + if ( rand.NextDouble( ) <= mutationRate ) + { + // clone the chromosome + IChromosome c = population[i].Clone( ); + // mutate it + c.Mutate( ); + // calculate fitness of the mutant + c.Evaluate( fitnessFunction ); + // add mutant to the population + population.Add( c ); + } + } + } + + /// + /// Do selection. + /// + /// + /// The method applies selection operator to the current population. Using + /// specified selection algorithm it selects members to the new generation from current + /// generates and adds certain amount of random members, if is required + /// (see ). + /// + public virtual void Selection( ) + { + // amount of random chromosomes in the new population + int randomAmount = (int) ( randomSelectionPortion * size ); + + // do selection + selectionMethod.ApplySelection( population, size - randomAmount ); + + // add random chromosomes + if ( randomAmount > 0 ) + { + IChromosome ancestor = population[0]; + + for ( int i = 0; i < randomAmount; i++ ) + { + // create new chromosome + IChromosome c = ancestor.CreateNew( ); + // calculate it's fitness + c.Evaluate( fitnessFunction ); + // add it to population + population.Add( c ); + } + } + + FindBestChromosome( ); + } + + /// + /// Run one epoch of the population. + /// + /// + /// The method runs one epoch of the population, doing crossover, mutation + /// and selection by calling , and + /// . + /// + public void RunEpoch( ) + { + Crossover( ); + Mutate( ); + Selection( ); + + if ( autoShuffling ) + Shuffle( ); + } + + /// + /// Shuffle randomly current population. + /// + /// + /// Population shuffling may be useful in cases when selection + /// operator results in not random order of chromosomes (for example, after elite + /// selection population may be ordered in ascending/descending order). + /// + public void Shuffle( ) + { + // current population size + int size = population.Count; + // create temporary copy of the population + List tempPopulation = population.GetRange( 0, size ); + // clear current population and refill it randomly + population.Clear( ); + + while ( size > 0 ) + { + int i = rand.Next( size ); + + population.Add( tempPopulation[i] ); + tempPopulation.RemoveAt( i ); + + size--; + } + } + + /// + /// Add chromosome to the population. + /// + /// + /// Chromosome to add to the population. + /// + /// The method adds specified chromosome to the current population. + /// Manual adding of chromosome maybe useful, when it is required to add some initialized + /// chromosomes instead of random. + /// + /// Adding chromosome manually should be done very carefully, since it + /// may break the population. The manually added chromosome must have the same type + /// and initialization parameters as the ancestor passed to constructor. + /// + /// + public void AddChromosome( IChromosome chromosome ) + { + chromosome.Evaluate( fitnessFunction ); + population.Add( chromosome ); + } + + /// + /// Perform migration between two populations. + /// + /// + /// Population to do migration with. + /// Number of chromosomes from each population to migrate. + /// Selection algorithm used to select chromosomes to migrate. + /// + /// The method performs migration between two populations - current and the + /// specified one. During migration + /// specified number of chromosomes is choosen from + /// each population using specified selection algorithms + /// and put into another population replacing worst members there. + /// + public void Migrate( Population anotherPopulation, int numberOfMigrants, ISelectionMethod migrantsSelector ) + { + int currentSize = this.size; + int anotherSize = anotherPopulation.Size; + + // create copy of current population + List currentCopy = new List( ); + + for ( int i = 0; i < currentSize; i++ ) + { + currentCopy.Add( population[i].Clone( ) ); + } + + // create copy of another population + List anotherCopy = new List( ); + + for ( int i = 0; i < anotherSize; i++ ) + { + anotherCopy.Add( anotherPopulation.population[i].Clone( ) ); + } + + // apply selection to both populations' copies - select members to migrate + migrantsSelector.ApplySelection( currentCopy, numberOfMigrants ); + migrantsSelector.ApplySelection( anotherCopy, numberOfMigrants ); + + // sort original populations, so the best chromosomes are in the beginning + population.Sort( ); + anotherPopulation.population.Sort( ); + + // remove worst chromosomes from both populations to free space for new members + population.RemoveRange( currentSize - numberOfMigrants, numberOfMigrants ); + anotherPopulation.population.RemoveRange( anotherSize - numberOfMigrants, numberOfMigrants ); + + // put migrants to corresponding populations + population.AddRange( anotherCopy ); + anotherPopulation.population.AddRange( currentCopy ); + + // find best chromosomes in each population + FindBestChromosome( ); + anotherPopulation.FindBestChromosome( ); + } + + /// + /// Resize population to the new specified size. + /// + /// + /// New size of population. + /// + /// The method does resizing of population. In the case if population + /// should grow, it just adds missing number of random members. In the case if + /// population should get smaller, the population's + /// selection method is used to reduce the population. + /// + /// Too small population's size was specified. The + /// exception is thrown in the case if is smaller than 2. + /// + public void Resize( int newPopulationSize ) + { + Resize( newPopulationSize, selectionMethod ); + } + + /// + /// Resize population to the new specified size. + /// + /// + /// New size of population. + /// Selection algorithm to use in the case + /// if population should get smaller. + /// + /// The method does resizing of population. In the case if population + /// should grow, it just adds missing number of random members. In the case if + /// population should get smaller, the specified selection method is used to + /// reduce the population. + /// + /// Too small population's size was specified. The + /// exception is thrown in the case if is smaller than 2. + /// + public void Resize( int newPopulationSize, ISelectionMethod membersSelector ) + { + if ( newPopulationSize < 2 ) + throw new ArgumentException( "Too small new population's size was specified." ); + + if ( newPopulationSize > size ) + { + // population is growing, so add new rundom members + + // Note: we use population.Count here instead of "size" because + // population may be bigger already after crossover/mutation. So + // we just keep those members instead of adding random member. + int toAdd = newPopulationSize - population.Count; + + for ( int i = 0; i < toAdd; i++ ) + { + // create new chromosome + IChromosome c = population[0].CreateNew( ); + // calculate it's fitness + c.Evaluate( fitnessFunction ); + // add it to population + population.Add( c ); + } + } + else + { + // do selection + membersSelector.ApplySelection( population, newPopulationSize ); + } + + size = newPopulationSize; + } + + // Find best chromosome in the population so far + private void FindBestChromosome( ) + { + bestChromosome = population[0]; + fitnessMax = bestChromosome.Fitness; + fitnessSum = fitnessMax; + + for ( int i = 1; i < size; i++ ) + { + double fitness = population[i].Fitness; + + // accumulate summary value + fitnessSum += fitness; + + // check for max + if ( fitness > fitnessMax ) + { + fitnessMax = fitness; + bestChromosome = population[i]; + } + } + fitnessAvg = fitnessSum / size; + } + } +} \ No newline at end of file diff --git a/Sources/Accord.Genetic/Properties/AssemblyInfo.cs b/Sources/Accord.Genetic/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..762a28c62 --- /dev/null +++ b/Sources/Accord.Genetic/Properties/AssemblyInfo.cs @@ -0,0 +1,13 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Accord.Genetic")] +[assembly: AssemblyDescription("Accord.NET - Genetic Programming Library")] +[assembly: AssemblyConfiguration("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. +[assembly: ComVisible(false)] diff --git a/Sources/Accord.Genetic/Selection Algorithms/EliteSelection.cs b/Sources/Accord.Genetic/Selection Algorithms/EliteSelection.cs new file mode 100644 index 0000000000..c6e9ce1b4 --- /dev/null +++ b/Sources/Accord.Genetic/Selection Algorithms/EliteSelection.cs @@ -0,0 +1,48 @@ +// AForge Genetic Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2006-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Genetic +{ + using System; + using System.Collections; + using System.Collections.Generic; + + /// + /// Elite selection method. + /// + /// + /// Elite selection method selects specified amount of + /// best chromosomes to the next generation. + /// + public class EliteSelection : ISelectionMethod + { + /// + /// Initializes a new instance of the class. + /// + public EliteSelection( ) { } + + /// + /// Apply selection to the specified population. + /// + /// + /// Population, which should be filtered. + /// The amount of chromosomes to keep. + /// + /// Filters specified population keeping only specified amount of best + /// chromosomes. + /// + public void ApplySelection( List chromosomes, int size ) + { + // sort chromosomes + chromosomes.Sort( ); + + // remove bad chromosomes + chromosomes.RemoveRange( size, chromosomes.Count - size ); + } + } +} diff --git a/Sources/Accord.Genetic/Selection Algorithms/ISelectionMethod.cs b/Sources/Accord.Genetic/Selection Algorithms/ISelectionMethod.cs new file mode 100644 index 0000000000..e209825d5 --- /dev/null +++ b/Sources/Accord.Genetic/Selection Algorithms/ISelectionMethod.cs @@ -0,0 +1,39 @@ +// AForge Genetic Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2006-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Genetic +{ + using System; + using System.Collections; + using System.Collections.Generic; + + /// + /// Genetic selection method interface. + /// + /// + /// The interface should be implemented by all classes, which + /// implement genetic selection algorithm. These algorithms select members of + /// current generation, which should be kept in the new generation. Basically, + /// these algorithms filter provided population keeping only specified amount of + /// members. + /// + public interface ISelectionMethod + { + /// + /// Apply selection to the specified population. + /// + /// + /// Population, which should be filtered. + /// The amount of chromosomes to keep. + /// + /// Filters specified population according to the implemented + /// selection algorithm. + /// + void ApplySelection( List chromosomes, int size ); + } +} \ No newline at end of file diff --git a/Sources/Accord.Genetic/Selection Algorithms/RankSelection.cs b/Sources/Accord.Genetic/Selection Algorithms/RankSelection.cs new file mode 100644 index 0000000000..032b62388 --- /dev/null +++ b/Sources/Accord.Genetic/Selection Algorithms/RankSelection.cs @@ -0,0 +1,99 @@ +// AForge Genetic Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +namespace AForge.Genetic +{ + using System; + using System.Collections; + using System.Collections.Generic; + using AForge; + + /// + /// Rank selection method. + /// + /// + /// The algorithm selects chromosomes to the new generation depending on + /// their fitness values - the better fitness value chromosome has, the more chances + /// it has to become member of the new generation. Each chromosome can be selected + /// several times to the new generation. + /// + /// This algorithm is similar to Roulette Wheel + /// Selection algorithm, but the difference is in "wheel" and its sectors' size + /// calculation method. The size of the wheel equals to size * ( size + 1 ) / 2, + /// where size is the current size of population. The worst chromosome has its sector's + /// size equal to 1, the next chromosome has its sector's size equal to 2, etc. + /// + /// + public class RankSelection : ISelectionMethod + { + // random number generator + private static ThreadSafeRandom rand = new ThreadSafeRandom( ); + + /// + /// Initializes a new instance of the class. + /// + public RankSelection( ) { } + + /// + /// Apply selection to the specified population. + /// + /// + /// Population, which should be filtered. + /// The amount of chromosomes to keep. + /// + /// Filters specified population keeping only those chromosomes, which + /// won "roulette" game. + /// + public void ApplySelection( List chromosomes, int size ) + { + // new population, initially empty + List newPopulation = new List( ); + // size of current population + int currentSize = chromosomes.Count; + + // sort current population + chromosomes.Sort( ); + + // calculate amount of ranges in the wheel + double ranges = currentSize * ( currentSize + 1 ) / 2; + + // create wheel ranges + double[] rangeMax = new double[currentSize]; + double s = 0; + + for ( int i = 0, n = currentSize; i < currentSize; i++, n-- ) + { + s += ( (double) n / ranges ); + rangeMax[i] = s; + } + + // select chromosomes from old population to the new population + for ( int j = 0; j < size; j++ ) + { + // get wheel value + double wheelValue = rand.NextDouble( ); + // find the chromosome for the wheel value + for ( int i = 0; i < currentSize; i++ ) + { + if ( wheelValue <= rangeMax[i] ) + { + // add the chromosome to the new population + newPopulation.Add( ((IChromosome) chromosomes[i]).Clone( ) ); + break; + } + } + } + + // empty current population + chromosomes.Clear( ); + + // move elements from new to current population + chromosomes.AddRange( newPopulation ); + } + } +} diff --git a/Sources/Accord.Genetic/Selection Algorithms/RouletteWheelSelection.cs b/Sources/Accord.Genetic/Selection Algorithms/RouletteWheelSelection.cs new file mode 100644 index 0000000000..9df0f8f84 --- /dev/null +++ b/Sources/Accord.Genetic/Selection Algorithms/RouletteWheelSelection.cs @@ -0,0 +1,100 @@ +// AForge Genetic Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2006-2011 +// contacts@aforgenet.com +// + +namespace AForge.Genetic +{ + using System; + using System.Collections; + using System.Collections.Generic; + using AForge; + + /// + /// Roulette wheel selection method. + /// + /// + /// The algorithm selects chromosomes to the new generation according to + /// their fitness values - the more fitness value chromosome has, the more chances + /// it has to become member of new generation. Each chromosome can be selected + /// several times to the new generation. + /// + /// The "roulette's wheel" is divided into sectors, which size is proportional to + /// the fitness values of chromosomes - the size of the wheel is the sum of all fitness + /// values, size of each sector equals to fitness value of chromosome. + /// + /// + public class RouletteWheelSelection : ISelectionMethod + { + // random number generator + private static ThreadSafeRandom rand = new ThreadSafeRandom( ); + + /// + /// Initializes a new instance of the class. + /// + public RouletteWheelSelection( ) { } + + /// + /// Apply selection to the specified population. + /// + /// + /// Population, which should be filtered. + /// The amount of chromosomes to keep. + /// + /// Filters specified population keeping only those chromosomes, which + /// won "roulette" game. + /// + public void ApplySelection( List chromosomes, int size ) + { + // new population, initially empty + List newPopulation = new List( ); + // size of current population + int currentSize = chromosomes.Count; + + // calculate summary fitness of current population + double fitnessSum = 0; + foreach ( IChromosome c in chromosomes ) + { + fitnessSum += c.Fitness; + } + + // create wheel ranges + double[] rangeMax = new double[currentSize]; + double s = 0; + int k = 0; + + foreach ( IChromosome c in chromosomes ) + { + // cumulative normalized fitness + s += ( c.Fitness / fitnessSum ); + rangeMax[k++] = s; + } + + // select chromosomes from old population to the new population + for ( int j = 0; j < size; j++ ) + { + // get wheel value + double wheelValue = rand.NextDouble( ); + // find the chromosome for the wheel value + for ( int i = 0; i < currentSize; i++ ) + { + if ( wheelValue <= rangeMax[i] ) + { + // add the chromosome to the new population + newPopulation.Add( ((IChromosome) chromosomes[i]).Clone( ) ); + break; + } + } + } + + // empty current population + chromosomes.Clear( ); + + // move elements from new to current population + chromosomes.AddRange( newPopulation ); + } + } +} diff --git a/Sources/Accord.IO/Accord.IO.cd b/Sources/Accord.IO/Accord.IO.cd index ea02688bf..4c37ce3a5 100644 --- a/Sources/Accord.IO/Accord.IO.cd +++ b/Sources/Accord.IO/Accord.IO.cd @@ -1,95 +1,129 @@ - - - - - - - - IABAAAAACAEECAAAAAEABAAAAAAAAAAAAAAAAAAAAAA= - ExcelReader.cs - - - - - - - - AAAAAAAAACAAABAAACgAAQAAgQAAAAAQAAAAAAAQAAA= - SparseReader.cs - - - - - - - - - AAAAEAAQACJAAAAAABgAABIgkAABAABgAABEAAAQAAA= - IdxReader.cs - - - - - - - - - - - - AGAAAAEAAAAAABAACmBAAAQQAAQBASgAAABgAAAQAAQ= - MatNode.cs - - - - - - - - - - - - - IEAAAEAAACAgAAAACAAAAAAAgAAAAAAAAAAEAAAQAAA= - MatReader.cs - - - - - - - - - - AAAAAAAAAAAAAAKAAAAAAAAAAAACAgAAAAAAAAAgAgA= - IdxReader.cs - - - + + + + + + + + IABAAAAACAEMCAAAAAEABCAAAAAAAAAAAAAAAAAAAAA= + ExcelReader.cs + + + + + + + + AAAAAAAAACAAABAAACgAAQIAgQAAAAAQAAAAAgAUCAA= + SparseReader.cs + + + + + + + + + AAAAEAAQACJAAAAAAhgAABIgkAABAARgAABEAAAQAAA= + IdxReader.cs + + + + + + + + + + + + + + Csv\CsvReader.IDataReader.cs + + + + + Csv\CsvReader.RecordEnumerator.cs + + + + + + UQtiuBAnCLkglDigCGDBTZGCpgCIR43GKYSgCBiGIFc= + Csv\CsvReader.cs + + + + + + + AAIAEAAEAKAAAACIAECAAAAAgAAAAAAAAQAgAAEAAAA= + Csv\CsvWriter.cs + + + + + + + AAAAAAAAAAAAAAKAAAAAAAAAAAACAgAAAAAAAAAgAgA= + IdxReader.cs + + + + + + AAAAAAAAAAAgAAAAAAAAAAAAAEAAAEAAAAAAAAAAAAA= + Csv\MissingFieldAction.cs + + + + + + AAAAAAAAAAAAAAAAgAAAAAAAAAAAAQAAAAAAAEAAAAA= + Csv\ParseErrorAction.cs + + + + + + AAAAAAAAAAAAAEAAAAAAAAAAACAAAAAAAIAAAAEAAAA= + Csv\ValueTrimmingOptions.cs + + + \ No newline at end of file diff --git a/Sources/Accord.IO/Accord.IO.csproj b/Sources/Accord.IO/Accord.IO.csproj index 2d1a84524..ddcd6c196 100644 --- a/Sources/Accord.IO/Accord.IO.csproj +++ b/Sources/Accord.IO/Accord.IO.csproj @@ -36,29 +36,29 @@ False True DEBUG;TRACE - ..\..\Debug\ + $(SolutionDir)..\Debug\ - ..\..\Release\net35 + $(SolutionDir)..\Release\net35 TRACE;CODE_ANALYSIS;NET35 v3.5 true - ..\..\Release\net35\Accord.IO.XML - ..\..\Release\net35\Accord.IO.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net35\Accord.IO.XML + $(SolutionDir)..\Release\net35\Accord.IO.dll.CodeAnalysisLog.xml - ..\..\Release\net40 + $(SolutionDir)..\Release\net40 TRACE;CODE_ANALYSIS;NET40 v4.0 - ..\..\Release\net40\Accord.IO.XML - ..\..\Release\net40\Accord.IO.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net40\Accord.IO.XML + $(SolutionDir)..\Release\net40\Accord.IO.dll.CodeAnalysisLog.xml - ..\..\Release\net45 + $(SolutionDir)..\Release\net45 TRACE;CODE_ANALYSIS;NET45 v4.5 - ..\..\Release\net45\Accord.IO.XML - ..\..\Release\net45\Accord.IO.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net45\Accord.IO.XML + $(SolutionDir)..\Release\net45\Accord.IO.dll.CodeAnalysisLog.xml @@ -132,4 +132,4 @@ ExceptionMessage.Designer.cs - \ No newline at end of file + diff --git a/Sources/Accord.IO/Csv/CsvReader.cs b/Sources/Accord.IO/Csv/CsvReader.cs index 053941921..575b9217b 100644 --- a/Sources/Accord.IO/Csv/CsvReader.cs +++ b/Sources/Accord.IO/Csv/CsvReader.cs @@ -1842,25 +1842,11 @@ public RecordEnumerator GetEnumerator() return new RecordEnumerator(this); } - /// - /// Returns an that can iterate through CSV records. - /// - /// An that can iterate through CSV records. - /// - /// The instance has been disposed of. - /// IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } - /// - /// Returns an that can iterate through CSV records. - /// - /// An that can iterate through CSV records. - /// - /// The instance has been disposed of. - /// IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); diff --git a/Sources/Accord.IO/ExcelReader.cs b/Sources/Accord.IO/ExcelReader.cs index b0f01b84a..a836967e1 100644 --- a/Sources/Accord.IO/ExcelReader.cs +++ b/Sources/Accord.IO/ExcelReader.cs @@ -23,6 +23,7 @@ namespace Accord.IO { using System; + using System.Collections.Generic; using System.Data; using System.Data.Common; using System.Data.OleDb; @@ -253,23 +254,32 @@ public string[] WorksheetNames /// public string[] GetWorksheetList() { - OleDbConnection connection = new OleDbConnection(strConnection); - connection.Open(); - DataTable tableWorksheets = connection.GetSchema("Tables"); - connection.Close(); + var set = new HashSet(); - worksheets = new string[tableWorksheets.Rows.Count]; - - for (int i = 0; i < worksheets.Length; i++) + using (var connection = new OleDbConnection(strConnection)) { - worksheets[i] = (string)tableWorksheets.Rows[i]["TABLE_NAME"]; - worksheets[i] = worksheets[i].Remove(worksheets[i].Length - 1).Trim('"', '\''); + connection.Open(); + + var table = connection.GetSchema("Tables"); - // removes the trailing $ and other characters appended in the table name - while (worksheets[i].EndsWith("$", StringComparison.Ordinal)) - worksheets[i] = worksheets[i].Remove(worksheets[i].Length - 1).Trim('"', '\''); + for (int i = 0; i < table.Rows.Count; i++) + { + string name = (string)table.Rows[i]["TABLE_NAME"]; + + // removes the trailing $ and other characters appended in the table name + while (name.EndsWith("$", StringComparison.Ordinal) + || name.EndsWith("$\"", StringComparison.Ordinal) + || name.EndsWith("$\'", StringComparison.Ordinal) + || name.EndsWith("$\"\'", StringComparison.Ordinal) + || name.EndsWith("$\'\"", StringComparison.Ordinal)) + name = name.Remove(name.Length - 1).Trim('"', '\''); + + set.Add(name); + } } + this.worksheets = new List(set).ToArray(); + return worksheets; } @@ -347,6 +357,24 @@ public DataSet GetWorksheet() return dataset; } + + private bool unquote(string str, char quote, out string unquoted) + { + unquoted = str; + + if (String.IsNullOrEmpty(str)) + return false; + + int length = str.Length; + if (length > 1 && str[0] == quote && str[length - 1] == quote) + { + unquoted = str.Substring(1, length - 2); + return true; + } + + return false; + } + } diff --git a/Sources/Accord.Imaging/AForge/Blob.cs b/Sources/Accord.Imaging/AForge/Blob.cs new file mode 100644 index 0000000000..9f7b4ab9c --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Blob.cs @@ -0,0 +1,210 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2012 +// contacts@aforgenet.com +// + +namespace AForge.Imaging +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + using System.ComponentModel; + using AForge; + + /// + /// Image's blob. + /// + /// + /// The class represents a blob - part of another images. The + /// class encapsulates the blob itself and information about its position + /// in parent image. + /// + /// The class is not responsible for blob's image disposing, so it should be + /// done manually when it is required. + /// + /// + public class Blob + { + // blob's image + private UnmanagedImage image; + // blob's image size - as original image or not + private bool originalSize = false; + + // blob's rectangle in the original image + private Rectangle rect; + // blob's ID in the original image + private int id; + // area of the blob + private int area; + // center of gravity + private AForge.Point cog; + // fullness of the blob ( area / ( width * height ) ) + private double fullness; + // mean color of the blob + private Color colorMean = Color.Black; + // color's standard deviation of the blob + private Color colorStdDev = Color.Black; + + /// + /// Blob's image. + /// + /// + /// The property keeps blob's image. In the case if it equals to null, + /// the image may be extracted using + /// or method. + /// + [Browsable(false)] + public UnmanagedImage Image + { + get { return image; } + internal set { image = value; } + } + + /// + /// Blob's image size. + /// + /// + /// The property specifies size of the blob's image. + /// If the property is set to , the blob's image size equals to the + /// size of original image. If the property is set to , the blob's + /// image size equals to size of actual blob. + /// + [Browsable(false)] + public bool OriginalSize + { + get { return originalSize; } + internal set { originalSize = value; } + } + + /// + /// Blob's rectangle in the original image. + /// + /// + /// The property specifies position of the blob in the original image + /// and its size. + /// + public Rectangle Rectangle + { + get { return rect; } + } + + /// + /// Blob's ID in the original image. + /// + [Browsable(false)] + public int ID + { + get { return id; } + internal set { id = value; } + } + + /// + /// Blob's area. + /// + /// + /// The property equals to blob's area measured in number of pixels + /// contained by the blob. + /// + public int Area + { + get { return area; } + internal set { area = value; } + } + + /// + /// Blob's fullness, [0, 1]. + /// + /// + /// The property equals to blob's fullness, which is calculated + /// as Area / ( Width * Height ). If it equals to 1, then + /// it means that entire blob's rectangle is filled by blob's pixel (no + /// blank areas), which is true only for rectangles. If it equals to 0.5, + /// for example, then it means that only half of the bounding rectangle is filled + /// by blob's pixels. + /// + public double Fullness + { + get { return fullness; } + internal set { fullness = value; } + } + + /// + /// Blob's center of gravity point. + /// + /// + /// The property keeps center of gravity point, which is calculated as + /// mean value of X and Y coordinates of blob's points. + /// + public AForge.Point CenterOfGravity + { + get { return cog; } + internal set { cog = value; } + } + + /// + /// Blob's mean color. + /// + /// + /// The property keeps mean color of pixels comprising the blob. + /// + public Color ColorMean + { + get { return colorMean; } + internal set { colorMean = value; } + } + + /// + /// Blob color's standard deviation. + /// + /// + /// The property keeps standard deviation of pixels' colors comprising the blob. + /// + public Color ColorStdDev + { + get { return colorStdDev; } + internal set { colorStdDev = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Blob's ID in the original image. + /// Blob's rectangle in the original image. + /// + /// This constructor leaves property not initialized. The blob's + /// image may be extracted later using + /// or method. + /// + public Blob(int id, Rectangle rect) + { + this.id = id; + this.rect = rect; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Source blob to copy. + /// + /// This copy constructor leaves property not initialized. The blob's + /// image may be extracted later using + /// or method. + /// + public Blob(Blob source) + { + // copy everything except image + id = source.id; + rect = source.rect; + cog = source.cog; + area = source.area; + fullness = source.fullness; + colorMean = source.colorMean; + colorStdDev = source.colorStdDev; + } + } +} diff --git a/Sources/Accord.Imaging/AForge/BlobCounter.cs b/Sources/Accord.Imaging/AForge/BlobCounter.cs new file mode 100644 index 0000000000..5173c3b88 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/BlobCounter.cs @@ -0,0 +1,582 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2012 +// contacts@aforgenet.com +// + +namespace AForge.Imaging +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Blob counter - counts objects in image, which are separated by black background. + /// + /// + /// The class counts and extracts stand alone objects in + /// images using connected components labeling algorithm. + /// + /// The algorithm treats all pixels with values less or equal to + /// as background, but pixels with higher values are treated as objects' pixels. + /// + /// For blobs' searching the class supports 8 bpp indexed grayscale images and + /// 24/32 bpp color images that are at least two pixels wide. Images that are one + /// pixel wide can be processed if they are rotated first, or they can be processed + /// with . + /// See documentation about for information about which + /// pixel formats are supported for extraction of blobs. + /// + /// Sample usage: + /// + /// // create an instance of blob counter algorithm + /// BlobCounter bc = new BlobCounter( ); + /// // process binary image + /// bc.ProcessImage( image ); + /// Rectangle[] rects = bc.GetObjectsRectangles( ); + /// // process blobs + /// foreach ( Rectangle rect in rects ) + /// { + /// // ... + /// } + /// + /// + /// + public class BlobCounter : BlobCounterBase + { + private byte backgroundThresholdR = 0; + private byte backgroundThresholdG = 0; + private byte backgroundThresholdB = 0; + + /// + /// Background threshold's value. + /// + /// + /// The property sets threshold value for distinguishing between background + /// pixel and objects' pixels. All pixel with values less or equal to this property are + /// treated as background, but pixels with higher values are treated as objects' pixels. + /// + /// In the case of colour images a pixel is treated as objects' pixel if any of its + /// RGB values are higher than corresponding values of this threshold. + /// + /// For processing grayscale image, set the property with all RGB components eqaul. + /// + /// Default value is set to (0, 0, 0) - black colour. + /// + public Color BackgroundThreshold + { + get { return Color.FromArgb(backgroundThresholdR, backgroundThresholdG, backgroundThresholdB); } + set + { + backgroundThresholdR = value.R; + backgroundThresholdG = value.G; + backgroundThresholdB = value.B; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Creates new instance of the class with + /// an empty objects map. Before using methods, which provide information about blobs + /// or extract them, the , + /// or + /// method should be called to collect objects map. + /// + public BlobCounter() { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Image to look for objects in. + /// + public BlobCounter(Bitmap image) : base(image) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Image data to look for objects in. + /// + public BlobCounter(BitmapData imageData) : base(imageData) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Unmanaged image to look for objects in. + /// + public BlobCounter(UnmanagedImage image) : base(image) { } + + /// + /// Actual objects map building. + /// + /// + /// Unmanaged image to process. + /// + /// The method supports 8 bpp indexed grayscale images and 24/32 bpp color images. + /// + /// Unsupported pixel format of the source image. + /// Cannot process images that are one pixel wide. Rotate the image + /// or use . + /// + protected override void BuildObjectsMap(UnmanagedImage image) + { + int stride = image.Stride; + + // check pixel format + if ((image.PixelFormat != PixelFormat.Format8bppIndexed) && + (image.PixelFormat != PixelFormat.Format24bppRgb) && + (image.PixelFormat != PixelFormat.Format32bppRgb) && + (image.PixelFormat != PixelFormat.Format32bppArgb) && + (image.PixelFormat != PixelFormat.Format32bppPArgb)) + { + throw new UnsupportedImageFormatException("Unsupported pixel format of the source image."); + } + + // we don't want one pixel width images + if (imageWidth == 1) + { + throw new InvalidImagePropertiesException("BlobCounter cannot process images that are one pixel wide. Rotate the image or use RecursiveBlobCounter."); + } + + int imageWidthM1 = imageWidth - 1; + + // allocate labels array + objectLabels = new int[imageWidth * imageHeight]; + // initial labels count + int labelsCount = 0; + + // create map + int maxObjects = ((imageWidth / 2) + 1) * ((imageHeight / 2) + 1) + 1; + int[] map = new int[maxObjects]; + + // initially map all labels to themself + for (int i = 0; i < maxObjects; i++) + { + map[i] = i; + } + + // do the job + unsafe + { + byte* src = (byte*)image.ImageData.ToPointer(); + int p = 0; + + if (image.PixelFormat == PixelFormat.Format8bppIndexed) + { + int offset = stride - imageWidth; + + // 1 - for pixels of the first row + if (*src > backgroundThresholdG) + { + objectLabels[p] = ++labelsCount; + } + ++src; + ++p; + + // process the rest of the first row + for (int x = 1; x < imageWidth; x++, src++, p++) + { + // check if we need to label current pixel + if (*src > backgroundThresholdG) + { + // check if the previous pixel already was labeled + if (src[-1] > backgroundThresholdG) + { + // label current pixel, as the previous + objectLabels[p] = objectLabels[p - 1]; + } + else + { + // create new label + objectLabels[p] = ++labelsCount; + } + } + } + src += offset; + + // 2 - for other rows + // for each row + for (int y = 1; y < imageHeight; y++) + { + // for the first pixel of the row, we need to check + // only upper and upper-right pixels + if (*src > backgroundThresholdG) + { + // check surrounding pixels + if (src[-stride] > backgroundThresholdG) + { + // label current pixel, as the above + objectLabels[p] = objectLabels[p - imageWidth]; + } + else if (src[1 - stride] > backgroundThresholdG) + { + // label current pixel, as the above right + objectLabels[p] = objectLabels[p + 1 - imageWidth]; + } + else + { + // create new label + objectLabels[p] = ++labelsCount; + } + } + ++src; + ++p; + + // check left pixel and three upper pixels for the rest of pixels + for (int x = 1; x < imageWidthM1; x++, src++, p++) + { + if (*src > backgroundThresholdG) + { + // check surrounding pixels + if (src[-1] > backgroundThresholdG) + { + // label current pixel, as the left + objectLabels[p] = objectLabels[p - 1]; + } + else if (src[-1 - stride] > backgroundThresholdG) + { + // label current pixel, as the above left + objectLabels[p] = objectLabels[p - 1 - imageWidth]; + } + else if (src[-stride] > backgroundThresholdG) + { + // label current pixel, as the above + objectLabels[p] = objectLabels[p - imageWidth]; + } + + if (src[1 - stride] > backgroundThresholdG) + { + if (objectLabels[p] == 0) + { + // label current pixel, as the above right + objectLabels[p] = objectLabels[p + 1 - imageWidth]; + } + else + { + int l1 = objectLabels[p]; + int l2 = objectLabels[p + 1 - imageWidth]; + + if ((l1 != l2) && (map[l1] != map[l2])) + { + // merge + if (map[l1] == l1) + { + // map left value to the right + map[l1] = map[l2]; + } + else if (map[l2] == l2) + { + // map right value to the left + map[l2] = map[l1]; + } + else + { + // both values already mapped + map[map[l1]] = map[l2]; + map[l1] = map[l2]; + } + + // reindex + for (int i = 1; i <= labelsCount; i++) + { + if (map[i] != i) + { + // reindex + int j = map[i]; + while (j != map[j]) + { + j = map[j]; + } + map[i] = j; + } + } + } + } + } + + // label the object if it is not yet + if (objectLabels[p] == 0) + { + // create new label + objectLabels[p] = ++labelsCount; + } + } + } + + // for the last pixel of the row, we need to check + // only upper and upper-left pixels + if (*src > backgroundThresholdG) + { + // check surrounding pixels + if (src[-1] > backgroundThresholdG) + { + // label current pixel, as the left + objectLabels[p] = objectLabels[p - 1]; + } + else if (src[-1 - stride] > backgroundThresholdG) + { + // label current pixel, as the above left + objectLabels[p] = objectLabels[p - 1 - imageWidth]; + } + else if (src[-stride] > backgroundThresholdG) + { + // label current pixel, as the above + objectLabels[p] = objectLabels[p - imageWidth]; + } + else + { + // create new label + objectLabels[p] = ++labelsCount; + } + } + ++src; + ++p; + + src += offset; + } + } + else + { + // color images + int pixelSize = Bitmap.GetPixelFormatSize(image.PixelFormat) / 8; + int offset = stride - imageWidth * pixelSize; + + int strideM1 = stride - pixelSize; + int strideP1 = stride + pixelSize; + + // 1 - for pixels of the first row + if ((src[RGB.R] | src[RGB.G] | src[RGB.B]) != 0) + { + objectLabels[p] = ++labelsCount; + } + src += pixelSize; + ++p; + + // process the rest of the first row + for (int x = 1; x < imageWidth; x++, src += pixelSize, p++) + { + // check if we need to label current pixel + if ((src[RGB.R] > backgroundThresholdR) || + (src[RGB.G] > backgroundThresholdG) || + (src[RGB.B] > backgroundThresholdB)) + { + // check if the previous pixel already was labeled + if ((src[RGB.R - pixelSize] > backgroundThresholdR) || + (src[RGB.G - pixelSize] > backgroundThresholdG) || + (src[RGB.B - pixelSize] > backgroundThresholdB)) + { + // label current pixel, as the previous + objectLabels[p] = objectLabels[p - 1]; + } + else + { + // create new label + objectLabels[p] = ++labelsCount; + } + } + } + src += offset; + + // 2 - for other rows + // for each row + for (int y = 1; y < imageHeight; y++) + { + // for the first pixel of the row, we need to check + // only upper and upper-right pixels + if ((src[RGB.R] > backgroundThresholdR) || + (src[RGB.G] > backgroundThresholdG) || + (src[RGB.B] > backgroundThresholdB)) + { + // check surrounding pixels + if ((src[RGB.R - stride] > backgroundThresholdR) || + (src[RGB.G - stride] > backgroundThresholdG) || + (src[RGB.B - stride] > backgroundThresholdB)) + { + // label current pixel, as the above + objectLabels[p] = objectLabels[p - imageWidth]; + } + else if ((src[RGB.R - strideM1] > backgroundThresholdR) || + (src[RGB.G - strideM1] > backgroundThresholdG) || + (src[RGB.B - strideM1] > backgroundThresholdB)) + { + // label current pixel, as the above right + objectLabels[p] = objectLabels[p + 1 - imageWidth]; + } + else + { + // create new label + objectLabels[p] = ++labelsCount; + } + } + src += pixelSize; + ++p; + + // check left pixel and three upper pixels for the rest of pixels + for (int x = 1; x < imageWidth - 1; x++, src += pixelSize, p++) + { + if ((src[RGB.R] > backgroundThresholdR) || + (src[RGB.G] > backgroundThresholdG) || + (src[RGB.B] > backgroundThresholdB)) + { + // check surrounding pixels + if ((src[RGB.R - pixelSize] > backgroundThresholdR) || + (src[RGB.G - pixelSize] > backgroundThresholdG) || + (src[RGB.B - pixelSize] > backgroundThresholdB)) + { + // label current pixel, as the left + objectLabels[p] = objectLabels[p - 1]; + } + else if ((src[RGB.R - strideP1] > backgroundThresholdR) || + (src[RGB.G - strideP1] > backgroundThresholdG) || + (src[RGB.B - strideP1] > backgroundThresholdB)) + { + // label current pixel, as the above left + objectLabels[p] = objectLabels[p - 1 - imageWidth]; + } + else if ((src[RGB.R - stride] > backgroundThresholdR) || + (src[RGB.G - stride] > backgroundThresholdG) || + (src[RGB.B - stride] > backgroundThresholdB)) + { + // label current pixel, as the above + objectLabels[p] = objectLabels[p - imageWidth]; + } + + if ((src[RGB.R - strideM1] > backgroundThresholdR) || + (src[RGB.G - strideM1] > backgroundThresholdG) || + (src[RGB.B - strideM1] > backgroundThresholdB)) + { + if (objectLabels[p] == 0) + { + // label current pixel, as the above right + objectLabels[p] = objectLabels[p + 1 - imageWidth]; + } + else + { + int l1 = objectLabels[p]; + int l2 = objectLabels[p + 1 - imageWidth]; + + if ((l1 != l2) && (map[l1] != map[l2])) + { + // merge + if (map[l1] == l1) + { + // map left value to the right + map[l1] = map[l2]; + } + else if (map[l2] == l2) + { + // map right value to the left + map[l2] = map[l1]; + } + else + { + // both values already mapped + map[map[l1]] = map[l2]; + map[l1] = map[l2]; + } + + // reindex + for (int i = 1; i <= labelsCount; i++) + { + if (map[i] != i) + { + // reindex + int j = map[i]; + while (j != map[j]) + { + j = map[j]; + } + map[i] = j; + } + } + } + } + } + + // label the object if it is not yet + if (objectLabels[p] == 0) + { + // create new label + objectLabels[p] = ++labelsCount; + } + } + } + + // for the last pixel of the row, we need to check + // only upper and upper-left pixels + if ((src[RGB.R] > backgroundThresholdR) || + (src[RGB.G] > backgroundThresholdG) || + (src[RGB.B] > backgroundThresholdB)) + { + // check surrounding pixels + if ((src[RGB.R - pixelSize] > backgroundThresholdR) || + (src[RGB.G - pixelSize] > backgroundThresholdG) || + (src[RGB.B - pixelSize] > backgroundThresholdB)) + { + // label current pixel, as the left + objectLabels[p] = objectLabels[p - 1]; + } + else if ((src[RGB.R - strideP1] > backgroundThresholdR) || + (src[RGB.G - strideP1] > backgroundThresholdG) || + (src[RGB.B - strideP1] > backgroundThresholdB)) + { + // label current pixel, as the above left + objectLabels[p] = objectLabels[p - 1 - imageWidth]; + } + else if ((src[RGB.R - stride] > backgroundThresholdR) || + (src[RGB.G - stride] > backgroundThresholdG) || + (src[RGB.B - stride] > backgroundThresholdB)) + { + // label current pixel, as the above + objectLabels[p] = objectLabels[p - imageWidth]; + } + else + { + // create new label + objectLabels[p] = ++labelsCount; + } + } + src += pixelSize; + ++p; + + src += offset; + } + } + } + + // allocate remapping array + int[] reMap = new int[map.Length]; + + // count objects and prepare remapping array + objectsCount = 0; + for (int i = 1; i <= labelsCount; i++) + { + if (map[i] == i) + { + // increase objects count + reMap[i] = ++objectsCount; + } + } + // second pass to complete remapping + for (int i = 1; i <= labelsCount; i++) + { + if (map[i] != i) + { + reMap[i] = reMap[map[i]]; + } + } + + // repair object labels + for (int i = 0, n = objectLabels.Length; i < n; i++) + { + objectLabels[i] = reMap[objectLabels[i]]; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/BlobCounterBase.cs b/Sources/Accord.Imaging/AForge/BlobCounterBase.cs new file mode 100644 index 0000000000..f46b9fbdf --- /dev/null +++ b/Sources/Accord.Imaging/AForge/BlobCounterBase.cs @@ -0,0 +1,1370 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2012 +// contacts@aforgenet.com +// + +namespace AForge.Imaging +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + using AForge; + + /// + /// Possible object orders. + /// + /// + /// The enumeration defines possible sorting orders of objects, found by blob + /// counting classes. + /// + public enum ObjectsOrder + { + /// + /// Unsorted order (as it is collected by algorithm). + /// + None, + + /// + /// Objects are sorted by size in descending order (bigger objects go first). + /// Size is calculated as Width * Height. + /// + Size, + + /// + /// Objects are sorted by area in descending order (bigger objects go first). + /// + Area, + + /// + /// Objects are sorted by Y coordinate, then by X coordinate in ascending order + /// (smaller coordinates go first). + /// + YX, + + /// + /// Objects are sorted by X coordinate, then by Y coordinate in ascending order + /// (smaller coordinates go first). + /// + XY + } + + /// + /// Base class for different blob counting algorithms. + /// + /// + /// The class is abstract and serves as a base for different blob counting algorithms. + /// Classes, which inherit from this base class, require to implement + /// method, which does actual building of object's label's map. + /// + /// For blobs' searcing usually all inherited classes accept binary images, which are actually + /// grayscale thresholded images. But the exact supported format should be checked in particular class, + /// inheriting from the base class. For blobs' extraction the class supports grayscale (8 bpp indexed) + /// and color images (24 and 32 bpp). + /// + /// Sample usage: + /// + /// // create an instance of blob counter algorithm + /// BlobCounterBase bc = new ... + /// // set filtering options + /// bc.FilterBlobs = true; + /// bc.MinWidth = 5; + /// bc.MinHeight = 5; + /// // process binary image + /// bc.ProcessImage( image ); + /// Blob[] blobs = bc.GetObjects( image, false ); + /// // process blobs + /// foreach ( Blob blob in blobs ) + /// { + /// // ... + /// // blob.Rectangle - blob's rectangle + /// // blob.Image - blob's image + /// } + /// + /// + /// + public abstract class BlobCounterBase + { + // found blobs + List blobs = new List(); + + // objects' sort order + private ObjectsOrder objectsOrder = ObjectsOrder.None; + + // filtering by size is required or not + private bool filterBlobs = false; + private IBlobsFilter filter = null; + + // coupled size filtering or not + private bool coupledSizeFiltering = false; + + // blobs' minimal and maximal size + private int minWidth = 1; + private int minHeight = 1; + private int maxWidth = int.MaxValue; + private int maxHeight = int.MaxValue; + + /// + /// Objects count. + /// + protected int objectsCount; + + /// + /// Objects' labels. + /// + protected int[] objectLabels; + + /// + /// Width of processed image. + /// + protected int imageWidth; + + /// + /// Height of processed image. + /// + protected int imageHeight; + + /// + /// Objects count. + /// + /// + /// Number of objects (blobs) found by method. + /// + /// + public int ObjectsCount + { + get { return objectsCount; } + } + + /// + /// Objects' labels. + /// + /// + /// The array of width * height size, which holds + /// labels for all objects. Background is represented with 0 value, + /// but objects are represented with labels starting from 1. + /// + public int[] ObjectLabels + { + get { return objectLabels; } + } + + /// + /// Objects sort order. + /// + /// + /// The property specifies objects' sort order, which are provided + /// by , , etc. + /// + /// + public ObjectsOrder ObjectsOrder + { + get { return objectsOrder; } + set { objectsOrder = value; } + } + + /// + /// Specifies if blobs should be filtered. + /// + /// + /// If the property is equal to false, then there is no any additional + /// post processing after image was processed. If the property is set to true, then + /// blobs filtering is done right after image processing routine. If + /// is set, then custom blobs' filtering is done, which is implemented by user. Otherwise + /// blobs are filtered according to dimensions specified in , + /// , and properties. + /// + /// Default value is set to . + /// + public bool FilterBlobs + { + get { return filterBlobs; } + set { filterBlobs = value; } + } + + /// + /// Specifies if size filetering should be coupled or not. + /// + /// + /// In uncoupled filtering mode, objects are filtered out in the case if + /// their width is smaller than or height is smaller than + /// . But in coupled filtering mode, objects are filtered out in + /// the case if their width is smaller than and height is + /// smaller than . In both modes the idea with filtering by objects' + /// maximum size is the same as filtering by objects' minimum size. + /// + /// Default value is set to , what means uncoupled filtering by size. + /// + /// + public bool CoupledSizeFiltering + { + get { return coupledSizeFiltering; } + set { coupledSizeFiltering = value; } + } + + /// + /// Minimum allowed width of blob. + /// + /// + /// The property specifies minimum object's width acceptable by blob counting + /// routine and has power only when property is set to + /// and custom blobs' filter is + /// set to . + /// + /// See documentation to for additional information. + /// + /// + public int MinWidth + { + get { return minWidth; } + set { minWidth = value; } + } + + /// + /// Minimum allowed height of blob. + /// + /// + /// The property specifies minimum object's height acceptable by blob counting + /// routine and has power only when property is set to + /// and custom blobs' filter is + /// set to . + /// + /// See documentation to for additional information. + /// + /// + public int MinHeight + { + get { return minHeight; } + set { minHeight = value; } + } + + /// + /// Maximum allowed width of blob. + /// + /// + /// The property specifies maximum object's width acceptable by blob counting + /// routine and has power only when property is set to + /// and custom blobs' filter is + /// set to . + /// + /// See documentation to for additional information. + /// + /// + public int MaxWidth + { + get { return maxWidth; } + set { maxWidth = value; } + } + + /// + /// Maximum allowed height of blob. + /// + /// + /// The property specifies maximum object's height acceptable by blob counting + /// routine and has power only when property is set to + /// and custom blobs' filter is + /// set to . + /// + /// See documentation to for additional information. + /// + /// + public int MaxHeight + { + get { return maxHeight; } + set { maxHeight = value; } + } + + /// + /// Custom blobs' filter to use. + /// + /// + /// The property specifies custom blobs' filtering routine to use. It has + /// effect only in the case if property is set to . + /// + /// When custom blobs' filtering routine is set, it has priority over default filtering done + /// with , , and . + /// + /// + public IBlobsFilter BlobsFilter + { + get { return filter; } + set { filter = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Creates new instance of the class with + /// an empty objects map. Before using methods, which provide information about blobs + /// or extract them, the , + /// or + /// method should be called to collect objects map. + /// + protected BlobCounterBase() { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Binary image to look for objects in. + /// + /// Creates new instance of the class with + /// initialized objects map built by calling method. + /// + protected BlobCounterBase(Bitmap image) + { + ProcessImage(image); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Binary image data to look for objects in. + /// + /// Creates new instance of the class with + /// initialized objects map built by calling method. + /// + protected BlobCounterBase(BitmapData imageData) + { + ProcessImage(imageData); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Unmanaged binary image to look for objects in. + /// + /// Creates new instance of the class with + /// initialized objects map built by calling method. + /// + protected BlobCounterBase(UnmanagedImage image) + { + ProcessImage(image); + } + + /// + /// Build objects map. + /// + /// + /// Source binary image. + /// + /// Processes the image and builds objects map, which is used later to extracts blobs. + /// + /// Unsupported pixel format of the source image. + /// + public void ProcessImage(Bitmap image) + { + // lock source bitmap data + BitmapData imageData = image.LockBits( + new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, image.PixelFormat); + + try + { + // process image + ProcessImage(imageData); + } + finally + { + // unlock source image + image.UnlockBits(imageData); + } + } + + /// + /// Build objects map. + /// + /// + /// Source binary image data. + /// + /// Processes the image and builds objects map, which is used later to extracts blobs. + /// + /// Unsupported pixel format of the source image. + /// + public void ProcessImage(BitmapData imageData) + { + // do actual objects map building + ProcessImage(new UnmanagedImage(imageData)); + } + + /// + /// Build object map from raw image data. + /// + /// + /// Source unmanaged binary image data. + /// + /// Processes the image and builds objects map, which is used later to extracts blobs. + /// + /// Unsupported pixel format of the source image. + /// Thrown by some inherited classes if some image property other + /// than the pixel format is not supported. See that class's documentation or the exception message for details. + /// + public void ProcessImage(UnmanagedImage image) + { + imageWidth = image.Width; + imageHeight = image.Height; + + // do actual objects map building + BuildObjectsMap(image); + + // collect information about blobs + CollectObjectsInfo(image); + + // filter blobs by size if required + if (filterBlobs) + { + // labels remapping array + int[] labelsMap = new int[objectsCount + 1]; + for (int i = 1; i <= objectsCount; i++) + { + labelsMap[i] = i; + } + + // check dimension of all objects and filter them + int objectsToRemove = 0; + + if (filter == null) + { + for (int i = objectsCount - 1; i >= 0; i--) + { + int blobWidth = blobs[i].Rectangle.Width; + int blobHeight = blobs[i].Rectangle.Height; + + if (coupledSizeFiltering == false) + { + // uncoupled filtering + if ( + (blobWidth < minWidth) || (blobHeight < minHeight) || + (blobWidth > maxWidth) || (blobHeight > maxHeight)) + { + labelsMap[i + 1] = 0; + objectsToRemove++; + blobs.RemoveAt(i); + } + } + else + { + // coupled filtering + if ( + ((blobWidth < minWidth) && (blobHeight < minHeight)) || + ((blobWidth > maxWidth) && (blobHeight > maxHeight))) + { + labelsMap[i + 1] = 0; + objectsToRemove++; + blobs.RemoveAt(i); + } + } + } + } + else + { + for (int i = objectsCount - 1; i >= 0; i--) + { + if (!filter.Check(blobs[i])) + { + labelsMap[i + 1] = 0; + objectsToRemove++; + blobs.RemoveAt(i); + } + } + } + + // update labels remapping array + int label = 0; + for (int i = 1; i <= objectsCount; i++) + { + if (labelsMap[i] != 0) + { + label++; + // update remapping array + labelsMap[i] = label; + } + } + + // repair object labels + for (int i = 0, n = objectLabels.Length; i < n; i++) + { + objectLabels[i] = labelsMap[objectLabels[i]]; + } + + objectsCount -= objectsToRemove; + + // repair IDs + for (int i = 0, n = blobs.Count; i < n; i++) + { + blobs[i].ID = i + 1; + } + } + + // do we need to sort the list? + if (objectsOrder != ObjectsOrder.None) + { + blobs.Sort(new BlobsSorter(objectsOrder)); + } + } + + /// + /// Get objects' rectangles. + /// + /// + /// Returns array of objects' rectangles. + /// + /// The method returns array of objects rectangles. Before calling the + /// method, the , + /// or method should be called, which will + /// build objects map. + /// + /// No image was processed before, so objects' rectangles + /// can not be collected. + /// + public Rectangle[] GetObjectsRectangles() + { + // check if objects map was collected + if (objectLabels == null) + throw new InvalidOperationException("Image should be processed before to collect objects map."); + + Rectangle[] rects = new Rectangle[objectsCount]; + + for (int i = 0; i < objectsCount; i++) + { + rects[i] = blobs[i].Rectangle; + } + + return rects; + } + + /// + /// Get objects' information. + /// + /// + /// Returns array of partially initialized blobs (without property initialized). + /// + /// By the amount of provided information, the method is between and + /// methods. The method provides array of blobs without initialized their image. + /// Blob's image may be extracted later using + /// or method. + /// + /// + /// + /// + /// // create blob counter and process image + /// BlobCounter bc = new BlobCounter( sourceImage ); + /// // specify sort order + /// bc.ObjectsOrder = ObjectsOrder.Size; + /// // get objects' information (blobs without image) + /// Blob[] blobs = bc.GetObjectInformation( ); + /// // process blobs + /// foreach ( Blob blob in blobs ) + /// { + /// // check blob's properties + /// if ( blob.Rectangle.Width > 50 ) + /// { + /// // the blob looks interesting, let's extract it + /// bc.ExtractBlobsImage( sourceImage, blob ); + /// } + /// } + /// + /// + /// + /// No image was processed before, so objects' information + /// can not be collected. + /// + public Blob[] GetObjectsInformation() + { + // check if objects map was collected + if (objectLabels == null) + throw new InvalidOperationException("Image should be processed before to collect objects map."); + + Blob[] blobsToReturn = new Blob[objectsCount]; + + // create each blob + for (int k = 0; k < objectsCount; k++) + { + blobsToReturn[k] = new Blob(blobs[k]); + } + + return blobsToReturn; + } + + /// + /// Get blobs. + /// + /// + /// Source image to extract objects from. + /// + /// Returns array of blobs. + /// Specifies size of blobs' image to extract. + /// If set to each blobs' image will have the same size as + /// the specified image. If set to each blobs' image will + /// have the size of its blob. + /// + /// The method returns array of blobs. Before calling the + /// method, the , + /// or method should be called, which will build + /// objects map. + /// + /// The method supports 24/32 bpp color and 8 bpp indexed grayscale images. + /// + /// + /// Unsupported pixel format of the provided image. + /// No image was processed before, so objects + /// can not be collected. + /// + public Blob[] GetObjects(Bitmap image, bool extractInOriginalSize) + { + Blob[] blobs = null; + // lock source bitmap data + BitmapData imageData = image.LockBits( + new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, image.PixelFormat); + + try + { + // process image + blobs = GetObjects(new UnmanagedImage(imageData), extractInOriginalSize); + } + finally + { + // unlock source images + image.UnlockBits(imageData); + } + return blobs; + } + + /// + /// Get blobs. + /// + /// + /// Source unmanaged image to extract objects from. + /// Specifies size of blobs' image to extract. + /// If set to each blobs' image will have the same size as + /// the specified image. If set to each blobs' image will + /// have the size of its blob. + /// + /// Returns array of blobs. + /// + /// The method returns array of blobs. Before calling the + /// method, the , + /// or method should be called, which will build + /// objects map. + /// + /// The method supports 24/32 bpp color and 8 bpp indexed grayscale images. + /// + /// + /// Unsupported pixel format of the provided image. + /// No image was processed before, so objects + /// can not be collected. + /// + public Blob[] GetObjects(UnmanagedImage image, bool extractInOriginalSize) + { + // check if objects map was collected + if (objectLabels == null) + throw new InvalidOperationException("Image should be processed before to collect objects map."); + + if ((image.PixelFormat != PixelFormat.Format24bppRgb) && + (image.PixelFormat != PixelFormat.Format8bppIndexed) && + (image.PixelFormat != PixelFormat.Format32bppRgb) && + (image.PixelFormat != PixelFormat.Format32bppArgb) && + (image.PixelFormat != PixelFormat.Format32bppRgb) && + (image.PixelFormat != PixelFormat.Format32bppPArgb) + ) + throw new UnsupportedImageFormatException("Unsupported pixel format of the provided image."); + + // image size + int width = image.Width; + int height = image.Height; + int srcStride = image.Stride; + int pixelSize = Bitmap.GetPixelFormatSize(image.PixelFormat) / 8; + + Blob[] objects = new Blob[objectsCount]; + + // create each image + for (int k = 0; k < objectsCount; k++) + { + int objectWidth = blobs[k].Rectangle.Width; + int objectHeight = blobs[k].Rectangle.Height; + + int blobImageWidth = (extractInOriginalSize) ? width : objectWidth; + int blobImageHeight = (extractInOriginalSize) ? height : objectHeight; + + int xmin = blobs[k].Rectangle.X; + int xmax = xmin + objectWidth - 1; + int ymin = blobs[k].Rectangle.Y; + int ymax = ymin + objectHeight - 1; + + int label = blobs[k].ID; + + // create new image + UnmanagedImage dstImage = UnmanagedImage.Create(blobImageWidth, blobImageHeight, image.PixelFormat); + + // copy image + unsafe + { + byte* src = (byte*)image.ImageData.ToPointer() + ymin * srcStride + xmin * pixelSize; + byte* dst = (byte*)dstImage.ImageData.ToPointer(); + int p = ymin * width + xmin; + + if (extractInOriginalSize) + { + // allign destination pointer also + dst += ymin * dstImage.Stride + xmin * pixelSize; + } + + int srcOffset = srcStride - objectWidth * pixelSize; + int dstOffset = dstImage.Stride - objectWidth * pixelSize; + int labelsOffset = width - objectWidth; + + // for each line + for (int y = ymin; y <= ymax; y++) + { + // copy each pixel + for (int x = xmin; x <= xmax; x++, p++, dst += pixelSize, src += pixelSize) + { + if (objectLabels[p] == label) + { + // copy pixel + *dst = *src; + + if (pixelSize > 1) + { + dst[1] = src[1]; + dst[2] = src[2]; + + if (pixelSize > 3) + { + dst[3] = src[3]; + } + } + } + } + src += srcOffset; + dst += dstOffset; + p += labelsOffset; + } + } + + objects[k] = new Blob(blobs[k]); + objects[k].Image = dstImage; + objects[k].OriginalSize = extractInOriginalSize; + } + + return objects; + } + + /// + /// Extract blob's image. + /// + /// + /// Source image to extract blob's image from. + /// Blob which is required to be extracted. + /// Specifies size of blobs' image to extract. + /// If set to each blobs' image will have the same size as + /// the specified image. If set to each blobs' image will + /// have the size of its blob. + /// + /// The method is used to extract image of partially initialized blob, which + /// was provided by method. Before calling the + /// method, the , + /// or method should be called, which will build + /// objects map. + /// + /// The method supports 24/32 bpp color and 8 bpp indexed grayscale images. + /// + /// + /// Unsupported pixel format of the provided image. + /// No image was processed before, so blob + /// can not be extracted. + /// + public void ExtractBlobsImage(Bitmap image, Blob blob, bool extractInOriginalSize) + { + // lock source bitmap data + BitmapData imageData = image.LockBits( + new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, image.PixelFormat); + + try + { + // process image + ExtractBlobsImage(new UnmanagedImage(imageData), blob, extractInOriginalSize); + } + finally + { + // unlock source images + image.UnlockBits(imageData); + } + } + + /// + /// Extract blob's image. + /// + /// + /// Source unmanaged image to extract blob's image from. + /// Blob which is required to be extracted. + /// Specifies size of blobs' image to extract. + /// If set to each blobs' image will have the same size as + /// the specified image. If set to each blobs' image will + /// have the size of its blob. + /// + /// The method is used to extract image of partially initialized blob, which + /// was provided by method. Before calling the + /// method, the , + /// or method should be called, which will build + /// objects map. + /// + /// The method supports 24/32 bpp color and 8 bpp indexed grayscale images. + /// + /// + /// Unsupported pixel format of the provided image. + /// No image was processed before, so blob + /// can not be extracted. + /// + public void ExtractBlobsImage(UnmanagedImage image, Blob blob, bool extractInOriginalSize) + { + // check if objects map was collected + if (objectLabels == null) + throw new InvalidOperationException("Image should be processed before to collect objects map."); + + if ((image.PixelFormat != PixelFormat.Format24bppRgb) && + (image.PixelFormat != PixelFormat.Format8bppIndexed) && + (image.PixelFormat != PixelFormat.Format32bppRgb) && + (image.PixelFormat != PixelFormat.Format32bppArgb) && + (image.PixelFormat != PixelFormat.Format32bppRgb) && + (image.PixelFormat != PixelFormat.Format32bppPArgb) + ) + throw new UnsupportedImageFormatException("Unsupported pixel format of the provided image."); + + // image size + int width = image.Width; + int height = image.Height; + int srcStride = image.Stride; + int pixelSize = Bitmap.GetPixelFormatSize(image.PixelFormat) / 8; + + int objectWidth = blob.Rectangle.Width; + int objectHeight = blob.Rectangle.Height; + + int blobImageWidth = (extractInOriginalSize) ? width : objectWidth; + int blobImageHeight = (extractInOriginalSize) ? height : objectHeight; + + int xmin = blob.Rectangle.Left; + int xmax = xmin + objectWidth - 1; + int ymin = blob.Rectangle.Top; + int ymax = ymin + objectHeight - 1; + + int label = blob.ID; + + // create new image + blob.Image = UnmanagedImage.Create(blobImageWidth, blobImageHeight, image.PixelFormat); + blob.OriginalSize = extractInOriginalSize; + + // copy image + unsafe + { + byte* src = (byte*)image.ImageData.ToPointer() + ymin * srcStride + xmin * pixelSize; + byte* dst = (byte*)blob.Image.ImageData.ToPointer(); + int p = ymin * width + xmin; + + if (extractInOriginalSize) + { + // allign destination pointer also + dst += ymin * blob.Image.Stride + xmin * pixelSize; + } + + int srcOffset = srcStride - objectWidth * pixelSize; + int dstOffset = blob.Image.Stride - objectWidth * pixelSize; + int labelsOffset = width - objectWidth; + + // for each line + for (int y = ymin; y <= ymax; y++) + { + // copy each pixel + for (int x = xmin; x <= xmax; x++, p++, dst += pixelSize, src += pixelSize) + { + if (objectLabels[p] == label) + { + // copy pixel + *dst = *src; + + if (pixelSize > 1) + { + dst[1] = src[1]; + dst[2] = src[2]; + + if (pixelSize > 3) + { + dst[3] = src[3]; + } + } + } + } + src += srcOffset; + dst += dstOffset; + p += labelsOffset; + } + } + } + + /// + /// Get list of points on the left and right edges of the blob. + /// + /// + /// Blob to collect edge points for. + /// List of points on the left edge of the blob. + /// List of points on the right edge of the blob. + /// + /// The method scans each line of the blob and finds the most left and the + /// most right points for it adding them to appropriate lists. The method may be very + /// useful in conjunction with different routines from , + /// which allow finding convex hull or quadrilateral's corners. + /// + /// Both lists of points are sorted by Y coordinate - points with smaller Y + /// value go first. + /// + /// + /// No image was processed before, so blob + /// can not be extracted. + /// + public void GetBlobsLeftAndRightEdges(Blob blob, out List leftEdge, out List rightEdge) + { + // check if objects map was collected + if (objectLabels == null) + throw new InvalidOperationException("Image should be processed before to collect objects map."); + + leftEdge = new List(); + rightEdge = new List(); + + int xmin = blob.Rectangle.Left; + int xmax = xmin + blob.Rectangle.Width - 1; + int ymin = blob.Rectangle.Top; + int ymax = ymin + blob.Rectangle.Height - 1; + + int label = blob.ID; + + // for each line + for (int y = ymin; y <= ymax; y++) + { + // scan from left to right + int p = y * imageWidth + xmin; + for (int x = xmin; x <= xmax; x++, p++) + { + if (objectLabels[p] == label) + { + leftEdge.Add(new IntPoint(x, y)); + break; + } + } + + // scan from right to left + p = y * imageWidth + xmax; + for (int x = xmax; x >= xmin; x--, p--) + { + if (objectLabels[p] == label) + { + rightEdge.Add(new IntPoint(x, y)); + break; + } + } + } + } + + /// + /// Get list of points on the top and bottom edges of the blob. + /// + /// + /// Blob to collect edge points for. + /// List of points on the top edge of the blob. + /// List of points on the bottom edge of the blob. + /// + /// The method scans each column of the blob and finds the most top and the + /// most bottom points for it adding them to appropriate lists. The method may be very + /// useful in conjunction with different routines from , + /// which allow finding convex hull or quadrilateral's corners. + /// + /// Both lists of points are sorted by X coordinate - points with smaller X + /// value go first. + /// + /// + /// No image was processed before, so blob + /// can not be extracted. + /// + public void GetBlobsTopAndBottomEdges(Blob blob, out List topEdge, out List bottomEdge) + { + // check if objects map was collected + if (objectLabels == null) + throw new InvalidOperationException("Image should be processed before to collect objects map."); + + topEdge = new List(); + bottomEdge = new List(); + + int xmin = blob.Rectangle.Left; + int xmax = xmin + blob.Rectangle.Width - 1; + int ymin = blob.Rectangle.Top; + int ymax = ymin + blob.Rectangle.Height - 1; + + int label = blob.ID; + + // for each column + for (int x = xmin; x <= xmax; x++) + { + // scan from top to bottom + int p = ymin * imageWidth + x; + for (int y = ymin; y <= ymax; y++, p += imageWidth) + { + if (objectLabels[p] == label) + { + topEdge.Add(new IntPoint(x, y)); + break; + } + } + + // scan from bottom to top + p = ymax * imageWidth + x; + for (int y = ymax; y >= ymin; y--, p -= imageWidth) + { + if (objectLabels[p] == label) + { + bottomEdge.Add(new IntPoint(x, y)); + break; + } + } + } + } + + /// + /// Get list of object's edge points. + /// + /// + /// Blob to collect edge points for. + /// + /// Returns unsorted list of blob's edge points. + /// + /// The method scans each row and column of the blob and finds the + /// most top/bottom/left/right points. The method returns similar result as if results of + /// both and + /// methods were combined, but each edge point occurs only once in the list. + /// + /// Edge points in the returned list are not ordered. This makes the list unusable + /// for visualization with methods, which draw polygon or poly-line. But the returned list + /// can be used with such algorithms, like convex hull search, shape analyzer, etc. + /// + /// + /// No image was processed before, so blob + /// can not be extracted. + /// + public List GetBlobsEdgePoints(Blob blob) + { + // check if objects map was collected + if (objectLabels == null) + throw new InvalidOperationException("Image should be processed before to collect objects map."); + + List edgePoints = new List(); + + int xmin = blob.Rectangle.Left; + int xmax = xmin + blob.Rectangle.Width - 1; + int ymin = blob.Rectangle.Top; + int ymax = ymin + blob.Rectangle.Height - 1; + + int label = blob.ID; + + // array of already processed points on left/right edges + // (index in these arrays represent Y coordinate, but value - X coordinate) + int[] leftProcessedPoints = new int[blob.Rectangle.Height]; + int[] rightProcessedPoints = new int[blob.Rectangle.Height]; + + // for each line + for (int y = ymin; y <= ymax; y++) + { + // scan from left to right + int p = y * imageWidth + xmin; + for (int x = xmin; x <= xmax; x++, p++) + { + if (objectLabels[p] == label) + { + edgePoints.Add(new IntPoint(x, y)); + leftProcessedPoints[y - ymin] = x; + break; + } + } + + // scan from right to left + p = y * imageWidth + xmax; + for (int x = xmax; x >= xmin; x--, p--) + { + if (objectLabels[p] == label) + { + // avoid adding the point we already have + if (leftProcessedPoints[y - ymin] != x) + { + edgePoints.Add(new IntPoint(x, y)); + } + rightProcessedPoints[y - ymin] = x; + break; + } + } + } + + // for each column + for (int x = xmin; x <= xmax; x++) + { + // scan from top to bottom + int p = ymin * imageWidth + x; + for (int y = ymin, y0 = 0; y <= ymax; y++, y0++, p += imageWidth) + { + if (objectLabels[p] == label) + { + // avoid adding the point we already have + if ((leftProcessedPoints[y0] != x) && + (rightProcessedPoints[y0] != x)) + { + edgePoints.Add(new IntPoint(x, y)); + } + break; + } + } + + // scan from bottom to top + p = ymax * imageWidth + x; + for (int y = ymax, y0 = ymax - ymin; y >= ymin; y--, y0--, p -= imageWidth) + { + if (objectLabels[p] == label) + { + // avoid adding the point we already have + if ((leftProcessedPoints[y0] != x) && + (rightProcessedPoints[y0] != x)) + { + edgePoints.Add(new IntPoint(x, y)); + } + break; + } + } + } + + return edgePoints; + } + + /// + /// Actual objects map building. + /// + /// + /// Unmanaged image to process. + /// + /// By the time this method is called bitmap's pixel format is not + /// yet checked, so this should be done by the class inheriting from the base class. + /// and members are initialized + /// before the method is called, so these members may be used safely. + /// + protected abstract void BuildObjectsMap(UnmanagedImage image); + + + #region Private Methods - Collecting objects' rectangles + + // Collect objects' rectangles + private unsafe void CollectObjectsInfo(UnmanagedImage image) + { + int i = 0, label; + + // create object coordinates arrays + int[] x1 = new int[objectsCount + 1]; + int[] y1 = new int[objectsCount + 1]; + int[] x2 = new int[objectsCount + 1]; + int[] y2 = new int[objectsCount + 1]; + + int[] area = new int[objectsCount + 1]; + long[] xc = new long[objectsCount + 1]; + long[] yc = new long[objectsCount + 1]; + + long[] meanR = new long[objectsCount + 1]; + long[] meanG = new long[objectsCount + 1]; + long[] meanB = new long[objectsCount + 1]; + + long[] stdDevR = new long[objectsCount + 1]; + long[] stdDevG = new long[objectsCount + 1]; + long[] stdDevB = new long[objectsCount + 1]; + + for (int j = 1; j <= objectsCount; j++) + { + x1[j] = imageWidth; + y1[j] = imageHeight; + } + + byte* src = (byte*)image.ImageData.ToPointer(); + + if (image.PixelFormat == PixelFormat.Format8bppIndexed) + { + int offset = image.Stride - imageWidth; + byte g; // pixel's grey value + + // walk through labels array + for (int y = 0; y < imageHeight; y++) + { + for (int x = 0; x < imageWidth; x++, i++, src++) + { + // get current label + label = objectLabels[i]; + + // skip unlabeled pixels + if (label == 0) + continue; + + // check and update all coordinates + + if (x < x1[label]) + { + x1[label] = x; + } + if (x > x2[label]) + { + x2[label] = x; + } + if (y < y1[label]) + { + y1[label] = y; + } + if (y > y2[label]) + { + y2[label] = y; + } + + area[label]++; + xc[label] += x; + yc[label] += y; + + g = *src; + meanG[label] += g; + stdDevG[label] += g * g; + } + + src += offset; + } + + for (int j = 1; j <= objectsCount; j++) + { + meanR[j] = meanB[j] = meanG[j]; + stdDevR[j] = stdDevB[j] = stdDevG[j]; + } + } + else + { + // color images + int pixelSize = Bitmap.GetPixelFormatSize(image.PixelFormat) / 8; + int offset = image.Stride - imageWidth * pixelSize; + byte r, g, b; // RGB value + + // walk through labels array + for (int y = 0; y < imageHeight; y++) + { + for (int x = 0; x < imageWidth; x++, i++, src += pixelSize) + { + // get current label + label = objectLabels[i]; + + // skip unlabeled pixels + if (label == 0) + continue; + + // check and update all coordinates + + if (x < x1[label]) + { + x1[label] = x; + } + if (x > x2[label]) + { + x2[label] = x; + } + if (y < y1[label]) + { + y1[label] = y; + } + if (y > y2[label]) + { + y2[label] = y; + } + + area[label]++; + xc[label] += x; + yc[label] += y; + + r = src[RGB.R]; + g = src[RGB.G]; + b = src[RGB.B]; + + meanR[label] += r; + meanG[label] += g; + meanB[label] += b; + + stdDevR[label] += r * r; + stdDevG[label] += g * g; + stdDevB[label] += b * b; + } + + src += offset; + } + } + + // create blobs + blobs.Clear(); + + for (int j = 1; j <= objectsCount; j++) + { + int blobArea = area[j]; + + Blob blob = new Blob(j, new Rectangle(x1[j], y1[j], x2[j] - x1[j] + 1, y2[j] - y1[j] + 1)); + blob.Area = blobArea; + blob.Fullness = (double)blobArea / ((x2[j] - x1[j] + 1) * (y2[j] - y1[j] + 1)); + blob.CenterOfGravity = new AForge.Point((float)xc[j] / blobArea, (float)yc[j] / blobArea); + blob.ColorMean = Color.FromArgb((byte)(meanR[j] / blobArea), (byte)(meanG[j] / blobArea), (byte)(meanB[j] / blobArea)); + blob.ColorStdDev = Color.FromArgb( + (byte)(Math.Sqrt(stdDevR[j] / blobArea - blob.ColorMean.R * blob.ColorMean.R)), + (byte)(Math.Sqrt(stdDevG[j] / blobArea - blob.ColorMean.G * blob.ColorMean.G)), + (byte)(Math.Sqrt(stdDevB[j] / blobArea - blob.ColorMean.B * blob.ColorMean.B))); + + blobs.Add(blob); + } + } + + // Rectangles' and blobs' sorter + private class BlobsSorter : System.Collections.Generic.IComparer + { + private ObjectsOrder order; + + public BlobsSorter(ObjectsOrder order) + { + this.order = order; + } + + public int Compare(Blob a, Blob b) + { + Rectangle aRect = a.Rectangle; + Rectangle bRect = b.Rectangle; + + switch (order) + { + case ObjectsOrder.Size: // sort by size + + // the order is changed to descending + return (bRect.Width * bRect.Height - aRect.Width * aRect.Height); + + case ObjectsOrder.Area: // sort by area + return b.Area - a.Area; + + case ObjectsOrder.YX: // YX order + + return ((aRect.Y * 100000 + aRect.X) - (bRect.Y * 100000 + bRect.X)); + + case ObjectsOrder.XY: // XY order + + return ((aRect.X * 100000 + aRect.Y) - (bRect.X * 100000 + bRect.Y)); + } + return 0; + } + } + + #endregion + } +} diff --git a/Sources/Accord.Imaging/AForge/BlockMatch.cs b/Sources/Accord.Imaging/AForge/BlockMatch.cs new file mode 100644 index 0000000000..003bec8d9 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/BlockMatch.cs @@ -0,0 +1,65 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging +{ + using System; + using System.Drawing; + + /// + /// Block match class keeps information about found block match. The class is + /// used with block matching algorithms implementing + /// interface. + /// + /// + public class BlockMatch + { + private IntPoint sourcePoint; + private IntPoint matchPoint; + private float similarity; + + /// + /// Reference point in source image. + /// + public IntPoint SourcePoint + { + get { return sourcePoint; } + } + + /// + /// Match point in search image (point of a found match). + /// + public IntPoint MatchPoint + { + get { return matchPoint; } + } + + /// + /// Similarity between blocks in source and search images, [0..1]. + /// + public float Similarity + { + get { return similarity; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Reference point in source image. + /// Match point in search image (point of a found match). + /// Similarity between blocks in source and search images, [0..1]. + /// + public BlockMatch(IntPoint sourcePoint, IntPoint matchPoint, float similarity) + { + this.sourcePoint = sourcePoint; + this.matchPoint = matchPoint; + this.similarity = similarity; + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Color Reduction/BurkesColorDithering.cs b/Sources/Accord.Imaging/AForge/Color Reduction/BurkesColorDithering.cs new file mode 100644 index 0000000000..a53725553 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Color Reduction/BurkesColorDithering.cs @@ -0,0 +1,71 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2010 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.ColorReduction +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Color dithering using Burkes error diffusion. + /// + /// + /// The image processing routine represents color dithering algorithm, which is based on + /// error diffusion dithering with Burkes coefficients. Error is diffused + /// on 7 neighbor pixels with next coefficients: + /// + /// | * | 8 | 4 | + /// | 2 | 4 | 8 | 4 | 2 | + /// + /// / 32 + /// + /// + /// The image processing routine accepts 24/32 bpp color images for processing. As a result this routine + /// produces 4 bpp or 8 bpp indexed image, which depends on size of the specified + /// color table - 4 bpp result for + /// color tables with 16 colors or less; 8 bpp result for larger color tables. + /// + /// Sample usage: + /// + /// // create color image quantization routine + /// ColorImageQuantizer ciq = new ColorImageQuantizer( new MedianCutQuantizer( ) ); + /// // create 8 colors table + /// Color[] colorTable = ciq.CalculatePalette( image, 8 ); + /// // create dithering routine + /// BurkesColorDithering dithering = new BurkesColorDithering( ); + /// dithering.ColorTable = colorTable; + /// // apply the dithering routine + /// Bitmap newImage = dithering.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + /// + /// + public sealed class BurkesColorDithering : ColorErrorDiffusionToAdjacentNeighbors + { + /// + /// Initializes a new instance of the class. + /// + /// + public BurkesColorDithering( ) + : base( new int[2][] { + new int[2] { 8, 4 }, + new int[5] { 2, 4, 8, 4, 2 } } ) + { + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Color Reduction/ColorErrorDiffusionToAdjacentNeighbors.cs b/Sources/Accord.Imaging/AForge/Color Reduction/ColorErrorDiffusionToAdjacentNeighbors.cs new file mode 100644 index 0000000000..2706070c1 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Color Reduction/ColorErrorDiffusionToAdjacentNeighbors.cs @@ -0,0 +1,194 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2010 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.ColorReduction +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Base class for error diffusion color dithering, where error is diffused to + /// adjacent neighbor pixels. + /// + /// + /// The class does error diffusion to adjacent neighbor pixels + /// using specified set of coefficients. These coefficients are represented by + /// 2 dimensional jugged array, where first array of coefficients is for + /// right-standing pixels, but the rest of arrays are for bottom-standing pixels. + /// All arrays except the first one should have odd number of coefficients. + /// + /// Suppose that error diffusion coefficients are represented by the next + /// jugged array: + /// + /// + /// int[][] coefficients = new int[2][] { + /// new int[1] { 7 }, + /// new int[3] { 3, 5, 1 } + /// }; + /// + /// + /// The above coefficients are used to diffuse error over the next neighbor + /// pixels (* marks current pixel, coefficients are placed to corresponding + /// neighbor pixels): + /// + /// | * | 7 | + /// | 3 | 5 | 1 | + /// + /// / 16 + /// + /// + /// The image processing routine accepts 24/32 bpp color images for processing. + /// + /// Sample usage: + /// + /// // create dithering routine + /// ColorErrorDiffusionToAdjacentNeighbors dithering = new ColorErrorDiffusionToAdjacentNeighbors( + /// new int[3][] { + /// new int[2] { 5, 3 }, + /// new int[5] { 2, 4, 5, 4, 2 }, + /// new int[3] { 2, 3, 2 } + /// } ); + /// // apply the dithering routine + /// Bitmap newImage = dithering.Apply( image ); + /// + /// + /// + public class ColorErrorDiffusionToAdjacentNeighbors : ErrorDiffusionColorDithering + { + // diffusion coefficients + private int[][] coefficients; + // sum of all coefficients + private int coefficientsSum; + + /// + /// Diffusion coefficients. + /// + /// + /// Set of coefficients, which are used for error diffusion to + /// pixel's neighbors. + /// + public int[][] Coefficients + { + get { return coefficients; } + set + { + coefficients = value; + CalculateCoefficientsSum( ); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Diffusion coefficients (see + /// for more information). + /// + public ColorErrorDiffusionToAdjacentNeighbors( int[][] coefficients ) + { + this.coefficients = coefficients; + CalculateCoefficientsSum( ); + } + + /// + /// Do error diffusion. + /// + /// + /// Error value of red component. + /// Error value of green component. + /// Error value of blue component. + /// Pointer to current processing pixel. + /// + /// All parameters of the image and current processing pixel's coordinates + /// are initialized by base class. + /// + protected override unsafe void Diffuse( int rError, int gError, int bError, byte* ptr ) + { + int edR; // error diffusion + int edG; // error diffusion + int edB; // error diffusion + + // do error diffusion to right-standing neighbors + int[] coefficientsRow = coefficients[0]; + + for ( int jI = 1, jP = pixelSize, jC = 0, k = coefficientsRow.Length; jC < k; jI++, jC++, jP += pixelSize ) + { + if ( x + jI >= width ) + break; + + edR = ptr[jP + RGB.R] + ( rError * coefficientsRow[jC] ) / coefficientsSum; + edR = ( edR < 0 ) ? 0 : ( ( edR > 255 ) ? 255 : edR ); + ptr[jP + RGB.R] = (byte) edR; + + edG = ptr[jP + RGB.G] + ( gError * coefficientsRow[jC] ) / coefficientsSum; + edG = ( edG < 0 ) ? 0 : ( ( edG > 255 ) ? 255 : edG ); + ptr[jP + RGB.G] = (byte) edG; + + edB = ptr[jP + RGB.B] + ( bError * coefficientsRow[jC] ) / coefficientsSum; + edB = ( edB < 0 ) ? 0 : ( ( edB > 255 ) ? 255 : edB ); + ptr[jP + RGB.B] = (byte) edB; + } + + // do error diffusion to bottom neigbors + for ( int i = 1, n = coefficients.Length; i < n; i++ ) + { + if ( y + i >= height ) + break; + + // move pointer to next image line + ptr += stride; + + // get coefficients of the row + coefficientsRow = coefficients[i]; + + // process the row + for ( int jC = 0, k = coefficientsRow.Length, jI = -( k >> 1 ), jP = -( k >> 1 ) * pixelSize; jC < k; jI++, jC++, jP += pixelSize ) + { + if ( x + jI >= width ) + break; + if ( x + jI < 0 ) + continue; + + edR = ptr[jP + RGB.R] + ( rError * coefficientsRow[jC] ) / coefficientsSum; + edR = ( edR < 0 ) ? 0 : ( ( edR > 255 ) ? 255 : edR ); + ptr[jP + RGB.R] = (byte) edR; + + edG = ptr[jP + RGB.G] + ( gError * coefficientsRow[jC] ) / coefficientsSum; + edG = ( edG < 0 ) ? 0 : ( ( edG > 255 ) ? 255 : edG ); + ptr[jP + RGB.G] = (byte) edG; + + edB = ptr[jP + RGB.B] + ( bError * coefficientsRow[jC] ) / coefficientsSum; + edB = ( edB < 0 ) ? 0 : ( ( edB > 255 ) ? 255 : edB ); + ptr[jP + RGB.B] = (byte) edB; + + } + } + } + + #region Private Members + + // Calculate coefficients' sum + private void CalculateCoefficientsSum( ) + { + coefficientsSum = 0; + + for ( int i = 0, n = coefficients.Length; i < n; i++ ) + { + int[] coefficientsRow = coefficients[i]; + + for ( int j = 0, k = coefficientsRow.Length; j < k; j++ ) + { + coefficientsSum += coefficientsRow[j]; + } + } + } + + #endregion + } +} diff --git a/Sources/Accord.Imaging/AForge/Color Reduction/ColorImageQuantizer.cs b/Sources/Accord.Imaging/AForge/Color Reduction/ColorImageQuantizer.cs new file mode 100644 index 0000000000..a6069b281 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Color Reduction/ColorImageQuantizer.cs @@ -0,0 +1,412 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.ColorReduction +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + using AForge.Imaging; + + /// + /// Color quantization tools. + /// + /// + /// The class contains methods aimed to simplify work with color quantization + /// algorithms implementing interface. Using its methods it is possible + /// to calculate reduced color palette for the specified image or reduce colors to the specified number. + /// + /// Sample usage: + /// + /// // instantiate the images' color quantization class + /// ColorImageQuantizer ciq = new ColorImageQuantizer( new MedianCutQuantizer( ) ); + /// // get 16 color palette for a given image + /// Color[] colorTable = ciq.CalculatePalette( image, 16 ); + /// + /// // ... or just reduce colors in the specified image + /// Bitmap newImage = ciq.ReduceColors( image, 16 ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class ColorImageQuantizer + { + private IColorQuantizer quantizer; + private bool useCaching = false; + + /// + /// Color quantization algorithm used by this class to build color palettes for the specified images. + /// + /// + public IColorQuantizer Quantizer + { + get { return quantizer; } + set { quantizer = value; } + } + + /// + /// Use color caching during color reduction or not. + /// + /// + /// The property has effect only for methods like and + /// specifies if internal cache of already processed colors should be used or not. For each pixel in the original + /// image the color reduction routine does search in target color palette to find the best matching color. + /// To avoid doing the search again and again for already processed colors, the class may use internal dictionary + /// which maps colors of original image to indexes in target color palette. + /// + /// + /// The property provides a trade off. On one hand it may speedup color reduction routine, but on another + /// hand it increases memory usage. Also cache usage may not be efficient for very small target color tables. + /// + /// Default value is set to . + /// + /// + public bool UseCaching + { + get { return useCaching; } + set { useCaching = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Color quantization algorithm to use for processing images. + /// + public ColorImageQuantizer( IColorQuantizer quantizer ) + { + this.quantizer = quantizer; + } + + /// + /// Calculate reduced color palette for the specified image. + /// + /// + /// Image to calculate palette for. + /// Palette size to calculate. + /// + /// Return reduced color palette for the specified image. + /// + /// See for details. + /// + public Color[] CalculatePalette( Bitmap image, int paletteSize ) + { + BitmapData data = image.LockBits( new Rectangle( 0, 0, image.Width, image.Height ), + ImageLockMode.ReadOnly, image.PixelFormat ); + + try + { + return CalculatePalette( new UnmanagedImage( data ), paletteSize ); + } + finally + { + image.UnlockBits( data ); + } + } + + /// + /// Calculate reduced color palette for the specified image. + /// + /// + /// Image to calculate palette for. + /// Palette size to calculate. + /// + /// Return reduced color palette for the specified image. + /// + /// The method processes the specified image and feeds color value of each pixel + /// to the specified color quantization algorithm. Finally it returns color palette built by + /// that algorithm. + /// + /// Unsupported format of the source image - it must 24 or 32 bpp color image. + /// + public Color[] CalculatePalette( UnmanagedImage image, int paletteSize ) + { + if ( ( image.PixelFormat != PixelFormat.Format24bppRgb ) && + ( image.PixelFormat != PixelFormat.Format32bppRgb ) && + ( image.PixelFormat != PixelFormat.Format32bppArgb ) && + ( image.PixelFormat != PixelFormat.Format32bppPArgb ) ) + { + throw new UnsupportedImageFormatException( "Unsupported format of the source image." ); + } + + quantizer.Clear( ); + + int width = image.Width; + int height = image.Height; + + int pixelSize = Bitmap.GetPixelFormatSize( image.PixelFormat ) / 8; + + unsafe + { + byte* ptr = (byte*) image.ImageData.ToPointer( ); + int offset = image.Stride - width * pixelSize; + + for ( int y = 0; y < height; y++ ) + { + for ( int x = 0; x < width; x++, ptr += pixelSize ) + { + quantizer.AddColor( Color.FromArgb( ptr[RGB.R], ptr[RGB.G], ptr[RGB.B] ) ); + } + + ptr += offset; + } + } + + return quantizer.GetPalette( paletteSize ); + } + + /// + /// Create an image with reduced number of colors. + /// + /// + /// Source image to process. + /// Number of colors to get in the output image, [2, 256]. + /// + /// Returns image with reduced number of colors. + /// + /// See for details. + /// + public Bitmap ReduceColors( Bitmap image, int paletteSize ) + { + BitmapData data = image.LockBits( new Rectangle( 0, 0, image.Width, image.Height ), + ImageLockMode.ReadOnly, image.PixelFormat ); + + try + { + Bitmap result = ReduceColors( new UnmanagedImage( data ), paletteSize ); + if ( ( image.HorizontalResolution > 0 ) && ( image.VerticalResolution > 0 ) ) + { + result.SetResolution( image.HorizontalResolution, image.VerticalResolution ); + } + return result; + } + finally + { + image.UnlockBits( data ); + } + } + + /// + /// Create an image with reduced number of colors. + /// + /// + /// Source image to process. + /// Number of colors to get in the output image, [2, 256]. + /// + /// Returns image with reduced number of colors. + /// + /// The method creates an image, which looks similar to the specified image, but contains + /// reduced number of colors. First, target color palette is calculated using + /// method and then a new image is created, where pixels from the given source image are substituted by + /// best matching colors from calculated color table. + /// + /// The output image has 4 bpp or 8 bpp indexed pixel format depending on the target palette size - + /// 4 bpp for palette size 16 or less; 8 bpp otherwise. + /// + /// + /// Unsupported format of the source image - it must 24 or 32 bpp color image. + /// Invalid size of the target color palette. + /// + public Bitmap ReduceColors( UnmanagedImage image, int paletteSize ) + { + if ( ( paletteSize < 2 ) || ( paletteSize > 256 ) ) + { + throw new ArgumentException( "Invalid size of the target color palette." ); + } + + return ReduceColors( image, CalculatePalette( image, paletteSize ) ); + } + + /// + /// Create an image with reduced number of colors using the specified palette. + /// + /// + /// Source image to process. + /// Target color palette. Must contatin 2-256 colors. + /// + /// Returns image with reduced number of colors. + /// + /// See for details. + /// + public Bitmap ReduceColors( Bitmap image, Color[] palette ) + { + BitmapData data = image.LockBits( new Rectangle( 0, 0, image.Width, image.Height ), + ImageLockMode.ReadOnly, image.PixelFormat ); + + try + { + Bitmap result = ReduceColors( new UnmanagedImage( data ), palette ); + if ( ( image.HorizontalResolution > 0 ) && ( image.VerticalResolution > 0 ) ) + { + result.SetResolution( image.HorizontalResolution, image.VerticalResolution ); + } + return result; + } + finally + { + image.UnlockBits( data ); + } + } + + /// + /// Create an image with reduced number of colors using the specified palette. + /// + /// + /// Source image to process. + /// Target color palette. Must contatin 2-256 colors. + /// + /// Returns image with reduced number of colors. + /// + /// The method creates an image, which looks similar to the specified image, but contains + /// reduced number of colors. Is substitutes every pixel of the source image with the closest matching color + /// in the specified paletter. + /// + /// The output image has 4 bpp or 8 bpp indexed pixel format depending on the target palette size - + /// 4 bpp for palette size 16 or less; 8 bpp otherwise. + /// + /// + /// Unsupported format of the source image - it must 24 or 32 bpp color image. + /// Invalid size of the target color palette. + /// + public Bitmap ReduceColors( UnmanagedImage image, Color[] palette ) + { + if ( ( image.PixelFormat != PixelFormat.Format24bppRgb ) && + ( image.PixelFormat != PixelFormat.Format32bppRgb ) && + ( image.PixelFormat != PixelFormat.Format32bppArgb ) && + ( image.PixelFormat != PixelFormat.Format32bppPArgb ) ) + { + throw new UnsupportedImageFormatException( "Unsupported format of the source image." ); + } + + if ( ( palette.Length < 2 ) || ( palette.Length > 256 ) ) + { + throw new ArgumentException( "Invalid size of the target color palette." ); + } + + paletteToUse = palette; + cache.Clear( ); + + // get image size + int width = image.Width; + int height = image.Height; + int stride = image.Stride; + int pixelSize = Bitmap.GetPixelFormatSize( image.PixelFormat ) / 8; + + int offset = stride - width * pixelSize; + + // create destination image + Bitmap destImage = new Bitmap( width, height, ( palette.Length > 16 ) ? + PixelFormat.Format8bppIndexed : PixelFormat.Format4bppIndexed ); + // and init its palette + ColorPalette cp = destImage.Palette; + for ( int i = 0, n = palette.Length; i < n; i++ ) + { + cp.Entries[i] = palette[i]; + } + destImage.Palette = cp; + + // lock destination image + BitmapData destData = destImage.LockBits( new Rectangle( 0, 0, width, height ), + ImageLockMode.ReadWrite, destImage.PixelFormat ); + + // do the job + unsafe + { + byte* ptr = (byte*) image.ImageData.ToPointer( ); + byte* dstBase = (byte*) destData.Scan0.ToPointer( ); + + bool is8bpp = ( palette.Length > 16 ); + + // for each line + for ( int y = 0; y < height; y++ ) + { + byte* dst = dstBase + y * destData.Stride; + + // for each pixels + for ( int x = 0; x < width; x++, ptr += pixelSize ) + { + // get color from palette, which is the closest to current pixel's value + byte colorIndex = (byte) GetClosestColor( ptr[RGB.R], ptr[RGB.G], ptr[RGB.B] ); + + // write color index as pixel's value to destination image + if ( is8bpp ) + { + *dst = colorIndex; + dst++; + } + else + { + if ( x % 2 == 0 ) + { + *dst |= (byte) ( colorIndex << 4 ); + } + else + { + *dst |= ( colorIndex ); + dst++; + } + } + } + ptr += offset; + } + } + + destImage.UnlockBits( destData ); + + return destImage; + } + + #region Helper methods + [NonSerialized] + private Color[] paletteToUse; + [NonSerialized] + private Dictionary cache = new Dictionary( ); + + // Get closest color from palette to specified color + private int GetClosestColor( int red, int green, int blue ) + { + Color color = Color.FromArgb( red, green, blue ); + + if ( ( useCaching ) && ( cache.ContainsKey( color ) ) ) + { + return cache[color]; + } + + int colorIndex = 0; + int minError = int.MaxValue; + + for ( int i = 0, n = paletteToUse.Length; i < n; i++ ) + { + int dr = red - paletteToUse[i].R; + int dg = green - paletteToUse[i].G; + int db = blue - paletteToUse[i].B; + + int error = dr * dr + dg * dg + db * db; + + if ( error < minError ) + { + minError = error; + colorIndex = (byte) i; + } + } + + if ( useCaching ) + { + cache.Add( color, colorIndex ); + } + + return colorIndex; + } + #endregion + } +} diff --git a/Sources/Accord.Imaging/AForge/Color Reduction/ErrorDiffusionColorDithering.cs b/Sources/Accord.Imaging/AForge/Color Reduction/ErrorDiffusionColorDithering.cs new file mode 100644 index 0000000000..b238600c6 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Color Reduction/ErrorDiffusionColorDithering.cs @@ -0,0 +1,333 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.ColorReduction +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + using AForge.Imaging; + + /// + /// Base class for error diffusion color dithering. + /// + /// + /// The class is the base class for color dithering algorithms based on + /// error diffusion. + /// + /// Color dithering with error diffusion is based on the idea that each pixel from the specified source + /// image is substituted with a best matching color (or better say with color's index) from the specified color + /// table. However, the error (difference between color value in the source image and the best matching color) + /// is diffused to neighbor pixels of the source image, which affects the way those pixels are substituted by colors + /// from the specified table. + /// + /// The image processing routine accepts 24/32 bpp color images for processing. As a result this routine + /// produces 4 bpp or 8 bpp indexed image, which depends on size of the specified color table - 4 bpp result for + /// color tables with 16 colors or less; 8 bpp result for larger color tables. + /// + /// + public abstract class ErrorDiffusionColorDithering + { + private bool useCaching = false; + + /// + /// Current processing X coordinate. + /// + protected int x; + + /// + /// Current processing Y coordinate. + /// + protected int y; + + /// + /// Processing image's width. + /// + protected int width; + + /// + /// Processing image's height. + /// + protected int height; + + /// + /// Processing image's stride (line size). + /// + protected int stride; + + /// + /// Processing image's pixel size in bytes. + /// + protected int pixelSize; + + private Color[] colorTable = new Color[16] + { + Color.Black, Color.DarkBlue, Color.DarkGreen, Color.DarkCyan, + Color.DarkRed, Color.DarkMagenta, Color.DarkKhaki, Color.LightGray, + Color.Gray, Color.Blue, Color.Green, Color.Cyan, + Color.Red, Color.Magenta, Color.Yellow, Color.White + }; + + /// + /// Color table to use for image dithering. Must contain 2-256 colors. + /// + /// + /// Color table size determines format of the resulting image produced by this + /// image processing routine. If color table contains 16 color or less, then result image will have + /// 4 bpp indexed pixel format. If color table contains more than 16 colors, then result image will + /// have 8 bpp indexed pixel format. + /// + /// By default the property is initialized with default 16 colors, which are: + /// Black, Dark Blue, Dark Green, Dark Cyan, Dark Red, Dark Magenta, Dark Khaki, Light Gray, + /// Gray, Blue, Green, Cyan, Red, Magenta, Yellow and White. + /// + /// + /// Color table length must be in the [2, 256] range. + /// + public Color[] ColorTable + { + get { return colorTable; } + set + { + if ( ( colorTable.Length < 2 ) || ( colorTable.Length > 256 ) ) + throw new ArgumentException( "Color table length must be in the [2, 256] range." ); + + colorTable = value; + } + } + + /// + /// Use color caching during color dithering or not. + /// + /// + /// The property specifies if internal cache of already processed colors should be used or not. + /// For each pixel in the original image the color dithering routine does search in target color palette to find + /// the best matching color. To avoid doing the search again and again for already processed colors, the class may + /// use internal dictionary which maps colors of original image to indexes in target color palette. + /// + /// + /// The property provides a trade off. On one hand it may speedup color dithering routine, but on another + /// hand it increases memory usage. Also cache usage may not be efficient for very small target color tables. + /// + /// Default value is set to . + /// + /// + public bool UseCaching + { + get { return useCaching; } + set { useCaching = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + protected ErrorDiffusionColorDithering( ) + { + } + + /// + /// Do error diffusion. + /// + /// + /// Error value of red component. + /// Error value of green component. + /// Error value of blue component. + /// Pointer to current processing pixel. + /// + /// All parameters of the image and current processing pixel's coordinates + /// are initialized in protected members. + /// + protected abstract unsafe void Diffuse( int rError, int gError, int bError, byte* ptr ); + + + /// + /// Perform color dithering for the specified image. + /// + /// + /// Source image to do color dithering for. + /// + /// Returns color dithered image. See for information about format of + /// the result image. + /// + /// Unsupported pixel format of the source image. It must 24 or 32 bpp color image. + /// + public Bitmap Apply( Bitmap sourceImage ) + { + BitmapData data = sourceImage.LockBits( new Rectangle( 0, 0, sourceImage.Width, sourceImage.Height ), + ImageLockMode.ReadOnly, sourceImage.PixelFormat ); + + Bitmap result = null; + + try + { + result = Apply( new UnmanagedImage( data ) ); + if ( ( sourceImage.HorizontalResolution > 0 ) && ( sourceImage.VerticalResolution > 0 ) ) + { + result.SetResolution( sourceImage.HorizontalResolution, sourceImage.VerticalResolution ); + } + } + finally + { + sourceImage.UnlockBits( data ); + } + + return result; + } + + /// + /// Perform color dithering for the specified image. + /// + /// + /// Source image to do color dithering for. + /// + /// Returns color dithered image. See for information about format of + /// the result image. + /// + /// Unsupported pixel format of the source image. It must 24 or 32 bpp color image. + /// + public Bitmap Apply( UnmanagedImage sourceImage ) + { + if ( ( sourceImage.PixelFormat != PixelFormat.Format24bppRgb ) && + ( sourceImage.PixelFormat != PixelFormat.Format32bppRgb ) && + ( sourceImage.PixelFormat != PixelFormat.Format32bppArgb ) && + ( sourceImage.PixelFormat != PixelFormat.Format32bppPArgb ) ) + { + throw new UnsupportedImageFormatException( "Unsupported pixel format of the source image." ); + } + + cache.Clear( ); + + // make a copy of the original image + UnmanagedImage source = sourceImage.Clone( ); + + // get image size + width = sourceImage.Width; + height = sourceImage.Height; + stride = sourceImage.Stride; + pixelSize = Bitmap.GetPixelFormatSize( sourceImage.PixelFormat ) / 8; + + int offset = stride - width * pixelSize; + + // create destination image + Bitmap destImage = new Bitmap( width, height, ( colorTable.Length > 16 ) ? + PixelFormat.Format8bppIndexed : PixelFormat.Format4bppIndexed ); + // and init its palette + ColorPalette cp = destImage.Palette; + for ( int i = 0, n = colorTable.Length; i < n; i++ ) + { + cp.Entries[i] = colorTable[i]; + } + destImage.Palette = cp; + + // lock destination image + BitmapData destData = destImage.LockBits( new Rectangle( 0, 0, width, height ), + ImageLockMode.ReadWrite, destImage.PixelFormat ); + + // pixel values + int r, g, b; + + // do the job + unsafe + { + byte* ptr = (byte*) source.ImageData.ToPointer( ); + byte* dstBase = (byte*) destData.Scan0.ToPointer( ); + byte colorIndex; + + bool is8bpp = ( colorTable.Length > 16 ); + + // for each line + for ( y = 0; y < height; y++ ) + { + byte* dst = dstBase + y * destData.Stride; + + // for each pixels + for ( x = 0; x < width; x++, ptr += pixelSize ) + { + r = ptr[RGB.R]; + g = ptr[RGB.G]; + b = ptr[RGB.B]; + + // get color from palette, which is the closest to current pixel's value + Color closestColor = GetClosestColor( r, g, b, out colorIndex ); + + // do error diffusion + Diffuse( r - closestColor.R, g - closestColor.G, b - closestColor.B, ptr ); + + // write color index as pixel's value to destination image + if ( is8bpp ) + { + *dst = colorIndex; + dst++; + } + else + { + if ( x % 2 == 0 ) + { + *dst |= (byte) ( colorIndex << 4 ); + } + else + { + *dst |= ( colorIndex ); + dst++; + } + } + } + ptr += offset; + } + } + + destImage.UnlockBits( destData ); + source.Dispose( ); + + return destImage; + } + + [NonSerialized] + private Dictionary cache = new Dictionary( ); + + // Get closest color from palette to the specified color + private Color GetClosestColor( int red, int green, int blue, out byte colorIndex ) + { + Color color = Color.FromArgb( red, green, blue ); + + if ( ( useCaching ) && ( cache.ContainsKey( color ) ) ) + { + colorIndex = cache[color]; + } + else + { + colorIndex = 0; + int minError = int.MaxValue; + + for ( int i = 0, n = colorTable.Length; i < n; i++ ) + { + int dr = red - colorTable[i].R; + int dg = green - colorTable[i].G; + int db = blue - colorTable[i].B; + + int error = dr * dr + dg * dg + db * db; + + if ( error < minError ) + { + minError = error; + colorIndex = (byte) i; + } + } + + if ( useCaching ) + { + cache.Add( color, colorIndex ); + } + } + + return colorTable[colorIndex]; + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Color Reduction/FloydSteinbergColorDithering.cs b/Sources/Accord.Imaging/AForge/Color Reduction/FloydSteinbergColorDithering.cs new file mode 100644 index 0000000000..d9988579b --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Color Reduction/FloydSteinbergColorDithering.cs @@ -0,0 +1,72 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2010 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.ColorReduction +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Color dithering using Floyd-Steinberg error diffusion. + /// + /// + /// The image processing routine represents color dithering algorithm, which is based on + /// error diffusion dithering with Floyd-Steinberg + /// coefficients. Error is diffused on 4 neighbor pixels with the next coefficients: + /// + /// + /// | * | 7 | + /// | 3 | 5 | 1 | + /// + /// / 16 + /// + /// + /// The image processing routine accepts 24/32 bpp color images for processing. As a result this routine + /// produces 4 bpp or 8 bpp indexed image, which depends on size of the specified + /// color table - 4 bpp result for + /// color tables with 16 colors or less; 8 bpp result for larger color tables. + /// + /// Sample usage: + /// + /// // create color image quantization routine + /// ColorImageQuantizer ciq = new ColorImageQuantizer( new MedianCutQuantizer( ) ); + /// // create 16 colors table + /// Color[] colorTable = ciq.CalculatePalette( image, 16 ); + /// // create dithering routine + /// FloydSteinbergColorDithering dithering = new FloydSteinbergColorDithering( ); + /// dithering.ColorTable = colorTable; + /// // apply the dithering routine + /// Bitmap newImage = dithering.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + /// + /// + public sealed class FloydSteinbergColorDithering : ColorErrorDiffusionToAdjacentNeighbors + { + /// + /// Initializes a new instance of the class. + /// + /// + public FloydSteinbergColorDithering( ) + : base( new int[2][] { + new int[1] { 7 }, + new int[3] { 3, 5, 1 } } ) + { + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Color Reduction/IColorQuantizer.cs b/Sources/Accord.Imaging/AForge/Color Reduction/IColorQuantizer.cs new file mode 100644 index 0000000000..1cb895ad1 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Color Reduction/IColorQuantizer.cs @@ -0,0 +1,63 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2010 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.ColorReduction +{ + using System; + using System.Drawing; + using AForge.Imaging; + + /// + /// Interface which is implemented by different color quantization algorithms. + /// + /// + /// The interface defines set of methods, which are to be implemented by different + /// color quantization algorithms - algorithms which are aimed to provide reduced color table/palette + /// for a color image. + /// + /// See documentation to particular implementation of the interface for additional information + /// about the algorithm. + /// + /// + public interface IColorQuantizer + { + /// + /// Process color by a color quantization algorithm. + /// + /// + /// Color to process. + /// + /// Depending on particular implementation of interface, + /// this method may simply process the specified color or store it in internal list for + /// later color palette calculation. + /// + void AddColor( Color color ); + + /// + /// Get palette of the specified size. + /// + /// + /// Palette size to return. + /// + /// Returns reduced color palette for the accumulated/processed colors. + /// + /// The method must be called after continuously calling method and + /// returns reduced color palette for colors accumulated/processed so far. + /// + Color[] GetPalette( int colorCount ); + + /// + /// Clear internals of the algorithm, like accumulated color table, etc. + /// + /// + /// The methods resets internal state of a color quantization algorithm returning + /// it to initial state. + /// + void Clear( ); + } +} diff --git a/Sources/Accord.Imaging/AForge/Color Reduction/JarvisJudiceNinkeColorDithering.cs b/Sources/Accord.Imaging/AForge/Color Reduction/JarvisJudiceNinkeColorDithering.cs new file mode 100644 index 0000000000..96f602abf --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Color Reduction/JarvisJudiceNinkeColorDithering.cs @@ -0,0 +1,73 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2010 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.ColorReduction +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Color dithering using Jarvis, Judice and Ninke error diffusion. + /// + /// + /// The image processing routine represents color dithering algorithm, which is based on + /// error diffusion dithering with Jarvis-Judice-Ninke coefficients. Error is diffused + /// on 12 neighbor pixels with next coefficients: + /// + /// | * | 7 | 5 | + /// | 3 | 5 | 7 | 5 | 3 | + /// | 1 | 3 | 5 | 3 | 1 | + /// + /// / 48 + /// + /// + /// The image processing routine accepts 24/32 bpp color images for processing. As a result this routine + /// produces 4 bpp or 8 bpp indexed image, which depends on size of the specified + /// color table - 4 bpp result for + /// color tables with 16 colors or less; 8 bpp result for larger color tables. + /// + /// Sample usage: + /// + /// // create color image quantization routine + /// ColorImageQuantizer ciq = new ColorImageQuantizer( new MedianCutQuantizer( ) ); + /// // create 32 colors table + /// Color[] colorTable = ciq.CalculatePalette( image, 32 ); + /// // create dithering routine + /// JarvisJudiceNinkeColorDithering dithering = new JarvisJudiceNinkeColorDithering( ); + /// dithering.ColorTable = colorTable; + /// // apply the dithering routine + /// Bitmap newImage = dithering.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + /// + /// + public sealed class JarvisJudiceNinkeColorDithering : ColorErrorDiffusionToAdjacentNeighbors + { + /// + /// Initializes a new instance of the class. + /// + /// + public JarvisJudiceNinkeColorDithering( ) + : base( new int[3][] { + new int[2] { 7, 5 }, + new int[5] { 3, 5, 7, 5, 3 }, + new int[5] { 1, 3, 5, 3, 1 } } ) + { + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Color Reduction/MedianCutCube.cs b/Sources/Accord.Imaging/AForge/Color Reduction/MedianCutCube.cs new file mode 100644 index 0000000000..d32e24725 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Color Reduction/MedianCutCube.cs @@ -0,0 +1,152 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2010 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.ColorReduction +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using AForge.Imaging; + + // Color cube used by Median Cut color quantization algorithm + internal class MedianCutCube + { + private List colors; + + private readonly byte minR, maxR; + private readonly byte minG, maxG; + private readonly byte minB, maxB; + + private Color? cubeColor = null; + + // Length of the "red side" of the cube + public int RedSize + { + get { return maxR - minR; } + } + + // Length of the "green size" of the cube + public int GreenSize + { + get { return maxG - minG; } + } + + // Length of the "blue size" of the cube + public int BlueSize + { + get { return maxB - minB; } + } + + // Mean cube's color + public Color Color + { + get + { + if ( cubeColor == null ) + { + int red = 0, green = 0, blue = 0; + + foreach ( Color color in colors ) + { + red += color.R; + green += color.G; + blue += color.B; + } + + int colorsCount = colors.Count; + + if ( colorsCount != 0 ) + { + red /= colorsCount; + green /= colorsCount; + blue /= colorsCount; + } + + cubeColor = Color.FromArgb( red, green, blue ); + } + + return cubeColor.Value; + } + } + + public MedianCutCube( List colors ) + { + this.colors = colors; + + // get min/max values for each RGB component of specified colors + minR = minG = minB = 255; + maxR = maxG = maxB = 0; + + foreach ( Color color in colors ) + { + if ( color.R < minR ) + minR = color.R; + if ( color.R > maxR ) + maxR = color.R; + + if ( color.G < minG ) + minG = color.G; + if ( color.G > maxG ) + maxG = color.G; + + if ( color.B < minB ) + minB = color.B; + if ( color.B > maxB ) + maxB = color.B; + } + } + + // Split the cube into 2 smaller cubes using the specified color side for splitting + public void SplitAtMedian( int rgbComponent, out MedianCutCube cube1, out MedianCutCube cube2 ) + { + switch ( rgbComponent ) + { + case RGB.R: + colors.Sort( new RedComparer( ) ); + break; + case RGB.G: + colors.Sort( new GreenComparer( ) ); + break; + case RGB.B: + colors.Sort( new BlueComparer( ) ); + break; + } + + int median = colors.Count / 2; + + cube1 = new MedianCutCube( colors.GetRange( 0, median ) ); + cube2 = new MedianCutCube( colors.GetRange( median, colors.Count - median ) ); + } + + #region Different comparers used for sorting colors by different components + private class RedComparer : IComparer + { + public int Compare( Color c1, Color c2 ) + { + return c1.R.CompareTo( c2.R ); + } + } + + private class GreenComparer : IComparer + { + public int Compare( Color c1, Color c2 ) + { + return c1.G.CompareTo( c2.G ); + } + } + + private class BlueComparer : IComparer + { + public int Compare( Color c1, Color c2 ) + { + return c1.B.CompareTo( c2.B ); + } + } + #endregion + } +} diff --git a/Sources/Accord.Imaging/AForge/Color Reduction/MedianCutQuantizer.cs b/Sources/Accord.Imaging/AForge/Color Reduction/MedianCutQuantizer.cs new file mode 100644 index 0000000000..d3c5489c0 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Color Reduction/MedianCutQuantizer.cs @@ -0,0 +1,137 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2010 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.ColorReduction +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using AForge.Imaging; + + /// + /// Median cut color quantization algorithm. + /// + /// + /// The class implements median cut + /// color quantization algorithm. + /// + /// See also class, which may simplify processing of images. + /// + /// Sample usage: + /// + /// // create the color quantization algorithm + /// IColorQuantizer quantizer = new MedianCutQuantizer( ); + /// // process colors (taken from image for example) + /// for ( int i = 0; i < pixelsToProcess; i++ ) + /// { + /// quantizer.AddColor( /* pixel color */ ); + /// } + /// // get palette reduced to 16 colors + /// Color[] palette = quantizer.GetPalette( 16 ); + /// + /// + /// + /// + /// + public class MedianCutQuantizer : IColorQuantizer + { + private List colors = new List(); + + /// + /// Add color to the list of processed colors. + /// + /// + /// Color to add to the internal list. + /// + /// The method adds the specified color into internal list of processed colors. The list + /// is used later by method to build reduced color table of the specified size. + /// + /// + public void AddColor(Color color) + { + colors.Add(color); + } + + /// + /// Get paletter of the specified size. + /// + /// + /// Palette size to get. + /// + /// Returns reduced palette of the specified size, which covers colors processed so far. + /// + /// The method must be called after continuously calling method and + /// returns reduced color palette for colors accumulated/processed so far. + /// + public Color[] GetPalette(int colorCount) + { + List cubes = new List(); + cubes.Add(new MedianCutCube(colors)); + + // split the cube until we get required amount of colors + SplitCubes(cubes, colorCount); + + // get the final palette + Color[] palette = new Color[colorCount]; + + for (int i = 0; i < colorCount; i++) + { + palette[i] = cubes[i].Color; + } + + return palette; + } + + /// + /// Clear internal state of the color quantization algorithm by clearing the list of colors + /// so far processed. + /// + /// + public void Clear() + { + colors.Clear(); + } + + // Split specified list of cubes into smaller cubes until the list gets the specified size + private static void SplitCubes(List cubes, int count) + { + int cubeIndexToSplit = cubes.Count - 1; + + while (cubes.Count < count) + { + MedianCutCube cubeToSplit = cubes[cubeIndexToSplit]; + MedianCutCube cube1, cube2; + + // find the longest color size to use for splitting + if ((cubeToSplit.RedSize >= cubeToSplit.GreenSize) && (cubeToSplit.RedSize >= cubeToSplit.BlueSize)) + { + cubeToSplit.SplitAtMedian(RGB.R, out cube1, out cube2); + } + else if (cubeToSplit.GreenSize >= cubeToSplit.BlueSize) + { + cubeToSplit.SplitAtMedian(RGB.G, out cube1, out cube2); + } + else + { + cubeToSplit.SplitAtMedian(RGB.B, out cube1, out cube2); + } + + // remove the old "big" cube + cubes.RemoveAt(cubeIndexToSplit); + // add two smaller cubes instead + cubes.Insert(cubeIndexToSplit, cube1); + cubes.Insert(cubeIndexToSplit, cube2); + + if (--cubeIndexToSplit < 0) + { + cubeIndexToSplit = cubes.Count - 1; + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Color Reduction/OrderedColorDithering.cs b/Sources/Accord.Imaging/AForge/Color Reduction/OrderedColorDithering.cs new file mode 100644 index 0000000000..8ce4b655e --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Color Reduction/OrderedColorDithering.cs @@ -0,0 +1,355 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.ColorReduction +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Color dithering with a thresold matrix (ordered dithering). + /// + /// + /// The class implements ordered color dithering as described on + /// Wikipedia. + /// The algorithm achieves dithering by applying a threshold map on + /// the pixels displayed, causing some of the pixels to be rendered at a different color, depending on + /// how far in between the color is of available color entries. + /// + /// The image processing routine accepts 24/32 bpp color images for processing. As a result this routine + /// produces 4 bpp or 8 bpp indexed image, which depends on size of the specified + /// color table - 4 bpp result for + /// color tables with 16 colors or less; 8 bpp result for larger color tables. + /// + /// Sample usage: + /// + /// // create color image quantization routine + /// ColorImageQuantizer ciq = new ColorImageQuantizer( new MedianCutQuantizer( ) ); + /// // create 256 colors table + /// Color[] colorTable = ciq.CalculatePalette( image, 256 ); + /// // create dithering routine + /// OrderedColorDithering dithering = new OrderedColorDithering( ); + /// dithering.ColorTable = colorTable; + /// // apply the dithering routine + /// Bitmap newImage = dithering.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class OrderedColorDithering + { + private bool useCaching = false; + + private Color[] colorTable = new Color[16] + { + Color.Black, Color.DarkBlue, Color.DarkGreen, Color.DarkCyan, + Color.DarkRed, Color.DarkMagenta, Color.DarkKhaki, Color.LightGray, + Color.Gray, Color.Blue, Color.Green, Color.Cyan, + Color.Red, Color.Magenta, Color.Yellow, Color.White + }; + + private byte[,] matrix = new byte[4, 4] + { + { 2, 18, 6, 22 }, + { 26, 10, 30, 14 }, + { 8, 24, 4, 20 }, + { 32, 16, 28, 12 } + }; + + /// + /// Threshold matrix - values to add source image's values. + /// + /// + /// The property keeps a threshold matrix, which is applied to values of a source image + /// to dither. By adding these values to the source image the algorithm produces the effect when pixels + /// of the same color in source image may have different color in the result image (which depends on pixel's + /// position). This threshold map is also known as an index matrix or Bayer matrix. + /// + /// By default the property is inialized with the below matrix: + /// + /// 2 18 6 22 + /// 26 10 30 14 + /// 8 24 4 20 + /// 32 16 28 12 + /// + /// + /// + /// + public byte[,] ThresholdMatrix + { + get { return (byte[,])matrix.Clone(); } + set + { + if (value == null) + throw new InvalidOperationException("Threshold matrix cannot be set to null."); + + matrix = value; + } + } + + /// + /// Color table to use for image dithering. Must contain 2-256 colors. + /// + /// + /// Color table size determines format of the resulting image produced by this + /// image processing routine. If color table contains 16 color or less, then result image will have + /// 4 bpp indexed pixel format. If color table contains more than 16 colors, then result image will + /// have 8 bpp indexed pixel format. + /// + /// By default the property is initialized with default 16 colors, which are: + /// Black, Dark Blue, Dark Green, Dark Cyan, Dark Red, Dark Magenta, Dark Khaki, Light Gray, + /// Gray, Blue, Green, Cyan, Red, Magenta, Yellow and White. + /// + /// + /// Color table length must be in the [2, 256] range. + /// + public Color[] ColorTable + { + get { return colorTable; } + set + { + if ((colorTable.Length < 2) || (colorTable.Length > 256)) + throw new ArgumentException("Color table length must be in the [2, 256] range."); + + colorTable = value; + } + } + + /// + /// Use color caching during color dithering or not. + /// + /// + /// The property specifies if internal cache of already processed colors should be used or not. + /// For each pixel in the original image the color dithering routine does search in target color palette to find + /// the best matching color. To avoid doing the search again and again for already processed colors, the class may + /// use internal dictionary which maps colors of original image to indexes in target color palette. + /// + /// + /// The property provides a trade off. On one hand it may speedup color dithering routine, but on another + /// hand it increases memory usage. Also cache usage may not be efficient for very small target color tables. + /// + /// Default value is set to . + /// + /// + public bool UseCaching + { + get { return useCaching; } + set { useCaching = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public OrderedColorDithering() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Threshold matrix (see property). + /// + public OrderedColorDithering(byte[,] matrix) + { + ThresholdMatrix = matrix; + } + + /// + /// Perform color dithering for the specified image. + /// + /// + /// Source image to do color dithering for. + /// + /// Returns color dithered image. See for information about format of + /// the result image. + /// + /// Unsupported pixel format of the source image. It must 24 or 32 bpp color image. + /// + public Bitmap Apply(Bitmap sourceImage) + { + BitmapData data = sourceImage.LockBits(new Rectangle(0, 0, sourceImage.Width, sourceImage.Height), + ImageLockMode.ReadOnly, sourceImage.PixelFormat); + + Bitmap result = null; + + try + { + result = Apply(new UnmanagedImage(data)); + if ((sourceImage.HorizontalResolution > 0) && (sourceImage.VerticalResolution > 0)) + { + result.SetResolution(sourceImage.HorizontalResolution, sourceImage.VerticalResolution); + } + } + finally + { + sourceImage.UnlockBits(data); + } + + return result; + } + + /// + /// Perform color dithering for the specified image. + /// + /// + /// Source image to do color dithering for. + /// + /// Returns color dithered image. See for information about format of + /// the result image. + /// + /// Unsupported pixel format of the source image. It must 24 or 32 bpp color image. + /// + public Bitmap Apply(UnmanagedImage sourceImage) + { + if ((sourceImage.PixelFormat != PixelFormat.Format24bppRgb) && + (sourceImage.PixelFormat != PixelFormat.Format32bppRgb) && + (sourceImage.PixelFormat != PixelFormat.Format32bppArgb) && + (sourceImage.PixelFormat != PixelFormat.Format32bppPArgb)) + { + throw new UnsupportedImageFormatException("Unsupported pixel format of the source image."); + } + + cache.Clear(); + + // get image size + int width = sourceImage.Width; + int height = sourceImage.Height; + int stride = sourceImage.Stride; + int pixelSize = Bitmap.GetPixelFormatSize(sourceImage.PixelFormat) / 8; + + + // create destination image + Bitmap destImage = new Bitmap(width, height, (colorTable.Length > 16) ? + PixelFormat.Format8bppIndexed : PixelFormat.Format4bppIndexed); + // and init its palette + ColorPalette cp = destImage.Palette; + for (int i = 0, n = colorTable.Length; i < n; i++) + { + cp.Entries[i] = colorTable[i]; + } + destImage.Palette = cp; + + // lock destination image + BitmapData destData = destImage.LockBits(new Rectangle(0, 0, width, height), + ImageLockMode.ReadWrite, destImage.PixelFormat); + + // pixel values + int r, g, b, toAdd; + int rows = matrix.GetLength(0); + int cols = matrix.GetLength(1); + + + // do the job + unsafe + { + byte* ptr = (byte*)sourceImage.ImageData.ToPointer(); + byte* dstBase = (byte*)destData.Scan0.ToPointer(); + byte colorIndex; + + bool is8bpp = (colorTable.Length > 16); + + // for each line + for (int y = 0; y < height; y++) + { + byte* dst = dstBase + y * destData.Stride; + + // for each pixels + for (int x = 0; x < width; x++, ptr += pixelSize) + { + toAdd = matrix[(y % rows), (x % cols)]; + r = ptr[RGB.R] + toAdd; + g = ptr[RGB.G] + toAdd; + b = ptr[RGB.B] + toAdd; + + if (r > 255) + r = 255; + if (g > 255) + g = 255; + if (b > 255) + b = 255; + + // get color from palette, which is the closest to current pixel's value + GetClosestColor(r, g, b, out colorIndex); + + // write color index as pixel's value to destination image + if (is8bpp) + { + *dst = colorIndex; + dst++; + } + else + { + if (x % 2 == 0) + { + *dst |= (byte)(colorIndex << 4); + } + else + { + *dst |= (colorIndex); + dst++; + } + } + } + } + } + + destImage.UnlockBits(destData); + + return destImage; + } + + [NonSerialized] + private Dictionary cache = new Dictionary(); + + // Get closest color from palette to the specified color + private Color GetClosestColor(int red, int green, int blue, out byte colorIndex) + { + Color color = Color.FromArgb(red, green, blue); + + if ((useCaching) && (cache.ContainsKey(color))) + { + colorIndex = cache[color]; + } + else + { + colorIndex = 0; + int minError = int.MaxValue; + + for (int i = 0, n = colorTable.Length; i < n; i++) + { + int dr = red - colorTable[i].R; + int dg = green - colorTable[i].G; + int db = blue - colorTable[i].B; + + int error = dr * dr + dg * dg + db * db; + + if (error < minError) + { + minError = error; + colorIndex = (byte)i; + } + } + + if (useCaching) + { + cache.Add(color, colorIndex); + } + } + + return colorTable[colorIndex]; + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Color Reduction/SierraColorDithering.cs b/Sources/Accord.Imaging/AForge/Color Reduction/SierraColorDithering.cs new file mode 100644 index 0000000000..518305950 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Color Reduction/SierraColorDithering.cs @@ -0,0 +1,68 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2010 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.ColorReduction +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Color dithering using Sierra error diffusion. + /// + /// + /// The image processing routine represents color dithering algorithm, which is based on + /// error diffusion dithering with Sierra coefficients. Error is diffused + /// on 10 neighbor pixels with next coefficients: + /// + /// | * | 5 | 3 | + /// | 2 | 4 | 5 | 4 | 2 | + /// | 2 | 3 | 2 | + /// + /// / 32 + /// + /// + /// The image processing routine accepts 24/32 bpp color images for processing. As a result this routine + /// produces 4 bpp or 8 bpp indexed image, which depends on size of the specified + /// color table - 4 bpp result for + /// color tables with 16 colors or less; 8 bpp result for larger color tables. + /// + /// Sample usage: + /// + /// // create dithering routine (use default color table) + /// SierraColorDithering dithering = new SierraColorDithering( ); + /// // apply the dithering routine + /// Bitmap newImage = dithering.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + /// + /// + public sealed class SierraColorDithering : ColorErrorDiffusionToAdjacentNeighbors + { + /// + /// Initializes a new instance of the class. + /// + /// + public SierraColorDithering( ) + : base( new int[3][] { + new int[2] { 5, 3 }, + new int[5] { 2, 4, 5, 4, 2 }, + new int[3] { 2, 3, 2 } } ) + { + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Color Reduction/StuckiColorDithering.cs b/Sources/Accord.Imaging/AForge/Color Reduction/StuckiColorDithering.cs new file mode 100644 index 0000000000..ecb0581b9 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Color Reduction/StuckiColorDithering.cs @@ -0,0 +1,73 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2010 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.ColorReduction +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Color dithering using Stucki error diffusion. + /// + /// + /// The image processing routine represents color dithering algorithm, which is based on + /// error diffusion dithering with Stucki coefficients. Error is diffused + /// on 12 neighbor pixels with next coefficients: + /// + /// | * | 8 | 4 | + /// | 2 | 4 | 8 | 4 | 2 | + /// | 1 | 2 | 4 | 2 | 1 | + /// + /// / 42 + /// + /// + /// The image processing routine accepts 24/32 bpp color images for processing. As a result this routine + /// produces 4 bpp or 8 bpp indexed image, which depends on size of the specified + /// color table - 4 bpp result for + /// color tables with 16 colors or less; 8 bpp result for larger color tables. + /// + /// Sample usage: + /// + /// // create color image quantization routine + /// ColorImageQuantizer ciq = new ColorImageQuantizer( new MedianCutQuantizer( ) ); + /// // create 64 colors table + /// Color[] colorTable = ciq.CalculatePalette( image, 64 ); + /// // create dithering routine + /// StuckiColorDithering dithering = new StuckiColorDithering( ); + /// dithering.ColorTable = colorTable; + /// // apply the dithering routine + /// Bitmap newImage = dithering.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + /// + /// + public sealed class StuckiColorDithering : ColorErrorDiffusionToAdjacentNeighbors + { + /// + /// Initializes a new instance of the class. + /// + /// + public StuckiColorDithering( ) + : base( new int[3][] { + new int[2] { 8, 4 }, + new int[5] { 2, 4, 8, 4, 2 }, + new int[5] { 1, 2, 4, 2, 1 } } ) + { + } + } +} diff --git a/Sources/Accord.Imaging/AForge/ColorConverter.cs b/Sources/Accord.Imaging/AForge/ColorConverter.cs new file mode 100644 index 0000000000..872de17b4 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/ColorConverter.cs @@ -0,0 +1,452 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging +{ + using System; + using System.Drawing; + + /// + /// RGB components. + /// + /// + /// The class encapsulates RGB color components. + /// PixelFormat.Format24bppRgb + /// actually means BGR format. + /// + /// + public class RGB + { + /// + /// Index of red component. + /// + public const short R = 2; + + /// + /// Index of green component. + /// + public const short G = 1; + + /// + /// Index of blue component. + /// + public const short B = 0; + + /// + /// Index of alpha component for ARGB images. + /// + public const short A = 3; + + /// + /// Red component. + /// + public byte Red; + + /// + /// Green component. + /// + public byte Green; + + /// + /// Blue component. + /// + public byte Blue; + + /// + /// Alpha component. + /// + public byte Alpha; + + /// + /// Color value of the class. + /// + public System.Drawing.Color Color + { + get { return Color.FromArgb(Alpha, Red, Green, Blue); } + set + { + Red = value.R; + Green = value.G; + Blue = value.B; + Alpha = value.A; + } + } + + /// + /// Initializes a new instance of the class. + /// + public RGB() + { + Red = 0; + Green = 0; + Blue = 0; + Alpha = 255; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Red component. + /// Green component. + /// Blue component. + /// + public RGB(byte red, byte green, byte blue) + { + this.Red = red; + this.Green = green; + this.Blue = blue; + this.Alpha = 255; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Red component. + /// Green component. + /// Blue component. + /// Alpha component. + /// + public RGB(byte red, byte green, byte blue, byte alpha) + { + this.Red = red; + this.Green = green; + this.Blue = blue; + this.Alpha = alpha; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Initialize from specified color. + /// + public RGB(System.Drawing.Color color) + { + this.Red = color.R; + this.Green = color.G; + this.Blue = color.B; + this.Alpha = color.A; + } + } + + /// + /// HSL components. + /// + /// + /// The class encapsulates HSL color components. + /// + public class HSL + { + /// + /// Hue component. + /// + /// + /// Hue is measured in the range of [0, 359]. + /// + public int Hue; + + /// + /// Saturation component. + /// + /// + /// Saturation is measured in the range of [0, 1]. + /// + public float Saturation; + + /// + /// Luminance value. + /// + /// + /// Luminance is measured in the range of [0, 1]. + /// + public float Luminance; + + /// + /// Initializes a new instance of the class. + /// + public HSL() { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Hue component. + /// Saturation component. + /// Luminance component. + /// + public HSL(int hue, float saturation, float luminance) + { + this.Hue = hue; + this.Saturation = saturation; + this.Luminance = luminance; + } + + /// + /// Convert from RGB to HSL color space. + /// + /// + /// Source color in RGB color space. + /// Destination color in HSL color space. + /// + /// See HSL and HSV Wiki + /// for information about the algorithm to convert from RGB to HSL. + /// + public static void FromRGB(RGB rgb, HSL hsl) + { + float r = (rgb.Red / 255.0f); + float g = (rgb.Green / 255.0f); + float b = (rgb.Blue / 255.0f); + + float min = Math.Min(Math.Min(r, g), b); + float max = Math.Max(Math.Max(r, g), b); + float delta = max - min; + + // get luminance value + hsl.Luminance = (max + min) / 2; + + if (delta == 0) + { + // gray color + hsl.Hue = 0; + hsl.Saturation = 0.0f; + } + else + { + // get saturation value + hsl.Saturation = (hsl.Luminance <= 0.5) ? (delta / (max + min)) : (delta / (2 - max - min)); + + // get hue value + float hue; + + if (r == max) + { + hue = ((g - b) / 6) / delta; + } + else if (g == max) + { + hue = (1.0f / 3) + ((b - r) / 6) / delta; + } + else + { + hue = (2.0f / 3) + ((r - g) / 6) / delta; + } + + // correct hue if needed + if (hue < 0) + hue += 1; + if (hue > 1) + hue -= 1; + + hsl.Hue = (int)(hue * 360); + } + } + + /// + /// Convert from RGB to HSL color space. + /// + /// + /// Source color in RGB color space. + /// + /// Returns instance, which represents converted color value. + /// + public static HSL FromRGB(RGB rgb) + { + HSL hsl = new HSL(); + FromRGB(rgb, hsl); + return hsl; + } + + /// + /// Convert from HSL to RGB color space. + /// + /// + /// Source color in HSL color space. + /// Destination color in RGB color space. + /// + public static void ToRGB(HSL hsl, RGB rgb) + { + if (hsl.Saturation == 0) + { + // gray values + rgb.Red = rgb.Green = rgb.Blue = (byte)(hsl.Luminance * 255); + } + else + { + float v1, v2; + float hue = (float)hsl.Hue / 360; + + v2 = (hsl.Luminance < 0.5) ? + (hsl.Luminance * (1 + hsl.Saturation)) : + ((hsl.Luminance + hsl.Saturation) - (hsl.Luminance * hsl.Saturation)); + v1 = 2 * hsl.Luminance - v2; + + rgb.Red = (byte)(255 * Hue_2_RGB(v1, v2, hue + (1.0f / 3))); + rgb.Green = (byte)(255 * Hue_2_RGB(v1, v2, hue)); + rgb.Blue = (byte)(255 * Hue_2_RGB(v1, v2, hue - (1.0f / 3))); + } + rgb.Alpha = 255; + } + + /// + /// Convert the color to RGB color space. + /// + /// + /// Returns instance, which represents converted color value. + /// + public RGB ToRGB() + { + RGB rgb = new RGB(); + ToRGB(this, rgb); + return rgb; + } + + #region Private members + // HSL to RGB helper routine + private static float Hue_2_RGB(float v1, float v2, float vH) + { + if (vH < 0) + vH += 1; + if (vH > 1) + vH -= 1; + if ((6 * vH) < 1) + return (v1 + (v2 - v1) * 6 * vH); + if ((2 * vH) < 1) + return v2; + if ((3 * vH) < 2) + return (v1 + (v2 - v1) * ((2.0f / 3) - vH) * 6); + return v1; + } + #endregion + } + + /// + /// YCbCr components. + /// + /// + /// The class encapsulates YCbCr color components. + /// + public class YCbCr + { + /// + /// Index of Y component. + /// + public const short YIndex = 0; + + /// + /// Index of Cb component. + /// + public const short CbIndex = 1; + + /// + /// Index of Cr component. + /// + public const short CrIndex = 2; + + /// + /// Y component. + /// + public float Y; + + /// + /// Cb component. + /// + public float Cb; + + /// + /// Cr component. + /// + public float Cr; + + /// + /// Initializes a new instance of the class. + /// + public YCbCr() { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Y component. + /// Cb component. + /// Cr component. + /// + public YCbCr(float y, float cb, float cr) + { + this.Y = Math.Max(0.0f, Math.Min(1.0f, y)); + this.Cb = Math.Max(-0.5f, Math.Min(0.5f, cb)); + this.Cr = Math.Max(-0.5f, Math.Min(0.5f, cr)); + } + + /// + /// Convert from RGB to YCbCr color space (Rec 601-1 specification). + /// + /// + /// Source color in RGB color space. + /// Destination color in YCbCr color space. + /// + public static void FromRGB(RGB rgb, YCbCr ycbcr) + { + float r = (float)rgb.Red / 255; + float g = (float)rgb.Green / 255; + float b = (float)rgb.Blue / 255; + + ycbcr.Y = (float)(0.2989 * r + 0.5866 * g + 0.1145 * b); + ycbcr.Cb = (float)(-0.1687 * r - 0.3313 * g + 0.5000 * b); + ycbcr.Cr = (float)(0.5000 * r - 0.4184 * g - 0.0816 * b); + } + + /// + /// Convert from RGB to YCbCr color space (Rec 601-1 specification). + /// + /// + /// Source color in RGB color space. + /// + /// Returns instance, which represents converted color value. + /// + public static YCbCr FromRGB(RGB rgb) + { + YCbCr ycbcr = new YCbCr(); + FromRGB(rgb, ycbcr); + return ycbcr; + } + + /// + /// Convert from YCbCr to RGB color space. + /// + /// + /// Source color in YCbCr color space. + /// Destination color in RGB color space. + /// + public static void ToRGB(YCbCr ycbcr, RGB rgb) + { + // Don't worry about zeros. Compiler will remove them + float r = Math.Max(0.0f, Math.Min(1.0f, (float)(ycbcr.Y + 0.0000 * ycbcr.Cb + 1.4022 * ycbcr.Cr))); + float g = Math.Max(0.0f, Math.Min(1.0f, (float)(ycbcr.Y - 0.3456 * ycbcr.Cb - 0.7145 * ycbcr.Cr))); + float b = Math.Max(0.0f, Math.Min(1.0f, (float)(ycbcr.Y + 1.7710 * ycbcr.Cb + 0.0000 * ycbcr.Cr))); + + rgb.Red = (byte)(r * 255); + rgb.Green = (byte)(g * 255); + rgb.Blue = (byte)(b * 255); + rgb.Alpha = 255; + } + + /// + /// Convert the color to RGB color space. + /// + /// + /// Returns instance, which represents converted color value. + /// + public RGB ToRGB() + { + RGB rgb = new RGB(); + ToRGB(this, rgb); + return rgb; + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Complex Filters/FrequencyFilter.cs b/Sources/Accord.Imaging/AForge/Complex Filters/FrequencyFilter.cs new file mode 100644 index 0000000000..9283e6728 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Complex Filters/FrequencyFilter.cs @@ -0,0 +1,131 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.ComplexFilters +{ + using System; + using AForge; + using AForge.Math; + using System.Numerics; + + /// + /// Filtering of frequencies outside of specified range in complex Fourier + /// transformed image. + /// + /// + /// The filer keeps only specified range of frequencies in complex + /// Fourier transformed image. The rest of frequencies are zeroed. + /// + /// Sample usage: + /// + /// // create complex image + /// ComplexImage complexImage = ComplexImage.FromBitmap( image ); + /// // do forward Fourier transformation + /// complexImage.ForwardFourierTransform( ); + /// // create filter + /// FrequencyFilter filter = new FrequencyFilter( new IntRange( 20, 128 ) ); + /// // apply filter + /// filter.Apply( complexImage ); + /// // do backward Fourier transformation + /// complexImage.BackwardFourierTransform( ); + /// // get complex image as bitmat + /// Bitmap fourierImage = complexImage.ToBitmap( ); + /// + /// + /// Initial image: + /// + /// Fourier image: + /// + /// + /// + public class FrequencyFilter : IComplexFilter + { + private IntRange frequencyRange = new IntRange(0, 1024); + + /// + /// Range of frequencies to keep. + /// + /// + /// The range specifies the range of frequencies to keep. Values is frequencies + /// outside of this range are zeroed. + /// + /// Default value is set to [0, 1024]. + /// + public IntRange FrequencyRange + { + get { return frequencyRange; } + set { frequencyRange = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public FrequencyFilter() { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Range of frequencies to keep. + /// + public FrequencyFilter(IntRange frequencyRange) + { + this.frequencyRange = frequencyRange; + } + + /// + /// Apply filter to complex image. + /// + /// + /// Complex image to apply filter to. + /// + /// The source complex image should be Fourier transformed. + /// + public void Apply(ComplexImage complexImage) + { + if (!complexImage.FourierTransformed) + { + throw new ArgumentException("The source complex image should be Fourier transformed."); + } + + // get image dimenstion + int width = complexImage.Width; + int height = complexImage.Height; + + // half of dimensions + int hw = width >> 1; + int hh = height >> 1; + + // min and max frequencies + int min = frequencyRange.Min; + int max = frequencyRange.Max; + + // complex data to process + Complex[,] data = complexImage.Data; + + // process all data + for (int i = 0; i < height; i++) + { + int y = i - hh; + + for (int j = 0; j < width; j++) + { + int x = j - hw; + int d = (int)Math.Sqrt(x * x + y * y); + + // filter values outside the range + if ((d > max) || (d < min)) + { + data[i, j] = Complex.Zero; + } + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Complex Filters/IComplexFilter.cs b/Sources/Accord.Imaging/AForge/Complex Filters/IComplexFilter.cs new file mode 100644 index 0000000000..020803a55 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Complex Filters/IComplexFilter.cs @@ -0,0 +1,34 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.ComplexFilters +{ + using System; + using AForge; + using AForge.Math; + + /// + /// Image processing filter, which operates with Fourier transformed + /// complex image. + /// + /// + /// The interface defines the set of methods, which should be + /// provided by all image processing filter, which operate with Fourier + /// transformed complex image. + /// + public interface IComplexFilter + { + /// + /// Apply filter to complex image. + /// + /// + /// Complex image to apply filter to. + /// + void Apply( ComplexImage complexImage ); + } +} diff --git a/Sources/Accord.Imaging/AForge/ComplexImage.cs b/Sources/Accord.Imaging/AForge/ComplexImage.cs new file mode 100644 index 0000000000..98880489b --- /dev/null +++ b/Sources/Accord.Imaging/AForge/ComplexImage.cs @@ -0,0 +1,313 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + using AForge; + using AForge.Math; + using System.Numerics; + + /// + /// Complex image. + /// + /// + /// The class is used to keep image represented in complex numbers sutable for Fourier + /// transformations. + /// + /// Sample usage: + /// + /// // create complex image + /// ComplexImage complexImage = ComplexImage.FromBitmap( image ); + /// // do forward Fourier transformation + /// complexImage.ForwardFourierTransform( ); + /// // get complex image as bitmat + /// Bitmap fourierImage = complexImage.ToBitmap( ); + /// + /// + /// Initial image: + /// + /// Fourier image: + /// + /// + /// + public class ComplexImage : ICloneable + { + // image complex data + private Complex[,] data; + + // image dimension + private int width; + private int height; + + // current state of the image (transformed with Fourier ot not) + private bool fourierTransformed = false; + + /// + /// Image width. + /// + /// + public int Width + { + get { return width; } + } + + /// + /// Image height. + /// + /// + public int Height + { + get { return height; } + } + + /// + /// Status of the image - Fourier transformed or not. + /// + /// + public bool FourierTransformed + { + get { return fourierTransformed; } + } + + /// + /// Complex image's data. + /// + /// + /// Return's 2D array of [height, width] size, which keeps image's + /// complex data. + /// + public Complex[,] Data + { + get { return data; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Image width. + /// Image height. + /// + /// The constractor is protected, what makes it imposible to instantiate this + /// class directly. To create an instance of this class or + /// method should be used. + /// + protected ComplexImage(int width, int height) + { + this.width = width; + this.height = height; + this.data = new Complex[height, width]; + this.fourierTransformed = false; + } + + /// + /// Clone the complex image. + /// + /// + /// Returns copy of the complex image. + /// + public object Clone() + { + // create new complex image + ComplexImage dstImage = new ComplexImage(width, height); + Complex[,] data = dstImage.data; + + for (int i = 0; i < height; i++) + { + for (int j = 0; j < width; j++) + { + data[i, j] = this.data[i, j]; + } + } + + // clone mode as well + dstImage.fourierTransformed = fourierTransformed; + + return dstImage; + } + + /// + /// Create complex image from grayscale bitmap. + /// + /// + /// Source grayscale bitmap (8 bpp indexed). + /// + /// Returns an instance of complex image. + /// + /// The source image has incorrect pixel format. + /// Image width and height should be power of 2. + /// + public static ComplexImage FromBitmap(Bitmap image) + { + // check image format + if (image.PixelFormat != PixelFormat.Format8bppIndexed) + { + throw new UnsupportedImageFormatException("Source image can be graysclae (8bpp indexed) image only."); + } + + // lock source bitmap data + BitmapData imageData = image.LockBits( + new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); + + ComplexImage complexImage; + + try + { + complexImage = FromBitmap(imageData); + } + finally + { + // unlock source images + image.UnlockBits(imageData); + } + + return complexImage; + } + + /// + /// Create complex image from grayscale bitmap. + /// + /// + /// Source image data (8 bpp indexed). + /// + /// Returns an instance of complex image. + /// + /// The source image has incorrect pixel format. + /// Image width and height should be power of 2. + /// + public static ComplexImage FromBitmap(BitmapData imageData) + { + // check image format + if (imageData.PixelFormat != PixelFormat.Format8bppIndexed) + { + throw new UnsupportedImageFormatException("Source image can be graysclae (8bpp indexed) image only."); + } + + // get source image size + int width = imageData.Width; + int height = imageData.Height; + int offset = imageData.Stride - width; + + // check image size + if ((!Tools.IsPowerOf2(width)) || (!Tools.IsPowerOf2(height))) + { + throw new InvalidImagePropertiesException("Image width and height should be power of 2."); + } + + // create new complex image + ComplexImage complexImage = new ComplexImage(width, height); + + Complex[,] data = complexImage.data; + + // do the job + unsafe + { + byte* src = (byte*)imageData.Scan0.ToPointer(); + + // for each line + for (int y = 0; y < height; y++) + { + // for each pixel + for (int x = 0; x < width; x++, src++) + data[y, x] = new Complex((float)*src / 255, data[y, x].Imaginary); + + src += offset; + } + } + + return complexImage; + } + + /// + /// Convert complex image to bitmap. + /// + /// + /// Returns grayscale bitmap. + /// + public Bitmap ToBitmap() + { + // create new image + Bitmap dstImage = AForge.Imaging.Image.CreateGrayscaleImage(width, height); + + // lock destination bitmap data + BitmapData dstData = dstImage.LockBits( + new Rectangle(0, 0, width, height), + ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed); + + int offset = dstData.Stride - width; + double scale = (fourierTransformed) ? Math.Sqrt(width * height) : 1; + + // do the job + unsafe + { + byte* dst = (byte*)dstData.Scan0.ToPointer(); + + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++, dst++) + { + *dst = (byte)System.Math.Max(0, System.Math.Min(255, data[y, x].Magnitude * scale * 255)); + } + dst += offset; + } + } + // unlock destination images + dstImage.UnlockBits(dstData); + + return dstImage; + } + + /// + /// Applies forward fast Fourier transformation to the complex image. + /// + /// + public void ForwardFourierTransform() + { + if (!fourierTransformed) + { + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + if (((x + y) & 0x1) != 0) + data[y, x] *= -1; + } + } + + FourierTransform.FFT2(data, FourierTransform.Direction.Forward); + fourierTransformed = true; + } + } + + /// + /// Applies backward fast Fourier transformation to the complex image. + /// + /// + public void BackwardFourierTransform() + { + if (fourierTransformed) + { + FourierTransform.FFT2(data, FourierTransform.Direction.Backward); + fourierTransformed = false; + + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + if (((x + y) & 0x1) != 0) + data[y, x] *= -1; + } + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/DocumentSkewChecker.cs b/Sources/Accord.Imaging/AForge/DocumentSkewChecker.cs new file mode 100644 index 0000000000..2cde8af31 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/DocumentSkewChecker.cs @@ -0,0 +1,502 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2005-2010 +// andrew.kirillov@aforgenet.com +// +// Alejandro Pirola, 2008 +// alejamp@gmail.com +// + +namespace AForge.Imaging +{ + using System; + using System.Collections; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Skew angle checker for scanned documents. + /// + /// + /// The class implements document's skew checking algorithm, which is based + /// on Hough line transformation. The algorithm + /// is based on searching for text base lines - black line of text bottoms' followed + /// by white line below. + /// + /// The routine supposes that a white-background document is provided + /// with black letters. The algorithm is not supposed for any type of objects, but for + /// document images with text. + /// + /// The range of angles to detect is controlled by property. + /// + /// The filter accepts 8 bpp grayscale images for processing. + /// + /// Sample usage: + /// + /// // create instance of skew checker + /// DocumentSkewChecker skewChecker = new DocumentSkewChecker( ); + /// // get documents skew angle + /// double angle = skewChecker.GetSkewAngle( documentImage ); + /// // create rotation filter + /// RotateBilinear rotationFilter = new RotateBilinear( -angle ); + /// rotationFilter.FillColor = Color.White; + /// // rotate image applying the filter + /// Bitmap rotatedImage = rotationFilter.Apply( documentImage ); + /// + /// + /// Initial image: + /// + /// Deskewed image: + /// + /// + /// + /// + /// + public class DocumentSkewChecker + { + // Hough transformation: quality settings + private int stepsPerDegree; + private int houghHeight; + private double thetaStep; + private double maxSkewToDetect; + + // Hough transformation: precalculated Sine and Cosine values + private double[] sinMap; + private double[] cosMap; + private bool needToInitialize = true; + + // Hough transformation: Hough map + private short[,] houghMap; + private short maxMapIntensity = 0; + + private int localPeakRadius = 4; + private ArrayList lines = new ArrayList( ); + + /// + /// Steps per degree, [1, 10]. + /// + /// + /// The value defines quality of Hough transform and its ability to detect + /// line slope precisely. + /// + /// Default value is set to 1. + /// + /// + public int StepsPerDegree + { + get { return stepsPerDegree; } + set + { + stepsPerDegree = Math.Max( 1, Math.Min( 10, value ) ); + needToInitialize = true; + } + } + + /// + /// Maximum skew angle to detect, [0, 45] degrees. + /// + /// + /// The value sets maximum document's skew angle to detect. + /// Document's skew angle can be as positive (rotated counter clockwise), as negative + /// (rotated clockwise). So setting this value to 25, for example, will lead to + /// [-25, 25] degrees detection range. + /// + /// Scanned documents usually have skew in the [-20, 20] degrees range. + /// + /// Default value is set to 30. + /// + /// + public double MaxSkewToDetect + { + get { return maxSkewToDetect; } + set + { + maxSkewToDetect = Math.Max( 0, Math.Min( 45, value ) ); + needToInitialize = true; + } + } + + /// + /// Minimum angle to detect skew in degrees. + /// + /// + /// The property is deprecated and setting it has not any effect. + /// Use property instead. + /// + [Obsolete( "The property is deprecated and setting it has not any effect. Use MaxSkewToDetect property instead." )] + public double MinBeta + { + get { return ( -maxSkewToDetect ); } + set { } + } + + /// + /// Maximum angle to detect skew in degrees. + /// + /// + /// The property is deprecated and setting it has not any effect. + /// Use property instead. + /// + [Obsolete( "The property is deprecated and setting it has not any effect. Use MaxSkewToDetect property instead." )] + public double MaxBeta + { + get { return ( maxSkewToDetect ); } + set { } + } + + /// + /// Radius for searching local peak value, [1, 10]. + /// + /// + /// The value determines radius around a map's value, which is analyzed to determine + /// if the map's value is a local maximum in specified area. + /// + /// Default value is set to 4. + /// + public int LocalPeakRadius + { + get { return localPeakRadius; } + set { localPeakRadius = Math.Max( 1, Math.Min( 10, value ) ); } + } + + /// + /// Initializes a new instance of the class. + /// + public DocumentSkewChecker( ) + { + StepsPerDegree = 10; + MaxSkewToDetect = 30; + } + + /// + /// Get skew angle of the provided document image. + /// + /// + /// Document's image to get skew angle of. + /// + /// Returns document's skew angle. If the returned angle equals to -90, + /// then document skew detection has failed. + /// + /// Unsupported pixel format of the source image. + /// + public double GetSkewAngle( Bitmap image ) + { + return GetSkewAngle( image, new Rectangle( 0, 0, image.Width, image.Height ) ); + } + + /// + /// Get skew angle of the provided document image. + /// + /// + /// Document's image to get skew angle of. + /// Image's rectangle to process (used to exclude processing of + /// regions, which are not relevant to skew detection). + /// + /// Returns document's skew angle. If the returned angle equals to -90, + /// then document skew detection has failed. + /// + /// Unsupported pixel format of the source image. + /// + public double GetSkewAngle( Bitmap image, Rectangle rect ) + { + // check image format + if ( image.PixelFormat != PixelFormat.Format8bppIndexed ) + { + throw new UnsupportedImageFormatException( "Unsupported pixel format of the source image." ); + } + + // lock source image + BitmapData imageData = image.LockBits( + new Rectangle( 0, 0, image.Width, image.Height ), + ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed ); + + double skewAngle; + + try + { + // process the image + skewAngle = GetSkewAngle( new UnmanagedImage( imageData ), rect ); + } + finally + { + // unlock image + image.UnlockBits( imageData ); + } + + return skewAngle; + } + + /// + /// Get skew angle of the provided document image. + /// + /// + /// Document's image data to get skew angle of. + /// + /// Returns document's skew angle. If the returned angle equals to -90, + /// then document skew detection has failed. + /// + /// Unsupported pixel format of the source image. + /// + public double GetSkewAngle( BitmapData imageData ) + { + return GetSkewAngle( new UnmanagedImage( imageData ), + new Rectangle( 0, 0, imageData.Width, imageData.Height ) ); + } + + /// + /// Get skew angle of the provided document image. + /// + /// + /// Document's image data to get skew angle of. + /// Image's rectangle to process (used to exclude processing of + /// regions, which are not relevant to skew detection). + /// + /// Returns document's skew angle. If the returned angle equals to -90, + /// then document skew detection has failed. + /// + /// Unsupported pixel format of the source image. + /// + public double GetSkewAngle( BitmapData imageData, Rectangle rect ) + { + return GetSkewAngle( new UnmanagedImage( imageData ), rect ); + } + + /// + /// Get skew angle of the provided document image. + /// + /// + /// Document's unmanaged image to get skew angle of. + /// + /// Returns document's skew angle. If the returned angle equals to -90, + /// then document skew detection has failed. + /// + /// Unsupported pixel format of the source image. + /// + public double GetSkewAngle( UnmanagedImage image ) + { + return GetSkewAngle( image, new Rectangle( 0, 0, image.Width, image.Height ) ); + } + + /// + /// Get skew angle of the provided document image. + /// + /// + /// Document's unmanaged image to get skew angle of. + /// Image's rectangle to process (used to exclude processing of + /// regions, which are not relevant to skew detection). + /// + /// Returns document's skew angle. If the returned angle equals to -90, + /// then document skew detection has failed. + /// + /// Unsupported pixel format of the source image. + /// + public double GetSkewAngle( UnmanagedImage image, Rectangle rect ) + { + if ( image.PixelFormat != PixelFormat.Format8bppIndexed ) + { + throw new UnsupportedImageFormatException( "Unsupported pixel format of the source image." ); + } + + // init hough transformation settings + InitHoughMap( ); + + // get source image size + int width = image.Width; + int height = image.Height; + int halfWidth = width / 2; + int halfHeight = height / 2; + + // make sure the specified rectangle recides with the source image + rect.Intersect( new Rectangle( 0, 0, width, height ) ); + + int startX = -halfWidth + rect.Left; + int startY = -halfHeight + rect.Top; + int stopX = width - halfWidth - ( width - rect.Right ); + int stopY = height - halfHeight - ( height - rect.Bottom ) - 1; + + int offset = image.Stride - rect.Width; + + // calculate Hough map's width + int halfHoughWidth = (int) Math.Sqrt( halfWidth * halfWidth + halfHeight * halfHeight ); + int houghWidth = halfHoughWidth * 2; + + houghMap = new short[houghHeight, houghWidth]; + + // do the job + unsafe + { + byte* src = (byte*) image.ImageData.ToPointer( ) + + rect.Top * image.Stride + rect.Left; + byte* srcBelow = src + image.Stride; + + // for each row + for ( int y = startY; y < stopY; y++ ) + { + // for each pixel + for ( int x = startX; x < stopX; x++, src++, srcBelow++ ) + { + // if current pixel is more black + // and pixel below is more white + if ( ( *src < 128 ) && ( *srcBelow >= 128 ) ) + { + // for each Theta value + for ( int theta = 0; theta < houghHeight; theta++ ) + { + int radius = (int) ( cosMap[theta] * x - sinMap[theta] * y ) + halfHoughWidth; + + if ( ( radius < 0 ) || ( radius >= houghWidth ) ) + continue; + + houghMap[theta, radius]++; + } + } + } + src += offset; + srcBelow += offset; + } + } + + // find max value in Hough map + maxMapIntensity = 0; + for ( int i = 0; i < houghHeight; i++ ) + { + for ( int j = 0; j < houghWidth; j++ ) + { + if ( houghMap[i, j] > maxMapIntensity ) + { + maxMapIntensity = houghMap[i, j]; + } + } + } + + CollectLines( (short) ( width / 10 ) ); + + // get skew angle + HoughLine[] hls = this.GetMostIntensiveLines( 5 ); + + double skewAngle = 0; + double sumIntensity = 0; + + foreach ( HoughLine hl in hls ) + { + if ( hl.RelativeIntensity > 0.5 ) + { + skewAngle += ( hl.Theta * hl.RelativeIntensity ); + sumIntensity += hl.RelativeIntensity; + } + } + if ( hls.Length > 0 ) skewAngle = skewAngle / sumIntensity; + + return skewAngle - 90.0; + } + + // Get specified amount of lines with highest intensity + private HoughLine[] GetMostIntensiveLines( int count ) + { + // lines count + int n = Math.Min( count, lines.Count ); + + // result array + HoughLine[] dst = new HoughLine[n]; + lines.CopyTo( 0, dst, 0, n ); + + return dst; + } + + // Collect lines with intesities greater or equal then specified + private void CollectLines( short minLineIntensity ) + { + int maxTheta = houghMap.GetLength( 0 ); + int maxRadius = houghMap.GetLength( 1 ); + + short intensity; + bool foundGreater; + + int halfHoughWidth = maxRadius >> 1; + + // clean lines collection + lines.Clear( ); + + // for each Theta value + for ( int theta = 0; theta < maxTheta; theta++ ) + { + // for each Radius value + for ( int radius = 0; radius < maxRadius; radius++ ) + { + // get current value + intensity = houghMap[theta, radius]; + + if ( intensity < minLineIntensity ) + continue; + + foundGreater = false; + + // check neighboors + for ( int tt = theta - localPeakRadius, ttMax = theta + localPeakRadius; tt < ttMax; tt++ ) + { + // skip out of map values + if ( tt < 0 ) + continue; + if ( tt >= maxTheta ) + break; + + // break if it is not local maximum + if ( foundGreater == true ) + break; + + for ( int tr = radius - localPeakRadius, trMax = radius + localPeakRadius; tr < trMax; tr++ ) + { + // skip out of map values + if ( tr < 0 ) + continue; + if ( tr >= maxRadius ) + break; + + // compare the neighboor with current value + if ( houghMap[tt, tr] > intensity ) + { + foundGreater = true; + break; + } + } + } + + // was it local maximum ? + if ( !foundGreater ) + { + // we have local maximum + lines.Add( new HoughLine( 90.0 - maxSkewToDetect + (double) theta / stepsPerDegree, (short) ( radius - halfHoughWidth ), intensity, (double) intensity / maxMapIntensity ) ); + } + } + } + + lines.Sort( ); + } + + // Init Hough settings and map + private void InitHoughMap( ) + { + if ( needToInitialize ) + { + needToInitialize = false; + + houghHeight = (int) ( 2 * maxSkewToDetect * stepsPerDegree ); + thetaStep = ( 2 * maxSkewToDetect * Math.PI / 180 ) / houghHeight; + + // precalculate Sine and Cosine values + sinMap = new double[houghHeight]; + cosMap = new double[houghHeight]; + + double minTheta = 90.0 - maxSkewToDetect; + + for ( int i = 0; i < houghHeight; i++ ) + { + sinMap[i] = Math.Sin( ( minTheta * Math.PI / 180 ) + ( i * thetaStep ) ); + cosMap[i] = Math.Cos( ( minTheta * Math.PI / 180 ) + ( i * thetaStep ) ); + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Drawing.cs b/Sources/Accord.Imaging/AForge/Drawing.cs new file mode 100644 index 0000000000..4f8da7948 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Drawing.cs @@ -0,0 +1,617 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Drawing primitives. + /// + /// + /// The class allows to do drawing of some primitives directly on + /// locked image data or unmanaged image. + /// + /// All methods of this class support drawing only on color 24/32 bpp images and + /// on grayscale 8 bpp indexed images. + /// + /// When it comes to alpha blending for 24/32 bpp images, all calculations are done + /// as described on Wikipeadia + /// (see "over" operator). + /// + /// + public static class Drawing + { + /// + /// Fill rectangle on the specified image. + /// + /// + /// Source image data to draw on. + /// Rectangle's coordinates to fill. + /// Rectangle's color. + /// + /// The source image has incorrect pixel format. + /// + public static void FillRectangle(BitmapData imageData, Rectangle rectangle, Color color) + { + FillRectangle(new UnmanagedImage(imageData), rectangle, color); + } + + /// + /// Fill rectangle on the specified image. + /// + /// + /// Source image to draw on. + /// Rectangle's coordinates to fill. + /// Rectangle's color. + /// + /// The source image has incorrect pixel format. + /// + public static void FillRectangle(UnmanagedImage image, Rectangle rectangle, Color color) + { + CheckPixelFormat(image.PixelFormat); + + int pixelSize = System.Drawing.Image.GetPixelFormatSize(image.PixelFormat) / 8; + + // image dimension + int imageWidth = image.Width; + int imageHeight = image.Height; + int stride = image.Stride; + + // rectangle dimension and position + int rectX1 = rectangle.X; + int rectY1 = rectangle.Y; + int rectX2 = rectangle.X + rectangle.Width - 1; + int rectY2 = rectangle.Y + rectangle.Height - 1; + + // check if rectangle is in the image + if ((rectX1 >= imageWidth) || (rectY1 >= imageHeight) || (rectX2 < 0) || (rectY2 < 0)) + { + // nothing to draw + return; + } + + int startX = Math.Max(0, rectX1); + int stopX = Math.Min(imageWidth - 1, rectX2); + int startY = Math.Max(0, rectY1); + int stopY = Math.Min(imageHeight - 1, rectY2); + + unsafe + { + // do the job + byte* ptr = (byte*)image.ImageData.ToPointer() + startY * stride + startX * pixelSize; + + if (image.PixelFormat == PixelFormat.Format8bppIndexed) + { + // grayscale image + byte gray = (byte)(0.2125 * color.R + 0.7154 * color.G + 0.0721 * color.B); + + int fillWidth = stopX - startX + 1; + + for (int y = startY; y <= stopY; y++) + { + AForge.SystemTools.SetUnmanagedMemory(ptr, gray, fillWidth); + ptr += stride; + } + } + else if (image.PixelFormat == PixelFormat.Format32bppArgb) + { + // color 32 bpp ARGB image + double fillAlpha = color.A / 255.0; + double fillNegAlpha = 1.0 - fillAlpha; + + double fillRedPart = fillAlpha * color.R; + double fillGreenPart = fillAlpha * color.G; + double fillBluePart = fillAlpha * color.B; + + int offset = stride - (stopX - startX + 1) * 4; + + for (int y = startY; y <= stopY; y++) + { + for (int x = startX; x <= stopX; x++, ptr += 4) + { + double srcAlphaPart = (ptr[RGB.A] / 255.0) * fillNegAlpha; + + ptr[RGB.R] = (byte)((fillRedPart + srcAlphaPart * ptr[RGB.R])); + ptr[RGB.G] = (byte)((fillGreenPart + srcAlphaPart * ptr[RGB.G])); + ptr[RGB.B] = (byte)((fillBluePart + srcAlphaPart * ptr[RGB.B])); + + ptr[RGB.A] = (byte)(255 * (fillAlpha + srcAlphaPart)); + } + ptr += offset; + } + } + else + { + // color 24/32 RGB image + byte red = color.R; + byte green = color.G; + byte blue = color.B; + + int offset = stride - (stopX - startX + 1) * pixelSize; + + if (color.A == 255) + { + // just copy fill color if it is not transparent + for (int y = startY; y <= stopY; y++) + { + for (int x = startX; x <= stopX; x++, ptr += pixelSize) + { + ptr[RGB.R] = red; + ptr[RGB.G] = green; + ptr[RGB.B] = blue; + } + ptr += offset; + } + } + else + { + // do alpha blending for transparent colors + int fillAlpha = color.A; + int fillNegAlpha = 255 - fillAlpha; + + int fillRedPart = fillAlpha * color.R; + int fillGreenPart = fillAlpha * color.G; + int fillBluePart = fillAlpha * color.B; + + for (int y = startY; y <= stopY; y++) + { + for (int x = startX; x <= stopX; x++, ptr += pixelSize) + { + ptr[RGB.R] = (byte)((fillRedPart + fillNegAlpha * ptr[RGB.R]) / 255); + ptr[RGB.G] = (byte)((fillGreenPart + fillNegAlpha * ptr[RGB.G]) / 255); + ptr[RGB.B] = (byte)((fillBluePart + fillNegAlpha * ptr[RGB.B]) / 255); + } + ptr += offset; + } + } + } + } + } + + /// + /// Draw rectangle on the specified image. + /// + /// + /// Source image data to draw on. + /// Rectangle's coordinates to draw. + /// Rectangle's color. + /// + /// The source image has incorrect pixel format. + /// + public static void Rectangle(BitmapData imageData, Rectangle rectangle, Color color) + { + Rectangle(new UnmanagedImage(imageData), rectangle, color); + } + + /// + /// Draw rectangle on the specified image. + /// + /// + /// Source image to draw on. + /// Rectangle's coordinates to draw. + /// Rectangle's color. + /// + /// The source image has incorrect pixel format. + /// + public static void Rectangle(UnmanagedImage image, Rectangle rectangle, Color color) + { + CheckPixelFormat(image.PixelFormat); + + // image dimension + int imageWidth = image.Width; + int imageHeight = image.Height; + int stride = image.Stride; + + // rectangle dimension and position + int rectX1 = rectangle.X; + int rectY1 = rectangle.Y; + int rectX2 = rectangle.X + rectangle.Width - 1; + int rectY2 = rectangle.Y + rectangle.Height - 1; + + // check if rectangle is in the image + if ((rectX1 >= imageWidth) || (rectY1 >= imageHeight) || (rectX2 < 0) || (rectY2 < 0)) + { + // nothing to draw + return; + } + + // obviously vertical/horizontal lines can be drawn faster, but at least we simplify the code + Line(image, new IntPoint(rectX1, rectY1), new IntPoint(rectX2, rectY1), color); + Line(image, new IntPoint(rectX2, rectY2), new IntPoint(rectX1, rectY2), color); + + Line(image, new IntPoint(rectX2, rectY1 + 1), new IntPoint(rectX2, rectY2 - 1), color); + Line(image, new IntPoint(rectX1, rectY2 - 1), new IntPoint(rectX1, rectY1 + 1), color); + } + + /// + /// Draw a line on the specified image. + /// + /// + /// Source image data to draw on. + /// The first point to connect. + /// The second point to connect. + /// Line's color. + /// + /// The source image has incorrect pixel format. + /// + public static void Line(BitmapData imageData, IntPoint point1, IntPoint point2, Color color) + { + Line(new UnmanagedImage(imageData), point1, point2, color); + } + + /// + /// Draw a line on the specified image. + /// + /// + /// Source image to draw on. + /// The first point to connect. + /// The second point to connect. + /// Line's color. + /// + /// The source image has incorrect pixel format. + /// + public static void Line(UnmanagedImage image, IntPoint point1, IntPoint point2, Color color) + { + // TODO: faster line drawing algorithm may be implemented with integer math + + CheckPixelFormat(image.PixelFormat); + + int pixelSize = System.Drawing.Image.GetPixelFormatSize(image.PixelFormat) / 8; + + // image dimension + int imageWidth = image.Width; + int imageHeight = image.Height; + int stride = image.Stride; + + // check if there is something to draw + if ( + ((point1.X < 0) && (point2.X < 0)) || + ((point1.Y < 0) && (point2.Y < 0)) || + ((point1.X >= imageWidth) && (point2.X >= imageWidth)) || + ((point1.Y >= imageHeight) && (point2.Y >= imageHeight))) + { + // nothing to draw + return; + } + + CheckEndPoint(imageWidth, imageHeight, point1, ref point2); + CheckEndPoint(imageWidth, imageHeight, point2, ref point1); + + // check again if there is something to draw + if ( + ((point1.X < 0) && (point2.X < 0)) || + ((point1.Y < 0) && (point2.Y < 0)) || + ((point1.X >= imageWidth) && (point2.X >= imageWidth)) || + ((point1.Y >= imageHeight) && (point2.Y >= imageHeight))) + { + // nothing to draw + return; + } + + int startX = point1.X; + int startY = point1.Y; + int stopX = point2.X; + int stopY = point2.Y; + + // compute pixel for grayscale image + byte gray = 0; + if (image.PixelFormat == PixelFormat.Format8bppIndexed) + { + gray = (byte)(0.2125 * color.R + 0.7154 * color.G + 0.0721 * color.B); + } + + // pre-compute some values for 32 bit color blending + double fillAlpha = color.A / 255.0; + double fillNegAlpha = 1.0 - fillAlpha; + + double fillRedPart = fillAlpha * color.R; + double fillGreenPart = fillAlpha * color.G; + double fillBluePart = fillAlpha * color.B; + + int fillNegAlphaInt = 255 - color.A; + + int fillRedPartInt = color.A * color.R; + int fillGreenPartInt = color.A * color.G; + int fillBluePartInt = color.A * color.B; + + // draw the line + int dx = stopX - startX; + int dy = stopY - startY; + + unsafe + { + if (Math.Abs(dx) >= Math.Abs(dy)) + { + // the line is more horizontal, we'll plot along the X axis + float slope = (dx != 0) ? (float)dy / dx : 0; + int step = (dx > 0) ? 1 : -1; + + // correct dx so last point is included as well + dx += step; + + if (image.PixelFormat == PixelFormat.Format8bppIndexed) + { + // grayscale image + for (int x = 0; x != dx; x += step) + { + int px = startX + x; + int py = (int)((float)startY + (slope * (float)x)); + + byte* ptr = (byte*)image.ImageData.ToPointer() + py * stride + px; + *ptr = gray; + } + } + else if (image.PixelFormat == PixelFormat.Format32bppArgb) + { + // color 32 ARGB image image + for (int x = 0; x != dx; x += step) + { + int px = startX + x; + int py = (int)((float)startY + (slope * (float)x)); + + byte* ptr = (byte*)image.ImageData.ToPointer() + py * stride + px * 4; + + double srcAlphaPart = (ptr[RGB.A] / 255.0) * fillNegAlpha; + + ptr[RGB.R] = (byte)((fillRedPart + srcAlphaPart * ptr[RGB.R])); + ptr[RGB.G] = (byte)((fillGreenPart + srcAlphaPart * ptr[RGB.G])); + ptr[RGB.B] = (byte)((fillBluePart + srcAlphaPart * ptr[RGB.B])); + + ptr[RGB.A] = (byte)(255 * (fillAlpha + srcAlphaPart)); + } + } + else + { + // color 24/32 bpp RGB image + if (color.A == 255) + { + // just copy color for none transparent colors + for (int x = 0; x != dx; x += step) + { + int px = startX + x; + int py = (int)((float)startY + (slope * (float)x)); + + byte* ptr = (byte*)image.ImageData.ToPointer() + py * stride + px * pixelSize; + + ptr[RGB.R] = color.R; + ptr[RGB.G] = color.G; + ptr[RGB.B] = color.B; + } + } + else + { + // do alpha blending for transparent colors + for (int x = 0; x != dx; x += step) + { + int px = startX + x; + int py = (int)((float)startY + (slope * (float)x)); + + byte* ptr = (byte*)image.ImageData.ToPointer() + py * stride + px * pixelSize; + + ptr[RGB.R] = (byte)((fillRedPartInt + fillNegAlphaInt * ptr[RGB.R]) / 255); + ptr[RGB.G] = (byte)((fillGreenPartInt + fillNegAlphaInt * ptr[RGB.G]) / 255); + ptr[RGB.B] = (byte)((fillBluePartInt + fillNegAlphaInt * ptr[RGB.B]) / 255); + } + } + } + } + else + { + // the line is more vertical, we'll plot along the y axis. + float slope = (dy != 0) ? (float)dx / dy : 0; + int step = (dy > 0) ? 1 : -1; + + // correct dy so last point is included as well + dy += step; + + if (image.PixelFormat == PixelFormat.Format8bppIndexed) + { + // grayscale image + for (int y = 0; y != dy; y += step) + { + int px = (int)((float)startX + (slope * (float)y)); + int py = startY + y; + + byte* ptr = (byte*)image.ImageData.ToPointer() + py * stride + px; + *ptr = gray; + } + } + else if (image.PixelFormat == PixelFormat.Format32bppArgb) + { + // color 32 bpp ARGB image + for (int y = 0; y != dy; y += step) + { + int px = (int)((float)startX + (slope * (float)y)); + int py = startY + y; + + byte* ptr = (byte*)image.ImageData.ToPointer() + py * stride + px * 4; + + double srcAlphaPart = (ptr[RGB.A] / 255.0) * fillNegAlpha; + + ptr[RGB.R] = (byte)((fillRedPart + srcAlphaPart * ptr[RGB.R])); + ptr[RGB.G] = (byte)((fillGreenPart + srcAlphaPart * ptr[RGB.G])); + ptr[RGB.B] = (byte)((fillBluePart + srcAlphaPart * ptr[RGB.B])); + + ptr[RGB.A] = (byte)(255 * (fillAlpha + srcAlphaPart)); + } + } + else + { + // color 24/32 bpp RGB image + if (color.A == 255) + { + // just copy color for none transparent colors + for (int y = 0; y != dy; y += step) + { + int px = (int)((float)startX + (slope * (float)y)); + int py = startY + y; + + byte* ptr = (byte*)image.ImageData.ToPointer() + py * stride + px * pixelSize; + + ptr[RGB.R] = color.R; + ptr[RGB.G] = color.G; + ptr[RGB.B] = color.B; + } + } + else + { + // do alpha blending for transparent colors + for (int y = 0; y != dy; y += step) + { + int px = (int)((float)startX + (slope * (float)y)); + int py = startY + y; + + byte* ptr = (byte*)image.ImageData.ToPointer() + py * stride + px * pixelSize; + + ptr[RGB.R] = (byte)((fillRedPartInt + fillNegAlphaInt * ptr[RGB.R]) / 255); + ptr[RGB.G] = (byte)((fillGreenPartInt + fillNegAlphaInt * ptr[RGB.G]) / 255); + ptr[RGB.B] = (byte)((fillBluePartInt + fillNegAlphaInt * ptr[RGB.B]) / 255); + } + } + } + } + } + } + + /// + /// Draw a polygon on the specified image. + /// + /// + /// Source image data to draw on. + /// Points of the polygon to draw. + /// Polygon's color. + /// + /// The method draws a polygon by connecting all points from the + /// first one to the last one and then connecting the last point with the first one. + /// + /// + public static void Polygon(BitmapData imageData, List points, Color color) + { + Polygon(new UnmanagedImage(imageData), points, color); + } + + /// + /// Draw a polygon on the specified image. + /// + /// + /// Source image to draw on. + /// Points of the polygon to draw. + /// Polygon's color. + /// + /// The method draws a polygon by connecting all points from the + /// first one to the last one and then connecting the last point with the first one. + /// + /// + public static void Polygon(UnmanagedImage image, List points, Color color) + { + for (int i = 1, n = points.Count; i < n; i++) + { + Line(image, points[i - 1], points[i], color); + } + Line(image, points[points.Count - 1], points[0], color); + } + + /// + /// Draw a polyline on the specified image. + /// + /// + /// Source image data to draw on. + /// Points of the polyline to draw. + /// polyline's color. + /// + /// The method draws a polyline by connecting all points from the + /// first one to the last one. Unlike + /// method, this method does not connect the last point with the first one. + /// + /// + public static void Polyline(BitmapData imageData, List points, Color color) + { + Polyline(new UnmanagedImage(imageData), points, color); + } + + /// + /// Draw a polyline on the specified image. + /// + /// + /// Source image to draw on. + /// Points of the polyline to draw. + /// polyline's color. + /// + /// The method draws a polyline by connecting all points from the + /// first one to the last one. Unlike + /// method, this method does not connect the last point with the first one. + /// + /// + public static void Polyline(UnmanagedImage image, List points, Color color) + { + for (int i = 1, n = points.Count; i < n; i++) + { + Line(image, points[i - 1], points[i], color); + } + } + + // Check for supported pixel format + private static void CheckPixelFormat(PixelFormat format) + { + // check pixel format + if ( + (format != PixelFormat.Format24bppRgb) && + (format != PixelFormat.Format8bppIndexed) && + (format != PixelFormat.Format32bppArgb) && + (format != PixelFormat.Format32bppRgb) + ) + { + throw new UnsupportedImageFormatException("Unsupported pixel format of the source image."); + } + } + + // Check end point and make sure it is in the image + private static void CheckEndPoint(int width, int height, IntPoint start, ref IntPoint end) + { + if (end.X >= width) + { + int newEndX = width - 1; + + double c = (double)(newEndX - start.X) / (end.X - start.X); + + end.Y = (int)(start.Y + c * (end.Y - start.Y)); + end.X = newEndX; + } + + if (end.Y >= height) + { + int newEndY = height - 1; + + double c = (double)(newEndY - start.Y) / (end.Y - start.Y); + + end.X = (int)(start.X + c * (end.X - start.X)); + end.Y = newEndY; + } + + if (end.X < 0) + { + double c = (double)(0 - start.X) / (end.X - start.X); + + end.Y = (int)(start.Y + c * (end.Y - start.Y)); + end.X = 0; + } + + if (end.Y < 0) + { + double c = (double)(0 - start.Y) / (end.Y - start.Y); + + end.X = (int)(start.X + c * (end.X - start.X)); + end.Y = 0; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Exceptions.cs b/Sources/Accord.Imaging/AForge/Exceptions.cs new file mode 100644 index 0000000000..9eda06dcd --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Exceptions.cs @@ -0,0 +1,95 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging +{ + using System; + + /// + /// Unsupported image format exception. + /// + /// + /// The unsupported image format exception is thrown in the case when + /// user passes an image of certain format to an image processing routine, which does + /// not support the format. Check documentation of the image processing routine + /// to discover which formats are supported by the routine. + /// + /// + [Serializable] + public class UnsupportedImageFormatException : ArgumentException + { + /// + /// Initializes a new instance of the class. + /// + public UnsupportedImageFormatException( ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Message providing some additional information. + /// + public UnsupportedImageFormatException( string message ) : + base( message ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Message providing some additional information. + /// Name of the invalid parameter. + /// + public UnsupportedImageFormatException( string message, string paramName ) : + base( message, paramName ) { } + } + + /// + /// Invalid image properties exception. + /// + /// + /// The invalid image properties exception is thrown in the case when + /// user provides an image with certain properties, which are treated as invalid by + /// particular image processing routine. Another case when this exception is + /// thrown is the case when user tries to access some properties of an image (or + /// of a recently processed image by some routine), which are not valid for that image. + /// + /// + public class InvalidImagePropertiesException : ArgumentException + { + /// + /// Initializes a new instance of the class. + /// + public InvalidImagePropertiesException( ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Message providing some additional information. + /// + public InvalidImagePropertiesException( string message ) : + base( message ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Message providing some additional information. + /// Name of the invalid parameter. + /// + public InvalidImagePropertiesException( string message, string paramName ) : + base( message, paramName ) { } + } + + // Some common exception messages + internal static class ExceptionMessage + { + public const string ColorHistogramException = "Cannot access color histogram since the last processed image was grayscale."; + public const string GrayHistogramException = "Cannot access gray histogram since the last processed image was color."; + } +} \ No newline at end of file diff --git a/Sources/Accord.Imaging/AForge/ExhaustiveBlockMatching.cs b/Sources/Accord.Imaging/AForge/ExhaustiveBlockMatching.cs new file mode 100644 index 0000000000..9b89a4af0 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/ExhaustiveBlockMatching.cs @@ -0,0 +1,397 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// +// Copyright Joan Charmant, 2008 +// joan.charmant@gmail.com +// +namespace AForge.Imaging +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Block matching implementation with the exhaustive search algorithm. + /// + /// + /// The class implements exhaustive search block matching algorithm + /// (see documentation for for information about + /// block matching algorithms). Exhaustive search algorithm tests each possible + /// location of block within search window trying to find a match with minimal + /// difference. + /// + /// Because of the exhaustive nature of the algorithm, high performance + /// should not be expected in the case if big number of reference points is provided + /// or big block size and search radius are specified. Minimizing theses values increases + /// performance. But too small block size and search radius may affect quality. + /// + /// The class processes only grayscale (8 bpp indexed) and color (24 bpp) images. + /// + /// Sample usage: + /// + /// // collect reference points using corners detector (for example) + /// SusanCornersDetector scd = new SusanCornersDetector( 30, 18 ); + /// List<IntPoint> points = scd.ProcessImage( sourceImage ); + /// + /// // create block matching algorithm's instance + /// ExhaustiveBlockMatching bm = new ExhaustiveBlockMatching( 8, 12 ); + /// // process images searching for block matchings + /// List<BlockMatch> matches = bm.ProcessImage( sourceImage, points, searchImage ); + /// + /// // draw displacement vectors + /// BitmapData data = sourceImage.LockBits( + /// new Rectangle( 0, 0, sourceImage.Width, sourceImage.Height ), + /// ImageLockMode.ReadWrite, sourceImage.PixelFormat ); + /// + /// foreach ( BlockMatch match in matches ) + /// { + /// // highlight the original point in source image + /// Drawing.FillRectangle( data, + /// new Rectangle( match.SourcePoint.X - 1, match.SourcePoint.Y - 1, 3, 3 ), + /// Color.Yellow ); + /// // draw line to the point in search image + /// Drawing.Line( data, match.SourcePoint, match.MatchPoint, Color.Red ); + /// + /// // check similarity + /// if ( match.Similarity > 0.98f ) + /// { + /// // process block with high similarity somehow special + /// } + /// } + /// + /// sourceImage.UnlockBits( data ); + /// + /// + /// Test image 1 (source): + /// + /// Test image 2 (search): + /// + /// Result image: + /// + /// + /// + public class ExhaustiveBlockMatching : IBlockMatching + { + // block size to search for + private int blockSize = 16; + // search radius (maximum shift from base position, in all 4 directions) + private int searchRadius = 12; + // blocks' similarity threshold + private float similarityThreshold = 0.9f; + + /// + /// Search radius. + /// + /// + /// The value specifies the shift from reference point in all + /// four directions, used to search for the best matching block. + /// + /// Default value is set to 12. + /// + /// + public int SearchRadius + { + get { return searchRadius; } + set { searchRadius = value; } + } + + /// + /// Block size to search for. + /// + /// + /// The value specifies block size to search for. For each provided + /// reference pointer, a square block of this size is taken from the source image + /// (reference point becomes the coordinate of block's center) and the best match + /// is searched in second image within specified search + /// radius. + /// + /// Default value is set to 16. + /// + /// + public int BlockSize + { + get { return blockSize; } + set { blockSize = value; } + } + + /// + /// Similarity threshold, [0..1]. + /// + /// + /// The property sets the minimal acceptable similarity between blocks + /// in source and search images. If similarity is lower than this value, + /// then the candidate block in search image is not treated as a match for the block + /// in source image. + /// + /// + /// Default value is set to 0.9. + /// + /// + public float SimilarityThreshold + { + get { return similarityThreshold; } + set { similarityThreshold = Math.Min( 1, Math.Max( 0, value ) ); } + } + + /// + /// Initializes a new instance of the class. + /// + public ExhaustiveBlockMatching( ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Block size to search for. + /// Search radius. + /// + public ExhaustiveBlockMatching( int blockSize, int searchRadius ) + { + this.blockSize = blockSize; + this.searchRadius = searchRadius; + } + + /// + /// Process images matching blocks between hem. + /// + /// + /// Source image with reference points. + /// List of reference points to be matched. + /// Image in which the reference points will be looked for. + /// + /// Returns list of found block matches. The list is sorted by similarity + /// of found matches in descending order. + /// + /// Source and search images sizes must match. + /// Source images can be grayscale (8 bpp indexed) or color (24 bpp) image only. + /// Source and search images must have same pixel format. + /// + public List ProcessImage( Bitmap sourceImage, List coordinates, Bitmap searchImage ) + { + // lock source image + BitmapData sourceImageData = sourceImage.LockBits( + new Rectangle( 0, 0, sourceImage.Width, sourceImage.Height ), + ImageLockMode.ReadOnly, sourceImage.PixelFormat ); + + BitmapData searchImageData = searchImage.LockBits( + new Rectangle( 0, 0, searchImage.Width, searchImage.Height ), + ImageLockMode.ReadOnly, searchImage.PixelFormat ); + + List matchings; + + try + { + // process the image + matchings = ProcessImage( new UnmanagedImage( sourceImageData ), + coordinates, new UnmanagedImage( searchImageData ) ); + } + finally + { + // unlock image + sourceImage.UnlockBits( sourceImageData ); + searchImage.UnlockBits( searchImageData ); + } + + return matchings; + } + + /// + /// Process images matching blocks between them. + /// + /// + /// Source image with reference points. + /// List of reference points to be matched. + /// Image in which the reference points will be looked for. + /// + /// Returns list of found block matches. The list is sorted by similarity + /// of found matches in descending order. + /// + /// Source and search images sizes must match. + /// Source images can be grayscale (8 bpp indexed) or color (24 bpp) image only. + /// Source and search images must have same pixel format. + /// + public List ProcessImage( BitmapData sourceImageData, List coordinates, BitmapData searchImageData ) + { + return ProcessImage( new UnmanagedImage( sourceImageData ), coordinates, new UnmanagedImage( searchImageData ) ); + } + + /// + /// Process images matching blocks between them. + /// + /// + /// Source unmanaged image with reference points. + /// List of reference points to be matched. + /// Unmanaged image in which the reference points will be looked for. + /// + /// Returns list of found block matches. The list is sorted by similarity + /// of found matches in descending order. + /// + /// Source and search images sizes must match. + /// Source images can be grayscale (8 bpp indexed) or color (24 bpp) image only. + /// Source and search images must have same pixel format. + /// + public List ProcessImage( UnmanagedImage sourceImage, List coordinates, UnmanagedImage searchImage ) + { + // source images sizes must match. + if ( ( sourceImage.Width != searchImage.Width ) || ( sourceImage.Height != searchImage.Height ) ) + throw new InvalidImagePropertiesException( "Source and search images sizes must match" ); + + // sources images must be graysclae or color. + if ( ( sourceImage.PixelFormat != PixelFormat.Format8bppIndexed ) && ( sourceImage.PixelFormat != PixelFormat.Format24bppRgb ) ) + throw new UnsupportedImageFormatException( "Source images can be graysclae (8 bpp indexed) or color (24 bpp) image only" ); + + // source images must have the same pixel format. + if ( sourceImage.PixelFormat != searchImage.PixelFormat ) + throw new InvalidImagePropertiesException( "Source and search images must have same pixel format" ); + + int pointsCount = coordinates.Count; + + // found matches + List matchingsList = new List( ); + + // get source image size + int width = sourceImage.Width; + int height = sourceImage.Height; + int stride = sourceImage.Stride; + int pixelSize = ( sourceImage.PixelFormat == PixelFormat.Format8bppIndexed ) ? 1 : 3; + + // pre-compute some values to avoid doing it in the loops. + int blockRadius = blockSize / 2; + int searchWindowSize = 2 * searchRadius; + int blockLineSize = blockSize * pixelSize; + int blockOffset = stride - ( blockSize * pixelSize ); + + // maximum possible difference of blocks + int maxDiff = blockSize * blockSize * pixelSize * 255; + + // integer similarity threshold + int threshold = (int) ( similarityThreshold * maxDiff ); + + // do the job + unsafe + { + byte* ptrSource = (byte*) sourceImage.ImageData.ToPointer( ); + byte* ptrSearch = (byte*) searchImage.ImageData.ToPointer( ); + + // for each point fed + for ( int iPoint = 0; iPoint < pointsCount; iPoint++ ) + { + int refPointX = coordinates[iPoint].X; + int refPointY = coordinates[iPoint].Y; + + // make sure the source block is inside the image + if ( + ( ( refPointX - blockRadius < 0 ) || ( refPointX + blockRadius >= width ) ) || + ( ( refPointY - blockRadius < 0 ) || ( refPointY + blockRadius >= height ) ) + ) + { + // skip point + continue; + } + + // startting seatch point + int searchStartX = refPointX - blockRadius - searchRadius; + int searchStartY = refPointY - blockRadius - searchRadius; + + // output match + int bestMatchX = refPointX; + int bestMatchY = refPointY; + + // Exhaustive Search Algorithm - we test each location within the search window + int minError = int.MaxValue; + + // for each search window's row + for ( int searchWindowRow = 0; searchWindowRow < searchWindowSize; searchWindowRow++ ) + { + if ( ( searchStartY + searchWindowRow < 0 ) || ( searchStartY + searchWindowRow + blockSize >= height ) ) + { + // skip row + continue; + } + + // for each search window's column + for ( int searchWindowCol = 0; searchWindowCol < searchWindowSize; searchWindowCol++ ) + { + // tested block location in search image + int blockSearchX = searchStartX + searchWindowCol; + int blockSearchY = searchStartY + searchWindowRow; + + if ( ( blockSearchX < 0 ) || ( blockSearchY + blockSize >= width ) ) + { + // skip column + continue; + } + + // get memory location of the block's upper left point in source and search images + byte* ptrSourceBlock = ptrSource + ( ( refPointY - blockRadius ) * stride ) + ( ( refPointX - blockRadius ) * pixelSize ); + byte* ptrSearchBlock = ptrSearch + ( blockSearchY * stride ) + ( blockSearchX * pixelSize ); + + // navigate this block, accumulating the error + int error = 0; + for ( int blockRow = 0; blockRow < blockSize; blockRow++ ) + { + for ( int blockCol = 0; blockCol < blockLineSize; blockCol++, ptrSourceBlock++, ptrSearchBlock++ ) + { + int diff = *ptrSourceBlock - *ptrSearchBlock; + if ( diff > 0 ) + { + error += diff; + } + else + { + error -= diff; + } + } + + // move to the next row + ptrSourceBlock += blockOffset; + ptrSearchBlock += blockOffset; + } + + // check if the sum of error is mimimal + if ( error < minError ) + { + minError = error; + + // keep best match so far + bestMatchX = blockSearchX + blockRadius; + bestMatchY = blockSearchY + blockRadius; + } + } + } + + // calculate blocks' similarity and compare it with threshold + int blockSimilarity = maxDiff - minError; + + if ( blockSimilarity >= threshold ) + { + matchingsList.Add( new BlockMatch( + new IntPoint( refPointX, refPointY ), new IntPoint( bestMatchX, bestMatchY ), + (float) blockSimilarity / maxDiff ) ); + } + } + } + + // sort in descending order + matchingsList.Sort( new MatchingsSorter( ) ); + + return matchingsList; + } + + // Sorter of found matchings + private class MatchingsSorter : System.Collections.Generic.IComparer + { + public int Compare( BlockMatch x, BlockMatch y ) + { + float diff = y.Similarity - x.Similarity; + + return ( diff > 0 ) ? 1 : ( diff < 0 ) ? -1 : 0; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/ExhaustiveTemplateMatching.cs b/Sources/Accord.Imaging/AForge/ExhaustiveTemplateMatching.cs new file mode 100644 index 0000000000..92fafb2be --- /dev/null +++ b/Sources/Accord.Imaging/AForge/ExhaustiveTemplateMatching.cs @@ -0,0 +1,401 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + using System.Collections.Generic; + + /// + /// Exhaustive template matching. + /// + /// + /// The class implements exhaustive template matching algorithm, + /// which performs complete scan of source image, comparing each pixel with corresponding + /// pixel of template. + /// + /// The class processes only grayscale 8 bpp and color 24 bpp images. + /// + /// Sample usage: + /// + /// // create template matching algorithm's instance + /// ExhaustiveTemplateMatching tm = new ExhaustiveTemplateMatching( 0.9f ); + /// // find all matchings with specified above similarity + /// TemplateMatch[] matchings = tm.ProcessImage( sourceImage, templateImage ); + /// // highlight found matchings + /// BitmapData data = sourceImage.LockBits( + /// new Rectangle( 0, 0, sourceImage.Width, sourceImage.Height ), + /// ImageLockMode.ReadWrite, sourceImage.PixelFormat ); + /// foreach ( TemplateMatch m in matchings ) + /// { + /// Drawing.Rectangle( data, m.Rectangle, Color.White ); + /// // do something else with matching + /// } + /// sourceImage.UnlockBits( data ); + /// + /// + /// The class also can be used to get similarity level between two image of the same + /// size, which can be useful to get information about how different/similar are images: + /// + /// // create template matching algorithm's instance + /// // use zero similarity to make sure algorithm will provide anything + /// ExhaustiveTemplateMatching tm = new ExhaustiveTemplateMatching( 0 ); + /// // compare two images + /// TemplateMatch[] matchings = tm.ProcessImage( image1, image2 ); + /// // check similarity level + /// if ( matchings[0].Similarity > 0.95f ) + /// { + /// // do something with quite similar images + /// } + /// + /// + /// + /// + public class ExhaustiveTemplateMatching : ITemplateMatching + { + private float similarityThreshold = 0.9f; + + /// + /// Similarity threshold, [0..1]. + /// + /// + /// The property sets the minimal acceptable similarity between template + /// and potential found candidate. If similarity is lower than this value, + /// then object is not treated as matching with template. + /// + /// + /// Default value is set to 0.9. + /// + /// + public float SimilarityThreshold + { + get { return similarityThreshold; } + set { similarityThreshold = Math.Min( 1, Math.Max( 0, value ) ); } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public ExhaustiveTemplateMatching( ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Similarity threshold. + /// + public ExhaustiveTemplateMatching( float similarityThreshold ) + { + this.similarityThreshold = similarityThreshold; + } + + /// + /// Process image looking for matchings with specified template. + /// + /// + /// Source image to process. + /// Template image to search for. + /// + /// Returns array of found template matches. The array is sorted by similarity + /// of found matches in descending order. + /// + /// The source image has incorrect pixel format. + /// Template image is bigger than source image. + /// + public TemplateMatch[] ProcessImage( Bitmap image, Bitmap template ) + { + return ProcessImage( image, template, new Rectangle( 0, 0, image.Width, image.Height ) ); + } + + /// + /// Process image looking for matchings with specified template. + /// + /// + /// Source image to process. + /// Template image to search for. + /// Rectangle in source image to search template for. + /// + /// Returns array of found template matches. The array is sorted by similarity + /// of found matches in descending order. + /// + /// The source image has incorrect pixel format. + /// Template image is bigger than source image. + /// + public TemplateMatch[] ProcessImage( Bitmap image, Bitmap template, Rectangle searchZone ) + { + // check image format + if ( + ( ( image.PixelFormat != PixelFormat.Format8bppIndexed ) && + ( image.PixelFormat != PixelFormat.Format24bppRgb ) ) || + ( image.PixelFormat != template.PixelFormat ) ) + { + throw new UnsupportedImageFormatException( "Unsupported pixel format of the source or template image." ); + } + + // check template's size + if ( ( template.Width > image.Width ) || ( template.Height > image.Height ) ) + { + throw new InvalidImagePropertiesException( "Template's size should be smaller or equal to source image's size." ); + } + + // lock source and template images + BitmapData imageData = image.LockBits( + new Rectangle( 0, 0, image.Width, image.Height ), + ImageLockMode.ReadOnly, image.PixelFormat ); + BitmapData templateData = template.LockBits( + new Rectangle( 0, 0, template.Width, template.Height ), + ImageLockMode.ReadOnly, template.PixelFormat ); + + TemplateMatch[] matchings; + + try + { + // process the image + matchings = ProcessImage( + new UnmanagedImage( imageData ), + new UnmanagedImage( templateData ), + searchZone ); + } + finally + { + // unlock images + image.UnlockBits( imageData ); + template.UnlockBits( templateData ); + } + + return matchings; + } + + /// + /// Process image looking for matchings with specified template. + /// + /// + /// Source image data to process. + /// Template image to search for. + /// + /// Returns array of found template matches. The array is sorted by similarity + /// of found matches in descending order. + /// + /// The source image has incorrect pixel format. + /// Template image is bigger than source image. + /// + public TemplateMatch[] ProcessImage( BitmapData imageData, BitmapData templateData ) + { + return ProcessImage( new UnmanagedImage( imageData ), new UnmanagedImage( templateData ), + new Rectangle( 0, 0, imageData.Width, imageData.Height ) ); + } + + /// + /// Process image looking for matchings with specified template. + /// + /// + /// Source image data to process. + /// Template image to search for. + /// Rectangle in source image to search template for. + /// + /// Returns array of found template matches. The array is sorted by similarity + /// of found matches in descending order. + /// + /// The source image has incorrect pixel format. + /// Template image is bigger than source image. + /// + public TemplateMatch[] ProcessImage( BitmapData imageData, BitmapData templateData, Rectangle searchZone ) + { + return ProcessImage( new UnmanagedImage( imageData ), new UnmanagedImage( templateData ), searchZone ); + } + + /// + /// Process image looking for matchings with specified template. + /// + /// + /// Unmanaged source image to process. + /// Unmanaged template image to search for. + /// + /// Returns array of found template matches. The array is sorted by similarity + /// of found matches in descending order. + /// + /// The source image has incorrect pixel format. + /// Template image is bigger than source image. + /// + public TemplateMatch[] ProcessImage( UnmanagedImage image, UnmanagedImage template ) + { + return ProcessImage( image, template, new Rectangle( 0, 0, image.Width, image.Height ) ); + } + + /// + /// Process image looking for matchings with specified template. + /// + /// + /// Unmanaged source image to process. + /// Unmanaged template image to search for. + /// Rectangle in source image to search template for. + /// + /// Returns array of found template matches. The array is sorted by similarity + /// of found matches in descending order. + /// + /// The source image has incorrect pixel format. + /// Template image is bigger than search zone. + /// + public TemplateMatch[] ProcessImage( UnmanagedImage image, UnmanagedImage template, Rectangle searchZone ) + { + // check image format + if ( + ( ( image.PixelFormat != PixelFormat.Format8bppIndexed ) && + ( image.PixelFormat != PixelFormat.Format24bppRgb ) ) || + ( image.PixelFormat != template.PixelFormat ) ) + { + throw new UnsupportedImageFormatException( "Unsupported pixel format of the source or template image." ); + } + + // clip search zone + Rectangle zone = searchZone; + zone.Intersect( new Rectangle( 0, 0, image.Width, image.Height ) ); + + // search zone's starting point + int startX = zone.X; + int startY = zone.Y; + + // get source and template image size + int sourceWidth = zone.Width; + int sourceHeight = zone.Height; + int templateWidth = template.Width; + int templateHeight = template.Height; + + // check template's size + if ( ( templateWidth > sourceWidth ) || ( templateHeight > sourceHeight ) ) + { + throw new InvalidImagePropertiesException( "Template's size should be smaller or equal to search zone." ); + } + + int pixelSize = ( image.PixelFormat == PixelFormat.Format8bppIndexed ) ? 1 : 3; + int sourceStride = image.Stride; + + // similarity map. its size is increased by 4 from each side to increase + // performance of non-maximum suppresion + int mapWidth = sourceWidth - templateWidth + 1; + int mapHeight = sourceHeight - templateHeight + 1; + int[,] map = new int[mapHeight + 4, mapWidth + 4]; + + // maximum possible difference with template + int maxDiff = templateWidth * templateHeight * pixelSize * 255; + + // integer similarity threshold + int threshold = (int) ( similarityThreshold * maxDiff ); + + // width of template in bytes + int templateWidthInBytes = templateWidth * pixelSize; + + // do the job + unsafe + { + byte* baseSrc = (byte*) image.ImageData.ToPointer( ); + byte* baseTpl = (byte*) template.ImageData.ToPointer( ); + + int sourceOffset = image.Stride - templateWidth * pixelSize; + int templateOffset = template.Stride - templateWidth * pixelSize; + + // for each row of the source image + for ( int y = 0; y < mapHeight; y++ ) + { + // for each pixel of the source image + for ( int x = 0; x < mapWidth; x++ ) + { + byte* src = baseSrc + sourceStride * ( y + startY ) + pixelSize * ( x + startX ); + byte* tpl = baseTpl; + + // compare template with source image starting from current X,Y + int dif = 0; + + // for each row of the template + for ( int i = 0; i < templateHeight; i++ ) + { + // for each pixel of the template + for ( int j = 0; j < templateWidthInBytes; j++, src++, tpl++ ) + { + int d = *src - *tpl; + if ( d > 0 ) + { + dif += d; + } + else + { + dif -= d; + } + } + src += sourceOffset; + tpl += templateOffset; + } + + // templates similarity + int sim = maxDiff - dif; + + if ( sim >= threshold ) + map[y + 2, x + 2] = sim; + } + } + } + + // collect interesting points - only those points, which are local maximums + List matchingsList = new List( ); + + // for each row + for ( int y = 2, maxY = mapHeight + 2; y < maxY; y++ ) + { + // for each pixel + for ( int x = 2, maxX = mapWidth + 2; x < maxX; x++ ) + { + int currentValue = map[y, x]; + + // for each windows' row + for ( int i = -2; ( currentValue != 0 ) && ( i <= 2 ); i++ ) + { + // for each windows' pixel + for ( int j = -2; j <= 2; j++ ) + { + if ( map[y + i, x + j] > currentValue ) + { + currentValue = 0; + break; + } + } + } + + // check if this point is really interesting + if ( currentValue != 0 ) + { + matchingsList.Add( new TemplateMatch( + new Rectangle( x - 2 + startX, y - 2 + startY, templateWidth, templateHeight ), + (float) currentValue / maxDiff ) ); + } + } + } + + // convert list to array + TemplateMatch[] matchings = new TemplateMatch[matchingsList.Count]; + matchingsList.CopyTo( matchings ); + // sort in descending order + Array.Sort( matchings, new MatchingsSorter( ) ); + + return matchings; + } + + // Sorter of found matchings + private class MatchingsSorter : System.Collections.IComparer + { + public int Compare( Object x, Object y ) + { + float diff = ( (TemplateMatch) y ).Similarity - ( (TemplateMatch) x ).Similarity; + + return ( diff > 0 ) ? 1 : ( diff < 0 ) ? -1 : 0; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/2 Source filters/Add.cs b/Sources/Accord.Imaging/AForge/Filters/2 Source filters/Add.cs new file mode 100644 index 0000000000..f5f6bfe05 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/2 Source filters/Add.cs @@ -0,0 +1,184 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Add fillter - add pixel values of two images. + /// + /// + /// The add filter takes two images (source and overlay images) + /// of the same size and pixel format and produces an image, where each pixel equals + /// to the sum value of corresponding pixels from provided images (if sum is greater + /// than maximum allowed value, 255 or 65535, then it is truncated to that maximum). + /// + /// The filter accepts 8 and 16 bpp grayscale images and 24, 32, 48 and 64 bpp + /// color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// Add filter = new Add( overlayImage ); + /// // apply the filter + /// Bitmap resultImage = filter.Apply( sourceImage ); + /// + /// + /// Source image: + /// + /// Overlay image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + /// + /// + public sealed class Add : BaseInPlaceFilter2 + { + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + public Add( ) + { + InitFormatTranslations( ); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Overlay image. + /// + public Add( Bitmap overlayImage ) + : base( overlayImage ) + { + InitFormatTranslations( ); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Unmanaged overlay image. + /// + public Add( UnmanagedImage unmanagedOverlayImage ) + : base( unmanagedOverlayImage ) + { + InitFormatTranslations( ); + } + + // Initialize format translation dictionary + private void InitFormatTranslations( ) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + formatTranslations[PixelFormat.Format16bppGrayScale] = PixelFormat.Format16bppGrayScale; + formatTranslations[PixelFormat.Format48bppRgb] = PixelFormat.Format48bppRgb; + formatTranslations[PixelFormat.Format64bppArgb] = PixelFormat.Format64bppArgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Overlay image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, UnmanagedImage overlay ) + { + PixelFormat pixelFormat = image.PixelFormat; + // get image dimension + int width = image.Width; + int height = image.Height; + + if ( + ( pixelFormat == PixelFormat.Format8bppIndexed ) || + ( pixelFormat == PixelFormat.Format24bppRgb ) || + ( pixelFormat == PixelFormat.Format32bppRgb ) || + ( pixelFormat == PixelFormat.Format32bppArgb ) ) + { + + // initialize other variables + int pixelSize = ( pixelFormat == PixelFormat.Format8bppIndexed ) ? 1 : + ( pixelFormat == PixelFormat.Format24bppRgb ) ? 3 : 4; + int lineSize = width * pixelSize; + int srcOffset = image.Stride - lineSize; + int ovrOffset = overlay.Stride - lineSize; + // new pixel value + int v; + + // do the job + byte * ptr = (byte*) image.ImageData.ToPointer( ); + byte * ovr = (byte*) overlay.ImageData.ToPointer( ); + + // for each line + for ( int y = 0; y < height; y++ ) + { + // for each pixel + for ( int x = 0; x < lineSize; x++, ptr++, ovr++ ) + { + v = (int) *ptr + (int) *ovr; + *ptr = ( v > 255 ) ? (byte) 255 : (byte) v; + } + ptr += srcOffset; + ovr += ovrOffset; + } + } + else + { + // initialize other variables + int pixelSize = ( pixelFormat == PixelFormat.Format16bppGrayScale ) ? 1 : + ( pixelFormat == PixelFormat.Format48bppRgb ) ? 3 : 4; + int lineSize = width * pixelSize; + int srcStride = image.Stride; + int ovrStride = overlay.Stride; + // new pixel value + int v; + + // do the job + byte* basePtr = (byte*) image.ImageData.ToPointer( ); + byte* baseOvr = (byte*) overlay.ImageData.ToPointer( ); + + // for each line + for ( int y = 0; y < height; y++ ) + { + ushort * ptr = (ushort*) ( basePtr + y * srcStride ); + ushort * ovr = (ushort*) ( baseOvr + y * ovrStride ); + + // for each pixel + for ( int x = 0; x < lineSize; x++, ptr++, ovr++ ) + { + v = (int) *ptr + (int) *ovr; + *ptr = ( v > 65535 ) ? (ushort) 65535 : (ushort) v; + } + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/2 Source filters/Difference.cs b/Sources/Accord.Imaging/AForge/Filters/2 Source filters/Difference.cs new file mode 100644 index 0000000000..62e791676 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/2 Source filters/Difference.cs @@ -0,0 +1,190 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Difference filter - get the difference between overlay and source images. + /// + /// + /// The difference filter takes two images (source and + /// overlay images) + /// of the same size and pixel format and produces an image, where each pixel equals + /// to absolute difference between corresponding pixels from provided images. + /// + /// The filter accepts 8 and 16 bpp grayscale images and 24, 32, 48 and 64 bpp + /// color images for processing. + /// + /// In the case if images with alpha channel are used (32 or 64 bpp), visualization + /// of the result image may seem a bit unexpected - most probably nothing will be seen + /// (in the case if image is displayed according to its alpha channel). This may be + /// caused by the fact that after differencing the entire alpha channel will be zeroed + /// (zero difference between alpha channels), what means that the resulting image will be + /// 100% transparent. + /// + /// Sample usage: + /// + /// // create filter + /// Difference filter = new Difference( overlayImage ); + /// // apply the filter + /// Bitmap resultImage = filter.Apply( sourceImage ); + /// + /// + /// Source image: + /// + /// Overlay image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + /// + /// + public sealed class Difference : BaseInPlaceFilter2 + { + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + public Difference( ) + { + InitFormatTranslations( ); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Overlay image. + /// + public Difference( Bitmap overlayImage ) + : base( overlayImage ) + { + InitFormatTranslations( ); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Unmanaged overlay image. + /// + public Difference( UnmanagedImage unmanagedOverlayImage ) + : base( unmanagedOverlayImage ) + { + InitFormatTranslations( ); + } + + // Initialize format translation dictionary + private void InitFormatTranslations( ) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + formatTranslations[PixelFormat.Format16bppGrayScale] = PixelFormat.Format16bppGrayScale; + formatTranslations[PixelFormat.Format48bppRgb] = PixelFormat.Format48bppRgb; + formatTranslations[PixelFormat.Format64bppArgb] = PixelFormat.Format64bppArgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Overlay image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, UnmanagedImage overlay ) + { + PixelFormat pixelFormat = image.PixelFormat; + // get image dimension + int width = image.Width; + int height = image.Height; + // pixel value + int v; + + if ( + ( pixelFormat == PixelFormat.Format8bppIndexed ) || + ( pixelFormat == PixelFormat.Format24bppRgb ) || + ( pixelFormat == PixelFormat.Format32bppRgb ) || + ( pixelFormat == PixelFormat.Format32bppArgb ) ) + { + // initialize other variables + int pixelSize = ( pixelFormat == PixelFormat.Format8bppIndexed ) ? 1 : + ( pixelFormat == PixelFormat.Format24bppRgb ) ? 3 : 4; + int lineSize = width * pixelSize; + int srcOffset = image.Stride - lineSize; + int ovrOffset = overlay.Stride - lineSize; + + // do the job + byte * ptr = (byte*) image.ImageData.ToPointer( ); + byte * ovr = (byte*) overlay.ImageData.ToPointer( ); + + // for each line + for ( int y = 0; y < height; y++ ) + { + // for each pixel + for ( int x = 0; x < lineSize; x++, ptr++, ovr++ ) + { + // abs(sub) + v = (int) *ptr - (int) *ovr; + *ptr = ( v < 0 ) ? (byte) -v : (byte) v; + } + ptr += srcOffset; + ovr += ovrOffset; + } + } + else + { + // initialize other variables + int pixelSize = ( pixelFormat == PixelFormat.Format16bppGrayScale ) ? 1 : + ( pixelFormat == PixelFormat.Format48bppRgb ) ? 3 : 4; + int lineSize = width * pixelSize; + int srcStride = image.Stride; + int ovrStride = overlay.Stride; + + // do the job + byte* basePtr = (byte*) image.ImageData.ToPointer( ); + byte* baseOvr = (byte*) overlay.ImageData.ToPointer( ); + + // for each line + for ( int y = 0; y < height; y++ ) + { + ushort * ptr = (ushort*) ( basePtr + y * srcStride ); + ushort * ovr = (ushort*) ( baseOvr + y * ovrStride ); + + // for each pixel + for ( int x = 0; x < lineSize; x++, ptr++, ovr++ ) + { + // abs(sub) + v = (int) *ptr - (int) *ovr; + *ptr = ( v < 0 ) ? (ushort) -v : (ushort) v; + } + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/2 Source filters/Intersect.cs b/Sources/Accord.Imaging/AForge/Filters/2 Source filters/Intersect.cs new file mode 100644 index 0000000000..f8b3ae189 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/2 Source filters/Intersect.cs @@ -0,0 +1,178 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Intersect filter - get MIN of pixels in two images. + /// + /// + /// The intersect filter takes two images (source and overlay images) + /// of the same size and pixel format and produces an image, where each pixel equals + /// to the minimum value of corresponding pixels from provided images. + /// + /// The filter accepts 8 and 16 bpp grayscale images and 24, 32, 48 and 64 bpp + /// color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// Intersect filter = new Intersect( overlayImage ); + /// // apply the filter + /// Bitmap resultImage = filter.Apply( sourceImage ); + /// + /// + /// Source image: + /// + /// Overlay image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + /// + /// + public sealed class Intersect : BaseInPlaceFilter2 + { + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + public Intersect( ) + { + InitFormatTranslations( ); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Overlay image. + /// + public Intersect( Bitmap overlayImage ) + : base( overlayImage ) + { + InitFormatTranslations( ); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Unmanaged overlay image. + /// + public Intersect( UnmanagedImage unmanagedOverlayImage ) + : base( unmanagedOverlayImage ) + { + InitFormatTranslations( ); + } + + // Initialize format translation dictionary + private void InitFormatTranslations( ) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + formatTranslations[PixelFormat.Format16bppGrayScale] = PixelFormat.Format16bppGrayScale; + formatTranslations[PixelFormat.Format48bppRgb] = PixelFormat.Format48bppRgb; + formatTranslations[PixelFormat.Format64bppArgb] = PixelFormat.Format64bppArgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Overlay image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, UnmanagedImage overlay ) + { + PixelFormat pixelFormat = image.PixelFormat; + // get image dimension + int width = image.Width; + int height = image.Height; + + if ( + ( pixelFormat == PixelFormat.Format8bppIndexed ) || + ( pixelFormat == PixelFormat.Format24bppRgb ) || + ( pixelFormat == PixelFormat.Format32bppRgb ) || + ( pixelFormat == PixelFormat.Format32bppArgb ) ) + { + // initialize other variables + int pixelSize = ( pixelFormat == PixelFormat.Format8bppIndexed ) ? 1 : + ( pixelFormat == PixelFormat.Format24bppRgb ) ? 3 : 4; + int lineSize = width * pixelSize; + int srcOffset = image.Stride - lineSize; + int ovrOffset = overlay.Stride - lineSize; + + // do the job + byte * ptr = (byte*) image.ImageData.ToPointer( ); + byte * ovr = (byte*) overlay.ImageData.ToPointer( ); + + // for each line + for ( int y = 0; y < height; y++ ) + { + // for each pixel + for ( int x = 0; x < lineSize; x++, ptr++, ovr++ ) + { + if ( *ovr < *ptr ) + *ptr = *ovr; + } + ptr += srcOffset; + ovr += ovrOffset; + } + } + else + { + // initialize other variables + int pixelSize = ( pixelFormat == PixelFormat.Format16bppGrayScale ) ? 1 : + ( pixelFormat == PixelFormat.Format48bppRgb ) ? 3 : 4; + int lineSize = width * pixelSize; + int srcStride = image.Stride; + int ovrStride = overlay.Stride; + + // do the job + byte* basePtr = (byte*) image.ImageData.ToPointer( ); + byte* baseOvr = (byte*) overlay.ImageData.ToPointer( ); + + // for each line + for ( int y = 0; y < height; y++ ) + { + ushort * ptr = (ushort*) ( basePtr + y * srcStride ); + ushort * ovr = (ushort*) ( baseOvr + y * ovrStride ); + + // for each pixel + for ( int x = 0; x < lineSize; x++, ptr++, ovr++ ) + { + if ( *ovr < *ptr ) + *ptr = *ovr; + } + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/2 Source filters/Merge.cs b/Sources/Accord.Imaging/AForge/Filters/2 Source filters/Merge.cs new file mode 100644 index 0000000000..ba6a7f88e --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/2 Source filters/Merge.cs @@ -0,0 +1,178 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Merge filter - get MAX of pixels in two images. + /// + /// + /// The merge filter takes two images (source and overlay images) + /// of the same size and pixel format and produces an image, where each pixel equals + /// to the maximum value of corresponding pixels from provided images. + /// + /// The filter accepts 8 and 16 bpp grayscale images and 24, 32, 48 and 64 bpp + /// color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// Merge filter = new Merge( overlayImage ); + /// // apply the filter + /// Bitmap resultImage = filter.Apply( sourceImage ); + /// + /// + /// Source image: + /// + /// Overlay image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + /// + /// + public sealed class Merge : BaseInPlaceFilter2 + { + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class + /// + public Merge( ) + { + InitFormatTranslations( ); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Overlay image. + /// + public Merge( Bitmap overlayImage ) + : base( overlayImage ) + { + InitFormatTranslations( ); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Unmanaged overlay image. + /// + public Merge( UnmanagedImage unmanagedOverlayImage ) + : base( unmanagedOverlayImage ) + { + InitFormatTranslations( ); + } + + // Initialize format translation dictionary + private void InitFormatTranslations( ) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + formatTranslations[PixelFormat.Format16bppGrayScale] = PixelFormat.Format16bppGrayScale; + formatTranslations[PixelFormat.Format48bppRgb] = PixelFormat.Format48bppRgb; + formatTranslations[PixelFormat.Format64bppArgb] = PixelFormat.Format64bppArgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Overlay image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, UnmanagedImage overlay ) + { + PixelFormat pixelFormat = image.PixelFormat; + // get image dimension + int width = image.Width; + int height = image.Height; + + if ( + ( pixelFormat == PixelFormat.Format8bppIndexed ) || + ( pixelFormat == PixelFormat.Format24bppRgb ) || + ( pixelFormat == PixelFormat.Format32bppRgb ) || + ( pixelFormat == PixelFormat.Format32bppArgb ) ) + { + // initialize other variables + int pixelSize = ( pixelFormat == PixelFormat.Format8bppIndexed ) ? 1 : + ( pixelFormat == PixelFormat.Format24bppRgb ) ? 3 : 4; + int lineSize = width * pixelSize; + int srcOffset = image.Stride - lineSize; + int ovrOffset = overlay.Stride - lineSize; + + // do the job + byte * ptr = (byte*) image.ImageData.ToPointer( ); + byte * ovr = (byte*) overlay.ImageData.ToPointer( ); + + // for each line + for ( int y = 0; y < height; y++ ) + { + // for each pixel + for ( int x = 0; x < lineSize; x++, ptr++, ovr++ ) + { + if ( *ovr > *ptr ) + *ptr = *ovr; + } + ptr += srcOffset; + ovr += ovrOffset; + } + } + else + { + // initialize other variables + int pixelSize = ( pixelFormat == PixelFormat.Format16bppGrayScale ) ? 1 : + ( pixelFormat == PixelFormat.Format48bppRgb ) ? 3 : 4; + int lineSize = width * pixelSize; + int srcStride = image.Stride; + int ovrStride = overlay.Stride; + + // do the job + byte* basePtr = (byte*) image.ImageData.ToPointer( ); + byte* baseOvr = (byte*) overlay.ImageData.ToPointer( ); + + // for each line + for ( int y = 0; y < height; y++ ) + { + ushort * ptr = (ushort*) ( basePtr + y * srcStride ); + ushort * ovr = (ushort*) ( baseOvr + y * ovrStride ); + + // for each pixel + for ( int x = 0; x < lineSize; x++, ptr++, ovr++ ) + { + if ( *ovr > *ptr ) + *ptr = *ovr; + } + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/2 Source filters/Morph.cs b/Sources/Accord.Imaging/AForge/Filters/2 Source filters/Morph.cs new file mode 100644 index 0000000000..514c95fee --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/2 Source filters/Morph.cs @@ -0,0 +1,151 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Morph filter. + /// + /// + /// The filter combines two images by taking + /// specified percent of pixels' intensities from source + /// image and the rest from overlay image. For example, if the + /// source percent value is set to 0.8, then each pixel + /// of the result image equals to 0.8 * source + 0.2 * overlay, where source + /// and overlay are corresponding pixels' values in source and overlay images. + /// + /// The filter accepts 8 bpp grayscale and 24 bpp color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// Morph filter = new Morph( overlayImage ); + /// filter.SourcePercent = 0.75; + /// // apply the filter + /// Bitmap resultImage = filter.Apply( sourceImage ); + /// + /// + /// Source image: + /// + /// Overlay image: + /// + /// Result image: + /// + /// + /// + public class Morph : BaseInPlaceFilter2 + { + private double sourcePercent = 0.50; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Percent of source image to keep, [0, 1]. + /// + /// + /// The property specifies the percentage of source pixels' to take. The + /// rest is taken from an overlay image. + /// + public double SourcePercent + { + get { return sourcePercent; } + set { sourcePercent = Math.Max( 0.0, Math.Min( 1.0, value ) ); } + } + + + /// + /// Initializes a new instance of the class. + /// + public Morph( ) + { + InitFormatTranslations( ); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Overlay image. + /// + public Morph( Bitmap overlayImage ) + : base( overlayImage ) + { + InitFormatTranslations( ); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Unmanaged overlay image. + /// + public Morph( UnmanagedImage unmanagedOverlayImage ) + : base( unmanagedOverlayImage ) + { + InitFormatTranslations( ); + } + + // Initialize format translation dictionary + private void InitFormatTranslations( ) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Overlay image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, UnmanagedImage overlay ) + { + // get image dimension + int width = image.Width; + int height = image.Height; + + // initialize other variables + int pixelSize = ( image.PixelFormat == PixelFormat.Format8bppIndexed ) ? 1 : 3; + int lineSize = width * pixelSize; + int offset = image.Stride - lineSize; + int ovrOffset = overlay.Stride - lineSize; + // percentage of overlay image + double q = 1.0 - sourcePercent; + + // do the job + byte * ptr = (byte*) image.ImageData.ToPointer( ); + byte * ovr = (byte*) overlay.ImageData.ToPointer( ); + + // for each line + for ( int y = 0; y < height; y++ ) + { + // for each pixel + for ( int x = 0; x < lineSize; x++, ptr++, ovr++ ) + { + *ptr = (byte) ( ( sourcePercent * ( *ptr ) ) + ( q * ( *ovr ) ) ); + } + ptr += offset; + ovr += ovrOffset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/2 Source filters/MoveTowards.cs b/Sources/Accord.Imaging/AForge/Filters/2 Source filters/MoveTowards.cs new file mode 100644 index 0000000000..e0b2bbe42 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/2 Source filters/MoveTowards.cs @@ -0,0 +1,247 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Move towards filter. + /// + /// + /// The result of this filter is an image, which is based on source image, + /// but updated in the way to decrease diffirence with overlay image - source image is + /// moved towards overlay image. The update equation is defined in the next way: + /// res = src + Min( Abs( ovr - src ), step ) * Sign( ovr - src ). + /// + /// The bigger is step size value the more resulting + /// image will look like overlay image. For example, in the case if step size is equal + /// to 255 (or 65535 for images with 16 bits per channel), the resulting image will be + /// equal to overlay image regardless of source image's pixel values. In the case if step + /// size is set to 1, the resulting image will very little differ from the source image. + /// But, in the case if the filter is applied repeatedly to the resulting image again and + /// again, it will become equal to overlay image in maximum 255 (65535 for images with 16 + /// bits per channel) iterations. + /// + /// The filter accepts 8 and 16 bpp grayscale images and 24, 32, 48 and 64 bpp + /// color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// MoveTowards filter = new MoveTowards( overlayImage, 20 ); + /// // apply the filter + /// Bitmap resultImage = filter.Apply( sourceImage ); + /// + /// + /// Source image: + /// + /// Overlay image: + /// + /// Result image: + /// + /// + /// + public class MoveTowards : BaseInPlaceFilter2 + { + private int stepSize = 1; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Step size, [0, 65535]. + /// + /// + /// + /// The property defines the maximum amount of changes per pixel in the source image. + /// + /// Default value is set to 1. + /// + /// + public int StepSize + { + get { return stepSize; } + set { stepSize = Math.Max( 1, Math.Min( 65535, value ) ); } + } + + /// + /// Initializes a new instance of the class + /// + public MoveTowards( ) + { + InitFormatTranslations( ); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Overlay image. + /// + public MoveTowards( Bitmap overlayImage ) + : base( overlayImage ) + { + InitFormatTranslations( ); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Overlay image. + /// Step size. + /// + public MoveTowards( Bitmap overlayImage, int stepSize ) + : base( overlayImage ) + { + InitFormatTranslations( ); + StepSize = stepSize; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Unmanaged overlay image. + /// + public MoveTowards( UnmanagedImage unmanagedOverlayImage ) + : base( unmanagedOverlayImage ) + { + InitFormatTranslations( ); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Unmanaged overlay image. + /// Step size. + /// + public MoveTowards( UnmanagedImage unmanagedOverlayImage, int stepSize ) + : base( unmanagedOverlayImage ) + { + InitFormatTranslations( ); + StepSize = stepSize; + } + + // Initialize format translation dictionary + private void InitFormatTranslations( ) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + formatTranslations[PixelFormat.Format16bppGrayScale] = PixelFormat.Format16bppGrayScale; + formatTranslations[PixelFormat.Format48bppRgb] = PixelFormat.Format48bppRgb; + formatTranslations[PixelFormat.Format64bppArgb] = PixelFormat.Format64bppArgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Overlay image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, UnmanagedImage overlay ) + { + PixelFormat pixelFormat = image.PixelFormat; + // get image dimension + int width = image.Width; + int height = image.Height; + // pixel value + int v; + + if ( + ( pixelFormat == PixelFormat.Format8bppIndexed ) || + ( pixelFormat == PixelFormat.Format24bppRgb ) || + ( pixelFormat == PixelFormat.Format32bppRgb ) || + ( pixelFormat == PixelFormat.Format32bppArgb ) ) + { + // initialize other variables + int pixelSize = ( pixelFormat == PixelFormat.Format8bppIndexed ) ? 1 : + ( pixelFormat == PixelFormat.Format24bppRgb ) ? 3 : 4; + int lineSize = width * pixelSize; + int srcOffset = image.Stride - lineSize; + int ovrOffset = overlay.Stride - lineSize; + + // do the job + byte * ptr = (byte*) image.ImageData.ToPointer( ); + byte * ovr = (byte*) overlay.ImageData.ToPointer( ); + + // for each line + for ( int y = 0; y < height; y++ ) + { + // for each pixel + for ( int x = 0; x < lineSize; x++, ptr++, ovr++ ) + { + v = (int) *ovr - *ptr; + if ( v > 0 ) + { + *ptr += (byte) ( ( stepSize < v ) ? stepSize : v ); + } + else if ( v < 0 ) + { + v = -v; + *ptr -= (byte) ( ( stepSize < v ) ? stepSize : v ); + } + } + ptr += srcOffset; + ovr += ovrOffset; + } + } + else + { + // initialize other variables + int pixelSize = ( pixelFormat == PixelFormat.Format16bppGrayScale ) ? 1 : + ( pixelFormat == PixelFormat.Format48bppRgb ) ? 3 : 4; + int lineSize = width * pixelSize; + int srcStride = image.Stride; + int ovrStride = overlay.Stride; + + // do the job + byte* basePtr = (byte*) image.ImageData.ToPointer( ); + byte* baseOvr = (byte*) overlay.ImageData.ToPointer( ); + + // for each line + for ( int y = 0; y < height; y++ ) + { + ushort * ptr = (ushort*) ( basePtr + y * srcStride ); + ushort * ovr = (ushort*) ( baseOvr + y * ovrStride ); + + // for each pixel + for ( int x = 0; x < lineSize; x++, ptr++, ovr++ ) + { + v = (int) *ovr - *ptr; + if ( v > 0 ) + { + *ptr += (ushort) ( ( stepSize < v ) ? stepSize : v ); + } + else if ( v < 0 ) + { + v = -v; + *ptr -= (ushort) ( ( stepSize < v ) ? stepSize : v ); + } + } + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/2 Source filters/StereoAnaglyph.cs b/Sources/Accord.Imaging/AForge/Filters/2 Source filters/StereoAnaglyph.cs new file mode 100644 index 0000000000..df2d9e654 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/2 Source filters/StereoAnaglyph.cs @@ -0,0 +1,267 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Stereo anaglyph filter. + /// + /// + /// The image processing filter produces stereo anaglyph images which are + /// aimed to be viewed through anaglyph glasses with red filter over the left eye and + /// cyan over the right. + /// + /// + /// + /// The stereo image is produced by combining two images of the same scene taken + /// from a bit different points. The right image must be provided to the filter using + /// property, but the left image must be provided to + /// method, which creates the anaglyph image. + /// + /// The filter accepts 24 bpp color images for processing. + /// + /// See enumeration for the list of supported anaglyph algorithms. + /// + /// Sample usage: + /// + /// // create filter + /// StereoAnaglyph filter = new StereoAnaglyph( ); + /// // set right image as overlay + /// filter.Overlay = rightImage + /// // apply the filter (providing left image) + /// Bitmap resultImage = filter.Apply( leftImage ); + /// + /// + /// Source image (left): + /// + /// Overlay image (right): + /// + /// Result image: + /// + /// + /// + /// + public class StereoAnaglyph : BaseInPlaceFilter2 + { + /// + /// Enumeration of algorithms for creating anaglyph images. + /// + /// + /// See anaglyph methods comparison for + /// descipton of different algorithms. + /// + /// + public enum Algorithm + { + /// + /// Creates anaglyph image using the below calculations: + /// + /// Ra=0.299*Rl+0.587*Gl+0.114*Bl; + /// Ga=0; + /// Ba=0.299*Rr+0.587*Gr+0.114*Br. + /// + /// + TrueAnaglyph, + + /// + /// Creates anaglyph image using the below calculations: + /// + /// Ra=0.299*Rl+0.587*Gl+0.114*Bl; + /// Ga=0.299*Rr+0.587*Gr+0.114*Br; + /// Ba=0.299*Rr+0.587*Gr+0.114*Br. + /// + /// + GrayAnaglyph, + + /// + /// Creates anaglyph image using the below calculations: + /// + /// Ra=Rl; + /// Ga=Gr; + /// Ba=Br. + /// + /// + ColorAnaglyph, + + /// + /// Creates anaglyph image using the below calculations: + /// + /// Ra=0.299*Rl+0.587*Gl+0.114*Bl; + /// Ga=Gr; + /// Ba=Br. + /// + /// + HalfColorAnaglyph, + + /// + /// Creates anaglyph image using the below calculations: + /// + /// Ra=0.7*Gl+0.3*Bl; + /// Ga=Gr; + /// Ba=Br. + /// + /// + OptimizedAnaglyph + } + + private Algorithm anaglyphAlgorithm = Algorithm.GrayAnaglyph; + + /// + /// Algorithm to use for creating anaglyph images. + /// + /// + /// Default value is set to . + /// + public Algorithm AnaglyphAlgorithm + { + get { return anaglyphAlgorithm; } + set { anaglyphAlgorithm = value; } + } + + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + public StereoAnaglyph( ) + { + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Algorithm to use for creating anaglyph images. + /// + public StereoAnaglyph( Algorithm anaglyphAlgorithm ) + : this( ) + { + this.anaglyphAlgorithm = anaglyphAlgorithm; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data (left image). + /// Overlay image data (right image). + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, UnmanagedImage overlay ) + { + // get image dimension + int width = image.Width; + int height = image.Height; + + // initialize other variables + int offset = image.Stride - width * 3; + int ovrOffset = overlay.Stride - width * 3; + + // do the job + byte * ptr = (byte*) image.ImageData.ToPointer( ); + byte * ovr = (byte*) overlay.ImageData.ToPointer( ); + + switch ( anaglyphAlgorithm ) + { + case Algorithm.TrueAnaglyph: + // for each line + for ( int y = 0; y < height; y++ ) + { + // for each pixel + for ( int x = 0; x < width; x++, ptr += 3, ovr += 3 ) + { + ptr[RGB.R] = (byte) ( ptr[RGB.R] * 0.299 + ptr[RGB.G] * 0.587 + ptr[RGB.B] * 0.114 ); + ptr[RGB.G] = 0; + ptr[RGB.B] = (byte) ( ovr[RGB.R] * 0.299 + ovr[RGB.G] * 0.587 + ovr[RGB.B] * 0.114 ); + } + ptr += offset; + ovr += ovrOffset; + } + break; + + case Algorithm.GrayAnaglyph: + // for each line + for ( int y = 0; y < height; y++ ) + { + // for each pixel + for ( int x = 0; x < width; x++, ptr += 3, ovr += 3 ) + { + ptr[RGB.R] = (byte) ( ptr[RGB.R] * 0.299 + ptr[RGB.G] * 0.587 + ptr[RGB.B] * 0.114 ); + ptr[RGB.G] = (byte) ( ovr[RGB.R] * 0.299 + ovr[RGB.G] * 0.587 + ovr[RGB.B] * 0.114 ); + ptr[RGB.B] = ptr[RGB.G]; + } + ptr += offset; + ovr += ovrOffset; + } + break; + + case Algorithm.ColorAnaglyph: + // for each line + for ( int y = 0; y < height; y++ ) + { + // for each pixel + for ( int x = 0; x < width; x++, ptr += 3, ovr += 3 ) + { + // keep Red as it is and take only Green and Blue from the second image + ptr[RGB.G] = ovr[RGB.G]; + ptr[RGB.B] = ovr[RGB.B]; + } + ptr += offset; + ovr += ovrOffset; + } + break; + + case Algorithm.HalfColorAnaglyph: + // for each line + for ( int y = 0; y < height; y++ ) + { + // for each pixel + for ( int x = 0; x < width; x++, ptr += 3, ovr += 3 ) + { + ptr[RGB.R] = (byte) ( ptr[RGB.R] * 0.299 + ptr[RGB.G] * 0.587 + ptr[RGB.B] * 0.114 ); + ptr[RGB.G] = ovr[RGB.G]; + ptr[RGB.B] = ovr[RGB.B]; + } + ptr += offset; + ovr += ovrOffset; + } + break; + + case Algorithm.OptimizedAnaglyph: + // for each line + for ( int y = 0; y < height; y++ ) + { + // for each pixel + for ( int x = 0; x < width; x++, ptr += 3, ovr += 3 ) + { + ptr[RGB.R] = (byte) ( ptr[RGB.G] * 0.7 + ptr[RGB.B] * 0.3 ); + ptr[RGB.G] = ovr[RGB.G]; + ptr[RGB.B] = ovr[RGB.B]; + } + ptr += offset; + ovr += ovrOffset; + } + break; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/2 Source filters/Subtract.cs b/Sources/Accord.Imaging/AForge/Filters/2 Source filters/Subtract.cs new file mode 100644 index 0000000000..d54c1f6c2 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/2 Source filters/Subtract.cs @@ -0,0 +1,184 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Subtract filter - subtract pixel values of two images. + /// + /// + /// The subtract filter takes two images (source and overlay images) + /// of the same size and pixel format and produces an image, where each pixel equals + /// to the difference value of corresponding pixels from provided images (if difference is less + /// than minimum allowed value, 0, then it is truncated to that minimum value). + /// + /// The filter accepts 8 and 16 bpp grayscale images and 24, 32, 48 and 64 bpp + /// color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// Subtract filter = new Subtract( overlayImage ); + /// // apply the filter + /// Bitmap resultImage = filter.Apply( sourceImage ); + /// + /// + /// Source image: + /// + /// Overlay image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + /// + /// + public sealed class Subtract : BaseInPlaceFilter2 + { + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + public Subtract( ) + { + InitFormatTranslations( ); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Overlay image + /// + public Subtract( Bitmap overlayImage ) + : base( overlayImage ) + { + InitFormatTranslations( ); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Unmanaged overlay image. + /// + public Subtract( UnmanagedImage unmanagedOverlayImage ) + : base( unmanagedOverlayImage ) + { + InitFormatTranslations( ); + } + + // Initialize format translation dictionary + private void InitFormatTranslations( ) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + formatTranslations[PixelFormat.Format16bppGrayScale] = PixelFormat.Format16bppGrayScale; + formatTranslations[PixelFormat.Format48bppRgb] = PixelFormat.Format48bppRgb; + formatTranslations[PixelFormat.Format64bppArgb] = PixelFormat.Format64bppArgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Overlay image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, UnmanagedImage overlay ) + { + PixelFormat pixelFormat = image.PixelFormat; + // get image dimension + int width = image.Width; + int height = image.Height; + + if ( + ( pixelFormat == PixelFormat.Format8bppIndexed ) || + ( pixelFormat == PixelFormat.Format24bppRgb ) || + ( pixelFormat == PixelFormat.Format32bppRgb ) || + ( pixelFormat == PixelFormat.Format32bppArgb ) ) + { + + // initialize other variables + int pixelSize = ( pixelFormat == PixelFormat.Format8bppIndexed ) ? 1 : + ( pixelFormat == PixelFormat.Format24bppRgb ) ? 3 : 4; + int lineSize = width * pixelSize; + int srcOffset = image.Stride - lineSize; + int ovrOffset = overlay.Stride - lineSize; + // new pixel value + int v; + + // do the job + byte * ptr = (byte*) image.ImageData.ToPointer( ); + byte * ovr = (byte*) overlay.ImageData.ToPointer( ); + + // for each line + for ( int y = 0; y < height; y++ ) + { + // for each pixel + for ( int x = 0; x < lineSize; x++, ptr++, ovr++ ) + { + v = (int) *ptr - (int) *ovr; + *ptr = ( v < 0 ) ? (byte) 0 : (byte) v; + } + ptr += srcOffset; + ovr += ovrOffset; + } + } + else + { + // initialize other variables + int pixelSize = ( pixelFormat == PixelFormat.Format16bppGrayScale ) ? 1 : + ( pixelFormat == PixelFormat.Format48bppRgb ) ? 3 : 4; + int lineSize = width * pixelSize; + int srcStride = image.Stride; + int ovrStride = overlay.Stride; + // new pixel value + int v; + + // do the job + byte* basePtr = (byte*) image.ImageData.ToPointer( ); + byte* baseOvr = (byte*) overlay.ImageData.ToPointer( ); + + // for each line + for ( int y = 0; y < height; y++ ) + { + ushort * ptr = (ushort*) ( basePtr + y * srcStride ); + ushort * ovr = (ushort*) ( baseOvr + y * ovrStride ); + + // for each pixel + for ( int x = 0; x < lineSize; x++, ptr++, ovr++ ) + { + v = (int) *ptr - (int) *ovr; + *ptr = ( v < 0 ) ? (ushort) 0 : (ushort) v; + } + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/2 Source filters/ThresholdedDifference.cs b/Sources/Accord.Imaging/AForge/Filters/2 Source filters/ThresholdedDifference.cs new file mode 100644 index 0000000000..9d1aef984 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/2 Source filters/ThresholdedDifference.cs @@ -0,0 +1,218 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2010 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Calculate difference between two images and threshold it. + /// + /// + /// The filter produces similar result as applying filter and + /// then filter - thresholded difference between two images. Result of this + /// image processing routine may be useful in motion detection applications or finding areas of significant + /// difference. + /// + /// The filter accepts 8 and 24/32color images for processing. + /// In the case of color images, the image processing routine differences sum over 3 RGB channels (Manhattan distance), i.e. + /// |diffR| + |diffG| + |diffB|. + /// + /// + /// Sample usage: + /// + /// // create filter + /// ThresholdedDifference filter = new ThresholdedDifference( 60 ); + /// // apply the filter + /// filter.OverlayImage = backgroundImage; + /// Bitmap resultImage = filter.Apply( sourceImage ); + /// + /// + /// Source image: + /// + /// Background image: + /// + /// Result image: + /// + /// + /// + /// + /// + public class ThresholdedDifference : BaseFilter2 + { + // format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + private int threshold = 15; + + /// + /// Difference threshold. + /// + /// + /// The property specifies difference threshold. If difference between pixels of processing image + /// and overlay image is greater than this value, then corresponding pixel of result image is set to white; otherwise + /// black. + /// + /// + /// Default value is set to 15. + /// + public int Threshold + { + get { return threshold; } + set { threshold = value; } + } + + private int whitePixelsCount = 0; + + /// + /// Number of pixels which were set to white in destination image during last image processing call. + /// + /// + /// The property may be useful to determine amount of difference between two images which, + /// for example, may be treated as amount of motion in motion detection applications, etc. + /// + public int WhitePixelsCount + { + get { return whitePixelsCount; } + } + + /// + /// Format translations dictionary. + /// + /// + /// See for more information. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public ThresholdedDifference( ) + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format32bppPArgb] = PixelFormat.Format8bppIndexed; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Difference threshold (see ). + /// + public ThresholdedDifference( int threshold ) : this( ) + { + this.threshold = threshold; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Overlay image data. + /// Destination image data + /// + protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage overlay, UnmanagedImage destinationData ) + { + whitePixelsCount = 0; + + // get source image size + int width = sourceData.Width; + int height = sourceData.Height; + int pixelSize = Bitmap.GetPixelFormatSize( sourceData.PixelFormat ) / 8; + + byte* src = (byte*) sourceData.ImageData.ToPointer( ); + byte* ovr = (byte*) overlay.ImageData.ToPointer( ); + byte* dst = (byte*) destinationData.ImageData.ToPointer( ); + + if ( pixelSize == 1 ) + { + // grayscale image + int srcOffset = sourceData.Stride - width; + int ovrOffset = overlay.Stride - width; + int dstOffset = destinationData.Stride - width; + + // for each line + for ( int y = 0; y < height; y++ ) + { + // for each pixel + for ( int x = 0; x < width; x++, src++, ovr++, dst++ ) + { + int diff = *src - *ovr; + + if ( diff < 0 ) + diff = -diff; + + if ( diff > threshold ) + { + *dst = (byte) 255; + whitePixelsCount++; + } + else + { + *dst = 0; + } + } + src += srcOffset; + ovr += ovrOffset; + dst += dstOffset; + } + } + else + { + // color image + int srcOffset = sourceData.Stride - pixelSize * width; + int ovrOffset = overlay.Stride - pixelSize * width; + int dstOffset = destinationData.Stride - width; + + // for each line + for ( int y = 0; y < height; y++ ) + { + // for each pixel + for ( int x = 0; x < width; x++, src += pixelSize, ovr += pixelSize, dst++ ) + { + int diffR = src[RGB.R] - ovr[RGB.R]; + int diffG = src[RGB.G] - ovr[RGB.G]; + int diffB = src[RGB.B] - ovr[RGB.B]; + + if ( diffR < 0 ) + diffR = -diffR; + if ( diffG < 0 ) + diffG = -diffG; + if ( diffB < 0 ) + diffB = -diffB; + + if ( diffR + diffG + diffB > threshold ) + { + *dst = (byte) 255; + whitePixelsCount++; + } + else + { + *dst = 0; + } + } + src += srcOffset; + ovr += ovrOffset; + dst += dstOffset; + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/2 Source filters/ThresholdedEuclideanDifference.cs b/Sources/Accord.Imaging/AForge/Filters/2 Source filters/ThresholdedEuclideanDifference.cs new file mode 100644 index 0000000000..32ddd1826 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/2 Source filters/ThresholdedEuclideanDifference.cs @@ -0,0 +1,210 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2010 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Calculate Euclidean difference between two images and threshold it. + /// + /// + /// The filter produces similar to , however it uses + /// Euclidean distance for finding difference between pixel values instead of Manhattan distance. Result of this + /// image processing routine may be useful in motion detection applications or finding areas of significant + /// difference. + /// + /// The filter accepts 8 and 24/32color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// ThresholdedEuclideanDifference filter = new ThresholdedEuclideanDifference( 60 ); + /// // apply the filter + /// filter.OverlayImage = backgroundImage; + /// Bitmap resultImage = filter.Apply( sourceImage ); + /// + /// + /// Source image: + /// + /// Background image: + /// + /// Result image: + /// + /// + /// + /// + /// + public class ThresholdedEuclideanDifference : BaseFilter2 + { + // format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + private int threshold = 15; + + /// + /// Difference threshold. + /// + /// + /// The property specifies difference threshold. If difference between pixels of processing image + /// and overlay image is greater than this value, then corresponding pixel of result image is set to white; otherwise + /// black. + /// + /// + /// Default value is set to 15. + /// + public int Threshold + { + get { return threshold; } + set { threshold = value; } + } + + private int whitePixelsCount = 0; + + /// + /// Number of pixels which were set to white in destination image during last image processing call. + /// + /// + /// The property may be useful to determine amount of difference between two images which, + /// for example, may be treated as amount of motion in motion detection applications, etc. + /// + public int WhitePixelsCount + { + get { return whitePixelsCount; } + } + + /// + /// Format translations dictionary. + /// + /// + /// See for more information. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public ThresholdedEuclideanDifference( ) + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format32bppPArgb] = PixelFormat.Format8bppIndexed; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Difference threshold (see ). + /// + public ThresholdedEuclideanDifference( int threshold ) : this( ) + { + this.threshold = threshold; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Overlay image data. + /// Destination image data + /// + protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage overlay, UnmanagedImage destinationData ) + { + whitePixelsCount = 0; + + // get source image size + int width = sourceData.Width; + int height = sourceData.Height; + int pixelSize = Bitmap.GetPixelFormatSize( sourceData.PixelFormat ) / 8; + + byte* src = (byte*) sourceData.ImageData.ToPointer( ); + byte* ovr = (byte*) overlay.ImageData.ToPointer( ); + byte* dst = (byte*) destinationData.ImageData.ToPointer( ); + + if ( pixelSize == 1 ) + { + // grayscale image + int srcOffset = sourceData.Stride - width; + int ovrOffset = overlay.Stride - width; + int dstOffset = destinationData.Stride - width; + + // for each line + for ( int y = 0; y < height; y++ ) + { + // for each pixel + for ( int x = 0; x < width; x++, src++, ovr++, dst++ ) + { + int diff = *src - *ovr; + + if ( diff < 0 ) + diff = -diff; + + if ( diff > threshold ) + { + *dst = (byte) 255; + whitePixelsCount++; + } + else + { + *dst = 0; + } + } + src += srcOffset; + ovr += ovrOffset; + dst += dstOffset; + } + } + else + { + // color image + int srcOffset = sourceData.Stride - pixelSize * width; + int ovrOffset = overlay.Stride - pixelSize * width; + int dstOffset = destinationData.Stride - width; + + int squaredThreshold = threshold * threshold; + + // for each line + for ( int y = 0; y < height; y++ ) + { + // for each pixel + for ( int x = 0; x < width; x++, src += pixelSize, ovr += pixelSize, dst++ ) + { + int diffR = src[RGB.R] - ovr[RGB.R]; + int diffG = src[RGB.G] - ovr[RGB.G]; + int diffB = src[RGB.B] - ovr[RGB.B]; + + if ( diffR * diffR + diffG * diffG + diffB * diffB > squaredThreshold ) + { + *dst = (byte) 255; + whitePixelsCount++; + } + else + { + *dst = 0; + } + } + src += srcOffset; + ovr += ovrOffset; + dst += dstOffset; + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Adaptive Binarization/BradleyLocalThresholding.cs b/Sources/Accord.Imaging/AForge/Filters/Adaptive Binarization/BradleyLocalThresholding.cs new file mode 100644 index 0000000000..014c2cc3c --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Adaptive Binarization/BradleyLocalThresholding.cs @@ -0,0 +1,159 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2010 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Adaptive thresholding using the internal image. + /// + /// + /// The image processing routine implements local thresholding technique described + /// by Derek Bradley and Gerhard Roth in the "Adaptive Thresholding Using the Integral Image" paper. + /// + /// + /// The brief idea of the algorithm is that every image's pixel is set to black if its brightness + /// is t percent lower (see ) than the average brightness + /// of surrounding pixels in the window of the specified size (see ), othwerwise it is set + /// to white. + /// + /// Sample usage: + /// + /// // create the filter + /// BradleyLocalThresholding filter = new BradleyLocalThresholding( ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class BradleyLocalThresholding : BaseInPlaceFilter + { + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + private int windowSize = 41; + private float pixelBrightnessDifferenceLimit = 0.15f; + + /// + /// Window size to calculate average value of pixels for. + /// + /// + /// The property specifies window size around processing pixel, which determines number of + /// neighbor pixels to use for calculating their average brightness. + /// + /// Default value is set to 41. + /// + /// The value should be odd. + /// + /// + public int WindowSize + { + get { return windowSize; } + set { windowSize = Math.Max( 3, value | 1 ); } + } + + /// + /// Brightness difference limit between processing pixel and average value across neighbors. + /// + /// + /// The property specifies what is the allowed difference percent between processing pixel + /// and average brightness of neighbor pixels in order to be set white. If the value of the + /// current pixel is t percent (this property value) lower than the average then it is set + /// to black, otherwise it is set to white. + /// + /// Default value is set to 0.15. + /// + /// + public float PixelBrightnessDifferenceLimit + { + get { return pixelBrightnessDifferenceLimit; } + set { pixelBrightnessDifferenceLimit = Math.Max( 0.0f, Math.Min( 1.0f, value ) ); } + } + + /// + /// Format translations dictionary. + /// + /// + /// See for more information. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public BradleyLocalThresholding( ) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image ) + { + // create integral image + IntegralImage im = IntegralImage.FromBitmap( image ); + + int width = image.Width; + int height = image.Height; + int widthM1 = width - 1; + int heightM1 = height - 1; + + int offset = image.Stride - width; + int radius = windowSize / 2; + + float avgBrightnessPart = 1.0f - pixelBrightnessDifferenceLimit; + + byte* ptr = (byte*) image.ImageData.ToPointer( ); + + for ( int y = 0; y < height; y++ ) + { + // rectangle's Y coordinates + int y1 = y - radius; + int y2 = y + radius; + + if ( y1 < 0 ) + y1 = 0; + if ( y2 > heightM1 ) + y2 = heightM1; + + for ( int x = 0; x < width; x++, ptr++ ) + { + // rectangle's X coordinates + int x1 = x - radius; + int x2 = x + radius; + + if ( x1 < 0 ) + x1 = 0; + if ( x2 > widthM1 ) + x2 = widthM1; + + *ptr = (byte) ( ( *ptr < (int) ( im.GetRectangleMeanUnsafe( x1, y1, x2, y2 ) * avgBrightnessPart ) ) ? 0 : 255 ); + } + + ptr += offset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Adaptive Binarization/IterativeThreshold.cs b/Sources/Accord.Imaging/AForge/Filters/Adaptive Binarization/IterativeThreshold.cs new file mode 100644 index 0000000000..3e2c4d843 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Adaptive Binarization/IterativeThreshold.cs @@ -0,0 +1,311 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Markus Falkensteiner, 2007 +// mfalkensteiner@gmx.at +// +// Copyright Andrew Kirillov, 2007-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Iterative threshold search and binarization. + /// + /// + /// + /// The algorithm works in the following way: + /// + /// select any start threshold; + /// compute average value of Background (B) and Object (O) values: + /// 1) all pixels with a value that is below threshold, belong to the Background values; + /// 2) all pixels greater or equal threshold, belong to the Object values. + /// + /// calculate new thresghold: (B + O) / 2; + /// if |oldThreshold - newThreshold| is less than a given manimum allowed error, then stop iteration process + /// and create the binary image with the new threshold. + /// + /// + /// + /// For additional information see Digital Image Processing, Gonzalez/Woods. Ch.10 page:599. + /// + /// The filter accepts 8 and 16 bpp grayscale images for processing. + /// + /// Since the filter can be applied as to 8 bpp and to 16 bpp images, + /// the initial value of property should be set appropriately to the + /// pixel format. In the case of 8 bpp images the threshold value is in the [0, 255] range, but + /// in the case of 16 bpp images the threshold value is in the [0, 65535] range. + /// + /// Sample usage: + /// + /// // create filter + /// IterativeThreshold filter = new IterativeThreshold( 2, 128 ); + /// // apply the filter + /// Bitmap newImage = filter.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image (calculated threshold is 102): + /// + /// + /// + /// + /// + /// + public class IterativeThreshold : Threshold + { + private int minError = 0; + + /// + /// Minimum error, value when iterative threshold search is stopped. + /// + /// + /// Default value is set to 0. + /// + public int MinimumError + { + get { return minError; } + set { minError = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public IterativeThreshold( ) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Minimum allowed error, that ends the iteration process. + /// + public IterativeThreshold( int minError ) + { + this.minError = minError; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Minimum allowed error, that ends the iteration process. + /// Initial threshold value. + /// + public IterativeThreshold( int minError, int threshold ) + { + this.minError = minError; + this.threshold = threshold; + } + + /// + /// Calculate binarization threshold for the given image. + /// + /// + /// Image to calculate binarization threshold for. + /// Rectangle to calculate binarization threshold for. + /// + /// Returns binarization threshold. + /// + /// The method is used to calculate binarization threshold only. The threshold + /// later may be applied to the image using image processing filter. + /// + /// Source pixel format is not supported by the routine. It should + /// 8 bpp grayscale (indexed) or 16 bpp grayscale image. + /// + public int CalculateThreshold( Bitmap image, Rectangle rect ) + { + int calculatedThreshold = 0; + + // lock source bitmap data + BitmapData data = image.LockBits( + new Rectangle( 0, 0, image.Width, image.Height ), + ImageLockMode.ReadOnly, image.PixelFormat ); + + try + { + calculatedThreshold = CalculateThreshold( data, rect ); + } + finally + { + // unlock image + image.UnlockBits( data ); + } + + return calculatedThreshold; + } + + /// + /// Calculate binarization threshold for the given image. + /// + /// + /// Image to calculate binarization threshold for. + /// Rectangle to calculate binarization threshold for. + /// + /// Returns binarization threshold. + /// + /// The method is used to calculate binarization threshold only. The threshold + /// later may be applied to the image using image processing filter. + /// + /// Source pixel format is not supported by the routine. It should + /// 8 bpp grayscale (indexed) or 16 bpp grayscale image. + /// + public int CalculateThreshold( BitmapData image, Rectangle rect ) + { + return CalculateThreshold( new UnmanagedImage( image ), rect ); + } + + /// + /// Calculate binarization threshold for the given image. + /// + /// + /// Image to calculate binarization threshold for. + /// Rectangle to calculate binarization threshold for. + /// + /// Returns binarization threshold. + /// + /// The method is used to calculate binarization threshold only. The threshold + /// later may be applied to the image using image processing filter. + /// + /// Source pixel format is not supported by the routine. It should + /// 8 bpp grayscale (indexed) or 16 bpp grayscale image. + /// + public int CalculateThreshold( UnmanagedImage image, Rectangle rect ) + { + if ( ( image.PixelFormat != PixelFormat.Format8bppIndexed ) && + ( image.PixelFormat != PixelFormat.Format16bppGrayScale ) ) + throw new UnsupportedImageFormatException( "Source pixel format is not supported by the routine." ); + + int calculatedThreshold = threshold; + + // get start and stop X-Y coordinates + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + + // histogram array + int[] integerHistogram = null; + int maxThreshold = 0; + + unsafe + { + if ( image.PixelFormat == PixelFormat.Format8bppIndexed ) + { + integerHistogram = new int[256]; + maxThreshold = 256; + + // collect histogram first + byte* ptr = (byte*) image.ImageData.ToPointer( ); + int offset = image.Stride - rect.Width; + + // allign pointer to the first pixel to process + ptr += ( startY * image.Stride + startX ); + + // for each line + for ( int y = startY; y < stopY; y++ ) + { + // for each pixel + for ( int x = startX; x < stopX; x++, ptr++ ) + { + integerHistogram[*ptr]++; + } + ptr += offset; + } + } + else + { + integerHistogram = new int[65536]; + maxThreshold = 65536; + + // collect histogram first + byte* basePtr = (byte*) image.ImageData.ToPointer( ) + startX * 2; + int stride = image.Stride; + + // for each line + for ( int y = startY; y < stopY; y++ ) + { + ushort* ptr = (ushort*) ( basePtr + y * stride ); + + // for each pixel + for ( int x = startX; x < stopX; x++, ptr++ ) + { + integerHistogram[*ptr]++; + } + } + } + } + + // old threshold value + int oldThreshold = 0; + + do + { + oldThreshold = calculatedThreshold; + + // object's mean and amount of object's pixels + double meanObject = 0; + int objectPixels = 0; + + // background's mean and amount of background's pixels + double meanBackground = 0; + int backgroundPixels = 0; + + for ( int t = 0; t < calculatedThreshold; t++ ) + { + meanBackground += (double) t * integerHistogram[t]; + backgroundPixels += integerHistogram[t]; + } + // calculate object pixels + for ( int t = calculatedThreshold; t < maxThreshold; t++ ) + { + meanObject += (double) t * integerHistogram[t]; + objectPixels += integerHistogram[t]; + } + meanBackground /= backgroundPixels; + meanObject /= objectPixels; + + // calculate new threshold value + if ( backgroundPixels == 0 ) + { + calculatedThreshold = (int) meanObject; + } + else if ( objectPixels == 0 ) + { + calculatedThreshold = (int) meanBackground; + } + else + { + calculatedThreshold = (int) ( ( meanBackground + meanObject ) / 2 ); + } + } + while ( Math.Abs( oldThreshold - calculatedThreshold ) > minError ); + + return calculatedThreshold; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + // calculate threshold for the given image + threshold = CalculateThreshold( image, rect ); + + // process image data using base filter + base.ProcessFilter( image, rect ); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Adaptive Binarization/OtsuThreshold.cs b/Sources/Accord.Imaging/AForge/Filters/Adaptive Binarization/OtsuThreshold.cs new file mode 100644 index 0000000000..5d1a0690a --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Adaptive Binarization/OtsuThreshold.cs @@ -0,0 +1,266 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Otsu thresholding. + /// + /// + /// The class implements Otsu thresholding, which is described in + /// N. Otsu, "A threshold selection method from gray-level histograms", IEEE Trans. Systems, + /// Man and Cybernetics 9(1), pp. 6266, 1979. + /// + /// This implementation instead of minimizing the weighted within-class variance + /// does maximization of between-class variance, what gives the same result. The approach is + /// described in this presentation. + /// + /// The filter accepts 8 bpp grayscale images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// OtsuThreshold filter = new OtsuThreshold( ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// // check threshold value + /// byte t = filter.ThresholdValue; + /// // ... + /// + /// + /// Initial image: + /// + /// Result image (calculated threshold is 97): + /// + /// + /// + /// + /// + /// + public class OtsuThreshold : BaseInPlacePartialFilter + { + private Threshold thresholdFilter = new Threshold(); + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Threshold value. + /// + /// + /// The property is read only and represents the value, which + /// was automaticaly calculated using Otsu algorithm. + /// + public int ThresholdValue + { + get { return thresholdFilter.ThresholdValue; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public OtsuThreshold() + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + } + + /// + /// Calculate binarization threshold for the given image. + /// + /// + /// Image to calculate binarization threshold for. + /// Rectangle to calculate binarization threshold for. + /// + /// Returns binarization threshold. + /// + /// The method is used to calculate binarization threshold only. The threshold + /// later may be applied to the image using image processing filter. + /// + /// Source pixel format is not supported by the routine. It should be + /// 8 bpp grayscale (indexed) image. + /// + public int CalculateThreshold(Bitmap image, Rectangle rect) + { + int calculatedThreshold = 0; + + // lock source bitmap data + BitmapData data = image.LockBits( + new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, image.PixelFormat); + + try + { + calculatedThreshold = CalculateThreshold(data, rect); + } + finally + { + // unlock image + image.UnlockBits(data); + } + + return calculatedThreshold; + } + + /// + /// Calculate binarization threshold for the given image. + /// + /// + /// Image to calculate binarization threshold for. + /// Rectangle to calculate binarization threshold for. + /// + /// Returns binarization threshold. + /// + /// The method is used to calculate binarization threshold only. The threshold + /// later may be applied to the image using image processing filter. + /// + /// Source pixel format is not supported by the routine. It should be + /// 8 bpp grayscale (indexed) image. + /// + public int CalculateThreshold(BitmapData image, Rectangle rect) + { + return CalculateThreshold(new UnmanagedImage(image), rect); + } + + /// + /// Calculate binarization threshold for the given image. + /// + /// + /// Image to calculate binarization threshold for. + /// Rectangle to calculate binarization threshold for. + /// + /// Returns binarization threshold. + /// + /// The method is used to calculate binarization threshold only. The threshold + /// later may be applied to the image using image processing filter. + /// + /// Source pixel format is not supported by the routine. It should be + /// 8 bpp grayscale (indexed) image. + /// + public int CalculateThreshold(UnmanagedImage image, Rectangle rect) + { + if (image.PixelFormat != PixelFormat.Format8bppIndexed) + throw new UnsupportedImageFormatException("Source pixel format is not supported by the routine."); + + int calculatedThreshold = 0; + + // get start and stop X-Y coordinates + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + int offset = image.Stride - rect.Width; + + // histogram array + int[] integerHistogram = new int[256]; + double[] histogram = new double[256]; + + unsafe + { + // collect histogram first + byte* ptr = (byte*)image.ImageData.ToPointer(); + + // allign pointer to the first pixel to process + ptr += (startY * image.Stride + startX); + + // for each line + for (int y = startY; y < stopY; y++) + { + // for each pixel + for (int x = startX; x < stopX; x++, ptr++) + { + integerHistogram[*ptr]++; + } + ptr += offset; + } + + // pixels count in the processing region + int pixelCount = (stopX - startX) * (stopY - startY); + // mean value of the processing region + double imageMean = 0; + + for (int i = 0; i < 256; i++) + { + histogram[i] = (double)integerHistogram[i] / pixelCount; + imageMean += histogram[i] * i; + } + + double max = double.MinValue; + + // initial class probabilities + double class1Probability = 0; + double class2Probability = 1; + + // initial class 1 mean value + double class1MeanInit = 0; + + // check all thresholds + for (int t = 0; (t < 256) && (class2Probability > 0); t++) + { + // calculate class means for the given threshold + double class1Mean = class1MeanInit; + double class2Mean = (imageMean - (class1Mean * class1Probability)) / class2Probability; + + // calculate between class variance + double betweenClassVariance = (class1Probability) * (1.0 - class1Probability) * Math.Pow(class1Mean - class2Mean, 2); + + // check if we found new threshold candidate + if (betweenClassVariance > max) + { + max = betweenClassVariance; + calculatedThreshold = t; + } + + // update initial probabilities and mean value + class1MeanInit *= class1Probability; + + class1Probability += histogram[t]; + class2Probability -= histogram[t]; + + class1MeanInit += (double)t * (double)histogram[t]; + + if (class1Probability != 0) + { + class1MeanInit /= class1Probability; + } + } + } + + return calculatedThreshold; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter(UnmanagedImage image, Rectangle rect) + { + // calculate threshold for the given image + thresholdFilter.ThresholdValue = CalculateThreshold(image, rect); + + // thresholding + thresholdFilter.ApplyInPlace(image, rect); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Adaptive Binarization/SISThreshold.cs b/Sources/Accord.Imaging/AForge/Filters/Adaptive Binarization/SISThreshold.cs new file mode 100644 index 0000000000..06871de37 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Adaptive Binarization/SISThreshold.cs @@ -0,0 +1,230 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Threshold using Simple Image Statistics (SIS). + /// + /// + /// The filter performs image thresholding calculating threshold automatically + /// using simple image statistics method. For each pixel: + /// + /// two gradients are calculated - ex = |I(x + 1, y) - I(x - 1, y)| and + /// |I(x, y + 1) - I(x, y - 1)|; + /// weight is calculated as maximum of two gradients; + /// sum of weights is updated (weightTotal += weight); + /// sum of weighted pixel values is updated (total += weight * I(x, y)). + /// + /// The result threshold is calculated as sum of weighted pixel values divided by sum of weight. + /// + /// The filter accepts 8 bpp grayscale images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// SISThreshold filter = new SISThreshold( ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image (calculated threshold is 127): + /// + /// + /// + /// + /// + /// + public class SISThreshold : BaseInPlacePartialFilter + { + private Threshold thresholdFilter = new Threshold(); + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Threshold value. + /// + /// + /// The property is read only and represents the value, which + /// was automaticaly calculated using image statistics. + /// + public int ThresholdValue + { + get { return thresholdFilter.ThresholdValue; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public SISThreshold() + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + } + + /// + /// Calculate binarization threshold for the given image. + /// + /// + /// Image to calculate binarization threshold for. + /// Rectangle to calculate binarization threshold for. + /// + /// Returns binarization threshold. + /// + /// The method is used to calculate binarization threshold only. The threshold + /// later may be applied to the image using image processing filter. + /// + /// Source pixel format is not supported by the routine. It should be + /// 8 bpp grayscale (indexed) image. + /// + public int CalculateThreshold(Bitmap image, Rectangle rect) + { + int calculatedThreshold = 0; + + // lock source bitmap data + BitmapData data = image.LockBits( + new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, image.PixelFormat); + + try + { + calculatedThreshold = CalculateThreshold(data, rect); + } + finally + { + // unlock image + image.UnlockBits(data); + } + + return calculatedThreshold; + } + + /// + /// Calculate binarization threshold for the given image. + /// + /// + /// Image to calculate binarization threshold for. + /// Rectangle to calculate binarization threshold for. + /// + /// Returns binarization threshold. + /// + /// The method is used to calculate binarization threshold only. The threshold + /// later may be applied to the image using image processing filter. + /// + /// Source pixel format is not supported by the routine. It should be + /// 8 bpp grayscale (indexed) image. + /// + public int CalculateThreshold(BitmapData image, Rectangle rect) + { + return CalculateThreshold(new UnmanagedImage(image), rect); + } + + /// + /// Calculate binarization threshold for the given image. + /// + /// + /// Image to calculate binarization threshold for. + /// Rectangle to calculate binarization threshold for. + /// + /// Returns binarization threshold. + /// + /// The method is used to calculate binarization threshold only. The threshold + /// later may be applied to the image using image processing filter. + /// + /// Source pixel format is not supported by the routine. It should be + /// 8 bpp grayscale (indexed) image. + /// + public static int CalculateThreshold(UnmanagedImage image, Rectangle rect) + { + if (image.PixelFormat != PixelFormat.Format8bppIndexed) + throw new UnsupportedImageFormatException("Source pixel format is not supported by the routine."); + + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + int stopXM1 = stopX - 1; + int stopYM1 = stopY - 1; + int stride = image.Stride; + int offset = stride - rect.Width; + + // differences and weights + double ex, ey, weight, weightTotal = 0, total = 0; + + unsafe + { + // do the job + byte* ptr = (byte*)image.ImageData.ToPointer(); + + // allign pointer to the first pixel to process + ptr += (startY * image.Stride + startX); + + // skip the first line for the first pass + ptr += stride; + + // for each line + for (int y = startY + 1; y < stopYM1; y++) + { + ptr++; + // for each pixels + for (int x = startX + 1; x < stopXM1; x++, ptr++) + { + // the equations are: + // ex = | I(x + 1, y) - I(x - 1, y) | + // ey = | I(x, y + 1) - I(x, y - 1) | + // weight = max(ex, ey) + // weightTotal += weight + // total += weight * I(x, y) + + ex = Math.Abs(ptr[1] - ptr[-1]); + ey = Math.Abs(ptr[stride] - ptr[-stride]); + weight = (ex > ey) ? ex : ey; + weightTotal += weight; + total += weight * (*ptr); + } + ptr += offset + 1; + } + } + + // calculate threshold + return (weightTotal == 0) ? (byte)0 : (byte)(total / weightTotal); + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter(UnmanagedImage image, Rectangle rect) + { + // calculate threshold + thresholdFilter.ThresholdValue = CalculateThreshold(image, rect); + + // thresholding + thresholdFilter.ApplyInPlace(image, rect); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Base classes/BaseFilter.cs b/Sources/Accord.Imaging/AForge/Filters/Base classes/BaseFilter.cs new file mode 100644 index 0000000000..7915afbd9 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Base classes/BaseFilter.cs @@ -0,0 +1,223 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Base class for filters, which produce new image of the same size as a + /// result of image processing. + /// + /// + /// The abstract class is the base class for all filters, which + /// do image processing creating new image with the same size as source. + /// Filters based on this class cannot be applied directly to the source + /// image, which is kept unchanged. + /// + /// The base class itself does not define supported pixel formats of source + /// image and resulting pixel formats of destination image. Filters inheriting from + /// this base class, should specify supported pixel formats and their transformations + /// overriding abstract property. + /// + /// + public abstract class BaseFilter : IFilter, IFilterInformation + { + /// + /// Format translations dictionary. + /// + /// + /// The dictionary defines, which pixel formats are supported for + /// source images and which pixel format will be used for resulting image. + /// + /// + /// See for more information. + /// + /// + public abstract Dictionary FormatTranslations { get; } + + /// + /// Apply filter to an image. + /// + /// + /// Source image to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The method keeps the source image unchanged and returns + /// the result of image processing filter as new image. + /// + /// Unsupported pixel format of the source image. + /// + public Bitmap Apply( Bitmap image ) + { + // lock source bitmap data + BitmapData srcData = image.LockBits( + new Rectangle( 0, 0, image.Width, image.Height ), + ImageLockMode.ReadOnly, image.PixelFormat ); + + Bitmap dstImage = null; + + try + { + // apply the filter + dstImage = Apply( srcData ); + if ( ( image.HorizontalResolution > 0 ) && ( image.VerticalResolution > 0 ) ) + { + dstImage.SetResolution( image.HorizontalResolution, image.VerticalResolution ); + } + } + finally + { + // unlock source image + image.UnlockBits( srcData ); + } + + return dstImage; + } + + /// + /// Apply filter to an image. + /// + /// + /// Source image to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The filter accepts bitmap data as input and returns the result + /// of image processing filter as new image. The source image data are kept + /// unchanged. + /// + /// Unsupported pixel format of the source image. + /// + public Bitmap Apply( BitmapData imageData ) + { + // check pixel format of the source image + CheckSourceFormat( imageData.PixelFormat ); + + // get width and height + int width = imageData.Width; + int height = imageData.Height; + + // destination image format + PixelFormat dstPixelFormat = FormatTranslations[imageData.PixelFormat]; + + // create new image of required format + Bitmap dstImage = ( dstPixelFormat == PixelFormat.Format8bppIndexed ) ? + AForge.Imaging.Image.CreateGrayscaleImage( width, height ) : + new Bitmap( width, height, dstPixelFormat ); + + // lock destination bitmap data + BitmapData dstData = dstImage.LockBits( + new Rectangle( 0, 0, width, height ), + ImageLockMode.ReadWrite, dstPixelFormat ); + + try + { + // process the filter + ProcessFilter( new UnmanagedImage( imageData ), new UnmanagedImage( dstData ) ); + } + finally + { + // unlock destination images + dstImage.UnlockBits( dstData ); + } + + return dstImage; + } + + /// + /// Apply filter to an image in unmanaged memory. + /// + /// + /// Source image in unmanaged memory to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The method keeps the source image unchanged and returns + /// the result of image processing filter as new image. + /// + /// Unsupported pixel format of the source image. + /// + public UnmanagedImage Apply( UnmanagedImage image ) + { + // check pixel format of the source image + CheckSourceFormat( image.PixelFormat ); + + // create new destination image + UnmanagedImage dstImage = UnmanagedImage.Create( image.Width, image.Height, FormatTranslations[image.PixelFormat] ); + + // process the filter + ProcessFilter( image, dstImage ); + + return dstImage; + } + + /// + /// Apply filter to an image in unmanaged memory. + /// + /// + /// Source image in unmanaged memory to apply filter to. + /// Destination image in unmanaged memory to put result into. + /// + /// The method keeps the source image unchanged and puts result of image processing + /// into destination image. + /// + /// The destination image must have the same width and height as source image. Also + /// destination image must have pixel format, which is expected by particular filter (see + /// property for information about pixel format conversions). + /// + /// + /// Unsupported pixel format of the source image. + /// Incorrect destination pixel format. + /// Destination image has wrong width and/or height. + /// + public void Apply( UnmanagedImage sourceImage, UnmanagedImage destinationImage ) + { + // check pixel format of the source and destination images + CheckSourceFormat( sourceImage.PixelFormat ); + + // ensure destination image has correct format + if ( destinationImage.PixelFormat != FormatTranslations[sourceImage.PixelFormat] ) + { + throw new InvalidImagePropertiesException( "Destination pixel format is specified incorrectly." ); + } + + // ensure destination image has correct size + if ( ( destinationImage.Width != sourceImage.Width ) || ( destinationImage.Height != sourceImage.Height ) ) + { + throw new InvalidImagePropertiesException( "Destination image must have the same width and height as source image." ); + } + + // process the filter + ProcessFilter( sourceImage, destinationImage ); + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + protected abstract unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData ); + + // Check pixel format of the source image + private void CheckSourceFormat( PixelFormat pixelFormat ) + { + if ( !FormatTranslations.ContainsKey( pixelFormat ) ) + throw new UnsupportedImageFormatException( "Source pixel format is not supported by the filter." ); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Base classes/BaseFilter2.cs b/Sources/Accord.Imaging/AForge/Filters/Base classes/BaseFilter2.cs new file mode 100644 index 0000000000..9a0e5a2e5 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Base classes/BaseFilter2.cs @@ -0,0 +1,194 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2010 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Base class for filters, which operate with two images of the same size and format and + /// produce new image as a result. + /// + /// + /// The abstract class is the base class for all filters, which can + /// be applied to an image producing new image as a result of image processing. + /// + /// The base class is aimed for such type of filters, which require additional image + /// to process the source image. The additional image is set by + /// or property and must have the same size and pixel format + /// as source image. See documentation of particular inherited class for information + /// about overlay image purpose. + /// + /// + /// + public abstract class BaseFilter2 : BaseFilter + { + private Bitmap overlayImage; + private UnmanagedImage unmanagedOverlayImage; + + /// + /// Overlay image. + /// + /// + /// + /// The property sets an overlay image, which will be used as the second image required + /// to process source image. See documentation of particular inherited class for information + /// about overlay image purpose. + /// + /// + /// Overlay image must have the same size and pixel format as source image. + /// Otherwise exception will be generated when filter is applied to source image. + /// + /// Setting this property will clear the property - + /// only one overlay image is allowed: managed or unmanaged. + /// + /// + public Bitmap OverlayImage + { + get { return overlayImage; } + set + { + overlayImage = value; + + if (value != null) + unmanagedOverlayImage = null; + } + } + + /// + /// Unmanaged overlay image. + /// + /// + /// + /// The property sets an overlay image, which will be used as the second image required + /// to process source image. See documentation of particular inherited class for information + /// about overlay image purpose. + /// + /// + /// Overlay image must have the same size and pixel format as source image. + /// Otherwise exception will be generated when filter is applied to source image. + /// + /// Setting this property will clear the property - + /// only one overlay image is allowed: managed or unmanaged. + /// + /// + public UnmanagedImage UnmanagedOverlayImage + { + get { return unmanagedOverlayImage; } + set + { + unmanagedOverlayImage = value; + + if (value != null) + overlayImage = null; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + protected BaseFilter2() { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Overlay image. + /// + protected BaseFilter2(Bitmap overlayImage) + { + this.overlayImage = overlayImage; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Unmanaged overlay image. + /// + protected BaseFilter2(UnmanagedImage unmanagedOverlayImage) + { + this.unmanagedOverlayImage = unmanagedOverlayImage; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData) + { + PixelFormat pixelFormat = sourceData.PixelFormat; + // get image dimension + int width = sourceData.Width; + int height = sourceData.Height; + + // check overlay type + if (overlayImage != null) + { + // source image and overlay must have same pixel format + if (pixelFormat != overlayImage.PixelFormat) + throw new InvalidImagePropertiesException("Source and overlay images must have same pixel format."); + + // check overlay image size + if ((width != overlayImage.Width) || (height != overlayImage.Height)) + throw new InvalidImagePropertiesException("Overlay image size must be equal to source image size."); + + // lock overlay image + BitmapData ovrData = overlayImage.LockBits( + new Rectangle(0, 0, width, height), + ImageLockMode.ReadOnly, pixelFormat); + + try + { + ProcessFilter(sourceData, new UnmanagedImage(ovrData), destinationData); + } + finally + { + // unlock overlay image + overlayImage.UnlockBits(ovrData); + } + } + else if (unmanagedOverlayImage != null) + { + // source image and overlay must have same pixel format + if (pixelFormat != unmanagedOverlayImage.PixelFormat) + throw new InvalidImagePropertiesException("Source and overlay images must have same pixel format."); + + // check overlay image size + if ((width != unmanagedOverlayImage.Width) || (height != unmanagedOverlayImage.Height)) + throw new InvalidImagePropertiesException("Overlay image size must be equal to source image size."); + + ProcessFilter(sourceData, unmanagedOverlayImage, destinationData); + } + else + { + throw new InvalidOperationException("Overlay image is not set."); + } + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Overlay image data. + /// Destination image data + /// + /// Overlay image size and pixel format is checked by this base class, before + /// passing execution to inherited class. + /// + protected abstract unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage overlay, UnmanagedImage destinationData); + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Base classes/BaseInPlaceFilter.cs b/Sources/Accord.Imaging/AForge/Filters/Base classes/BaseInPlaceFilter.cs new file mode 100644 index 0000000000..30787cd8e --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Base classes/BaseInPlaceFilter.cs @@ -0,0 +1,307 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Base class for filters, which may be applied directly to the source image. + /// + /// + /// The abstract class is the base class for all filters, which can + /// be applied to an image producing new image as a result of image processing or + /// applied directly to the source image without changing its size and pixel format. + /// + /// + public abstract class BaseInPlaceFilter : IFilter, IInPlaceFilter, IFilterInformation + { + /// + /// Format translations dictionary. + /// + /// + /// The dictionary defines, which pixel formats are supported for + /// source images and which pixel format will be used for resulting image. + /// + /// + /// See for more information. + /// + /// + public abstract Dictionary FormatTranslations { get; } + + /// + /// Apply filter to an image. + /// + /// + /// Source image to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The method keeps the source image unchanged and returns + /// the result of image processing filter as new image. + /// + /// Unsupported pixel format of the source image. + /// + public Bitmap Apply( Bitmap image ) + { + // lock source bitmap data + BitmapData srcData = image.LockBits( + new Rectangle( 0, 0, image.Width, image.Height ), + ImageLockMode.ReadOnly, image.PixelFormat ); + + Bitmap dstImage = null; + + try + { + // apply the filter + dstImage = Apply( srcData ); + if ( ( image.HorizontalResolution > 0 ) && ( image.VerticalResolution > 0 ) ) + { + dstImage.SetResolution( image.HorizontalResolution, image.VerticalResolution ); + } + } + finally + { + // unlock source image + image.UnlockBits( srcData ); + } + + return dstImage; + } + + /// + /// Apply filter to an image. + /// + /// + /// Source image to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The filter accepts bitmap data as input and returns the result + /// of image processing filter as new image. The source image data are kept + /// unchanged. + /// + /// Unsupported pixel format of the source image. + /// + public Bitmap Apply( BitmapData imageData ) + { + // destination image format + PixelFormat dstPixelFormat = imageData.PixelFormat; + + // check pixel format of the source image + CheckSourceFormat( dstPixelFormat ); + + // get image dimension + int width = imageData.Width; + int height = imageData.Height; + + // create new image of required format + Bitmap dstImage = ( dstPixelFormat == PixelFormat.Format8bppIndexed ) ? + AForge.Imaging.Image.CreateGrayscaleImage( width, height ) : + new Bitmap( width, height, dstPixelFormat ); + + // lock destination bitmap data + BitmapData dstData = dstImage.LockBits( + new Rectangle( 0, 0, width, height ), + ImageLockMode.ReadWrite, dstPixelFormat ); + + // copy image + AForge.SystemTools.CopyUnmanagedMemory( dstData.Scan0, imageData.Scan0, imageData.Stride * height ); + + try + { + // process the filter + ProcessFilter( new UnmanagedImage( dstData ) ); + } + finally + { + // unlock destination images + dstImage.UnlockBits( dstData ); + } + + return dstImage; + } + + /// + /// Apply filter to an image in unmanaged memory. + /// + /// + /// Source image in unmanaged memory to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The method keeps the source image unchanged and returns + /// the result of image processing filter as new image. + /// + /// Unsupported pixel format of the source image. + /// + public UnmanagedImage Apply( UnmanagedImage image ) + { + // check pixel format of the source image + CheckSourceFormat( image.PixelFormat ); + + // create new destination image + UnmanagedImage dstImage = UnmanagedImage.Create( image.Width, image.Height, image.PixelFormat ); + + Apply( image, dstImage ); + + return dstImage; + } + + /// + /// Apply filter to an image in unmanaged memory. + /// + /// + /// Source image in unmanaged memory to apply filter to. + /// Destination image in unmanaged memory to put result into. + /// + /// The method keeps the source image unchanged and puts result of image processing + /// into destination image. + /// + /// The destination image must have the same width and height as source image. Also + /// destination image must have pixel format, which is expected by particular filter (see + /// property for information about pixel format conversions). + /// + /// + /// Unsupported pixel format of the source image. + /// Incorrect destination pixel format. + /// Destination image has wrong width and/or height. + /// + public void Apply( UnmanagedImage sourceImage, UnmanagedImage destinationImage ) + { + // check pixel format of the source image + CheckSourceFormat( sourceImage.PixelFormat ); + + // ensure destination image has correct format + if ( destinationImage.PixelFormat != sourceImage.PixelFormat ) + { + throw new InvalidImagePropertiesException( "Destination pixel format must be the same as pixel format of source image." ); + } + + // ensure destination image has correct size + if ( ( destinationImage.Width != sourceImage.Width ) || ( destinationImage.Height != sourceImage.Height ) ) + { + throw new InvalidImagePropertiesException( "Destination image must have the same width and height as source image." ); + } + + // usually stride will be the same for 2 images of the size size/format, + // but since this a public a method and users may provide any evil, we need to check it + int dstStride = destinationImage.Stride; + int srcStride = sourceImage.Stride; + int lineSize = Math.Min( srcStride, dstStride ); + + unsafe + { + byte* dst = (byte*) destinationImage.ImageData.ToPointer( ); + byte* src = (byte*) sourceImage.ImageData.ToPointer( ); + + // copy image + for ( int y = 0, height = sourceImage.Height; y < height; y++ ) + { + AForge.SystemTools.CopyUnmanagedMemory( dst, src, lineSize ); + dst += dstStride; + src += srcStride; + } + } + + // process the filter + ProcessFilter( destinationImage ); + } + + /// + /// Apply filter to an image. + /// + /// + /// Image to apply filter to. + /// + /// The method applies the filter directly to the provided source image. + /// + /// Unsupported pixel format of the source image. + /// + public void ApplyInPlace( Bitmap image ) + { + // check pixel format of the source image + CheckSourceFormat( image.PixelFormat ); + + // lock source bitmap data + BitmapData data = image.LockBits( + new Rectangle( 0, 0, image.Width, image.Height ), + ImageLockMode.ReadWrite, image.PixelFormat ); + + try + { + // process the filter + ProcessFilter( new UnmanagedImage( data ) ); + } + finally + { + // unlock image + image.UnlockBits( data ); + } + } + + /// + /// Apply filter to an image. + /// + /// + /// Image data to apply filter to. + /// + /// The method applies the filter directly to the provided source image. + /// + /// Unsupported pixel format of the source image. + /// + public void ApplyInPlace( BitmapData imageData ) + { + // check pixel format of the source image + CheckSourceFormat( imageData.PixelFormat ); + + // process the filter + ProcessFilter( new UnmanagedImage( imageData ) ); + } + + /// + /// Apply filter to an unmanaged image. + /// + /// + /// Unmanaged image to apply filter to. + /// + /// The method applies the filter directly to the provided source unmanaged image. + /// + /// Unsupported pixel format of the source image. + /// + public void ApplyInPlace( UnmanagedImage image ) + { + // check pixel format of the source image + CheckSourceFormat( image.PixelFormat ); + + // process the filter + ProcessFilter( image ); + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// + protected abstract unsafe void ProcessFilter( UnmanagedImage image ); + + // Check pixel format of the source image + private void CheckSourceFormat( PixelFormat pixelFormat ) + { + if ( !FormatTranslations.ContainsKey( pixelFormat ) ) + throw new UnsupportedImageFormatException( "Source pixel format is not supported by the filter." ); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Base classes/BaseInPlaceFilter2.cs b/Sources/Accord.Imaging/AForge/Filters/Base classes/BaseInPlaceFilter2.cs new file mode 100644 index 0000000000..a0a8b04a5 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Base classes/BaseInPlaceFilter2.cs @@ -0,0 +1,196 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Base class for filters, which operate with two images of the same size and format and + /// may be applied directly to the source image. + /// + /// + /// The abstract class is the base class for all filters, which can + /// be applied to an image producing new image as a result of image processing or + /// applied directly to the source image without changing its size and pixel format. + /// + /// The base class is aimed for such type of filters, which require additional image + /// to process the source image. The additional image is set by + /// or property and must have the same size and pixel format + /// as source image. See documentation of particular inherited class for information + /// about overlay image purpose. + /// + /// + /// + public abstract class BaseInPlaceFilter2 : BaseInPlaceFilter + { + private Bitmap overlayImage; + private UnmanagedImage unmanagedOverlayImage; + + /// + /// Overlay image. + /// + /// + /// + /// The property sets an overlay image, which will be used as the second image required + /// to process source image. See documentation of particular inherited class for information + /// about overlay image purpose. + /// + /// + /// Overlay image must have the same size and pixel format as source image. + /// Otherwise exception will be generated when filter is applied to source image. + /// + /// Setting this property will clear the property - + /// only one overlay image is allowed: managed or unmanaged. + /// + /// + public Bitmap OverlayImage + { + get { return overlayImage; } + set + { + overlayImage = value; + + if ( value != null ) + unmanagedOverlayImage = null; + } + } + + /// + /// Unmanaged overlay image. + /// + /// + /// + /// The property sets an overlay image, which will be used as the second image required + /// to process source image. See documentation of particular inherited class for information + /// about overlay image purpose. + /// + /// + /// Overlay image must have the same size and pixel format as source image. + /// Otherwise exception will be generated when filter is applied to source image. + /// + /// Setting this property will clear the property - + /// only one overlay image is allowed: managed or unmanaged. + /// + /// + public UnmanagedImage UnmanagedOverlayImage + { + get { return unmanagedOverlayImage; } + set + { + unmanagedOverlayImage = value; + + if ( value != null ) + overlayImage = null; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + protected BaseInPlaceFilter2( ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Overlay image. + /// + protected BaseInPlaceFilter2( Bitmap overlayImage ) + { + this.overlayImage = overlayImage; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Unmanaged overlay image. + /// + protected BaseInPlaceFilter2( UnmanagedImage unmanagedOverlayImage ) + { + this.unmanagedOverlayImage = unmanagedOverlayImage; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// + /// Source and overlay images have different pixel formats and/or size. + /// Overlay image is not set. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image ) + { + PixelFormat pixelFormat = image.PixelFormat; + // get image dimension + int width = image.Width; + int height = image.Height; + + // check overlay type + if ( overlayImage != null ) + { + // source image and overlay must have same pixel format + if ( pixelFormat != overlayImage.PixelFormat ) + throw new InvalidImagePropertiesException( "Source and overlay images must have same pixel format." ); + + // check overlay image size + if ( ( width != overlayImage.Width ) || ( height != overlayImage.Height ) ) + throw new InvalidImagePropertiesException( "Overlay image size must be equal to source image size." ); + + // lock overlay image + BitmapData ovrData = overlayImage.LockBits( + new Rectangle( 0, 0, width, height ), + ImageLockMode.ReadOnly, pixelFormat ); + + try + { + ProcessFilter( image, new UnmanagedImage( ovrData ) ); + } + finally + { + // unlock overlay image + overlayImage.UnlockBits( ovrData ); + } + } + else if ( unmanagedOverlayImage != null ) + { + // source image and overlay must have same pixel format + if ( pixelFormat != unmanagedOverlayImage.PixelFormat ) + throw new InvalidImagePropertiesException( "Source and overlay images must have same pixel format." ); + + // check overlay image size + if ( ( width != unmanagedOverlayImage.Width ) || ( height != unmanagedOverlayImage.Height ) ) + throw new InvalidImagePropertiesException( "Overlay image size must be equal to source image size." ); + + ProcessFilter( image, unmanagedOverlayImage ); + } + else + { + throw new InvalidOperationException("Overlay image is not set."); + } + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Overlay image data. + /// + /// Overlay image size and pixel format is checked by this base class, before + /// passing execution to inherited class. + /// + protected abstract unsafe void ProcessFilter( UnmanagedImage image, UnmanagedImage overlay ); + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Base classes/BaseInPlacePartialFilter.cs b/Sources/Accord.Imaging/AForge/Filters/Base classes/BaseInPlacePartialFilter.cs new file mode 100644 index 0000000000..dea6bcd49 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Base classes/BaseInPlacePartialFilter.cs @@ -0,0 +1,364 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Base class for filters, which may be applied directly to the source image or its part. + /// + /// + /// The abstract class is the base class for all filters, which can + /// be applied to an image producing new image as a result of image processing or + /// applied directly to the source image (or its part) without changing its size and + /// pixel format. + /// + /// + public abstract class BaseInPlacePartialFilter : IFilter, IInPlaceFilter, IInPlacePartialFilter, IFilterInformation + { + /// + /// Format translations dictionary. + /// + /// + /// The dictionary defines, which pixel formats are supported for + /// source images and which pixel format will be used for resulting image. + /// + /// + /// See for more information. + /// + /// + public abstract Dictionary FormatTranslations { get; } + + /// + /// Apply filter to an image. + /// + /// + /// Source image to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The method keeps the source image unchanged and returns + /// the result of image processing filter as new image. + /// + /// Unsupported pixel format of the source image. + /// + public Bitmap Apply( Bitmap image ) + { + // lock source bitmap data + BitmapData srcData = image.LockBits( + new Rectangle( 0, 0, image.Width, image.Height ), + ImageLockMode.ReadOnly, image.PixelFormat ); + + Bitmap dstImage = null; + + try + { + // apply the filter + dstImage = Apply( srcData ); + if ( ( image.HorizontalResolution > 0 ) && ( image.VerticalResolution > 0 ) ) + { + dstImage.SetResolution( image.HorizontalResolution, image.VerticalResolution ); + } + } + finally + { + // unlock source image + image.UnlockBits( srcData ); + } + + return dstImage; + } + + /// + /// Apply filter to an image. + /// + /// + /// Source image to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The filter accepts bitmap data as input and returns the result + /// of image processing filter as new image. The source image data are kept + /// unchanged. + /// + /// Unsupported pixel format of the source image. + /// + public Bitmap Apply( BitmapData imageData ) + { + // destination image format + PixelFormat dstPixelFormat = imageData.PixelFormat; + + // check pixel format of the source image + CheckSourceFormat( dstPixelFormat ); + + // get image dimension + int width = imageData.Width; + int height = imageData.Height; + + // create new image of required format + Bitmap dstImage = ( dstPixelFormat == PixelFormat.Format8bppIndexed ) ? + AForge.Imaging.Image.CreateGrayscaleImage( width, height ) : + new Bitmap( width, height, dstPixelFormat ); + + // lock destination bitmap data + BitmapData dstData = dstImage.LockBits( + new Rectangle( 0, 0, width, height ), + ImageLockMode.ReadWrite, dstPixelFormat ); + + // copy image + AForge.SystemTools.CopyUnmanagedMemory( dstData.Scan0, imageData.Scan0, imageData.Stride * height ); + + try + { + // process the filter + ProcessFilter( new UnmanagedImage( dstData ), new Rectangle( 0, 0, width, height ) ); + } + finally + { + // unlock destination images + dstImage.UnlockBits( dstData ); + } + + return dstImage; + } + + /// + /// Apply filter to an image in unmanaged memory. + /// + /// + /// Source image in unmanaged memory to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The method keeps the source image unchanged and returns + /// the result of image processing filter as new image. + /// + /// Unsupported pixel format of the source image. + /// + public UnmanagedImage Apply( UnmanagedImage image ) + { + // check pixel format of the source image + CheckSourceFormat( image.PixelFormat ); + + // create new destination image + UnmanagedImage dstImage = UnmanagedImage.Create( image.Width, image.Height, image.PixelFormat ); + + Apply( image, dstImage ); + + return dstImage; + } + + /// + /// Apply filter to an image in unmanaged memory. + /// + /// + /// Source image in unmanaged memory to apply filter to. + /// Destination image in unmanaged memory to put result into. + /// + /// The method keeps the source image unchanged and puts result of image processing + /// into destination image. + /// + /// The destination image must have the same width and height as source image. Also + /// destination image must have pixel format, which is expected by particular filter (see + /// property for information about pixel format conversions). + /// + /// + /// Unsupported pixel format of the source image. + /// Incorrect destination pixel format. + /// Destination image has wrong width and/or height. + /// + public void Apply( UnmanagedImage sourceImage, UnmanagedImage destinationImage ) + { + // check pixel format of the source image + CheckSourceFormat( sourceImage.PixelFormat ); + + // ensure destination image has correct format + if ( destinationImage.PixelFormat != sourceImage.PixelFormat ) + { + throw new InvalidImagePropertiesException( "Destination pixel format must be the same as pixel format of source image." ); + } + + // ensure destination image has correct size + if ( ( destinationImage.Width != sourceImage.Width ) || ( destinationImage.Height != sourceImage.Height ) ) + { + throw new InvalidImagePropertiesException( "Destination image must have the same width and height as source image." ); + } + + // usually stride will be the same for 2 images of the size size/format, + // but since this a public a method and users may provide any evil, we to need check it + int dstStride = destinationImage.Stride; + int srcStride = sourceImage.Stride; + int lineSize = Math.Min( srcStride, dstStride ); + + unsafe + { + byte* dst = (byte*) destinationImage.ImageData.ToPointer( ); + byte* src = (byte*) sourceImage.ImageData.ToPointer( ); + + // copy image + for ( int y = 0, height = sourceImage.Height; y < height; y++ ) + { + AForge.SystemTools.CopyUnmanagedMemory( dst, src, lineSize ); + dst += dstStride; + src += srcStride; + } + } + + // process the filter + ProcessFilter( destinationImage, new Rectangle( 0, 0, destinationImage.Width, destinationImage.Height ) ); + } + + /// + /// Apply filter to an image. + /// + /// + /// Image to apply filter to. + /// + /// The method applies the filter directly to the provided source image. + /// + /// Unsupported pixel format of the source image. + /// + public void ApplyInPlace( Bitmap image ) + { + // apply the filter + ApplyInPlace( image, new Rectangle( 0, 0, image.Width, image.Height ) ); + } + + /// + /// Apply filter to an image. + /// + /// + /// Image data to apply filter to. + /// + /// The method applies the filter directly to the provided source image. + /// + /// Unsupported pixel format of the source image. + /// + public void ApplyInPlace( BitmapData imageData ) + { + // check pixel format of the source image + CheckSourceFormat( imageData.PixelFormat ); + + // apply the filter + ProcessFilter( new UnmanagedImage( imageData ), new Rectangle( 0, 0, imageData.Width, imageData.Height ) ); + } + + /// + /// Apply filter to an unmanaged image. + /// + /// + /// Unmanaged image to apply filter to. + /// + /// The method applies the filter directly to the provided source unmanaged image. + /// + /// Unsupported pixel format of the source image. + /// + public void ApplyInPlace( UnmanagedImage image ) + { + // check pixel format of the source image + CheckSourceFormat( image.PixelFormat ); + + // process the filter + ProcessFilter( image, new Rectangle( 0, 0, image.Width, image.Height ) ); + } + + /// + /// Apply filter to an image or its part. + /// + /// + /// Image to apply filter to. + /// Image rectangle for processing by the filter. + /// + /// The method applies the filter directly to the provided source image. + /// + /// Unsupported pixel format of the source image. + /// + public void ApplyInPlace( Bitmap image, Rectangle rect ) + { + // lock source bitmap data + BitmapData data = image.LockBits( + new Rectangle( 0, 0, image.Width, image.Height ), + ImageLockMode.ReadWrite, image.PixelFormat ); + + try + { + // apply the filter + ApplyInPlace( new UnmanagedImage( data ), rect ); + } + finally + { + // unlock image + image.UnlockBits( data ); + } + } + + /// + /// Apply filter to an image or its part. + /// + /// + /// Image data to apply filter to. + /// Image rectangle for processing by the filter. + /// + /// The method applies the filter directly to the provided source image. + /// + /// Unsupported pixel format of the source image. + /// + public void ApplyInPlace( BitmapData imageData, Rectangle rect ) + { + // apply the filter + ApplyInPlace( new UnmanagedImage( imageData ), rect ); + } + + /// + /// Apply filter to an unmanaged image or its part. + /// + /// + /// Unmanaged image to apply filter to. + /// Image rectangle for processing by the filter. + /// + /// The method applies the filter directly to the provided source image. + /// + /// Unsupported pixel format of the source image. + /// + public void ApplyInPlace( UnmanagedImage image, Rectangle rect ) + { + // check pixel format of the source image + CheckSourceFormat( image.PixelFormat ); + + // validate rectangle + rect.Intersect( new Rectangle( 0, 0, image.Width, image.Height ) ); + + // process the filter if rectangle is not empty + if ( ( rect.Width | rect.Height ) != 0 ) + ProcessFilter( image, rect ); + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected abstract unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ); + + // Check pixel format of the source image + private void CheckSourceFormat( PixelFormat pixelFormat ) + { + if ( !FormatTranslations.ContainsKey( pixelFormat ) ) + throw new UnsupportedImageFormatException( "Source pixel format is not supported by the filter." ); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Base classes/BaseResizeFilter.cs b/Sources/Accord.Imaging/AForge/Filters/Base classes/BaseResizeFilter.cs new file mode 100644 index 0000000000..4c25c2e79 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Base classes/BaseResizeFilter.cs @@ -0,0 +1,80 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Base class for image resizing filters. + /// + /// + /// The abstract class is the base class for all filters, + /// which implement image rotation algorithms. + /// + /// + public abstract class BaseResizeFilter : BaseTransformationFilter + { + /// + /// New image width. + /// + protected int newWidth; + + /// + /// New image height. + /// + protected int newHeight; + + /// + /// Width of the new resized image. + /// + /// + public int NewWidth + { + get { return newWidth; } + set { newWidth = Math.Max( 1, value ); } + } + + /// + /// Height of the new resized image. + /// + /// + public int NewHeight + { + get { return newHeight; } + set { newHeight = Math.Max( 1, value ); } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Width of the new resized image. + /// Height of the new resize image. + /// + protected BaseResizeFilter( int newWidth, int newHeight ) + { + this.newWidth = newWidth; + this.newHeight = newHeight; + } + + /// + /// Calculates new image size. + /// + /// + /// Source image data. + /// + /// New image size - size of the destination image. + /// + protected override System.Drawing.Size CalculateNewImageSize( UnmanagedImage sourceData ) + { + return new Size( newWidth, newHeight ); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Base classes/BaseRotateFilter.cs b/Sources/Accord.Imaging/AForge/Filters/Base classes/BaseRotateFilter.cs new file mode 100644 index 0000000000..073cdec93 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Base classes/BaseRotateFilter.cs @@ -0,0 +1,147 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Base class for image rotation filters. + /// + /// + /// The abstract class is the base class for all filters, + /// which implement rotating algorithms. + /// + public abstract class BaseRotateFilter : BaseTransformationFilter + { + /// + /// Rotation angle. + /// + protected double angle; + + /// + /// Keep image size or not. + /// + protected bool keepSize = false; + + /// + /// Fill color. + /// + protected Color fillColor = Color.FromArgb(0, 0, 0); + + /// + /// Rotation angle, [0, 360]. + /// + public double Angle + { + get { return angle; } + set { angle = value % 360; } + } + + /// + /// Keep image size or not. + /// + /// + /// The property determines if source image's size will be kept + /// as it is or not. If the value is set to false, then the new image will have + /// new dimension according to rotation angle. If the valus is set to + /// true, then the new image will have the same size, which means that some parts + /// of the image may be clipped because of rotation. + /// + /// + public bool KeepSize + { + get { return keepSize; } + set { keepSize = value; } + } + + /// + /// Fill color. + /// + /// + /// The fill color is used to fill areas of destination image, + /// which don't have corresponsing pixels in source image. + /// + public Color FillColor + { + get { return fillColor; } + set { fillColor = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Rotation angle. + /// + /// This constructor sets property to false. + /// + /// + protected BaseRotateFilter(double angle) + { + this.angle = angle; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Rotation angle. + /// Keep image size or not. + /// + protected BaseRotateFilter(double angle, bool keepSize) + { + this.angle = angle; + this.keepSize = keepSize; + } + + /// + /// Calculates new image size. + /// + /// + /// Source image data. + /// + /// New image size - size of the destination image. + /// + protected override System.Drawing.Size CalculateNewImageSize(UnmanagedImage sourceData) + { + // return same size if original image size should be kept + if (keepSize) + return new Size(sourceData.Width, sourceData.Height); + + // angle's sine and cosine + double angleRad = -angle * Math.PI / 180; + double angleCos = Math.Cos(angleRad); + double angleSin = Math.Sin(angleRad); + + // calculate half size + double halfWidth = (double)sourceData.Width / 2; + double halfHeight = (double)sourceData.Height / 2; + + // rotate corners + double cx1 = halfWidth * angleCos; + double cy1 = halfWidth * angleSin; + + double cx2 = halfWidth * angleCos - halfHeight * angleSin; + double cy2 = halfWidth * angleSin + halfHeight * angleCos; + + double cx3 = -halfHeight * angleSin; + double cy3 = halfHeight * angleCos; + + double cx4 = 0; + double cy4 = 0; + + // recalculate image size + halfWidth = Math.Max(Math.Max(cx1, cx2), Math.Max(cx3, cx4)) - Math.Min(Math.Min(cx1, cx2), Math.Min(cx3, cx4)); + halfHeight = Math.Max(Math.Max(cy1, cy2), Math.Max(cy3, cy4)) - Math.Min(Math.Min(cy1, cy2), Math.Min(cy3, cy4)); + + return new Size((int)(halfWidth * 2 + 0.5), (int)(halfHeight * 2 + 0.5)); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Base classes/BaseTransformationFilter.cs b/Sources/Accord.Imaging/AForge/Filters/Base classes/BaseTransformationFilter.cs new file mode 100644 index 0000000000..3591e6cdb --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Base classes/BaseTransformationFilter.cs @@ -0,0 +1,238 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Base class for filters, which may produce new image of different size as a + /// result of image processing. + /// + /// + /// The abstract class is the base class for all filters, which + /// do image processing creating new image of the size, which may differ from the + /// size of source image. Filters based on this class cannot be applied directly + /// to the source image, which is kept unchanged. + /// + /// The base class itself does not define supported pixel formats of source + /// image and resulting pixel formats of destination image. Filters inheriting from + /// this base class, should specify supported pixel formats and their transformations + /// overriding abstract property. + /// + /// + public abstract class BaseTransformationFilter : IFilter, IFilterInformation + { + /// + /// Format translations dictionary. + /// + /// + /// The dictionary defines, which pixel formats are supported for + /// source images and which pixel format will be used for resulting image. + /// + /// + /// See for more information. + /// + /// + public abstract Dictionary FormatTranslations { get; } + + /// + /// Apply filter to an image. + /// + /// + /// Source image to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The method keeps the source image unchanged and returns + /// the result of image processing filter as new image. + /// + /// Unsupported pixel format of the source image. + /// + public Bitmap Apply( Bitmap image ) + { + // lock source bitmap data + BitmapData srcData = image.LockBits( + new Rectangle( 0, 0, image.Width, image.Height ), + ImageLockMode.ReadOnly, image.PixelFormat ); + + Bitmap dstImage = null; + + try + { + // apply the filter + dstImage = Apply( srcData ); + if ( ( image.HorizontalResolution > 0 ) && ( image.VerticalResolution > 0 ) ) + { + dstImage.SetResolution( image.HorizontalResolution, image.VerticalResolution ); + } + } + finally + { + // unlock source image + image.UnlockBits( srcData ); + } + + return dstImage; + } + + /// + /// Apply filter to an image. + /// + /// + /// Source image to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The filter accepts bitmap data as input and returns the result + /// of image processing filter as new image. The source image data are kept + /// unchanged. + /// + /// Unsupported pixel format of the source image. + /// + public Bitmap Apply( BitmapData imageData ) + { + // check pixel format of the source image + CheckSourceFormat( imageData.PixelFormat ); + + // destination image format + PixelFormat dstPixelFormat = FormatTranslations[imageData.PixelFormat]; + + // get new image size + Size newSize = CalculateNewImageSize( new UnmanagedImage( imageData ) ); + + // create new image of required format + Bitmap dstImage = ( dstPixelFormat == PixelFormat.Format8bppIndexed ) ? + AForge.Imaging.Image.CreateGrayscaleImage( newSize.Width, newSize.Height ) : + new Bitmap( newSize.Width, newSize.Height, dstPixelFormat ); + + // lock destination bitmap data + BitmapData dstData = dstImage.LockBits( + new Rectangle( 0, 0, newSize.Width, newSize.Height ), + ImageLockMode.ReadWrite, dstPixelFormat ); + + try + { + // process the filter + ProcessFilter( new UnmanagedImage( imageData ), new UnmanagedImage( dstData ) ); + } + finally + { + // unlock destination images + dstImage.UnlockBits( dstData ); + } + + return dstImage; + } + + /// + /// Apply filter to an image in unmanaged memory. + /// + /// + /// Source image in unmanaged memory to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The method keeps the source image unchanged and returns + /// the result of image processing filter as new image. + /// + /// Unsupported pixel format of the source image. + /// + public UnmanagedImage Apply( UnmanagedImage image ) + { + // check pixel format of the source image + CheckSourceFormat( image.PixelFormat ); + + // get new image size + Size newSize = CalculateNewImageSize( image ); + + // create new destination image + UnmanagedImage dstImage = UnmanagedImage.Create( newSize.Width, newSize.Height, FormatTranslations[image.PixelFormat] ); + + // process the filter + ProcessFilter( image, dstImage ); + + return dstImage; + } + + /// + /// Apply filter to an image in unmanaged memory. + /// + /// + /// Source image in unmanaged memory to apply filter to. + /// Destination image in unmanaged memory to put result into. + /// + /// The method keeps the source image unchanged and puts result of image processing + /// into destination image. + /// + /// The destination image must have the same width and height as source image. Also + /// destination image must have pixel format, which is expected by particular filter (see + /// property for information about pixel format conversions). + /// + /// + /// Unsupported pixel format of the source image. + /// Incorrect destination pixel format. + /// Destination image has wrong width and/or height. + /// + public void Apply( UnmanagedImage sourceImage, UnmanagedImage destinationImage ) + { + // check pixel format of the source and destination images + CheckSourceFormat( sourceImage.PixelFormat ); + + // ensure destination image has correct format + if ( destinationImage.PixelFormat != FormatTranslations[sourceImage.PixelFormat] ) + { + throw new InvalidImagePropertiesException( "Destination pixel format is specified incorrectly." ); + } + + // get new image size + Size newSize = CalculateNewImageSize( sourceImage ); + + // ensure destination image has correct size + if ( ( destinationImage.Width != newSize.Width ) || ( destinationImage.Height != newSize.Height ) ) + { + throw new InvalidImagePropertiesException( "Destination image must have the size expected by the filter." ); + } + + // process the filter + ProcessFilter( sourceImage, destinationImage ); + } + + /// + /// Calculates new image size. + /// + /// + /// Source image data. + /// + /// New image size - size of the destination image. + /// + protected abstract System.Drawing.Size CalculateNewImageSize( UnmanagedImage sourceData ); + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + protected abstract unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData ); + + // Check pixel format of the source image + private void CheckSourceFormat( PixelFormat pixelFormat ) + { + if ( !FormatTranslations.ContainsKey( pixelFormat ) ) + throw new UnsupportedImageFormatException( "Source pixel format is not supported by the filter." ); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Base classes/BaseUsingCopyPartialFilter.cs b/Sources/Accord.Imaging/AForge/Filters/Base classes/BaseUsingCopyPartialFilter.cs new file mode 100644 index 0000000000..17c414518 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Base classes/BaseUsingCopyPartialFilter.cs @@ -0,0 +1,359 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Base class for filters, which require source image backup to make them applicable to + /// source image (or its part) directly. + /// + /// + /// The base class is used for filters, which can not do + /// direct manipulations with source image. To make effect of in-place filtering, + /// these filters create a background copy of the original image (done by this + /// base class) and then do manipulations with it putting result back to the original + /// source image. + /// + /// The background copy of the source image is created only in the case of in-place + /// filtering. Otherwise background copy is not created - source image is processed and result is + /// put to destination image. + /// + /// The base class is for those filters, which support as filtering entire image, as + /// partial filtering of specified rectangle only. + /// + /// + public abstract class BaseUsingCopyPartialFilter : IFilter, IInPlaceFilter, IInPlacePartialFilter, IFilterInformation + { + /// + /// Format translations dictionary. + /// + /// + /// The dictionary defines, which pixel formats are supported for + /// source images and which pixel format will be used for resulting image. + /// + /// + /// See for more information. + /// + /// + public abstract Dictionary FormatTranslations { get; } + + /// + /// Apply filter to an image. + /// + /// + /// Source image to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The method keeps the source image unchanged and returns + /// the result of image processing filter as new image. + /// + /// Unsupported pixel format of the source image. + /// + public Bitmap Apply(Bitmap image) + { + // lock source bitmap data + BitmapData srcData = image.LockBits( + new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, image.PixelFormat); + + Bitmap dstImage = null; + + try + { + // apply the filter + dstImage = Apply(srcData); + if ((image.HorizontalResolution > 0) && (image.VerticalResolution > 0)) + { + dstImage.SetResolution(image.HorizontalResolution, image.VerticalResolution); + } + } + finally + { + // unlock source image + image.UnlockBits(srcData); + } + + return dstImage; + } + + /// + /// Apply filter to an image. + /// + /// + /// Source image to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The filter accepts bitmap data as input and returns the result + /// of image processing filter as new image. The source image data are kept + /// unchanged. + /// + /// Unsupported pixel format of the source image. + /// + public Bitmap Apply(BitmapData imageData) + { + // check pixel format of the source image + CheckSourceFormat(imageData.PixelFormat); + + // get width and height + int width = imageData.Width; + int height = imageData.Height; + + // destination image format + PixelFormat dstPixelFormat = FormatTranslations[imageData.PixelFormat]; + + // create new image of required format + Bitmap dstImage = (dstPixelFormat == PixelFormat.Format8bppIndexed) ? + AForge.Imaging.Image.CreateGrayscaleImage(width, height) : + new Bitmap(width, height, dstPixelFormat); + + // lock destination bitmap data + BitmapData dstData = dstImage.LockBits( + new Rectangle(0, 0, width, height), + ImageLockMode.ReadWrite, dstPixelFormat); + + try + { + // process the filter + ProcessFilter(new UnmanagedImage(imageData), new UnmanagedImage(dstData), new Rectangle(0, 0, width, height)); + } + finally + { + // unlock destination images + dstImage.UnlockBits(dstData); + } + + return dstImage; + } + + /// + /// Apply filter to an image in unmanaged memory. + /// + /// + /// Source image in unmanaged memory to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The method keeps the source image unchanged and returns + /// the result of image processing filter as new image. + /// + /// Unsupported pixel format of the source image. + /// + public UnmanagedImage Apply(UnmanagedImage image) + { + // check pixel format of the source image + CheckSourceFormat(image.PixelFormat); + + // create new destination image + UnmanagedImage dstImage = UnmanagedImage.Create(image.Width, image.Height, FormatTranslations[image.PixelFormat]); + + // process the filter + ProcessFilter(image, dstImage, new Rectangle(0, 0, image.Width, image.Height)); + + return dstImage; + } + + /// + /// Apply filter to an image in unmanaged memory. + /// + /// + /// Source image in unmanaged memory to apply filter to. + /// Destination image in unmanaged memory to put result into. + /// + /// The method keeps the source image unchanged and puts result of image processing + /// into destination image. + /// + /// The destination image must have the same width and height as source image. Also + /// destination image must have pixel format, which is expected by particular filter (see + /// property for information about pixel format conversions). + /// + /// + /// Unsupported pixel format of the source image. + /// Incorrect destination pixel format. + /// Destination image has wrong width and/or height. + /// + public void Apply(UnmanagedImage sourceImage, UnmanagedImage destinationImage) + { + // check pixel format of the source and destination images + CheckSourceFormat(sourceImage.PixelFormat); + + // ensure destination image has correct format + if (destinationImage.PixelFormat != FormatTranslations[sourceImage.PixelFormat]) + { + throw new InvalidImagePropertiesException("Destination pixel format is specified incorrectly."); + } + + // ensure destination image has correct size + if ((destinationImage.Width != sourceImage.Width) || (destinationImage.Height != sourceImage.Height)) + { + throw new InvalidImagePropertiesException("Destination image must have the same width and height as source image."); + } + + // process the filter + ProcessFilter(sourceImage, destinationImage, new Rectangle(0, 0, sourceImage.Width, sourceImage.Height)); + } + + /// + /// Apply filter to an image. + /// + /// + /// Image to apply filter to. + /// + /// The method applies the filter directly to the provided source image. + /// + /// Unsupported pixel format of the source image. + /// + public void ApplyInPlace(Bitmap image) + { + // apply the filter + ApplyInPlace(image, new Rectangle(0, 0, image.Width, image.Height)); + } + + /// + /// Apply filter to an image. + /// + /// + /// Image data to apply filter to. + /// + /// The method applies the filter directly to the provided source image. + /// + /// Unsupported pixel format of the source image. + /// + public void ApplyInPlace(BitmapData imageData) + { + // apply the filter + ApplyInPlace(new UnmanagedImage(imageData), new Rectangle(0, 0, imageData.Width, imageData.Height)); + } + + /// + /// Apply filter to an unmanaged image. + /// + /// + /// Unmanaged image to apply filter to. + /// + /// The method applies the filter directly to the provided source unmanaged image. + /// + /// Unsupported pixel format of the source image. + /// + public void ApplyInPlace(UnmanagedImage image) + { + // apply the filter + ApplyInPlace(image, new Rectangle(0, 0, image.Width, image.Height)); + } + + /// + /// Apply filter to an image or its part. + /// + /// + /// Image to apply filter to. + /// Image rectangle for processing by the filter. + /// + /// The method applies the filter directly to the provided source image. + /// + /// Unsupported pixel format of the source image. + /// + public void ApplyInPlace(Bitmap image, Rectangle rect) + { + // lock source bitmap data + BitmapData data = image.LockBits( + new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadWrite, image.PixelFormat); + + try + { + // apply the filter + ApplyInPlace(new UnmanagedImage(data), rect); + } + finally + { + // unlock image + image.UnlockBits(data); + } + } + + /// + /// Apply filter to an image or its part. + /// + /// + /// Image data to apply filter to. + /// Image rectangle for processing by the filter. + /// + /// The method applies the filter directly to the provided source image. + /// + /// Unsupported pixel format of the source image. + /// + public void ApplyInPlace(BitmapData imageData, Rectangle rect) + { + // apply the filter + ApplyInPlace(new UnmanagedImage(imageData), rect); + } + + /// + /// Apply filter to an unmanaged image or its part. + /// + /// + /// Unmanaged image to apply filter to. + /// Image rectangle for processing by the filter. + /// + /// The method applies the filter directly to the provided source image. + /// + /// Unsupported pixel format of the source image. + /// + public void ApplyInPlace(UnmanagedImage image, Rectangle rect) + { + // check pixel format of the source image + CheckSourceFormat(image.PixelFormat); + + // validate rectangle + rect.Intersect(new Rectangle(0, 0, image.Width, image.Height)); + + // process the filter if rectangle is not empty + if ((rect.Width | rect.Height) != 0) + { + // create a copy of the source image + int size = image.Stride * image.Height; + + IntPtr imageCopy = MemoryManager.Alloc(size); + AForge.SystemTools.CopyUnmanagedMemory(imageCopy, image.ImageData, size); + + // process the filter + ProcessFilter( + new UnmanagedImage(imageCopy, image.Width, image.Height, image.Stride, image.PixelFormat), + image, rect); + + MemoryManager.Free(imageCopy); + } + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// Image rectangle for processing by the filter. + /// + protected abstract unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect); + + // Check pixel format of the source image + private void CheckSourceFormat(PixelFormat pixelFormat) + { + if (!FormatTranslations.ContainsKey(pixelFormat)) + throw new UnsupportedImageFormatException("Source pixel format is not supported by the filter."); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Binarization/BayerDithering.cs b/Sources/Accord.Imaging/AForge/Filters/Binarization/BayerDithering.cs new file mode 100644 index 0000000000..fdfb0b578 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Binarization/BayerDithering.cs @@ -0,0 +1,58 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + + /// + /// Ordered dithering using Bayer matrix. + /// + /// + /// The filter represents filter initialized + /// with the next threshold matrix: + /// + /// byte[,] matrix = new byte[4, 4] + /// { + /// { 0, 192, 48, 240 }, + /// { 128, 64, 176, 112 }, + /// { 32, 224, 16, 208 }, + /// { 160, 96, 144, 80 } + /// }; + /// + /// + /// The filter accepts 8 bpp grayscale images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// BayerDithering filter = new BayerDithering( ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public sealed class BayerDithering : OrderedDithering + { + /// + /// Initializes a new instance of the class. + /// + /// + public BayerDithering( ) : base( new byte[,] { + { 0, 192, 48, 240 }, + { 128, 64, 176, 112 }, + { 32, 224, 16, 208 }, + { 160, 96, 144, 80 } } ) + { + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Binarization/BurkesDithering.cs b/Sources/Accord.Imaging/AForge/Filters/Binarization/BurkesDithering.cs new file mode 100644 index 0000000000..ae7f43e23 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Binarization/BurkesDithering.cs @@ -0,0 +1,64 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// +// Original idea from CxImage +// http://www.codeproject.com/bitmap/cximage.asp +// +namespace AForge.Imaging.Filters +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Dithering using Burkes error diffusion. + /// + /// + /// The filter represents binarization filter, which is based on + /// error diffusion dithering with Burkes coefficients. Error is diffused + /// on 7 neighbor pixels with next coefficients: + /// + /// | * | 8 | 4 | + /// | 2 | 4 | 8 | 4 | 2 | + /// + /// / 32 + /// + /// + /// The filter accepts 8 bpp grayscale images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// BurkesDithering filter = new BurkesDithering( ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + /// + /// + public sealed class BurkesDithering : ErrorDiffusionToAdjacentNeighbors + { + /// + /// Initializes a new instance of the class. + /// + /// + public BurkesDithering( ) : base( new int[2][] { + new int[2] { 8, 4 }, + new int[5] { 2, 4, 8, 4, 2 } + } ) + { + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Binarization/ErrorDiffusionDithering.cs b/Sources/Accord.Imaging/AForge/Filters/Binarization/ErrorDiffusionDithering.cs new file mode 100644 index 0000000000..a9153de57 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Binarization/ErrorDiffusionDithering.cs @@ -0,0 +1,173 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + using AForge; + + /// + /// Base class for error diffusion dithering. + /// + /// + /// The class is the base class for binarization algorithms based on + /// error diffusion. + /// + /// Binarization with error diffusion in its idea is similar to binarization based on thresholding + /// of pixels' cumulative value (see ). Each pixel is binarized based not only + /// on its own value, but on values of some surrounding pixels. During pixel's binarization, its binarization + /// error is distributed (diffused) to some neighbor pixels with some coefficients. This error diffusion + /// updates neighbor pixels changing their values, what affects their upcoming binarization. Error diffuses + /// only on unprocessed yet neighbor pixels, which are right and bottom pixels usually (in the case if image + /// processing is done from upper left corner to bottom right corner). Binarization error equals + /// to processing pixel value, if it is below threshold value, or pixel value minus 255 otherwise. + /// + /// The filter accepts 8 bpp grayscale images for processing. + /// + /// + public abstract class ErrorDiffusionDithering : BaseInPlacePartialFilter + { + private byte threshold = 128; + + /// + /// Threshold value. + /// + /// + /// Default value is 128. + /// + public byte ThresholdValue + { + get { return threshold; } + set { threshold = value; } + } + + /// + /// Current processing X coordinate. + /// + protected int x; + + /// + /// Current processing Y coordinate. + /// + protected int y; + + /// + /// Processing X start position. + /// + protected int startX; + + /// + /// Processing Y start position. + /// + protected int startY; + + /// + /// Processing X stop position. + /// + protected int stopX; + + /// + /// Processing Y stop position. + /// + protected int stopY; + + /// + /// Processing image's stride (line size). + /// + protected int stride; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + protected ErrorDiffusionDithering() + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + } + + /// + /// Do error diffusion. + /// + /// + /// Current error value. + /// Pointer to current processing pixel. + /// + /// All parameters of the image and current processing pixel's coordinates + /// are initialized in protected members. + /// + protected abstract unsafe void Diffuse(int errorValue, byte* ptr); + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter(UnmanagedImage image, Rectangle rect) + { + // processing start and stop X,Y positions + startX = rect.Left; + startY = rect.Top; + stopX = startX + rect.Width; + stopY = startY + rect.Height; + stride = image.Stride; + + int offset = stride - rect.Width; + + // pixel value and error value + int v, error; + + // do the job + byte* ptr = (byte*)image.ImageData.ToPointer(); + + // allign pointer to the first pixel to process + ptr += (startY * stride + startX); + + // for each line + for (y = startY; y < stopY; y++) + { + // for each pixels + for (x = startX; x < stopX; x++, ptr++) + { + v = *ptr; + + // fill the next destination pixel + if (v >= threshold) + { + *ptr = 255; + error = v - 255; + } + else + { + *ptr = 0; + error = v; + } + + // do error diffusion + Diffuse(error, ptr); + } + ptr += offset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Binarization/ErrorDiffusionToAdjacentNeighbors.cs b/Sources/Accord.Imaging/AForge/Filters/Binarization/ErrorDiffusionToAdjacentNeighbors.cs new file mode 100644 index 0000000000..852967833 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Binarization/ErrorDiffusionToAdjacentNeighbors.cs @@ -0,0 +1,171 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Base class for error diffusion dithering, where error is diffused to + /// adjacent neighbor pixels. + /// + /// + /// The class does error diffusion to adjacent neighbor pixels + /// using specified set of coefficients. These coefficients are represented by + /// 2 dimensional jugged array, where first array of coefficients is for + /// right-standing pixels, but the rest of arrays are for bottom-standing pixels. + /// All arrays except the first one should have odd number of coefficients. + /// + /// Suppose that error diffusion coefficients are represented by the next + /// jugged array: + /// + /// + /// int[][] coefficients = new int[2][] { + /// new int[1] { 7 }, + /// new int[3] { 3, 5, 1 } + /// }; + /// + /// + /// The above coefficients are used to diffuse error over the next neighbor + /// pixels (* marks current pixel, coefficients are placed to corresponding + /// neighbor pixels): + /// + /// | * | 7 | + /// | 3 | 5 | 1 | + /// + /// / 16 + /// + /// + /// The filter accepts 8 bpp grayscale images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// ErrorDiffusionToAdjacentNeighbors filter = new ErrorDiffusionToAdjacentNeighbors( + /// new int[3][] { + /// new int[2] { 5, 3 }, + /// new int[5] { 2, 4, 5, 4, 2 }, + /// new int[3] { 2, 3, 2 } + /// } ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// + public class ErrorDiffusionToAdjacentNeighbors : ErrorDiffusionDithering + { + // diffusion coefficients + private int[][] coefficients; + // sum of all coefficients + private int coefficientsSum; + + /// + /// Diffusion coefficients. + /// + /// + /// Set of coefficients, which are used for error diffusion to + /// pixel's neighbors. + /// + public int[][] Coefficients + { + get { return coefficients; } + set + { + coefficients = value; + CalculateCoefficientsSum(); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Diffusion coefficients. + /// + public ErrorDiffusionToAdjacentNeighbors(int[][] coefficients) + { + this.coefficients = coefficients; + CalculateCoefficientsSum(); + } + + /// + /// Do error diffusion. + /// + /// + /// Current error value. + /// Pointer to current processing pixel. + /// + /// All parameters of the image and current processing pixel's coordinates + /// are initialized by base class. + /// + protected override unsafe void Diffuse(int errorValue, byte* ptr) + { + int ed; // error diffusion + + // do error diffusion to right-standing neighbors + int[] coefficientsRow = coefficients[0]; + + for (int jI = 1, jC = 0, k = coefficientsRow.Length; jC < k; jI++, jC++) + { + if (x + jI >= stopX) + break; + + ed = ptr[jI] + (errorValue * coefficientsRow[jC]) / coefficientsSum; + ed = (ed < 0) ? 0 : ((ed > 255) ? 255 : ed); + ptr[jI] = (byte)ed; + } + + // do error diffusion to bottom neigbors + for (int i = 1, n = coefficients.Length; i < n; i++) + { + if (y + i >= stopY) + break; + + // move pointer to next image line + ptr += stride; + + // get coefficients of the row + coefficientsRow = coefficients[i]; + + // process the row + for (int jC = 0, k = coefficientsRow.Length, jI = -(k >> 1); jC < k; jI++, jC++) + { + if (x + jI >= stopX) + break; + if (x + jI < startX) + continue; + + ed = ptr[jI] + (errorValue * coefficientsRow[jC]) / coefficientsSum; + ed = (ed < 0) ? 0 : ((ed > 255) ? 255 : ed); + ptr[jI] = (byte)ed; + } + } + } + + #region Private Members + + // Calculate coefficients' sum + private void CalculateCoefficientsSum() + { + coefficientsSum = 0; + + for (int i = 0, n = coefficients.Length; i < n; i++) + { + int[] coefficientsRow = coefficients[i]; + + for (int j = 0, k = coefficientsRow.Length; j < k; j++) + { + coefficientsSum += coefficientsRow[j]; + } + } + } + + #endregion + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Binarization/FloydSteinbergDithering.cs b/Sources/Accord.Imaging/AForge/Filters/Binarization/FloydSteinbergDithering.cs new file mode 100644 index 0000000000..776277ae2 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Binarization/FloydSteinbergDithering.cs @@ -0,0 +1,64 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Dithering using Floyd-Steinberg error diffusion. + /// + /// + /// The filter represents binarization filter, which is based on + /// error diffusion dithering with Floyd-Steinberg + /// coefficients. Error is diffused on 4 neighbor pixels with next coefficients: + /// + /// + /// | * | 7 | + /// | 3 | 5 | 1 | + /// + /// / 16 + /// + /// + /// The filter accepts 8 bpp grayscale images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// FloydSteinbergDithering filter = new FloydSteinbergDithering( ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + /// + /// + public sealed class FloydSteinbergDithering : ErrorDiffusionToAdjacentNeighbors + { + /// + /// Initializes a new instance of the class. + /// + /// + public FloydSteinbergDithering( ) + : base( new int[2][] { + new int[1] { 7 }, + new int[3] { 3, 5, 1 } + } ) + { + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Binarization/JarvisJudiceNinkeDithering.cs b/Sources/Accord.Imaging/AForge/Filters/Binarization/JarvisJudiceNinkeDithering.cs new file mode 100644 index 0000000000..7ff99cd94 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Binarization/JarvisJudiceNinkeDithering.cs @@ -0,0 +1,66 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// +// Original idea from CxImage +// http://www.codeproject.com/bitmap/cximage.asp +// +namespace AForge.Imaging.Filters +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Dithering using Jarvis, Judice and Ninke error diffusion. + /// + /// + /// The filter represents binarization filter, which is based on + /// error diffusion dithering with Jarvis-Judice-Ninke coefficients. Error is diffused + /// on 12 neighbor pixels with next coefficients: + /// + /// | * | 7 | 5 | + /// | 3 | 5 | 7 | 5 | 3 | + /// | 1 | 3 | 5 | 3 | 1 | + /// + /// / 48 + /// + /// + /// The filter accepts 8 bpp grayscale images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// JarvisJudiceNinkeDithering filter = new JarvisJudiceNinkeDithering( ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + /// + /// + public sealed class JarvisJudiceNinkeDithering : ErrorDiffusionToAdjacentNeighbors + { + /// + /// Initializes a new instance of the class. + /// + /// + public JarvisJudiceNinkeDithering( ) : base( new int[3][] { + new int[2] { 7, 5 }, + new int[5] { 3, 5, 7, 5, 3 }, + new int[5] { 1, 3, 5, 3, 1 } + } ) + { + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Binarization/OrderedDithering.cs b/Sources/Accord.Imaging/AForge/Filters/Binarization/OrderedDithering.cs new file mode 100644 index 0000000000..cc04aa24d --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Binarization/OrderedDithering.cs @@ -0,0 +1,134 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Binarization with thresholds matrix. + /// + /// + /// Idea of the filter is the same as idea of filter - + /// change pixel value to white, if its intensity is equal or higher than threshold value, or + /// to black otherwise. But instead of using single threshold value for all pixel, the filter + /// uses matrix of threshold values. Processing image is divided to adjacent windows of matrix + /// size each. For pixels binarization inside of each window, corresponding threshold values are + /// used from specified threshold matrix. + /// + /// The filter accepts 8 bpp grayscale images for processing. + /// + /// Sample usage: + /// + /// // create binarization matrix + /// byte[,] matrix = new byte[4, 4] + /// { + /// { 95, 233, 127, 255 }, + /// { 159, 31, 191, 63 }, + /// { 111, 239, 79, 207 }, + /// { 175, 47, 143, 15 } + /// }; + /// // create filter + /// OrderedDithering filter = new OrderedDithering( matrix ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + public class OrderedDithering : BaseInPlacePartialFilter + { + private int rows = 4; + private int cols = 4; + + private byte[,] matrix = new byte[4, 4] + { + { 15, 143, 47, 175 }, + { 207, 79, 239, 111 }, + { 63, 191, 31, 159 }, + { 255, 127, 223, 95 } + }; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public OrderedDithering( ) + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Thresholds matrix. + /// + public OrderedDithering( byte[,] matrix ) + : this( ) + { + rows = matrix.GetLength( 0 ); + cols = matrix.GetLength( 1 ); + + this.matrix = matrix; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + int offset = image.Stride - rect.Width; + + // do the job + byte* ptr = (byte*) image.ImageData.ToPointer( ); + + // allign pointer to the first pixel to process + ptr += ( startY * image.Stride + startX ); + + // for each line + for ( int y = startY; y < stopY; y++ ) + { + // for each pixel + for ( int x = startX; x < stopX; x++, ptr++ ) + { + *ptr = (byte) ( ( *ptr <= matrix[( y % rows ), ( x % cols )] ) ? 0 : 255 ); + } + ptr += offset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Binarization/SierraDithering.cs b/Sources/Accord.Imaging/AForge/Filters/Binarization/SierraDithering.cs new file mode 100644 index 0000000000..7a0270fce --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Binarization/SierraDithering.cs @@ -0,0 +1,66 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// +// Original idea from CxImage +// http://www.codeproject.com/bitmap/cximage.asp +// +namespace AForge.Imaging.Filters +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Dithering using Sierra error diffusion. + /// + /// + /// The filter represents binarization filter, which is based on + /// error diffusion dithering with Sierra coefficients. Error is diffused + /// on 10 neighbor pixels with next coefficients: + /// + /// | * | 5 | 3 | + /// | 2 | 4 | 5 | 4 | 2 | + /// | 2 | 3 | 2 | + /// + /// / 32 + /// + /// + /// The filter accepts 8 bpp grayscale images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// SierraDithering filter = new SierraDithering( ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + /// + /// + public sealed class SierraDithering : ErrorDiffusionToAdjacentNeighbors + { + /// + /// Initializes a new instance of the class. + /// + /// + public SierraDithering( ) : base( new int[3][] { + new int[2] { 5, 3 }, + new int[5] { 2, 4, 5, 4, 2 }, + new int[3] { 2, 3, 2 } + } ) + { + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Binarization/StuckiDithering.cs b/Sources/Accord.Imaging/AForge/Filters/Binarization/StuckiDithering.cs new file mode 100644 index 0000000000..3ac858d95 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Binarization/StuckiDithering.cs @@ -0,0 +1,66 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// +// Original idea from CxImage +// http://www.codeproject.com/bitmap/cximage.asp +// +namespace AForge.Imaging.Filters +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Dithering using Stucki error diffusion. + /// + /// + /// The filter represents binarization filter, which is based on + /// error diffusion dithering with Stucki coefficients. Error is diffused + /// on 12 neighbor pixels with next coefficients: + /// + /// | * | 8 | 4 | + /// | 2 | 4 | 8 | 4 | 2 | + /// | 1 | 2 | 4 | 2 | 1 | + /// + /// / 42 + /// + /// + /// The filter accepts 8 bpp grayscale images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// StuckiDithering filter = new StuckiDithering( ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + /// + /// + public sealed class StuckiDithering : ErrorDiffusionToAdjacentNeighbors + { + /// + /// Initializes a new instance of the class. + /// + /// + public StuckiDithering( ) : base( new int[3][] { + new int[2] { 8, 4 }, + new int[5] { 2, 4, 8, 4, 2 }, + new int[5] { 1, 2, 4, 2, 1 } + } ) + { + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Binarization/Threshold.cs b/Sources/Accord.Imaging/AForge/Filters/Binarization/Threshold.cs new file mode 100644 index 0000000000..35c109d68 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Binarization/Threshold.cs @@ -0,0 +1,151 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Threshold binarization. + /// + /// + /// The filter does image binarization using specified threshold value. All pixels + /// with intensities equal or higher than threshold value are converted to white pixels. All other + /// pixels with intensities below threshold value are converted to black pixels. + /// + /// The filter accepts 8 and 16 bpp grayscale images for processing. + /// + /// Since the filter can be applied as to 8 bpp and to 16 bpp images, + /// the value should be set appropriately to the pixel format. + /// In the case of 8 bpp images the threshold value is in the [0, 255] range, but in the case + /// of 16 bpp images the threshold value is in the [0, 65535] range. + /// + /// Sample usage: + /// + /// // create filter + /// Threshold filter = new Threshold( 100 ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class Threshold : BaseInPlacePartialFilter + { + /// + /// Threshold value. + /// + protected int threshold = 128; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Threshold value. + /// + /// + /// Default value is set to 128. + /// + public int ThresholdValue + { + get { return threshold; } + set { threshold = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public Threshold( ) + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format16bppGrayScale] = PixelFormat.Format16bppGrayScale; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Threshold value. + /// + public Threshold( int threshold ) + : this( ) + { + this.threshold = threshold; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + + if ( image.PixelFormat == PixelFormat.Format8bppIndexed ) + { + int offset = image.Stride - rect.Width; + + // do the job + byte* ptr = (byte*) image.ImageData.ToPointer( ); + + // allign pointer to the first pixel to process + ptr += ( startY * image.Stride + startX ); + + // for each line + for ( int y = startY; y < stopY; y++ ) + { + // for each pixel + for ( int x = startX; x < stopX; x++, ptr++ ) + { + *ptr = (byte) ( ( *ptr >= threshold ) ? 255 : 0 ); + } + ptr += offset; + } + } + else + { + byte* basePtr = (byte*) image.ImageData.ToPointer( ) + startX * 2; + int stride = image.Stride; + + // for each line + for ( int y = startY; y < stopY; y++ ) + { + ushort* ptr = (ushort*) ( basePtr + stride * y ); + + // for each pixel + for ( int x = startX; x < stopX; x++, ptr++ ) + { + *ptr = (ushort) ( ( *ptr >= threshold ) ? 65535 : 0 ); + } + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Binarization/ThresholdWithCarry.cs b/Sources/Accord.Imaging/AForge/Filters/Binarization/ThresholdWithCarry.cs new file mode 100644 index 0000000000..494695f7f --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Binarization/ThresholdWithCarry.cs @@ -0,0 +1,141 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Threshold binarization with error carry. + /// + /// + /// The filter is similar to filter in the way, + /// that it also uses threshold value for image binarization. Unlike regular threshold + /// filter, this filter uses cumulative pixel value in comparing with threshold value. + /// If cumulative pixel value is below threshold value, then image pixel becomes black. + /// If cumulative pixel value is equal or higher than threshold value, then image pixel + /// becomes white and cumulative pixel value is decreased by 255. In the beginning of each + /// image line the cumulative value is reset to 0. + /// + /// + /// The filter accepts 8 bpp grayscale images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// Threshold filter = new Threshold( 100 ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class ThresholdWithCarry : BaseInPlacePartialFilter + { + private byte threshold = 128; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Threshold value. + /// + /// + /// Default value is 128. + /// + public byte ThresholdValue + { + get { return threshold; } + set { threshold = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public ThresholdWithCarry( ) + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Threshold value. + /// + public ThresholdWithCarry( byte threshold ) + : this( ) + { + this.threshold = threshold; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + int offset = image.Stride - rect.Width; + + // value which is caried from pixel to pixel + short carry = 0; + + // do the job + byte* ptr = (byte*) image.ImageData.ToPointer( ); + + // allign pointer to the first pixel to process + ptr += ( startY * image.Stride + startX ); + + // for each line + for ( int y = startY; y < stopY; y++ ) + { + carry = 0; + + // for each pixel + for ( int x = startX; x < stopX; x++, ptr++ ) + { + carry += *ptr; + + if ( carry >= threshold ) + { + *ptr = (byte) 255; + carry -= 255; + } + else + { + *ptr = (byte) 0; + } + } + ptr += offset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Color Filters/BayerFilter.cs b/Sources/Accord.Imaging/AForge/Filters/Color Filters/BayerFilter.cs new file mode 100644 index 0000000000..2a5efe6d4 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Color Filters/BayerFilter.cs @@ -0,0 +1,260 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Generic Bayer fileter image processing routine. + /// + /// + /// The class implements Bayer filter + /// routine, which creates color image out of grayscale image produced by image sensor built with + /// Bayer color matrix. + /// + /// This Bayer filter implementation is made generic by allowing user to specify used + /// Bayer pattern. This makes it slower. For optimized version + /// of the Bayer filter see class, which implements Bayer filter + /// specifically optimized for some well known patterns. + /// + /// The filter accepts 8 bpp grayscale images and produces 24 bpp RGB image. + /// + /// Sample usage: + /// + /// // create filter + /// BayerFilter filter = new BayerFilter( ); + /// // apply the filter + /// Bitmap rgbImage = filter.Apply( image ); + /// + /// + /// Source image: + /// + /// Result image: + /// + /// + /// + /// + /// + public class BayerFilter : BaseFilter + { + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + private bool performDemosaicing = true; + private int[,] bayerPattern = new int[2, 2] { { RGB.G, RGB.R }, { RGB.B, RGB.G } }; + + /// + /// Specifies if demosaicing must be done or not. + /// + /// + /// The property specifies if color demosaicing must be done or not. + /// If the property is set to , then pixels of the result color image + /// are colored according to the Bayer pattern used, i.e. every pixel + /// of the source grayscale image is copied to corresponding color plane of the result image. + /// If the property is set to , then pixels of the result image + /// are set to color, which is obtained by averaging color components from the 3x3 window - pixel + /// itself plus 8 surrounding neighbors. + /// + /// Default value is set to . + /// + /// + public bool PerformDemosaicing + { + get { return performDemosaicing; } + set { performDemosaicing = value; } + } + + /// + /// Specifies Bayer pattern used for decoding color image. + /// + /// + /// The property specifies 2x2 array of RGB color indexes, which set the + /// Bayer patter used for decoding color image. + /// + /// By default the property is set to: + /// + /// new int[2, 2] { { RGB.G, RGB.R }, { RGB.B, RGB.G } } + /// , + /// which corresponds to + /// + /// G R + /// B G + /// + /// pattern. + /// + /// + /// + public int[,] BayerPattern + { + get { return bayerPattern; } + set + { + bayerPattern = value; + } + } + + /// + /// Format translations dictionary. + /// + /// + /// See + /// documentation for additional information. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public BayerFilter( ) + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format24bppRgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData ) + { + // get width and height + int width = sourceData.Width; + int height = sourceData.Height; + + int widthM1 = width - 1; + int heightM1 = height - 1; + + int srcStride = sourceData.Stride; + + int srcOffset = srcStride - width; + int dstOffset = destinationData.Stride - width * 3; + + // do the job + byte * src = (byte*) sourceData.ImageData.ToPointer( ); + byte * dst = (byte*) destinationData.ImageData.ToPointer( ); + + int[] rgbValues = new int[3]; + int[] rgbCounters = new int[3]; + + if ( !performDemosaicing ) + { + // for each line + for ( int y = 0; y < height; y++ ) + { + // for each pixel + for ( int x = 0; x < width; x++, src++, dst += 3 ) + { + dst[RGB.R] = dst[RGB.G] = dst[RGB.B] = 0; + dst[bayerPattern[y & 1, x & 1]] = *src; + } + src += srcOffset; + dst += dstOffset; + } + } + else + { + // for each line + for ( int y = 0; y < height; y++ ) + { + // for each pixel + for ( int x = 0; x < width; x++, src++, dst += 3 ) + { + rgbValues[0] = rgbValues[1] = rgbValues[2] = 0; + rgbCounters[0] = rgbCounters[1] = rgbCounters[2] = 0; + + int bayerIndex = bayerPattern[y & 1, x & 1]; + + rgbValues[bayerIndex] += *src; + rgbCounters[bayerIndex]++; + + if ( x != 0 ) + { + bayerIndex = bayerPattern[y & 1, ( x - 1 ) & 1]; + + rgbValues[bayerIndex] += src[-1]; + rgbCounters[bayerIndex]++; + } + + if ( x != widthM1 ) + { + bayerIndex = bayerPattern[y & 1, ( x + 1 ) & 1]; + + rgbValues[bayerIndex] += src[1]; + rgbCounters[bayerIndex]++; + } + + if ( y != 0 ) + { + bayerIndex = bayerPattern[( y - 1 ) & 1, x & 1]; + + rgbValues[bayerIndex] += src[-srcStride]; + rgbCounters[bayerIndex]++; + + if ( x != 0 ) + { + bayerIndex = bayerPattern[( y - 1 ) & 1, ( x - 1 ) & 1]; + + rgbValues[bayerIndex] += src[-srcStride - 1]; + rgbCounters[bayerIndex]++; + } + + if ( x != widthM1 ) + { + bayerIndex = bayerPattern[( y - 1 ) & 1, ( x + 1 ) & 1]; + + rgbValues[bayerIndex] += src[-srcStride + 1]; + rgbCounters[bayerIndex]++; + } + } + + if ( y != heightM1 ) + { + bayerIndex = bayerPattern[( y + 1 ) & 1, x & 1]; + + rgbValues[bayerIndex] += src[srcStride]; + rgbCounters[bayerIndex]++; + + if ( x != 0 ) + { + bayerIndex = bayerPattern[( y + 1 ) & 1, ( x - 1 ) & 1]; + + rgbValues[bayerIndex] += src[srcStride - 1]; + rgbCounters[bayerIndex]++; + } + + if ( x != widthM1 ) + { + bayerIndex = bayerPattern[( y + 1 ) & 1, ( x + 1 ) & 1]; + + rgbValues[bayerIndex] += src[srcStride + 1]; + rgbCounters[bayerIndex]++; + } + } + + dst[RGB.R] = (byte) ( rgbValues[RGB.R] / rgbCounters[RGB.R] ); + dst[RGB.G] = (byte) ( rgbValues[RGB.G] / rgbCounters[RGB.G] ); + dst[RGB.B] = (byte) ( rgbValues[RGB.B] / rgbCounters[RGB.B] ); + } + src += srcOffset; + dst += dstOffset; + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Color Filters/BayerFilterOptimized.cs b/Sources/Accord.Imaging/AForge/Filters/Color Filters/BayerFilterOptimized.cs new file mode 100644 index 0000000000..b670ef381 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Color Filters/BayerFilterOptimized.cs @@ -0,0 +1,568 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Set of Bayer patterns supported by . + /// + public enum BayerPattern + { + /// + /// Pattern:

+ /// G R
+ /// B G + ///
+ GRBG, + + /// + /// Pattern:

+ /// B G
+ /// G R + ///
+ BGGR + } + + /// + /// Optimized Bayer fileter image processing routine. + /// + /// + /// The class implements Bayer filter + /// routine, which creates color image out of grayscale image produced by image sensor built with + /// Bayer color matrix. + /// + /// This class does all the same as class. However this version is + /// optimized for some well known patterns defined in enumeration. + /// Also this class processes images with even width and height only. Image size must be at least 2x2 pixels. + /// + /// + /// The filter accepts 8 bpp grayscale images and produces 24 bpp RGB image. + /// + /// Sample usage: + /// + /// // create filter + /// BayerFilter filter = new BayerFilter( ); + /// // apply the filter + /// Bitmap rgbImage = filter.Apply( image ); + /// + /// + /// + /// + /// + public class BayerFilterOptimized : BaseFilter + { + private BayerPattern bayerPattern = BayerPattern.GRBG; + + /// + /// Bayer pattern of source images to decode. + /// + /// + /// The property specifies Bayer pattern of source images to be + /// decoded into color images. + /// + /// Default value is set to . + /// + /// + public BayerPattern Pattern + { + get { return bayerPattern; } + set { bayerPattern = value; } + } + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + /// + /// See + /// documentation for additional information. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public BayerFilterOptimized() + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format24bppRgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + protected override void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData) + { + // get width and height + int width = sourceData.Width; + int height = sourceData.Height; + + if (((width & 1) == 1) || ((height & 1) == 1) || + (width < 2) || (height < 2)) + { + throw new InvalidImagePropertiesException("Source image must have even width and height. Width and height can not be smaller than 2."); + } + + switch (bayerPattern) + { + case BayerPattern.GRBG: + ApplyGRBG(sourceData, destinationData); + break; + + case BayerPattern.BGGR: + ApplyBGGR(sourceData, destinationData); + break; + } + } + + #region GRBG pattern + private static unsafe void ApplyGRBG(UnmanagedImage sourceData, UnmanagedImage destinationData) + { + int width = sourceData.Width; + int height = sourceData.Height; + + int widthM1 = width - 1; + int heightM1 = height - 1; + + int srcStride = sourceData.Stride; + int dstStride = destinationData.Stride; + + int srcStrideP1 = srcStride + 1; + int srcStrideM1 = srcStride - 1; + int srcMStride = -srcStride; + int srcMStrideP1 = srcMStride + 1; + int srcMStrideM1 = srcMStride - 1; + + int srcOffset = srcStride - width; + int dstOffset = dstStride - width * 3; + + // do the job + byte* src = (byte*)sourceData.ImageData.ToPointer(); + byte* dst = (byte*)destinationData.ImageData.ToPointer(); + + // --- process the first line + + // . . . + // . G R + // . B G + dst[RGB.R] = src[1]; + dst[RGB.G] = (byte)((*src + src[srcStrideP1]) >> 1); + dst[RGB.B] = src[srcStride]; + + src++; + dst += 3; + + for (int x = 1; x < widthM1; x += 2) + { + // . . . + // G R G + // B G B + dst[RGB.R] = *src; + dst[RGB.G] = (byte)((src[srcStride] + src[-1] + src[1]) / 3); + dst[RGB.B] = (byte)((src[srcStrideM1] + src[srcStrideP1]) >> 1); + + src++; + dst += 3; + + // . . . + // R G R + // G B G + dst[RGB.R] = (byte)((src[-1] + src[1]) >> 1); + dst[RGB.G] = (byte)((*src + src[srcStrideM1] + src[srcStrideP1]) / 3); + dst[RGB.B] = src[srcStride]; + + src++; + dst += 3; + } + + // . . . + // G R . + // B G . + dst[RGB.R] = *src; + dst[RGB.G] = (byte)((src[-1] + src[srcStride]) >> 1); + dst[RGB.B] = src[srcStrideM1]; + + + // allign to the next line + src += srcOffset + 1; + dst += dstOffset + 3; + + // --- process all lines except the first one and the last one + for (int y = 1; y < heightM1; y += 2) + { + // . G R + // . B G + // . G R + dst[RGB.R] = (byte)((src[srcMStrideP1] + src[srcStrideP1]) >> 1); + dst[RGB.G] = (byte)((src[srcMStride] + src[srcStride] + src[1]) / 3); + dst[RGB.B] = *src; + + dst += dstStride; + src += srcStride; + + // ( y+1 pixel ) + // . B G + // . G R + // . B G + dst[RGB.R] = src[1]; + dst[RGB.G] = (byte)((*src + src[srcMStrideP1] + src[srcStrideP1]) / 3); + dst[RGB.B] = (byte)((src[srcMStride] + src[srcStride]) >> 1); + + dst -= dstStride; + src -= srcStride; + + src++; + dst += 3; + + for (int x = 1; x < widthM1; x += 2) + { + // G R G + // B G B + // G R G + dst[RGB.R] = (byte)((src[srcMStride] + src[srcStride]) >> 1); + dst[RGB.G] = (byte)((*src + src[srcMStrideM1] + src[srcMStrideP1] + + src[srcStrideM1] + src[srcStrideP1]) / 5); + dst[RGB.B] = (byte)((src[-1] + src[1]) >> 1); + + // ( y+1 pixel ) + // B G B + // G R G + // B G B + dst += dstStride; + src += srcStride; + + dst[RGB.R] = *src; + dst[RGB.G] = (byte)((src[srcMStride] + src[srcStride] + + src[-1] + src[1]) >> 2); + dst[RGB.B] = (byte)((src[srcMStrideM1] + src[srcMStrideP1] + + src[srcStrideM1] + src[srcStrideP1]) >> 2); + + // ( y+1 x+1 pixel ) + // G B G + // R G R + // G B G + dst += 3; + src++; + + dst[RGB.R] = (byte)((src[-1] + src[1]) >> 1); + dst[RGB.G] = (byte)((*src + src[srcMStrideM1] + src[srcMStrideP1] + + src[srcStrideM1] + src[srcStrideP1]) / 5); + dst[RGB.B] = (byte)((src[srcMStride] + src[srcStride]) >> 1); + + // ( x+1 pixel ) + // R G R + // G B G + // R G R + dst -= dstStride; + src -= srcStride; + + dst[RGB.R] = (byte)((src[srcMStrideM1] + src[srcMStrideP1] + + src[srcStrideM1] + src[srcStrideP1]) >> 2); + dst[RGB.G] = (byte)((src[srcMStride] + src[srcStride] + + src[-1] + src[1]) >> 2); + dst[RGB.B] = *src; + + dst += 3; + src++; + } + + // G R . + // B G . + // G R . + dst[RGB.R] = (byte)((src[srcMStride] + src[srcStride]) >> 1); + dst[RGB.G] = (byte)((*src + src[srcMStrideM1] + src[srcStrideM1]) / 3); + dst[RGB.B] = (byte)src[-1]; + + src += srcStride; + dst += dstStride; + + // ( y+1 pixel ) + // B G . + // G R . + // B G . + dst[RGB.R] = *src; + dst[RGB.G] = (byte)((src[srcMStride] + src[srcStride] + src[-1]) / 3); + dst[RGB.B] = (byte)((src[srcMStrideM1] + src[srcStrideM1]) >> 1); + + + // allign to the next line + src += srcOffset + 1; + dst += dstOffset + 3; + } + + // --- process the first line + + // . G R + // . B G + // . . . + dst[RGB.R] = src[srcMStrideP1]; + dst[RGB.G] = (byte)((src[srcMStride] + src[1]) >> 1); + dst[RGB.B] = *src; + + src++; + dst += 3; + + for (int x = 1; x < widthM1; x += 2) + { + // G R G + // B G B + // . . . + dst[RGB.R] = src[srcMStride]; + dst[RGB.G] = (byte)((src[srcMStrideM1] + src[srcMStrideP1] + *src) / 3); + dst[RGB.B] = (byte)((src[-1] + src[1]) >> 1); + + src++; + dst += 3; + + // R G R + // G B G + // . . . + dst[RGB.R] = (byte)((src[srcMStrideM1] + src[srcMStrideP1]) >> 1); + dst[RGB.G] = (byte)((src[srcMStride] + src[-1] + src[1]) / 3); + dst[RGB.B] = *src; + + src++; + dst += 3; + } + + // G R . + // B G . + // . . . + dst[RGB.R] = src[srcMStride]; + dst[RGB.G] = (byte)((*src + src[srcMStrideM1]) >> 1); + dst[RGB.B] = src[-1]; + } + #endregion + + #region BGGR pattern + private static unsafe void ApplyBGGR(UnmanagedImage sourceData, UnmanagedImage destinationData) + { + int width = sourceData.Width; + int height = sourceData.Height; + + int widthM1 = width - 1; + int heightM1 = height - 1; + + int srcStride = sourceData.Stride; + int dstStride = destinationData.Stride; + + int srcStrideP1 = srcStride + 1; + int srcStrideM1 = srcStride - 1; + int srcMStride = -srcStride; + int srcMStrideP1 = srcMStride + 1; + int srcMStrideM1 = srcMStride - 1; + + int srcOffset = srcStride - width; + int dstOffset = dstStride - width * 3; + + // do the job + byte* src = (byte*)sourceData.ImageData.ToPointer(); + byte* dst = (byte*)destinationData.ImageData.ToPointer(); + + // --- process the first line + + // . . . + // . B G + // . G R + dst[RGB.R] = src[srcStrideP1]; + dst[RGB.G] = (byte)((src[1] + src[srcStride]) >> 1); + dst[RGB.B] = *src; + + src++; + dst += 3; + + for (int x = 1; x < widthM1; x += 2) + { + // . . . + // B G B + // G R G + dst[RGB.R] = src[srcStride]; + dst[RGB.G] = (byte)((*src + src[srcStrideM1] + src[srcStrideP1]) / 3); + dst[RGB.B] = (byte)((src[-1] + src[1]) >> 1); + + src++; + dst += 3; + + // . . . + // G B G + // R G R + dst[RGB.R] = (byte)((src[srcStrideM1] + src[srcStrideP1]) >> 1); + dst[RGB.G] = (byte)((src[-1] + src[srcStride] + src[1]) / 3); + dst[RGB.B] = *src; + + src++; + dst += 3; + } + + // . . . + // B G . + // G R . + dst[RGB.R] = src[srcStride]; + dst[RGB.G] = (byte)((*src + src[srcStrideM1]) >> 1); + dst[RGB.B] = src[-1]; + + + // allign to the next line + src += srcOffset + 1; + dst += dstOffset + 3; + + // --- process all lines except the first one and the last one + for (int y = 1; y < heightM1; y += 2) + { + // . B G + // . G R + // . B G + dst[RGB.R] = src[1]; + dst[RGB.G] = (byte)((src[srcMStrideP1] + src[srcStrideP1] + *src) / 3); + dst[RGB.B] = (byte)((src[srcMStride] + src[srcStride]) >> 1); + + dst += dstStride; + src += srcStride; + + // ( y+1 pixel ) + // . G R + // . B G + // . G R + dst[RGB.R] = (byte)((src[srcMStrideP1] + src[srcStrideP1]) >> 1); + dst[RGB.G] = (byte)((src[1] + src[srcMStride] + src[srcStride]) / 3); + dst[RGB.B] = *src; + + dst -= dstStride; + src -= srcStride; + + src++; + dst += 3; + + for (int x = 1; x < widthM1; x += 2) + { + // B G B + // G R G + // B G B + dst[RGB.R] = *src; + dst[RGB.G] = (byte)((src[srcMStride] + src[srcStride] + src[-1] + src[1]) >> 2); + dst[RGB.B] = (byte)((src[srcMStrideM1] + src[srcMStrideP1] + src[srcStrideM1] + src[srcStrideP1]) >> 2); + + // ( y+1 pixel ) + // G R G + // B G B + // G R G + dst += dstStride; + src += srcStride; + + dst[RGB.R] = (byte)((src[srcMStride] + src[srcStride]) >> 1); + dst[RGB.G] = (byte)((*src + src[srcMStrideM1] + src[srcMStrideP1] + src[srcStrideM1] + src[srcStrideP1]) / 5); + dst[RGB.B] = (byte)((src[-1] + src[1]) >> 1); + + // ( y+1 x+1 pixel ) + // R G R + // G B G + // R G R + dst += 3; + src++; + + dst[RGB.R] = (byte)((src[srcMStrideM1] + src[srcMStrideP1] + src[srcStrideM1] + src[srcStrideP1]) >> 2); + dst[RGB.G] = (byte)((src[srcMStride] + src[srcStride] + src[-1] + src[1]) >> 2); + dst[RGB.B] = *src; + + // ( x+1 pixel ) + // G B G + // R G R + // G B G + dst -= dstStride; + src -= srcStride; + + dst[RGB.R] = (byte)((src[-1] + src[1]) >> 1); + dst[RGB.G] = (byte)((src[srcMStrideM1] + src[srcMStrideP1] + src[srcStrideM1] + src[srcStrideP1] + *src) / 5); + dst[RGB.B] = (byte)((src[srcMStride] + src[srcStride]) >> 1); + + dst += 3; + src++; + } + + // B G . + // G R . + // B G . + dst[RGB.R] = *src; + dst[RGB.G] = (byte)((src[srcMStride] + src[srcStride] + src[-1]) / 3); + dst[RGB.B] = (byte)((src[srcMStrideM1] + src[srcStrideM1]) >> 1); + src += srcStride; + dst += dstStride; + + // ( y+1 pixel ) + // G R . + // B G . + // G R . + dst[RGB.R] = (byte)((src[srcMStride] + src[srcStride]) >> 1); + dst[RGB.G] = (byte)((src[srcMStrideM1] + src[srcStrideM1] + *src) / 3); + dst[RGB.B] = src[-1]; + + // align to the next line + src += srcOffset + 1; + dst += dstOffset + 3; + } + + // --- process the first line + + // . B G + // . G R + // . . . + dst[RGB.R] = src[1]; + dst[RGB.G] = (byte)((src[srcMStrideP1] + *src) >> 1); + dst[RGB.B] = src[srcMStride]; + + src++; + dst += 3; + + for (int x = 1; x < widthM1; x += 2) + { + // B G B + // G R G + // . . . + dst[RGB.R] = *src; + dst[RGB.G] = (byte)((src[-1] + src[1] + src[srcMStride]) / 3); + dst[RGB.B] = (byte)((src[srcMStrideM1] + src[srcMStrideP1]) >> 1); + + src++; + dst += 3; + + // G B G + // R G R + // . . . + dst[RGB.R] = (byte)((src[-1] + src[1]) >> 1); + dst[RGB.G] = (byte)((*src + src[srcMStrideM1] + src[srcMStrideP1]) / 3); + dst[RGB.B] = src[srcMStride]; + + src++; + dst += 3; + } + + // B G . + // G R . + // . . . + dst[RGB.R] = *src; + dst[RGB.G] = (byte)((src[srcMStride] + src[-1]) >> 1); + dst[RGB.B] = src[srcMStrideM1]; + } + #endregion + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Color Filters/BrightnessCorrection.cs b/Sources/Accord.Imaging/AForge/Filters/Color Filters/BrightnessCorrection.cs new file mode 100644 index 0000000000..52cbde766 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Color Filters/BrightnessCorrection.cs @@ -0,0 +1,130 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2012 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + using AForge; + + /// + /// Brightness adjusting in RGB color space. + /// + /// + /// The filter operates in RGB color space and adjusts + /// pixels' brightness by increasing every pixel's RGB values by the specified + /// adjust value. The filter is based on + /// filter and simply sets all input ranges to (0, 255-) and + /// all output range to (, 255) in the case if the adjust value is positive. + /// If the adjust value is negative, then all input ranges are set to + /// (-, 255 ) and all output ranges are set to + /// ( 0, 255+). + /// + /// See documentation for more information about the base filter. + /// + /// The filter accepts 8 bpp grayscale and 24/32 bpp color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// BrightnessCorrection filter = new BrightnessCorrection( -50 ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + public class BrightnessCorrection : BaseInPlacePartialFilter + { + private LevelsLinear baseFilter = new LevelsLinear( ); + private int adjustValue; + + /// + /// Brightness adjust value, [-255, 255]. + /// + /// + /// Default value is set to 10, which corresponds to increasing + /// RGB values of each pixel by 10. + /// + public int AdjustValue + { + get { return adjustValue; } + set + { + adjustValue = Math.Max( -255, Math.Min( 255, value ) ); + + if ( adjustValue > 0 ) + { + baseFilter.InRed = baseFilter.InGreen = baseFilter.InBlue = baseFilter.InGray = + new IntRange( 0, 255 - adjustValue ); + baseFilter.OutRed = baseFilter.OutGreen = baseFilter.OutBlue = baseFilter.OutGray = + new IntRange( adjustValue, 255 ); + } + else + { + baseFilter.InRed = baseFilter.InGreen = baseFilter.InBlue = baseFilter.InGray = + new IntRange( -adjustValue, 255 ); + baseFilter.OutRed = baseFilter.OutGreen = baseFilter.OutBlue = baseFilter.OutGray = + new IntRange( 0, 255 + adjustValue ); + } + } + } + + /// + /// Format translations dictionary. + /// + /// + /// See + /// documentation for additional information. + /// + public override Dictionary FormatTranslations + { + get { return baseFilter.FormatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public BrightnessCorrection( ) + { + AdjustValue = 10; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Brightness adjust value. + /// + public BrightnessCorrection( int adjustValue ) + { + AdjustValue = adjustValue; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + baseFilter.ApplyInPlace( image, rect ); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Color Filters/ChannelFiltering.cs b/Sources/Accord.Imaging/AForge/Filters/Color Filters/ChannelFiltering.cs new file mode 100644 index 0000000000..cb2725d3f --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Color Filters/ChannelFiltering.cs @@ -0,0 +1,305 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + using AForge; + + /// + /// Channels filters. + /// + /// + /// The filter does color channels' filtering by clearing (filling with + /// specified values) values, which are inside/outside of the specified value's + /// range. The filter allows to fill certain ranges of RGB color channels with specified + /// value. + /// + /// The filter is similar to , but operates with not + /// entire pixels, but with their RGB values individually. This means that pixel itself may + /// not be filtered (will be kept), but one of its RGB values may be filtered if they are + /// inside/outside of specified range. + /// + /// The filter accepts 24 and 32 bpp color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// ChannelFiltering filter = new ChannelFiltering( ); + /// // set channels' ranges to keep + /// filter.Red = new IntRange( 0, 255 ); + /// filter.Green = new IntRange( 100, 255 ); + /// filter.Blue = new IntRange( 100, 255 ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + public class ChannelFiltering : BaseInPlacePartialFilter + { + private IntRange red = new IntRange(0, 255); + private IntRange green = new IntRange(0, 255); + private IntRange blue = new IntRange(0, 255); + + private byte fillR = 0; + private byte fillG = 0; + private byte fillB = 0; + + private bool redFillOutsideRange = true; + private bool greenFillOutsideRange = true; + private bool blueFillOutsideRange = true; + + private byte[] mapRed = new byte[256]; + private byte[] mapGreen = new byte[256]; + private byte[] mapBlue = new byte[256]; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + #region Public properties + + /// + /// Red channel's range. + /// + public IntRange Red + { + get { return red; } + set + { + red = value; + CalculateMap(red, fillR, redFillOutsideRange, mapRed); + } + } + + /// + /// Red fill value. + /// + public byte FillRed + { + get { return fillR; } + set + { + fillR = value; + CalculateMap(red, fillR, redFillOutsideRange, mapRed); + } + } + + /// + /// Green channel's range. + /// + public IntRange Green + { + get { return green; } + set + { + green = value; + CalculateMap(green, fillG, greenFillOutsideRange, mapGreen); + } + } + + /// + /// Green fill value. + /// + public byte FillGreen + { + get { return fillG; } + set + { + fillG = value; + CalculateMap(green, fillG, greenFillOutsideRange, mapGreen); + } + } + + /// + /// Blue channel's range. + /// + public IntRange Blue + { + get { return blue; } + set + { + blue = value; + CalculateMap(blue, fillB, blueFillOutsideRange, mapBlue); + } + } + + /// + /// Blue fill value. + /// + public byte FillBlue + { + get { return fillB; } + set + { + fillB = value; + CalculateMap(blue, fillB, blueFillOutsideRange, mapBlue); + } + } + + /// + /// Determines, if red channel should be filled inside or outside filtering range. + /// + /// + /// Default value is set to . + /// + public bool RedFillOutsideRange + { + get { return redFillOutsideRange; } + set + { + redFillOutsideRange = value; + CalculateMap(red, fillR, redFillOutsideRange, mapRed); + } + } + + /// + /// Determines, if green channel should be filled inside or outside filtering range. + /// + /// + /// Default value is set to . + /// + public bool GreenFillOutsideRange + { + get { return greenFillOutsideRange; } + set + { + greenFillOutsideRange = value; + CalculateMap(green, fillG, greenFillOutsideRange, mapGreen); + } + } + + /// + /// Determines, if blue channel should be filled inside or outside filtering range. + /// + /// + /// Default value is set to . + /// + public bool BlueFillOutsideRange + { + get { return blueFillOutsideRange; } + set + { + blueFillOutsideRange = value; + CalculateMap(blue, fillB, blueFillOutsideRange, mapBlue); + } + } + + #endregion + + + /// + /// Initializes a new instance of the class. + /// + /// + public ChannelFiltering() + : this(new IntRange(0, 255), new IntRange(0, 255), new IntRange(0, 255)) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Red channel's filtering range. + /// Green channel's filtering range. + /// Blue channel's filtering range. + /// + public ChannelFiltering(IntRange red, IntRange green, IntRange blue) + { + Red = red; + Green = green; + Blue = blue; + + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter(UnmanagedImage image, Rectangle rect) + { + // get pixel size + int pixelSize = (image.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4; + + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + int offset = image.Stride - rect.Width * pixelSize; + + // do the job + byte* ptr = (byte*)image.ImageData.ToPointer(); + + // allign pointer to the first pixel to process + ptr += (startY * image.Stride + startX * pixelSize); + + // for each row + for (int y = startY; y < stopY; y++) + { + // for each pixel + for (int x = startX; x < stopX; x++, ptr += pixelSize) + { + // red + ptr[RGB.R] = mapRed[ptr[RGB.R]]; + // green + ptr[RGB.G] = mapGreen[ptr[RGB.G]]; + // blue + ptr[RGB.B] = mapBlue[ptr[RGB.B]]; + } + ptr += offset; + } + } + + /// + /// Calculate filtering map. + /// + /// + /// Filtering range. + /// Fillter value. + /// Fill outside or inside the range. + /// Filtering map. + /// + private static void CalculateMap(IntRange range, byte fill, bool fillOutsideRange, byte[] map) + { + for (int i = 0; i < 256; i++) + { + if ((i >= range.Min) && (i <= range.Max)) + { + map[i] = (fillOutsideRange) ? (byte)i : fill; + } + else + { + map[i] = (fillOutsideRange) ? fill : (byte)i; + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Color Filters/ColorFiltering.cs b/Sources/Accord.Imaging/AForge/Filters/Color Filters/ColorFiltering.cs new file mode 100644 index 0000000000..38a01fbfa --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Color Filters/ColorFiltering.cs @@ -0,0 +1,220 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + using AForge; + + /// + /// Color filtering. + /// + /// + /// The filter filters pixels inside/outside of specified RGB color range - + /// it keeps pixels with colors inside/outside of specified range and fills the rest with + /// specified color. + /// + /// The filter accepts 24 and 32 bpp color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// ColorFiltering filter = new ColorFiltering( ); + /// // set color ranges to keep + /// filter.Red = new IntRange( 100, 255 ); + /// filter.Green = new IntRange( 0, 75 ); + /// filter.Blue = new IntRange( 0, 75 ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + /// + /// + public class ColorFiltering : BaseInPlacePartialFilter + { + private IntRange red = new IntRange( 0, 255 ); + private IntRange green = new IntRange( 0, 255 ); + private IntRange blue = new IntRange( 0, 255 ); + + private byte fillR = 0; + private byte fillG = 0; + private byte fillB = 0; + private bool fillOutsideRange = true; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + #region Public properties + + /// + /// Range of red color component. + /// + public IntRange Red + { + get { return red; } + set { red = value; } + } + + /// + /// Range of green color component. + /// + public IntRange Green + { + get { return green; } + set { green = value; } + } + + /// + /// Range of blue color component. + /// + public IntRange Blue + { + get { return blue; } + set { blue = value; } + } + + /// + /// Fill color used to fill filtered pixels. + /// + public RGB FillColor + { + get { return new RGB( fillR, fillG, fillB ); } + set + { + fillR = value.Red; + fillG = value.Green; + fillB = value.Blue; + } + } + + /// + /// Determines, if pixels should be filled inside or outside of specified + /// color ranges. + /// + /// + /// Default value is set to , which means + /// the filter removes colors outside of the specified range. + /// + public bool FillOutsideRange + { + get { return fillOutsideRange; } + set { fillOutsideRange = value; } + } + + #endregion + + /// + /// Initializes a new instance of the class. + /// + /// + public ColorFiltering( ) + { + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Red components filtering range. + /// Green components filtering range. + /// Blue components filtering range. + /// + public ColorFiltering( IntRange red, IntRange green, IntRange blue ) : + this( ) + { + this.red = red; + this.green = green; + this.blue = blue; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + // get pixel size + int pixelSize = ( image.PixelFormat == PixelFormat.Format24bppRgb ) ? 3 : 4; + + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + int offset = image.Stride - rect.Width * pixelSize; + + // do the job + byte* ptr = (byte*) image.ImageData.ToPointer( ); + byte r, g, b; + + // allign pointer to the first pixel to process + ptr += ( startY * image.Stride + startX * pixelSize ); + + // for each row + for ( int y = startY; y < stopY; y++ ) + { + // for each pixel + for ( int x = startX; x < stopX; x++, ptr += pixelSize ) + { + r = ptr[RGB.R]; + g = ptr[RGB.G]; + b = ptr[RGB.B]; + + // check pixel + if ( + ( r >= red.Min ) && ( r <= red.Max ) && + ( g >= green.Min ) && ( g <= green.Max ) && + ( b >= blue.Min ) && ( b <= blue.Max ) + ) + { + if ( !fillOutsideRange ) + { + ptr[RGB.R] = fillR; + ptr[RGB.G] = fillG; + ptr[RGB.B] = fillB; + } + } + else + { + if ( fillOutsideRange ) + { + ptr[RGB.R] = fillR; + ptr[RGB.G] = fillG; + ptr[RGB.B] = fillB; + } + } + } + ptr += offset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Color Filters/ColorRemapping.cs b/Sources/Accord.Imaging/AForge/Filters/Color Filters/ColorRemapping.cs new file mode 100644 index 0000000000..2a2db5137 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Color Filters/ColorRemapping.cs @@ -0,0 +1,267 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + using AForge; + + /// + /// Color remapping. + /// + /// + /// The filter allows to remap colors of the image. Unlike filter + /// the filter allow to do non-linear remapping. For each pixel of specified image the filter changes + /// its values (value of each color plane) to values, which are stored in remapping arrays by corresponding + /// indexes. For example, if pixel's RGB value equals to (32, 96, 128), the filter will change it to + /// ([32], [96], [128]). + /// + /// The filter accepts 8 bpp grayscale and 24/32 bpp color images for processing. + /// + /// Sample usage: + /// + /// // create map + /// byte[] map = new byte[256]; + /// for ( int i = 0; i < 256; i++ ) + /// { + /// map[i] = (byte) Math.Min( 255, Math.Pow( 2, (double) i / 32 ) ); + /// } + /// // create filter + /// ColorRemapping filter = new ColorRemapping( map, map, map ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class ColorRemapping : BaseInPlacePartialFilter + { + // color maps + private byte[] redMap; + private byte[] greenMap; + private byte[] blueMap; + private byte[] grayMap; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Remapping array for red color plane. + /// + /// + /// The remapping array should contain 256 remapping values. The remapping occurs + /// by changing pixel's red value r to [r]. + /// + /// A map should be array with 256 value. + /// + public byte[] RedMap + { + get { return redMap; } + set + { + // check the map + if ( ( value == null ) || ( value.Length != 256 ) ) + throw new ArgumentException( "A map should be array with 256 value." ); + + redMap = value; + } + } + + /// + /// Remapping array for green color plane. + /// + /// + /// The remapping array should contain 256 remapping values. The remapping occurs + /// by changing pixel's green value g to [g]. + /// + /// A map should be array with 256 value. + /// + public byte[] GreenMap + { + get { return greenMap; } + set + { + // check the map + if ( ( value == null ) || ( value.Length != 256 ) ) + throw new ArgumentException( "A map should be array with 256 value." ); + + greenMap = value; + } + } + + /// + /// Remapping array for blue color plane. + /// + /// + /// The remapping array should contain 256 remapping values. The remapping occurs + /// by changing pixel's blue value b to [b]. + /// + /// A map should be array with 256 value. + /// + public byte[] BlueMap + { + get { return blueMap; } + set + { + // check the map + if ( ( value == null ) || ( value.Length != 256 ) ) + throw new ArgumentException( "A map should be array with 256 value." ); + + blueMap = value; + } + } + + /// + /// Remapping array for gray color. + /// + /// + /// The remapping array should contain 256 remapping values. The remapping occurs + /// by changing pixel's value g to [g]. + /// + /// The gray map is for grayscale images only. + /// + /// A map should be array with 256 value. + /// + public byte[] GrayMap + { + get { return grayMap; } + set + { + // check the map + if ( ( value == null ) || ( value.Length != 256 ) ) + throw new ArgumentException( "A map should be array with 256 value." ); + + grayMap = value; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Initializes the filter without any remapping. All + /// pixel values are mapped to the same values. + /// + public ColorRemapping( ) + { + redMap = new byte[256]; + greenMap = new byte[256]; + blueMap = new byte[256]; + grayMap = new byte[256]; + + // fill the maps + for ( int i = 0; i < 256; i++ ) + { + redMap[i] = greenMap[i] = blueMap[i] = grayMap[i] = (byte) i; + } + + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Red map. + /// Green map. + /// Blue map. + /// + public ColorRemapping( byte[] redMap, byte[] greenMap, byte[] blueMap ) : this( ) + { + RedMap = redMap; + GreenMap = greenMap; + BlueMap = blueMap; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Gray map. + /// + /// This constructor is supposed for grayscale images. + /// + public ColorRemapping( byte[] grayMap ) : this( ) + { + GrayMap = grayMap; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + int pixelSize = Image.GetPixelFormatSize( image.PixelFormat ) / 8; + + // processing start and stop X,Y positions + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + int offset = image.Stride - rect.Width * pixelSize; + + // do the job + byte* ptr = (byte*) image.ImageData.ToPointer( ); + + // allign pointer to the first pixel to process + ptr += ( startY * image.Stride + startX * pixelSize ); + + if ( image.PixelFormat == PixelFormat.Format8bppIndexed ) + { + // grayscale image + for ( int y = startY; y < stopY; y++ ) + { + for ( int x = startX; x < stopX; x++, ptr++ ) + { + // gray + *ptr = grayMap[*ptr]; + } + ptr += offset; + } + } + else + { + // RGB image + for ( int y = startY; y < stopY; y++ ) + { + for ( int x = startX; x < stopX; x++, ptr += pixelSize ) + { + // red + ptr[RGB.R] = redMap[ptr[RGB.R]]; + // green + ptr[RGB.G] = greenMap[ptr[RGB.G]]; + // blue + ptr[RGB.B] = blueMap[ptr[RGB.B]]; + } + ptr += offset; + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Color Filters/ContrastCorrection.cs b/Sources/Accord.Imaging/AForge/Filters/Color Filters/ContrastCorrection.cs new file mode 100644 index 0000000000..69853bb1e --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Color Filters/ContrastCorrection.cs @@ -0,0 +1,137 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2012 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + using AForge; + + /// + /// Contrast adjusting in RGB color space. + /// + /// + /// The filter operates in RGB color space and adjusts + /// pixels' contrast value by increasing RGB values of bright pixel and decreasing + /// RGB values of dark pixels (or vise versa if contrast needs to be decreased). + /// The filter is based on + /// filter and simply sets all input ranges to (, 255-) and + /// all output range to (0, 255) in the case if the factor value is positive. + /// If the factor value is negative, then all input ranges are set to + /// (0, 255 ) and all output ranges are set to + /// (-, 255_). + /// + /// See documentation forr more information about the base filter. + /// + /// The filter accepts 8 bpp grayscale and 24/32 bpp color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// ContrastCorrection filter = new ContrastCorrection( 15 ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + public class ContrastCorrection : BaseInPlacePartialFilter + { + private LevelsLinear baseFilter = new LevelsLinear( ); + private int factor; + + /// + /// Contrast adjusting factor, [-127, 127]. + /// + /// + /// Factor which is used to adjust contrast. Factor values greater than + /// 0 increase contrast making light areas lighter and dark areas darker. Factor values + /// less than 0 decrease contrast - decreasing variety of contrast. + /// + /// Default value is set to 10. + /// + public int Factor + { + get { return factor; } + set + { + factor = Math.Max( -127, Math.Min( 127, value ) ); + + + if ( factor > 0 ) + { + baseFilter.InRed = baseFilter.InGreen = baseFilter.InBlue = baseFilter.InGray = + new IntRange( factor, 255 - factor ); + + baseFilter.OutRed = baseFilter.OutGreen = baseFilter.OutBlue = baseFilter.OutGray = + new IntRange( 0, 255 ); + } + else + { + baseFilter.OutRed = baseFilter.OutGreen = baseFilter.OutBlue = baseFilter.OutGray = + new IntRange( -factor, 255 + factor ); + + baseFilter.InRed = baseFilter.InGreen = baseFilter.InBlue = baseFilter.InGray = + new IntRange( 0, 255 ); + } + } + } + + /// + /// Format translations dictionary. + /// + /// + /// See + /// documentation for additional information. + /// + public override Dictionary FormatTranslations + { + get { return baseFilter.FormatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public ContrastCorrection( ) + { + Factor = 10; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Contrast adjusting factor. + /// + public ContrastCorrection( int factor ) + { + Factor = factor; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + baseFilter.ApplyInPlace( image, rect ); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Color Filters/ContrastStretch.cs b/Sources/Accord.Imaging/AForge/Filters/Color Filters/ContrastStretch.cs new file mode 100644 index 0000000000..db1512a80 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Color Filters/ContrastStretch.cs @@ -0,0 +1,171 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2010 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Contrast stretching filter. + /// + /// + /// Contrast stretching (or as it is often called normalization) is a simple image enhancement + /// technique that attempts to improve the contrast in an image by 'stretching' the range of intensity values + /// it contains to span a desired range of values, e.g. the full range of pixel values that the image type + /// concerned allows. It differs from the more sophisticated histogram equalization + /// in that it can only apply a linear scaling function to the image pixel values. + /// + /// The result of this filter may be achieved by using class, which allows to + /// get pixels' intensities histogram, and filter, which does linear correction + /// of pixel's intensities. + /// + /// The filter accepts 8 bpp grayscale and 24 bpp color images. + /// + /// Sample usage: + /// + /// // create filter + /// ContrastStretch filter = new ContrastStretch( ); + /// // process image + /// filter.ApplyInPlace( sourceImage ); + /// + /// + /// Source image: + /// + /// Result image: + /// + /// + /// + public class ContrastStretch : BaseInPlacePartialFilter + { + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + public ContrastStretch( ) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + int pixelSize = Image.GetPixelFormatSize( image.PixelFormat ) / 8; + + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + int stride = image.Stride; + int offset = stride - rect.Width * pixelSize; + + // levels linear correction filter is going to be used on STEP 2 + LevelsLinear levelsLinear = new LevelsLinear( ); + + // STEP 1 - search for min and max pixel values + byte* ptr = (byte*) image.ImageData.ToPointer( ); + + // check image format + if ( image.PixelFormat == PixelFormat.Format8bppIndexed ) + { + // allign pointer to the first pixel to process + ptr += ( startY * stride + startX ); + + byte min = 255; + byte max = 0; + + for ( int y = startY; y < stopY; y++ ) + { + for ( int x = startX; x < stopX; x++, ptr++ ) + { + byte value = *ptr; + + if ( value < min ) + min = value; + + if ( value > max ) + max = value; + } + ptr += offset; + } + + levelsLinear.InGray = new IntRange( min, max ); + } + else + { + // allign pointer to the first pixel to process + ptr += ( startY * stride + startX * pixelSize ); + + byte minR = 255, minG = 255, minB = 255; + byte maxR = 0, maxG = 0, maxB = 0; + + for ( int y = startY; y < stopY; y++ ) + { + for ( int x = startX; x < stopX; x++, ptr += pixelSize ) + { + // red + byte value = ptr[RGB.R]; + + if ( value < minR ) + minR = value; + + if ( value > maxR ) + maxR = value; + + // green + value = ptr[RGB.G]; + + if ( value < minG ) + minG = value; + + if ( value > maxG ) + maxG = value; + + // blue + value = ptr[RGB.B]; + + if ( value < minB ) + minB = value; + + if ( value > maxB ) + maxB = value; + } + ptr += offset; + } + + levelsLinear.InRed = new IntRange( minR, maxR ); + levelsLinear.InGreen = new IntRange( minG, maxG ); + levelsLinear.InBlue = new IntRange( minB, maxB ); + } + + // STEP 2 - run levels linear correction + levelsLinear.ApplyInPlace( image, rect ); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Color Filters/EuclideanColorFiltering.cs b/Sources/Accord.Imaging/AForge/Filters/Color Filters/EuclideanColorFiltering.cs new file mode 100644 index 0000000000..e7a728d3f --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Color Filters/EuclideanColorFiltering.cs @@ -0,0 +1,211 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2010 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Euclidean color filtering. + /// + /// + /// The filter filters pixels, which color is inside/outside + /// of RGB sphere with specified center and radius - it keeps pixels with + /// colors inside/outside of the specified sphere and fills the rest with + /// specified color. + /// + /// The filter accepts 24 and 32 bpp color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// EuclideanColorFiltering filter = new EuclideanColorFiltering( ); + /// // set center colol and radius + /// filter.CenterColor = new RGB( 215, 30, 30 ); + /// filter.Radius = 100; + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + public class EuclideanColorFiltering : BaseInPlacePartialFilter + { + private short radius = 100; + private RGB center = new RGB( 255, 255, 255 ); + private RGB fill = new RGB( 0, 0, 0 ); + private bool fillOutside = true; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// RGB sphere's radius, [0, 450]. + /// + /// + /// Default value is 100. + /// + public short Radius + { + get { return radius; } + set + { + radius = System.Math.Max( (short) 0, System.Math.Min( (short) 450, value ) ); + } + } + + /// + /// RGB sphere's center. + /// + /// + /// Default value is (255, 255, 255) - white color. + /// + public RGB CenterColor + { + get { return center; } + set { center = value; } + } + + /// + /// Fill color used to fill filtered pixels. + /// + public RGB FillColor + { + get { return fill; } + set { fill = value; } + } + + /// + /// Determines, if pixels should be filled inside or outside specified + /// RGB sphere. + /// + /// + /// Default value is set to , which means + /// the filter removes colors outside of the specified range. + /// + public bool FillOutside + { + get { return fillOutside; } + set { fillOutside = value; } + } + + + /// + /// Initializes a new instance of the class. + /// + /// + public EuclideanColorFiltering() + { + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// RGB sphere's center. + /// RGB sphere's radius. + /// + public EuclideanColorFiltering( RGB center, short radius ) : + this( ) + { + this.center = center; + this.radius = radius; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + // get pixel size + int pixelSize = ( image.PixelFormat == PixelFormat.Format24bppRgb ) ? 3 : 4; + + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + int offset = image.Stride - rect.Width * pixelSize; + int radius2 = radius * radius; + + int dr, dg, db; + // sphere's center + int cR = center.Red; + int cG = center.Green; + int cB = center.Blue; + // fill color + byte fR = fill.Red; + byte fG = fill.Green; + byte fB = fill.Blue; + + // do the job + byte* ptr = (byte*) image.ImageData.ToPointer( ); + + // allign pointer to the first pixel to process + ptr += ( startY * image.Stride + startX * pixelSize ); + + // for each row + for ( int y = startY; y < stopY; y++ ) + { + // for each pixel + for ( int x = startX; x < stopX; x++, ptr += pixelSize ) + { + dr = cR - ptr[RGB.R]; + dg = cG - ptr[RGB.G]; + db = cB - ptr[RGB.B]; + + // calculate the distance + if ( dr * dr + dg * dg + db * db <= radius2 ) + { + // inside sphere + if ( !fillOutside ) + { + ptr[RGB.R] = fR; + ptr[RGB.G] = fG; + ptr[RGB.B] = fB; + } + } + else + { + // outside sphere + if ( fillOutside ) + { + ptr[RGB.R] = fR; + ptr[RGB.G] = fG; + ptr[RGB.B] = fB; + } + } + } + ptr += offset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Color Filters/ExtractChannel.cs b/Sources/Accord.Imaging/AForge/Filters/Color Filters/ExtractChannel.cs new file mode 100644 index 0000000000..e823b028c --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Color Filters/ExtractChannel.cs @@ -0,0 +1,181 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Extract RGB channel from image. + /// + /// + /// Extracts specified channel of color image and returns + /// it as grayscale image. + /// + /// The filter accepts 24, 32, 48 and 64 bpp color images and produces + /// 8 (if source is 24 or 32 bpp image) or 16 (if source is 48 or 64 bpp image) + /// bpp grayscale image. + /// + /// Sample usage: + /// + /// // create filter + /// ExtractChannel filter = new ExtractChannel( RGB.G ); + /// // apply the filter + /// Bitmap channelImage = filter.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + public class ExtractChannel : BaseFilter + { + private short channel = RGB.R; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// ARGB channel to extract. + /// + /// + /// Default value is set to . + /// + /// Invalid channel is specified. + /// + public short Channel + { + get { return channel; } + set + { + if ( + ( value != RGB.R ) && ( value != RGB.G ) && + ( value != RGB.B ) && ( value != RGB.A ) + ) + { + throw new ArgumentException( "Invalid channel is specified." ); + } + channel = value; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public ExtractChannel( ) + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format48bppRgb] = PixelFormat.Format16bppGrayScale; + formatTranslations[PixelFormat.Format64bppArgb] = PixelFormat.Format16bppGrayScale; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// ARGB channel to extract. + /// + public ExtractChannel( short channel ) : this( ) + { + this.Channel = channel; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + /// Can not extract alpha channel from none ARGB image. The + /// exception is throw, when alpha channel is requested from RGB image. + /// + protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData ) + { + // get width and height + int width = sourceData.Width; + int height = sourceData.Height; + + int pixelSize = Image.GetPixelFormatSize( sourceData.PixelFormat ) / 8; + + if ( ( channel == RGB.A ) && ( pixelSize != 4 ) && ( pixelSize != 8 ) ) + { + throw new InvalidImagePropertiesException( "Can not extract alpha channel from none ARGB image." ); + } + + if ( pixelSize <= 4 ) + { + int srcOffset = sourceData.Stride - width * pixelSize; + int dstOffset = destinationData.Stride - width; + + // do the job + byte * src = (byte*) sourceData.ImageData.ToPointer( ); + byte * dst = (byte*) destinationData.ImageData.ToPointer( ); + + // allign source pointer to the required channel + src += channel; + + for ( int y = 0; y < height; y++ ) + { + for ( int x = 0; x < width; x++, src += pixelSize, dst++ ) + { + *dst = *src; + } + src += srcOffset; + dst += dstOffset; + } + } + else + { + pixelSize /= 2; + + byte* srcBase = (byte*) sourceData.ImageData.ToPointer( ); + byte* dstBase = (byte*) destinationData.ImageData.ToPointer( ); + int srcStride = sourceData.Stride; + int dstStride = destinationData.Stride; + + // for each line + for ( int y = 0; y < height; y++ ) + { + ushort* src = (ushort*) ( srcBase + y * srcStride ); + ushort* dst = (ushort*) ( dstBase + y * dstStride ); + + // allign source pointer to the required channel + src += channel; + + // for each pixel + for ( int x = 0; x < width; x++, src += pixelSize, dst++ ) + { + *dst = *src; + } + } + + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Color Filters/GammaCorrection.cs b/Sources/Accord.Imaging/AForge/Filters/Color Filters/GammaCorrection.cs new file mode 100644 index 0000000000..1e2d55e91 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Color Filters/GammaCorrection.cs @@ -0,0 +1,137 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Gamma correction filter. + /// + /// + /// The filter performs gamma correction + /// of specified image in RGB color space. Each pixels' value is converted using the Vout=Ving + /// equation, where g is gamma value. + /// + /// The filter accepts 8 bpp grayscale and 24 bpp color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// GammaCorrection filter = new GammaCorrection( 0.5 ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class GammaCorrection : BaseInPlacePartialFilter + { + private double gamma; + private byte[] table = new byte[256]; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Gamma value, [0.1, 5.0]. + /// + /// + /// Default value is set to 2.2. + /// + public double Gamma + { + get { return gamma; } + set + { + // get gamma value + gamma = Math.Max( 0.1, Math.Min( 5.0, value ) ); + + // calculate tranformation table + double g = 1 / gamma; + for ( int i = 0; i < 256; i++ ) + { + table[i] = (byte) Math.Min( 255, (int) ( Math.Pow( i / 255.0, g ) * 255 + 0.5 ) ); + } + } + } + + + /// + /// Initializes a new instance of the class. + /// + public GammaCorrection( ) : this ( 2.2 ) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Gamma value. + /// + public GammaCorrection( double gamma ) + { + Gamma = gamma; + + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + } + + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + int pixelSize = ( image.PixelFormat == PixelFormat.Format8bppIndexed ) ? 1 : 3; + + // processing start and stop X,Y positions + int startX = rect.Left * pixelSize; + int startY = rect.Top; + int stopX = startX + rect.Width * pixelSize; + int stopY = startY + rect.Height; + int offset = image.Stride - rect.Width * pixelSize; + + // do the job + byte* ptr = (byte*) image.ImageData.ToPointer( ); + + // allign pointer to the first pixel to process + ptr += ( startY * image.Stride + startX ); + + // gamma correction + for ( int y = startY; y < stopY; y++ ) + { + for ( int x = startX; x < stopX; x++, ptr++ ) + { + // process each pixel + *ptr = table[*ptr]; + } + ptr += offset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Color Filters/Grayscale.cs b/Sources/Accord.Imaging/AForge/Filters/Color Filters/Grayscale.cs new file mode 100644 index 0000000000..2e4e99192 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Color Filters/Grayscale.cs @@ -0,0 +1,249 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Base class for image grayscaling. + /// + /// + /// This class is the base class for image grayscaling. Other + /// classes should inherit from this class and specify RGB + /// coefficients used for color image conversion to grayscale. + /// + /// The filter accepts 24, 32, 48 and 64 bpp color images and produces + /// 8 (if source is 24 or 32 bpp image) or 16 (if source is 48 or 64 bpp image) + /// bpp grayscale image. + /// + /// Sample usage: + /// + /// // create grayscale filter (BT709) + /// Grayscale filter = new Grayscale( 0.2125, 0.7154, 0.0721 ); + /// // apply the filter + /// Bitmap grayImage = filter.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + /// + public class Grayscale : BaseFilter + { + /// + /// Set of predefined common grayscaling algorithms, which have + /// already initialized grayscaling coefficients. + /// + /// + public static class CommonAlgorithms + { + /// + /// Grayscale image using BT709 algorithm. + /// + /// + /// + /// The instance uses BT709 algorithm to convert color image + /// to grayscale. The conversion coefficients are: + /// + /// Red: 0.2125; + /// Green: 0.7154; + /// Blue: 0.0721. + /// + /// + /// Sample usage: + /// + /// + /// // apply the filter + /// Bitmap grayImage = Grayscale.CommonAlgorithms.BT709.Apply( image ); + /// + /// + /// + public static readonly Grayscale BT709 = new Grayscale(0.2125, 0.7154, 0.0721); + + /// + /// Grayscale image using R-Y algorithm. + /// + /// + /// + /// The instance uses R-Y algorithm to convert color image + /// to grayscale. The conversion coefficients are: + /// + /// Red: 0.5; + /// Green: 0.419; + /// Blue: 0.081. + /// + /// + /// Sample usage: + /// + /// + /// // apply the filter + /// Bitmap grayImage = Grayscale.CommonAlgorithms.RMY.Apply( image ); + /// + /// + /// + public static readonly Grayscale RMY = new Grayscale(0.5000, 0.4190, 0.0810); + + /// + /// Grayscale image using Y algorithm. + /// + /// + /// + /// The instance uses Y algorithm to convert color image + /// to grayscale. The conversion coefficients are: + /// + /// Red: 0.299; + /// Green: 0.587; + /// Blue: 0.114. + /// + /// + /// Sample usage: + /// + /// + /// // apply the filter + /// Bitmap grayImage = Grayscale.CommonAlgorithms.Y.Apply( image ); + /// + /// + /// + public static readonly Grayscale Y = new Grayscale(0.2990, 0.5870, 0.1140); + } + + + /// + /// Portion of red channel's value to use during conversion from RGB to grayscale. + /// + /// + public readonly double RedCoefficient; + + /// + /// Portion of green channel's value to use during conversion from RGB to grayscale. + /// + /// + public readonly double GreenCoefficient; + + /// + /// Portion of blue channel's value to use during conversion from RGB to grayscale. + /// + /// + public readonly double BlueCoefficient; + + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Red coefficient. + /// Green coefficient. + /// Blue coefficient. + /// + public Grayscale(double cr, double cg, double cb) + { + RedCoefficient = cr; + GreenCoefficient = cg; + BlueCoefficient = cb; + + // initialize format translation dictionary + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format48bppRgb] = PixelFormat.Format16bppGrayScale; + formatTranslations[PixelFormat.Format64bppArgb] = PixelFormat.Format16bppGrayScale; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData) + { + // get width and height + int width = sourceData.Width; + int height = sourceData.Height; + PixelFormat srcPixelFormat = sourceData.PixelFormat; + + if ( + (srcPixelFormat == PixelFormat.Format24bppRgb) || + (srcPixelFormat == PixelFormat.Format32bppRgb) || + (srcPixelFormat == PixelFormat.Format32bppArgb)) + { + int pixelSize = (srcPixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4; + int srcOffset = sourceData.Stride - width * pixelSize; + int dstOffset = destinationData.Stride - width; + + int rc = (int)(0x10000 * RedCoefficient); + int gc = (int)(0x10000 * GreenCoefficient); + int bc = (int)(0x10000 * BlueCoefficient); + + // make sure sum of coefficients equals to 0x10000 + while (rc + gc + bc < 0x10000) + { + bc++; + } + + // do the job + byte* src = (byte*)sourceData.ImageData.ToPointer(); + byte* dst = (byte*)destinationData.ImageData.ToPointer(); + + // for each line + for (int y = 0; y < height; y++) + { + // for each pixel + for (int x = 0; x < width; x++, src += pixelSize, dst++) + { + *dst = (byte)((rc * src[RGB.R] + gc * src[RGB.G] + bc * src[RGB.B]) >> 16); + } + src += srcOffset; + dst += dstOffset; + } + } + else + { + int pixelSize = (srcPixelFormat == PixelFormat.Format48bppRgb) ? 3 : 4; + byte* srcBase = (byte*)sourceData.ImageData.ToPointer(); + byte* dstBase = (byte*)destinationData.ImageData.ToPointer(); + int srcStride = sourceData.Stride; + int dstStride = destinationData.Stride; + + // for each line + for (int y = 0; y < height; y++) + { + ushort* src = (ushort*)(srcBase + y * srcStride); + ushort* dst = (ushort*)(dstBase + y * dstStride); + + // for each pixel + for (int x = 0; x < width; x++, src += pixelSize, dst++) + { + *dst = (ushort)(RedCoefficient * src[RGB.R] + GreenCoefficient * src[RGB.G] + BlueCoefficient * src[RGB.B]); + } + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Color Filters/GrayscaleBT709.cs b/Sources/Accord.Imaging/AForge/Filters/Color Filters/GrayscaleBT709.cs new file mode 100644 index 0000000000..34ea7e9e1 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Color Filters/GrayscaleBT709.cs @@ -0,0 +1,39 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Grayscale image using BT709 algorithm. + /// + /// + /// The class uses BT709 algorithm to convert color image + /// to grayscale. The conversion coefficients are: + /// + /// Red: 0.2125; + /// Green: 0.7154; + /// Blue: 0.0721. + /// + /// + /// + /// + /// + /// + /// + [Obsolete( "Use Grayscale.CommonAlgorithms.BT709 object instead" )] + public sealed class GrayscaleBT709 : Grayscale + { + /// + /// Initializes a new instance of the class. + /// + public GrayscaleBT709( ) : base( 0.2125, 0.7154, 0.0721 ) { } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Color Filters/GrayscaleRMY.cs b/Sources/Accord.Imaging/AForge/Filters/Color Filters/GrayscaleRMY.cs new file mode 100644 index 0000000000..471dd0036 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Color Filters/GrayscaleRMY.cs @@ -0,0 +1,39 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Grayscale image using R-Y algorithm. + /// + /// + /// The class uses R-Y algorithm to convert color image + /// to grayscale. The conversion coefficients are: + /// + /// Red: 0.5; + /// Green: 0.419; + /// Blue: 0.081. + /// + /// + /// + /// + /// + /// + /// + [Obsolete( "Use Grayscale.CommonAlgorithms.RMY object instead" )] + public sealed class GrayscaleRMY : Grayscale + { + /// + /// Initializes a new instance of the class. + /// + public GrayscaleRMY( ) : base( 0.5, 0.419, 0.081 ) { } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Color Filters/GrayscaleToRGB.cs b/Sources/Accord.Imaging/AForge/Filters/Color Filters/GrayscaleToRGB.cs new file mode 100644 index 0000000000..1203573b7 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Color Filters/GrayscaleToRGB.cs @@ -0,0 +1,91 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.comm +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Convert grayscale image to RGB. + /// + /// + /// The filter creates color image from specified grayscale image + /// initializing all RGB channels to the same value - pixel's intensity of grayscale image. + /// + /// The filter accepts 8 bpp grayscale images and produces + /// 24 bpp RGB image. + /// + /// Sample usage: + /// + /// // create filter + /// GrayscaleToRGB filter = new GrayscaleToRGB( ); + /// // apply the filter + /// Bitmap rgbImage = filter.Apply( image ); + /// + /// + /// + /// + public sealed class GrayscaleToRGB : BaseFilter + { + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public GrayscaleToRGB( ) + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format24bppRgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData ) + { + // get width and height + int width = sourceData.Width; + int height = sourceData.Height; + + int srcOffset = sourceData.Stride - width; + int dstOffset = destinationData.Stride - width * 3; + + // do the job + byte * src = (byte*) sourceData.ImageData.ToPointer( ); + byte * dst = (byte*) destinationData.ImageData.ToPointer( ); + + // for each line + for ( int y = 0; y < height; y++ ) + { + // for each pixel + for ( int x = 0; x < width; x++, src++, dst += 3 ) + { + dst[RGB.R] = dst[RGB.G] = dst[RGB.B] = *src; + } + src += srcOffset; + dst += dstOffset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Color Filters/GrayscaleY.cs b/Sources/Accord.Imaging/AForge/Filters/Color Filters/GrayscaleY.cs new file mode 100644 index 0000000000..77d8c8531 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Color Filters/GrayscaleY.cs @@ -0,0 +1,39 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Grayscale image using Y algorithm. + /// + /// + /// The class uses Y algorithm to convert color image + /// to grayscale. The conversion coefficients are: + /// + /// Red: 0.299; + /// Green: 0.587; + /// Blue: 0.114. + /// + /// + /// + /// + /// + /// + /// + [Obsolete( "Use Grayscale.CommonAlgorithms.Y object instead" )] + public sealed class GrayscaleY : Grayscale + { + /// + /// Initializes a new instance of the class. + /// + public GrayscaleY( ) : base( 0.299, 0.587, 0.114 ) { } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Color Filters/HistogramEqualization.cs b/Sources/Accord.Imaging/AForge/Filters/Color Filters/HistogramEqualization.cs new file mode 100644 index 0000000000..a15d901b3 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Color Filters/HistogramEqualization.cs @@ -0,0 +1,194 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright +// Andrew Kirillov (andrew.kirillov@gmail.com), +// Mladen Prajdic (spirit1_fe@yahoo.com) +// 2005-2008 +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Histogram equalization filter. + /// + /// + /// The filter does histogram equalization increasing local contrast in images. The effect + /// of histogram equalization can be better seen on images, where pixel values have close contrast values. + /// Through this adjustment, pixels intensities can be better distributed on the histogram. This allows for + /// areas of lower local contrast to gain a higher contrast without affecting the global contrast. + /// + /// + /// The filter accepts 8 bpp grayscale images and 24/32 bpp + /// color images for processing. + /// + /// For color images the histogram equalization is applied to each color plane separately. + /// + /// Sample usage: + /// + /// // create filter + /// HistogramEqualization filter = new HistogramEqualization( ); + /// // process image + /// filter.ApplyInPlace( sourceImage ); + /// + /// + /// Source image: + /// + /// Result image: + /// + /// + /// + public class HistogramEqualization : BaseInPlacePartialFilter + { + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + public HistogramEqualization( ) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + int pixelSize = ( image.PixelFormat == PixelFormat.Format8bppIndexed ) ? 1 : + ( image.PixelFormat == PixelFormat.Format24bppRgb ) ? 3 : 4; + + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + int stride = image.Stride; + int offset = stride - rect.Width * pixelSize; + + int numberOfPixels = ( stopX - startX ) * ( stopY - startY ); + + // check image format + if ( image.PixelFormat == PixelFormat.Format8bppIndexed ) + { + // grayscale image + byte* ptr = (byte*) image.ImageData.ToPointer( ); + // allign pointer to the first pixel to process + ptr += ( startY * stride + startX ); + + // calculate histogram + int[] histogram = new int[256]; + for ( int y = startY; y < stopY; y++ ) + { + for ( int x = startX; x < stopX; x++, ptr++ ) + { + histogram[*ptr]++; + } + ptr += offset; + } + + // calculate new intensity levels + byte[] equalizedHistogram = Equalize( histogram, numberOfPixels ); + + // update pixels' intensities + ptr = (byte*) image.ImageData.ToPointer( ); + // allign pointer to the first pixel to process + ptr += ( startY * stride + startX ); + + for ( int y = startY; y < stopY; y++ ) + { + for ( int x = startX; x < stopX; x++, ptr++ ) + { + *ptr = equalizedHistogram[*ptr]; + } + ptr += offset; + } + } + else + { + // color image + byte* ptr = (byte*) image.ImageData.ToPointer( ); + // allign pointer to the first pixel to process + ptr += ( startY * stride + startX * pixelSize ); + + // calculate histogram + int[] histogramR = new int[256]; + int[] histogramG = new int[256]; + int[] histogramB = new int[256]; + + for ( int y = startY; y < stopY; y++ ) + { + for ( int x = startX; x < stopX; x++, ptr += pixelSize ) + { + histogramR[ptr[RGB.R]]++; + histogramG[ptr[RGB.G]]++; + histogramB[ptr[RGB.B]]++; + } + ptr += offset; + } + + // calculate new intensity levels + byte[] equalizedHistogramR = Equalize( histogramR, numberOfPixels ); + byte[] equalizedHistogramG = Equalize( histogramG, numberOfPixels ); + byte[] equalizedHistogramB = Equalize( histogramB, numberOfPixels ); + + // update pixels' intensities + ptr = (byte*) image.ImageData.ToPointer( ); + // allign pointer to the first pixel to process + ptr += ( startY * stride + startX * pixelSize ); + + for ( int y = startY; y < stopY; y++ ) + { + for ( int x = startX; x < stopX; x++, ptr += pixelSize ) + { + ptr[RGB.R] = equalizedHistogramR[ptr[RGB.R]]; + ptr[RGB.G] = equalizedHistogramG[ptr[RGB.G]]; + ptr[RGB.B] = equalizedHistogramB[ptr[RGB.B]]; + } + ptr += offset; + } + } + } + + + // Histogram + private static byte[] Equalize(int[] histogram, long numPixel) + { + byte[] equalizedHistogram = new byte[256]; + float coef = 255.0f / numPixel; + + // calculate the first value + float prev = histogram[0] * coef; + equalizedHistogram[0] = (byte) prev; + + // calcualte the rest of values + for ( int i = 1; i < 256; i++ ) + { + prev += histogram[i] * coef; + equalizedHistogram[i] = (byte) prev; + } + + return equalizedHistogram; + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Color Filters/Invert.cs b/Sources/Accord.Imaging/AForge/Filters/Color Filters/Invert.cs new file mode 100644 index 0000000000..fa477cbe4 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Color Filters/Invert.cs @@ -0,0 +1,123 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Invert image. + /// + /// + /// The filter inverts colored and grayscale images. + /// + /// The filter accepts 8, 16 bpp grayscale and 24, 48 bpp color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// Invert filter = new Invert( ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public sealed class Invert : BaseInPlacePartialFilter + { + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + public Invert( ) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format16bppGrayScale] = PixelFormat.Format16bppGrayScale; + formatTranslations[PixelFormat.Format48bppRgb] = PixelFormat.Format48bppRgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + int pixelSize = ( ( image.PixelFormat == PixelFormat.Format8bppIndexed ) || + ( image.PixelFormat == PixelFormat.Format16bppGrayScale ) ) ? 1 : 3; + + int startY = rect.Top; + int stopY = startY + rect.Height; + + int startX = rect.Left * pixelSize; + int stopX = startX + rect.Width * pixelSize; + + byte* basePtr = (byte*) image.ImageData.ToPointer( ); + + if ( + ( image.PixelFormat == PixelFormat.Format8bppIndexed ) || + ( image.PixelFormat == PixelFormat.Format24bppRgb ) ) + { + int offset = image.Stride - ( stopX - startX ); + + // allign pointer to the first pixel to process + byte* ptr = basePtr + ( startY * image.Stride + rect.Left * pixelSize ); + + // invert + for ( int y = startY; y < stopY; y++ ) + { + for ( int x = startX; x < stopX; x++, ptr++ ) + { + // ivert each pixel + *ptr = (byte) ( 255 - *ptr ); + } + ptr += offset; + } + } + else + { + int stride = image.Stride; + + // allign pointer to the first pixel to process + basePtr += ( startY * image.Stride + rect.Left * pixelSize * 2 ); + + // invert + for ( int y = startY; y < stopY; y++ ) + { + ushort* ptr = (ushort*) ( basePtr ); + + for ( int x = startX; x < stopX; x++, ptr++ ) + { + // ivert each pixel + *ptr = (ushort) ( 65535 - *ptr ); + } + basePtr += stride; + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Color Filters/LevelsLinear.cs b/Sources/Accord.Imaging/AForge/Filters/Color Filters/LevelsLinear.cs new file mode 100644 index 0000000000..191140ae0 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Color Filters/LevelsLinear.cs @@ -0,0 +1,321 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2010 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + using AForge; + + /// + /// Linear correction of RGB channels. + /// + /// + /// The filter performs linear correction of RGB channels by mapping specified + /// channels' input ranges to output ranges. It is similar to the + /// , but the remapping is linear. + /// + /// The filter accepts 8 bpp grayscale and 24/32 bpp color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// LevelsLinear filter = new LevelsLinear( ); + /// // set ranges + /// filter.InRed = new IntRange( 30, 230 ); + /// filter.InGreen = new IntRange( 50, 240 ); + /// filter.InBlue = new IntRange( 10, 210 ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + public class LevelsLinear : BaseInPlacePartialFilter + { + private IntRange inRed = new IntRange(0, 255); + private IntRange inGreen = new IntRange(0, 255); + private IntRange inBlue = new IntRange(0, 255); + + private IntRange outRed = new IntRange(0, 255); + private IntRange outGreen = new IntRange(0, 255); + private IntRange outBlue = new IntRange(0, 255); + + private byte[] mapRed = new byte[256]; + private byte[] mapGreen = new byte[256]; + private byte[] mapBlue = new byte[256]; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + #region Public Propertis + + /// + /// Red component's input range. + /// + public IntRange InRed + { + get { return inRed; } + set + { + inRed = value; + CalculateMap(inRed, outRed, mapRed); + } + } + + /// + /// Green component's input range. + /// + public IntRange InGreen + { + get { return inGreen; } + set + { + inGreen = value; + CalculateMap(inGreen, outGreen, mapGreen); + } + } + + /// + /// Blue component's input range. + /// + public IntRange InBlue + { + get { return inBlue; } + set + { + inBlue = value; + CalculateMap(inBlue, outBlue, mapBlue); + } + } + + /// + /// Gray component's input range. + /// + public IntRange InGray + { + get { return inGreen; } + set + { + inGreen = value; + CalculateMap(inGreen, outGreen, mapGreen); + } + } + + /// + /// Input range for RGB components. + /// + /// + /// The property allows to set red, green and blue input ranges to the same value. + /// + public IntRange Input + { + set + { + inRed = inGreen = inBlue = value; + CalculateMap(inRed, outRed, mapRed); + CalculateMap(inGreen, outGreen, mapGreen); + CalculateMap(inBlue, outBlue, mapBlue); + } + } + + /// + /// Red component's output range. + /// + public IntRange OutRed + { + get { return outRed; } + set + { + outRed = value; + CalculateMap(inRed, outRed, mapRed); + } + } + + /// + /// Green component's output range. + /// + public IntRange OutGreen + { + get { return outGreen; } + set + { + outGreen = value; + CalculateMap(inGreen, outGreen, mapGreen); + } + } + + /// + /// Blue component's output range. + /// + public IntRange OutBlue + { + get { return outBlue; } + set + { + outBlue = value; + CalculateMap(inBlue, outBlue, mapBlue); + } + } + + /// + /// Gray component's output range. + /// + public IntRange OutGray + { + get { return outGreen; } + set + { + outGreen = value; + CalculateMap(inGreen, outGreen, mapGreen); + } + } + + /// + /// Output range for RGB components. + /// + /// + /// The property allows to set red, green and blue output ranges to the same value. + /// + public IntRange Output + { + set + { + outRed = outGreen = outBlue = value; + CalculateMap(inRed, outRed, mapRed); + CalculateMap(inGreen, outGreen, mapGreen); + CalculateMap(inBlue, outBlue, mapBlue); + } + } + + #endregion + + + /// + /// Initializes a new instance of the class. + /// + public LevelsLinear() + { + CalculateMap(inRed, outRed, mapRed); + CalculateMap(inGreen, outGreen, mapGreen); + CalculateMap(inBlue, outBlue, mapBlue); + + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter(UnmanagedImage image, Rectangle rect) + { + int pixelSize = Image.GetPixelFormatSize(image.PixelFormat) / 8; + + // processing start and stop X,Y positions + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + int offset = image.Stride - rect.Width * pixelSize; + + // do the job + byte* ptr = (byte*)image.ImageData.ToPointer(); + + // allign pointer to the first pixel to process + ptr += (startY * image.Stride + startX * pixelSize); + + if (image.PixelFormat == PixelFormat.Format8bppIndexed) + { + // grayscale image + for (int y = startY; y < stopY; y++) + { + for (int x = startX; x < stopX; x++, ptr++) + { + // gray + *ptr = mapGreen[*ptr]; + } + ptr += offset; + } + } + else + { + // RGB image + for (int y = startY; y < stopY; y++) + { + for (int x = startX; x < stopX; x++, ptr += pixelSize) + { + // red + ptr[RGB.R] = mapRed[ptr[RGB.R]]; + // green + ptr[RGB.G] = mapGreen[ptr[RGB.G]]; + // blue + ptr[RGB.B] = mapBlue[ptr[RGB.B]]; + } + ptr += offset; + } + } + } + + + /// + /// Calculate conversion map. + /// + /// + /// Input range. + /// Output range. + /// Conversion map. + /// + private static void CalculateMap(IntRange inRange, IntRange outRange, byte[] map) + { + double k = 0, b = 0; + + if (inRange.Max != inRange.Min) + { + k = (double)(outRange.Max - outRange.Min) / (double)(inRange.Max - inRange.Min); + b = (double)(outRange.Min) - k * inRange.Min; + } + + for (int i = 0; i < 256; i++) + { + byte v = (byte)i; + + if (v >= inRange.Max) + v = (byte)outRange.Max; + else if (v <= inRange.Min) + v = (byte)outRange.Min; + else + v = (byte)(k * v + b); + + map[i] = v; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Color Filters/LevelsLinear16bpp.cs b/Sources/Accord.Imaging/AForge/Filters/Color Filters/LevelsLinear16bpp.cs new file mode 100644 index 0000000000..ad303894b --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Color Filters/LevelsLinear16bpp.cs @@ -0,0 +1,313 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2010 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + using AForge; + + /// + /// Linear correction of RGB channels for images, which have 16 bpp planes (16 bit gray images or 48/64 bit colour images). + /// + /// + /// The filter performs linear correction of RGB channels by mapping specified + /// channels' input ranges to output ranges. This version of the filter processes only images + /// with 16 bpp colour planes. See for 8 bpp version. + /// + /// The filter accepts 16 bpp grayscale and 48/64 bpp colour images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// LevelsLinear16bpp filter = new LevelsLinear16bpp( ); + /// // set ranges + /// filter.InRed = new IntRange( 3000, 42000 ); + /// filter.InGreen = new IntRange( 5000, 37500 ); + /// filter.InBlue = new IntRange( 1000, 60000 ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// + /// + /// + public class LevelsLinear16bpp : BaseInPlacePartialFilter + { + private IntRange inRed = new IntRange(0, 65535); + private IntRange inGreen = new IntRange(0, 65535); + private IntRange inBlue = new IntRange(0, 65535); + + private IntRange outRed = new IntRange(0, 65535); + private IntRange outGreen = new IntRange(0, 65535); + private IntRange outBlue = new IntRange(0, 65535); + + private ushort[] mapRed = new ushort[65536]; + private ushort[] mapGreen = new ushort[65536]; + private ushort[] mapBlue = new ushort[65536]; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + #region Public Propertis + + /// + /// Red component's input range. + /// + public IntRange InRed + { + get { return inRed; } + set + { + inRed = value; + CalculateMap(inRed, outRed, mapRed); + } + } + + /// + /// Green component's input range. + /// + public IntRange InGreen + { + get { return inGreen; } + set + { + inGreen = value; + CalculateMap(inGreen, outGreen, mapGreen); + } + } + + /// + /// Blue component's input range. + /// + public IntRange InBlue + { + get { return inBlue; } + set + { + inBlue = value; + CalculateMap(inBlue, outBlue, mapBlue); + } + } + + /// + /// Gray component's input range. + /// + public IntRange InGray + { + get { return inGreen; } + set + { + inGreen = value; + CalculateMap(inGreen, outGreen, mapGreen); + } + } + + /// + /// Input range for RGB components. + /// + /// + /// The property allows to set red, green and blue input ranges to the same value. + /// + public IntRange Input + { + set + { + inRed = inGreen = inBlue = value; + CalculateMap(inRed, outRed, mapRed); + CalculateMap(inGreen, outGreen, mapGreen); + CalculateMap(inBlue, outBlue, mapBlue); + } + } + + /// + /// Red component's output range. + /// + public IntRange OutRed + { + get { return outRed; } + set + { + outRed = value; + CalculateMap(inRed, outRed, mapRed); + } + } + + /// + /// Green component's output range. + /// + public IntRange OutGreen + { + get { return outGreen; } + set + { + outGreen = value; + CalculateMap(inGreen, outGreen, mapGreen); + } + } + + /// + /// Blue component's output range. + /// + public IntRange OutBlue + { + get { return outBlue; } + set + { + outBlue = value; + CalculateMap(inBlue, outBlue, mapBlue); + } + } + + /// + /// Gray component's output range. + /// + public IntRange OutGray + { + get { return outGreen; } + set + { + outGreen = value; + CalculateMap(inGreen, outGreen, mapGreen); + } + } + + /// + /// Output range for RGB components. + /// + /// + /// The property allows to set red, green and blue output ranges to the same value. + /// + public IntRange Output + { + set + { + outRed = outGreen = outBlue = value; + CalculateMap(inRed, outRed, mapRed); + CalculateMap(inGreen, outGreen, mapGreen); + CalculateMap(inBlue, outBlue, mapBlue); + } + } + + #endregion + + + /// + /// Initializes a new instance of the class. + /// + public LevelsLinear16bpp() + { + CalculateMap(inRed, outRed, mapRed); + CalculateMap(inGreen, outGreen, mapGreen); + CalculateMap(inBlue, outBlue, mapBlue); + + formatTranslations[PixelFormat.Format16bppGrayScale] = PixelFormat.Format16bppGrayScale; + formatTranslations[PixelFormat.Format48bppRgb] = PixelFormat.Format48bppRgb; + formatTranslations[PixelFormat.Format64bppArgb] = PixelFormat.Format64bppArgb; + formatTranslations[PixelFormat.Format64bppPArgb] = PixelFormat.Format64bppPArgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter(UnmanagedImage image, Rectangle rect) + { + int pixelSize = Image.GetPixelFormatSize(image.PixelFormat) / 16; + + // processing start and stop X,Y positions + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + + // do the job + byte* basePtr = (byte*)image.ImageData.ToPointer(); + + if (image.PixelFormat == PixelFormat.Format16bppGrayScale) + { + // grayscale image + for (int y = startY; y < stopY; y++) + { + ushort* ptr = (ushort*)(basePtr + y * image.Stride) + startX; + + for (int x = startX; x < stopX; x++, ptr++) + { + // gray + *ptr = mapGreen[*ptr]; + } + } + } + else + { + // RGB image + for (int y = startY; y < stopY; y++) + { + ushort* ptr = (ushort*)(basePtr + y * image.Stride) + startX * pixelSize; + + for (int x = startX; x < stopX; x++, ptr += pixelSize) + { + // red + ptr[RGB.R] = mapRed[ptr[RGB.R]]; + // green + ptr[RGB.G] = mapGreen[ptr[RGB.G]]; + // blue + ptr[RGB.B] = mapBlue[ptr[RGB.B]]; + } + } + } + } + + + /// + /// Calculate conversion map. + /// + /// + /// Input range. + /// Output range. + /// Conversion map. + /// + private static void CalculateMap(IntRange inRange, IntRange outRange, ushort[] map) + { + double k = 0, b = 0; + + if (inRange.Max != inRange.Min) + { + k = (double)(outRange.Max - outRange.Min) / (double)(inRange.Max - inRange.Min); + b = (double)(outRange.Min) - k * inRange.Min; + } + + for (int i = 0; i < 65536; i++) + { + ushort v = (ushort)i; + + if (v >= inRange.Max) + v = (ushort)outRange.Max; + else if (v <= inRange.Min) + v = (ushort)outRange.Min; + else + v = (ushort)(k * v + b); + + map[i] = v; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Color Filters/ReplaceChannel.cs b/Sources/Accord.Imaging/AForge/Filters/Color Filters/ReplaceChannel.cs new file mode 100644 index 0000000000..490ba5c06 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Color Filters/ReplaceChannel.cs @@ -0,0 +1,333 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Replace RGB channel of color imgae. + /// + /// + /// Replaces specified RGB channel of color image with + /// specified grayscale image. + /// + /// The filter is quite useful in conjunction with filter + /// (however may be used alone in some cases). Using the filter + /// it is possible to extract one of RGB channel, perform some image processing with it and then + /// put it back into the original color image. + /// + /// The filter accepts 24, 32, 48 and 64 bpp color images for processing. + /// + /// Sample usage: + /// + /// // extract red channel + /// ExtractChannel extractFilter = new ExtractChannel( RGB.R ); + /// Bitmap channel = extractFilter.Apply( image ); + /// // threshold channel + /// Threshold thresholdFilter = new Threshold( 230 ); + /// thresholdFilter.ApplyInPlace( channel ); + /// // put the channel back + /// ReplaceChannel replaceFilter = new ReplaceChannel( RGB.R, channel ); + /// replaceFilter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + public class ReplaceChannel : BaseInPlacePartialFilter + { + private short channel = RGB.R; + private Bitmap channelImage; + private UnmanagedImage unmanagedChannelImage; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// ARGB channel to replace. + /// + /// + /// Default value is set to . + /// + /// Invalid channel is specified. + /// + public short Channel + { + get { return channel; } + set + { + if ( + (value != RGB.R) && (value != RGB.G) && + (value != RGB.B) && (value != RGB.A) + ) + { + throw new ArgumentException("Invalid channel is specified."); + } + channel = value; + } + } + + /// + /// Grayscale image to use for channel replacement. + /// + /// + /// + /// Setting this property will clear the property - + /// only one channel image is allowed: managed or unmanaged. + /// + /// + /// Channel image should be 8 bpp indexed or 16 bpp grayscale image. + /// + public Bitmap ChannelImage + { + get { return channelImage; } + set + { + if (value != null) + { + // check for valid format + if ((value.PixelFormat != PixelFormat.Format8bppIndexed) && + (value.PixelFormat != PixelFormat.Format16bppGrayScale)) + throw new InvalidImagePropertiesException("Channel image should be 8 bpp indexed or 16 bpp grayscale image."); + } + + channelImage = value; + unmanagedChannelImage = null; + } + } + + /// + /// Unmanaged grayscale image to use for channel replacement. + /// + /// + /// + /// Setting this property will clear the property - + /// only one channel image is allowed: managed or unmanaged. + /// + /// + /// Channel image should be 8 bpp indexed or 16 bpp grayscale image. + /// + public UnmanagedImage UnmanagedChannelImage + { + get { return unmanagedChannelImage; } + set + { + if (value != null) + { + // check for valid format + if ((value.PixelFormat != PixelFormat.Format8bppIndexed) && + (value.PixelFormat != PixelFormat.Format16bppGrayScale)) + throw new InvalidImagePropertiesException("Channel image should be 8 bpp indexed or 16 bpp grayscale image."); + } + + channelImage = null; + unmanagedChannelImage = value; + } + } + + // private constructor + private ReplaceChannel() + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + formatTranslations[PixelFormat.Format48bppRgb] = PixelFormat.Format16bppGrayScale; + formatTranslations[PixelFormat.Format64bppArgb] = PixelFormat.Format16bppGrayScale; + } + + + /// + /// Initializes a new instance of the class. + /// + /// + /// ARGB channel to replace. + /// + public ReplaceChannel(short channel) + : this() + { + this.Channel = channel; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// ARGB channel to replace. + /// Channel image to use for replacement. + /// + public ReplaceChannel(short channel, Bitmap channelImage) + : this() + { + this.Channel = channel; + this.ChannelImage = channelImage; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// RGB channel to replace. + /// Unmanaged channel image to use for replacement. + /// + public ReplaceChannel(short channel, UnmanagedImage channelImage) + : this() + { + this.Channel = channel; + this.UnmanagedChannelImage = channelImage; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + /// Channel image was not specified. + /// Channel image size does not match source + /// image size. + /// Channel image's format does not correspond to format of the source image. + /// + /// Can not replace alpha channel of none ARGB image. The + /// exception is throw, when alpha channel is requested to be replaced in RGB image. + /// + protected override unsafe void ProcessFilter(UnmanagedImage image, Rectangle rect) + { + if ((channelImage == null) && (unmanagedChannelImage == null)) + throw new InvalidOperationException("Channel image was not specified."); + + int pixelSize = Image.GetPixelFormatSize(image.PixelFormat) / 8; + + if ((channel == RGB.A) && (pixelSize != 4) && (pixelSize != 8)) + throw new InvalidImagePropertiesException("Can not replace alpha channel of none ARGB image."); + + int width = image.Width; + int height = image.Height; + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + int offset = image.Stride - rect.Width * pixelSize; + + BitmapData chData = null; + // pointer to channel's data + byte* ch; + // channel's image stride + int chStride = 0; + PixelFormat chFormat = PixelFormat.Format16bppGrayScale; + + // check channel's image type + if (channelImage != null) + { + // check channel's image dimension + if ((width != channelImage.Width) || (height != channelImage.Height)) + throw new InvalidImagePropertiesException("Channel image size does not match source image size."); + + // lock channel image + chData = channelImage.LockBits( + new Rectangle(0, 0, width, height), + ImageLockMode.ReadOnly, channelImage.PixelFormat); + + ch = (byte*)chData.Scan0.ToPointer(); + chStride = chData.Stride; + chFormat = chData.PixelFormat; + } + else + { + // check channel's image dimension + if ((width != unmanagedChannelImage.Width) || (height != unmanagedChannelImage.Height)) + throw new InvalidImagePropertiesException("Channel image size does not match source image size."); + + ch = (byte*)unmanagedChannelImage.ImageData; + chStride = unmanagedChannelImage.Stride; + chFormat = unmanagedChannelImage.PixelFormat; + } + + if (pixelSize <= 4) + { + // check channel image's format + if (chFormat != PixelFormat.Format8bppIndexed) + throw new InvalidImagePropertiesException("Channel image's format does not correspond to format of the source image."); + + int offsetCh = chData.Stride - rect.Width; + + // do the job + byte* dst = (byte*)image.ImageData.ToPointer(); + + // allign pointers to the first pixel to process + dst += (startY * image.Stride + startX * pixelSize); + ch += (startY * chStride + startX); + + // for each line + for (int y = startY; y < stopY; y++) + { + // for each pixel + for (int x = startX; x < stopX; x++, dst += pixelSize, ch++) + { + dst[channel] = *ch; + } + dst += offset; + ch += offsetCh; + } + } + else + { + // check channel image's format + if (chFormat != PixelFormat.Format16bppGrayScale) + throw new InvalidImagePropertiesException("Channel image's format does not correspond to format of the source image."); + + int stride = image.Stride; + + // do the job + byte* baseDst = (byte*)image.ImageData.ToPointer(); + // allign pointers for X coordinate + baseDst += startX * pixelSize; + ch += startX * 2; + + pixelSize /= 2; + + // for each line + for (int y = startY; y < stopY; y++) + { + ushort* dst = (ushort*)(baseDst + y * stride); + ushort* chPtr = (ushort*)(ch + y * chStride); + + // for each pixel + for (int x = startX; x < stopX; x++, dst += pixelSize, chPtr++) + { + dst[channel] = *chPtr; + } + } + } + + if (chData != null) + { + // unlock + channelImage.UnlockBits(chData); + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Color Filters/RotateChannels.cs b/Sources/Accord.Imaging/AForge/Filters/Color Filters/RotateChannels.cs new file mode 100644 index 0000000000..effce17a8 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Color Filters/RotateChannels.cs @@ -0,0 +1,101 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Rotate RGB channels. + /// + /// + /// The filter rotates RGB channels: red channel is replaced with green, + /// green channel is replaced with blue, blue channel is replaced with red. + /// + /// The filter accepts 24/32 bpp color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// RotateChannels filter = new RotateChannels( ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public sealed class RotateChannels : BaseInPlacePartialFilter + { + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + public RotateChannels( ) + { + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + int pixelSize = ( image.PixelFormat == PixelFormat.Format24bppRgb ) ? 3 : 4; + + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + int offset = image.Stride - rect.Width * pixelSize; + + // do the job + byte* ptr = (byte*) image.ImageData.ToPointer( ); + byte t; + + // allign pointer to the first pixel to process + ptr += ( startY * image.Stride + startX * pixelSize ); + + // for each line + for ( int y = startY; y < stopY; y++ ) + { + // for each pixel + for ( int x = startX; x < stopX; x++, ptr += pixelSize ) + { + // rotate colors of each pixel + t = ptr[RGB.R]; + ptr[RGB.R] = ptr[RGB.G]; + ptr[RGB.G] = ptr[RGB.B]; + ptr[RGB.B] = t; + } + ptr += offset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Color Filters/Sepia.cs b/Sources/Accord.Imaging/AForge/Filters/Color Filters/Sepia.cs new file mode 100644 index 0000000000..781f50489 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Color Filters/Sepia.cs @@ -0,0 +1,135 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Sepia filter - old brown photo. + /// + /// + /// The filter makes an image look like an old brown photo. The main + /// idea of the algorithm: + /// + /// transform to YIQ color space; + /// modify it; + /// transform back to RGB. + /// + /// + /// + /// 1) RGB -> YIQ: + /// + /// Y = 0.299 * R + 0.587 * G + 0.114 * B + /// I = 0.596 * R - 0.274 * G - 0.322 * B + /// Q = 0.212 * R - 0.523 * G + 0.311 * B + /// + /// + /// + /// + /// 2) update: + /// + /// I = 51 + /// Q = 0 + /// + /// + /// + /// + /// 3) YIQ -> RGB: + /// + /// R = 1.0 * Y + 0.956 * I + 0.621 * Q + /// G = 1.0 * Y - 0.272 * I - 0.647 * Q + /// B = 1.0 * Y - 1.105 * I + 1.702 * Q + /// + /// + /// + /// The filter accepts 24/32 bpp color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// Sepia filter = new Sepia( ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public sealed class Sepia : BaseInPlacePartialFilter + { + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + public Sepia( ) + { + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + int pixelSize = ( image.PixelFormat == PixelFormat.Format24bppRgb ) ? 3 : 4; + + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + int offset = image.Stride - rect.Width * pixelSize; + + // do the job + byte* ptr = (byte*) image.ImageData.ToPointer( ); + byte t; + + // allign pointer to the first pixel to process + ptr += ( startY * image.Stride + startX * pixelSize ); + + // for each line + for ( int y = startY; y < stopY; y++ ) + { + // for each pixel + for ( int x = startX; x < stopX; x++, ptr += pixelSize ) + { + t = (byte) ( 0.299 * ptr[RGB.R] + 0.587 * ptr[RGB.G] + 0.114 * ptr[RGB.B] ); + + // red + ptr[RGB.R] = (byte) ( ( t > 206 ) ? 255 : t + 49 ); + // green + ptr[RGB.G] = (byte) ( ( t < 14 ) ? 0 : t - 14 ); + // blue + ptr[RGB.B] = (byte) ( ( t < 56 ) ? 0 : t - 56 ); + } + ptr += offset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Color Segmentation/SimplePosterization.cs b/Sources/Accord.Imaging/AForge/Filters/Color Segmentation/SimplePosterization.cs new file mode 100644 index 0000000000..befbf28cb --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Color Segmentation/SimplePosterization.cs @@ -0,0 +1,214 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// +// Copyright © Frank Nagl, 2008-2009 +// admin@franknagl.de +// www.franknagl.de +// +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Simple posterization of an image. + /// + /// + /// The class implements simple posterization of an image by splitting + /// each color plane into adjacent areas of the specified size. After the process + /// is done, each color plane will contain maximum of 256/PosterizationInterval levels. + /// For example, if grayscale image is posterized with posterization interval equal to 64, + /// then result image will contain maximum of 4 tones. If color image is posterized with the + /// same posterization interval, then it will contain maximum of 43=64 colors. + /// See property to get information about the way how to control + /// color used to fill posterization areas. + /// + /// Posterization is a process in photograph development which converts normal photographs + /// into an image consisting of distinct, but flat, areas of different tones or colors. + /// + /// The filter accepts 8 bpp grayscale and 24/32 bpp color images. + /// + /// Sample usage: + /// + /// // create filter + /// SimplePosterization filter = new SimplePosterization( ); + /// // process image + /// filter.ApplyInPlace( sourceImage ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class SimplePosterization : BaseInPlacePartialFilter + { + /// + /// Enumeration of possible types of filling posterized areas. + /// + public enum PosterizationFillingType + { + /// + /// Fill area with minimum color's value. + /// + Min, + /// + /// Fill area with maximum color's value. + /// + Max, + /// + /// Fill area with average color's value. + /// + Average + } + + byte posterizationInterval = 64; + PosterizationFillingType fillingType = PosterizationFillingType.Average; + + /// + /// Posterization interval, which specifies size of posterization areas. + /// + /// + /// The property specifies size of adjacent posterization areas + /// for each color plane. The value has direct effect on the amount of colors + /// in the result image. For example, if grayscale image is posterized with posterization + /// interval equal to 64, then result image will contain maximum of 4 tones. If color + /// image is posterized with same posterization interval, then it will contain maximum + /// of 43=64 colors. + /// + /// Default value is set to 64. + /// + /// + public byte PosterizationInterval + { + get { return posterizationInterval; } + set { posterizationInterval = value; } + } + + /// + /// Posterization filling type. + /// + /// + /// The property controls the color, which is used to substitute + /// colors within the same posterization interval - minimum, maximum or average value. + /// + /// + /// Default value is set to . + /// + /// + public PosterizationFillingType FillingType + { + get { return fillingType; } + set { fillingType = value; } + } + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + public SimplePosterization( ) + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format8bppIndexed; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Specifies filling type of posterization areas. + /// + public SimplePosterization( PosterizationFillingType fillingType ) : this ( ) + { + this.fillingType = fillingType; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + // get pixel size + int pixelSize = Image.GetPixelFormatSize( image.PixelFormat ) / 8; + + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + int offset = image.Stride - rect.Width * pixelSize; + + // calculate posterization offset + int posterizationOffset = ( fillingType == PosterizationFillingType.Min ) ? + 0 : ( ( fillingType == PosterizationFillingType.Max ) ? + posterizationInterval - 1 : posterizationInterval / 2 ); + + // calculate mapping array + byte[] map = new byte[256]; + + for ( int i = 0; i < 256; i++ ) + { + map[i] = (byte) Math.Min( 255, ( i / posterizationInterval ) * posterizationInterval + posterizationOffset ); + } + + // do the job + byte* ptr = (byte*) image.ImageData.ToPointer( ); + + // allign pointer to the first pixel to process + ptr += ( startY * image.Stride + startX * pixelSize ); + + // check image format + if ( image.PixelFormat == PixelFormat.Format8bppIndexed ) + { + // for each line + for ( int y = startY; y < stopY; y++ ) + { + // for each pixel in line + for ( int x = startX; x < stopX; x++, ptr++ ) + { + *ptr = map[*ptr]; + } + ptr += offset; + } + } + else + { + // for each line + for ( int y = startY; y < stopY; y++ ) + { + // for each pixel in line + for ( int x = startX; x < stopX; x++, ptr += pixelSize ) + { + ptr[RGB.R] = map[ptr[RGB.R]]; + ptr[RGB.G] = map[ptr[RGB.G]]; + ptr[RGB.B] = map[ptr[RGB.B]]; + } + ptr += offset; + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Convolution/Blur.cs b/Sources/Accord.Imaging/AForge/Filters/Convolution/Blur.cs new file mode 100644 index 0000000000..522620d55 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Convolution/Blur.cs @@ -0,0 +1,64 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + /// + /// Blur filter. + /// + /// + /// The filter performs convolution filter using + /// the blur kernel: + /// + /// + /// 1 2 3 2 1 + /// 2 4 5 4 2 + /// 3 5 6 5 3 + /// 2 4 5 4 2 + /// 1 2 3 2 1 + /// + /// + /// For the list of supported pixel formats, see the documentation to + /// filter. + /// + /// By default this filter sets property to + /// , so the alpha channel of 32 bpp and 64 bpp images is blurred as well. + /// + /// + /// Sample usage: + /// + /// // create filter + /// Blur filter = new Blur( ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + public sealed class Blur : Convolution + { + /// + /// Initializes a new instance of the class. + /// + public Blur( ) : base( new int[,] { + { 1, 2, 3, 2, 1 }, + { 2, 4, 5, 4, 2 }, + { 3, 5, 6, 5, 3 }, + { 2, 4, 5, 4, 2 }, + { 1, 2, 3, 2, 1 } } ) + { + base.ProcessAlpha = true; + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Convolution/Convolution.cs b/Sources/Accord.Imaging/AForge/Filters/Convolution/Convolution.cs new file mode 100644 index 0000000000..2309cab48 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Convolution/Convolution.cs @@ -0,0 +1,942 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Convolution filter. + /// + /// + /// The filter implements convolution operator, which calculates each pixel + /// of the result image as weighted sum of the correspond pixel and its neighbors in the source + /// image. The weights are set by convolution kernel. The weighted + /// sum is divided by before putting it into result image and also + /// may be thresholded using value. + /// + /// Convolution is a simple mathematical operation which is fundamental to many common + /// image processing filters. Depending on the type of provided kernel, the filter may produce + /// different results, like blur image, sharpen it, find edges, etc. + /// + /// The filter accepts 8 and 16 bpp grayscale images and 24, 32, 48 and 64 bpp + /// color images for processing. Note: depending on the value of + /// property, the alpha channel is either copied as is or processed with the kernel. + /// + /// Sample usage: + /// + /// // define emboss kernel + /// int[,] kernel = { + /// { -2, -1, 0 }, + /// { -1, 1, 1 }, + /// { 0, 1, 2 } }; + /// // create filter + /// Convolution filter = new Convolution( kernel ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class Convolution : BaseUsingCopyPartialFilter + { + // convolution kernel + private int[,] kernel; + // division factor + private int divisor = 1; + // threshold to add to weighted sum + private int threshold = 0; + // kernel size + private int size; + // use dynamic divisor for edges + private bool dynamicDivisorForEdges = true; + // specifies if alpha channel must be processed or just copied + private bool processAlpha = false; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Convolution kernel. + /// + /// + /// + /// Convolution kernel must be square and its width/height + /// should be odd and should be in the [3, 99] range. + /// + /// Setting convolution kernel through this property does not + /// affect - it is not recalculated automatically. + /// + /// + /// Invalid kernel size is specified. + /// + public int[,] Kernel + { + get { return kernel; } + set + { + int s = value.GetLength(0); + + // check kernel size + if ((s != value.GetLength(1)) || (s < 3) || (s > 99) || (s % 2 == 0)) + throw new ArgumentException("Invalid kernel size."); + + this.kernel = value; + this.size = s; + } + } + + /// + /// Division factor. + /// + /// + /// The value is used to divide convolution - weighted sum + /// of pixels is divided by this value. + /// + /// The value may be calculated automatically in the case if constructor + /// with one parameter is used (). + /// + /// + /// Divisor can not be equal to zero. + /// + public int Divisor + { + get { return divisor; } + set + { + if (value == 0) + throw new ArgumentException("Divisor can not be equal to zero."); + divisor = value; + } + } + + /// + /// Threshold to add to weighted sum. + /// + /// + /// The property specifies threshold value, which is added to each weighted + /// sum of pixels. The value is added right after division was done by + /// value. + /// + /// Default value is set to 0. + /// + /// + public int Threshold + { + get { return threshold; } + set { threshold = value; } + } + + /// + /// Use dynamic divisor for edges or not. + /// + /// + /// The property specifies how to handle edges. If it is set to + /// , then the same divisor (which is specified by + /// property or calculated automatically) will be applied both for non-edge regions + /// and for edge regions. If the value is set to , then dynamically + /// calculated divisor will be used for edge regions, which is sum of those kernel + /// elements, which are taken into account for particular processed pixel + /// (elements, which are not outside image). + /// + /// Default value is set to . + /// + /// + public bool DynamicDivisorForEdges + { + get { return dynamicDivisorForEdges; } + set { dynamicDivisorForEdges = value; } + } + + /// + /// Specifies if alpha channel must be processed or just copied. + /// + /// + /// The property specifies the way how alpha channel is handled for 32 bpp + /// and 64 bpp images. If the property is set to , then alpha + /// channel's values are just copied as is. If the property is set to + /// then alpha channel is convolved using the specified kernel same way as RGB channels. + /// + /// Default value is set to . + /// + /// + public bool ProcessAlpha + { + get { return processAlpha; } + set { processAlpha = value; } + } + + /// + /// Initializes a new instance of the class. + /// + protected Convolution() + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format16bppGrayScale] = PixelFormat.Format16bppGrayScale; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + formatTranslations[PixelFormat.Format48bppRgb] = PixelFormat.Format48bppRgb; + formatTranslations[PixelFormat.Format64bppArgb] = PixelFormat.Format64bppArgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Convolution kernel. + /// + /// Using this constructor (specifying only convolution kernel), + /// division factor will be calculated automatically + /// summing all kernel values. In the case if kernel's sum equals to zero, + /// division factor will be assigned to 1. + /// + /// Invalid kernel size is specified. Kernel must be + /// square, its width/height should be odd and should be in the [3, 25] range. + /// + public Convolution(int[,] kernel) + : this() + { + Kernel = kernel; + + divisor = 0; + + // calculate divisor + for (int i = 0, n = kernel.GetLength(0); i < n; i++) + { + for (int j = 0, k = kernel.GetLength(1); j < k; j++) + { + divisor += kernel[i, j]; + } + } + if (divisor == 0) + divisor = 1; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Convolution kernel. + /// Divisor, used used to divide weighted sum. + /// + /// Invalid kernel size is specified. Kernel must be + /// square, its width/height should be odd and should be in the [3, 25] range. + /// Divisor can not be equal to zero. + /// + public Convolution(int[,] kernel, int divisor) + : this() + { + Kernel = kernel; + Divisor = divisor; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect) + { + int pixelSize = Image.GetPixelFormatSize(sourceData.PixelFormat) / 8; + + // processing start and stop X,Y positions + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + + // check pixel size to find if we deal with 8 or 16 bpp channels + if ((pixelSize <= 4) && (pixelSize != 2)) + { + int srcStride = sourceData.Stride; + int dstStride = destinationData.Stride; + + int srcOffset = srcStride - rect.Width * pixelSize; + int dstOffset = dstStride - rect.Width * pixelSize; + + byte* src = (byte*)sourceData.ImageData.ToPointer(); + byte* dst = (byte*)destinationData.ImageData.ToPointer(); + + // allign pointers to the first pixel to process + src += (startY * srcStride + startX * pixelSize); + dst += (startY * dstStride + startX * pixelSize); + + // do the processing job + if (destinationData.PixelFormat == PixelFormat.Format8bppIndexed) + { + // grayscale image + Process8bppImage(src, dst, srcStride, dstStride, srcOffset, dstOffset, startX, startY, stopX, stopY); + } + else + { + // RGB image + if ((pixelSize == 3) || (!processAlpha)) + { + Process24bppImage(src, dst, srcStride, dstStride, srcOffset, dstOffset, startX, startY, stopX, stopY, pixelSize); + } + else + { + Process32bppImage(src, dst, srcStride, dstStride, srcOffset, dstOffset, startX, startY, stopX, stopY); + } + } + } + else + { + pixelSize /= 2; + + int dstStride = destinationData.Stride / 2; + int srcStride = sourceData.Stride / 2; + + // base pointers + ushort* baseSrc = (ushort*)sourceData.ImageData.ToPointer(); + ushort* baseDst = (ushort*)destinationData.ImageData.ToPointer(); + + // allign pointers by X + baseSrc += (startX * pixelSize); + baseDst += (startX * pixelSize); + + if (sourceData.PixelFormat == PixelFormat.Format16bppGrayScale) + { + // 16 bpp grayscale image + Process16bppImage(baseSrc, baseDst, srcStride, dstStride, startX, startY, stopX, stopY); + } + else + { + // RGB image + if ((pixelSize == 3) || (!processAlpha)) + { + Process48bppImage(baseSrc, baseDst, srcStride, dstStride, startX, startY, stopX, stopY, pixelSize); + } + else + { + Process64bppImage(baseSrc, baseDst, srcStride, dstStride, startX, startY, stopX, stopY); + } + } + } + } + + // Process 8 bpp grayscale images + private unsafe void Process8bppImage(byte* src, byte* dst, + int srcStride, int dstStride, int srcOffset, int dstOffset, + int startX, int startY, int stopX, int stopY) + { + // loop and array indexes + int i, j, t, k, ir, jr; + // kernel's radius + int radius = size >> 1; + // color sums + long g, div; + + // kernel size + int kernelSize = size * size; + // number of kernel elements taken into account + int processedKernelSize; + + // for each line + for (int y = startY; y < stopY; y++) + { + // for each pixel + for (int x = startX; x < stopX; x++, src++, dst++) + { + g = div = processedKernelSize = 0; + + // for each kernel row + for (i = 0; i < size; i++) + { + ir = i - radius; + t = y + ir; + + // skip row + if (t < startY) + continue; + // break + if (t >= stopY) + break; + + // for each kernel column + for (j = 0; j < size; j++) + { + jr = j - radius; + t = x + jr; + + // skip column + if (t < startX) + continue; + + if (t < stopX) + { + k = kernel[i, j]; + + div += k; + g += k * src[ir * srcStride + jr]; + processedKernelSize++; + } + } + } + + // check if all kernel elements were processed + if (processedKernelSize == kernelSize) + { + // all kernel elements are processed - we are not on the edge + div = divisor; + } + else + { + // we are on edge. do we need to use dynamic divisor or not? + if (!dynamicDivisorForEdges) + { + // do + div = divisor; + } + } + + // check divider + if (div != 0) + { + g /= div; + } + g += threshold; + *dst = (byte)((g > 255) ? 255 : ((g < 0) ? 0 : g)); + } + src += srcOffset; + dst += dstOffset; + } + } + + // Process 24 bpp images or 32 bpp images with copying alpha channel + private unsafe void Process24bppImage(byte* src, byte* dst, + int srcStride, int dstStride, int srcOffset, int dstOffset, + int startX, int startY, int stopX, int stopY, int pixelSize) + { + // loop and array indexes + int i, j, t, k, ir, jr; + // kernel's radius + int radius = size >> 1; + // color sums + long r, g, b, div; + + // kernel size + int kernelSize = size * size; + // number of kernel elements taken into account + int processedKernelSize; + + byte* p; + + // for each line + for (int y = startY; y < stopY; y++) + { + // for each pixel + for (int x = startX; x < stopX; x++, src += pixelSize, dst += pixelSize) + { + r = g = b = div = processedKernelSize = 0; + + // for each kernel row + for (i = 0; i < size; i++) + { + ir = i - radius; + t = y + ir; + + // skip row + if (t < startY) + continue; + // break + if (t >= stopY) + break; + + // for each kernel column + for (j = 0; j < size; j++) + { + jr = j - radius; + t = x + jr; + + // skip column + if (t < startX) + continue; + + if (t < stopX) + { + k = kernel[i, j]; + p = &src[ir * srcStride + jr * pixelSize]; + + div += k; + + r += k * p[RGB.R]; + g += k * p[RGB.G]; + b += k * p[RGB.B]; + + processedKernelSize++; + } + } + } + + // check if all kernel elements were processed + if (processedKernelSize == kernelSize) + { + // all kernel elements are processed - we are not on the edge + div = divisor; + } + else + { + // we are on edge. do we need to use dynamic divisor or not? + if (!dynamicDivisorForEdges) + { + // do + div = divisor; + } + } + + // check divider + if (div != 0) + { + r /= div; + g /= div; + b /= div; + } + r += threshold; + g += threshold; + b += threshold; + + dst[RGB.R] = (byte)((r > 255) ? 255 : ((r < 0) ? 0 : r)); + dst[RGB.G] = (byte)((g > 255) ? 255 : ((g < 0) ? 0 : g)); + dst[RGB.B] = (byte)((b > 255) ? 255 : ((b < 0) ? 0 : b)); + + // take care of alpha channel + if (pixelSize == 4) + dst[RGB.A] = src[RGB.A]; + } + src += srcOffset; + dst += dstOffset; + } + } + + // Process 32 bpp images including alpha channel + private unsafe void Process32bppImage(byte* src, byte* dst, + int srcStride, int dstStride, int srcOffset, int dstOffset, + int startX, int startY, int stopX, int stopY) + { + // loop and array indexes + int i, j, t, k, ir, jr; + // kernel's radius + int radius = size >> 1; + // color sums + long r, g, b, a, div; + + // kernel size + int kernelSize = size * size; + // number of kernel elements taken into account + int processedKernelSize; + + byte* p; + + // for each line + for (int y = startY; y < stopY; y++) + { + // for each pixel + for (int x = startX; x < stopX; x++, src += 4, dst += 4) + { + r = g = b = a = div = processedKernelSize = 0; + + // for each kernel row + for (i = 0; i < size; i++) + { + ir = i - radius; + t = y + ir; + + // skip row + if (t < startY) + continue; + // break + if (t >= stopY) + break; + + // for each kernel column + for (j = 0; j < size; j++) + { + jr = j - radius; + t = x + jr; + + // skip column + if (t < startX) + continue; + + if (t < stopX) + { + k = kernel[i, j]; + p = &src[ir * srcStride + jr * 4]; + + div += k; + + r += k * p[RGB.R]; + g += k * p[RGB.G]; + b += k * p[RGB.B]; + a += k * p[RGB.A]; + + processedKernelSize++; + } + } + } + + // check if all kernel elements were processed + if (processedKernelSize == kernelSize) + { + // all kernel elements are processed - we are not on the edge + div = divisor; + } + else + { + // we are on edge. do we need to use dynamic divisor or not? + if (!dynamicDivisorForEdges) + { + // do + div = divisor; + } + } + + // check divider + if (div != 0) + { + r /= div; + g /= div; + b /= div; + a /= div; + } + r += threshold; + g += threshold; + b += threshold; + a += threshold; + + dst[RGB.R] = (byte)((r > 255) ? 255 : ((r < 0) ? 0 : r)); + dst[RGB.G] = (byte)((g > 255) ? 255 : ((g < 0) ? 0 : g)); + dst[RGB.B] = (byte)((b > 255) ? 255 : ((b < 0) ? 0 : b)); + dst[RGB.A] = (byte)((a > 255) ? 255 : ((a < 0) ? 0 : a)); + } + src += srcOffset; + dst += dstOffset; + } + } + + // Process 16 bpp grayscale images + private unsafe void Process16bppImage(ushort* baseSrc, ushort* baseDst, int srcStride, int dstStride, + int startX, int startY, int stopX, int stopY) + { + // loop and array indexes + int i, j, t, k, ir, jr; + // kernel's radius + int radius = size >> 1; + // color sums + long g, div; + + // kernel size + int kernelSize = size * size; + // number of kernel elements taken into account + int processedKernelSize; + + // for each line + for (int y = startY; y < stopY; y++) + { + ushort* src = baseSrc + y * srcStride; + ushort* dst = baseDst + y * dstStride; + + // for each pixel + for (int x = startX; x < stopX; x++, src++, dst++) + { + g = div = processedKernelSize = 0; + + // for each kernel row + for (i = 0; i < size; i++) + { + ir = i - radius; + t = y + ir; + + // skip row + if (t < startY) + continue; + // break + if (t >= stopY) + break; + + // for each kernel column + for (j = 0; j < size; j++) + { + jr = j - radius; + t = x + jr; + + // skip column + if (t < startX) + continue; + + if (t < stopX) + { + k = kernel[i, j]; + + div += k; + g += k * src[ir * srcStride + jr]; + processedKernelSize++; + } + } + } + + // check if all kernel elements were processed + if (processedKernelSize == kernelSize) + { + // all kernel elements are processed - we are not on the edge + div = divisor; + } + else + { + // we are on edge. do we need to use dynamic divisor or not? + if (!dynamicDivisorForEdges) + { + // do + div = divisor; + } + } + + // check divider + if (div != 0) + { + g /= div; + } + g += threshold; + *dst = (ushort)((g > 65535) ? 65535 : ((g < 0) ? 0 : g)); + } + } + } + + // Process 48 bpp images or 64 bpp images with copying alpha channel + private unsafe void Process48bppImage(ushort* baseSrc, ushort* baseDst, int srcStride, int dstStride, + int startX, int startY, int stopX, int stopY, int pixelSize) + { + // loop and array indexes + int i, j, t, k, ir, jr; + // kernel's radius + int radius = size >> 1; + // color sums + long r, g, b, div; + + // kernel size + int kernelSize = size * size; + // number of kernel elements taken into account + int processedKernelSize; + + ushort* p; + + // for each line + for (int y = startY; y < stopY; y++) + { + ushort* src = baseSrc + y * srcStride; + ushort* dst = baseDst + y * dstStride; + + // for each pixel + for (int x = startX; x < stopX; x++, src += pixelSize, dst += pixelSize) + { + r = g = b = div = processedKernelSize = 0; + + // for each kernel row + for (i = 0; i < size; i++) + { + ir = i - radius; + t = y + ir; + + // skip row + if (t < startY) + continue; + // break + if (t >= stopY) + break; + + // for each kernel column + for (j = 0; j < size; j++) + { + jr = j - radius; + t = x + jr; + + // skip column + if (t < startX) + continue; + + if (t < stopX) + { + k = kernel[i, j]; + p = &src[ir * srcStride + jr * pixelSize]; + + div += k; + + r += k * p[RGB.R]; + g += k * p[RGB.G]; + b += k * p[RGB.B]; + + processedKernelSize++; + } + } + } + + // check if all kernel elements were processed + if (processedKernelSize == kernelSize) + { + // all kernel elements are processed - we are not on the edge + div = divisor; + } + else + { + // we are on edge. do we need to use dynamic divisor or not? + if (!dynamicDivisorForEdges) + { + // do + div = divisor; + } + } + + // check divider + if (div != 0) + { + r /= div; + g /= div; + b /= div; + } + r += threshold; + g += threshold; + b += threshold; + + dst[RGB.R] = (ushort)((r > 65535) ? 65535 : ((r < 0) ? 0 : r)); + dst[RGB.G] = (ushort)((g > 65535) ? 65535 : ((g < 0) ? 0 : g)); + dst[RGB.B] = (ushort)((b > 65535) ? 65535 : ((b < 0) ? 0 : b)); + + // take care of alpha channel + if (pixelSize == 4) + dst[RGB.A] = src[RGB.A]; + } + } + } + + // Process 64 bpp images including alpha channel + private unsafe void Process64bppImage(ushort* baseSrc, ushort* baseDst, int srcStride, int dstStride, + int startX, int startY, int stopX, int stopY) + { + // loop and array indexes + int i, j, t, k, ir, jr; + // kernel's radius + int radius = size >> 1; + // color sums + long r, g, b, a, div; + + // kernel size + int kernelSize = size * size; + // number of kernel elements taken into account + int processedKernelSize; + + ushort* p; + + // for each line + for (int y = startY; y < stopY; y++) + { + ushort* src = baseSrc + y * srcStride; + ushort* dst = baseDst + y * dstStride; + + // for each pixel + for (int x = startX; x < stopX; x++, src += 4, dst += 4) + { + r = g = b = a = div = processedKernelSize = 0; + + // for each kernel row + for (i = 0; i < size; i++) + { + ir = i - radius; + t = y + ir; + + // skip row + if (t < startY) + continue; + // break + if (t >= stopY) + break; + + // for each kernel column + for (j = 0; j < size; j++) + { + jr = j - radius; + t = x + jr; + + // skip column + if (t < startX) + continue; + + if (t < stopX) + { + k = kernel[i, j]; + p = &src[ir * srcStride + jr * 4]; + + div += k; + + r += k * p[RGB.R]; + g += k * p[RGB.G]; + b += k * p[RGB.B]; + a += k * p[RGB.A]; + + processedKernelSize++; + } + } + } + + // check if all kernel elements were processed + if (processedKernelSize == kernelSize) + { + // all kernel elements are processed - we are not on the edge + div = divisor; + } + else + { + // we are on edge. do we need to use dynamic divisor or not? + if (!dynamicDivisorForEdges) + { + // do + div = divisor; + } + } + + // check divider + if (div != 0) + { + r /= div; + g /= div; + b /= div; + a /= div; + } + r += threshold; + g += threshold; + b += threshold; + a += threshold; + + dst[RGB.R] = (ushort)((r > 65535) ? 65535 : ((r < 0) ? 0 : r)); + dst[RGB.G] = (ushort)((g > 65535) ? 65535 : ((g < 0) ? 0 : g)); + dst[RGB.B] = (ushort)((b > 65535) ? 65535 : ((b < 0) ? 0 : b)); + dst[RGB.A] = (ushort)((a > 65535) ? 65535 : ((a < 0) ? 0 : a)); + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Convolution/Edges.cs b/Sources/Accord.Imaging/AForge/Filters/Convolution/Edges.cs new file mode 100644 index 0000000000..2c51dd44b --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Convolution/Edges.cs @@ -0,0 +1,54 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + /// + /// Simple edge detector. + /// + /// + /// The filter performs convolution filter using + /// the edges kernel: + /// + /// + /// 0 -1 0 + /// -1 4 -1 + /// 0 -1 0 + /// + /// + /// For the list of supported pixel formats, see the documentation to + /// filter. + /// + /// Sample usage: + /// + /// // create filter + /// Edges filter = new Edges( ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + public sealed class Edges : Convolution + { + /// + /// Initializes a new instance of the class. + /// + public Edges( ) : base( new int[,] { + { 0, -1, 0 }, + { -1, 4, -1 }, + { 0, -1, 0 } } ) + { + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Convolution/GaussianBlur.cs b/Sources/Accord.Imaging/AForge/Filters/Convolution/GaussianBlur.cs new file mode 100644 index 0000000000..3392e7a45 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Convolution/GaussianBlur.cs @@ -0,0 +1,171 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Gaussian blur filter. + /// + /// + /// The filter performs convolution filter using + /// the kernel, which is calculate with the help of + /// method and then converted to integer kernel by dividing all elements by the element with the + /// smallest value. Using the kernel the convolution filter is known as Gaussian blur. + /// + /// Using property it is possible to configure + /// sigma value of Gaussian function. + /// + /// For the list of supported pixel formats, see the documentation to + /// filter. + /// + /// By default this filter sets property to + /// , so the alpha channel of 32 bpp and 64 bpp images is blurred as well. + /// + /// + /// Sample usage: + /// + /// // create filter with kernel size equal to 11 + /// // and Gaussia sigma value equal to 4.0 + /// GaussianBlur filter = new GaussianBlur( 4, 11 ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + public sealed class GaussianBlur : Convolution + { + private double sigma = 1.4; + private int size = 5; + + /// + /// Gaussian sigma value, [0.5, 5.0]. + /// + /// + /// Sigma value for Gaussian function used to calculate + /// the kernel. + /// + /// Default value is set to 1.4. + /// + /// + public double Sigma + { + get { return sigma; } + set + { + // get new sigma value + sigma = Math.Max( 0.5, Math.Min( 5.0, value ) ); + // create filter + CreateFilter( ); + } + } + + /// + /// Kernel size, [3, 21]. + /// + /// + /// Size of Gaussian kernel. + /// + /// Default value is set to 5. + /// + /// + public int Size + { + get { return size; } + set + { + size = Math.Max( 3, Math.Min( 21, value | 1 ) ); + CreateFilter( ); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public GaussianBlur( ) + { + CreateFilter( ); + base.ProcessAlpha = true; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Gaussian sigma value. + /// + public GaussianBlur( double sigma ) + { + Sigma = sigma; + base.ProcessAlpha = true; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Gaussian sigma value. + /// Kernel size. + /// + public GaussianBlur( double sigma, int size ) + { + Sigma = sigma; + Size = size; + base.ProcessAlpha = true; + } + + // Private members + #region Private Members + + // Create Gaussian filter + private void CreateFilter( ) + { + // create Gaussian function + AForge.Math.Gaussian gaus = new AForge.Math.Gaussian( sigma ); + // create kernel + double[,] kernel = gaus.Kernel2D( size ); + double min = kernel[0, 0]; + // integer kernel + int[,] intKernel = new int[size, size]; + int divisor = 0; + + for ( int i = 0; i < size; i++ ) + { + for ( int j = 0; j < size; j++ ) + { + double v = kernel[i, j] / min; + + if ( v > ushort.MaxValue ) + { + v = ushort.MaxValue; + } + intKernel[i, j] = (int) v; + + // collect divisor + divisor += intKernel[i, j]; + } + } + + // update filter + this.Kernel = intKernel; + this.Divisor = divisor; + } + #endregion + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Convolution/Mean.cs b/Sources/Accord.Imaging/AForge/Filters/Convolution/Mean.cs new file mode 100644 index 0000000000..653b13c98 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Convolution/Mean.cs @@ -0,0 +1,63 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + /// + /// Mean filter. + /// + /// + /// The filter performs each pixel value's averaging with its 8 neighbors, which is + /// convolution filter using the mean kernel: + /// + /// + /// 1 1 1 + /// 1 1 1 + /// 1 1 1 + /// + /// + /// For the list of supported pixel formats, see the documentation to + /// filter. + /// + /// With the above kernel the convolution filter is just calculates each pixel's value + /// in result image as average of 9 corresponding pixels in the source image. + /// + /// By default this filter sets property to + /// , so the alpha channel of 32 bpp and 64 bpp images is blurred as well. + /// + /// + /// Sample usage: + /// + /// // create filter + /// Mean filter = new Mean( ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + public sealed class Mean : Convolution + { + /// + /// Initializes a new instance of the class. + /// + public Mean( ) : base( new int[,] { + { 1, 1, 1 }, + { 1, 1, 1 }, + { 1, 1, 1 } } ) + { + base.ProcessAlpha = true; + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Convolution/Sharpen.cs b/Sources/Accord.Imaging/AForge/Filters/Convolution/Sharpen.cs new file mode 100644 index 0000000000..2911911e3 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Convolution/Sharpen.cs @@ -0,0 +1,54 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + /// + /// Sharpen filter + /// + /// + /// The filter performs convolution filter using + /// the sharpen kernel: + /// + /// + /// 0 -1 0 + /// -1 5 -1 + /// 0 -1 0 + /// + /// + /// For the list of supported pixel formats, see the documentation to + /// filter. + /// + /// Sample usage: + /// + /// // create filter + /// Sharpen filter = new Sharpen( ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + public sealed class Sharpen : Convolution + { + /// + /// Initializes a new instance of the class. + /// + public Sharpen( ) : base( new int[,] { + { 0, -1, 0 }, + { -1, 5, -1 }, + { 0, -1, 0 } } ) + { + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Convolution/SharpenEx.cs b/Sources/Accord.Imaging/AForge/Filters/Convolution/SharpenEx.cs new file mode 100644 index 0000000000..dd33ec92e --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Convolution/SharpenEx.cs @@ -0,0 +1,191 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@aforgenet.com +// +// Original idea of the SharpenEx found in Paint.NET project +// http://www.eecs.wsu.edu/paint.net/ +// +namespace AForge.Imaging.Filters +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Gaussian sharpen filter. + /// + /// + /// The filter performs convolution filter using + /// the kernel, which is calculate with the help of + /// method and then converted to integer sharpening kernel. First of all the integer kernel + /// is calculated from by dividing all elements by + /// the element with the smallest value. Then the integer kernel is converted to sharpen kernel by + /// negating all kernel's elements (multiplying with -1), but the central kernel's element + /// is calculated as 2 * sum - centralElement, where sum is the sum off elements + /// in the integer kernel before negating. + /// + /// For the list of supported pixel formats, see the documentation to + /// filter. + /// + /// Sample usage: + /// + /// // create filter with kernel size equal to 11 + /// // and Gaussia sigma value equal to 4.0 + /// GaussianSharpen filter = new GaussianSharpen( 4, 11 ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + public class GaussianSharpen : Convolution + { + private double sigma = 1.4; + private int size = 5; + + /// + /// Gaussian sigma value, [0.5, 5.0]. + /// + /// + /// Sigma value for Gaussian function used to calculate + /// the kernel. + /// + /// Default value is set to 1.4. + /// + /// + public double Sigma + { + get { return sigma; } + set + { + // get new sigma value + sigma = Math.Max( 0.5, Math.Min( 5.0, value ) ); + // create filter + CreateFilter( ); + } + } + + /// + /// Kernel size, [3, 5]. + /// + /// + /// Size of Gaussian kernel. + /// + /// Default value is set to 5. + /// + /// + public int Size + { + get { return size; } + set + { + size = Math.Max( 3, Math.Min( 21, value | 1 ) ); + CreateFilter( ); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public GaussianSharpen( ) + { + CreateFilter( ); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Gaussian sigma value. + /// + public GaussianSharpen( double sigma ) + { + Sigma = sigma; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Gaussian sigma value. + /// Kernel size. + /// + public GaussianSharpen( double sigma, int size ) + { + Sigma = sigma; + Size = size; + } + + // Private members + #region Private Members + + // Create Gaussian filter + private void CreateFilter( ) + { + // create Gaussian function + AForge.Math.Gaussian gaus = new AForge.Math.Gaussian( sigma ); + // create kernel + double[,] kernel = gaus.Kernel2D( size ); + double min = kernel[0, 0]; + // integer kernel + int[,] intKernel = new int[size, size]; + int sum = 0; + int divisor = 0; + + // calculate integer kernel + for ( int i = 0; i < size; i++ ) + { + for ( int j = 0; j < size; j++ ) + { + double v = kernel[i, j] / min; + + if ( v > ushort.MaxValue ) + { + v = ushort.MaxValue; + } + intKernel[i, j] = (int) v; + + // collect sum + sum += intKernel[i, j]; + } + } + + // recalc kernel + int c = size >> 1; + + for ( int i = 0; i < size; i++ ) + { + for ( int j = 0; j < size; j++ ) + { + if ( ( i == c ) && ( j == c ) ) + { + // calculate central value + intKernel[i, j] = 2 * sum - intKernel[i, j]; + } + else + { + // invert value + intKernel[i, j] = -intKernel[i, j]; + } + + // collect divisor + divisor += intKernel[i, j]; + } + } + + // update filter + this.Kernel = intKernel; + this.Divisor = divisor; + } + #endregion + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Edge Detectors/CannyEdgeDetector.cs b/Sources/Accord.Imaging/AForge/Filters/Edge Detectors/CannyEdgeDetector.cs new file mode 100644 index 0000000000..32d62efda --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Edge Detectors/CannyEdgeDetector.cs @@ -0,0 +1,366 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@aforgenet.com +// +// Article by Bill Green was used as the reference +// http://www.pages.drexel.edu/~weg22/can_tut.html +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Canny edge detector. + /// + /// + /// The filter searches for objects' edges by applying Canny edge detector. + /// The implementation follows + /// Bill Green's Canny edge detection tutorial. + /// + /// The implemented canny edge detector has one difference with the above linked algorithm. + /// The difference is in hysteresis step, which is a bit simplified (getting faster as a result). On the + /// hysteresis step each pixel is compared with two threshold values: and + /// . If pixel's value is greater or equal to , then + /// it is kept as edge pixel. If pixel's value is greater or equal to , then + /// it is kept as edge pixel only if there is at least one neighbouring pixel (8 neighbours are checked) which + /// has value greater or equal to ; otherwise it is none edge pixel. In the case + /// if pixel's value is less than , then it is marked as none edge immediately. + /// + /// + /// The filter accepts 8 bpp grayscale images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// CannyEdgeDetector filter = new CannyEdgeDetector( ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class CannyEdgeDetector : BaseUsingCopyPartialFilter + { + private GaussianBlur gaussianFilter = new GaussianBlur(); + private byte lowThreshold = 20; + private byte highThreshold = 100; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Low threshold. + /// + /// + /// Low threshold value used for hysteresis + /// (see tutorial + /// for more information). + /// + /// Default value is set to 20. + /// + /// + public byte LowThreshold + { + get { return lowThreshold; } + set { lowThreshold = value; } + } + + /// + /// High threshold. + /// + /// + /// High threshold value used for hysteresis + /// (see tutorial + /// for more information). + /// + /// Default value is set to 100. + /// + /// + public byte HighThreshold + { + get { return highThreshold; } + set { highThreshold = value; } + } + + /// + /// Gaussian sigma. + /// + /// + /// Sigma value for Gaussian bluring. + /// + public double GaussianSigma + { + get { return gaussianFilter.Sigma; } + set { gaussianFilter.Sigma = value; } + } + + /// + /// Gaussian size. + /// + /// + /// Size of Gaussian kernel. + /// + public int GaussianSize + { + get { return gaussianFilter.Size; } + set { gaussianFilter.Size = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public CannyEdgeDetector() + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Low threshold. + /// High threshold. + /// + public CannyEdgeDetector(byte lowThreshold, byte highThreshold) + : this() + { + this.lowThreshold = lowThreshold; + this.highThreshold = highThreshold; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Low threshold. + /// High threshold. + /// Gaussian sigma. + /// + public CannyEdgeDetector(byte lowThreshold, byte highThreshold, double sigma) + : this() + { + this.lowThreshold = lowThreshold; + this.highThreshold = highThreshold; + gaussianFilter.Sigma = sigma; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect) + { + // processing start and stop X,Y positions + int startX = rect.Left + 1; + int startY = rect.Top + 1; + int stopX = startX + rect.Width - 2; + int stopY = startY + rect.Height - 2; + + int width = rect.Width - 2; + int height = rect.Height - 2; + + int dstStride = destinationData.Stride; + int srcStride = sourceData.Stride; + + int dstOffset = dstStride - rect.Width + 2; + int srcOffset = srcStride - rect.Width + 2; + + // pixel's value and gradients + int gx, gy; + // + double orientation, toAngle = 180.0 / System.Math.PI; + float leftPixel = 0, rightPixel = 0; + + // STEP 1 - blur image + UnmanagedImage blurredImage = gaussianFilter.Apply(sourceData); + + // orientation array + byte[] orients = new byte[width * height]; + // gradients array + float[,] gradients = new float[sourceData.Width, sourceData.Height]; + float maxGradient = float.NegativeInfinity; + + // do the job + byte* src = (byte*)blurredImage.ImageData.ToPointer(); + // allign pointer + src += srcStride * startY + startX; + + // STEP 2 - calculate magnitude and edge orientation + int p = 0; + + // for each line + for (int y = startY; y < stopY; y++) + { + // for each pixel + for (int x = startX; x < stopX; x++, src++, p++) + { + gx = src[-srcStride + 1] + src[srcStride + 1] + - src[-srcStride - 1] - src[srcStride - 1] + + 2 * (src[1] - src[-1]); + + gy = src[-srcStride - 1] + src[-srcStride + 1] + - src[srcStride - 1] - src[srcStride + 1] + + 2 * (src[-srcStride] - src[srcStride]); + + // get gradient value + gradients[x, y] = (float)Math.Sqrt(gx * gx + gy * gy); + if (gradients[x, y] > maxGradient) + maxGradient = gradients[x, y]; + + // --- get orientation + if (gx == 0) + { + // can not divide by zero + orientation = (gy == 0) ? 0 : 90; + } + else + { + double div = (double)gy / gx; + + // handle angles of the 2nd and 4th quads + if (div < 0) + { + orientation = 180 - System.Math.Atan(-div) * toAngle; + } + // handle angles of the 1st and 3rd quads + else + { + orientation = System.Math.Atan(div) * toAngle; + } + + // get closest angle from 0, 45, 90, 135 set + if (orientation < 22.5) + orientation = 0; + else if (orientation < 67.5) + orientation = 45; + else if (orientation < 112.5) + orientation = 90; + else if (orientation < 157.5) + orientation = 135; + else orientation = 0; + } + + // save orientation + orients[p] = (byte)orientation; + } + src += srcOffset; + } + + // STEP 3 - suppres non maximums + byte* dst = (byte*)destinationData.ImageData.ToPointer(); + // allign pointer + dst += dstStride * startY + startX; + + p = 0; + + // for each line + for (int y = startY; y < stopY; y++) + { + // for each pixel + for (int x = startX; x < stopX; x++, dst++, p++) + { + // get two adjacent pixels + switch (orients[p]) + { + case 0: + leftPixel = gradients[x - 1, y]; + rightPixel = gradients[x + 1, y]; + break; + case 45: + leftPixel = gradients[x - 1, y + 1]; + rightPixel = gradients[x + 1, y - 1]; + break; + case 90: + leftPixel = gradients[x, y + 1]; + rightPixel = gradients[x, y - 1]; + break; + case 135: + leftPixel = gradients[x + 1, y + 1]; + rightPixel = gradients[x - 1, y - 1]; + break; + } + // compare current pixels value with adjacent pixels + if ((gradients[x, y] < leftPixel) || (gradients[x, y] < rightPixel)) + { + *dst = 0; + } + else + { + *dst = (byte)(gradients[x, y] / maxGradient * 255); + } + } + dst += dstOffset; + } + + // STEP 4 - hysteresis + dst = (byte*)destinationData.ImageData.ToPointer(); + // allign pointer + dst += dstStride * startY + startX; + + // for each line + for (int y = startY; y < stopY; y++) + { + // for each pixel + for (int x = startX; x < stopX; x++, dst++) + { + if (*dst < highThreshold) + { + if (*dst < lowThreshold) + { + // non edge + *dst = 0; + } + else + { + // check 8 neighboring pixels + if ((dst[-1] < highThreshold) && + (dst[1] < highThreshold) && + (dst[-dstStride - 1] < highThreshold) && + (dst[-dstStride] < highThreshold) && + (dst[-dstStride + 1] < highThreshold) && + (dst[dstStride - 1] < highThreshold) && + (dst[dstStride] < highThreshold) && + (dst[dstStride + 1] < highThreshold)) + { + *dst = 0; + } + } + } + } + dst += dstOffset; + } + + // STEP 5 - draw black rectangle to remove those pixels, which were not processed + // (this needs to be done for those cases, when filter is applied "in place" - + // source image is modified instead of creating new copy) + Drawing.Rectangle(destinationData, rect, Color.Black); + + // release blurred image + blurredImage.Dispose(); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Edge Detectors/DifferenceEdgeDetector.cs b/Sources/Accord.Imaging/AForge/Filters/Edge Detectors/DifferenceEdgeDetector.cs new file mode 100644 index 0000000000..190a26e30 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Edge Detectors/DifferenceEdgeDetector.cs @@ -0,0 +1,151 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Difference edge detector. + /// + /// + /// The filter finds objects' edges by calculating maximum difference + /// between pixels in 4 directions around the processing pixel. + /// + /// Suppose 3x3 square element of the source image (x - is currently processed + /// pixel): + /// + /// P1 P2 P3 + /// P8 x P4 + /// P7 P6 P5 + /// + /// The corresponding pixel of the result image equals to: + /// + /// max( |P1-P5|, |P2-P6|, |P3-P7|, |P4-P8| ) + /// + /// + /// + /// The filter accepts 8 bpp grayscale images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// DifferenceEdgeDetector filter = new DifferenceEdgeDetector( ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + public class DifferenceEdgeDetector : BaseUsingCopyPartialFilter + { + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public DifferenceEdgeDetector() + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect) + { + // processing start and stop X,Y positions + int startX = rect.Left + 1; + int startY = rect.Top + 1; + int stopX = startX + rect.Width - 2; + int stopY = startY + rect.Height - 2; + + int dstStride = destinationData.Stride; + int srcStride = sourceData.Stride; + + int dstOffset = dstStride - rect.Width + 2; + int srcOffset = srcStride - rect.Width + 2; + + int d, max; + + // data pointers + byte* src = (byte*)sourceData.ImageData.ToPointer(); + byte* dst = (byte*)destinationData.ImageData.ToPointer(); + + // allign pointers + src += srcStride * startY + startX; + dst += dstStride * startY + startX; + + // for each line + for (int y = startY; y < stopY; y++) + { + // for each pixel + for (int x = startX; x < stopX; x++, src++, dst++) + { + // left diagonal + max = (int)src[-srcStride - 1] - src[srcStride + 1]; + if (max < 0) + max = -max; + + // right diagonal + d = (int)src[-srcStride + 1] - src[srcStride - 1]; + if (d < 0) + d = -d; + if (d > max) + max = d; + // vertical + d = (int)src[-srcStride] - src[srcStride]; + if (d < 0) + d = -d; + if (d > max) + max = d; + // horizontal + d = (int)src[-1] - src[1]; + if (d < 0) + d = -d; + if (d > max) + max = d; + + *dst = (byte)max; + } + src += srcOffset; + dst += dstOffset; + } + + // draw black rectangle to remove those pixels, which were not processed + // (this needs to be done for those cases, when filter is applied "in place" - + // source image is modified instead of creating new copy) + Drawing.Rectangle(destinationData, rect, Color.Black); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Edge Detectors/HomogenityEdgeDetector.cs b/Sources/Accord.Imaging/AForge/Filters/Edge Detectors/HomogenityEdgeDetector.cs new file mode 100644 index 0000000000..c9e987e46 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Edge Detectors/HomogenityEdgeDetector.cs @@ -0,0 +1,180 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Homogenity edge detector. + /// + /// + /// The filter finds objects' edges by calculating maximum difference + /// of processing pixel with neighboring pixels in 8 direction. + /// + /// Suppose 3x3 square element of the source image (x - is currently processed + /// pixel): + /// + /// P1 P2 P3 + /// P8 x P4 + /// P7 P6 P5 + /// + /// The corresponding pixel of the result image equals to: + /// + /// max( |x-P1|, |x-P2|, |x-P3|, |x-P4|, + /// |x-P5|, |x-P6|, |x-P7|, |x-P8| ) + /// + /// + /// + /// The filter accepts 8 bpp grayscale images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// HomogenityEdgeDetector filter = new HomogenityEdgeDetector( ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + public class HomogenityEdgeDetector : BaseUsingCopyPartialFilter + { + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public HomogenityEdgeDetector() + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect) + { + // processing start and stop X,Y positions + int startX = rect.Left + 1; + int startY = rect.Top + 1; + int stopX = startX + rect.Width - 2; + int stopY = startY + rect.Height - 2; + + int dstStride = destinationData.Stride; + int srcStride = sourceData.Stride; + + int dstOffset = dstStride - rect.Width + 2; + int srcOffset = srcStride - rect.Width + 2; + + int d, max, v; + + // data pointers + byte* src = (byte*)sourceData.ImageData.ToPointer(); + byte* dst = (byte*)destinationData.ImageData.ToPointer(); + + // allign pointers + src += srcStride * startY + startX; + dst += dstStride * startY + startX; + + // for each line + for (int y = startY; y < stopY; y++) + { + // for each pixel + for (int x = startX; x < stopX; x++, src++, dst++) + { + max = 0; + v = *src; + + // top-left + d = v - src[-srcStride - 1]; + if (d < 0) + d = -d; + if (d > max) + max = d; + // top + d = v - src[-srcStride]; + if (d < 0) + d = -d; + if (d > max) + max = d; + // top-right + d = v - src[-srcStride + 1]; + if (d < 0) + d = -d; + if (d > max) + max = d; + // left + d = v - src[-1]; + if (d < 0) + d = -d; + if (d > max) + max = d; + // right + d = v - src[1]; + if (d < 0) + d = -d; + if (d > max) + max = d; + // bottom-left + d = v - src[srcStride - 1]; + if (d < 0) + d = -d; + if (d > max) + max = d; + // bottom + d = v - src[srcStride]; + if (d < 0) + d = -d; + if (d > max) + max = d; + // bottom-right + d = v - src[srcStride + 1]; + if (d < 0) + d = -d; + if (d > max) + max = d; + + *dst = (byte)max; + } + src += srcOffset; + dst += dstOffset; + } + + // draw black rectangle to remove those pixels, which were not processed + // (this needs to be done for those cases, when filter is applied "in place" - + // source image is modified instead of creating new copy) + Drawing.Rectangle(destinationData, rect, Color.Black); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Edge Detectors/SobelEdgeDetector.cs b/Sources/Accord.Imaging/AForge/Filters/Edge Detectors/SobelEdgeDetector.cs new file mode 100644 index 0000000000..69c6afe37 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Edge Detectors/SobelEdgeDetector.cs @@ -0,0 +1,188 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Sobel edge detector. + /// + /// + /// The filter searches for objects' edges by applying Sobel operator. + /// + /// Each pixel of the result image is calculated as approximated absolute gradient + /// magnitude for corresponding pixel of the source image: + /// + /// |G| = |Gx| + |Gy] , + /// + /// where Gx and Gy are calculate utilizing Sobel convolution kernels: + /// + /// Gx Gy + /// -1 0 +1 +1 +2 +1 + /// -2 0 +2 0 0 0 + /// -1 0 +1 -1 -2 -1 + /// + /// Using the above kernel the approximated magnitude for pixel x is calculate using + /// the next equation: + /// + /// P1 P2 P3 + /// P8 x P4 + /// P7 P6 P5 + /// + /// |G| = |P1 + 2P2 + P3 - P7 - 2P6 - P5| + + /// |P3 + 2P4 + P5 - P1 - 2P8 - P7| + /// + /// + /// + /// The filter accepts 8 bpp grayscale images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// SobelEdgeDetector filter = new SobelEdgeDetector( ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + public class SobelEdgeDetector : BaseUsingCopyPartialFilter + { + private bool scaleIntensity = true; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Scale intensity or not. + /// + /// + /// The property determines if edges' pixels intensities of the result image + /// should be scaled in the range of the lowest and the highest possible intensity + /// values. + /// + /// Default value is set to . + /// + /// + public bool ScaleIntensity + { + get { return scaleIntensity; } + set { scaleIntensity = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public SobelEdgeDetector() + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect) + { + // processing start and stop X,Y positions + int startX = rect.Left + 1; + int startY = rect.Top + 1; + int stopX = startX + rect.Width - 2; + int stopY = startY + rect.Height - 2; + + int dstStride = destinationData.Stride; + int srcStride = sourceData.Stride; + + int dstOffset = dstStride - rect.Width + 2; + int srcOffset = srcStride - rect.Width + 2; + + // data pointers + byte* src = (byte*)sourceData.ImageData.ToPointer(); + byte* dst = (byte*)destinationData.ImageData.ToPointer(); + + // allign pointers + src += srcStride * startY + startX; + dst += dstStride * startY + startX; + + // variables for gradient calculation + double g, max = 0; + + // for each line + for (int y = startY; y < stopY; y++) + { + // for each pixel + for (int x = startX; x < stopX; x++, src++, dst++) + { + g = Math.Min(255, + Math.Abs(src[-srcStride - 1] + src[-srcStride + 1] + - src[srcStride - 1] - src[srcStride + 1] + + 2 * (src[-srcStride] - src[srcStride])) + + Math.Abs(src[-srcStride + 1] + src[srcStride + 1] + - src[-srcStride - 1] - src[srcStride - 1] + + 2 * (src[1] - src[-1]))); + + if (g > max) + max = g; + *dst = (byte)g; + } + src += srcOffset; + dst += dstOffset; + } + + + // do we need scaling + if ((scaleIntensity) && (max != 255)) + { + // make the second pass for intensity scaling + double factor = 255.0 / (double)max; + dst = (byte*)destinationData.ImageData.ToPointer(); + dst += dstStride * startY + startX; + + // for each line + for (int y = startY; y < stopY; y++) + { + // for each pixel + for (int x = startX; x < stopX; x++, dst++) + { + *dst = (byte)(factor * (*dst)); + } + dst += dstOffset; + } + } + + // draw black rectangle to remove those pixels, which were not processed + // (this needs to be done for those cases, when filter is applied "in place" - + // source image is modified instead of creating new copy) + Drawing.Rectangle(destinationData, rect, Color.Black); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/FilterIterator.cs b/Sources/Accord.Imaging/AForge/Filters/FilterIterator.cs new file mode 100644 index 0000000000..284e00e7f --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/FilterIterator.cs @@ -0,0 +1,276 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2010 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Filter iterator. + /// + /// + /// Filter iterator performs specified amount of filter's iterations. + /// The filter take the specified base filter and applies it + /// to source image specified amount of times. + /// + /// The filter itself does not have any restrictions to pixel format of source + /// image. This is set by base filter. + /// + /// The filter does image processing using only + /// interface of the specified base filter. This means + /// that this filter may not utilize all potential features of the base filter, like + /// in-place processing (see ) and region based processing + /// (see ). To utilize those features, it is required to + /// do filter's iteration manually. + /// + /// Sample usage (morphological thinning): + /// + /// // create filter sequence + /// FiltersSequence filterSequence = new FiltersSequence( ); + /// // add 8 thinning filters with different structuring elements + /// filterSequence.Add( new HitAndMiss( + /// new short [,] { { 0, 0, 0 }, { -1, 1, -1 }, { 1, 1, 1 } }, + /// HitAndMiss.Modes.Thinning ) ); + /// filterSequence.Add( new HitAndMiss( + /// new short [,] { { -1, 0, 0 }, { 1, 1, 0 }, { -1, 1, -1 } }, + /// HitAndMiss.Modes.Thinning ) ); + /// filterSequence.Add( new HitAndMiss( + /// new short [,] { { 1, -1, 0 }, { 1, 1, 0 }, { 1, -1, 0 } }, + /// HitAndMiss.Modes.Thinning ) ); + /// filterSequence.Add( new HitAndMiss( + /// new short [,] { { -1, 1, -1 }, { 1, 1, 0 }, { -1, 0, 0 } }, + /// HitAndMiss.Modes.Thinning ) ); + /// filterSequence.Add( new HitAndMiss( + /// new short [,] { { 1, 1, 1 }, { -1, 1, -1 }, { 0, 0, 0 } }, + /// HitAndMiss.Modes.Thinning ) ); + /// filterSequence.Add( new HitAndMiss( + /// new short [,] { { -1, 1, -1 }, { 0, 1, 1 }, { 0, 0, -1 } }, + /// HitAndMiss.Modes.Thinning ) ); + /// filterSequence.Add( new HitAndMiss( + /// new short [,] { { 0, -1, 1 }, { 0, 1, 1 }, { 0, -1, 1 } }, + /// HitAndMiss.Modes.Thinning ) ); + /// filterSequence.Add( new HitAndMiss( + /// new short [,] { { 0, 0, -1 }, { 0, 1, 1 }, { -1, 1, -1 } }, + /// HitAndMiss.Modes.Thinning ) ); + /// // create filter iterator for 10 iterations + /// FilterIterator filter = new FilterIterator( filterSequence, 10 ); + /// // apply the filter + /// Bitmap newImage = filter.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class FilterIterator : IFilter, IFilterInformation + { + private IFilter baseFilter; + private int iterations = 1; + + /// + /// Format translations dictionary. + /// + /// + /// See + /// documentation for additional information. + /// + /// The filter provides format translation dictionary taken from + /// filter. + /// + /// + public Dictionary FormatTranslations + { + get { return ( (IFilterInformation) baseFilter).FormatTranslations; } + } + + /// + /// Base filter. + /// + /// + /// The base filter is the filter to be applied specified amount of iterations to + /// a specified image. + /// + public IFilter BaseFilter + { + get { return baseFilter; } + set { baseFilter = value; } + } + + /// + /// Iterations amount, [1, 255]. + /// + /// + /// The amount of times to apply specified filter to a specified image. + /// + /// Default value is set to 1. + /// + /// + public int Iterations + { + get { return iterations; } + set { iterations = Math.Max( 1, Math.Min( 255, value ) ); } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Filter to iterate. + /// + public FilterIterator( IFilter baseFilter ) + { + this.baseFilter = baseFilter; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Filter to iterate. + /// Iterations amount. + /// + public FilterIterator( IFilter baseFilter, int iterations ) + { + this.baseFilter = baseFilter; + this.iterations = iterations; + } + + /// + /// Apply filter to an image. + /// + /// + /// Source image to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The method keeps the source image unchanged and returns + /// the result of image processing filter as new image. + /// + public Bitmap Apply( Bitmap image ) + { + // lock source bitmap data + BitmapData imageData = image.LockBits( + new Rectangle( 0, 0, image.Width, image.Height ), + ImageLockMode.ReadOnly, image.PixelFormat ); + + // apply the filter + Bitmap dstImage = Apply( imageData ); + + // unlock source image + image.UnlockBits( imageData ); + + return dstImage; + } + + /// + /// Apply filter to an image. + /// + /// + /// Source image to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The filter accepts bitmap data as input and returns the result + /// of image processing filter as new image. The source image data are kept + /// unchanged. + /// + public Bitmap Apply( BitmapData imageData ) + { + // initial iteration + Bitmap dstImg = baseFilter.Apply( imageData ); + Bitmap tmpImg; + + // continue to iterate + for ( int i = 1; i < iterations; i++ ) + { + tmpImg = dstImg; + dstImg = baseFilter.Apply( tmpImg ); + tmpImg.Dispose( ); + } + + return dstImg; + } + + /// + /// Apply filter to an image in unmanaged memory. + /// + /// + /// Source image in unmanaged memory to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The method keeps the source image unchanged and returns + /// the result of image processing filter as new image. + /// + public UnmanagedImage Apply( UnmanagedImage image ) + { + // initial iteration + UnmanagedImage dstImg = baseFilter.Apply( image ); + UnmanagedImage tmpImg; + + // continue to iterate + for ( int i = 1; i < iterations; i++ ) + { + tmpImg = dstImg; + dstImg = baseFilter.Apply( tmpImg ); + tmpImg.Dispose( ); + } + + return dstImg; + } + + /// + /// Apply filter to an image in unmanaged memory. + /// + /// + /// Source image in unmanaged memory to apply filter to. + /// Destination image in unmanaged memory to put result into. + /// + /// The method keeps the source image unchanged and puts result of image processing + /// into destination image. + /// + /// The destination image must have the same width and height as source image. Also + /// destination image must have pixel format, which is expected by particular filter (see + /// property for information about pixel format conversions). + /// + /// + public void Apply( UnmanagedImage sourceImage, UnmanagedImage destinationImage ) + { + if ( iterations == 1 ) + { + baseFilter.Apply( sourceImage, destinationImage ); + } + else + { + // initial iteration + UnmanagedImage dstImg = baseFilter.Apply( sourceImage ); + UnmanagedImage tmpImg; + + iterations--; + // continue to iterate + for ( int i = 1; i < iterations; i++ ) + { + tmpImg = dstImg; + dstImg = baseFilter.Apply( tmpImg ); + tmpImg.Dispose( ); + } + + // put result of last iteration into the specified destination + baseFilter.Apply( dstImg, destinationImage ); + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/FiltersSequence.cs b/Sources/Accord.Imaging/AForge/Filters/FiltersSequence.cs new file mode 100644 index 0000000000..9a24e14cd --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/FiltersSequence.cs @@ -0,0 +1,238 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2010 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + using System.Collections; + + /// + /// Filters' collection to apply to an image in sequence. + /// + /// + /// The class represents collection of filters, which need to be applied + /// to an image in sequence. Using the class user may specify set of filters, which will + /// be applied to source image one by one in the order user defines them. + /// + /// The class itself does not define which pixel formats are accepted for the source + /// image and which pixel formats may be produced by the filter. Format of acceptable source + /// and possible output is defined by filters, which added to the sequence. + /// + /// Sample usage: + /// + /// // create filter, which is binarization sequence + /// FiltersSequence filter = new FiltersSequence( + /// new GrayscaleBT709( ), + /// new Threshold( ) + /// ); + /// // apply the filter + /// Bitmap newImage = filter.Apply( image ); + /// + /// + /// + public class FiltersSequence : CollectionBase, IFilter + { + /// + /// Initializes a new instance of the class. + /// + /// + public FiltersSequence() { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Sequence of filters to apply. + /// + public FiltersSequence(params IFilter[] filters) + { + InnerList.AddRange(filters); + } + + /// + /// Get filter at the specified index. + /// + /// + /// Index of filter to get. + /// + /// Returns filter at specified index. + /// + public IFilter this[int index] + { + get { return ((IFilter)InnerList[index]); } + } + + /// + /// Add new filter to the sequence. + /// + /// + /// Filter to add to the sequence. + /// + public void Add(IFilter filter) + { + InnerList.Add(filter); + } + + /// + /// Apply filter to an image. + /// + /// + /// Source image to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The method keeps the source image unchanged and returns + /// the result of image processing filter as new image. + /// + /// No filters were added into the filters' sequence. + /// + public Bitmap Apply(Bitmap image) + { + Bitmap dstImage = null; + // lock source bitmap data + BitmapData imageData = image.LockBits( + new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, image.PixelFormat); + + try + { + // apply the filter + dstImage = Apply(imageData); + } + finally + { + // unlock source image + image.UnlockBits(imageData); + } + + return dstImage; + } + + /// + /// Apply filter to an image. + /// + /// + /// Source image to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The filter accepts bitmap data as input and returns the result + /// of image processing filter as new image. The source image data are kept + /// unchanged. + /// + /// No filters were added into the filters' sequence. + /// + public Bitmap Apply(BitmapData imageData) + { + // to increase performance the method passes execution to the method, which + // operates with unmanaged images - this saves time, because redundant managed + // locks/unlocks are eliminated + + // get result as an unmanaged image + UnmanagedImage dstUnmanagedImage = Apply(new UnmanagedImage(imageData)); + // convert unmanaged image to managed + Bitmap dstImage = dstUnmanagedImage.ToManagedImage(); + // dispose unmanaged mage + dstUnmanagedImage.Dispose(); + + return dstImage; + } + + /// + /// Apply filter to an image in unmanaged memory. + /// + /// + /// Source image in unmanaged memory to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The method keeps the source image unchanged and returns + /// the result of image processing filter as new image. + /// + /// No filters were added into the filters' sequence. + /// + public UnmanagedImage Apply(UnmanagedImage image) + { + int n = InnerList.Count; + + // check for empty sequence + if (n == 0) + throw new InvalidOperationException("No filters in the sequence."); + + UnmanagedImage dstImg = null; + UnmanagedImage tmpImg = null; + + // apply the first filter + dstImg = ((IFilter)InnerList[0]).Apply(image); + + // apply other filters + for (int i = 1; i < n; i++) + { + tmpImg = dstImg; + dstImg = ((IFilter)InnerList[i]).Apply(tmpImg); + tmpImg.Dispose(); + } + + return dstImg; + } + + /// + /// Apply filter to an image in unmanaged memory. + /// + /// + /// Source image in unmanaged memory to apply filter to. + /// Destination image in unmanaged memory to put result into. + /// + /// The method keeps the source image unchanged and puts result of image processing + /// into destination image. + /// + /// The destination image must have width, height and pixel format as it is expected by + /// the final filter in the sequence. + /// + /// + /// No filters were added into the filters' sequence. + /// + public void Apply(UnmanagedImage sourceImage, UnmanagedImage destinationImage) + { + int n = InnerList.Count; + + // check for empty sequence + if (n == 0) + throw new InvalidOperationException("No filters in the sequence."); + + if (n == 1) + { + ((IFilter)InnerList[0]).Apply(sourceImage, destinationImage); + } + else + { + UnmanagedImage tmpImg1 = null; + UnmanagedImage tmpImg2 = null; + + // apply the first filter + tmpImg1 = ((IFilter)InnerList[0]).Apply(sourceImage); + + // apply other filters, except the last one + n--; + for (int i = 1; i < n; i++) + { + tmpImg2 = tmpImg1; + tmpImg1 = ((IFilter)InnerList[i]).Apply(tmpImg2); + tmpImg2.Dispose(); + } + + ((IFilter)InnerList[n]).Apply(tmpImg1, destinationImage); + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Flood Fillers/PointedColorFloodFill.cs b/Sources/Accord.Imaging/AForge/Filters/Flood Fillers/PointedColorFloodFill.cs new file mode 100644 index 0000000000..5161f4d5f --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Flood Fillers/PointedColorFloodFill.cs @@ -0,0 +1,449 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2010 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Flood filling with specified color starting from specified point. + /// + /// + /// The filter performs image's area filling (4 directional) starting + /// from the specified point. It fills + /// the area of the pointed color, but also fills other colors, which + /// are similar to the pointed within specified tolerance. + /// The area is filled using specified fill color. + /// + /// + /// The filter accepts 8 bpp grayscale images and 24 bpp + /// color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// PointedColorFloodFill filter = new PointedColorFloodFill( ); + /// // configure the filter + /// filter.Tolerance = Color.FromArgb( 150, 92, 92 ); + /// filter.FillColor = Color.FromArgb( 255, 255, 255 ); + /// filter.StartingPoint = new IntPoint( 150, 100 ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + public unsafe class PointedColorFloodFill : BaseInPlacePartialFilter + { + // map of pixels, which are already checked by the flood fill algorithm + private bool[,] checkedPixels; + + // set of variables (which describe image property and min/max color) to avoid passing them + // recursively as parameters + byte* scan0; // pointer to first image line + int stride; // size of image's line + int startX; // X1 of bounding rectangle + int stopX; // Y1 of bounding rectangle + int startY; // X2 of bounding rectangle (including) + int stopY; // Y2 of bounding rectangle (including) + + // min/max colors + byte minR, maxR; // min/max Red + byte minG, maxG; // min/max Green (Gray) color + byte minB, maxB; // min/max Blue + + // fill color + byte fillR, fillG, fillB; + + // starting point to fill from + private IntPoint startingPoint = new IntPoint( 0, 0 ); + // filling tolerance + private Color tolerance = Color.FromArgb( 0, 0, 0 ); + + // format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Flood fill tolerance. + /// + /// + /// The tolerance value determines which colors to fill. If the + /// value is set to 0, then only color of the pointed pixel + /// is filled. If the value is not 0, then other colors may be filled as well, + /// which are similar to the color of the pointed pixel within the specified + /// tolerance. + /// + /// The tolerance value is specified as , + /// where each component (R, G and B) represents tolerance for the corresponding + /// component of color. This allows to set different tolerances for red, green + /// and blue components. + /// + /// + public Color Tolerance + { + get { return tolerance; } + set { tolerance = value; } + } + + /// + /// Fill color. + /// + /// + /// The fill color is used to fill image's area starting from the + /// specified point. + /// + /// For grayscale images the color needs to be specified with all three + /// RGB values set to the same value, (128, 128, 128) for example. + /// + /// Default value is set to black. + /// + /// + public Color FillColor + { + get { return Color.FromArgb( fillR, fillG, fillB ); } + set + { + fillR = value.R; + fillG = value.G; + fillB = value.B; + } + } + + /// + /// Point to start filling from. + /// + /// + /// The property allows to set the starting point, where filling is + /// started from. + /// + /// Default value is set to (0, 0). + /// + /// + public IntPoint StartingPoint + { + get { return startingPoint; } + set { startingPoint = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public PointedColorFloodFill( ) + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Fill color. + /// + public PointedColorFloodFill( Color fillColor ) + : this( ) + { + FillColor = fillColor; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + // skip, if there is nothing to fill + if ( !rect.Contains( startingPoint.X, startingPoint.Y ) ) + return; + + // save bounding rectangle + startX = rect.Left; + startY = rect.Top; + stopX = rect.Right - 1; + stopY = rect.Bottom - 1; + + // save image properties + scan0 = (byte*) image.ImageData.ToPointer( ); + stride = image.Stride; + + // create map visited pixels + checkedPixels = new bool[image.Height, image.Width]; + + if ( image.PixelFormat == PixelFormat.Format8bppIndexed ) + { + byte startColor = *( (byte*) CoordsToPointerGray( startingPoint.X, startingPoint.Y ) ); + minG = (byte) ( Math.Max( 0, startColor - tolerance.G ) ); + maxG = (byte) ( Math.Min( 255, startColor + tolerance.G ) ); + + LinearFloodFill4Gray( startingPoint ); + } + else + { + byte* startColor = (byte*) CoordsToPointerRGB( startingPoint.X, startingPoint.Y ); + + minR = (byte) ( Math.Max( 0, startColor[RGB.R] - tolerance.R ) ); + maxR = (byte) ( Math.Min( 255, startColor[RGB.R] + tolerance.R ) ); + minG = (byte) ( Math.Max( 0, startColor[RGB.G] - tolerance.G ) ); + maxG = (byte) ( Math.Min( 255, startColor[RGB.G] + tolerance.G ) ); + minB = (byte) ( Math.Max( 0, startColor[RGB.B] - tolerance.B ) ); + maxB = (byte) ( Math.Min( 255, startColor[RGB.B] + tolerance.B ) ); + + LinearFloodFill4RGB( startingPoint ); + } + } + + // Liner flood fill in 4 directions for grayscale images + private unsafe void LinearFloodFill4Gray( IntPoint startingPoint ) + { + Queue points = new Queue( ); + points.Enqueue( startingPoint ); + + while ( points.Count > 0 ) + { + IntPoint point = points.Dequeue( ); + + int x = point.X; + int y = point.Y; + + // get image pointer for current (X, Y) + byte* p = (byte*) CoordsToPointerGray( x, y ); + + // find left end of line to fill + int leftLineEdge = x; + byte* ptr = p; + + while ( true ) + { + // fill current pixel + *ptr = fillG; + // mark the pixel as checked + checkedPixels[y, leftLineEdge] = true; + + leftLineEdge--; + ptr -= 1; + + // check if we need to stop on the edge of image or color area + if ( ( leftLineEdge < startX ) || ( checkedPixels[y, leftLineEdge] ) || ( !CheckGrayPixel( *ptr ) ) ) + break; + + } + leftLineEdge++; + + // find right end of line to fill + int rightLineEdge = x; + ptr = p; + + while ( true ) + { + // fill current pixel + *ptr = fillG; + // mark the pixel as checked + checkedPixels[y, rightLineEdge] = true; + + rightLineEdge++; + ptr += 1; + + // check if we need to stop on the edge of image or color area + if ( rightLineEdge > stopX || ( checkedPixels[y, rightLineEdge] ) || ( !CheckGrayPixel( *ptr ) ) ) + break; + } + rightLineEdge--; + + + // loop to go up and down + ptr = (byte*) CoordsToPointerGray( leftLineEdge, y ); + + bool upperPointIsQueued = false; + bool lowerPointIsQueued = false; + int upperY = y - 1; + int lowerY = y + 1; + + for ( int i = leftLineEdge; i <= rightLineEdge; i++, ptr++ ) + { + // go up + if ( ( y > startY ) && ( !checkedPixels[y - 1, i] ) && ( CheckGrayPixel( *( ptr - stride ) ) ) ) + { + if ( !upperPointIsQueued ) + { + points.Enqueue( new IntPoint( i, upperY ) ); + upperPointIsQueued = true; + } + } + else + { + upperPointIsQueued = false; + } + + // go down + if ( ( y < stopY ) && ( !checkedPixels[y + 1, i] ) && ( CheckGrayPixel( *( ptr + stride ) ) ) ) + { + if ( !lowerPointIsQueued ) + { + points.Enqueue( new IntPoint( i, lowerY ) ); + lowerPointIsQueued = true; + } + } + else + { + lowerPointIsQueued = false; + } + } + } + } + + // Liner flood fill in 4 directions for RGB + private unsafe void LinearFloodFill4RGB( IntPoint startPoint ) + { + Queue points = new Queue( ); + points.Enqueue( startingPoint ); + + while ( points.Count > 0 ) + { + IntPoint point = points.Dequeue( ); + + int x = point.X; + int y = point.Y; + + // get image pointer for current (X, Y) + byte* p = (byte*) CoordsToPointerRGB( x, y ); + + // find left end of line to fill + int leftLineEdge = x; + byte* ptr = p; + + while ( true ) + { + // fill current pixel + ptr[RGB.R] = fillR; + ptr[RGB.G] = fillG; + ptr[RGB.B] = fillB; + // mark the pixel as checked + checkedPixels[y, leftLineEdge] = true; + + leftLineEdge--; + ptr -= 3; + + // check if we need to stop on the edge of image or color area + if ( ( leftLineEdge < startX ) || ( checkedPixels[y, leftLineEdge] ) || ( !CheckRGBPixel( ptr ) ) ) + break; + + } + leftLineEdge++; + + // find right end of line to fill + int rightLineEdge = x; + ptr = p; + + while ( true ) + { + // fill current pixel + ptr[RGB.R] = fillR; + ptr[RGB.G] = fillG; + ptr[RGB.B] = fillB; + // mark the pixel as checked + checkedPixels[y, rightLineEdge] = true; + + rightLineEdge++; + ptr += 3; + + // check if we need to stop on the edge of image or color area + if ( rightLineEdge > stopX || ( checkedPixels[y, rightLineEdge] ) || ( !CheckRGBPixel( ptr ) ) ) + break; + } + rightLineEdge--; + + // loop to go up and down + ptr = (byte*) CoordsToPointerRGB( leftLineEdge, y ); + + bool upperPointIsQueued = false; + bool lowerPointIsQueued = false; + int upperY = y - 1; + int lowerY = y + 1; + + for ( int i = leftLineEdge; i <= rightLineEdge; i++, ptr += 3 ) + { + // go up + if ( ( y > startY ) && ( !checkedPixels[upperY, i] ) && ( CheckRGBPixel( ptr - stride ) ) ) + { + if ( !upperPointIsQueued ) + { + points.Enqueue( new IntPoint( i, upperY ) ); + upperPointIsQueued = true; + } + } + else + { + upperPointIsQueued = false; + } + + // go down + if ( ( y < stopY ) && ( !checkedPixels[lowerY, i] ) && ( CheckRGBPixel( ptr + stride ) ) ) + { + if ( !lowerPointIsQueued ) + { + points.Enqueue( new IntPoint( i, lowerY ) ); + lowerPointIsQueued = true; + } + } + else + { + lowerPointIsQueued = false; + } + } + } + } + + // Check if pixel equals to the starting color within required tolerance + private unsafe bool CheckGrayPixel( byte pixel ) + { + return ( pixel >= minG ) && ( pixel <= maxG ); + } + + // Check if pixel equals to the starting color within required tolerance + private unsafe bool CheckRGBPixel( byte* pixel ) + { + return ( pixel[RGB.R] >= minR ) && ( pixel[RGB.R] <= maxR ) && + ( pixel[RGB.G] >= minG ) && ( pixel[RGB.G] <= maxG ) && + ( pixel[RGB.B] >= minB ) && ( pixel[RGB.B] <= maxB ); + } + + // Convert image coordinate to pointer for Grayscale images + private byte* CoordsToPointerGray( int x, int y ) + { + return scan0 + ( stride * y ) + x; + } + + // Convert image coordinate to pointer for RGB images + private byte* CoordsToPointerRGB( int x, int y ) + { + return scan0 + ( stride * y ) + x * 3; + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Flood Fillers/PointedMeanFloodFill.cs b/Sources/Accord.Imaging/AForge/Filters/Flood Fillers/PointedMeanFloodFill.cs new file mode 100644 index 0000000000..84ed02bb5 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Flood Fillers/PointedMeanFloodFill.cs @@ -0,0 +1,407 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Flood filling with mean color starting from specified point. + /// + /// + /// The filter performs image's area filling (4 directional) starting + /// from the specified point. It fills + /// the area of the pointed color, but also fills other colors, which + /// are similar to the pointed within specified tolerance. + /// The area is filled using its mean color. + /// + /// + /// The filter is similar to filter, but instead + /// of filling the are with specified color, it fills the area with its mean color. This means + /// that this is a two pass filter - first pass is to calculate the mean value and the second pass is to + /// fill the area. Unlike to filter, this filter has nothing + /// to do in the case if zero tolerance is specified. + /// + /// The filter accepts 8 bpp grayscale images and 24 bpp + /// color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// PointedMeanFloodFill filter = new PointedMeanFloodFill( ); + /// // configre the filter + /// filter.Tolerance = Color.FromArgb( 150, 92, 92 ); + /// filter.StartingPoint = new IntPoint( 150, 100 ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + public unsafe class PointedMeanFloodFill : BaseInPlacePartialFilter + { + // map of pixels, which are already checked by the flood fill algorithm + private bool[,] checkedPixels; + + // set of variables (which describe image property and min/max color) to avoid passing them + // recursively as parameters + byte* scan0; // pointer to first image line + int stride; // size of image's line + int startX; // X1 of bounding rectangle + int stopX; // Y1 of bounding rectangle + int startY; // X2 of bounding rectangle (including) + int stopY; // Y2 of bounding rectangle (including) + + // min/max colors + byte minR, maxR; // min/max Red + byte minG, maxG; // min/max Green (Gray) color + byte minB, maxB; // min/max Blue + + // mean color + int meanR, meanG, meanB; + int pixelsCount = 0; + + // starting point to fill from + private IntPoint startingPoint = new IntPoint( 0, 0 ); + // filling tolerance + private Color tolerance = Color.FromArgb( 16, 16, 16 ); + + // format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + /// + /// See + /// documentation for additional information. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Flood fill tolerance. + /// + /// + /// The tolerance value determines the level of similarity between + /// colors to fill and the pointed color. If the value is set to zero, then the + /// filter does nothing, since the filling area contains only one color and its + /// filling with mean is meaningless. + /// + /// The tolerance value is specified as , + /// where each component (R, G and B) represents tolerance for the corresponding + /// component of color. This allows to set different tolerances for red, green + /// and blue components. + /// + /// Default value is set to (16, 16, 16). + /// + /// + public Color Tolerance + { + get { return tolerance; } + set { tolerance = value; } + } + + /// + /// Point to start filling from. + /// + /// + /// The property allows to set the starting point, where filling is + /// started from. + /// + /// Default value is set to (0, 0). + /// + /// + public IntPoint StartingPoint + { + get { return startingPoint; } + set { startingPoint = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public PointedMeanFloodFill( ) + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + // skip, if there is nothing to fill + if ( !rect.Contains( startingPoint.X, startingPoint.Y ) || ( tolerance == Color.Black ) ) + return; + + // save bounding rectangle + startX = rect.Left; + startY = rect.Top; + stopX = rect.Right - 1; + stopY = rect.Bottom - 1; + + // save image properties + scan0 = (byte*) image.ImageData.ToPointer( ); + stride = image.Stride; + + // create map of visited pixels + checkedPixels = new bool[image.Height, image.Width]; + + pixelsCount = meanR = meanG = meanB = 0; + + if ( image.PixelFormat == PixelFormat.Format8bppIndexed ) + { + byte startColor= *( (byte*) CoordsToPointerGray( startingPoint.X, startingPoint.Y ) ); + minG = (byte) ( Math.Max( 0, startColor - tolerance.G ) ); + maxG = (byte) ( Math.Min( 255, startColor + tolerance.G ) ); + + LinearFloodFill4Gray( startingPoint.X, startingPoint.Y ); + + // calculate mean value + meanG /= pixelsCount; + byte fillG = (byte) meanG; + + // do fill with the mean + byte* src = (byte*) image.ImageData.ToPointer( ); + // allign pointer to the first pixel to process + src += ( startY * stride + startX ); + + int offset = stride - rect.Width; + + // for each line + for ( int y = startY; y <= stopY; y++ ) + { + // for each pixel + for ( int x = startX; x <= stopX; x++, src++ ) + { + if ( checkedPixels[y, x] ) + { + *src = fillG; + } + } + src += offset; + } + } + else + { + byte* startColor= (byte*) CoordsToPointerRGB( startingPoint.X, startingPoint.Y ); + + minR = (byte) ( Math.Max( 0, startColor[RGB.R] - tolerance.R ) ); + maxR = (byte) ( Math.Min( 255, startColor[RGB.R] + tolerance.R ) ); + minG = (byte) ( Math.Max( 0, startColor[RGB.G] - tolerance.G ) ); + maxG = (byte) ( Math.Min( 255, startColor[RGB.G] + tolerance.G ) ); + minB = (byte) ( Math.Max( 0, startColor[RGB.B] - tolerance.B ) ); + maxB = (byte) ( Math.Min( 255, startColor[RGB.B] + tolerance.B ) ); + + LinearFloodFill4RGB( startingPoint.X, startingPoint.Y ); + + // calculate mean value + meanR /= pixelsCount; + meanG /= pixelsCount; + meanB /= pixelsCount; + + byte fillR = (byte) meanR; + byte fillG = (byte) meanG; + byte fillB = (byte) meanB; + + // do fill with the mean + byte* src = (byte*) image.ImageData.ToPointer( ); + // allign pointer to the first pixel to process + src += ( startY * stride + startX * 3); + + int offset = stride - rect.Width * 3; + + // for each line + for ( int y = startY; y <= stopY; y++ ) + { + // for each pixel + for ( int x = startX; x <= stopX; x++, src += 3 ) + { + if ( checkedPixels[y, x] ) + { + src[RGB.R] = fillR; + src[RGB.G] = fillG; + src[RGB.B] = fillB; + } + } + src += offset; + } + } + } + + // Liner flood fill in 4 directions for grayscale images + private unsafe void LinearFloodFill4Gray( int x, int y ) + { + // get image pointer for current (X, Y) + byte* p = (byte*) CoordsToPointerGray( x, y ); + + // find left end of line to fill + int leftLineEdge = x; + byte* ptr = p; + + while ( true ) + { + // sum value of the current pixel + meanG += *ptr; + pixelsCount++; + // mark the pixel as checked + checkedPixels[y, leftLineEdge] = true; + + leftLineEdge--; + ptr -= 1; + + // check if we need to stop on the edge of image or color area + if ( ( leftLineEdge < startX ) || ( checkedPixels[y, leftLineEdge] ) || ( !CheckGrayPixel( *ptr ) ) ) + break; + + } + leftLineEdge++; + + // find right end of line to fill + int rightLineEdge = x + 1; + ptr = p + 1; + + // while we don't need to stop on the edge of image or color area + while ( !( rightLineEdge > stopX || ( checkedPixels[y, rightLineEdge] ) || ( !CheckGrayPixel( *ptr ) ) ) ) + { + // sum value of the current pixel + meanG += *ptr; + pixelsCount++; + // mark the pixel as checked + checkedPixels[y, rightLineEdge] = true; + + rightLineEdge++; + ptr += 1; + + } + rightLineEdge--; + + + // loop to go up and down + ptr = (byte*) CoordsToPointerGray( leftLineEdge, y ); + for ( int i = leftLineEdge; i <= rightLineEdge; i++, ptr++ ) + { + // go up + if ( ( y > startY ) && ( !checkedPixels[y - 1, i] ) && ( CheckGrayPixel( *( ptr - stride ) ) ) ) + LinearFloodFill4Gray( i, y - 1 ); + // go down + if ( ( y < stopY ) && ( !checkedPixels[y + 1, i] ) && ( CheckGrayPixel( *( ptr + stride ) ) ) ) + LinearFloodFill4Gray( i, y + 1 ); + } + } + + // Liner flood fill in 4 directions for RGB + private unsafe void LinearFloodFill4RGB( int x, int y ) + { + // get image pointer for current (X, Y) + byte* p = (byte*) CoordsToPointerRGB( x, y ); + + // find left end of line to fill + int leftLineEdge = x; + byte* ptr = p; + + while ( true ) + { + // sum value of the current pixel + meanR += ptr[RGB.R]; + meanG += ptr[RGB.G]; + meanB += ptr[RGB.B]; + pixelsCount++; + // mark the pixel as checked + checkedPixels[y, leftLineEdge] = true; + + leftLineEdge--; + ptr -= 3; + + // check if we need to stop on the edge of image or color area + if ( ( leftLineEdge < startX ) || ( checkedPixels[y, leftLineEdge] ) || ( !CheckRGBPixel( ptr ) ) ) + break; + + } + leftLineEdge++; + + // find right end of line to fill + int rightLineEdge = x + 1; + ptr = p + 3; + + // while we don't need to stop on the edge of image or color area + while ( !( rightLineEdge > stopX || ( checkedPixels[y, rightLineEdge] ) || ( !CheckRGBPixel( ptr ) ) ) ) + { + // sum value of the current pixel + meanR += ptr[RGB.R]; + meanG += ptr[RGB.G]; + meanB += ptr[RGB.B]; + pixelsCount++; + // mark the pixel as checked + checkedPixels[y, rightLineEdge] = true; + + rightLineEdge++; + ptr += 3; + } + rightLineEdge--; + + + // loop to go up and down + ptr = (byte*) CoordsToPointerRGB( leftLineEdge, y ); + for ( int i = leftLineEdge; i <= rightLineEdge; i++, ptr += 3 ) + { + // go up + if ( ( y > startY ) && ( !checkedPixels[y - 1, i] ) && ( CheckRGBPixel( ptr - stride ) ) ) + LinearFloodFill4RGB( i, y - 1 ); + // go down + if ( ( y < stopY ) && ( !checkedPixels[y + 1, i] ) && ( CheckRGBPixel( ptr + stride ) ) ) + LinearFloodFill4RGB( i, y + 1 ); + } + } + + // Check if pixel equals to the starting color within required tolerance + private unsafe bool CheckGrayPixel( byte pixel ) + { + return ( pixel >= minG ) && ( pixel <= maxG ); + } + + // Check if pixel equals to the starting color within required tolerance + private unsafe bool CheckRGBPixel( byte* pixel ) + { + return ( pixel[RGB.R] >= minR ) && ( pixel[RGB.R] <= maxR ) && + ( pixel[RGB.G] >= minG ) && ( pixel[RGB.G] <= maxG ) && + ( pixel[RGB.B] >= minB ) && ( pixel[RGB.B] <= maxB ); + } + + // Convert image coordinate to pointer for Grayscale images + private byte* CoordsToPointerGray( int x, int y ) + { + return scan0 + ( stride * y ) + x; + } + + // Convert image coordinate to pointer for RGB images + private byte* CoordsToPointerRGB( int x, int y ) + { + return scan0 + ( stride * y ) + x * 3; + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/HSL Filters/HSLFiltering.cs b/Sources/Accord.Imaging/AForge/Filters/HSL Filters/HSLFiltering.cs new file mode 100644 index 0000000000..d913fceac --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/HSL Filters/HSLFiltering.cs @@ -0,0 +1,312 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + using AForge; + + /// + /// Color filtering in HSL color space. + /// + /// + /// The filter operates in HSL color space and filters + /// pixels, which color is inside/outside of the specified HSL range - + /// it keeps pixels with colors inside/outside of the specified range and fills the + /// rest with specified color. + /// + /// The filter accepts 24 and 32 bpp color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// HSLFiltering filter = new HSLFiltering( ); + /// // set color ranges to keep + /// filter.Hue = new IntRange( 335, 0 ); + /// filter.Saturation = new Range( 0.6f, 1 ); + /// filter.Luminance = new Range( 0.1f, 1 ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// Sample usage with saturation update only: + /// + /// // create filter + /// HSLFiltering filter = new HSLFiltering( ); + /// // configure the filter + /// filter.Hue = new IntRange( 340, 20 ); + /// filter.UpdateLuminance = false; + /// filter.UpdateHue = false; + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Result image: + /// + /// + /// + /// + /// + /// + public class HSLFiltering : BaseInPlacePartialFilter + { + private IntRange hue = new IntRange( 0, 359 ); + private Range saturation = new Range( 0.0f, 1.0f ); + private Range luminance = new Range( 0.0f, 1.0f ); + + private int fillH = 0; + private float fillS = 0.0f; + private float fillL = 0.0f; + private bool fillOutsideRange = true; + + private bool updateH = true; + private bool updateS = true; + private bool updateL = true; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + #region Public properties + + /// + /// Range of hue component, [0, 359]. + /// + /// + /// Because of hue values are cycled, the minimum value of the hue + /// range may have bigger integer value than the maximum value, for example [330, 30]. + /// + public IntRange Hue + { + get { return hue; } + set { hue = value; } + } + + /// + /// Range of saturation component, [0, 1]. + /// + public Range Saturation + { + get { return saturation; } + set { saturation = value; } + } + + /// + /// Range of luminance component, [0, 1]. + /// + public Range Luminance + { + get { return luminance; } + set { luminance = value; } + } + + /// + /// Fill color used to fill filtered pixels. + /// + public HSL FillColor + { + get { return new HSL( fillH, fillS, fillL ); } + set + { + fillH = value.Hue; + fillS = value.Saturation; + fillL = value.Luminance; + } + } + + /// + /// Determines, if pixels should be filled inside or outside specified + /// color range. + /// + /// + /// Default value is set to , which means + /// the filter removes colors outside of the specified range. + /// + public bool FillOutsideRange + { + get { return fillOutsideRange; } + set { fillOutsideRange = value; } + } + + /// + /// Determines, if hue value of filtered pixels should be updated. + /// + /// + /// The property specifies if hue of filtered pixels should be + /// updated with value from fill color or not. + /// + /// Default value is set to . + /// + public bool UpdateHue + { + get { return updateH; } + set { updateH = value; } + } + + /// + /// Determines, if saturation value of filtered pixels should be updated. + /// + /// + /// The property specifies if saturation of filtered pixels should be + /// updated with value from fill color or not. + /// + /// Default value is set to . + /// + public bool UpdateSaturation + { + get { return updateS; } + set { updateS = value; } + } + + /// + /// Determines, if luminance value of filtered pixels should be updated. + /// + /// + /// The property specifies if luminance of filtered pixels should be + /// updated with value from fill color or not. + /// + /// Default value is set to . + /// + public bool UpdateLuminance + { + get { return updateL; } + set { updateL = value; } + } + + #endregion + + + /// + /// Initializes a new instance of the class. + /// + public HSLFiltering( ) + { + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Range of hue component. + /// Range of saturation component. + /// Range of luminance component. + /// + public HSLFiltering( IntRange hue, Range saturation, Range luminance ) : + this( ) + { + this.hue = hue; + this.saturation = saturation; + this.luminance = luminance; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + // get pixel size + int pixelSize = ( image.PixelFormat == PixelFormat.Format24bppRgb ) ? 3 : 4; + + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + int offset = image.Stride - rect.Width * pixelSize; + + RGB rgb = new RGB( ); + HSL hsl = new HSL( ); + + bool updated; + + // do the job + byte* ptr = (byte*) image.ImageData.ToPointer( ); + + // allign pointer to the first pixel to process + ptr += ( startY * image.Stride + startX * pixelSize ); + + // for each row + for ( int y = startY; y < stopY; y++ ) + { + // for each pixel + for ( int x = startX; x < stopX; x++, ptr += pixelSize ) + { + updated = false; + rgb.Red = ptr[RGB.R]; + rgb.Green = ptr[RGB.G]; + rgb.Blue = ptr[RGB.B]; + + // convert to HSL + AForge.Imaging.HSL.FromRGB( rgb, hsl ); + + // check HSL values + if ( + ( hsl.Saturation >= saturation.Min ) && ( hsl.Saturation <= saturation.Max ) && + ( hsl.Luminance >= luminance.Min ) && ( hsl.Luminance <= luminance.Max ) && + ( + ( ( hue.Min < hue.Max ) && ( hsl.Hue >= hue.Min ) && ( hsl.Hue <= hue.Max ) ) || + ( ( hue.Min > hue.Max ) && ( ( hsl.Hue >= hue.Min ) || ( hsl.Hue <= hue.Max ) ) ) + ) + ) + { + if ( !fillOutsideRange ) + { + if ( updateH ) hsl.Hue = fillH; + if ( updateS ) hsl.Saturation = fillS; + if ( updateL ) hsl.Luminance = fillL; + + updated = true; + } + } + else + { + if ( fillOutsideRange ) + { + if ( updateH ) hsl.Hue = fillH; + if ( updateS ) hsl.Saturation = fillS; + if ( updateL ) hsl.Luminance = fillL; + + updated = true; + } + } + + if ( updated ) + { + // convert back to RGB + AForge.Imaging.HSL.ToRGB( hsl, rgb ); + + ptr[RGB.R] = rgb.Red; + ptr[RGB.G] = rgb.Green; + ptr[RGB.B] = rgb.Blue; + } + } + ptr += offset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/HSL Filters/HSLLinear.cs b/Sources/Accord.Imaging/AForge/Filters/HSL Filters/HSLLinear.cs new file mode 100644 index 0000000000..36c513afd --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/HSL Filters/HSLLinear.cs @@ -0,0 +1,209 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + using AForge; + + /// + /// Luminance and saturation linear correction. + /// + /// + /// The filter operates in HSL color space and provides + /// with the facility of luminance and saturation linear correction - mapping specified channels' + /// input ranges to specified output ranges. + /// + /// The filter accepts 24 and 32 bpp color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// HSLLinear filter = new HSLLinear( ); + /// // configure the filter + /// filter.InLuminance = new Range( 0, 0.85f ); + /// filter.OutSaturation = new Range( 0.25f, 1 ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + public class HSLLinear : BaseInPlacePartialFilter + { + private Range inLuminance = new Range( 0.0f, 1.0f ); + private Range inSaturation = new Range( 0.0f, 1.0f ); + private Range outLuminance = new Range( 0.0f, 1.0f ); + private Range outSaturation = new Range( 0.0f, 1.0f ); + + #region Public Propertis + + /// + /// Luminance input range. + /// + /// + /// Luminance component is measured in the range of [0, 1]. + /// + public Range InLuminance + { + get { return inLuminance; } + set { inLuminance = value; } + } + + /// + /// Luminance output range. + /// + /// + /// Luminance component is measured in the range of [0, 1]. + /// + public Range OutLuminance + { + get { return outLuminance; } + set { outLuminance = value; } + } + + /// + /// Saturation input range. + /// + /// + /// Saturation component is measured in the range of [0, 1]. + /// + public Range InSaturation + { + get { return inSaturation; } + set { inSaturation = value; } + } + + /// + /// Saturation output range. + /// + /// + /// Saturation component is measured in the range of [0, 1]. + /// + public Range OutSaturation + { + get { return outSaturation; } + set { outSaturation = value; } + } + + #endregion + + // format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public HSLLinear( ) + { + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + int pixelSize = Image.GetPixelFormatSize( image.PixelFormat ) / 8; + + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + int offset = image.Stride - rect.Width * pixelSize; + + RGB rgb = new RGB( ); + HSL hsl = new HSL( ); + + float kl = 0, bl = 0; + float ks = 0, bs = 0; + + // luminance line parameters + if ( inLuminance.Max != inLuminance.Min ) + { + kl = ( outLuminance.Max - outLuminance.Min ) / ( inLuminance.Max - inLuminance.Min ); + bl = outLuminance.Min - kl * inLuminance.Min; + } + // saturation line parameters + if ( inSaturation.Max != inSaturation.Min ) + { + ks = ( outSaturation.Max - outSaturation.Min ) / ( inSaturation.Max - inSaturation.Min ); + bs = outSaturation.Min - ks * inSaturation.Min; + } + + // do the job + byte* ptr = (byte*) image.ImageData.ToPointer( ); + + // allign pointer to the first pixel to process + ptr += ( startY * image.Stride + startX * pixelSize ); + + // for each row + for ( int y = startY; y < stopY; y++ ) + { + // for each pixel + for ( int x = startX; x < stopX; x++, ptr += pixelSize ) + { + rgb.Red = ptr[RGB.R]; + rgb.Green = ptr[RGB.G]; + rgb.Blue = ptr[RGB.B]; + + // convert to HSL + AForge.Imaging.HSL.FromRGB( rgb, hsl ); + + // do luminance correction + if ( hsl.Luminance >= inLuminance.Max ) + hsl.Luminance = outLuminance.Max; + else if ( hsl.Luminance <= inLuminance.Min ) + hsl.Luminance = outLuminance.Min; + else + hsl.Luminance = kl * hsl.Luminance + bl; + + // do saturation correct correction + if ( hsl.Saturation >= inSaturation.Max ) + hsl.Saturation = outSaturation.Max; + else if ( hsl.Saturation <= inSaturation.Min ) + hsl.Saturation = outSaturation.Min; + else + hsl.Saturation = ks * hsl.Saturation + bs; + + // convert back to RGB + AForge.Imaging.HSL.ToRGB( hsl, rgb ); + + ptr[RGB.R] = rgb.Red; + ptr[RGB.G] = rgb.Green; + ptr[RGB.B] = rgb.Blue; + } + ptr += offset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/HSL Filters/HueModifier.cs b/Sources/Accord.Imaging/AForge/Filters/HSL Filters/HueModifier.cs new file mode 100644 index 0000000000..ebc05ea78 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/HSL Filters/HueModifier.cs @@ -0,0 +1,143 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Hue modifier. + /// + /// + /// The filter operates in HSL color space and updates + /// pixels' hue values setting it to the specified value (luminance and + /// saturation are kept unchanged). The result of the filter looks like the image + /// is observed through a glass of the given color. + /// + /// The filter accepts 24 and 32 bpp color images for processing. + /// Sample usage: + /// + /// // create filter + /// HueModifier filter = new HueModifier( 180 ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class HueModifier : BaseInPlacePartialFilter + { + private int hue = 0; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Hue value to set, [0, 359]. + /// + /// + /// Default value is set to 0. + /// + public int Hue + { + get { return hue; } + set { hue = Math.Max( 0, Math.Min( 359, value ) ); } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public HueModifier( ) + { + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + formatTranslations[PixelFormat.Format32bppPArgb] = PixelFormat.Format32bppPArgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Hue value to set. + /// + public HueModifier( int hue ) : this( ) + { + this.hue = hue; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + int pixelSize = Bitmap.GetPixelFormatSize( image.PixelFormat ) / 8; + + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + int offset = image.Stride - rect.Width * pixelSize; + + RGB rgb = new RGB( ); + HSL hsl = new HSL( ); + + // do the job + byte* ptr = (byte*) image.ImageData.ToPointer( ); + + // allign pointer to the first pixel to process + ptr += ( startY * image.Stride + startX * pixelSize ); + + // for each row + for ( int y = startY; y < stopY; y++ ) + { + // for each pixel + for ( int x = startX; x < stopX; x++, ptr += pixelSize ) + { + rgb.Red = ptr[RGB.R]; + rgb.Green = ptr[RGB.G]; + rgb.Blue = ptr[RGB.B]; + + // convert to HSL + AForge.Imaging.HSL.FromRGB( rgb, hsl ); + + // modify hue value + hsl.Hue = hue; + + // convert back to RGB + AForge.Imaging.HSL.ToRGB( hsl, rgb ); + + ptr[RGB.R] = rgb.Red; + ptr[RGB.G] = rgb.Green; + ptr[RGB.B] = rgb.Blue; + } + ptr += offset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/HSL Filters/SaturationCorrection.cs b/Sources/Accord.Imaging/AForge/Filters/HSL Filters/SaturationCorrection.cs new file mode 100644 index 0000000000..b08567c5d --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/HSL Filters/SaturationCorrection.cs @@ -0,0 +1,155 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright AForge.NET, 2007-2014 +// aforge.net@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + using AForge; + + /// + /// Saturation adjusting in HSL color space. + /// + /// + /// The filter operates in HSL color space and adjusts + /// pixels' saturation value, increasing it or decreasing by specified percentage. + /// The filters is based on filter, passing work to it after + /// recalculating saturation adjust value to input/output + /// ranges of the filter. + /// + /// The filter accepts 24 and 32 bpp color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// SaturationCorrection filter = new SaturationCorrection( -0.5f ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class SaturationCorrection : BaseInPlacePartialFilter + { + private float adjustValue; // [-1, 1] + + /// + /// Saturation adjust value, [-1, 1]. + /// + /// + /// Default value is set to 0.1, which corresponds to increasing + /// saturation by 10%. + /// + public float AdjustValue + { + get { return adjustValue; } + set { adjustValue = Math.Max( -1.0f, Math.Min( 1.0f, value ) ); } + } + + // format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public SaturationCorrection( ) : this( 0.1f ) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Saturation adjust value. + /// + public SaturationCorrection( float adjustValue ) + { + AdjustValue = adjustValue; + + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + formatTranslations[PixelFormat.Format32bppPArgb] = PixelFormat.Format32bppPArgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + int pixelSize = Bitmap.GetPixelFormatSize( image.PixelFormat ) / 8; + + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + int offset = image.Stride - rect.Width * pixelSize; + + RGB rgb = new RGB( ); + HSL hsl = new HSL( ); + + float desaturationChangeFactor = 1.0f + adjustValue; + + // do the job + byte* ptr = (byte*) image.ImageData.ToPointer( ); + + // allign pointer to the first pixel to process + ptr += ( startY * image.Stride + startX * pixelSize ); + + // for each row + for ( int y = startY; y < stopY; y++ ) + { + // for each pixel + for ( int x = startX; x < stopX; x++, ptr += pixelSize ) + { + rgb.Red = ptr[RGB.R]; + rgb.Green = ptr[RGB.G]; + rgb.Blue = ptr[RGB.B]; + + // convert to HSL + AForge.Imaging.HSL.FromRGB( rgb, hsl ); + + if ( adjustValue > 0 ) + { + hsl.Saturation += ( 1.0f - hsl.Saturation ) * adjustValue * hsl.Saturation; + } + else if ( adjustValue < 0 ) + { + hsl.Saturation *= desaturationChangeFactor; + } + + // convert back to RGB + AForge.Imaging.HSL.ToRGB( hsl, rgb ); + + ptr[RGB.R] = rgb.Red; + ptr[RGB.G] = rgb.Green; + ptr[RGB.B] = rgb.Blue; + } + ptr += offset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/IFilter.cs b/Sources/Accord.Imaging/AForge/Filters/IFilter.cs new file mode 100644 index 0000000000..f39e6545e --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/IFilter.cs @@ -0,0 +1,91 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2010 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Image processing filter interface. + /// + /// + /// The interface defines the set of methods, which should be + /// provided by all image processing filters. Methods of this interface + /// keep the source image unchanged and returt the result of image processing + /// filter as new image. + /// + /// + /// + /// + public interface IFilter + { + /// + /// Apply filter to an image. + /// + /// + /// Source image to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The method keeps the source image unchanged and returns + /// the result of image processing filter as new image. + /// + Bitmap Apply( Bitmap image ); + + /// + /// Apply filter to an image. + /// + /// + /// Source image to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The filter accepts bitmap data as input and returns the result + /// of image processing filter as new image. The source image data are kept + /// unchanged. + /// + Bitmap Apply( BitmapData imageData ); + + /// + /// Apply filter to an image. + /// + /// + /// Image in unmanaged memory. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The method keeps the source image unchanged and returns + /// the result of image processing filter as new image. + /// + UnmanagedImage Apply( UnmanagedImage image ); + + /// + /// Apply filter to an image. + /// + /// + /// Source image to be processed. + /// Destination image to store filter's result. + /// + /// The method keeps the source image unchanged and puts the + /// the result of image processing filter into destination image. + /// + /// The destination image must have the size, which is expected by + /// the filter. + /// + /// + /// In the case if destination image has incorrect + /// size. + /// + void Apply( UnmanagedImage sourceImage, UnmanagedImage destinationImage ); + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/IFilterInformation.cs b/Sources/Accord.Imaging/AForge/Filters/IFilterInformation.cs new file mode 100644 index 0000000000..b55808d3a --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/IFilterInformation.cs @@ -0,0 +1,62 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright © Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Interface which provides information about image processing filter. + /// + /// + /// The interface defines set of properties, which provide different type + /// of information about image processing filters implementing interface + /// or another filter's interface. + /// + public interface IFilterInformation + { + /// + /// Format translations dictionary. + /// + /// + /// The dictionary defines, which pixel formats are supported for + /// source images and which pixel format will be used for resulting image. + /// + /// + /// Keys of this dictionary defines all pixel formats which are supported for source + /// images, but corresponding values define what will be resulting pixel format. For + /// example, if value Format16bppGrayScale + /// is put into the dictionary with the + /// Format48bppRgb key, then it means + /// that the filter accepts color 48 bpp image and produces 16 bpp grayscale image as a result + /// of image processing. + /// + /// The information provided by this property is mostly actual for filters, which can not + /// be applied directly to the source image, but provide new image a result. Since usually all + /// filters implement interface, the information provided by this property + /// (if filter also implements interface) may be useful to + /// user to resolve filter's capabilities. + /// + /// Sample usage: + /// + /// // get filter's IFilterInformation interface + /// IFilterInformation info = (IFilterInformation) filter; + /// // check if the filter supports our image's format + /// if ( info.FormatTranslations.ContainsKey( image.PixelFormat ) + /// { + /// // format is supported, check what will be result of image processing + /// PixelFormat resultingFormat = info.FormatTranslations[image.PixelFormat]; + /// } + /// /// + /// + /// + Dictionary FormatTranslations { get; } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/IInPlaceFilter.cs b/Sources/Accord.Imaging/AForge/Filters/IInPlaceFilter.cs new file mode 100644 index 0000000000..a9ac50966 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/IInPlaceFilter.cs @@ -0,0 +1,61 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// In-place filter interface. + /// + /// + /// The interface defines the set of methods, which should be + /// implemented by filters, which are capable to do image processing + /// directly on the source image. Not all image processing filters + /// can be applied directly to the source image - only filters, which do not + /// change image's dimension and pixel format, can be applied directly to the + /// source image. + /// + /// + /// + /// + public interface IInPlaceFilter + { + /// + /// Apply filter to an image. + /// + /// + /// Image to apply filter to. + /// + /// The method applies filter directly to the provided image data. + /// + void ApplyInPlace( Bitmap image ); + + /// + /// Apply filter to an image. + /// + /// + /// Image to apply filter to. + /// + /// The method applies filter directly to the provided image data. + /// + void ApplyInPlace( BitmapData imageData ); + + /// + /// Apply filter to an image in unmanaged memory. + /// + /// + /// Image in unmanaged memory. + /// + /// The method applies filter directly to the provided image data. + /// + void ApplyInPlace( UnmanagedImage image ); + } +} + diff --git a/Sources/Accord.Imaging/AForge/Filters/IInPlacePartialFilter.cs b/Sources/Accord.Imaging/AForge/Filters/IInPlacePartialFilter.cs new file mode 100644 index 0000000000..1d46f2f75 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/IInPlacePartialFilter.cs @@ -0,0 +1,67 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// In-place partial filter interface. + /// + /// + /// The interface defines the set of methods, which should be + /// implemented by filters, which are capable to do image processing + /// directly on the source image. Not all image processing filters + /// can be applied directly to the source image - only filters, which do not + /// change image dimension and pixel format, can be applied directly to the + /// source image. + /// + /// The interface also supports partial image filtering, allowing to specify + /// image rectangle, which should be filtered. + /// + /// + /// + /// + /// + public interface IInPlacePartialFilter + { + /// + /// Apply filter to an image or its part. + /// + /// + /// Image to apply filter to. + /// Image rectangle for processing by filter. + /// + /// The method applies filter directly to the provided image data. + /// + void ApplyInPlace( Bitmap image, Rectangle rect ); + + /// + /// Apply filter to an image or its part. + /// + /// + /// Image to apply filter to. + /// Image rectangle for processing by filter. + /// + /// The method applies filter directly to the provided image data. + /// + void ApplyInPlace( BitmapData imageData, Rectangle rect ); + + /// + /// Apply filter to an image in unmanaged memory. + /// + /// + /// Image in unmanaged memory. + /// Image rectangle for processing by filter. + /// + /// The method applies filter directly to the provided image. + /// + void ApplyInPlace( UnmanagedImage image, Rectangle rect ); + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/IlluminationCorrection/FlatFieldCorrection.cs b/Sources/Accord.Imaging/AForge/Filters/IlluminationCorrection/FlatFieldCorrection.cs new file mode 100644 index 0000000000..82a63f248 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/IlluminationCorrection/FlatFieldCorrection.cs @@ -0,0 +1,283 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright +// Mladen Prajdic (spirit1_fe@yahoo.com), +// Andrew Kirillov (andrew.kirillov@aforgenet.com) +// 2005-2009 +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Flat field correction filter. + /// + /// + /// The goal of flat-field correction is to remove artifacts from 2-D images that + /// are caused by variations in the pixel-to-pixel sensitivity of the detector and/or by distortions + /// in the optical path. The filter requires two images for the input - source image, which represents + /// acquisition of some objects (using microscope, for example), and background image, which is taken + /// without any objects presented. The source image is corrected using the formula: src = bgMean * src / bg, + /// where src - source image's pixel value, bg - background image's pixel value, bgMean - mean + /// value of background image. + /// + /// If background image is not provided, then it will be automatically generated on each filter run + /// from source image. The automatically generated background image is produced running Gaussian Blur on the + /// original image with (sigma value is set to 5, kernel size is set to 21). Before blurring the original image + /// is resized to 1/3 of its original size and then the result of blurring is resized back to the original size. + /// + /// + /// The class processes only grayscale (8 bpp indexed) and color (24 bpp) images. + /// + /// Sample usage: + /// + /// // create filter + /// FlatFieldCorrection filter = new FlatFieldCorrection( bgImage ); + /// // process image + /// filter.ApplyInPlace( sourceImage ); + /// + /// + /// Source image: + /// + /// Background image: + /// + /// Result image: + /// + /// + /// + public class FlatFieldCorrection : BaseInPlaceFilter + { + Bitmap backgroundImage = null; + UnmanagedImage unmanagedBackgroundImage = null; + + /// + /// Background image used for flat field correction. + /// + /// + /// The property sets the background image (without any objects), which will be used + /// for illumination correction of an image passed to the filter. + /// + /// The background image must have the same size and pixel format as source image. + /// Otherwise exception will be generated when filter is applied to source image. + /// + /// Setting this property will clear the property - + /// only one background image is allowed: managed or unmanaged. + /// + /// + public Bitmap BackgoundImage + { + get { return backgroundImage; } + set + { + backgroundImage = value; + + if ( value != null ) + unmanagedBackgroundImage = null; + } + } + + /// + /// Background image used for flat field correction. + /// + /// + /// The property sets the background image (without any objects), which will be used + /// for illumination correction of an image passed to the filter. + /// + /// The background image must have the same size and pixel format as source image. + /// Otherwise exception will be generated when filter is applied to source image. + /// + /// Setting this property will clear the property - + /// only one background image is allowed: managed or unmanaged. + /// + /// + public UnmanagedImage UnmanagedBackgoundImage + { + get { return unmanagedBackgroundImage; } + set + { + unmanagedBackgroundImage = value; + + if ( value != null ) + backgroundImage = null; + } + } + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + /// + /// See for more information. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// This constructor does not set background image, which means that background + /// image will be generated on the fly on each filter run. The automatically generated background + /// image is produced running Gaussian Blur on the original image with (sigma value is set to 5, + /// kernel size is set to 21). Before blurring the original image is resized to 1/3 of its original size + /// and then the result of blurring is resized back to the original size. + /// + public FlatFieldCorrection( ) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Background image used for flat field correction. + /// + public FlatFieldCorrection( Bitmap backgroundImage ) : this( ) + { + this.backgroundImage = backgroundImage; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image ) + { + UnmanagedImage bgImage = null; + BitmapData bgLockedData = null; + + // get image size + int width = image.Width; + int height = image.Height; + int offset = image.Stride - ( ( image.PixelFormat == PixelFormat.Format8bppIndexed ) ? width : width * 3 ); + + // check if we have provided background + if ( ( backgroundImage == null ) && ( unmanagedBackgroundImage == null ) ) + { + // resize image to 1/3 of its original size to make bluring faster + ResizeBicubic resizeFilter = new ResizeBicubic( (int) width / 3, (int) height / 3 ); + UnmanagedImage tempImage = resizeFilter.Apply( image ); + + // create background image from the input image blurring it with Gaussian 5 times + GaussianBlur blur = new GaussianBlur( 5, 21 ); + + blur.ApplyInPlace( tempImage ); + blur.ApplyInPlace( tempImage ); + blur.ApplyInPlace( tempImage ); + blur.ApplyInPlace( tempImage ); + blur.ApplyInPlace( tempImage ); + + // resize the blurred image back to original size + resizeFilter.NewWidth = width; + resizeFilter.NewHeight = height; + bgImage = resizeFilter.Apply( tempImage ); + + tempImage.Dispose( ); + } + else + { + if ( backgroundImage != null ) + { + // check background image + if ( ( width != backgroundImage.Width ) || ( height != backgroundImage.Height ) || ( image.PixelFormat != backgroundImage.PixelFormat ) ) + { + throw new InvalidImagePropertiesException( "Source image and background images must have the same size and pixel format" ); + } + + // lock background image + bgLockedData = backgroundImage.LockBits( + new Rectangle( 0, 0, width, height ), + ImageLockMode.ReadOnly, backgroundImage.PixelFormat ); + + bgImage = new UnmanagedImage( bgLockedData ); + } + else + { + bgImage = unmanagedBackgroundImage; + } + } + + // get background image's statistics (mean value is used as correction factor) + ImageStatistics bgStatistics = new ImageStatistics( bgImage ); + + byte* src = (byte*) image.ImageData.ToPointer( ); + byte* bg = (byte*) bgImage.ImageData.ToPointer( ); + + // do the job + if ( image.PixelFormat == PixelFormat.Format8bppIndexed ) + { + // grayscale image + double mean = bgStatistics.Gray.Mean; + + for ( int y = 0; y < height; y++ ) + { + for ( int x = 0; x < width; x++, src++, bg++ ) + { + if ( *bg != 0 ) + { + *src = (byte) Math.Min( mean * *src / *bg, 255 ); + } + } + src += offset; + bg += offset; + } + } + else + { + // color image + double meanR = bgStatistics.Red.Mean; + double meanG = bgStatistics.Green.Mean; + double meanB = bgStatistics.Blue.Mean; + + for ( int y = 0; y < height; y++ ) + { + for ( int x = 0; x < width; x++, src += 3, bg += 3 ) + { + // red + if ( bg[RGB.R] != 0 ) + { + src[RGB.R] = (byte) Math.Min( meanR * src[RGB.R] / bg[RGB.R], 255 ); + } + // green + if ( bg[RGB.G] != 0 ) + { + src[RGB.G] = (byte) Math.Min( meanG * src[RGB.G] / bg[RGB.G], 255 ); + } + // blue + if ( bg[RGB.B] != 0 ) + { + src[RGB.B] = (byte) Math.Min( meanB * src[RGB.B] / bg[RGB.B], 255 ); + } + } + src += offset; + bg += offset; + } + } + + if ( backgroundImage != null ) + { + backgroundImage.UnlockBits( bgLockedData ); + } + + // dispose background image if it was not set manually + if ( ( backgroundImage == null ) && ( unmanagedBackgroundImage == null ) ) + { + bgImage.Dispose( ); + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Morphology/BottomHat.cs b/Sources/Accord.Imaging/AForge/Filters/Morphology/BottomHat.cs new file mode 100644 index 0000000000..1d46b0988 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Morphology/BottomHat.cs @@ -0,0 +1,105 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Bottop-hat operator from Mathematical Morphology. + /// + /// + /// Bottom-hat morphological operator subtracts + /// input image from the result of morphological closing on the + /// the input image. + /// + /// Applied to binary image, the filter allows to get all object parts, which were + /// added by closing filter, but were not removed after that due + /// to formed connections/fillings. + /// + /// The filter accepts 8 and 16 bpp grayscale images and 24 and 48 bpp + /// color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// BottomHat filter = new BottomHat( ); + /// // apply the filter + /// filter.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + public class BottomHat : BaseInPlaceFilter + { + private Closing closing = new Closing( ); + private Subtract subtract = new Subtract( ); + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public BottomHat( ) + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format16bppGrayScale] = PixelFormat.Format16bppGrayScale; + formatTranslations[PixelFormat.Format48bppRgb] = PixelFormat.Format48bppRgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Structuring element to pass to operator. + /// + public BottomHat( short[,] se ) : this( ) + { + closing = new Closing( se ); + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image ) + { + // copy source image + UnmanagedImage sourceImage = image.Clone( ); + // perform closing on the source image + closing.ApplyInPlace( image ); + // subtract source image from the closed image + subtract.UnmanagedOverlayImage = sourceImage; + subtract.ApplyInPlace( image ); + + sourceImage.Dispose( ); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Morphology/Closing.cs b/Sources/Accord.Imaging/AForge/Filters/Morphology/Closing.cs new file mode 100644 index 0000000000..c222b8e8f --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Morphology/Closing.cs @@ -0,0 +1,280 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2010 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Closing operator from Mathematical Morphology. + /// + /// + /// Closing morphology operator equals to dilatation followed + /// by erosion. + /// + /// Applied to binary image, the filter may be used connect or fill objects. Since dilatation is used + /// first, it may connect/fill object areas. Then erosion restores objects. But since dilatation may connect + /// something before, erosion may not remove after that because of the formed connection. + /// + /// See documentation to and classes for more + /// information and list of supported pixel formats. + /// + /// Sample usage: + /// + /// // create filter + /// Closing filter = new Closing( ); + /// // apply the filter + /// filter.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + /// + public class Closing : IFilter, IInPlaceFilter, IInPlacePartialFilter, IFilterInformation + { + private Erosion errosion = new Erosion( ); + private Dilatation dilatation = new Dilatation( ); + + /// + /// Format translations dictionary. + /// + public Dictionary FormatTranslations + { + get { return errosion.FormatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Initializes new instance of the class using + /// default structuring element for both and + /// classes - 3x3 structuring element with all elements equal to 1. + /// + /// + public Closing( ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Structuring element. + /// + /// See documentation to and + /// classes for information about structuring element constraints. + /// + public Closing( short[,] se ) + { + errosion = new Erosion( se ); + dilatation = new Dilatation(se); + } + + /// + /// Apply filter to an image. + /// + /// + /// Source image to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The method keeps the source image unchanged and returns + /// the result of image processing filter as new image. + /// + /// Unsupported pixel format of the source image. + /// + public Bitmap Apply( Bitmap image ) + { + Bitmap tempImage = dilatation.Apply( image ); + Bitmap destImage = errosion.Apply( tempImage ); + + tempImage.Dispose( ); + + return destImage; + } + + /// + /// Apply filter to an image. + /// + /// + /// Source image to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The filter accepts bitmap data as input and returns the result + /// of image processing filter as new image. The source image data are kept + /// unchanged. + /// + public Bitmap Apply( BitmapData imageData ) + { + Bitmap tempImage = dilatation.Apply( imageData ); + Bitmap destImage = errosion.Apply( tempImage ); + + tempImage.Dispose( ); + + return destImage; + } + + /// + /// Apply filter to an image in unmanaged memory. + /// + /// + /// Source image in unmanaged memory to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The method keeps the source image unchanged and returns + /// the result of image processing filter as new image. + /// + /// Unsupported pixel format of the source image. + /// + public UnmanagedImage Apply( UnmanagedImage image ) + { + UnmanagedImage destImage = dilatation.Apply( image ); + errosion.ApplyInPlace( destImage ); + + return destImage; + } + + /// + /// Apply filter to an image in unmanaged memory. + /// + /// + /// Source image in unmanaged memory to apply filter to. + /// Destination image in unmanaged memory to put result into. + /// + /// The method keeps the source image unchanged and puts result of image processing + /// into destination image. + /// + /// The destination image must have the same width and height as source image. Also + /// destination image must have pixel format, which is expected by particular filter (see + /// property for information about pixel format conversions). + /// + /// + /// Unsupported pixel format of the source image. + /// Incorrect destination pixel format. + /// Destination image has wrong width and/or height. + /// + public void Apply( UnmanagedImage sourceImage, UnmanagedImage destinationImage ) + { + dilatation.Apply( sourceImage, destinationImage ); + errosion.ApplyInPlace( destinationImage ); + } + + /// + /// Apply filter to an image. + /// + /// + /// Image to apply filter to. + /// + /// The method applies the filter directly to the provided source image. + /// + /// Unsupported pixel format of the source image. + /// + public void ApplyInPlace( Bitmap image ) + { + dilatation.ApplyInPlace( image ); + errosion.ApplyInPlace( image ); + } + + /// + /// Apply filter to an image. + /// + /// + /// Image data to apply filter to. + /// + /// The method applies the filter directly to the provided source image. + /// + /// Unsupported pixel format of the source image. + /// + public void ApplyInPlace( BitmapData imageData ) + { + dilatation.ApplyInPlace( imageData ); + errosion.ApplyInPlace( imageData ); + } + + /// + /// Apply filter to an unmanaged image. + /// + /// + /// Unmanaged image to apply filter to. + /// + /// The method applies the filter directly to the provided source unmanaged image. + /// + /// Unsupported pixel format of the source image. + /// + public void ApplyInPlace( UnmanagedImage image ) + { + dilatation.ApplyInPlace( image ); + errosion.ApplyInPlace( image ); + } + + /// + /// Apply filter to an image or its part. + /// + /// + /// Image to apply filter to. + /// Image rectangle for processing by the filter. + /// + /// The method applies the filter directly to the provided source image. + /// + /// Unsupported pixel format of the source image. + /// + public void ApplyInPlace( Bitmap image, Rectangle rect ) + { + dilatation.ApplyInPlace( image, rect ); + errosion.ApplyInPlace( image, rect ); + } + + /// + /// Apply filter to an image or its part. + /// + /// + /// Image data to apply filter to. + /// Image rectangle for processing by the filter. + /// + /// The method applies the filter directly to the provided source image. + /// + /// Unsupported pixel format of the source image. + /// + public void ApplyInPlace( BitmapData imageData, Rectangle rect ) + { + dilatation.ApplyInPlace( imageData, rect ); + errosion.ApplyInPlace( imageData, rect ); + } + + /// + /// Apply filter to an unmanaged image or its part. + /// + /// + /// Unmanaged image to apply filter to. + /// Image rectangle for processing by the filter. + /// + /// The method applies the filter directly to the provided source image. + /// + /// Unsupported pixel format of the source image. + /// + public void ApplyInPlace( UnmanagedImage image, Rectangle rect ) + { + dilatation.ApplyInPlace( image, rect ); + errosion.ApplyInPlace( image, rect ); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Morphology/Dilatation.cs b/Sources/Accord.Imaging/AForge/Filters/Morphology/Dilatation.cs new file mode 100644 index 0000000000..d73415477 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Morphology/Dilatation.cs @@ -0,0 +1,463 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2014 +// aforge.net@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Dilatation operator from Mathematical Morphology. + /// + /// + /// The filter assigns maximum value of surrounding pixels to each pixel of + /// the result image. Surrounding pixels, which should be processed, are specified by + /// structuring element: 1 - to process the neighbor, -1 - to skip it. + /// + /// The filter especially useful for binary image processing, where it allows to grow + /// separate objects or join objects. + /// + /// For processing image with 3x3 structuring element, there are different optimizations + /// available, like and . + /// + /// The filter accepts 8 and 16 bpp grayscale images and 24 and 48 bpp + /// color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// Dilatation filter = new Dilatation( ); + /// // apply the filter + /// filter.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + /// + /// + /// + public class Dilatation : BaseUsingCopyPartialFilter + { + // structuring element + private short[,] se = new short[3, 3] { { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 } }; + private int size = 3; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Initializes new instance of the class using + /// default structuring element - 3x3 structuring element with all elements equal to 1. + /// + /// + public Dilatation( ) + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format16bppGrayScale] = PixelFormat.Format16bppGrayScale; + formatTranslations[PixelFormat.Format48bppRgb] = PixelFormat.Format48bppRgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Structuring element. + /// + /// Structuring elemement for the dilatation morphological operator + /// must be square matrix with odd size in the range of [3, 99]. + /// + /// Invalid size of structuring element. + /// + public Dilatation( short[,] se ) + : this( ) + { + int s = se.GetLength( 0 ); + + // check structuring element size + if ( ( s != se.GetLength( 1 ) ) || ( s < 3 ) || ( s > 99 ) || ( s % 2 == 0 ) ) + throw new ArgumentException( "Invalid size of structuring element." ); + + this.se = se; + this.size = s; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect ) + { + PixelFormat pixelFormat = sourceData.PixelFormat; + + // processing start and stop X,Y positions + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + + // structuring element's radius + int r = size >> 1; + + // flag to indicate if at least one pixel for the given structuring element was found + bool foundSomething; + + if ( ( pixelFormat == PixelFormat.Format8bppIndexed ) || ( pixelFormat == PixelFormat.Format24bppRgb ) ) + { + int pixelSize = ( pixelFormat == PixelFormat.Format8bppIndexed ) ? 1 : 3; + + int dstStride = destinationData.Stride; + int srcStride = sourceData.Stride; + + // base pointers + byte* baseSrc = (byte*) sourceData.ImageData.ToPointer( ); + byte* baseDst = (byte*) destinationData.ImageData.ToPointer( ); + + // allign pointers by X + baseSrc += ( startX * pixelSize ); + baseDst += ( startX * pixelSize ); + + if ( pixelFormat == PixelFormat.Format8bppIndexed ) + { + // grayscale image + + // compute each line + for ( int y = startY; y < stopY; y++ ) + { + byte* src = baseSrc + y * srcStride; + byte* dst = baseDst + y * dstStride; + + byte max, v; + + // loop and array indexes + int t, ir, jr, i, j; + + // for each pixel + for ( int x = startX; x < stopX; x++, src++, dst++ ) + { + max = 0; + foundSomething = false; + + // for each structuring element's row + for ( i = 0; i < size; i++ ) + { + ir = i - r; + t = y + ir; + + // skip row + if ( t < startY ) + continue; + // break + if ( t >= stopY ) + break; + + // for each structuring slement's column + for ( j = 0; j < size; j++ ) + { + jr = j - r; + t = x + jr; + + // skip column + if ( t < startX ) + continue; + if ( t < stopX ) + { + if ( se[i, j] == 1 ) + { + foundSomething = true; + // get new MAX value + v = src[ir * srcStride + jr]; + if ( v > max ) + max = v; + } + } + } + } + // result pixel + *dst = ( foundSomething ) ? max : *src; + } + } + } + else + { + // 24 bpp color image + + // compute each line + for ( int y = startY; y < stopY; y++ ) + { + byte* src = baseSrc + y * srcStride; + byte* dst = baseDst + y * dstStride; + + byte maxR, maxG, maxB, v; + byte* p; + + // loop and array indexes + int t, ir, jr, i, j; + + // for each pixel + for ( int x = startX; x < stopX; x++, src += 3, dst += 3 ) + { + maxR = maxG = maxB = 0; + foundSomething = false; + + // for each structuring element's row + for ( i = 0; i < size; i++ ) + { + ir = i - r; + t = y + ir; + + // skip row + if ( t < startY ) + continue; + // break + if ( t >= stopY ) + break; + + // for each structuring element's column + for ( j = 0; j < size; j++ ) + { + jr = j - r; + t = x + jr; + + // skip column + if ( t < startX ) + continue; + if ( t < stopX ) + { + if ( se[i, j] == 1 ) + { + foundSomething = true; + // get new MAX values + p = &src[ir * srcStride + jr * 3]; + + // red + v = p[RGB.R]; + if ( v > maxR ) + maxR = v; + + // green + v = p[RGB.G]; + if ( v > maxG ) + maxG = v; + + // blue + v = p[RGB.B]; + if ( v > maxB ) + maxB = v; + } + } + } + } + // result pixel + if ( foundSomething ) + { + dst[RGB.R] = maxR; + dst[RGB.G] = maxG; + dst[RGB.B] = maxB; + } + else + { + dst[RGB.R] = src[RGB.R]; + dst[RGB.G] = src[RGB.G]; + dst[RGB.B] = src[RGB.B]; + } + } + } + } + } + else + { + int pixelSize = ( pixelFormat == PixelFormat.Format16bppGrayScale ) ? 1 : 3; + + int dstStride = destinationData.Stride / 2; + int srcStride = sourceData.Stride / 2; + + // base pointers + ushort* baseSrc = (ushort*) sourceData.ImageData.ToPointer( ); + ushort* baseDst = (ushort*) destinationData.ImageData.ToPointer( ); + + // allign pointers by X + baseSrc += ( startX * pixelSize ); + baseDst += ( startX * pixelSize ); + + if ( pixelFormat == PixelFormat.Format16bppGrayScale ) + { + // 16 bpp grayscale image + + // compute each line + for( int y = startY; y < stopY; y++ ) + { + ushort* src = baseSrc + y * srcStride; + ushort* dst = baseDst + y * dstStride; + + ushort max, v; + + // loop and array indexes + int t, ir, jr, i, j; + + // for each pixel + for ( int x = startX; x < stopX; x++, src++, dst++ ) + { + max = 0; + foundSomething = false; + + // for each structuring element's row + for ( i = 0; i < size; i++ ) + { + ir = i - r; + t = y + ir; + + // skip row + if ( t < startY ) + continue; + // break + if ( t >= stopY ) + break; + + // for each structuring slement's column + for ( j = 0; j < size; j++ ) + { + jr = j - r; + t = x + jr; + + // skip column + if ( t < startX ) + continue; + if ( t < stopX ) + { + if ( se[i, j] == 1 ) + { + foundSomething = true; + // get new MAX value + v = src[ir * srcStride + jr]; + if ( v > max ) + max = v; + } + } + } + } + // result pixel + *dst = ( foundSomething ) ? max : *src; + } + } + } + else + { + // 48 bpp color image + + // compute each line + for( int y = startY; y < stopY; y++ ) + { + ushort* src = baseSrc + y * srcStride; + ushort* dst = baseDst + y * dstStride; + + ushort maxR, maxG, maxB, v; + ushort* p; + + // loop and array indexes + int t, ir, jr, i, j; + + // for each pixel + for ( int x = startX; x < stopX; x++, src += 3, dst += 3 ) + { + maxR = maxG = maxB = 0; + foundSomething = false; + + // for each structuring element's row + for ( i = 0; i < size; i++ ) + { + ir = i - r; + t = y + ir; + + // skip row + if ( t < startY ) + continue; + // break + if ( t >= stopY ) + break; + + // for each structuring element's column + for ( j = 0; j < size; j++ ) + { + jr = j - r; + t = x + jr; + + // skip column + if ( t < startX ) + continue; + if ( t < stopX ) + { + if ( se[i, j] == 1 ) + { + foundSomething = true; + // get new MAX values + p = &src[ir * srcStride + jr * 3]; + + // red + v = p[RGB.R]; + if ( v > maxR ) + maxR = v; + + // green + v = p[RGB.G]; + if ( v > maxG ) + maxG = v; + + // blue + v = p[RGB.B]; + if ( v > maxB ) + maxB = v; + } + } + } + } + // result pixel + if ( foundSomething ) + { + dst[RGB.R] = maxR; + dst[RGB.G] = maxG; + dst[RGB.B] = maxB; + } + else + { + dst[RGB.R] = src[RGB.R]; + dst[RGB.G] = src[RGB.G]; + dst[RGB.B] = src[RGB.B]; + } + } + } + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Morphology/Erosion.cs b/Sources/Accord.Imaging/AForge/Filters/Morphology/Erosion.cs new file mode 100644 index 0000000000..26bf3dae9 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Morphology/Erosion.cs @@ -0,0 +1,465 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2014 +// aforge.net@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Erosion operator from Mathematical Morphology. + /// + /// + /// The filter assigns minimum value of surrounding pixels to each pixel of + /// the result image. Surrounding pixels, which should be processed, are specified by + /// structuring element: 1 - to process the neighbor, -1 - to skip it. + /// + /// The filter especially useful for binary image processing, where it removes pixels, which + /// are not surrounded by specified amount of neighbors. It gives ability to remove noisy pixels + /// (stand-alone pixels) or shrink objects. + /// + /// For processing image with 3x3 structuring element, there are different optimizations + /// available, like and . + /// + /// The filter accepts 8 and 16 bpp grayscale images and 24 and 48 bpp + /// color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// Erosion filter = new Erosion( ); + /// // apply the filter + /// filter.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + /// + /// + /// + public class Erosion : BaseUsingCopyPartialFilter + { + // structuring element + private short[,] se = new short[3, 3] { { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 } }; + private int size = 3; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Initializes new instance of the class using + /// default structuring element - 3x3 structuring element with all elements equal to 1. + /// + /// + public Erosion( ) + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format16bppGrayScale] = PixelFormat.Format16bppGrayScale; + formatTranslations[PixelFormat.Format48bppRgb] = PixelFormat.Format48bppRgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Structuring element. + /// + /// Structuring elemement for the erosion morphological operator + /// must be square matrix with odd size in the range of [3, 99]. + /// + /// Invalid size of structuring element. + /// + public Erosion( short[,] se ) + : this( ) + { + int s = se.GetLength( 0 ); + + // check structuring element size + if ( ( s != se.GetLength( 1 ) ) || ( s < 3 ) || ( s > 99 ) || ( s % 2 == 0 ) ) + throw new ArgumentException( "Invalid size of structuring element." ); + + this.se = se; + this.size = s; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect ) + { + PixelFormat pixelFormat = sourceData.PixelFormat; + + // processing start and stop X,Y positions + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + + // structuring element's radius + int r = size >> 1; + + // flag to indicate if at least one pixel for the given structuring element was found + bool foundSomething; + + if ( ( pixelFormat == PixelFormat.Format8bppIndexed ) || ( pixelFormat == PixelFormat.Format24bppRgb ) ) + { + int pixelSize = ( pixelFormat == PixelFormat.Format8bppIndexed ) ? 1 : 3; + + int dstStride = destinationData.Stride; + int srcStride = sourceData.Stride; + + // base pointers + byte* baseSrc = (byte*) sourceData.ImageData.ToPointer( ); + byte* baseDst = (byte*) destinationData.ImageData.ToPointer( ); + + // allign pointers by X + baseSrc += ( startX * pixelSize ); + baseDst += ( startX * pixelSize ); + + if ( pixelFormat == PixelFormat.Format8bppIndexed ) + { + // grayscale image + + // compute each line + for ( int y = startY; y < stopY; y++ ) + { + byte* src = baseSrc + y * srcStride; + byte* dst = baseDst + y * dstStride; + + byte min, v; + + // loop and array indexes + int t, ir, jr, i, j; + + // for each pixel + for ( int x = startX; x < stopX; x++, src++, dst++ ) + { + min = 255; + foundSomething = false; + + // for each structuring element's row + for ( i = 0; i < size; i++ ) + { + ir = i - r; + t = y + ir; + + // skip row + if ( t < startY ) + continue; + // break + if ( t >= stopY ) + break; + + // for each structuring element's column + for ( j = 0; j < size; j++ ) + { + jr = j - r; + t = x + jr; + + // skip column + if ( t < startX ) + continue; + if ( t < stopX ) + { + if ( se[i, j] == 1 ) + { + foundSomething = true; + // get new MIN value + v = src[ir * srcStride + jr]; + if ( v < min ) + min = v; + } + } + } + } + // result pixel + *dst = ( foundSomething ) ? min : *src; + } + } + } + else + { + // 24 bpp color image + + // compute each line + for ( int y = startY; y < stopY; y++ ) + { + byte* src = baseSrc + y * srcStride; + byte* dst = baseDst + y * dstStride; + + byte minR, minG, minB, v; + byte* p; + + // loop and array indexes + int t, ir, jr, i, j; + + // for each pixel + for ( int x = startX; x < stopX; x++, src += 3, dst += 3 ) + { + minR = minG = minB = 255; + foundSomething = false; + + // for each structuring element's row + for ( i = 0; i < size; i++ ) + { + ir = i - r; + t = y + ir; + + // skip row + if ( t < startY ) + continue; + // break + if ( t >= stopY ) + break; + + // for each structuring element's column + for ( j = 0; j < size; j++ ) + { + jr = j - r; + t = x + jr; + + // skip column + if ( t < startX ) + continue; + if ( t < stopX ) + { + if ( se[i, j] == 1 ) + { + foundSomething = true; + // get new MIN values + p = &src[ir * srcStride + jr * 3]; + + // red + v = p[RGB.R]; + if ( v < minR ) + minR = v; + + // green + v = p[RGB.G]; + if ( v < minG ) + minG = v; + + // blue + v = p[RGB.B]; + if ( v < minB ) + minB = v; + } + } + } + } + // result pixel + if ( foundSomething ) + { + dst[RGB.R] = minR; + dst[RGB.G] = minG; + dst[RGB.B] = minB; + } + else + { + dst[RGB.R] = src[RGB.R]; + dst[RGB.G] = src[RGB.G]; + dst[RGB.B] = src[RGB.B]; + } + } + } + } + } + else + { + int pixelSize = ( pixelFormat == PixelFormat.Format16bppGrayScale ) ? 1 : 3; + + int dstStride = destinationData.Stride / 2; + int srcStride = sourceData.Stride / 2; + + // base pointers + ushort* baseSrc = (ushort*) sourceData.ImageData.ToPointer( ); + ushort* baseDst = (ushort*) destinationData.ImageData.ToPointer( ); + + // allign pointers by X + baseSrc += ( startX * pixelSize ); + baseDst += ( startX * pixelSize ); + + if ( pixelFormat == PixelFormat.Format16bppGrayScale ) + { + // 16 bpp grayscale image + + // compute each line + for ( int y = startY; y < stopY; y++ ) + { + ushort* src = baseSrc + y * srcStride; + ushort* dst = baseDst + y * dstStride; + + ushort min, v; + + // loop and array indexes + int t, ir, jr, i, j; + + // for each pixel + for ( int x = startX; x < stopX; x++, src++, dst++ ) + { + min = 65535; + foundSomething = false; + + // for each structuring element's row + for ( i = 0; i < size; i++ ) + { + ir = i - r; + t = y + ir; + + // skip row + if ( t < startY ) + continue; + // break + if ( t >= stopY ) + break; + + // for each structuring element's column + for ( j = 0; j < size; j++ ) + { + jr = j - r; + t = x + jr; + + // skip column + if ( t < startX ) + continue; + if ( t < stopX ) + { + if ( se[i, j] == 1 ) + { + foundSomething = true; + // get new MIN value + v = src[ir * srcStride + jr]; + if ( v < min ) + min = v; + } + } + } + } + // result pixel + *dst = ( foundSomething ) ? min : *src; + + } + } + } + else + { + // 48 bpp color image + + // compute each line + for ( int y = startY; y < stopY; y++ ) + { + ushort* src = baseSrc + y * srcStride; + ushort* dst = baseDst + y * dstStride; + + ushort minR, minG, minB, v; + ushort* p; + + // loop and array indexes + int t, ir, jr, i, j; + + // for each pixel + for ( int x = startX; x < stopX; x++, src += 3, dst += 3 ) + { + minR = minG = minB = 65535; + foundSomething = false; + + // for each structuring element's row + for ( i = 0; i < size; i++ ) + { + ir = i - r; + t = y + ir; + + // skip row + if ( t < startY ) + continue; + // break + if ( t >= stopY ) + break; + + // for each structuring element's column + for ( j = 0; j < size; j++ ) + { + jr = j - r; + t = x + jr; + + // skip column + if ( t < startX ) + continue; + if ( t < stopX ) + { + if ( se[i, j] == 1 ) + { + foundSomething = true; + // get new MIN values + p = &src[ir * srcStride + jr * 3]; + + // red + v = p[RGB.R]; + if ( v < minR ) + minR = v; + + // green + v = p[RGB.G]; + if ( v < minG ) + minG = v; + + // blue + v = p[RGB.B]; + if ( v < minB ) + minB = v; + } + } + } + } + // result pixel + if ( foundSomething ) + { + dst[RGB.R] = minR; + dst[RGB.G] = minG; + dst[RGB.B] = minB; + } + else + { + dst[RGB.R] = src[RGB.R]; + dst[RGB.G] = src[RGB.G]; + dst[RGB.B] = src[RGB.B]; + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/Sources/Accord.Imaging/AForge/Filters/Morphology/HitAndMiss.cs b/Sources/Accord.Imaging/AForge/Filters/Morphology/HitAndMiss.cs new file mode 100644 index 0000000000..4ce75694f --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Morphology/HitAndMiss.cs @@ -0,0 +1,268 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@aaforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Hit-And-Miss operator from Mathematical Morphology. + /// + /// + /// The hit-and-miss filter represents generalization of + /// and filters by extending flexibility of structuring element and + /// providing different modes of its work. Structuring element may contain: + /// + /// 1 - foreground; + /// 0 - background; + /// -1 - don't care. + /// + /// + /// + /// Filter's mode is set by property. The list of modes and its + /// documentation may be found in enumeration. + /// + /// The filter accepts 8 bpp grayscale images for processing. Note: grayscale images are treated + /// as binary with 0 value equals to black and 255 value equals to white. + /// + /// Sample usage: + /// + /// // define kernel to remove pixels on the right side of objects + /// // (pixel is removed, if there is white pixel on the left and + /// // black pixel on the right) + /// short[,] se = new short[,] { + /// { -1, -1, -1 }, + /// { 1, 1, 0 }, + /// { -1, -1, -1 } + /// }; + /// // create filter + /// HitAndMiss filter = new HitAndMiss( se, HitAndMiss.Modes.Thinning ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class HitAndMiss : BaseUsingCopyPartialFilter + { + /// + /// Hit and Miss modes. + /// + /// + /// Bellow is a list of modes meaning depending on pixel's correspondence + /// to specified structuring element: + /// + /// - on match pixel is set to white, otherwise to black; + /// - on match pixel is set to black, otherwise not changed. + /// - on match pixel is set to white, otherwise not changed. + /// + /// + /// + public enum Modes + { + /// + /// Hit and miss mode. + /// + HitAndMiss = 0, + + /// + /// Thinning mode. + /// + Thinning = 1, + + /// + /// Thickening mode. + /// + Thickening = 2 + } + + // structuring element + private short[,] se; + private int size; + + // operation mode + private Modes mode = Modes.HitAndMiss; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Operation mode. + /// + /// + /// Mode to use for the filter. See enumeration + /// for the list of available modes and their documentation. + /// + /// Default mode is set to . + /// + public Modes Mode + { + get { return mode; } + set { mode = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Structuring element. + /// + /// Structuring elemement for the hit-and-miss morphological operator + /// must be square matrix with odd size in the range of [3, 99]. + /// + /// Invalid size of structuring element. + /// + public HitAndMiss( short[,] se ) + { + int s = se.GetLength( 0 ); + + // check structuring element size + if ( ( s != se.GetLength( 1 ) ) || ( s < 3 ) || ( s > 99 ) || ( s % 2 == 0 ) ) + throw new ArgumentException( ); + + this.se = se; + this.size = s; + + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Structuring element. + /// Operation mode. + /// + public HitAndMiss( short[,] se, Modes mode ) + : this( se ) + { + this.mode = mode; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect ) + { + // processing start and stop X,Y positions + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + + int srcStride = sourceData.Stride; + int dstStride = destinationData.Stride; + int srcOffset = srcStride - rect.Width; + int dstOffset = dstStride - rect.Width; + + // loop and array indexes + int ir, jr, i, j; + // structuring element's radius + int r = size >> 1; + // pixel value + byte dstValue, v; + // structuring element's value + short sv; + + // mode values + byte[] hitValue = new byte[3] { 255, 0, 255 }; + byte[] missValue = new byte[3] { 0, 0, 0 }; + int modeIndex = (int) mode; + + // do the job + byte* src = (byte*) sourceData.ImageData.ToPointer( ); + byte* dst = (byte*) destinationData.ImageData.ToPointer( ); + + // allign pointers to the first pixel to process + src += ( startY * srcStride + startX ); + dst += ( startY * dstStride + startX ); + + // for each line + for ( int y = startY; y < stopY; y++ ) + { + // for each pixel + for ( int x = startX; x < stopX; x++, src++, dst++ ) + { + missValue[1] = missValue[2] = *src; + dstValue = 255; + + // for each structuring element's row + for ( i = 0; i < size; i++ ) + { + ir = i - r; + + // for each structuring element's column + for ( j = 0; j < size; j++ ) + { + jr = j - r; + + // get structuring element's value + sv = se[i, j]; + + // skip "don't care" values + if ( sv == -1 ) + continue; + + // check, if we outside + if ( + ( y + ir < startY ) || ( y + ir >= stopY ) || + ( x + jr < startX ) || ( x + jr >= stopX ) + ) + { + // if it so, the result is zero, + // because it was required pixel + dstValue = 0; + break; + } + + // get source image value + v = src[ir * srcStride + jr]; + + if ( + ( ( sv != 0 ) || ( v != 0 ) ) && + ( ( sv != 1 ) || ( v != 255 ) ) + ) + { + // failed structuring element mutch + dstValue = 0; + break; + } + } + + if ( dstValue == 0 ) + break; + } + // result pixel + *dst = ( dstValue == 255 ) ? hitValue[modeIndex] : missValue[modeIndex]; + } + src += srcOffset; + dst += dstOffset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Morphology/Opening.cs b/Sources/Accord.Imaging/AForge/Filters/Morphology/Opening.cs new file mode 100644 index 0000000000..ed0284fb8 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Morphology/Opening.cs @@ -0,0 +1,280 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2010 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Opening operator from Mathematical Morphology. + /// + /// + /// Opening morphology operator equals to erosion followed + /// by dilatation. + /// + /// Applied to binary image, the filter may be used for removing small object keeping big objects + /// unchanged. Since erosion is used first, it removes all small objects. Then dilatation restores big + /// objects, which were not removed by erosion. + /// + /// See documentation to and classes for more + /// information and list of supported pixel formats. + /// + /// Sample usage: + /// + /// // create filter + /// Opening filter = new Opening( ); + /// // apply the filter + /// filter.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + /// + public class Opening : IFilter, IInPlaceFilter, IInPlacePartialFilter, IFilterInformation + { + private Erosion errosion = new Erosion( ); + private Dilatation dilatation = new Dilatation( ); + + /// + /// Format translations dictionary. + /// + public Dictionary FormatTranslations + { + get { return errosion.FormatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Initializes new instance of the class using + /// default structuring element for both and + /// classes - 3x3 structuring element with all elements equal to 1. + /// + /// + public Opening( ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Structuring element. + /// + /// See documentation to and + /// classes for information about structuring element constraints. + /// + public Opening( short[,] se ) + { + errosion = new Erosion( se ); + dilatation = new Dilatation( se ); + } + + /// + /// Apply filter to an image. + /// + /// + /// Source image to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The method keeps the source image unchanged and returns + /// the result of image processing filter as new image. + /// + /// Unsupported pixel format of the source image. + /// + public Bitmap Apply( Bitmap image ) + { + Bitmap tempImage = errosion.Apply( image ); + Bitmap destImage = dilatation.Apply( tempImage ); + + tempImage.Dispose( ); + + return destImage; + } + + /// + /// Apply filter to an image. + /// + /// + /// Source image to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The filter accepts bitmap data as input and returns the result + /// of image processing filter as new image. The source image data are kept + /// unchanged. + /// + public Bitmap Apply( BitmapData imageData ) + { + Bitmap tempImage = errosion.Apply( imageData ); + Bitmap destImage = dilatation.Apply( tempImage ); + + tempImage.Dispose( ); + + return destImage; + } + + /// + /// Apply filter to an image in unmanaged memory. + /// + /// + /// Source image in unmanaged memory to apply filter to. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The method keeps the source image unchanged and returns + /// the result of image processing filter as new image. + /// + /// Unsupported pixel format of the source image. + /// + public UnmanagedImage Apply( UnmanagedImage image ) + { + UnmanagedImage destImage = errosion.Apply( image ); + dilatation.ApplyInPlace( destImage ); + + return destImage; + } + + /// + /// Apply filter to an image in unmanaged memory. + /// + /// + /// Source image in unmanaged memory to apply filter to. + /// Destination image in unmanaged memory to put result into. + /// + /// The method keeps the source image unchanged and puts result of image processing + /// into destination image. + /// + /// The destination image must have the same width and height as source image. Also + /// destination image must have pixel format, which is expected by particular filter (see + /// property for information about pixel format conversions). + /// + /// + /// Unsupported pixel format of the source image. + /// Incorrect destination pixel format. + /// Destination image has wrong width and/or height. + /// + public void Apply( UnmanagedImage sourceImage, UnmanagedImage destinationImage ) + { + errosion.Apply( sourceImage, destinationImage ); + dilatation.ApplyInPlace( destinationImage ); + } + + /// + /// Apply filter to an image. + /// + /// + /// Image to apply filter to. + /// + /// The method applies the filter directly to the provided source image. + /// + /// Unsupported pixel format of the source image. + /// + public void ApplyInPlace( Bitmap image ) + { + errosion.ApplyInPlace( image ); + dilatation.ApplyInPlace( image ); + } + + /// + /// Apply filter to an image. + /// + /// + /// Image data to apply filter to. + /// + /// The method applies the filter directly to the provided source image. + /// + /// Unsupported pixel format of the source image. + /// + public void ApplyInPlace( BitmapData imageData ) + { + errosion.ApplyInPlace( imageData ); + dilatation.ApplyInPlace( imageData ); + } + + /// + /// Apply filter to an unmanaged image. + /// + /// + /// Unmanaged image to apply filter to. + /// + /// The method applies the filter directly to the provided source unmanaged image. + /// + /// Unsupported pixel format of the source image. + /// + public void ApplyInPlace( UnmanagedImage image ) + { + errosion.ApplyInPlace( image ); + dilatation.ApplyInPlace( image ); + } + + /// + /// Apply filter to an image or its part. + /// + /// + /// Image to apply filter to. + /// Image rectangle for processing by the filter. + /// + /// The method applies the filter directly to the provided source image. + /// + /// Unsupported pixel format of the source image. + /// + public void ApplyInPlace( Bitmap image, Rectangle rect ) + { + errosion.ApplyInPlace( image, rect ); + dilatation.ApplyInPlace( image, rect ); + } + + /// + /// Apply filter to an image or its part. + /// + /// + /// Image data to apply filter to. + /// Image rectangle for processing by the filter. + /// + /// The method applies the filter directly to the provided source image. + /// + /// Unsupported pixel format of the source image. + /// + public void ApplyInPlace( BitmapData imageData, Rectangle rect ) + { + errosion.ApplyInPlace( imageData, rect ); + dilatation.ApplyInPlace( imageData, rect ); + } + + /// + /// Apply filter to an unmanaged image or its part. + /// + /// + /// Unmanaged image to apply filter to. + /// Image rectangle for processing by the filter. + /// + /// The method applies the filter directly to the provided source image. + /// + /// Unsupported pixel format of the source image. + /// + public void ApplyInPlace( UnmanagedImage image, Rectangle rect ) + { + errosion.ApplyInPlace( image, rect ); + dilatation.ApplyInPlace( image, rect ); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Morphology/Specific Optimizations/BinaryDilatation3x3.cs b/Sources/Accord.Imaging/AForge/Filters/Morphology/Specific Optimizations/BinaryDilatation3x3.cs new file mode 100644 index 0000000000..819cb6962 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Morphology/Specific Optimizations/BinaryDilatation3x3.cs @@ -0,0 +1,155 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Binary dilatation operator from Mathematical Morphology with 3x3 structuring element. + /// + /// + /// The filter represents an optimized version of + /// filter, which is aimed for binary images (containing black and white pixels) processed + /// with 3x3 structuring element. This makes this filter ideal for growing objects in binary + /// images – it puts white pixel to the destination image in the case if there is at least + /// one white neighbouring pixel in the source image. + /// + /// See filter, which represents generic version of + /// dilatation filter supporting custom structuring elements and wider range of image formats. + /// + /// The filter accepts 8 bpp grayscale (binary) images for processing. + /// + /// + /// + /// + /// + public class BinaryDilatation3x3 : BaseUsingCopyPartialFilter + { + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public BinaryDilatation3x3( ) + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// Image rectangle for processing by the filter. + /// + /// Processing rectangle mast be at least 3x3 in size. + /// + protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect ) + { + if ( ( rect.Width < 3 ) || ( rect.Height < 3 ) ) + { + throw new InvalidImagePropertiesException( "Processing rectangle mast be at least 3x3 in size." ); + } + + // processing start and stop X,Y positions + int startX = rect.Left + 1; + int startY = rect.Top + 1; + int stopX = rect.Right - 1; + int stopY = rect.Bottom - 1; + + int dstStride = destinationData.Stride; + int srcStride = sourceData.Stride; + + int dstOffset = dstStride - rect.Width + 1; + int srcOffset = srcStride - rect.Width + 1; + + // image pointers + byte* src = (byte*) sourceData.ImageData.ToPointer( ); + byte* dst = (byte*) destinationData.ImageData.ToPointer( ); + + // allign pointers by X and Y + src += ( startX - 1 ) + ( startY - 1 ) * srcStride; + dst += ( startX - 1 ) + ( startY - 1 ) * dstStride; + + // --- process the first line + *dst = (byte) ( *src | src[1] | src[srcStride] | src[srcStride + 1] ); + + src++; + dst++; + + // for each pixel + for ( int x = startX; x < stopX; x++, src++, dst++ ) + { + *dst = (byte) ( *src | src[-1] | src[1] | + src[srcStride] | src[srcStride - 1] | src[srcStride + 1] ); + } + + *dst = (byte) ( *src | src[-1] | src[srcStride] | src[srcStride - 1] ); + + src += srcOffset; + dst += dstOffset; + + // --- process all lines except the last one + for ( int y = startY; y < stopY; y++ ) + { + *dst = (byte) ( *src | src[1] | + src[-srcStride] | src[-srcStride + 1] | + src[srcStride] | src[srcStride + 1] ); + + src++; + dst++; + + // for each pixel + for ( int x = startX; x < stopX; x++, src++, dst++ ) + { + *dst = (byte) ( *src | src[-1] | src[1] | + src[-srcStride] | src[-srcStride - 1] | src[-srcStride + 1] | + src[ srcStride] | src[ srcStride - 1] | src[ srcStride + 1] ); + } + + *dst = (byte) ( *src | src[-1] | + src[-srcStride] | src[-srcStride - 1] | + src[srcStride] | src[srcStride - 1] ); + + src += srcOffset; + dst += dstOffset; + } + + // --- process the last line + *dst = (byte) ( *src | src[1] | src[-srcStride] | src[-srcStride + 1] ); + + src++; + dst++; + + // for each pixel + for ( int x = startX; x < stopX; x++, src++, dst++ ) + { + *dst = (byte) ( *src | src[-1] | src[1] | + src[-srcStride] | src[-srcStride - 1] | src[-srcStride + 1] ); + } + + *dst = (byte) ( *src | src[-1] | src[-srcStride] | src[-srcStride - 1] ); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Morphology/Specific Optimizations/BinaryErosion3x3.cs b/Sources/Accord.Imaging/AForge/Filters/Morphology/Specific Optimizations/BinaryErosion3x3.cs new file mode 100644 index 0000000000..9c3438678 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Morphology/Specific Optimizations/BinaryErosion3x3.cs @@ -0,0 +1,138 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Binary erosion operator from Mathematical Morphology with 3x3 structuring element. + /// + /// + /// The filter represents an optimized version of + /// filter, which is aimed for binary images (containing black and white pixels) processed + /// with 3x3 structuring element. This makes this filter ideal for removing noise in binary + /// images – it removes all white pixels, which are neighbouring with at least one blank pixel. + /// + /// + /// See filter, which represents generic version of + /// erosion filter supporting custom structuring elements and wider range of image formats. + /// + /// The filter accepts 8 bpp grayscale (binary) images for processing. + /// + /// + /// + /// + public class BinaryErosion3x3 : BaseUsingCopyPartialFilter + { + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public BinaryErosion3x3( ) + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// Image rectangle for processing by the filter. + /// + /// Processing rectangle mast be at least 3x3 in size. + /// + protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect ) + { + if ( ( rect.Width < 3 ) || ( rect.Height < 3 ) ) + { + throw new InvalidImagePropertiesException( "Processing rectangle mast be at least 3x3 in size." ); + } + + // processing start and stop X,Y positions + int startX = rect.Left + 1; + int startY = rect.Top + 1; + int stopX = rect.Right - 1; + int stopY = rect.Bottom - 1; + + int dstStride = destinationData.Stride; + int srcStride = sourceData.Stride; + + int dstOffset = dstStride - rect.Width + 1; + int srcOffset = srcStride - rect.Width + 1; + + // image pointers + byte* src = (byte*) sourceData.ImageData.ToPointer( ); + byte* dst = (byte*) destinationData.ImageData.ToPointer( ); + + // allign pointers by X and Y + src += ( startX - 1 ) + ( startY - 1 ) * srcStride; + dst += ( startX - 1 ) + ( startY - 1 ) * dstStride; + + // --- process the first line setting all to black + for ( int x = startX - 1; x < stopX; x++, src++, dst++ ) + { + *dst = 0; + } + *dst = 0; + + src += srcOffset; + dst += dstOffset; + + // --- process all lines except the last one + for ( int y = startY; y < stopY; y++ ) + { + // set edge pixel to black + *dst = 0; + + src++; + dst++; + + // for each pixel + for ( int x = startX; x < stopX; x++, src++, dst++ ) + { + *dst = (byte) ( *src & src[-1] & src[1] & + src[-srcStride] & src[-srcStride - 1] & src[-srcStride + 1] & + src[srcStride] & src[srcStride - 1] & src[srcStride + 1] ); + } + + // set edge pixel to black + *dst = 0; + + src += srcOffset; + dst += dstOffset; + } + + // --- process the last line setting all to black + + // for each pixel + for ( int x = startX - 1; x < stopX; x++, src++, dst++ ) + { + *dst = 0; + } + *dst = 0; + } + } +} \ No newline at end of file diff --git a/Sources/Accord.Imaging/AForge/Filters/Morphology/Specific Optimizations/Dilatation3x3.cs b/Sources/Accord.Imaging/AForge/Filters/Morphology/Specific Optimizations/Dilatation3x3.cs new file mode 100644 index 0000000000..51dc32b4d --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Morphology/Specific Optimizations/Dilatation3x3.cs @@ -0,0 +1,255 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Dilatation operator from Mathematical Morphology with 3x3 structuring element. + /// + /// + /// The filter represents an optimized version of + /// filter, which is aimed for grayscale image processing with 3x3 structuring element. + /// + /// See filter, which represents generic version of + /// dilatation filter supporting custom structuring elements and wider range of image formats. + /// + /// The filter accepts 8 bpp grayscale images for processing. + /// + /// + /// + /// + /// + public class Dilatation3x3 : BaseUsingCopyPartialFilter + { + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public Dilatation3x3( ) + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// Image rectangle for processing by the filter. + /// + /// Processing rectangle mast be at least 3x3 in size. + /// + protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect ) + { + if ( ( rect.Width < 3 ) || ( rect.Height < 3 ) ) + { + throw new InvalidImagePropertiesException( "Processing rectangle mast be at least 3x3 in size." ); + } + + // processing start and stop X,Y positions + int startX = rect.Left + 1; + int startY = rect.Top + 1; + int stopX = rect.Right - 1; + int stopY = rect.Bottom - 1; + + int dstStride = destinationData.Stride; + int srcStride = sourceData.Stride; + + int dstOffset = dstStride - rect.Width + 1; + int srcOffset = srcStride - rect.Width + 1; + + // image pointers + byte* src = (byte*) sourceData.ImageData.ToPointer( ); + byte* dst = (byte*) destinationData.ImageData.ToPointer( ); + + byte max; + + // allign pointers by X and Y + src += ( startX - 1 ) + ( startY - 1 ) * srcStride; + dst += ( startX - 1 ) + ( startY - 1 ) * dstStride; + + // --- process the first line + max = *src; + + if ( src[1] > max ) + max = src[1]; + if ( src[srcStride] > max ) + max = src[srcStride]; + if ( src[srcStride + 1] > max ) + max = src[srcStride + 1]; + + *dst = max; + + src++; + dst++; + + // for each pixel + for ( int x = startX; x < stopX; x++, src++, dst++ ) + { + max = *src; + + if ( src[-1] > max ) + max = src[-1]; + if ( src[1] > max ) + max = src[1]; + if ( src[srcStride - 1] > max ) + max = src[srcStride - 1]; + if ( src[srcStride] > max ) + max = src[srcStride]; + if ( src[srcStride + 1] > max ) + max = src[srcStride + 1]; + + *dst = max; + } + + max = *src; + + if ( src[-1] > max ) + max = src[-1]; + if ( src[srcStride - 1] > max ) + max = src[srcStride - 1]; + if ( src[srcStride] > max ) + max = src[srcStride]; + + *dst = max; + + src += srcOffset; + dst += dstOffset; + + // --- process all lines except the last one + for ( int y = startY; y < stopY; y++ ) + { + max = *src; + + if ( src[1] > max ) + max = src[1]; + if ( src[-srcStride] > max ) + max = src[-srcStride]; + if ( src[-srcStride + 1] > max ) + max = src[-srcStride + 1]; + if ( src[srcStride] > max ) + max = src[srcStride]; + if ( src[srcStride + 1] > max ) + max = src[srcStride + 1]; + + *dst = max; + + src++; + dst++; + + // for each pixel + for ( int x = startX; x < stopX; x++, src++, dst++ ) + { + max = *src; + + if ( src[-1] > max ) + max = src[-1]; + if ( src[1] > max ) + max = src[1]; + if ( src[-srcStride - 1] > max ) + max = src[-srcStride - 1]; + if ( src[-srcStride] > max ) + max = src[-srcStride]; + if ( src[-srcStride + 1] > max ) + max = src[-srcStride + 1]; + if ( src[srcStride - 1] > max ) + max = src[srcStride - 1]; + if ( src[srcStride] > max ) + max = src[srcStride]; + if ( src[srcStride + 1] > max ) + max = src[srcStride + 1]; + + *dst = max; + } + + max = *src; + + if ( src[-1] > max ) + max = src[-1]; + if ( src[-srcStride - 1] > max ) + max = src[-srcStride - 1]; + if ( src[-srcStride] > max ) + max = src[-srcStride]; + if ( src[srcStride - 1] > max ) + max = src[srcStride - 1]; + if ( src[srcStride] > max ) + max = src[srcStride]; + + *dst = max; + + src += srcOffset; + dst += dstOffset; + } + + // --- process the last line + *dst = (byte) ( *src | src[1] | src[-srcStride] | src[-srcStride + 1] ); + + max = *src; + + if ( src[1] > max ) + max = src[1]; + if ( src[-srcStride] > max ) + max = src[-srcStride]; + if ( src[-srcStride + 1] > max ) + max = src[-srcStride + 1]; + + *dst = max; + + src++; + dst++; + + // for each pixel + for ( int x = startX; x < stopX; x++, src++, dst++ ) + { + max = *src; + + if ( src[-1] > max ) + max = src[-1]; + if ( src[1] > max ) + max = src[1]; + if ( src[-srcStride - 1] > max ) + max = src[-srcStride - 1]; + if ( src[-srcStride] > max ) + max = src[-srcStride]; + if ( src[-srcStride + 1] > max ) + max = src[-srcStride + 1]; + + *dst = max; + } + + max = *src; + + if ( src[-1] > max ) + max = src[-1]; + if ( src[-srcStride - 1] > max ) + max = src[-srcStride - 1]; + if ( src[-srcStride] > max ) + max = src[-srcStride]; + + *dst = max; + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Morphology/Specific Optimizations/Erosion3.x3.cs b/Sources/Accord.Imaging/AForge/Filters/Morphology/Specific Optimizations/Erosion3.x3.cs new file mode 100644 index 0000000000..c2108685f --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Morphology/Specific Optimizations/Erosion3.x3.cs @@ -0,0 +1,255 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Erosion operator from Mathematical Morphology with 3x3 structuring element. + /// + /// + /// The filter represents an optimized version of + /// filter, which is aimed for grayscale image processing with 3x3 structuring element. + /// + /// See filter, which represents generic version of + /// erosion filter supporting custom structuring elements and wider range of image formats. + /// + /// The filter accepts 8 bpp grayscale images for processing. + /// + /// + /// + /// + /// + public class Erosion3x3 : BaseUsingCopyPartialFilter + { + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public Erosion3x3( ) + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// Image rectangle for processing by the filter. + /// + /// Processing rectangle mast be at least 3x3 in size. + /// + protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect ) + { + if ( ( rect.Width < 3 ) || ( rect.Height < 3 ) ) + { + throw new InvalidImagePropertiesException( "Processing rectangle mast be at least 3x3 in size." ); + } + + // processing start and stop X,Y positions + int startX = rect.Left + 1; + int startY = rect.Top + 1; + int stopX = rect.Right - 1; + int stopY = rect.Bottom - 1; + + int dstStride = destinationData.Stride; + int srcStride = sourceData.Stride; + + int dstOffset = dstStride - rect.Width + 1; + int srcOffset = srcStride - rect.Width + 1; + + // image pointers + byte* src = (byte*) sourceData.ImageData.ToPointer( ); + byte* dst = (byte*) destinationData.ImageData.ToPointer( ); + + byte min; + + // allign pointers by X and Y + src += ( startX - 1 ) + ( startY - 1 ) * srcStride; + dst += ( startX - 1 ) + ( startY - 1 ) * dstStride; + + // --- process the first line + min = *src; + + if ( src[1] < min ) + min = src[1]; + if ( src[srcStride] < min ) + min = src[srcStride]; + if ( src[srcStride + 1] < min ) + min = src[srcStride + 1]; + + *dst = min; + + src++; + dst++; + + // for each pixel + for ( int x = startX; x < stopX; x++, src++, dst++ ) + { + min = *src; + + if ( src[-1] < min ) + min = src[-1]; + if ( src[1] < min ) + min = src[1]; + if ( src[srcStride - 1] < min ) + min = src[srcStride - 1]; + if ( src[srcStride] < min ) + min = src[srcStride]; + if ( src[srcStride + 1] < min ) + min = src[srcStride + 1]; + + *dst = min; + } + + min = *src; + + if ( src[-1] < min ) + min = src[-1]; + if ( src[srcStride - 1] < min ) + min = src[srcStride - 1]; + if ( src[srcStride] < min ) + min = src[srcStride]; + + *dst = min; + + src += srcOffset; + dst += dstOffset; + + // --- process all lines except the last one + for ( int y = startY; y < stopY; y++ ) + { + min = *src; + + if ( src[1] < min ) + min = src[1]; + if ( src[-srcStride] < min ) + min = src[-srcStride]; + if ( src[-srcStride + 1] < min ) + min = src[-srcStride + 1]; + if ( src[srcStride] < min ) + min = src[srcStride]; + if ( src[srcStride + 1] < min ) + min = src[srcStride + 1]; + + *dst = min; + + src++; + dst++; + + // for each pixel + for ( int x = startX; x < stopX; x++, src++, dst++ ) + { + min = *src; + + if ( src[-1] < min ) + min = src[-1]; + if ( src[1] < min ) + min = src[1]; + if ( src[-srcStride - 1] < min ) + min = src[-srcStride - 1]; + if ( src[-srcStride] < min ) + min = src[-srcStride]; + if ( src[-srcStride + 1] < min ) + min = src[-srcStride + 1]; + if ( src[srcStride - 1] < min ) + min = src[srcStride - 1]; + if ( src[srcStride] < min ) + min = src[srcStride]; + if ( src[srcStride + 1] < min ) + min = src[srcStride + 1]; + + *dst = min; + } + + min = *src; + + if ( src[-1] < min ) + min = src[-1]; + if ( src[-srcStride - 1] < min ) + min = src[-srcStride - 1]; + if ( src[-srcStride] < min ) + min = src[-srcStride]; + if ( src[srcStride - 1] < min ) + min = src[srcStride - 1]; + if ( src[srcStride] < min ) + min = src[srcStride]; + + *dst = min; + + src += srcOffset; + dst += dstOffset; + } + + // --- process the last line + *dst = (byte) ( *src | src[1] | src[-srcStride] | src[-srcStride + 1] ); + + min = *src; + + if ( src[1] < min ) + min = src[1]; + if ( src[-srcStride] < min ) + min = src[-srcStride]; + if ( src[-srcStride + 1] < min ) + min = src[-srcStride + 1]; + + *dst = min; + + src++; + dst++; + + // for each pixel + for ( int x = startX; x < stopX; x++, src++, dst++ ) + { + min = *src; + + if ( src[-1] < min ) + min = src[-1]; + if ( src[1] < min ) + min = src[1]; + if ( src[-srcStride - 1] < min ) + min = src[-srcStride - 1]; + if ( src[-srcStride] < min ) + min = src[-srcStride]; + if ( src[-srcStride + 1] < min ) + min = src[-srcStride + 1]; + + *dst = min; + } + + min = *src; + + if ( src[-1] < min ) + min = src[-1]; + if ( src[-srcStride - 1] < min ) + min = src[-srcStride - 1]; + if ( src[-srcStride] < min ) + min = src[-srcStride]; + + *dst = min; + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Morphology/TopHat.cs b/Sources/Accord.Imaging/AForge/Filters/Morphology/TopHat.cs new file mode 100644 index 0000000000..18a194e61 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Morphology/TopHat.cs @@ -0,0 +1,103 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2010 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Top-hat operator from Mathematical Morphology. + /// + /// + /// Top-hat morphological operator subtracts + /// result of morphological opening on the input image + /// from the input image itself. + /// + /// Applied to binary image, the filter allows to get all those object (their parts) + /// which were removed by opening filter, but never restored. + /// + /// The filter accepts 8 and 16 bpp grayscale images and 24 and 48 bpp + /// color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// TopHat filter = new TopHat( ); + /// // apply the filter + /// filter.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + public class TopHat : BaseInPlaceFilter + { + private Opening opening = new Opening( ); + private Subtract subtract = new Subtract( ); + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public TopHat( ) + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format16bppGrayScale] = PixelFormat.Format16bppGrayScale; + formatTranslations[PixelFormat.Format48bppRgb] = PixelFormat.Format48bppRgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Structuring element to pass to operator. + /// + public TopHat( short[,] se ) : this( ) + { + opening = new Opening( se ); + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image ) + { + // perform opening on the source image + UnmanagedImage openedImage = opening.Apply( image ); + // subtract opened image from source image + subtract.UnmanagedOverlayImage = openedImage; + subtract.ApplyInPlace( image ); + + openedImage.Dispose( ); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Noise generation/AdditiveNoise.cs b/Sources/Accord.Imaging/AForge/Filters/Noise generation/AdditiveNoise.cs new file mode 100644 index 0000000000..6369d275b --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Noise generation/AdditiveNoise.cs @@ -0,0 +1,130 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + using AForge.Math.Random; + + /// + /// Additive noise filter. + /// + /// + /// The filter adds random value to each pixel of the source image. + /// The distribution of random values can be specified by random generator. + /// + /// + /// The filter accepts 8 bpp grayscale images and 24 bpp + /// color images for processing. + /// + /// Sample usage: + /// + /// // create random generator + /// IRandomNumberGenerator generator = new UniformGenerator( new Range( -50, 50 ) ); + /// // create filter + /// AdditiveNoise filter = new AdditiveNoise( generator ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class AdditiveNoise : BaseInPlacePartialFilter + { + // random number generator to add noise + IRandomNumberGenerator generator = new UniformGenerator( new Range( -10, 10 ) ); + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Random number genertor used to add noise. + /// + /// + /// Default generator is uniform generator in the range of (-10, 10). + /// + public IRandomNumberGenerator Generator + { + get { return generator; } + set { generator = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public AdditiveNoise( ) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Random number genertor used to add noise. + /// + public AdditiveNoise( IRandomNumberGenerator generator ) + : this( ) + { + this.generator = generator; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + int pixelSize = ( image.PixelFormat == PixelFormat.Format8bppIndexed ) ? 1 : 3; + + int startY = rect.Top; + int stopY = startY + rect.Height; + + int startX = rect.Left * pixelSize; + int stopX = startX + rect.Width * pixelSize; + + int offset = image.Stride - ( stopX - startX ); + + // do the job + byte* ptr = (byte*) image.ImageData.ToPointer( ); + + // allign pointer to the first pixel to process + ptr += ( startY * image.Stride + rect.Left * pixelSize ); + + // for each line + for ( int y = startY; y < stopY; y++ ) + { + // for each pixel + for ( int x = startX; x < stopX; x++, ptr++ ) + { + *ptr = (byte) Math.Max( 0, Math.Min( 255, *ptr + generator.Next( ) ) ); + } + ptr += offset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Noise generation/SaltAndPepperNoise.cs b/Sources/Accord.Imaging/AForge/Filters/Noise generation/SaltAndPepperNoise.cs new file mode 100644 index 0000000000..f996663bf --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Noise generation/SaltAndPepperNoise.cs @@ -0,0 +1,142 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Salt and pepper noise. + /// + /// + /// The filter adds random salt and pepper noise - sets + /// maximum or minimum values to randomly selected pixels. + /// + /// The filter accepts 8 bpp grayscale images and 24/32 bpp + /// color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// SaltAndPepperNoise filter = new SaltAndPepperNoise( 10 ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class SaltAndPepperNoise : BaseInPlacePartialFilter + { + // noise amount in percents + private double noiseAmount = 10; + + // random number generator + private Random rand = new Random( ); + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Amount of noise to generate in percents, [0, 100]. + /// + /// + public double NoiseAmount + { + get { return noiseAmount; } + set { noiseAmount = Math.Max( 0, Math.Min( 100, value ) ); } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public SaltAndPepperNoise( ) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Amount of noise to generate in percents, [0, 100]. + /// + public SaltAndPepperNoise( double noiseAmount ) + : this( ) + { + this.noiseAmount = noiseAmount; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + int startX = rect.Left; + int startY = rect.Top; + int width = rect.Width; + int height = rect.Height; + int stride = image.Stride; + + int noisyPixels = (int) ( ( width * height * noiseAmount ) / 100 ); + + // values to set + byte[] values = new byte[2] { 0, 255 }; + + // do the job + byte* ptr = (byte*) image.ImageData.ToPointer( ); + + if ( image.PixelFormat == PixelFormat.Format8bppIndexed ) + { + // grayscale image + for ( int i = 0; i < noisyPixels; i++ ) + { + int x = startX + rand.Next( width ); + int y = startY + rand.Next( height ); + + ptr[y * stride + x] = values[rand.Next( 2 )]; + } + } + else + { + int pixelSize = ( image.PixelFormat == PixelFormat.Format24bppRgb ) ? 3 : 4; + + // color image + for ( int i = 0; i < noisyPixels; i++ ) + { + int x = startX + rand.Next( width ); + int y = startY + rand.Next( height ); + int colorPlane = rand.Next( 3 ); + + ptr[y * stride + x * pixelSize + colorPlane] = values[rand.Next( 2 )]; + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Normalized RGB/ExtractNormalizedRGBChannel.cs b/Sources/Accord.Imaging/AForge/Filters/Normalized RGB/ExtractNormalizedRGBChannel.cs new file mode 100644 index 0000000000..d39627960 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Normalized RGB/ExtractNormalizedRGBChannel.cs @@ -0,0 +1,174 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Extract normalized RGB channel from color image. + /// + /// + /// Extracts specified normalized RGB channel of color image and returns + /// it as grayscale image. + /// + /// Normalized RGB color space is defined as: + /// + /// r = R / (R + G + B ), + /// g = G / (R + G + B ), + /// b = B / (R + G + B ), + /// + /// where R, G and B are components of RGB color space and + /// r, g and b are components of normalized RGB color space. + /// + /// + /// The filter accepts 24, 32, 48 and 64 bpp color images and produces + /// 8 (if source is 24 or 32 bpp image) or 16 (if source is 48 or 64 bpp image) + /// bpp grayscale image. + /// + /// Sample usage: + /// + /// // create filter + /// ExtractNormalizedRGBChannel filter = new ExtractNormalizedRGBChannel( RGB.G ); + /// // apply the filter + /// Bitmap channelImage = filter.Apply( image ); + /// + /// + /// + /// + /// + /// + public class ExtractNormalizedRGBChannel : BaseFilter + { + private short channel = RGB.R; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Normalized RGB channel to extract. + /// + /// + /// Default value is set to . + /// + /// Invalid channel is specified. + /// + public short Channel + { + get { return channel; } + set + { + if ( ( value != RGB.R ) && ( value != RGB.G ) && ( value != RGB.B ) ) + { + throw new ArgumentException( "Invalid channel is specified." ); + } + channel = value; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public ExtractNormalizedRGBChannel( ) + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format48bppRgb] = PixelFormat.Format16bppGrayScale; + formatTranslations[PixelFormat.Format64bppArgb] = PixelFormat.Format16bppGrayScale; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Normalized RGB channel to extract. + /// + public ExtractNormalizedRGBChannel( short channel ) + : this( ) + { + this.Channel = channel; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData ) + { + // get width and height + int width = sourceData.Width; + int height = sourceData.Height; + + int pixelSize = Image.GetPixelFormatSize( sourceData.PixelFormat ) / 8; + int sum; + + if ( pixelSize <= 4 ) + { + int srcOffset = sourceData.Stride - width * pixelSize; + int dstOffset = destinationData.Stride - width; + + // do the job + byte * src = (byte*) sourceData.ImageData.ToPointer( ); + byte * dst = (byte*) destinationData.ImageData.ToPointer( ); + + for ( int y = 0; y < height; y++ ) + { + for ( int x = 0; x < width; x++, src += pixelSize, dst++ ) + { + sum = ( src[RGB.R] + src[RGB.G] + src[RGB.B] ); + + *dst = ( sum != 0 ) ? (byte) ( 255 * src[channel] / sum ) : (byte) 0; + } + src += srcOffset; + dst += dstOffset; + } + } + else + { + pixelSize /= 2; + + byte* srcBase = (byte*) sourceData.ImageData.ToPointer( ); + byte* dstBase = (byte*) destinationData.ImageData.ToPointer( ); + int srcStride = sourceData.Stride; + int dstStride = destinationData.Stride; + + // for each line + for ( int y = 0; y < height; y++ ) + { + ushort* src = (ushort*) ( srcBase + y * srcStride ); + ushort* dst = (ushort*) ( dstBase + y * dstStride ); + + // for each pixel + for ( int x = 0; x < width; x++, src += pixelSize, dst++ ) + { + sum = ( src[RGB.R] + src[RGB.G] + src[RGB.B] ); + + *dst = ( sum != 0 ) ? (ushort) ( 65535 * src[channel] / sum ) : (ushort) 0; + } + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Other/ApplyMask.cs b/Sources/Accord.Imaging/AForge/Filters/Other/ApplyMask.cs new file mode 100644 index 0000000000..25f31ea74 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Other/ApplyMask.cs @@ -0,0 +1,400 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Apply mask to the specified image. + /// + /// + /// The filter applies mask to the specified image - keeps all pixels + /// in the image if corresponding pixels/values of the mask are not equal to 0. For all + /// 0 pixels/values in mask, corresponding pixels in the source image are set to 0. + /// + /// Mask can be specified as .NET's managed Bitmap, as + /// UnmanagedImage or as byte array. + /// In the case if mask is specified as image, it must be 8 bpp grayscale image. In all case + /// mask size must be the same as size of the image to process. + /// + /// The filter accepts 8/16 bpp grayscale and 24/32/48/64 bpp color images for processing. + /// + /// + public class ApplyMask : BaseInPlacePartialFilter + { + private Bitmap maskImage; + private UnmanagedImage unmanagedMaskImage; + private byte[,] mask; + + /// + /// Mask image to apply. + /// + /// + /// The property specifies mask image to use. The image must be grayscale + /// (8 bpp format) and have the same size as the source image to process. + /// + /// When the property is set, both and + /// properties are set to . + /// + /// + /// The mask image must be 8 bpp grayscale image. + /// + public Bitmap MaskImage + { + get { return maskImage; } + set + { + if ((maskImage != null) && (maskImage.PixelFormat != PixelFormat.Format8bppIndexed)) + { + throw new ArgumentException("The mask image must be 8 bpp grayscale image."); + } + + maskImage = value; + unmanagedMaskImage = null; + mask = null; + } + } + + /// + /// Unmanaged mask image to apply. + /// + /// + /// The property specifies unmanaged mask image to use. The image must be grayscale + /// (8 bpp format) and have the same size as the source image to process. + /// + /// When the property is set, both and + /// properties are set to . + /// + /// + /// The mask image must be 8 bpp grayscale image. + /// + public UnmanagedImage UnmanagedMaskImage + { + get { return unmanagedMaskImage; } + set + { + if ((unmanagedMaskImage != null) && (unmanagedMaskImage.PixelFormat != PixelFormat.Format8bppIndexed)) + { + throw new ArgumentException("The mask image must be 8 bpp grayscale image."); + } + + unmanagedMaskImage = value; + maskImage = null; + mask = null; + } + } + + /// + /// Mask to apply. + /// + /// + /// The property specifies mask array to use. Size of the array must + /// be the same size as the size of the source image to process - its 0th dimension + /// must be equal to image's height and its 1st dimension must be equal to width. For + /// example, for 640x480 image, the mask array must be defined as: + /// + /// byte[,] mask = new byte[480, 640]; + /// + /// + /// + public byte[,] Mask + { + get { return mask; } + set + { + mask = value; + maskImage = null; + unmanagedMaskImage = null; + } + } + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + /// + /// See + /// documentation for additional information. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + private ApplyMask() + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppPArgb] = PixelFormat.Format32bppPArgb; + formatTranslations[PixelFormat.Format16bppGrayScale] = PixelFormat.Format16bppGrayScale; + formatTranslations[PixelFormat.Format48bppRgb] = PixelFormat.Format48bppRgb; + formatTranslations[PixelFormat.Format64bppArgb] = PixelFormat.Format64bppArgb; + formatTranslations[PixelFormat.Format64bppPArgb] = PixelFormat.Format64bppPArgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Mask image to use. + /// + public ApplyMask(Bitmap maskImage) + : this() + { + MaskImage = maskImage; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Unmanaged mask image to use. + /// + public ApplyMask(UnmanagedImage unmanagedMaskImage) + : this() + { + UnmanagedMaskImage = unmanagedMaskImage; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// to use. + /// + public ApplyMask(byte[,] mask) + : this() + { + Mask = mask; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + /// None of the possible mask properties were set. Need to provide mask before applying the filter. + /// Invalid size of provided mask. Its size must be the same as the size of the image to mask. + /// + protected override unsafe void ProcessFilter(UnmanagedImage image, Rectangle rect) + { + if (mask != null) + { + if ((image.Width != mask.GetLength(1)) || + (image.Height != mask.GetLength(0))) + { + throw new ArgumentException("Invalid size of mask array. Its size must be the same as the size of the image to mask."); + } + + fixed (byte* maskPtr = mask) + { + ProcessImage(image, rect, maskPtr, mask.GetLength(1)); + } + } + else if (unmanagedMaskImage != null) + { + if ((image.Width != unmanagedMaskImage.Width) || + (image.Height != unmanagedMaskImage.Height)) + { + throw new ArgumentException("Invalid size of unmanaged mask image. Its size must be the same as the size of the image to mask."); + } + + ProcessImage(image, rect, (byte*)unmanagedMaskImage.ImageData.ToPointer(), + unmanagedMaskImage.Stride); + } + else if (maskImage != null) + { + if ((image.Width != maskImage.Width) || + (image.Height != maskImage.Height)) + { + throw new ArgumentException("Invalid size of mask image. Its size must be the same as the size of the image to mask."); + } + + BitmapData maskData = maskImage.LockBits(new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); + + try + { + ProcessImage(image, rect, (byte*)maskData.Scan0.ToPointer(), + maskData.Stride); + } + finally + { + maskImage.UnlockBits(maskData); + } + } + else + { + throw new InvalidOperationException("None of the possible mask properties were set. Need to provide mask before applying the filter."); + } + } + + private static unsafe void ProcessImage(UnmanagedImage image, Rectangle rect, byte* mask, int maskLineSize) + { + int pixelSize = Bitmap.GetPixelFormatSize(image.PixelFormat) / 8; + + int startY = rect.Top; + int stopY = startY + rect.Height; + + int startX = rect.Left; + int stopX = startX + rect.Width; + + int stride = image.Stride; + int maskOffset = maskLineSize - rect.Width; + + // allign mask to the first pixel + mask += maskLineSize * startY + startX; + + if ((pixelSize <= 4) && (pixelSize != 2)) + { + // 8 bits per channel + byte* imagePtr = (byte*)image.ImageData.ToPointer() + + stride * startY + pixelSize * startX; + int offset = stride - rect.Width * pixelSize; + + #region 8 bit cases + switch (pixelSize) + { + case 1: + // 8 bpp grayscale + for (int y = startY; y < stopY; y++) + { + for (int x = startX; x < stopX; x++, imagePtr++, mask++) + { + if (*mask == 0) + { + *imagePtr = 0; + } + } + imagePtr += offset; + mask += maskOffset; + } + break; + + case 3: + // 24 bpp color + for (int y = startY; y < stopY; y++) + { + for (int x = startX; x < stopX; x++, imagePtr += 3, mask++) + { + if (*mask == 0) + { + imagePtr[RGB.R] = 0; + imagePtr[RGB.G] = 0; + imagePtr[RGB.B] = 0; + } + } + imagePtr += offset; + mask += maskOffset; + } + break; + + case 4: + // 32 bpp color + for (int y = startY; y < stopY; y++) + { + for (int x = startX; x < stopX; x++, imagePtr += 4, mask++) + { + if (*mask == 0) + { + imagePtr[RGB.R] = 0; + imagePtr[RGB.G] = 0; + imagePtr[RGB.B] = 0; + imagePtr[RGB.A] = 0; + } + } + imagePtr += offset; + mask += maskOffset; + } + break; + } + #endregion + } + else + { + // 16 bits per channel + byte* imagePtrBase = (byte*)image.ImageData.ToPointer() + + stride * startY + pixelSize * startX; + + #region 16 bit cases + switch (pixelSize) + { + case 2: + // 16 bpp grayscale + for (int y = startY; y < stopY; y++) + { + ushort* imagePtr = (ushort*)imagePtrBase; + + for (int x = startX; x < stopX; x++, imagePtr++, mask++) + { + if (*mask == 0) + { + *imagePtr = 0; + } + } + imagePtrBase += stride; + mask += maskOffset; + } + break; + + case 6: + // 16 bpp grayscale + for (int y = startY; y < stopY; y++) + { + ushort* imagePtr = (ushort*)imagePtrBase; + + for (int x = startX; x < stopX; x++, imagePtr += 3, mask++) + { + if (*mask == 0) + { + imagePtr[RGB.R] = 0; + imagePtr[RGB.G] = 0; + imagePtr[RGB.B] = 0; + } + } + imagePtrBase += stride; + mask += maskOffset; + } + break; + + case 8: + // 16 bpp grayscale + for (int y = startY; y < stopY; y++) + { + ushort* imagePtr = (ushort*)imagePtrBase; + + for (int x = startX; x < stopX; x++, imagePtr += 4, mask++) + { + if (*mask == 0) + { + imagePtr[RGB.R] = 0; + imagePtr[RGB.G] = 0; + imagePtr[RGB.B] = 0; + imagePtr[RGB.A] = 0; + } + } + imagePtrBase += stride; + mask += maskOffset; + } + break; + } + #endregion + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Other/BlobsFiltering.cs b/Sources/Accord.Imaging/AForge/Filters/Other/BlobsFiltering.cs new file mode 100644 index 0000000000..f3b2b24f0 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Other/BlobsFiltering.cs @@ -0,0 +1,255 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Blobs filtering by size. + /// + /// + /// The filter performs filtering of blobs by their size in the specified + /// source image - all blobs, which are smaller or bigger then specified limits, are + /// removed from the image. + /// + /// The image processing filter treats all none black pixels as objects' + /// pixels and all black pixel as background. + /// + /// The filter accepts 8 bpp grayscale images and 24/32 + /// color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// BlobsFiltering filter = new BlobsFiltering( ); + /// // configure filter + /// filter.CoupledSizeFiltering = true; + /// filter.MinWidth = 70; + /// filter.MinHeight = 70; + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + public class BlobsFiltering : BaseInPlaceFilter + { + private BlobCounter blobCounter = new BlobCounter( ); + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Specifies if size filetering should be coupled or not. + /// + /// + /// See documentation for property + /// of class for more information. + /// + public bool CoupledSizeFiltering + { + get { return blobCounter.CoupledSizeFiltering; } + set { blobCounter.CoupledSizeFiltering = value; } + } + + /// + /// Minimum allowed width of blob. + /// + /// + public int MinWidth + { + get { return blobCounter.MinWidth; } + set { blobCounter.MinWidth = value; } + } + + /// + /// Minimum allowed height of blob. + /// + /// + public int MinHeight + { + get { return blobCounter.MinHeight; } + set { blobCounter.MinHeight = value; } + } + + /// + /// Maximum allowed width of blob. + /// + /// + public int MaxWidth + { + get { return blobCounter.MaxWidth; } + set { blobCounter.MaxWidth = value; } + } + + /// + /// Maximum allowed height of blob. + /// + /// + public int MaxHeight + { + get { return blobCounter.MaxHeight; } + set { blobCounter.MaxHeight = value; } + } + + /// + /// Custom blobs' filter to use. + /// + /// + /// See for information + /// about custom blobs' filtering routine. + /// + public IBlobsFilter BlobsFilter + { + get { return blobCounter.BlobsFilter; } + set { blobCounter.BlobsFilter = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public BlobsFiltering( ) + { + blobCounter.FilterBlobs = true; + blobCounter.MinWidth = 1; + blobCounter.MinHeight = 1; + blobCounter.MaxWidth = int.MaxValue; + blobCounter.MaxHeight = int.MaxValue; + + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + formatTranslations[PixelFormat.Format32bppPArgb] = PixelFormat.Format32bppPArgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Minimum allowed width of blob. + /// Minimum allowed height of blob. + /// Maximum allowed width of blob. + /// Maximum allowed height of blob. + /// + /// This constructor creates an instance of class + /// with property set to false. + /// + public BlobsFiltering( int minWidth, int minHeight, int maxWidth, int maxHeight ) + : this( minWidth, minHeight, maxWidth, maxHeight, false ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Minimum allowed width of blob. + /// Minimum allowed height of blob. + /// Maximum allowed width of blob. + /// Maximum allowed height of blob. + /// Specifies if size filetering should be coupled or not. + /// + /// For information about coupled filtering mode see documentation for + /// property of + /// class. + /// + public BlobsFiltering( int minWidth, int minHeight, int maxWidth, int maxHeight, bool coupledSizeFiltering ) + : this( ) + { + blobCounter.MinWidth = minWidth; + blobCounter.MinHeight = minHeight; + blobCounter.MaxWidth = maxWidth; + blobCounter.MaxHeight = maxHeight; + blobCounter.CoupledSizeFiltering = coupledSizeFiltering; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Custom blobs' filtering routine to use + /// (see ). + /// + public BlobsFiltering( IBlobsFilter blobsFilter ) : this( ) + { + blobCounter.BlobsFilter = blobsFilter; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image ) + { + // use blob counter to build objects map and filter them + blobCounter.ProcessImage( image ); + int[] objectsMap = blobCounter.ObjectLabels; + + // get image width and height + int width = image.Width; + int height = image.Height; + + // do the job + byte* ptr = (byte*) image.ImageData.ToPointer( ); + + if ( image.PixelFormat == PixelFormat.Format8bppIndexed ) + { + int offset = image.Stride - width; + + for ( int y = 0, p = 0; y < height; y++ ) + { + for ( int x = 0; x < width; x++, ptr++, p++ ) + { + if ( objectsMap[p] == 0 ) + { + *ptr = 0; + } + } + ptr += offset; + } + } + else + { + int pixelSize = Bitmap.GetPixelFormatSize( image.PixelFormat ) / 8; + int offset = image.Stride - width * pixelSize; + + for ( int y = 0, p = 0; y < height; y++ ) + { + for ( int x = 0; x < width; x++, ptr += pixelSize, p++ ) + { + if ( objectsMap[p] == 0 ) + { + ptr[RGB.R] = ptr[RGB.G] = ptr[RGB.B] = 0; + } + } + ptr += offset; + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Other/CanvasCrop.cs b/Sources/Accord.Imaging/AForge/Filters/Other/CanvasCrop.cs new file mode 100644 index 0000000000..0e592c6ef --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Other/CanvasCrop.cs @@ -0,0 +1,240 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Volodymyr Goncharov, 2007 +// volodymyr.goncharov@gmail.com +// +// Copyright Andrew Kirillov, 2007-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System.Drawing; + using System.Collections.Generic; + using System.Drawing.Imaging; + + /// + /// Fill areas outiside of specified region. + /// + /// + /// + /// The filter fills areas outside of specified region using the specified color. + /// + /// The filter accepts 8bpp grayscale and 24/32 bpp color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// CanvasCrop filter = new CanvasCrop( new Rectangle( + /// 5, 5, image.Width - 10, image.Height - 10 ), Color.Red ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + public class CanvasCrop : BaseInPlaceFilter + { + // RGB fill color + private byte fillRed = 255; + private byte fillGreen = 255; + private byte fillBlue = 255; + // gray fill color + private byte fillGray = 255; + // region to keep + private Rectangle region; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + /// + /// See + /// documentation for additional information. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// RGB fill color. + /// + /// + /// The color is used to fill areas out of specified region in color images. + /// + /// Default value is set to white - RGB(255, 255, 255). + /// + public Color FillColorRGB + { + get { return Color.FromArgb(fillRed, fillGreen, fillBlue); } + set + { + fillRed = value.R; + fillGreen = value.G; + fillBlue = value.B; + } + } + + /// + /// Gray fill color. + /// + /// + /// The color is used to fill areas out of specified region in grayscale images. + /// + /// Default value is set to white - 255. + /// + public byte FillColorGray + { + get { return fillGray; } + set { fillGray = value; } + } + + /// + /// Region to keep. + /// + /// + /// Pixels inside of the specified region will keep their values, but + /// pixels outside of the region will be filled with specified color. + /// + public Rectangle Region + { + get { return region; } + set { region = value; } + } + + // Private constructor to do common initialization + private CanvasCrop() + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Region to keep. + /// + public CanvasCrop(Rectangle region) + : this() + { + this.region = region; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Region to keep. + /// RGB color to use for filling areas outside of specified region in color images. + /// + public CanvasCrop(Rectangle region, Color fillColorRgb) + : this() + { + this.region = region; + this.fillRed = fillColorRgb.R; + this.fillGreen = fillColorRgb.G; + this.fillBlue = fillColorRgb.B; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Region to keep. + /// Gray color to use for filling areas outside of specified region in grayscale images. + /// + public CanvasCrop(Rectangle region, byte fillColorGray) + : this() + { + this.region = region; + this.fillGray = fillColorGray; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Region to keep. + /// RGB color to use for filling areas outside of specified region in color images. + /// Gray color to use for filling areas outside of specified region in grayscale images. + /// + public CanvasCrop(Rectangle region, Color fillColorRgb, byte fillColorGray) + : this() + { + this.region = region; + this.fillRed = fillColorRgb.R; + this.fillGreen = fillColorRgb.G; + this.fillBlue = fillColorRgb.B; + this.fillGray = fillColorGray; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// + protected override unsafe void ProcessFilter(UnmanagedImage image) + { + int pixelSize = Image.GetPixelFormatSize(image.PixelFormat) / 8; + + // get image width and height + int width = image.Width; + int height = image.Height; + int offset = image.Stride - width * pixelSize; + + // do the job + byte* ptr = (byte*)image.ImageData.ToPointer(); + + if (image.PixelFormat == PixelFormat.Format8bppIndexed) + { + // grayscale image + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++, ptr++) + { + if (!region.Contains(x, y)) + { + *ptr = fillGray; + } + } + ptr += offset; + } + } + else + { + // color image + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++, ptr += pixelSize) + { + if (!region.Contains(x, y)) + { + // red + ptr[RGB.R] = fillRed; + // green + ptr[RGB.G] = fillGreen; + // blue + ptr[RGB.B] = fillBlue; + } + } + ptr += offset; + } + } + } + } +} \ No newline at end of file diff --git a/Sources/Accord.Imaging/AForge/Filters/Other/CanvasFill.cs b/Sources/Accord.Imaging/AForge/Filters/Other/CanvasFill.cs new file mode 100644 index 0000000000..7d03af6e0 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Other/CanvasFill.cs @@ -0,0 +1,242 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2007-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Fill areas iniside of the specified region. + /// + /// + /// + /// The filter fills areas inside of specified region using the specified color. + /// + /// The filter accepts 8bpp grayscale and 24/32 bpp color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// CanvasFill filter = new CanvasFill( new Rectangle( + /// 5, 5, image.Width - 10, image.Height - 10 ), Color.Red ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// + /// + /// + public class CanvasFill : BaseInPlaceFilter + { + // RGB fill color + private byte fillRed = 255; + private byte fillGreen = 255; + private byte fillBlue = 255; + // gray fill color + private byte fillGray = 255; + // region to keep + private Rectangle region; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + /// + /// See + /// documentation for additional information. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + + /// + /// RGB fill color. + /// + /// + /// The color is used to fill areas out of specified region in color images. + /// + /// Default value is set to white - RGB(255, 255, 255). + /// + public Color FillColorRGB + { + get { return Color.FromArgb(fillRed, fillGreen, fillBlue); } + set + { + fillRed = value.R; + fillGreen = value.G; + fillBlue = value.B; + } + } + + /// + /// Gray fill color. + /// + /// + /// The color is used to fill areas out of specified region in grayscale images. + /// + /// Default value is set to white - 255. + /// + public byte FillColorGray + { + get { return fillGray; } + set { fillGray = value; } + } + + /// + /// Region to fill. + /// + /// + /// Pixels inside of the specified region will be filled with specified color. + /// + public Rectangle Region + { + get { return region; } + set { region = value; } + } + + // Private constructor to do common initialization + private CanvasFill() + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Region to fill. + /// + public CanvasFill(Rectangle region) + : this() + { + this.region = region; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Region to fill. + /// RGB color to use for filling areas inside of specified region in color images. + /// + public CanvasFill(Rectangle region, Color fillColorRGB) + : this() + { + this.region = region; + this.fillRed = fillColorRGB.R; + this.fillGreen = fillColorRGB.G; + this.fillBlue = fillColorRGB.B; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Region to fill. + /// Gray color to use for filling areas inside of specified region in grayscale images. + /// + public CanvasFill(Rectangle region, byte fillColorGray) + : this() + { + this.region = region; + this.fillGray = fillColorGray; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Region to fill. + /// RGB color to use for filling areas inside of specified region in color images. + /// Gray color to use for filling areas inside of specified region in grayscale images. + /// + public CanvasFill(Rectangle region, Color fillColorRGB, byte fillColorGray) + : this() + { + this.region = region; + this.fillRed = fillColorRGB.R; + this.fillGreen = fillColorRGB.G; + this.fillBlue = fillColorRGB.B; + this.fillGray = fillColorGray; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// + protected override unsafe void ProcessFilter(UnmanagedImage image) + { + int pixelSize = Image.GetPixelFormatSize(image.PixelFormat) / 8; + + // get image width and height + int width = image.Width; + int height = image.Height; + + // start (X, Y) point of filling region + int startX = Math.Max(0, region.X); + int startY = Math.Max(0, region.Y); + + // check if there is nothing to do + if ((startX >= width) || (startY >= height)) + return; + + // stop (X, Y) point of filling region + int stopX = Math.Min(width, region.Right); + int stopY = Math.Min(height, region.Bottom); + + // check if there is nothing to do + if ((stopX <= startX) || (stopY <= startY)) + return; + + int stride = image.Stride; + + // do the job + byte* ptr = (byte*)image.ImageData.ToPointer() + startY * stride + startX * pixelSize; + + if (image.PixelFormat == PixelFormat.Format8bppIndexed) + { + // grayscale image + int fillWidth = stopX - startX; + + for (int y = startY; y < stopY; y++) + { + AForge.SystemTools.SetUnmanagedMemory(ptr, fillGray, fillWidth); + ptr += stride; + } + } + else + { + // color image + int offset = stride - (stopX - startX) * pixelSize; + + for (int y = startY; y < stopY; y++) + { + for (int x = startX; x < stopX; x++, ptr += pixelSize) + { + ptr[RGB.R] = fillRed; + ptr[RGB.G] = fillGreen; + ptr[RGB.B] = fillBlue; + } + ptr += offset; + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Other/CanvasMove.cs b/Sources/Accord.Imaging/AForge/Filters/Other/CanvasMove.cs new file mode 100644 index 0000000000..ab5211b2b --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Other/CanvasMove.cs @@ -0,0 +1,426 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System.Drawing; + using System.Collections.Generic; + using System.Drawing.Imaging; + + /// + /// Move canvas to the specified point. + /// + /// + /// + /// The filter moves canvas to the specified area filling unused empty areas with specified color. + /// + /// The filter accepts 8/16 bpp grayscale images and 24/32/48/64 bpp color image + /// for processing. + /// + /// Sample usage: + /// + /// // create filter + /// CanvasMove filter = new CanvasMove( new IntPoint( -50, -50 ), Color.Green ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class CanvasMove : BaseInPlaceFilter + { + // RGB fill color + private byte fillRed = 255; + private byte fillGreen = 255; + private byte fillBlue = 255; + private byte fillAlpha = 255; + // gray fill color + private byte fillGray = 255; + // point to move to + private IntPoint movePoint; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + /// + /// See + /// documentation for additional information. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// RGB fill color. + /// + /// + /// The color is used to fill empty areas in color images. + /// + /// Default value is set to white - ARGB(255, 255, 255, 255). + /// + public Color FillColorRGB + { + get { return Color.FromArgb(fillAlpha, fillRed, fillGreen, fillBlue); } + set + { + fillRed = value.R; + fillGreen = value.G; + fillBlue = value.B; + fillAlpha = value.A; + } + } + + /// + /// Gray fill color. + /// + /// + /// The color is used to fill empty areas in grayscale images. + /// + /// Default value is set to white - 255. + /// + public byte FillColorGray + { + get { return fillGray; } + set { fillGray = value; } + } + + /// + /// Point to move the canvas to. + /// + /// + public IntPoint MovePoint + { + get { return movePoint; } + set { movePoint = value; } + } + + // Private constructor to do common initialization + private CanvasMove() + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format16bppGrayScale] = PixelFormat.Format16bppGrayScale; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format48bppRgb] = PixelFormat.Format48bppRgb; + formatTranslations[PixelFormat.Format64bppArgb] = PixelFormat.Format64bppArgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Point to move the canvas to. + /// + public CanvasMove(IntPoint movePoint) + : this() + { + this.movePoint = movePoint; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Point to move the canvas. + /// RGB color to use for filling areas empty areas in color images. + /// + public CanvasMove(IntPoint movePoint, Color fillColorRGB) + : this() + { + this.movePoint = movePoint; + this.fillRed = fillColorRGB.R; + this.fillGreen = fillColorRGB.G; + this.fillBlue = fillColorRGB.B; + this.fillAlpha = fillColorRGB.A; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Point to move the canvas. + /// Gray color to use for filling empty areas in grayscale images. + /// + public CanvasMove(IntPoint movePoint, byte fillColorGray) + : this() + { + this.movePoint = movePoint; + this.fillGray = fillColorGray; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Point to move the canvas. + /// RGB color to use for filling areas empty areas in color images. + /// Gray color to use for filling empty areas in grayscale images. + /// + public CanvasMove(IntPoint movePoint, Color fillColorRGB, byte fillColorGray) + : this() + { + this.movePoint = movePoint; + this.fillRed = fillColorRGB.R; + this.fillGreen = fillColorRGB.G; + this.fillBlue = fillColorRGB.B; + this.fillAlpha = fillColorRGB.A; + this.fillGray = fillColorGray; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// + protected override void ProcessFilter(UnmanagedImage image) + { + int pixelSize = Image.GetPixelFormatSize(image.PixelFormat) / 8; + + switch (pixelSize) + { + case 1: + case 3: + case 4: + ProcessFilter8bpc(image); + break; + case 2: + case 6: + case 8: + ProcessFilter16bpc(image); + break; + } + } + + // Process the filter on the image with 8 bits per color channel + private unsafe void ProcessFilter8bpc(UnmanagedImage image) + { + int pixelSize = Image.GetPixelFormatSize(image.PixelFormat) / 8; + bool is32bpp = (pixelSize == 4); + + // get image width and height + int width = image.Width; + int height = image.Height; + int stride = image.Stride; + + int movePointX = movePoint.X; + int movePointY = movePoint.Y; + + // intersection rectangle + Rectangle intersect = Rectangle.Intersect( + new Rectangle(0, 0, width, height), + new Rectangle(movePointX, movePointY, width, height)); + + // start, stop and step for X adn Y + int yStart = 0; + int yStop = height; + int yStep = 1; + int xStart = 0; + int xStop = width; + int xStep = 1; + + if (movePointY > 0) + { + yStart = height - 1; + yStop = -1; + yStep = -1; + } + if (movePointX > 0) + { + xStart = width - 1; + xStop = -1; + xStep = -1; + } + + // do the job + byte* src = (byte*)image.ImageData.ToPointer(); + byte* pixel, moved; + + if (image.PixelFormat == PixelFormat.Format8bppIndexed) + { + // grayscale image + for (int y = yStart; y != yStop; y += yStep) + { + for (int x = xStart; x != xStop; x += xStep) + { + // current pixel + pixel = src + y * stride + x; + + if (intersect.Contains(x, y)) + { + moved = src + (y - movePointY) * stride + (x - movePointX); + + *pixel = *moved; + } + else + { + *pixel = fillGray; + } + } + } + } + else + { + // color image + for (int y = yStart; y != yStop; y += yStep) + { + for (int x = xStart; x != xStop; x += xStep) + { + // current pixel + pixel = src + y * stride + x * pixelSize; + + if (intersect.Contains(x, y)) + { + moved = src + (y - movePointY) * stride + (x - movePointX) * pixelSize; + + pixel[RGB.R] = moved[RGB.R]; + pixel[RGB.G] = moved[RGB.G]; + pixel[RGB.B] = moved[RGB.B]; + + if (is32bpp) + { + pixel[RGB.A] = moved[RGB.A]; + } + } + else + { + pixel[RGB.R] = fillRed; + pixel[RGB.G] = fillGreen; + pixel[RGB.B] = fillBlue; + + if (is32bpp) + { + pixel[RGB.A] = fillAlpha; + } + } + } + } + } + } + + // Process the filter on the image with 16 bits per color channel + private unsafe void ProcessFilter16bpc(UnmanagedImage image) + { + int pixelSize = Image.GetPixelFormatSize(image.PixelFormat) / 8; + bool is64bpp = (pixelSize == 8); + + // pad fill colours to 16-bits + ushort fillRed = (ushort)(this.fillRed << 8); + ushort fillGreen = (ushort)(this.fillGreen << 8); + ushort fillBlue = (ushort)(this.fillBlue << 8); + ushort fillAlpha = (ushort)(this.fillAlpha << 8); + + // get image width and height + int width = image.Width; + int height = image.Height; + int stride = image.Stride; + + int movePointX = movePoint.X; + int movePointY = movePoint.Y; + + // intersection rectangle + Rectangle intersect = Rectangle.Intersect( + new Rectangle(0, 0, width, height), + new Rectangle(movePointX, movePointY, width, height)); + + // start, stop and step for X and Y + int yStart = 0; + int yStop = height; + int yStep = 1; + int xStart = 0; + int xStop = width; + int xStep = 1; + + if (movePointY > 0) + { + yStart = height - 1; + yStop = -1; + yStep = -1; + } + if (movePointX > 0) + { + xStart = width - 1; + xStop = -1; + xStep = -1; + } + + // do the job + byte* src = (byte*)image.ImageData.ToPointer(); + ushort* pixel, moved; + + if (image.PixelFormat == PixelFormat.Format16bppGrayScale) + { + // grayscale image + for (int y = yStart; y != yStop; y += yStep) + { + for (int x = xStart; x != xStop; x += xStep) + { + // current pixel + pixel = (ushort*)(src + y * stride + x * 2); + + if (intersect.Contains(x, y)) + { + moved = (ushort*)(src + (y - movePointY) * stride + (x - movePointX) * 2); + *pixel = *moved; + } + else + { + *pixel = fillGray; + } + } + } + } + else + { + // color image + for (int y = yStart; y != yStop; y += yStep) + { + for (int x = xStart; x != xStop; x += xStep) + { + // current pixel + pixel = (ushort*)(src + y * stride + x * pixelSize); + + if (intersect.Contains(x, y)) + { + moved = (ushort*)(src + (y - movePointY) * stride + (x - movePointX) * pixelSize); + + pixel[RGB.R] = moved[RGB.R]; + pixel[RGB.G] = moved[RGB.G]; + pixel[RGB.B] = moved[RGB.B]; + + if (is64bpp) + { + pixel[RGB.A] = moved[RGB.A]; + } + } + else + { + pixel[RGB.R] = fillRed; + pixel[RGB.G] = fillGreen; + pixel[RGB.B] = fillBlue; + + if (is64bpp) + { + pixel[RGB.A] = fillAlpha; + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/Sources/Accord.Imaging/AForge/Filters/Other/ConnectedComponentsLabeling.cs b/Sources/Accord.Imaging/AForge/Filters/Other/ConnectedComponentsLabeling.cs new file mode 100644 index 0000000000..aaaabdc00 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Other/ConnectedComponentsLabeling.cs @@ -0,0 +1,233 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Connected components labeling. + /// + /// + /// The filter performs labeling of objects in the source image. It colors + /// each separate object using different color. The image processing filter treats all none + /// black pixels as objects' pixels and all black pixel as background. + /// + /// The filter accepts 8 bpp grayscale images and 24/32 bpp color images and produces + /// 24 bpp RGB image. + /// + /// Sample usage: + /// + /// // create filter + /// ConnectedComponentsLabeling filter = new ConnectedComponentsLabeling( ); + /// // apply the filter + /// Bitmap newImage = filter.Apply( image ); + /// // check objects count + /// int objectCount = filter.ObjectCount; + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class ConnectedComponentsLabeling : BaseFilter + { + // Color table for coloring objects + private static Color[] colorTable = new Color[] + { + Color.Red, Color.Green, Color.Blue, Color.Yellow, + Color.Violet, Color.Brown, Color.Olive, Color.Cyan, + + Color.Magenta, Color.Gold, Color.Indigo, Color.Ivory, + Color.HotPink, Color.DarkRed, Color.DarkGreen, Color.DarkBlue, + + Color.DarkSeaGreen, Color.Gray, Color.DarkKhaki, Color.DarkGray, + Color.LimeGreen, Color.Tomato, Color.SteelBlue, Color.SkyBlue, + + Color.Silver, Color.Salmon, Color.SaddleBrown, Color.RosyBrown, + Color.PowderBlue, Color.Plum, Color.PapayaWhip, Color.Orange + }; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + // blob counter + private BlobCounterBase blobCounter = new BlobCounter( ); + + /// + /// Blob counter used to locate separate blobs. + /// + /// + /// The property allows to set blob counter to use for blobs' localization. + /// + /// Default value is set to . + /// + /// + public BlobCounterBase BlobCounter + { + get { return blobCounter; } + set { blobCounter = value; } + } + + /// + /// Colors used to color the binary image. + /// + public static Color[] ColorTable + { + get { return colorTable; } + set { colorTable = value; } + } + + /// + /// Specifies if blobs should be filtered. + /// + /// + /// See documentation for property + /// of class for more information. + /// + public bool FilterBlobs + { + get { return blobCounter.FilterBlobs; } + set { blobCounter.FilterBlobs = value; } + } + + /// + /// Specifies if size filetering should be coupled or not. + /// + /// + /// See documentation for property + /// of class for more information. + /// + public bool CoupledSizeFiltering + { + get { return blobCounter.CoupledSizeFiltering; } + set { blobCounter.CoupledSizeFiltering = value; } + } + + /// + /// Minimum allowed width of blob. + /// + /// + public int MinWidth + { + get { return blobCounter.MinWidth; } + set { blobCounter.MinWidth = value; } + } + + /// + /// Minimum allowed height of blob. + /// + /// + public int MinHeight + { + get { return blobCounter.MinHeight; } + set { blobCounter.MinHeight = value; } + } + + /// + /// Maximum allowed width of blob. + /// + /// + public int MaxWidth + { + get { return blobCounter.MaxWidth; } + set { blobCounter.MaxWidth = value; } + } + + /// + /// Maximum allowed height of blob. + /// + /// + public int MaxHeight + { + get { return blobCounter.MaxHeight; } + set { blobCounter.MaxHeight = value; } + } + + /// + /// Objects count. + /// + /// + /// The amount of objects found in the last processed image. + /// + public int ObjectCount + { + get { return blobCounter.ObjectsCount; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public ConnectedComponentsLabeling( ) + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppPArgb] = PixelFormat.Format24bppRgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData ) + { + // process the image + blobCounter.ProcessImage( sourceData ); + + // get object labels + int[] labels = blobCounter.ObjectLabels; + + // get width and height + int width = sourceData.Width; + int height = sourceData.Height; + + int dstOffset = destinationData.Stride - width * 3; + + // do the job + byte* dst = (byte*) destinationData.ImageData.ToPointer( ); + int p = 0; + + // for each row + for ( int y = 0; y < height; y++ ) + { + // for each pixel + for ( int x = 0; x < width; x++, dst += 3, p++ ) + { + if ( labels[p] != 0 ) + { + Color c = colorTable[( labels[p] - 1 ) % colorTable.Length]; + + dst[RGB.R] = c.R; + dst[RGB.G] = c.G; + dst[RGB.B] = c.B; + } + } + dst += dstOffset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Other/CornersMarker.cs b/Sources/Accord.Imaging/AForge/Filters/Other/CornersMarker.cs new file mode 100644 index 0000000000..f52f7c695 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Other/CornersMarker.cs @@ -0,0 +1,123 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Filter to mark (highlight) corners of objects. + /// + /// + /// + /// The filter highlights corners of objects on the image using provided corners + /// detection algorithm. + /// + /// The filter accepts 8 bpp grayscale and 24/32 color images for processing. + /// + /// Sample usage: + /// + /// // create corner detector's instance + /// SusanCornersDetector scd = new SusanCornersDetector( ); + /// // create corner maker filter + /// CornersMarker filter = new CornersMarker( scd, Color.Red ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class CornersMarker : BaseInPlaceFilter + { + // color used to mark corners + private Color markerColor = Color.White; + // algorithm used to detect corners + private ICornersDetector detector = null; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Color used to mark corners. + /// + public Color MarkerColor + { + get { return markerColor; } + set { markerColor = value; } + } + + /// + /// Interface of corners' detection algorithm used to detect corners. + /// + public ICornersDetector Detector + { + get { return detector; } + set { detector = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Interface of corners' detection algorithm. + /// + public CornersMarker( ICornersDetector detector ) : this( detector, Color.White ) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Interface of corners' detection algorithm. + /// Marker's color used to mark corner. + /// + public CornersMarker( ICornersDetector detector, Color markerColor ) + { + this.detector = detector; + this.markerColor = markerColor; + + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image ) + { + // get collection of corners + List corners = detector.ProcessImage( image ); + // mark all corners + foreach ( IntPoint corner in corners ) + { + Drawing.FillRectangle( image, new Rectangle( corner.X - 1, corner.Y - 1, 3, 3 ), markerColor ); + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Other/ExtractBiggestBlob.cs b/Sources/Accord.Imaging/AForge/Filters/Other/ExtractBiggestBlob.cs new file mode 100644 index 0000000000..6e50ef1a5 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Other/ExtractBiggestBlob.cs @@ -0,0 +1,260 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Extract the biggest blob from image. + /// + /// + /// The filter locates the biggest blob in the source image and extracts it. + /// The filter also can use the source image for the biggest blob's location only, but extract it from + /// another image, which is set using property. The original image + /// usually is the source of the processed image. + /// + /// The filter accepts 8 bpp grayscale images and 24/32 color images for processing as source image passed to + /// method and also for the . + /// + /// Sample usage: + /// + /// // create filter + /// ExtractBiggestBlob filter = new ExtractBiggestBlob( ); + /// // apply the filter + /// Bitmap biggestBlobsImage = filter.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class ExtractBiggestBlob : IFilter, IFilterInformation + { + private Bitmap originalImage = null; + private IntPoint blobPosition; + + /// + /// Position of the extracted blob. + /// + /// + /// After applying the filter this property keeps position of the extracted + /// blob in the source image. + /// + public IntPoint BlobPosition + { + get { return blobPosition; } + } + + /// + /// Format translations dictionary. + /// + /// + /// The dictionary defines, which pixel formats are supported for + /// source images and which pixel format will be used for resulting image. + /// + /// + /// See for more information. + /// + /// + public Dictionary FormatTranslations + { + get + { + Dictionary formatTranslations = new Dictionary( ); + + // initialize format translation dictionary + if ( originalImage == null ) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppPArgb] = PixelFormat.Format32bppPArgb; + } + else + { + formatTranslations[PixelFormat.Format8bppIndexed] = originalImage.PixelFormat; + formatTranslations[PixelFormat.Format24bppRgb] = originalImage.PixelFormat; + formatTranslations[PixelFormat.Format32bppArgb] = originalImage.PixelFormat; + formatTranslations[PixelFormat.Format32bppRgb] = originalImage.PixelFormat; + formatTranslations[PixelFormat.Format32bppPArgb] = originalImage.PixelFormat; + } + + return formatTranslations; + } + } + + /// + /// Original image, which is the source of the processed image where the biggest blob is searched for. + /// + /// + /// The property may be set to . In this case the biggest blob + /// is extracted from the image, which is passed to image. + /// + /// + public Bitmap OriginalImage + { + get { return originalImage; } + set { originalImage = value; } + } + + /// + /// Apply filter to an image. + /// + /// + /// Source image to get biggest blob from. + /// + /// Returns image of the biggest blob. + /// + /// Unsupported pixel format of the source image. + /// Unsupported pixel format of the original image. + /// Source and original images must have the same size. + /// The source image does not contain any blobs. + /// + public Bitmap Apply( Bitmap image ) + { + // lock source bitmap data + BitmapData srcData = image.LockBits( + new Rectangle( 0, 0, image.Width, image.Height ), + ImageLockMode.ReadOnly, image.PixelFormat ); + + Bitmap dstImage = null; + + try + { + // apply the filter + dstImage = Apply( srcData ); + } + finally + { + // unlock source image + image.UnlockBits( srcData ); + } + + return dstImage; + } + + /// + /// Apply filter to an image. + /// + /// + /// Source image to get biggest blob from. + /// + /// Returns image of the biggest blob. + /// + /// Unsupported pixel format of the source image. + /// Unsupported pixel format of the original image. + /// Source and original images must have the same size. + /// The source image does not contain any blobs. + /// + public Bitmap Apply( BitmapData imageData ) + { + // check pixel format of the source image + if ( !FormatTranslations.ContainsKey( imageData.PixelFormat ) ) + throw new UnsupportedImageFormatException( "Source pixel format is not supported by the filter." ); + + // locate blobs in the source image + BlobCounter blobCounter = new BlobCounter( imageData ); + // get information about blobs + Blob[] blobs = blobCounter.GetObjectsInformation( ); + // find the biggest blob + int maxSize = 0; + Blob biggestBlob = null; + + for ( int i = 0, n = blobs.Length; i < n; i++ ) + { + int size = blobs[i].Rectangle.Width * blobs[i].Rectangle.Height; + + if ( size > maxSize ) + { + maxSize = size; + biggestBlob = blobs[i]; + } + } + + // check if any blob was found + if ( biggestBlob == null ) + { + throw new ArgumentException( "The source image does not contain any blobs." ); + } + + blobPosition = new IntPoint( biggestBlob.Rectangle.Left, biggestBlob.Rectangle.Top ); + + // extract biggest blob's image + if ( originalImage == null ) + { + blobCounter.ExtractBlobsImage( new UnmanagedImage( imageData ), biggestBlob, false ); + } + else + { + // check original image's format + if ( + ( originalImage.PixelFormat != PixelFormat.Format24bppRgb ) && + ( originalImage.PixelFormat != PixelFormat.Format32bppArgb ) && + ( originalImage.PixelFormat != PixelFormat.Format32bppRgb ) && + ( originalImage.PixelFormat != PixelFormat.Format32bppPArgb ) && + ( originalImage.PixelFormat != PixelFormat.Format8bppIndexed ) + ) + { + throw new UnsupportedImageFormatException( "Original image may be grayscale (8bpp indexed) or color (24/32bpp) image only." ); + } + + // check its size + if ( ( originalImage.Width != imageData.Width ) || ( originalImage.Height != imageData.Height ) ) + { + throw new InvalidImagePropertiesException( "Original image must have the same size as passed source image." ); + } + + blobCounter.ExtractBlobsImage( originalImage, biggestBlob, false ); + } + + Bitmap managedImage = biggestBlob.Image.ToManagedImage( ); + + // dispose unmanaged image of the biggest blob + biggestBlob.Image.Dispose( ); + + return managedImage; + } + + /// + /// Apply filter to an image (not implemented). + /// + /// + /// Image in unmanaged memory. + /// + /// Returns filter's result obtained by applying the filter to + /// the source image. + /// + /// The method is not implemented. + /// + public UnmanagedImage Apply( UnmanagedImage image ) + { + throw new NotImplementedException( "The method is not implemented for the filter." ); + } + + /// + /// Apply filter to an image (not implemented). + /// + /// + /// Source image to be processed. + /// Destination image to store filter's result. + /// + /// The method is not implemented. + /// + public void Apply( UnmanagedImage sourceImage, UnmanagedImage destinationImage ) + { + throw new NotImplementedException( "The method is not implemented filter." ); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Other/FillHoles.cs b/Sources/Accord.Imaging/AForge/Filters/Other/FillHoles.cs new file mode 100644 index 0000000000..d490c3c8d --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Other/FillHoles.cs @@ -0,0 +1,180 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2010 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Fill holes in objects in binary image. + /// + /// + /// The filter allows to fill black holes in white object in a binary image. + /// It is possible to specify maximum holes' size to fill using + /// and properties. + /// + /// The filter accepts binary image only, which are represented as 8 bpp images. + /// + /// Sample usage: + /// + /// // create and configure the filter + /// FillHoles filter = new FillHoles( ); + /// filter.MaxHoleHeight = 20; + /// filter.MaxHoleWidth = 20; + /// filter.CoupledSizeFiltering = false; + /// // apply the filter + /// Bitmap result = filter.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class FillHoles : BaseInPlaceFilter + { + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + // coupled size filtering or not + private bool coupledSizeFiltering = true; + // maximum hole size to fill + private int maxHoleWidth = int.MaxValue; + private int maxHoleHeight = int.MaxValue; + + /// + /// Specifies if size filetering should be coupled or not. + /// + /// + /// In uncoupled filtering mode, holes are filled in the case if + /// their width is smaller than or equal to or height is smaller than + /// or equal to . But in coupled filtering mode, holes are filled only in + /// the case if both width and height are smaller or equal to the corresponding value. + /// + /// Default value is set to , what means coupled filtering by size. + /// + /// + public bool CoupledSizeFiltering + { + get { return coupledSizeFiltering; } + set { coupledSizeFiltering = value; } + } + + /// + /// Maximum width of a hole to fill. + /// + /// + /// All holes, which have width greater than this value, are kept unfilled. + /// See for additional information. + /// + /// Default value is set to . + /// + public int MaxHoleWidth + { + get { return maxHoleWidth; } + set { maxHoleWidth = Math.Max( value, 0 ); } + } + + /// + /// Maximum height of a hole to fill. + /// + /// + /// All holes, which have height greater than this value, are kept unfilled. + /// See for additional information. + /// + /// Default value is set to . + /// + public int MaxHoleHeight + { + get { return maxHoleHeight; } + set { maxHoleHeight = Math.Max( value, 0 ); } + } + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + public FillHoles( ) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image ) + { + int width = image.Width; + int height = image.Height; + + // 1 - invert the source image + Invert invertFilter = new Invert( ); + UnmanagedImage invertedImage = invertFilter.Apply( image ); + + // 2 - use blob counter to find holes (they are white objects now on the inverted image) + BlobCounter blobCounter = new BlobCounter( ); + blobCounter.ProcessImage( invertedImage ); + Blob[] blobs = blobCounter.GetObjectsInformation( ); + + // 3 - check all blobs and determine which should be filtered + byte[] newObjectColors = new byte[blobs.Length + 1]; + newObjectColors[0] = 255; // don't touch the objects, which have 0 ID + + for ( int i = 0, n = blobs.Length; i < n; i++ ) + { + Blob blob = blobs[i]; + + if ( ( blob.Rectangle.Left == 0 ) || ( blob.Rectangle.Top == 0 ) || + ( blob.Rectangle.Right == width ) || ( blob.Rectangle.Bottom == height ) ) + { + newObjectColors[blob.ID] = 0; + } + else + { + if ( ( ( coupledSizeFiltering ) && ( blob.Rectangle.Width <= maxHoleWidth ) && ( blob.Rectangle.Height <= maxHoleHeight ) ) | + ( ( !coupledSizeFiltering ) && ( ( blob.Rectangle.Width <= maxHoleWidth ) || ( blob.Rectangle.Height <= maxHoleHeight ) ) ) ) + { + newObjectColors[blob.ID] = 255; + } + else + { + newObjectColors[blob.ID] = 0; + } + } + } + + // 4 - process the source image image and fill holes + byte* ptr = (byte*) image.ImageData.ToPointer( ); + int offset = image.Stride - width; + + int[] objectLabels = blobCounter.ObjectLabels; + + for ( int y = 0, i = 0; y < height; y++ ) + { + for ( int x = 0; x < width; x++, i++, ptr++ ) + { + *ptr = newObjectColors[objectLabels[i]]; + } + ptr += offset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Other/HorizontalRunLengthSmoothing.cs b/Sources/Accord.Imaging/AForge/Filters/Other/HorizontalRunLengthSmoothing.cs new file mode 100644 index 0000000000..5671fb27b --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Other/HorizontalRunLengthSmoothing.cs @@ -0,0 +1,179 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Horizontal run length smoothing algorithm. + /// + /// + /// The class implements horizontal run length smoothing algorithm, which + /// is described in: K.Y. Wong, R.G. Casey and F.M. Wahl, "Document analysis system," + /// IBM J. Res. Devel., Vol. 26, NO. 6,111). 647-656, 1982. + /// + /// Unlike the original description of this algorithm, this implementation must be applied + /// to inverted binary images containing document, i.e. white text on black background. So this + /// implementation fills horizontal black gaps between white pixels. + /// + /// This algorithm is usually used together with , + /// and then further analysis of white blobs. + /// + /// The filter accepts 8 bpp grayscale images, which are supposed to be binary inverted documents. + /// + /// Sample usage: + /// + /// // create filter + /// HorizontalRunLengthSmoothing hrls = new HorizontalRunLengthSmoothing( 32 ); + /// // apply the filter + /// hrls.ApplyInPlace( image ); + /// + /// + /// Source image: + /// + /// Result image: + /// + /// + /// + /// + /// + public class HorizontalRunLengthSmoothing : BaseInPlacePartialFilter + { + private int maxGapSize = 10; + private bool processGapsWithImageBorders = false; + + /// + /// Maximum gap size to fill (in pixels). + /// + /// + /// The property specifies maximum horizontal gap between white pixels to fill. + /// If number of black pixels between some white pixels is bigger than this value, then those + /// black pixels are left as is; otherwise the gap is filled with white pixels. + /// + /// + /// Default value is set to 10. Minimum value is 1. Maximum value is 1000. + /// + public int MaxGapSize + { + get { return maxGapSize; } + set { maxGapSize = Math.Max( 1, Math.Min( 1000, value ) ); } + } + + /// + /// Process gaps between objects and image borders or not. + /// + /// + /// The property sets if gaps between image borders and objects must be treated as + /// gaps between objects and also filled. + /// + /// Default value is set to . + /// + /// + public bool ProcessGapsWithImageBorders + { + get { return processGapsWithImageBorders; } + set { processGapsWithImageBorders = value; } + } + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + /// + /// See + /// documentation for additional information. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public HorizontalRunLengthSmoothing( ) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Maximum gap size to fill (see ). + /// + public HorizontalRunLengthSmoothing( int maxGapSize ) : this( ) + { + MaxGapSize = maxGapSize; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + int startY = rect.Top; + int stopY = startY + rect.Height; + int width = rect.Width; + int offset = image.Stride - rect.Width; + + byte* ptr = (byte*) image.ImageData.ToPointer( ) + startY * image.Stride + rect.Left; + + for ( int y = startY; y < stopY; y++ ) + { + byte* lineStart = ptr; + byte* lineEndPtr = ptr + width; + + // fill gaps between white pixels + while ( ptr < lineEndPtr ) + { + byte* gapStart = ptr; + + // look for non black pixel + while ( ( ptr < lineEndPtr ) && ( *ptr == 0 ) ) + { + ptr++; + } + + // fill the gap between white areas + if ( ptr - gapStart <= maxGapSize ) + { + if ( ( processGapsWithImageBorders ) || + ( ( gapStart != lineStart ) && ( ptr != lineEndPtr ) ) ) + { + while ( gapStart < ptr ) + { + *gapStart = 255; + gapStart++; + } + } + } + + // skip all non black pixels + while ( ( ptr < lineEndPtr ) && ( *ptr != 0 ) ) + { + ptr++; + } + } + + ptr += offset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Other/ImageWarp.cs b/Sources/Accord.Imaging/AForge/Filters/Other/ImageWarp.cs new file mode 100644 index 0000000000..08af5b5fc --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Other/ImageWarp.cs @@ -0,0 +1,206 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2010 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Image warp effect filter. + /// + /// + /// The image processing filter implements a warping filter, which + /// sets pixels in destination image to values from source image taken with specified offset + /// (see ). + /// + /// + /// The filter accepts 8 bpp grayscale images and 24/32 + /// color images for processing. + /// + /// Sample usage: + /// + /// // build warp map + /// int width = image.Width; + /// int height = image.Height; + /// + /// IntPoint[,] warpMap = new IntPoint[height, width]; + /// + /// int size = 8; + /// int maxOffset = -size + 1; + /// + /// for ( int y = 0; y < height; y++ ) + /// { + /// for ( int x = 0; x < width; x++ ) + /// { + /// int dx = ( x / size ) * size - x; + /// int dy = ( y / size ) * size - y; + /// + /// if ( dx + dy <= maxOffset ) + /// { + /// dx = ( x / size + 1 ) * size - 1 - x; + /// } + /// + /// warpMap[y, x] = new IntPoint( dx, dy ); + /// } + /// } + /// // create filter + /// ImageWarp filter = new ImageWarp( warpMap ); + /// // apply the filter + /// Bitmap newImage = filter.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class ImageWarp : BaseFilter + { + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + private IntPoint[,] warpMap = null; + + /// + /// Map used for warping images. + /// + /// + /// The property sets displacement map used for warping images. + /// The map sets offsets of pixels in source image, which are used to set values in destination + /// image. In other words, each pixel in destination image is set to the same value + /// as pixel in source image with corresponding offset (coordinates of pixel in source image + /// are calculated as sum of destination coordinate and corresponding value from warp map). + /// + /// + /// The map array is accessed using [y, x] indexing, i.e. + /// first dimension in the map array corresponds to Y axis of image. + /// + /// If the map is smaller or bigger than the image to process, then only minimum + /// overlapping area of the image is processed. This allows to prepare single big map and reuse + /// it for a set of images for creating similar effects. + /// + /// + public IntPoint[,] WarpMap + { + get { return warpMap; } + set + { + if (value == null) + throw new InvalidOperationException("Warp map can not be set to null."); + + warpMap = value; + } + } + + /// + /// Format translations dictionary. + /// + /// + /// See + /// documentation for additional information. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Map used for warping images (see ). + /// + public ImageWarp(IntPoint[,] warpMap) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + + WarpMap = warpMap; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData) + { + int pixelSize = Image.GetPixelFormatSize(sourceData.PixelFormat) / 8; + + // image width and height + int width = sourceData.Width; + int height = sourceData.Height; + + int widthToProcess = Math.Min(width, warpMap.GetLength(1)); + int heightToProcess = Math.Min(height, warpMap.GetLength(0)); + + int srcStride = sourceData.Stride; + int dstStride = destinationData.Stride; + int dstOffset = dstStride - widthToProcess * pixelSize; + + // new pixel's position + int ox, oy; + + byte* src = (byte*)sourceData.ImageData.ToPointer(); + byte* dst = (byte*)destinationData.ImageData.ToPointer(); + byte* p; + + // for each line + for (int y = 0; y < heightToProcess; y++) + { + // for each pixel + for (int x = 0; x < widthToProcess; x++) + { + // get original pixel's coordinates + ox = x + warpMap[y, x].X; + oy = y + warpMap[y, x].Y; + + // check if the random pixel is inside of image + if ((ox >= 0) && (oy >= 0) && (ox < width) && (oy < height)) + { + p = src + oy * srcStride + ox * pixelSize; + + for (int i = 0; i < pixelSize; i++, dst++, p++) + { + *dst = *p; + } + } + else + { + for (int i = 0; i < pixelSize; i++, dst++) + { + *dst = 0; + } + } + } + + // copy remaining pixel in the row + if (width != widthToProcess) + { + AForge.SystemTools.CopyUnmanagedMemory(dst, src + y * srcStride + widthToProcess * pixelSize, (width - widthToProcess) * pixelSize); + } + + dst += dstOffset; + } + + // copy remaining rows of pixels + for (int y = heightToProcess; y < height; y++, dst += dstStride) + { + AForge.SystemTools.CopyUnmanagedMemory(dst, src + y * srcStride, width * pixelSize); + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Other/Jitter.cs b/Sources/Accord.Imaging/AForge/Filters/Other/Jitter.cs new file mode 100644 index 0000000000..2b9d6340a --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Other/Jitter.cs @@ -0,0 +1,187 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// +// Original idea from CxImage +// http://www.codeproject.com/bitmap/cximage.asp +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Jitter filter. + /// + /// + /// The filter moves each pixel of a source image in + /// random direction within a window of specified radius. + /// + /// The filter accepts 8 bpp grayscale images and 24/32 + /// color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// Jitter filter = new Jitter( 4 ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class Jitter : BaseUsingCopyPartialFilter + { + private int radius = 2; + + // random number generator + private Random rand = new Random(); + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + /// + /// See + /// documentation for additional information. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Jittering radius, [1, 10] + /// + /// + /// Determines radius in which pixels can move. + /// + /// Default value is set to 2. + /// + /// + public int Radius + { + get { return radius; } + set { radius = Math.Max(1, Math.Min(10, value)); } + } + + /// + /// Initializes a new instance of the class. + /// + public Jitter() + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Jittering radius. + /// + public Jitter(int radius) + : this() + { + Radius = radius; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect) + { + int pixelSize = Image.GetPixelFormatSize(sourceData.PixelFormat) / 8; + + // processing start and stop X,Y positions + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + + int srcStride = sourceData.Stride; + int dstStride = destinationData.Stride; + int dstOffset = dstStride - rect.Width * pixelSize; + + // new pixel's position + int ox, oy; + + // maximum value for random number generator + int max = radius * 2 + 1; + + byte* src = (byte*)sourceData.ImageData.ToPointer(); + byte* dst = (byte*)destinationData.ImageData.ToPointer(); + byte* p; + + // copy source to destination before + if (srcStride == dstStride) + { + AForge.SystemTools.CopyUnmanagedMemory(dst, src, srcStride * sourceData.Height); + } + else + { + int len = sourceData.Width * pixelSize; + + for (int y = 0, heigh = sourceData.Height; y < heigh; y++) + { + AForge.SystemTools.CopyUnmanagedMemory( + dst + dstStride * y, src + srcStride * y, len); + } + } + + // allign pointer to the first pixel to process + dst += (startY * dstStride + startX * pixelSize); + + // Note: + // It is possible to speed-up this filter creating separate + // loops for RGB and grayscale images. + + // for each line + for (int y = startY; y < stopY; y++) + { + // for each pixel + for (int x = startX; x < stopX; x++) + { + // generate radnom pixel's position + ox = x + rand.Next(max) - radius; + oy = y + rand.Next(max) - radius; + + // check if the random pixel is inside our image + if ((ox >= startX) && (oy >= startY) && (ox < stopX) && (oy < stopY)) + { + p = src + oy * srcStride + ox * pixelSize; + + for (int i = 0; i < pixelSize; i++, dst++, p++) + { + *dst = *p; + } + } + else + { + dst += pixelSize; + } + } + dst += dstOffset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Other/MaskedFilter.cs b/Sources/Accord.Imaging/AForge/Filters/Other/MaskedFilter.cs new file mode 100644 index 0000000000..45b8fa6bc --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Other/MaskedFilter.cs @@ -0,0 +1,482 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Apply filter according to the specified mask. + /// + /// + /// The image processing routine applies the specified to + /// a source image according to the specified mask - if a pixel/value in the specified mask image/array + /// is set to 0, then the original pixel's value is kept; otherwise the pixel is filtered using the + /// specified base filter. + /// + /// Mask can be specified as .NET's managed Bitmap, as + /// UnmanagedImage or as byte array. + /// In the case if mask is specified as image, it must be 8 bpp grayscale image. In all case + /// mask size must be the same as size of the image to process. + /// + /// Pixel formats accepted by this filter are specified by the . + /// + /// Sample usage: + /// + /// // create the filter + /// MaskedFilter maskedFilter = new MaskedFilter( new Sepia( ), maskImage ); + /// // apply the filter + /// maskedFilter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Mask image: + /// + /// Result image: + /// + /// + /// + public class MaskedFilter : BaseInPlacePartialFilter + { + private IFilter baseFilter = null; + + // masks (one of them must be set) + private Bitmap maskImage; + private UnmanagedImage unmanagedMaskImage; + private byte[,] mask; + + /// + /// Base filter to apply to the source image. + /// + /// + /// The property specifies base filter which is applied to the specified source + /// image (to all pixels which have corresponding none 0 value in mask image/array). + /// + /// The base filter must implement interface. + /// + /// The base filter must never change image's pixel format. For example, if source + /// image's pixel format is 24 bpp color image, then it must stay the same after the base + /// filter is applied. + /// + /// The base filter must never change size of the source image. + /// + /// + /// Base filter can not be set to null. + /// The specified base filter must implement IFilterInformation interface. + /// The specified filter must never change pixel format. + /// + public IFilter BaseFilter + { + get { return baseFilter; } + + private set + { + if (value == null) + throw new InvalidOperationException("Base filter can not be set to null."); + + var filterInfo = value as IFilterInformation; + + if (filterInfo == null) + throw new ArgumentException("The specified base filter must implement IFilterInformation interface."); + + // check that the base filter does not change pixel format of image + Dictionary baseFormatTranslations = filterInfo.FormatTranslations; + + foreach (var translation in baseFormatTranslations) + { + if (translation.Key != translation.Value) + throw new ArgumentException("The specified filter must never change pixel format."); + } + + baseFilter = value; + } + } + + /// + /// Mask image to apply. + /// + /// + /// The property specifies mask image to use. The image must be grayscale + /// (8 bpp format) and have the same size as the source image to process. + /// + /// When the property is set, both and + /// properties are set to . + /// + /// + /// The mask image must be 8 bpp grayscale image. + /// + public Bitmap MaskImage + { + get { return maskImage; } + set + { + if ((maskImage != null) && (maskImage.PixelFormat != PixelFormat.Format8bppIndexed)) + { + throw new ArgumentException("The mask image must be 8 bpp grayscale image."); + } + + maskImage = value; + unmanagedMaskImage = null; + mask = null; + } + } + + /// + /// Unmanaged mask image to apply. + /// + /// + /// The property specifies unmanaged mask image to use. The image must be grayscale + /// (8 bpp format) and have the same size as the source image to process. + /// + /// When the property is set, both and + /// properties are set to . + /// + /// + /// The mask image must be 8 bpp grayscale image. + /// + public UnmanagedImage UnmanagedMaskImage + { + get { return unmanagedMaskImage; } + set + { + if ((unmanagedMaskImage != null) && (unmanagedMaskImage.PixelFormat != PixelFormat.Format8bppIndexed)) + { + throw new ArgumentException("The mask image must be 8 bpp grayscale image."); + } + + unmanagedMaskImage = value; + maskImage = null; + mask = null; + } + } + + /// + /// Mask to apply. + /// + /// + /// The property specifies mask array to use. Size of the array must + /// be the same size as the size of the source image to process - its 0th dimension + /// must be equal to image's height and its 1st dimension must be equal to width. For + /// example, for 640x480 image, the mask array must be defined as: + /// + /// byte[,] mask = new byte[480, 640]; + /// + /// + /// + public byte[,] Mask + { + get { return mask; } + set + { + mask = value; + maskImage = null; + unmanagedMaskImage = null; + } + } + + /// + /// Format translations dictionary. + /// + /// + /// See + /// documentation for additional information. + /// + /// The property returns format translation table from the + /// . + /// + /// + public override Dictionary FormatTranslations + { + get { return ((IFilterInformation)baseFilter).FormatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Base filter to apply to the specified source image. + /// Mask image to use. + /// + public MaskedFilter(IFilter baseFiler, Bitmap maskImage) + { + BaseFilter = baseFiler; + MaskImage = maskImage; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Base filter to apply to the specified source image. + /// Unmanaged mask image to use. + /// + public MaskedFilter(IFilter baseFiler, UnmanagedImage unmanagedMaskImage) + { + BaseFilter = baseFiler; + UnmanagedMaskImage = unmanagedMaskImage; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Base filter to apply to the specified source image. + /// to use. + /// + public MaskedFilter(IFilter baseFiler, byte[,] mask) + { + BaseFilter = baseFiler; + Mask = mask; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + /// None of the possible mask properties were set. Need to provide mask before applying the filter. + /// Invalid size of provided mask. Its size must be the same as the size of the image to mask. + /// + protected override unsafe void ProcessFilter(UnmanagedImage image, Rectangle rect) + { + if (mask != null) + { + if ((image.Width != mask.GetLength(1)) || + (image.Height != mask.GetLength(0))) + { + throw new ArgumentException("Invalid size of mask array. Its size must be the same as the size of the image to mask."); + } + + fixed (byte* maskPtr = mask) + { + ProcessImage(image, rect, maskPtr, mask.GetLength(1)); + } + } + else if (unmanagedMaskImage != null) + { + if ((image.Width != unmanagedMaskImage.Width) || + (image.Height != unmanagedMaskImage.Height)) + { + throw new ArgumentException("Invalid size of unmanaged mask image. Its size must be the same as the size of the image to mask."); + } + + ProcessImage(image, rect, (byte*)unmanagedMaskImage.ImageData.ToPointer(), + unmanagedMaskImage.Stride); + } + else if (maskImage != null) + { + if ((image.Width != maskImage.Width) || + (image.Height != maskImage.Height)) + { + throw new ArgumentException("Invalid size of mask image. Its size must be the same as the size of the image to mask."); + } + + BitmapData maskData = maskImage.LockBits(new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); + + try + { + ProcessImage(image, rect, (byte*)maskData.Scan0.ToPointer(), + maskData.Stride); + } + finally + { + maskImage.UnlockBits(maskData); + } + } + else + { + throw new InvalidOperationException("None of the possible mask properties were set. Need to provide mask before applying the filter."); + } + } + + private unsafe void ProcessImage(UnmanagedImage image, Rectangle rect, byte* mask, int maskLineSize) + { + // apply base filter to the specified image + UnmanagedImage filteredImage = baseFilter.Apply(image); + + if ((image.Width != filteredImage.Width) || + (image.Height != filteredImage.Height)) + { + throw new ArgumentException("Base filter must not change image size."); + } + + int pixelSize = Bitmap.GetPixelFormatSize(image.PixelFormat) / 8; + + int startY = rect.Top; + int stopY = startY + rect.Height; + + int startX = rect.Left; + int stopX = startX + rect.Width; + + int srcStride = image.Stride; + int filteredStride = filteredImage.Stride; + int maskOffset = maskLineSize - rect.Width; + + // allign mask to the first pixel + mask += maskLineSize * startY + startX; + + if ((pixelSize <= 4) && (pixelSize != 2)) + { + // 8 bits per channel + byte* imagePtr = (byte*)image.ImageData.ToPointer() + + srcStride * startY + pixelSize * startX; + int srcOffset = srcStride - rect.Width * pixelSize; + + byte* filteredPtr = (byte*)filteredImage.ImageData.ToPointer() + + filteredStride * startY + pixelSize * startX; + int filteredOffset = filteredStride - rect.Width * pixelSize; + + #region 8 bit cases + switch (pixelSize) + { + case 1: + // 8 bpp grayscale + for (int y = startY; y < stopY; y++) + { + for (int x = startX; x < stopX; x++, imagePtr++, filteredPtr++, mask++) + { + if (*mask != 0) + { + *imagePtr = *filteredPtr; + } + } + imagePtr += srcOffset; + filteredPtr += filteredOffset; + mask += maskOffset; + } + break; + + case 3: + // 24 bpp color + for (int y = startY; y < stopY; y++) + { + for (int x = startX; x < stopX; x++, imagePtr += 3, filteredPtr += 3, mask++) + { + if (*mask != 0) + { + imagePtr[RGB.R] = filteredPtr[RGB.R]; + imagePtr[RGB.G] = filteredPtr[RGB.G]; + imagePtr[RGB.B] = filteredPtr[RGB.B]; + } + } + imagePtr += srcOffset; + filteredPtr += filteredOffset; + mask += maskOffset; + } + break; + + case 4: + // 32 bpp color + for (int y = startY; y < stopY; y++) + { + for (int x = startX; x < stopX; x++, imagePtr += 4, filteredPtr += 4, mask++) + { + if (*mask != 0) + { + imagePtr[RGB.R] = filteredPtr[RGB.R]; + imagePtr[RGB.G] = filteredPtr[RGB.G]; + imagePtr[RGB.B] = filteredPtr[RGB.B]; + imagePtr[RGB.A] = filteredPtr[RGB.A]; + } + } + imagePtr += srcOffset; + filteredPtr += filteredOffset; + mask += maskOffset; + } + break; + } + #endregion + } + else + { + // 16 bits per channel + byte* imagePtrBase = (byte*)image.ImageData.ToPointer() + + srcStride * startY + pixelSize * startX; + byte* filteredPtrBase = (byte*)filteredImage.ImageData.ToPointer() + + filteredStride * startY + pixelSize * startX; + + #region 16 bit cases + switch (pixelSize) + { + case 2: + // 16 bpp grayscale + for (int y = startY; y < stopY; y++) + { + ushort* imagePtr = (ushort*)imagePtrBase; + ushort* filteredPtr = (ushort*)filteredPtrBase; + + for (int x = startX; x < stopX; x++, imagePtr++, filteredPtr++, mask++) + { + if (*mask != 0) + { + *imagePtr = *filteredPtr; + } + } + imagePtrBase += srcStride; + filteredPtrBase += filteredStride; + mask += maskOffset; + } + break; + + case 6: + // 16 bpp grayscale + for (int y = startY; y < stopY; y++) + { + ushort* imagePtr = (ushort*)imagePtrBase; + ushort* filteredPtr = (ushort*)filteredPtrBase; + + for (int x = startX; x < stopX; x++, imagePtr += 3, filteredPtr += 3, mask++) + { + if (*mask != 0) + { + imagePtr[RGB.R] = filteredPtr[RGB.R]; + imagePtr[RGB.G] = filteredPtr[RGB.G]; + imagePtr[RGB.B] = filteredPtr[RGB.B]; + } + } + imagePtrBase += srcStride; + filteredPtrBase += filteredStride; + mask += maskOffset; + } + break; + + case 8: + // 16 bpp grayscale + for (int y = startY; y < stopY; y++) + { + ushort* imagePtr = (ushort*)imagePtrBase; + ushort* filteredPtr = (ushort*)filteredPtrBase; + + for (int x = startX; x < stopX; x++, imagePtr += 4, filteredPtr += 4, mask++) + { + if (*mask != 0) + { + imagePtr[RGB.R] = filteredPtr[RGB.R]; + imagePtr[RGB.G] = filteredPtr[RGB.G]; + imagePtr[RGB.B] = filteredPtr[RGB.B]; + imagePtr[RGB.A] = filteredPtr[RGB.A]; + } + } + imagePtrBase += srcStride; + filteredPtrBase += filteredStride; + mask += maskOffset; + } + break; + } + #endregion + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Other/Mirror.cs b/Sources/Accord.Imaging/AForge/Filters/Other/Mirror.cs new file mode 100644 index 0000000000..a3771162e --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Other/Mirror.cs @@ -0,0 +1,215 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Mirroring filter. + /// + /// + /// The filter mirrors image around X and/or Y axis (horizontal and vertical + /// mirroring). + /// + /// The filter accepts 8 bpp grayscale images and 24 bpp + /// color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// Mirror filter = new Mirror( false, true ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class Mirror : BaseInPlacePartialFilter + { + private bool mirrorX = false; + private bool mirrorY = false; + + // format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Specifies if mirroring should be done for X axis (horizontal mirroring). + /// + /// + public bool MirrorX + { + get { return mirrorX; } + set { mirrorX = value; } + } + + /// + /// Specifies if mirroring should be done for Y axis (vertical mirroring). + /// + /// + public bool MirrorY + { + get { return mirrorY; } + set { mirrorY = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Specifies if mirroring should be done for X axis. + /// Specifies if mirroring should be done for Y axis + /// + public Mirror( bool mirrorX, bool mirrorY ) + { + this.mirrorX = mirrorX; + this.MirrorY = mirrorY; + + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + int pixelSize = ( image.PixelFormat == PixelFormat.Format8bppIndexed ) ? 1 : 3; + + int width = rect.Width; + int height = rect.Height; + + // processing start and stop X,Y positions + int startY = rect.Top; + int stopY = startY + height; + int startX = rect.Left; + int stopX = startX + width; + int startXInBytes = startX * pixelSize; + int stopXInBytes = stopX * pixelSize; + + int stride = image.Stride; + + // perform Y mirroring + if ( mirrorY ) + { + // first pointer - points to the first pixel in line + byte* ptr1 = (byte*) image.ImageData.ToPointer( ); + ptr1 += ( startY * stride + startX * pixelSize ); + // second pointer - points to the last pixel in line + byte* ptr2 = (byte*) image.ImageData.ToPointer( ); + ptr2 += ( startY * stride + ( stopX - 1 ) * pixelSize ); + + // offsets + int offset1 = stride - ( width >> 1 ) * pixelSize; + int offset2 = stride + ( width >> 1 ) * pixelSize; + + // temporary value for swapping + byte v; + + if ( image.PixelFormat == PixelFormat.Format8bppIndexed ) + { + // grayscale mirroring + + // for each line + for ( int y = startY; y < stopY; y++ ) + { + // for each pixel + for ( int x = startX, halfStopX = startX + ( width >> 1 ); x < halfStopX; x++, ptr1++, ptr2-- ) + { + // swap values + v = *ptr1; + *ptr1 = *ptr2; + *ptr2 = v; + } + ptr1 += offset1; + ptr2 += offset2; + } + } + else + { + // color mirroring + + // for each line + for ( int y = startY; y < stopY; y++ ) + { + // for each pixel + for ( int x = startX, halfStopX = startX + ( width >> 1 ); x < halfStopX; x++, ptr1 += 3, ptr2 -= 3 ) + { + // swap Red + v = ptr1[RGB.R]; + ptr1[RGB.R] = ptr2[RGB.R]; + ptr2[RGB.R] = v; + + // swap Green + v = ptr1[RGB.G]; + ptr1[RGB.G] = ptr2[RGB.G]; + ptr2[RGB.G] = v; + + // swap Blue + v = ptr1[RGB.B]; + ptr1[RGB.B] = ptr2[RGB.B]; + ptr2[RGB.B] = v; + } + ptr1 += offset1; + ptr2 += offset2; + } + } + } + + // perform X mirroring + if ( mirrorX ) + { + int offset = stride - rect.Width * pixelSize; + + // first pointer - points to the first line + byte* ptr1 = (byte*) image.ImageData.ToPointer( ); + ptr1 += ( startY * stride + startX * pixelSize ); + // second pointer - points to the last line + byte* ptr2 = (byte*) image.ImageData.ToPointer( ); + ptr2 += ( ( stopY - 1 ) * stride + startX * pixelSize ); + + // temporary value for swapping + byte v; + + // for each line + for ( int y = startY, halfStopY = startY + ( height >> 1 ); y < halfStopY; y++ ) + { + // for each pixel + for ( int x = startXInBytes; x < stopXInBytes; x++, ptr1++, ptr2++ ) + { + // swap values + v = *ptr1; + *ptr1 = *ptr2; + *ptr2 = v; + } + ptr1 += offset; + ptr2 += offset - stride - stride; + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Other/OilPainting.cs b/Sources/Accord.Imaging/AForge/Filters/Other/OilPainting.cs new file mode 100644 index 0000000000..5b83ebf25 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Other/OilPainting.cs @@ -0,0 +1,287 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// +// Original idea found in Paint.NET project +// http://www.eecs.wsu.edu/paint.net/ +// +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Oil painting filter. + /// + /// + /// Processing source image the filter changes each pixels' value + /// to the value of pixel with the most frequent intensity within window of the + /// specified size. Going through the window the filters + /// finds which intensity of pixels is the most frequent. Then it updates value + /// of the pixel in the center of the window to the value with the most frequent + /// intensity. The update procedure creates the effect of oil painting. + /// + /// The filter accepts 8 bpp grayscale images and 24/32 + /// color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// OilPainting filter = new OilPainting( 15 ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class OilPainting : BaseUsingCopyPartialFilter + { + private int brushSize = 5; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + /// + /// See + /// documentation for additional information. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Brush size, [3, 21]. + /// + /// + /// Window size to search for most frequent pixels' intensity. + /// + /// Default value is set to 5. + /// + public int BrushSize + { + get { return brushSize; } + set { brushSize = Math.Max(3, Math.Min(21, value | 1)); } + } + + /// + /// Initializes a new instance of the class. + /// + public OilPainting() + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Brush size. + /// + public OilPainting(int brushSize) + : this() + { + BrushSize = brushSize; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect) + { + int pixelSize = Image.GetPixelFormatSize(sourceData.PixelFormat) / 8; + + // processing start and stop X,Y positions + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + + int srcStride = sourceData.Stride; + int dstStride = destinationData.Stride; + int srcOffset = srcStride - rect.Width * pixelSize; + int dstOffset = srcStride - rect.Width * pixelSize; + + // loop and array indexes + int i, j, t; + // brush radius + int radius = brushSize >> 1; + + // intensity values + byte intensity, maxIntensity; + int[] intensities = new int[256]; + + byte* src = (byte*)sourceData.ImageData.ToPointer(); + byte* dst = (byte*)destinationData.ImageData.ToPointer(); + byte* p; + + // allign pointers to the first pixel to process + src += (startY * srcStride + startX * pixelSize); + dst += (startY * dstStride + startX * pixelSize); + + if (destinationData.PixelFormat == PixelFormat.Format8bppIndexed) + { + // Grayscale image + + // for each line + for (int y = startY; y < stopY; y++) + { + // for each pixel + for (int x = startX; x < stopX; x++, src++, dst++) + { + // clear arrays + Array.Clear(intensities, 0, 256); + + // for each kernel row + for (i = -radius; i <= radius; i++) + { + t = y + i; + + // skip row + if (t < startY) + continue; + // break + if (t >= stopY) + break; + + // for each kernel column + for (j = -radius; j <= radius; j++) + { + t = x + j; + + // skip column + if (t < startX) + continue; + + if (t < stopX) + { + intensity = src[i * srcStride + j]; + intensities[intensity]++; + } + } + } + + // get most frequent intesity + maxIntensity = 0; + j = 0; + + for (i = 0; i < 256; i++) + { + if (intensities[i] > j) + { + maxIntensity = (byte)i; + j = intensities[i]; + } + } + + // set destination pixel + *dst = maxIntensity; + } + src += srcOffset; + dst += dstOffset; + } + } + else + { + // RGB image + int[] red = new int[256]; + int[] green = new int[256]; + int[] blue = new int[256]; + + // for each line + for (int y = startY; y < stopY; y++) + { + // for each pixel + for (int x = startX; x < stopX; x++, src += pixelSize, dst += pixelSize) + { + // clear arrays + Array.Clear(intensities, 0, 256); + Array.Clear(red, 0, 256); + Array.Clear(green, 0, 256); + Array.Clear(blue, 0, 256); + + // for each kernel row + for (i = -radius; i <= radius; i++) + { + t = y + i; + + // skip row + if (t < startY) + continue; + // break + if (t >= stopY) + break; + + // for each kernel column + for (j = -radius; j <= radius; j++) + { + t = x + j; + + // skip column + if (t < startX) + continue; + + if (t < stopX) + { + p = &src[i * srcStride + j * pixelSize]; + + // grayscale value using BT709 + intensity = (byte)(0.2125 * p[RGB.R] + 0.7154 * p[RGB.G] + 0.0721 * p[RGB.B]); + + // + intensities[intensity]++; + // red + red[intensity] += p[RGB.R]; + // green + green[intensity] += p[RGB.G]; + // blue + blue[intensity] += p[RGB.B]; + } + } + } + + // get most frequent intesity + maxIntensity = 0; + j = 0; + + for (i = 0; i < 256; i++) + { + if (intensities[i] > j) + { + maxIntensity = (byte)i; + j = intensities[i]; + } + } + + // set destination pixel + dst[RGB.R] = (byte)(red[maxIntensity] / intensities[maxIntensity]); + dst[RGB.G] = (byte)(green[maxIntensity] / intensities[maxIntensity]); + dst[RGB.B] = (byte)(blue[maxIntensity] / intensities[maxIntensity]); + } + src += srcOffset; + dst += dstOffset; + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Other/Pixellate.cs b/Sources/Accord.Imaging/AForge/Filters/Other/Pixellate.cs new file mode 100644 index 0000000000..aa1d577aa --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Other/Pixellate.cs @@ -0,0 +1,265 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Pixellate filter. + /// + /// + /// The filter processes an image creating the effect of an image with larger + /// pixels - pixellated image. The effect is achieved by filling image's rectangles of the + /// specified size by the color, which is mean color value for the corresponding rectangle. + /// The size of rectangles to process is set by and + /// properties. + /// + /// The filter accepts 8 bpp grayscale images and 24 bpp + /// color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// Pixellate filter = new Pixellate( ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class Pixellate : BaseInPlacePartialFilter + { + private int pixelWidth = 8; + private int pixelHeight = 8; + + // format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Pixel width, [2, 32]. + /// + /// + /// Default value is set to 8. + /// + /// + /// + /// + public int PixelWidth + { + get { return pixelWidth; } + set { pixelWidth = Math.Max(2, Math.Min(32, value)); } + } + + /// + /// Pixel height, [2, 32]. + /// + /// + /// Default value is set to 8. + /// + /// + /// + /// + public int PixelHeight + { + get { return pixelHeight; } + set { pixelHeight = Math.Max(2, Math.Min(32, value)); } + } + + /// + /// Pixel size, [2, 32]. + /// + /// + /// The property is used to set both and + /// simultaneously. + /// + public int PixelSize + { + set { pixelWidth = pixelHeight = Math.Max(2, Math.Min(32, value)); } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public Pixellate() + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Pixel size. + /// + public Pixellate(int pixelSize) + : this() + { + PixelSize = pixelSize; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Pixel width. + /// Pixel height. + /// + public Pixellate(int pixelWidth, int pixelHeight) + : this() + { + PixelWidth = pixelWidth; + PixelHeight = pixelHeight; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter(UnmanagedImage image, Rectangle rect) + { + int pixelSize = (image.PixelFormat == PixelFormat.Format8bppIndexed) ? 1 : 3; + + // processing start and stop Y positions + int startY = rect.Top; + int stopY = startY + rect.Height; + // processing width and offset + int width = rect.Width; + int offset = image.Stride - width * pixelSize; + + // loop indexes and temp vars + int i, j, k, x, t1, t2; + // line length to process + int len = (int)((width - 1) / pixelWidth) + 1; + // reminder + int rem = ((width - 1) % pixelWidth) + 1; + + // do the job + byte* src = (byte*)image.ImageData.ToPointer(); + // allign pointer to the first pixel to process + src += (startY * image.Stride + rect.Left * pixelSize); + + byte* dst = src; + + if (image.PixelFormat == PixelFormat.Format8bppIndexed) + { + // Grayscale image + int[] tmp = new int[len]; + + for (int y1 = startY, y2 = startY; y1 < stopY; ) + { + // collect pixels + Array.Clear(tmp, 0, len); + + // calculate + for (i = 0; (i < pixelHeight) && (y1 < stopY); i++, y1++) + { + // for each pixel + for (x = 0; x < width; x++, src++) + { + tmp[(int)(x / pixelWidth)] += (int)*src; + } + src += offset; + } + + // get average values + t1 = i * pixelWidth; + t2 = i * rem; + + for (j = 0; j < len - 1; j++) + tmp[j] /= t1; + tmp[j] /= t2; + + // save average value to destination image + for (i = 0; (i < pixelHeight) && (y2 < stopY); i++, y2++) + { + // for each pixel + for (x = 0; x < width; x++, dst++) + { + *dst = (byte)tmp[(int)(x / pixelWidth)]; + } + dst += offset; + } + } + } + else + { + // RGB image + int[] tmp = new int[len * 3]; + + for (int y1 = startY, y2 = startY; y1 < stopY; ) + { + // collect pixels + Array.Clear(tmp, 0, len * 3); + + // calculate + for (i = 0; (i < pixelHeight) && (y1 < stopY); i++, y1++) + { + // for each pixel + for (x = 0; x < width; x++, src += 3) + { + k = (x / pixelWidth) * 3; + tmp[k] += src[RGB.R]; + tmp[k + 1] += src[RGB.G]; + tmp[k + 2] += src[RGB.B]; + } + src += offset; + } + + // get average values + t1 = i * pixelWidth; + t2 = i * rem; + + for (j = 0, k = 0; j < len - 1; j++, k += 3) + { + tmp[k] /= t1; + tmp[k + 1] /= t1; + tmp[k + 2] /= t1; + } + tmp[k] /= t2; + tmp[k + 1] /= t2; + tmp[k + 2] /= t2; + + // save average value to destination image + for (i = 0; (i < pixelHeight) && (y2 < stopY); i++, y2++) + { + // for each pixel + for (x = 0; x < width; x++, dst += 3) + { + k = (x / pixelWidth) * 3; + dst[RGB.R] = (byte)tmp[k]; + dst[RGB.G] = (byte)tmp[k + 1]; + dst[RGB.B] = (byte)tmp[k + 2]; + } + dst += offset; + } + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Other/SimpleSkeletonization.cs b/Sources/Accord.Imaging/AForge/Filters/Other/SimpleSkeletonization.cs new file mode 100644 index 0000000000..4c8a8c1f6 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Other/SimpleSkeletonization.cs @@ -0,0 +1,215 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Simple skeletonization filter. + /// + /// + /// The filter build simple objects' skeletons by thinning them until + /// they have one pixel wide "bones" horizontally and vertically. The filter uses + /// and colors to distinguish + /// between object and background. + /// + /// The filter accepts 8 bpp grayscale images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// SimpleSkeletonization filter = new SimpleSkeletonization( ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class SimpleSkeletonization : BaseUsingCopyPartialFilter + { + private byte bg = 0; + private byte fg = 255; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + /// + /// See + /// documentation for additional information. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Background pixel color. + /// + /// + /// The property sets background (none object) color to look for. + /// + /// Default value is set to 0 - black. + /// + public byte Background + { + get { return bg; } + set { bg = value; } + } + + /// + /// Foreground pixel color. + /// + /// + /// The property sets objects' (none background) color to look for. + /// + /// Default value is set to 255 - white. + /// + public byte Foreground + { + get { return fg; } + set { fg = value; } + } + + /// + /// Initializes a new instance of the class. + /// + public SimpleSkeletonization() + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Background pixel color. + /// Foreground pixel color. + /// + public SimpleSkeletonization(byte bg, byte fg) + : this() + { + this.bg = bg; + this.fg = fg; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect) + { + // processing start and stop X,Y positions + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + + int srcStride = sourceData.Stride; + int dstStride = destinationData.Stride; + int srcOffset = srcStride - rect.Width; + + int start; + + // do the job + byte* src0 = (byte*)sourceData.ImageData.ToPointer(); + byte* dst0 = (byte*)destinationData.ImageData.ToPointer(); + byte* src = src0; + byte* dst = dst0; + + // horizontal pass + + // allign pointers to the first pixel to process + src += (startY * srcStride + startX); + dst += (startY * dstStride); + + // for each line + for (int y = startY; y < stopY; y++) + { + // make destination image filled with background color + AForge.SystemTools.SetUnmanagedMemory(dst + startX, bg, stopX - startX); + + start = -1; + // for each pixel + for (int x = startX; x < stopX; x++, src++) + { + // looking for foreground pixel + if (start == -1) + { + if (*src == fg) + start = x; + continue; + } + + // looking for non foreground pixel + if (*src != fg) + { + dst[start + ((x - start) >> 1)] = (byte)fg; + start = -1; + } + } + if (start != -1) + { + dst[start + ((stopX - start) >> 1)] = (byte)fg; + } + src += srcOffset; + dst += dstStride; + } + + // vertical pass + + // allign pointer to the first line to process + src0 += (startY * srcStride); + + // for each column + for (int x = startX; x < stopX; x++) + { + src = src0 + x; + dst = dst0 + x; + + start = -1; + // for each row + for (int y = startY; y < stopY; y++, src += srcStride) + { + // looking for foreground pixel + if (start == -1) + { + if (*src == fg) + start = y; + continue; + } + + // looking for non foreground pixel + if (*src != fg) + { + dst[dstStride * (start + ((y - start) >> 1))] = (byte)fg; + start = -1; + } + } + if (start != -1) + { + dst[dstStride * (start + ((stopY - start) >> 1))] = (byte)fg; + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Other/TexturedFilter.cs b/Sources/Accord.Imaging/AForge/Filters/Other/TexturedFilter.cs new file mode 100644 index 0000000000..e09905efe --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Other/TexturedFilter.cs @@ -0,0 +1,450 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + using AForge.Imaging.Textures; + + /// + /// Textured filter - filter an image using texture. + /// + /// + /// The filter is similar to filter in its + /// nature, but instead of working with source image and overly, it uses provided + /// filters to create images to merge (see and + /// properties). In addition, it uses a bit more complex formula for calculation + /// of destination pixel's value, which gives greater amount of flexibility:
+ /// dst = * ( src1 * textureValue + src2 * ( 1.0 - textureValue ) ) + * src2, + /// where src1 is value of pixel from the image produced by , + /// src2 is value of pixel from the image produced by , + /// dst is value of pixel in a destination image and textureValue is corresponding value + /// from provided texture (see or ).
+ /// + /// It is possible to set to . In this case + /// original source image will be used instead of result produced by the second filter. + /// + /// The filter 24 bpp color images for processing. + /// + /// Sample usage #1: + /// + /// // create filter + /// TexturedFilter filter = new TexturedFilter( new CloudsTexture( ), + /// new HueModifier( 50 ) ); + /// // apply the filter + /// Bitmap newImage = filter.Apply( image ); + /// + /// + /// Sample usage #2: + /// + /// // create filter + /// TexturedFilter filter = new TexturedFilter( new CloudsTexture( ), + /// new GrayscaleBT709( ), new Sepia( ) ); + /// // apply the filter + /// Bitmap newImage = filter.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image #1: + /// + /// Result image #2: + /// + ///
+ /// + public class TexturedFilter : BaseFilter + { + // texture generator + private ITextureGenerator textureGenerator; + // generated texture + private float[,] texture = null; + // two filters + private IFilter filter1 = null; + private IFilter filter2 = null; + + // filtering factor + private double filterLevel = 1.0; + // preservation factor + private double preserveLevel = 0.0; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + /// + /// See for more information. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Filter level value, [0, 1]. + /// + /// + /// Filtering factor determines portion of the destionation image, which is formed + /// as a result of merging source images using specified texture. + /// + /// Default value is set to 1.0. + /// + /// See class description for more details. + /// + /// + public double FilterLevel + { + get { return filterLevel; } + set { filterLevel = Math.Max(0.0, Math.Min(1.0, value)); } + } + + /// + /// Preserve level value + /// + /// + /// Preserving factor determines portion taken from the image produced + /// by (or from original source) without applying textured + /// merge to it. + /// + /// Default value is set to 0.0. + /// + /// See class description for more details. + /// + /// + public double PreserveLevel + { + get { return preserveLevel; } + set { preserveLevel = Math.Max(0.0, Math.Min(1.0, value)); } + } + + /// + /// Generated texture. + /// + /// + /// Two dimensional array of texture intensities. + /// + /// Size of the provided texture should be the same as size of images, which will + /// be passed to the filter. + /// + /// The property has priority over this property - if + /// generator is specified than the static generated texture is not used. + /// + /// + public float[,] Texture + { + get { return texture; } + set { texture = value; } + } + + /// + /// Texture generator. + /// + /// + /// Generator used to generate texture. + /// + /// The property has priority over the property. + /// + /// + public ITextureGenerator TextureGenerator + { + get { return textureGenerator; } + set { textureGenerator = value; } + } + + /// + /// First filter. + /// + /// + /// Filter, which is used to produce first image for the merge. The filter + /// needs to implement interface, so it could be possible + /// to get information about the filter. The filter must be able to process color 24 bpp + /// images and produce color 24 bpp or grayscale 8 bppp images as result. + /// + /// + /// The specified filter does not support 24 bpp color images. + /// The specified filter does not produce image of supported format. + /// The specified filter does not implement IFilterInformation interface. + /// + public IFilter Filter1 + { + get { return filter1; } + set + { + var info = value as IFilterInformation; + + if (info == null) + throw new ArgumentException("The specified filter does not implement IFilterInformation interface."); + + if (!info.FormatTranslations.ContainsKey(PixelFormat.Format24bppRgb)) + throw new UnsupportedImageFormatException("The specified filter does not support 24 bpp color images."); + + if ((info.FormatTranslations[PixelFormat.Format24bppRgb] != PixelFormat.Format24bppRgb) && + (info.FormatTranslations[PixelFormat.Format24bppRgb] != PixelFormat.Format8bppIndexed)) + throw new UnsupportedImageFormatException("The specified filter does not produce image of supported format."); + + filter1 = value; + } + } + + /// + /// Second filter + /// + /// + /// Filter, which is used to produce second image for the merge. The filter + /// needs to implement interface, so it could be possible + /// to get information about the filter. The filter must be able to process color 24 bpp + /// images and produce color 24 bpp or grayscale 8 bppp images as result. + /// + /// The filter may be set to . In this case original source image + /// is used as a second image for the merge. + /// + /// + /// The specified filter does not support 24 bpp color images. + /// The specified filter does not produce image of supported format. + /// The specified filter does not implement IFilterInformation interface. + /// + public IFilter Filter2 + { + get { return filter2; } + + set + { + IFilterInformation info = value as IFilterInformation; + + if (info == null) + throw new ArgumentException("The specified filter does not implement IFilterInformation interface."); + + if (!info.FormatTranslations.ContainsKey(PixelFormat.Format24bppRgb)) + throw new UnsupportedImageFormatException("The specified filter does not support 24 bpp color images."); + + if ((info.FormatTranslations[PixelFormat.Format24bppRgb] != PixelFormat.Format24bppRgb) && + (info.FormatTranslations[PixelFormat.Format24bppRgb] != PixelFormat.Format8bppIndexed)) + throw new UnsupportedImageFormatException("The specified filter does not produce image of supported format."); + + filter2 = value; + } + } + + // Private constructor to + private TexturedFilter() + { + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Generated texture. + /// First filter. + /// + public TexturedFilter(float[,] texture, IFilter filter1) + : this() + { + this.texture = texture; + this.filter1 = filter1; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Generated texture. + /// First filter. + /// Second filter. + /// + public TexturedFilter(float[,] texture, IFilter filter1, IFilter filter2) + : this() + { + this.texture = texture; + this.filter1 = filter1; + this.filter2 = filter2; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Texture generator. + /// First filter. + /// + public TexturedFilter(ITextureGenerator generator, IFilter filter1) + : this() + { + this.textureGenerator = generator; + this.filter1 = filter1; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Texture generator. + /// First filter. + /// Second filter. + /// + public TexturedFilter(ITextureGenerator generator, IFilter filter1, IFilter filter2) + : this() + { + this.textureGenerator = generator; + this.filter1 = filter1; + this.filter2 = filter2; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + /// Texture size does not match image size. + /// Filters should not change image dimension. + /// + protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData) + { + // get source image dimension + int width = sourceData.Width; + int height = sourceData.Height; + + // if generator was specified, then generate a texture + // otherwise use provided texture + if (textureGenerator != null) + { + texture = textureGenerator.Generate(width, height); + } + else + { + // check existing texture + if ((texture.GetLength(0) != height) || (texture.GetLength(1) != width)) + { + // sorry, but source image must have the same dimension as texture + throw new InvalidImagePropertiesException("Texture size does not match image size."); + } + } + + // apply first filter + UnmanagedImage filteredImage1 = filter1.Apply(sourceData); + + // check size of the result image + if ((width != filteredImage1.Width) || (height != filteredImage1.Height)) + { + filteredImage1.Dispose(); + throw new InvalidOperationException("Filters should not change image dimension."); + } + + // convert 1st image to RGB if required + if (filteredImage1.PixelFormat == PixelFormat.Format8bppIndexed) + { + GrayscaleToRGB coloringFilter = new GrayscaleToRGB(); + UnmanagedImage temp = coloringFilter.Apply(filteredImage1); + filteredImage1.Dispose(); + filteredImage1 = temp; + } + + UnmanagedImage filteredImage2 = null; + // apply second filter, if it was specified + if (filter2 != null) + { + filteredImage2 = filter2.Apply(sourceData); + // check size of the result image + if ((width != filteredImage2.Width) || (height != filteredImage2.Height)) + { + filteredImage1.Dispose(); + filteredImage2.Dispose(); + // we are not handling such situations yet + throw new InvalidOperationException("Filters should not change image dimension."); + } + + // convert 2nd image to RGB if required + if (filteredImage2.PixelFormat == PixelFormat.Format8bppIndexed) + { + GrayscaleToRGB coloringFilter = new GrayscaleToRGB(); + UnmanagedImage temp = coloringFilter.Apply(filteredImage2); + filteredImage2.Dispose(); + filteredImage2 = temp; + } + } + + // use source image as a second image, if second filter is not set + if (filteredImage2 == null) + { + filteredImage2 = sourceData; + } + + // do the job + unsafe + { + byte* dst = (byte*)destinationData.ImageData.ToPointer(); + byte* src1 = (byte*)filteredImage1.ImageData.ToPointer(); + byte* src2 = (byte*)filteredImage2.ImageData.ToPointer(); + + int dstOffset = destinationData.Stride - 3 * width; + int src1Offset = filteredImage1.Stride - 3 * width; + int src2Offset = filteredImage2.Stride - 3 * width; + + if (preserveLevel != 0.0) + { + // for each line + for (int y = 0; y < height; y++) + { + // for each pixel + for (int x = 0; x < width; x++) + { + double t1 = texture[y, x]; + double t2 = 1 - t1; + + for (int i = 0; i < 3; i++, src1++, src2++, dst++) + { + *dst = (byte)Math.Min(255.0f, + filterLevel * (t1 * (*src1) + t2 * (*src2)) + + preserveLevel * (*src2)); + } + } + src1 += src1Offset; + src2 += src2Offset; + dst += dstOffset; + } + } + else + { + // for each line + for (int y = 0; y < height; y++) + { + // for each pixel + for (int x = 0; x < width; x++) + { + double t1 = texture[y, x]; + double t2 = 1 - t1; + + for (int i = 0; i < 3; i++, src1++, src2++, dst++) + { + *dst = (byte)Math.Min(255.0f, t1 * *src1 + t2 * *src2); + } + } + src1 += src1Offset; + src2 += src2Offset; + dst += dstOffset; + } + } + } + + // dispose temp images + filteredImage1.Dispose(); + if (filteredImage2 != sourceData) + { + filteredImage2.Dispose(); + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Other/TexturedMerge.cs b/Sources/Accord.Imaging/AForge/Filters/Other/TexturedMerge.cs new file mode 100644 index 0000000000..db769a41f --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Other/TexturedMerge.cs @@ -0,0 +1,210 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Merge two images using factors from texture. + /// + /// + /// The filter is similar to filter in its idea, but + /// instead of using single value for balancing amount of source's and overlay's image + /// values (see ), the filter uses texture, which determines + /// the amount to take from source image and overlay image. + /// + /// The filter uses specified texture to adjust values using the next formula:
+ /// dst = src * textureValue + ovr * ( 1.0 - textureValue ),
+ /// where src is value of pixel in a source image, ovr is value of pixel in + /// overlay image, dst is value of pixel in a destination image and + /// textureValue is corresponding value from provided texture (see or + /// ).
+ /// + /// The filter accepts 8 bpp grayscale and 24 bpp color images for processing. + /// + /// Sample usage #1: + /// + /// // create filter + /// TexturedMerge filter = new TexturedMerge( new TextileTexture( ) ); + /// // create an overlay image to merge with + /// filter.OverlayImage = new Bitmap( image.Width, image.Height, + /// PixelFormat.Format24bppRgb ); + /// // fill the overlay image with solid color + /// PointedColorFloodFill fillFilter = new PointedColorFloodFill( Color.DarkKhaki ); + /// fillFilter.ApplyInPlace( filter.OverlayImage ); + /// // apply the merge filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Sample usage #2: + /// + /// // create filter + /// TexturedMerge filter = new TexturedMerge( new CloudsTexture( ) ); + /// // create 2 images with modified Hue + /// HueModifier hm1 = new HueModifier( 50 ); + /// HueModifier hm2 = new HueModifier( 200 ); + /// filter.OverlayImage = hm2.Apply( image ); + /// hm1.ApplyInPlace( image ); + /// // apply the merge filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image #1: + /// + /// Result image #2: + /// + ///
+ /// + public class TexturedMerge : BaseInPlaceFilter2 + { + // texture generator + private AForge.Imaging.Textures.ITextureGenerator textureGenerator; + // generated texture + private float[,] texture = null; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + /// + /// See for more information. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Generated texture. + /// + /// + /// Two dimensional array of texture intensities. + /// + /// In the case if image passed to the filter is smaller or + /// larger than the specified texture, than image's region is processed, which equals to the + /// minimum overlapping area. + /// + /// The property has priority over this property - if + /// generator is specified than the static generated texture is not used. + /// + /// + public float[,] Texture + { + get { return texture; } + set { texture = value; } + } + + /// + /// Texture generator. + /// + /// + /// Generator used to generate texture. + /// + /// The property has priority over the property. + /// + /// + public AForge.Imaging.Textures.ITextureGenerator TextureGenerator + { + get { return textureGenerator; } + set { textureGenerator = value; } + } + + // Private constructor to do common initialization + private TexturedMerge( ) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Generated texture. + /// + public TexturedMerge( float[,] texture ) : this( ) + { + this.texture = texture; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Texture generator. + /// + public TexturedMerge( AForge.Imaging.Textures.ITextureGenerator generator ) : this( ) + { + this.textureGenerator = generator; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Overlay image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, UnmanagedImage overlay ) + { + // get image dimension + int width = image.Width; + int height = image.Height; + + // width and height to process + int widthToProcess = width; + int heightToProcess = height; + + // if generator was specified, then generate a texture + // otherwise use provided texture + if ( textureGenerator != null ) + { + texture = textureGenerator.Generate( width, height ); + } + else + { + widthToProcess = Math.Min( width, texture.GetLength( 1 ) ); + heightToProcess = Math.Min( height, texture.GetLength( 0 ) ); + } + + int pixelSize = Image.GetPixelFormatSize( image.PixelFormat ) / 8; + int srcOffset = image.Stride - widthToProcess * pixelSize; + int ovrOffset = overlay.Stride - widthToProcess * pixelSize; + + // do the job + byte* ptr = (byte*) image.ImageData.ToPointer( ); + byte* ovr = (byte*) overlay.ImageData.ToPointer( ); + + // for each line + for ( int y = 0; y < heightToProcess; y++ ) + { + // for each pixel + for ( int x = 0; x < widthToProcess; x++ ) + { + double t1 = texture[y, x]; + double t2 = 1 - t1; + + for ( int i = 0; i < pixelSize; i++, ptr++, ovr++ ) + { + *ptr = (byte) Math.Min( 255.0f, *ptr * t1 + *ovr * t2 ); + } + } + ptr += srcOffset; + ovr += ovrOffset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Other/Texturer.cs b/Sources/Accord.Imaging/AForge/Filters/Other/Texturer.cs new file mode 100644 index 0000000000..eada66a4c --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Other/Texturer.cs @@ -0,0 +1,262 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Texturer filter. + /// + /// + /// Adjust pixels color values using factors from the given texture. In conjunction with different type + /// of texture generators, the filter may produce different type of interesting effects. + /// + /// The filter uses specified texture to adjust values using the next formula:
+ /// dst = src * + src * * textureValue,
+ /// where src is value of pixel in a source image, dst is value of pixel in a destination image and + /// textureValue is corresponding value from provided texture (see or + /// ). Using and values it is possible + /// to control the portion of source data affected by texture. + ///
+ /// + /// In most cases the and properties are set in such + /// way, that + = 1. But there is no limitations actually + /// for those values, so their sum may be as greater, as lower than 1 in order create different type of + /// effects. + /// + /// The filter accepts 8 bpp grayscale and 24 bpp color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// Texturer filter = new Texturer( new TextileTexture( ), 0.3, 0.7 ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + ///
+ /// + public class Texturer : BaseInPlacePartialFilter + { + // texture generator + private AForge.Imaging.Textures.ITextureGenerator textureGenerator; + // generated texture + private float[,] texture = null; + + // filtering factor + private double filterLevel = 0.5; + // preservation factor + private double preserveLevel = 0.5; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + /// + /// See for more information. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Filter level value. + /// + /// + /// Filtering factor determines image fraction to filter - to multiply + /// by values from the provided texture. + /// + /// Default value is set to 0.5. + /// + /// See class description for more details. + /// + /// + public double FilterLevel + { + get { return filterLevel; } + set { filterLevel = Math.Max( 0.0, Math.Min( 1.0, value ) ); } + } + + /// + /// Preserve level value. + /// + /// + /// Preserving factor determines image fraction to keep from filtering. + /// + /// Default value is set to 0.5. + /// + /// See class description for more details. + /// + /// + public double PreserveLevel + { + get { return preserveLevel; } + set { preserveLevel = Math.Max( 0.0, Math.Min( 1.0, value ) ); } + } + + /// + /// Generated texture. + /// + /// + /// Two dimensional array of texture intensities. + /// + /// In the case if image passed to the filter is smaller or + /// larger than the specified texture, than image's region is processed, which equals to the + /// minimum overlapping area. + /// + /// The property has priority over this property - if + /// generator is specified than the static generated texture is not used. + /// + /// + public float[,] Texture + { + get { return texture; } + set { texture = value; } + } + + /// + /// Texture generator. + /// + /// + /// Generator used to generate texture. + /// + /// The property has priority over the property. + /// + /// + public AForge.Imaging.Textures.ITextureGenerator TextureGenerator + { + get { return textureGenerator; } + set { textureGenerator = value; } + } + + // Private constructor to do common initialization + private Texturer( ) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Generated texture. + /// + public Texturer( float[,] texture ) : this( ) + { + this.texture = texture; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Generated texture. + /// Filter level value (see property). + /// Preserve level value (see property). + /// + public Texturer( float[,] texture, double filterLevel, double preserveLevel ) : this( ) + { + this.texture = texture; + this.filterLevel = filterLevel; + this.preserveLevel = preserveLevel; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Texture generator. + /// + public Texturer( AForge.Imaging.Textures.ITextureGenerator generator ) : this( ) + { + this.textureGenerator = generator; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Texture generator. + /// Filter level value (see property). + /// Preserve level value (see property). + /// + public Texturer( AForge.Imaging.Textures.ITextureGenerator generator, double filterLevel, double preserveLevel ) + : this( ) + { + this.textureGenerator = generator; + this.filterLevel = filterLevel; + this.preserveLevel = preserveLevel; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + int pixelSize = Image.GetPixelFormatSize( image.PixelFormat ) / 8; + + // processing width and height + int width = rect.Width; + int height = rect.Height; + + // processing region's dimension + int widthToProcess = width; + int heightToProcess = height; + + // if generator was specified, then generate a texture + // otherwise use provided texture + if ( textureGenerator != null ) + { + texture = textureGenerator.Generate( width, height ); + } + else + { + widthToProcess = Math.Min( width, texture.GetLength( 1 ) ); + heightToProcess = Math.Min( height, texture.GetLength( 0 ) ); + } + + int offset = image.Stride - widthToProcess * pixelSize; + + // do the job + byte* ptr = (byte*) image.ImageData.ToPointer( ); + + // allign pointer to the first pixel to process + ptr += ( rect.Top * image.Stride + rect.Left * pixelSize ); + + // texture + for ( int y = 0; y < heightToProcess; y++ ) + { + for ( int x = 0; x < widthToProcess; x++ ) + { + double t = texture[y, x]; + // process each pixel + for ( int i = 0; i < pixelSize; i++, ptr++ ) + { + *ptr = (byte) Math.Min( 255.0f, ( preserveLevel * ( *ptr ) ) + ( filterLevel * ( *ptr ) ) * t ); + } + } + ptr += offset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Other/VerticalRunLengthSmoothing.cs b/Sources/Accord.Imaging/AForge/Filters/Other/VerticalRunLengthSmoothing.cs new file mode 100644 index 0000000000..0112508ff --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Other/VerticalRunLengthSmoothing.cs @@ -0,0 +1,185 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Vertical run length smoothing algorithm. + /// + /// + /// The class implements vertical run length smoothing algorithm, which + /// is described in: K.Y. Wong, R.G. Casey and F.M. Wahl, "Document analysis system," + /// IBM J. Res. Devel., Vol. 26, NO. 6,111). 647-656, 1982. + /// + /// Unlike the original description of this algorithm, this implementation must be applied + /// to inverted binary images containing document, i.e. white text on black background. So this + /// implementation fills vertical black gaps between white pixels. + /// + /// This algorithm is usually used together with , + /// and then further analysis of white blobs. + /// + /// The filter accepts 8 bpp grayscale images, which are supposed to be binary inverted documents. + /// + /// Sample usage: + /// + /// // create filter + /// VerticalRunLengthSmoothing vrls = new VerticalRunLengthSmoothing( 32 ); + /// // apply the filter + /// vrls.ApplyInPlace( image ); + /// + /// + /// Source image: + /// + /// Result image: + /// + /// + /// + /// + /// + public class VerticalRunLengthSmoothing : BaseInPlacePartialFilter + { + private int maxGapSize = 10; + private bool processGapsWithImageBorders = false; + + /// + /// Maximum gap size to fill (in pixels). + /// + /// + /// The property specifies maximum vertical gap between white pixels to fill. + /// If number of black pixels between some white pixels is bigger than this value, then those + /// black pixels are left as is; otherwise the gap is filled with white pixels. + /// + /// + /// Default value is set to 10. Minimum value is 1. Maximum value is 1000. + /// + public int MaxGapSize + { + get { return maxGapSize; } + set { maxGapSize = Math.Max( 1, Math.Min( 1000, value ) ); } + } + + /// + /// Process gaps between objects and image borders or not. + /// + /// + /// The property sets if gaps between image borders and objects must be treated as + /// gaps between objects and also filled. + /// + /// Default value is set to . + /// + /// + public bool ProcessGapsWithImageBorders + { + get { return processGapsWithImageBorders; } + set { processGapsWithImageBorders = value; } + } + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + /// + /// See + /// documentation for additional information. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public VerticalRunLengthSmoothing( ) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Maximum gap size to fill (see ). + /// + public VerticalRunLengthSmoothing( int maxGapSize ) + : this( ) + { + MaxGapSize = maxGapSize; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + int startX = rect.Left; + int stopX = startX + rect.Width; + + int height = rect.Height; + + int stride = image.Stride; + + byte* basePtr = (byte*) image.ImageData.ToPointer( ) + rect.Top * stride + startX; + + for ( int x = startX; x < stopX; x++ ) + { + byte* ptr = basePtr; + byte* columnStartPtr = ptr; + byte* columnEndPtr = ptr + stride * height; + + // fill gaps between white pixels + while ( ptr < columnEndPtr ) + { + byte* gapStart = ptr; + int gapSize = 0; + + // look for non black pixel + while ( ( ptr < columnEndPtr ) && ( *ptr == 0 ) ) + { + ptr += stride; + gapSize++; + } + + // fill the gap between white areas + if ( gapSize <= maxGapSize ) + { + if ( ( processGapsWithImageBorders ) || + ( ( gapStart != columnStartPtr ) && ( ptr != columnEndPtr ) ) ) + { + while ( gapStart < ptr ) + { + *gapStart = 255; + gapStart += stride; + } + } + } + + // skip all non black pixels + while ( ( ptr < columnEndPtr ) && ( *ptr != 0 ) ) + { + ptr += stride; + } + } + + basePtr++; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Other/WaterWave.cs b/Sources/Accord.Imaging/AForge/Filters/Other/WaterWave.cs new file mode 100644 index 0000000000..6cb91d9d9 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Other/WaterWave.cs @@ -0,0 +1,213 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2005-2010 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Simple water wave effect filter. + /// + /// + /// The image processing filter implements simple water wave effect. Using + /// properties of the class, it is possible to set number of vertical/horizontal waves, + /// as well as their amplitude. + /// + /// Bilinear interpolation is used to create smooth effect. + /// + /// The filter accepts 8 bpp grayscale images and 24/32 + /// color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// WaterWave filter = new WaterWave( ); + /// filter.HorizontalWavesCount = 10; + /// filter.HorizontalWavesAmplitude = 5; + /// filter.VerticalWavesCount = 3; + /// filter.VerticalWavesAmplitude = 15; + /// // apply the filter + /// Bitmap newImage = filter.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class WaterWave : BaseFilter + { + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + private int xWavesCount = 5; + private int yWavesCount = 5; + private int xWavesAmplitude = 10; + private int yWavesAmplitude = 10; + + /// + /// Number of horizontal waves, [1, 10000]. + /// + /// + /// Default value is set to 5. + /// + public int HorizontalWavesCount + { + get { return xWavesCount; } + set { xWavesCount = Math.Max(1, Math.Min(10000, value)); } + } + + /// + /// Number of vertical waves, [1, 10000]. + /// + /// + /// Default value is set to 5. + /// + public int VerticalWavesCount + { + get { return yWavesCount; } + set { yWavesCount = Math.Max(1, Math.Min(10000, value)); } + } + + /// + /// Amplitude of horizontal waves measured in pixels, [0, 10000]. + /// + /// + /// Default value is set to 10. + /// + public int HorizontalWavesAmplitude + { + get { return xWavesAmplitude; } + set { xWavesAmplitude = Math.Max(0, Math.Min(10000, value)); } + } + + /// + /// Amplitude of vertical waves measured in pixels, [0, 10000]. + /// + /// + /// Default value is set to 10. + /// + public int VerticalWavesAmplitude + { + get { return yWavesAmplitude; } + set { yWavesAmplitude = Math.Max(0, Math.Min(10000, value)); } + } + + /// + /// Format translations dictionary. + /// + /// + /// See + /// documentation for additional information. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + + /// + /// Initializes a new instance of the class. + /// + public WaterWave() + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData) + { + int pixelSize = Image.GetPixelFormatSize(sourceData.PixelFormat) / 8; + + // processing start and stop X,Y positions + int width = sourceData.Width; + int height = sourceData.Height; + + int srcStride = sourceData.Stride; + int dstStride = destinationData.Stride; + int dstOffset = dstStride - width * pixelSize; + + // coordinates of source points + double ox, oy, dx1, dy1, dx2, dy2; + int ox1, oy1, ox2, oy2; + + // width and height decreased by 1 + int ymax = height - 1; + int xmax = width - 1; + + byte* src = (byte*)sourceData.ImageData.ToPointer(); + byte* dst = (byte*)destinationData.ImageData.ToPointer(); + byte* p1, p2, p3, p4; + + double xFactor = 2 * Math.PI * xWavesCount / width; + double yFactor = 2 * Math.PI * yWavesCount / height; + + // for each line + for (int y = 0; y < height; y++) + { + double yPart = Math.Sin(yFactor * y) * yWavesAmplitude; + + // for each pixel + for (int x = 0; x < width; x++) + { + ox = x + yPart; + oy = y + Math.Cos(xFactor * x) * xWavesAmplitude; + + // check if the source pixel is inside of image + if ((ox >= 0) && (oy >= 0) && (ox < width) && (oy < height)) + { + // perform bilinear interpolation + oy1 = (int)oy; + oy2 = (oy1 == ymax) ? oy1 : oy1 + 1; + dy1 = oy - (double)oy1; + dy2 = 1.0 - dy1; + + ox1 = (int)ox; + ox2 = (ox1 == xmax) ? ox1 : ox1 + 1; + dx1 = ox - (double)ox1; + dx2 = 1.0 - dx1; + + p1 = src + oy1 * srcStride + ox1 * pixelSize; + p2 = src + oy1 * srcStride + ox2 * pixelSize; + p3 = src + oy2 * srcStride + ox1 * pixelSize; + p4 = src + oy2 * srcStride + ox2 * pixelSize; + + for (int i = 0; i < pixelSize; i++, dst++, p1++, p2++, p3++, p4++) + { + *dst = (byte)( + dy2 * (dx2 * (*p1) + dx1 * (*p2)) + + dy1 * (dx2 * (*p3) + dx1 * (*p4))); + } + } + else + { + for (int i = 0; i < pixelSize; i++, dst++) + { + *dst = 0; + } + } + } + dst += dstOffset; + } + } + } +} + diff --git a/Sources/Accord.Imaging/AForge/Filters/Smooting/AdaptiveSmooth.cs b/Sources/Accord.Imaging/AForge/Filters/Smooting/AdaptiveSmooth.cs new file mode 100644 index 0000000000..581645986 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Smooting/AdaptiveSmooth.cs @@ -0,0 +1,250 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// +// Found description in +// "An Edge Detection Technique Using the Facet +// Model and Parameterized Relaxation Labeling" +// by Ioannis Matalas, Student Member, IEEE, Ralph Benjamin, and Richard Kitney +// +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Adaptive Smoothing - noise removal with edges preserving. + /// + /// + /// The filter is aimed to perform image smoothing, but keeping sharp edges. + /// This makes it applicable to additive noise removal and smoothing objects' interiors, but + /// not applicable for spikes (salt and pepper noise) removal. + /// + /// The next calculations are done for each pixel: + /// + /// weights are calculate for 9 pixels - pixel itself and 8 neighbors: + /// + /// w(x, y) = exp( -1 * (Gx^2 + Gy^2) / (2 * factor^2) ) + /// Gx(x, y) = (I(x + 1, y) - I(x - 1, y)) / 2 + /// Gy(x, y) = (I(x, y + 1) - I(x, y - 1)) / 2 + /// , + /// where factor is a configurable value determining smoothing's quality. + /// sum of 9 weights is calclated (weightTotal); + /// sum of 9 weighted pixel values is calculatd (total); + /// destination pixel is calculated as total / weightTotal. + /// + /// + /// Description of the filter was found in "An Edge Detection Technique Using + /// the Facet Model and Parameterized Relaxation Labeling" by Ioannis Matalas, Student Member, + /// IEEE, Ralph Benjamin, and Richard Kitney. + /// + /// The filter accepts 8 bpp grayscale images and 24 bpp + /// color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// AdaptiveSmoothing filter = new AdaptiveSmoothing( ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class AdaptiveSmoothing : BaseUsingCopyPartialFilter + { + private double factor = 3.0; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Factor value. + /// + /// + /// Factor determining smoothing quality (see + /// documentation). + /// + /// Default value is set to 3. + /// + /// + public double Factor + { + get { return factor; } + set { factor = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public AdaptiveSmoothing() + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Factor value. + /// + public AdaptiveSmoothing(double factor) + : this() + { + this.factor = factor; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect) + { + int pixelSize = Image.GetPixelFormatSize(sourceData.PixelFormat) / 8; + int pixelSize2 = pixelSize * 2; + + // processing start and stop X,Y positions + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + + int startXP2 = startX + 2; + int startYP2 = startY + 2; + int stopXM2 = stopX - 2; + int stopYM2 = stopY - 2; + + int srcStride = sourceData.Stride; + int dstStride = destinationData.Stride; + int srcOffset = srcStride - rect.Width * pixelSize; + int dstOffset = dstStride - rect.Width * pixelSize; + + // gradient and weights + double gx, gy, weight, weightTotal, total; + + // precalculated factor value + double f = -8 * factor * factor; + + // do the job + byte* src = (byte*)sourceData.ImageData.ToPointer() + srcStride * 2; + byte* dst = (byte*)destinationData.ImageData.ToPointer() + dstStride * 2; + + // allign pointers to the first pixel to process + src += (startY * srcStride + startX * pixelSize); + dst += (startY * dstStride + startX * pixelSize); + + for (int y = startYP2; y < stopYM2; y++) + { + src += pixelSize2; + dst += pixelSize2; + + for (int x = startXP2; x < stopXM2; x++) + { + for (int i = 0; i < pixelSize; i++, src++, dst++) + { + weightTotal = 0; + total = 0; + + // original formulas for weight calculation: + // w(x, y) = exp( -1 * (Gx^2 + Gy^2) / (2 * factor^2) ) + // Gx(x, y) = (I(x + 1, y) - I(x - 1, y)) / 2 + // Gy(x, y) = (I(x, y + 1) - I(x, y - 1)) / 2 + // + // here is a little bit optimized version + + // x - 1, y - 1 + gx = src[-srcStride] - src[-pixelSize2 - srcStride]; + gy = src[-pixelSize] - src[-pixelSize - 2 * srcStride]; + weight = System.Math.Exp((gx * gx + gy * gy) / f); + total += weight * src[-pixelSize - srcStride]; + weightTotal += weight; + + // x, y - 1 + gx = src[pixelSize - srcStride] - src[-pixelSize - srcStride]; + gy = *src - src[-2 * srcStride]; + weight = System.Math.Exp((gx * gx + gy * gy) / f); + total += weight * src[-srcStride]; + weightTotal += weight; + + // x + 1, y - 1 + gx = src[pixelSize2 - srcStride] - src[-srcStride]; + gy = src[pixelSize] - src[pixelSize - 2 * srcStride]; + weight = System.Math.Exp((gx * gx + gy * gy) / f); + total += weight * src[pixelSize - srcStride]; + weightTotal += weight; + + // x - 1, y + gx = *src - src[-pixelSize2]; + gy = src[-pixelSize + srcStride] - src[-pixelSize - srcStride]; + weight = System.Math.Exp((gx * gx + gy * gy) / f); + total += weight * src[-pixelSize]; + weightTotal += weight; + + // x, y + gx = src[pixelSize] - src[-pixelSize]; + gy = src[srcStride] - src[-srcStride]; + weight = System.Math.Exp((gx * gx + gy * gy) / f); + total += weight * (*src); + weightTotal += weight; + + // x + 1, y + gx = src[pixelSize2] - *src; + gy = src[pixelSize + srcStride] - src[pixelSize - srcStride]; + weight = System.Math.Exp((gx * gx + gy * gy) / f); + total += weight * src[pixelSize]; + weightTotal += weight; + + // x - 1, y + 1 + gx = src[srcStride] - src[-pixelSize2 + srcStride]; + gy = src[-pixelSize + 2 * srcStride] - src[-pixelSize]; + weight = System.Math.Exp((gx * gx + gy * gy) / f); + total += weight * src[-pixelSize + srcStride]; + weightTotal += weight; + + // x, y + 1 + gx = src[pixelSize + srcStride] - src[-pixelSize + srcStride]; + gy = src[2 * srcStride] - *src; + weight = System.Math.Exp((gx * gx + gy * gy) / f); + total += weight * src[srcStride]; + weightTotal += weight; + + // x + 1, y + 1 + gx = src[pixelSize2 + srcStride] - src[srcStride]; + gy = src[pixelSize + 2 * srcStride] - src[pixelSize]; + weight = System.Math.Exp((gx * gx + gy * gy) / f); + total += weight * src[pixelSize + srcStride]; + weightTotal += weight; + + // save destination value + *dst = (weightTotal == 0.0) ? *src : (byte)System.Math.Min(total / weightTotal, 255.0); + } + } + src += srcOffset + pixelSize2; + dst += dstOffset + pixelSize2; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Smooting/BilateralSmoothing.cs b/Sources/Accord.Imaging/AForge/Filters/Smooting/BilateralSmoothing.cs new file mode 100644 index 0000000000..5dbe01def --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Smooting/BilateralSmoothing.cs @@ -0,0 +1,857 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2012 +// contacts@aforgenet.com +// +// Original implementation by Maxim Saplin, 2012 +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Bilateral filter implementation - edge preserving smoothing and noise reduction that uses chromatic and spatial factors. + /// + /// + /// + /// Bilateral filter conducts "selective" Gaussian smoothing of areas of same color (domains) which removes noise and contrast artifacts + /// while preserving sharp edges. + /// + /// Two major parameters and define the result of the filter. + /// By changing these parameters you may achieve either only noise reduction with little change to the + /// image or get nice looking effect to the entire image. + /// + /// Although the filter can use parallel processing large values + /// (greater than 25) on high resolution images may decrease speed of processing. Also on high + /// resolution images small values (less than 9) may not provide noticeable + /// results. + /// + /// More details on the algorithm can be found by following this + /// link. + /// + /// The filter accepts 8 bpp grayscale images and 24/32 bpp color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// BilateralSmoothing filter = new BilateralSmoothing( ); + /// filter.KernelSize = 7; + /// filter.SpatialFactor = 10; + /// filter.ColorFactor = 60; + /// filter.ColorPower = 0.5; + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class BilateralSmoothing : BaseUsingCopyPartialFilter + { + private Dictionary formatTranslations = new Dictionary(); + + private const int maxKernelSize = 255; + private const int colorsCount = 256; + + private int kernelSize = 9; + private double spatialFactor = 10; + private double spatialPower = 2; + private double colorFactor = 50; + private double colorPower = 2; + + private bool spatialPropertiesChanged = true; + private bool colorPropertiesChanged = true; + + private bool limitKernelSize = true; + private bool enableParallelProcessing = false; + + /// + /// Specifies if exception must be thrown in the case a large + /// kernel size is used which may lead + /// to significant performance issues. + /// + /// + /// + /// Default value is set to . + /// + /// + public bool LimitKernelSize + { + get { return limitKernelSize; } + set { limitKernelSize = value; } + } + + /// + /// Enable or not parallel processing on multi-core CPUs. + /// + /// + /// If the property is set to , then this image processing + /// routine will run in parallel on the systems with multiple core/CPUs. The + /// is used to make it parallel. + /// + /// Default value is set to . + /// + /// + public bool EnableParallelProcessing + { + get { return enableParallelProcessing; } + set { enableParallelProcessing = value; } + } + + /// + /// Size of a square for limiting surrounding pixels that take part in calculations, [3, 255]. + /// + /// + /// The greater the value the more is the general power of the filter. Small values + /// (less than 9) on high resolution images (3000 pixels wide) do not give significant results. + /// Large values increase the number of calculations and degrade performance. + /// + /// The value of this property must be an odd integer in the [3, 255] range if + /// is set to or in the [3, 25] range + /// otherwise. + /// + /// Default value is set to 9. + /// + /// + /// The specified value is out of range (see + /// eception message for details). + /// The value of this must be an odd integer. + /// + public int KernelSize + { + get + { + return kernelSize; + } + set + { + if (value > maxKernelSize) + throw new ArgumentOutOfRangeException("value", "Maximum allowed value of KernelSize property is " + maxKernelSize.ToString()); + + if ((limitKernelSize) && (value > 25)) + throw new ArgumentOutOfRangeException("value", "KernerlSize is larger then 25. Time for applying is significant and may lead to application freezing. In order to use any KernelSize value set property 'LimitKernelSize' to false."); + + if (value < 3) + throw new ArgumentOutOfRangeException("value", "KernelSize must be greater than 3"); + + if (value % 2 == 0) + throw new ArgumentOutOfRangeException("value", "KernerlSize must be an odd integer."); + + kernelSize = value; + } + } + + /// + /// Determines smoothing power within a color domain (neighbor pixels of similar color), >= 1. + /// + /// + /// + /// Default value is set to 10. + /// + /// + public double SpatialFactor + { + get + { + return spatialFactor; + } + set + { + spatialFactor = Math.Max(1, value); + spatialPropertiesChanged = true; + } + } + + /// + /// Exponent power, used in Spatial function calculation, >= 1. + /// + /// + /// + /// Default value is set to 2. + /// + /// + public double SpatialPower + { + get + { + return spatialPower; + } + set + { + spatialPower = Math.Max(1, value); + spatialPropertiesChanged = true; + } + } + + /// + /// Determines the variance of color for a color domain, >= 1. + /// + /// + /// + /// Default value is set to 50. + /// + /// + public double ColorFactor + { + get + { + return colorFactor; + } + set + { + colorFactor = Math.Max(1, value); + colorPropertiesChanged = true; + } + } + + /// + /// Exponent power, used in Color function calculation, >= 1. + /// + /// + /// + /// Default value is set to 2. + /// + /// + public double ColorPower + { + get + { + return colorPower; + } + set + { + colorPower = Math.Max(1, value); + colorPropertiesChanged = true; + } + } + + /// + /// Format translations dictionary. + /// + /// + /// See + /// documentation for additional information. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public BilateralSmoothing() + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + } + + private double[,] spatialFunc; + private double[,] colorFunc; + + // For performance improvements Color and Spatial functions are recalculated prior to filter execution and put into 2 dimensional arrays + private void InitSpatialFunc() + { + if ((spatialFunc == null) || (spatialFunc.Length != kernelSize * kernelSize) || + (spatialPropertiesChanged)) + { + if ((spatialFunc == null) || (spatialFunc.Length != kernelSize * kernelSize)) + { + spatialFunc = new double[kernelSize, kernelSize]; + } + + int kernelRadius = kernelSize / 2; + + for (int i = 0; i < kernelSize; i++) + { + int ti = i - kernelRadius; + int ti2 = ti * ti; + + for (int k = 0; k < kernelSize; k++) + { + int tk = k - kernelRadius; + int tk2 = tk * tk; + + spatialFunc[i, k] = Math.Exp(-0.5 * Math.Pow(Math.Sqrt((ti2 + tk2) / spatialFactor), spatialPower)); + } + } + + spatialPropertiesChanged = false; + } + } + + // For performance improvements Color and Spatial functions are recalculated prior to filter execution and put into 2 dimensional arrays + private void InitColorFunc() + { + if ((colorFunc == null) || (colorPropertiesChanged)) + { + if (colorFunc == null) + { + colorFunc = new double[colorsCount, colorsCount]; + } + + for (int i = 0; i < colorsCount; i++) + { + for (int k = 0; k < colorsCount; k++) + { + colorFunc[i, k] = Math.Exp(-0.5 * (Math.Pow(Math.Abs(i - k) / colorFactor, colorPower))); + } + } + + colorPropertiesChanged = false; + } + } + + private void InitFilter() + { + InitSpatialFunc(); + InitColorFunc(); + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect) + { + int kernelHalf = kernelSize / 2; + + InitFilter(); + + if ((rect.Width <= kernelSize) || (rect.Height <= kernelSize)) + { + ProcessWithEdgeChecks(sourceData, destinationData, rect); + } + else + { + Rectangle safeArea = rect; + safeArea.Inflate(-kernelHalf, -kernelHalf); + + if ((Environment.ProcessorCount > 1) && (enableParallelProcessing)) + { + ProcessWithoutChecksParallel(sourceData, destinationData, safeArea); + } + else + { + ProcessWithoutChecks(sourceData, destinationData, safeArea); + } + + // top + ProcessWithEdgeChecks(sourceData, destinationData, + new Rectangle(rect.Left, rect.Top, rect.Width, kernelHalf)); + // bottom + ProcessWithEdgeChecks(sourceData, destinationData, + new Rectangle(rect.Left, rect.Bottom - kernelHalf, rect.Width, kernelHalf)); + // left + ProcessWithEdgeChecks(sourceData, destinationData, + new Rectangle(rect.Left, rect.Top + kernelHalf, kernelHalf, rect.Height - kernelHalf * 2)); + // right + ProcessWithEdgeChecks(sourceData, destinationData, + new Rectangle(rect.Right - kernelHalf, rect.Top + kernelHalf, kernelHalf, rect.Height - kernelHalf * 2)); + } + } + + // Perform parallel image processing without checking pixels' coordinates to make sure those are in bounds + private unsafe void ProcessWithoutChecksParallel(UnmanagedImage source, UnmanagedImage destination, Rectangle rect) + { + int startX = rect.Left; + int startY = rect.Top; + int stopX = rect.Right; + int stopY = rect.Bottom; + + int pixelSize = System.Drawing.Image.GetPixelFormatSize(source.PixelFormat) / 8; + int kernelHalf = kernelSize / 2; + int bytesInKernelRow = kernelSize * pixelSize; + + int srcStride = source.Stride; + int dstStride = destination.Stride; + + + // offset of the first kernel's pixel + int srcKernelFistPixelOffset = kernelHalf * (srcStride + pixelSize); + + // offset to move to the next kernel's pixel after processing one kernel's row + int srcKernelOffset = srcStride - bytesInKernelRow; + + byte* srcBase = (byte*)source.ImageData.ToPointer(); + byte* dstBase = (byte*)destination.ImageData.ToPointer(); + + // align pointers to the left most pixel in the first row + srcBase += startX * pixelSize; + dstBase += startX * pixelSize; + + if (pixelSize > 1) + { + Parallel.For(startY, stopY, delegate(int y) + { + byte* src = srcBase + y * srcStride; + byte* dst = dstBase + y * dstStride; + + byte srcR, srcG, srcB; + byte srcR0, srcG0, srcB0; + byte* srcPixel; + + int tx, ty; + + double sCoefR, sCoefG, sCoefB, sMembR, sMembG, sMembB, coefR, coefG, coefB; + + for (int x = startX; x < stopX; x++, src += pixelSize, dst += pixelSize) + { + // lower right corner - to start processing from that point + srcPixel = src + srcKernelFistPixelOffset; + + sCoefR = 0; + sCoefG = 0; + sCoefB = 0; + sMembR = 0; + sMembG = 0; + sMembB = 0; + + srcR0 = src[RGB.R]; + srcG0 = src[RGB.G]; + srcB0 = src[RGB.B]; + + // move from lower right to upper left corner + ty = kernelSize; + while (ty != 0) + { + ty--; + + tx = kernelSize; + while (tx != 0) + { + tx--; + + srcR = srcPixel[RGB.R]; + srcG = srcPixel[RGB.G]; + srcB = srcPixel[RGB.B]; + + coefR = spatialFunc[tx, ty] * colorFunc[srcR, srcR0]; + coefG = spatialFunc[tx, ty] * colorFunc[srcG, srcG0]; + coefB = spatialFunc[tx, ty] * colorFunc[srcB, srcB0]; + + sCoefR += coefR; + sCoefG += coefG; + sCoefB += coefB; + + sMembR += coefR * srcR; + sMembG += coefG * srcG; + sMembB += coefB * srcB; + + srcPixel -= pixelSize; + } + + srcPixel -= srcKernelOffset; + } + + dst[RGB.R] = (byte)(sMembR / sCoefR); + dst[RGB.G] = (byte)(sMembG / sCoefG); + dst[RGB.B] = (byte)(sMembB / sCoefB); + } + }); + } + else + { + // 8bpp grayscale images + Parallel.For(startY, stopY, delegate(int y) + { + byte* src = srcBase + y * srcStride; + byte* dst = dstBase + y * dstStride; + + byte srcC; + byte srcC0; + byte* srcPixel; + double sCoefC, sMembC, coefC; + + int tx, ty; + + for (int x = startX; x < stopX; x++, src++, dst++) + { + // lower right corner - to start processing from that point + srcPixel = src + srcKernelFistPixelOffset; + + sCoefC = 0; + sMembC = 0; + + srcC0 = *src; + + // move from lower right to upper left corner + ty = kernelSize; + while (ty != 0) + { + ty--; + + tx = kernelSize; + while (tx != 0) + { + tx--; + + srcC = *(srcPixel); + coefC = spatialFunc[tx, ty] * colorFunc[srcC, srcC0]; + + sCoefC += coefC; + sMembC += coefC * srcC; + + srcPixel -= pixelSize; + } + + srcPixel -= srcKernelOffset; + } + + *dst = (byte)(sMembC / sCoefC); + } + }); + } + } + + // Perform image processing without checking pixels' coordinates to make sure those are in bounds + private unsafe void ProcessWithoutChecks(UnmanagedImage source, UnmanagedImage destination, Rectangle rect) + { + int startX = rect.Left; + int startY = rect.Top; + int stopX = rect.Right; + int stopY = rect.Bottom; + + int pixelSize = System.Drawing.Image.GetPixelFormatSize(source.PixelFormat) / 8; + int kernelHalf = kernelSize / 2; + int bytesInKernelRow = kernelSize * pixelSize; + + int srcStride = source.Stride; + int dstStride = destination.Stride; + + int srcOffset = srcStride - rect.Width * pixelSize; + int dstOffset = dstStride - rect.Width * pixelSize; + + // offset of the first kernel's pixel + int srcKernelFistPixelOffset = kernelHalf * (srcStride + pixelSize); + // offset to move to the next kernel's pixel after processing one kernel's row + int srcKernelOffset = srcStride - bytesInKernelRow; + + int tx, ty; + + byte* src = (byte*)source.ImageData.ToPointer(); + byte* dst = (byte*)destination.ImageData.ToPointer(); + + // allign pointers to the first pixel to process + src += startY * srcStride + startX * pixelSize; + dst += startY * dstStride + startX * pixelSize; + + if (pixelSize > 1) + { + byte srcR, srcG, srcB; + byte srcR0, srcG0, srcB0; + byte* srcPixel; + + double sCoefR, sCoefG, sCoefB, sMembR, sMembG, sMembB, coefR, coefG, coefB; + + for (int y = startY; y < stopY; y++) + { + for (int x = startX; x < stopX; x++, src += pixelSize, dst += pixelSize) + { + // lower right corner - to start processing from that point + srcPixel = src + srcKernelFistPixelOffset; + + sCoefR = 0; + sCoefG = 0; + sCoefB = 0; + sMembR = 0; + sMembG = 0; + sMembB = 0; + + srcR0 = src[RGB.R]; + srcG0 = src[RGB.G]; + srcB0 = src[RGB.B]; + + // move from lower right to upper left corner + ty = kernelSize; + while (ty != 0) + { + ty--; + + tx = kernelSize; + while (tx != 0) + { + tx--; + + srcR = srcPixel[RGB.R]; + srcG = srcPixel[RGB.G]; + srcB = srcPixel[RGB.B]; + + coefR = spatialFunc[tx, ty] * colorFunc[srcR, srcR0]; + coefG = spatialFunc[tx, ty] * colorFunc[srcG, srcG0]; + coefB = spatialFunc[tx, ty] * colorFunc[srcB, srcB0]; + + sCoefR += coefR; + sCoefG += coefG; + sCoefB += coefB; + + sMembR += coefR * srcR; + sMembG += coefG * srcG; + sMembB += coefB * srcB; + + srcPixel -= pixelSize; + } + + srcPixel -= srcKernelOffset; + } + + dst[RGB.R] = (byte)(sMembR / sCoefR); + dst[RGB.G] = (byte)(sMembG / sCoefG); + dst[RGB.B] = (byte)(sMembB / sCoefB); + } + src += srcOffset; + dst += dstOffset; + } + } + else + { + // 8bpp grayscale images + byte srcC; + byte srcC0; + byte* srcPixel; + double sCoefC, sMembC, coefC; + + for (int y = startY; y < stopY; y++) + { + for (int x = startX; x < stopX; x++, src++, dst++) + { + // lower right corner - to start processing from that point + srcPixel = src + srcKernelFistPixelOffset; + + sCoefC = 0; + sMembC = 0; + + srcC0 = *src; + + // move from lower right to upper left corner + ty = kernelSize; + while (ty != 0) + { + ty--; + + tx = kernelSize; + while (tx != 0) + { + tx--; + + srcC = *(srcPixel); + coefC = spatialFunc[tx, ty] * colorFunc[srcC, srcC0]; + + sCoefC += coefC; + sMembC += coefC * srcC; + + srcPixel -= pixelSize; + } + + srcPixel -= srcKernelOffset; + } + + *dst = (byte)(sMembC / sCoefC); + } + src += srcOffset; + dst += dstOffset; + } + } + } + + // Perform image processing with checking pixels' coordinates to make sure those are in bounds + private unsafe void ProcessWithEdgeChecks(UnmanagedImage source, UnmanagedImage destination, Rectangle rect) + { + int width = source.Width; + int height = source.Height; + + int startX = rect.Left; + int startY = rect.Top; + int stopX = rect.Right; + int stopY = rect.Bottom; + + int pixelSize = System.Drawing.Image.GetPixelFormatSize(source.PixelFormat) / 8; + int kernelHalf = kernelSize / 2; + int bytesInKernelRow = kernelSize * pixelSize; + + int srcStride = source.Stride; + int dstStride = destination.Stride; + + int srcOffset = srcStride - rect.Width * pixelSize; + int dstOffset = dstStride - rect.Width * pixelSize; + + // offset of the first kernel's pixel + int srcKernelFistPixelOffset = kernelHalf * (srcStride + pixelSize); + // offset to move to the next kernel's pixel after processing one kernel's row + int srcKernelOffset = srcStride - bytesInKernelRow; + + int rx, ry; + int tx, ty; + + byte* src = (byte*)source.ImageData.ToPointer(); + byte* dst = (byte*)destination.ImageData.ToPointer(); + + // allign pointers to the first pixel to process + src += startY * srcStride + startX * pixelSize; + dst += startY * dstStride + startX * pixelSize; + + if (pixelSize > 1) + { + // color images + byte srcR, srcG, srcB; + byte srcR0, srcG0, srcB0; + byte* srcPixel; + + double sCoefR, sCoefG, sCoefB, sMembR, sMembG, sMembB, coefR, coefG, coefB; + + for (int y = startY; y < stopY; y++) + { + for (int x = startX; x < stopX; x++, src += pixelSize, dst += pixelSize) + { + // lower right corner - to start processing from that point + srcPixel = src + srcKernelFistPixelOffset; + + sCoefR = 0; + sCoefG = 0; + sCoefB = 0; + sMembR = 0; + sMembG = 0; + sMembB = 0; + + srcR0 = src[RGB.R]; + srcG0 = src[RGB.G]; + srcB0 = src[RGB.B]; + + // move from lower right to upper left corner + ty = kernelSize; + while (ty != 0) + { + ty--; + ry = ty - kernelHalf; + + if ((ry + y >= height) || (ry + y < 0)) // bounds check + { + srcPixel -= srcStride; + continue; + } + + tx = kernelSize; + while (tx != 0) + { + tx--; + rx = tx - kernelHalf; + + if ((rx + x >= width) || (rx + x < 0)) // bounds check + { + srcPixel -= pixelSize; + continue; + } + + srcR = srcPixel[RGB.R]; + srcG = srcPixel[RGB.G]; + srcB = srcPixel[RGB.B]; + + coefR = spatialFunc[tx, ty] * colorFunc[srcR, srcR0]; + coefG = spatialFunc[tx, ty] * colorFunc[srcG, srcG0]; + coefB = spatialFunc[tx, ty] * colorFunc[srcB, srcB0]; + + sCoefR += coefR; + sCoefG += coefG; + sCoefB += coefB; + + sMembR += coefR * srcR; + sMembG += coefG * srcG; + sMembB += coefB * srcB; + + srcPixel -= pixelSize; + } + + srcPixel -= srcKernelOffset; + } + + dst[RGB.R] = (byte)(sMembR / sCoefR); + dst[RGB.G] = (byte)(sMembG / sCoefG); + dst[RGB.B] = (byte)(sMembB / sCoefB); + } + + src += srcOffset; + dst += dstOffset; + } + } + else + { + // 8bpp grayscale images + byte srcC; + byte srcC0; + byte* srcPixel; + double sCoefC, sMembC, coefC; + + for (int y = startY; y < stopY; y++) + { + for (int x = startX; x < stopX; x++, src++, dst++) + { + // lower right corner - to start processing from that point + srcPixel = src + srcKernelFistPixelOffset; + + sCoefC = 0; + sMembC = 0; + + srcC0 = *src; + + // move from lower right to upper left corner + ty = kernelSize; + while (ty != 0) + { + ty--; + ry = (int)(ty - kernelHalf); + + if ((ry + y >= height) || (ry + y < 0)) // bounds check + { + srcPixel -= srcStride; + continue; + } + + tx = kernelSize; + while (tx != 0) + { + tx--; + rx = (int)(tx - kernelHalf); + + if ((rx + x >= source.Width) || (rx + x < 0)) // bounds check + { + srcPixel -= pixelSize; + continue; + } + + srcC = *(srcPixel); + coefC = spatialFunc[tx, ty] * colorFunc[srcC, srcC0]; + + sCoefC += coefC; + sMembC += coefC * srcC; + + srcPixel -= pixelSize; + } + + srcPixel -= srcKernelOffset; + } + + *dst = (byte)(sMembC / sCoefC); + } + src += srcOffset; + dst += dstOffset; + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Smooting/ConservativeSmoothing.cs b/Sources/Accord.Imaging/AForge/Filters/Smooting/ConservativeSmoothing.cs new file mode 100644 index 0000000000..04f347fac --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Smooting/ConservativeSmoothing.cs @@ -0,0 +1,283 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Conservative smoothing. + /// + /// + /// The filter implements conservative smoothing, which is a noise reduction + /// technique that derives its name from the fact that it employs a simple, fast filtering + /// algorithm that sacrifices noise suppression power in order to preserve the high spatial + /// frequency detail (e.g. sharp edges) in an image. It is explicitly designed to remove noise + /// spikes - isolated pixels of exceptionally low or high pixel intensity + /// (salt and pepper noise). + /// + /// If the filter finds a pixel which has minimum/maximum value compared to its surrounding + /// pixel, then its value is replaced by minimum/maximum value of those surrounding pixel. + /// For example, lets suppose the filter uses kernel size of 3x3, + /// which means each pixel has 8 surrounding pixel. If pixel's value is smaller than any value + /// of surrounding pixels, then the value of the pixel is replaced by minimum value of those surrounding + /// pixels. + /// + /// The filter accepts 8 bpp grayscale images and 24/32 bpp + /// color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// ConservativeSmoothing filter = new ConservativeSmoothing( ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class ConservativeSmoothing : BaseUsingCopyPartialFilter + { + private int size = 3; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Kernel size, [3, 25]. + /// + /// + /// Determines the size of pixel's square used for smoothing. + /// + /// Default value is set to 3. + /// + /// The value should be odd. + /// + /// + public int KernelSize + { + get { return size; } + set { size = Math.Max(3, Math.Min(25, value | 1)); } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public ConservativeSmoothing() + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Kernel size. + /// + public ConservativeSmoothing(int size) + : this() + { + KernelSize = size; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect) + { + int pixelSize = Image.GetPixelFormatSize(sourceData.PixelFormat) / 8; + + // processing start and stop X,Y positions + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + + int srcStride = sourceData.Stride; + int dstStride = destinationData.Stride; + int srcOffset = srcStride - rect.Width * pixelSize; + int dstOffset = dstStride - rect.Width * pixelSize; + + // loop and array indexes + int i, j, t; + // kernel's radius + int radius = size >> 1; + // pixel value (min and max) + byte minR, maxR, minG, maxG, minB, maxB, v; + + byte* src = (byte*)sourceData.ImageData.ToPointer(); + byte* dst = (byte*)destinationData.ImageData.ToPointer(); + byte* p; + + // allign pointers to the first pixel to process + src += (startY * srcStride + startX * pixelSize); + dst += (startY * dstStride + startX * pixelSize); + + if (destinationData.PixelFormat == PixelFormat.Format8bppIndexed) + { + // Grayscale image + + // for each line + for (int y = startY; y < stopY; y++) + { + // for each pixel + for (int x = startX; x < stopX; x++, src++, dst++) + { + minG = 255; + maxG = 0; + + // for each kernel row + for (i = -radius; i <= radius; i++) + { + t = y + i; + + // skip row + if (t < startY) + continue; + // break + if (t >= stopY) + break; + + // for each kernel column + for (j = -radius; j <= radius; j++) + { + t = x + j; + + // skip column + if (t < startX) + continue; + + if ((i != j) && (t < stopX)) + { + // find MIN and MAX values + v = src[i * srcStride + j]; + + if (v < minG) + minG = v; + if (v > maxG) + maxG = v; + } + } + } + // set destination pixel + v = *src; + *dst = (v > maxG) ? maxG : ((v < minG) ? minG : v); + } + src += srcOffset; + dst += dstOffset; + } + } + else + { + // RGB image + + // for each line + for (int y = startY; y < stopY; y++) + { + // for each pixel + for (int x = startX; x < stopX; x++, src += pixelSize, dst += pixelSize) + { + minR = minG = minB = 255; + maxR = maxG = maxB = 0; + + // for each kernel row + for (i = -radius; i <= radius; i++) + { + t = y + i; + + // skip row + if (t < startY) + continue; + // break + if (t >= stopY) + break; + + // for each kernel column + for (j = -radius; j <= radius; j++) + { + t = x + j; + + // skip column + if (t < startX) + continue; + + if ((i != j) && (t < stopX)) + { + p = &src[i * srcStride + j * pixelSize]; + + // find MIN and MAX values + + // red + v = p[RGB.R]; + + if (v < minR) + minR = v; + if (v > maxR) + maxR = v; + + // green + v = p[RGB.G]; + + if (v < minG) + minG = v; + if (v > maxG) + maxG = v; + + // blue + v = p[RGB.B]; + + if (v < minB) + minB = v; + if (v > maxB) + maxB = v; + } + } + } + // set destination pixel + + // red + v = src[RGB.R]; + dst[RGB.R] = (v > maxR) ? maxR : ((v < minR) ? minR : v); + // green + v = src[RGB.G]; + dst[RGB.G] = (v > maxG) ? maxG : ((v < minG) ? minG : v); + // blue + v = src[RGB.B]; + dst[RGB.B] = (v > maxB) ? maxB : ((v < minB) ? minB : v); + } + src += srcOffset; + dst += dstOffset; + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Smooting/Median.cs b/Sources/Accord.Imaging/AForge/Filters/Smooting/Median.cs new file mode 100644 index 0000000000..e23c26a19 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Smooting/Median.cs @@ -0,0 +1,252 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Median filter. + /// + /// + /// The median filter is normally used to reduce noise in an image, somewhat like + /// the mean filter. However, it often does a better job than the mean + /// filter of preserving useful detail in the image. + /// + /// Each pixel of the original source image is replaced with the median of neighboring pixel + /// values. The median is calculated by first sorting all the pixel values from the surrounding + /// neighborhood into numerical order and then replacing the pixel being considered with the + /// middle pixel value. + /// + /// The filter accepts 8 bpp grayscale images and 24/32 bpp + /// color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// Median filter = new Median( ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class Median : BaseUsingCopyPartialFilter + { + private int size = 3; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Processing square size for the median filter, [3, 25]. + /// + /// + /// Default value is set to 3. + /// + /// The value should be odd. + /// + /// + public int Size + { + get { return size; } + set { size = Math.Max(3, Math.Min(25, value | 1)); } + } + + /// + /// Initializes a new instance of the class. + /// + public Median() + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Processing square size. + /// + public Median(int size) + : this() + { + Size = size; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect) + { + int pixelSize = Image.GetPixelFormatSize(sourceData.PixelFormat) / 8; + + // processing start and stop X,Y positions + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + + int srcStride = sourceData.Stride; + int dstStride = destinationData.Stride; + int srcOffset = srcStride - rect.Width * pixelSize; + int dstOffset = dstStride - rect.Width * pixelSize; + + // loop and array indexes + int i, j, t; + // processing square's radius + int radius = size >> 1; + // number of elements + int c; + + // array to hold pixel values (R, G, B) + byte[] r = new byte[size * size]; + byte[] g = new byte[size * size]; + byte[] b = new byte[size * size]; + + byte* src = (byte*)sourceData.ImageData.ToPointer(); + byte* dst = (byte*)destinationData.ImageData.ToPointer(); + byte* p; + + // allign pointers to the first pixel to process + src += (startY * srcStride + startX * pixelSize); + dst += (startY * dstStride + startX * pixelSize); + + // do the processing job + if (destinationData.PixelFormat == PixelFormat.Format8bppIndexed) + { + // grayscale image + + // for each line + for (int y = startY; y < stopY; y++) + { + // for each pixel + for (int x = startX; x < stopX; x++, src++, dst++) + { + c = 0; + + // for each kernel row + for (i = -radius; i <= radius; i++) + { + t = y + i; + + // skip row + if (t < startY) + continue; + // break + if (t >= stopY) + break; + + // for each kernel column + for (j = -radius; j <= radius; j++) + { + t = x + j; + + // skip column + if (t < startX) + continue; + + if (t < stopX) + { + g[c++] = src[i * srcStride + j]; + } + } + } + // sort elements + Array.Sort(g, 0, c); + // get the median + *dst = g[c >> 1]; + } + src += srcOffset; + dst += dstOffset; + } + } + else + { + // RGB image + + // for each line + for (int y = startY; y < stopY; y++) + { + // for each pixel + for (int x = startX; x < stopX; x++, src += pixelSize, dst += pixelSize) + { + c = 0; + + // for each kernel row + for (i = -radius; i <= radius; i++) + { + t = y + i; + + // skip row + if (t < startY) + continue; + // break + if (t >= stopY) + break; + + // for each kernel column + for (j = -radius; j <= radius; j++) + { + t = x + j; + + // skip column + if (t < startX) + continue; + + if (t < stopX) + { + p = &src[i * srcStride + j * pixelSize]; + + r[c] = p[RGB.R]; + g[c] = p[RGB.G]; + b[c] = p[RGB.B]; + c++; + } + } + } + + // sort elements + Array.Sort(r, 0, c); + Array.Sort(g, 0, c); + Array.Sort(b, 0, c); + // get the median + t = c >> 1; + dst[RGB.R] = r[t]; + dst[RGB.G] = g[t]; + dst[RGB.B] = b[t]; + } + src += srcOffset; + dst += dstOffset; + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Transform/BackwardQuadrilateralTransformation.cs b/Sources/Accord.Imaging/AForge/Filters/Transform/BackwardQuadrilateralTransformation.cs new file mode 100644 index 0000000000..ad9207492 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Transform/BackwardQuadrilateralTransformation.cs @@ -0,0 +1,430 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2007-2010 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + using AForge; + using AForge.Math.Geometry; + + /// + /// Performs backward quadrilateral transformation into an area in destination image. + /// + /// + /// The class implements backward quadrilateral transformation algorithm, + /// which allows to transform any rectangular image into any quadrilateral area + /// in a given destination image. The idea of the algorithm is based on homogeneous + /// transformation and its math is described by Paul Heckbert in his + /// "Projective Mappings for Image Warping" paper. + /// + /// + /// The image processing routines implements similar math to , + /// but performs it in backward direction. + /// + /// The image processing filter accepts 8 grayscale images and 24/32 bpp + /// color images for processing. + /// + /// Sample usage: + /// + /// // define quadrilateral's corners + /// List<IntPoint> corners = new List<IntPoint>( ); + /// corners.Add( new IntPoint( 99, 99 ) ); + /// corners.Add( new IntPoint( 156, 79 ) ); + /// corners.Add( new IntPoint( 184, 126 ) ); + /// corners.Add( new IntPoint( 122, 150 ) ); + /// // create filter + /// BackwardQuadrilateralTransformation filter = + /// new BackwardQuadrilateralTransformation( sourceImage, corners ); + /// // apply the filter + /// Bitmap newImage = filter.Apply( image ); + /// + /// + /// Source image: + /// + /// Destination image: + /// + /// Result image: + /// + /// + /// + /// + /// + public class BackwardQuadrilateralTransformation : BaseInPlaceFilter + { + private Bitmap sourceImage = null; + private UnmanagedImage sourceUnmanagedImage = null; + private List destinationQuadrilateral = null; + + private bool useInterpolation = true; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + /// + /// See + /// documentation for additional information. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Source image to be transformed into specified quadrilateral. + /// + /// + /// The property sets the source image, which will be transformed + /// to the specified quadrilateral and put into destination image the filter is applied to. + /// + /// The source image must have the same pixel format as a destination image the filter + /// is applied to. Otherwise exception will be generated when filter is applied. + /// + /// Setting this property will clear the property - + /// only one source image is allowed: managed or unmanaged. + /// + /// + public Bitmap SourceImage + { + get { return sourceImage; } + set + { + sourceImage = value; + + if (value != null) + sourceUnmanagedImage = null; + } + } + + /// + /// Source unmanaged image to be transformed into specified quadrilateral. + /// + /// + /// The property sets the source image, which will be transformed + /// to the specified quadrilateral and put into destination image the filter is applied to. + /// + /// The source image must have the same pixel format as a destination image the filter + /// is applied to. Otherwise exception will be generated when filter is applied. + /// + /// Setting this property will clear the property - + /// only one source image is allowed: managed or unmanaged. + /// + /// + public UnmanagedImage SourceUnmanagedImage + { + get { return sourceUnmanagedImage; } + set + { + sourceUnmanagedImage = value; + + if (value != null) + sourceImage = null; + } + } + + /// + /// Quadrilateral in destination image to transform into. + /// + /// + /// The property specifies 4 corners of a quadrilateral area + /// in destination image where the source image will be transformed into. + /// + /// + public List DestinationQuadrilateral + { + get { return destinationQuadrilateral; } + set { destinationQuadrilateral = value; } + } + + /// + /// Specifies if bilinear interpolation should be used or not. + /// + /// + /// Default value is set to - interpolation + /// is used. + /// + /// + public bool UseInterpolation + { + get { return useInterpolation; } + set { useInterpolation = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public BackwardQuadrilateralTransformation() + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + formatTranslations[PixelFormat.Format32bppPArgb] = PixelFormat.Format32bppPArgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Source image to be transformed into specified quadrilateral + /// (see ). + /// + public BackwardQuadrilateralTransformation(Bitmap sourceImage) + : this() + { + this.sourceImage = sourceImage; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Source unmanaged image to be transformed into specified quadrilateral + /// (see ). + /// + public BackwardQuadrilateralTransformation(UnmanagedImage sourceUnmanagedImage) + : this() + { + this.sourceUnmanagedImage = sourceUnmanagedImage; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Source image to be transformed into specified quadrilateral + /// (see ). + /// Quadrilateral in destination image to transform into. + /// + public BackwardQuadrilateralTransformation(Bitmap sourceImage, List destinationQuadrilateral) + : this() + { + this.sourceImage = sourceImage; + this.destinationQuadrilateral = destinationQuadrilateral; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Source unmanaged image to be transformed into specified quadrilateral + /// (see ). + /// Quadrilateral in destination image to transform into. + /// + public BackwardQuadrilateralTransformation(UnmanagedImage sourceUnmanagedImage, List destinationQuadrilateral) + : this() + { + this.sourceUnmanagedImage = sourceUnmanagedImage; + this.destinationQuadrilateral = destinationQuadrilateral; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Image data to process by the filter. + /// + /// Destination quadrilateral was not set. + /// + protected override unsafe void ProcessFilter(UnmanagedImage image) + { + if (destinationQuadrilateral == null) + throw new InvalidOperationException("Destination quadrilateral was not set."); + + // check overlay type + if (sourceImage != null) + { + // source and destination images must have same pixel format + if (image.PixelFormat != sourceImage.PixelFormat) + throw new InvalidImagePropertiesException("Source and destination images must have same pixel format."); + + // lock source image + BitmapData srcData = sourceImage.LockBits( + new Rectangle(0, 0, sourceImage.Width, sourceImage.Height), + ImageLockMode.ReadOnly, sourceImage.PixelFormat); + + try + { + ProcessFilter(image, new UnmanagedImage(srcData)); + } + finally + { + // unlock source image + sourceImage.UnlockBits(srcData); + } + } + else if (sourceUnmanagedImage != null) + { + // source and destination images must have same pixel format + if (image.PixelFormat != sourceUnmanagedImage.PixelFormat) + throw new InvalidImagePropertiesException("Source and destination images must have same pixel format."); + + ProcessFilter(image, sourceUnmanagedImage); + } + else + { + throw new InvalidOperationException("Source image is not set."); + } + } + + // Process both images transforming source image into quadrilateral in destination image + private unsafe void ProcessFilter(UnmanagedImage dstImage, UnmanagedImage srcImage) + { + // get source and destination images size + int srcWidth = srcImage.Width; + int srcHeight = srcImage.Height; + int dstWidth = dstImage.Width; + int dstHeight = dstImage.Height; + + int pixelSize = Image.GetPixelFormatSize(srcImage.PixelFormat) / 8; + int srcStride = srcImage.Stride; + int dstStride = dstImage.Stride; + + // get bounding rectangle of the quadrilateral + IntPoint minXY, maxXY; + PointsCloud.GetBoundingRectangle(destinationQuadrilateral, out minXY, out maxXY); + + // make sure the rectangle is inside of destination image + if ((maxXY.X < 0) || (maxXY.Y < 0) || (minXY.X >= dstWidth) || (minXY.Y >= dstHeight)) + return; // nothing to do, since quadrilateral is completely outside + + // correct rectangle if required + if (minXY.X < 0) + minXY.X = 0; + if (minXY.Y < 0) + minXY.Y = 0; + if (maxXY.X >= dstWidth) + maxXY.X = dstWidth - 1; + if (maxXY.Y >= dstHeight) + maxXY.Y = dstHeight - 1; + + int startX = minXY.X; + int startY = minXY.Y; + int stopX = maxXY.X + 1; + int stopY = maxXY.Y + 1; + int offset = dstStride - (stopX - startX) * pixelSize; + + // calculate tranformation matrix + List srcRect = new List(); + srcRect.Add(new IntPoint(0, 0)); + srcRect.Add(new IntPoint(srcWidth - 1, 0)); + srcRect.Add(new IntPoint(srcWidth - 1, srcHeight - 1)); + srcRect.Add(new IntPoint(0, srcHeight - 1)); + + double[,] matrix = QuadTransformationCalcs.MapQuadToQuad(destinationQuadrilateral, srcRect); + + // do the job + byte* ptr = (byte*)dstImage.ImageData.ToPointer(); + byte* baseSrc = (byte*)srcImage.ImageData.ToPointer(); + + // allign pointer to the first pixel to process + ptr += (startY * dstStride + startX * pixelSize); + + if (!useInterpolation) + { + byte* p; + + // for each row + for (int y = startY; y < stopY; y++) + { + // for each pixel + for (int x = startX; x < stopX; x++) + { + double factor = matrix[2, 0] * x + matrix[2, 1] * y + matrix[2, 2]; + double srcX = (matrix[0, 0] * x + matrix[0, 1] * y + matrix[0, 2]) / factor; + double srcY = (matrix[1, 0] * x + matrix[1, 1] * y + matrix[1, 2]) / factor; + + if ((srcX >= 0) && (srcY >= 0) && (srcX < srcWidth) && (srcY < srcHeight)) + { + // get pointer to the pixel in the source image + p = baseSrc + (int)srcY * srcStride + (int)srcX * pixelSize; + // copy pixel's values + for (int i = 0; i < pixelSize; i++, ptr++, p++) + { + *ptr = *p; + } + } + else + { + // skip the pixel + ptr += pixelSize; + } + } + ptr += offset; + } + } + else + { + int srcWidthM1 = srcWidth - 1; + int srcHeightM1 = srcHeight - 1; + + // coordinates of source points + double dx1, dy1, dx2, dy2; + int sx1, sy1, sx2, sy2; + + // temporary pointers + byte* p1, p2, p3, p4; + + // for each row + for (int y = startY; y < stopY; y++) + { + // for each pixel + for (int x = startX; x < stopX; x++) + { + double factor = matrix[2, 0] * x + matrix[2, 1] * y + matrix[2, 2]; + double srcX = (matrix[0, 0] * x + matrix[0, 1] * y + matrix[0, 2]) / factor; + double srcY = (matrix[1, 0] * x + matrix[1, 1] * y + matrix[1, 2]) / factor; + + if ((srcX >= 0) && (srcY >= 0) && (srcX < srcWidth) && (srcY < srcHeight)) + { + sx1 = (int)srcX; + sx2 = (sx1 == srcWidthM1) ? sx1 : sx1 + 1; + dx1 = srcX - sx1; + dx2 = 1.0 - dx1; + + sy1 = (int)srcY; + sy2 = (sy1 == srcHeightM1) ? sy1 : sy1 + 1; + dy1 = srcY - sy1; + dy2 = 1.0 - dy1; + + // get four points + p1 = p2 = baseSrc + sy1 * srcStride; + p1 += sx1 * pixelSize; + p2 += sx2 * pixelSize; + + p3 = p4 = baseSrc + sy2 * srcStride; + p3 += sx1 * pixelSize; + p4 += sx2 * pixelSize; + + // interpolate using 4 points + for (int i = 0; i < pixelSize; i++, ptr++, p1++, p2++, p3++, p4++) + { + *ptr = (byte)( + dy2 * (dx2 * (*p1) + dx1 * (*p2)) + + dy1 * (dx2 * (*p3) + dx1 * (*p4))); + } + } + else + { + // skip the pixel + ptr += pixelSize; + } + } + ptr += offset; + } + } + } + } +} \ No newline at end of file diff --git a/Sources/Accord.Imaging/AForge/Filters/Transform/Crop.cs b/Sources/Accord.Imaging/AForge/Filters/Transform/Crop.cs new file mode 100644 index 0000000000..2afafb0d4 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Transform/Crop.cs @@ -0,0 +1,141 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Crop an image. + /// + /// + /// + /// The filter crops an image providing a new image, which contains only the specified + /// rectangle of the original image. + /// + /// The filter accepts 8 and 16 bpp grayscale images and 24, 32, 48 and 64 bpp + /// color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// Crop filter = new Crop( new Rectangle( 75, 75, 320, 240 ) ); + /// // apply the filter + /// Bitmap newImage = filter.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class Crop : BaseTransformationFilter + { + private Rectangle rect; + + // format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Rectangle to crop. + /// + public Rectangle Rectangle + { + get { return rect; } + set { rect = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Rectangle to crop. + /// + public Crop( Rectangle rect ) + { + this.rect = rect; + + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + formatTranslations[PixelFormat.Format16bppGrayScale] = PixelFormat.Format16bppGrayScale; + formatTranslations[PixelFormat.Format48bppRgb] = PixelFormat.Format48bppRgb; + formatTranslations[PixelFormat.Format64bppArgb] = PixelFormat.Format64bppArgb; + } + + /// + /// Calculates new image size. + /// + /// + /// Source image data. + /// + /// New image size - size of the destination image. + /// + protected override System.Drawing.Size CalculateNewImageSize( UnmanagedImage sourceData ) + { + return new Size( rect.Width, rect.Height ); + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData ) + { + // validate rectangle + Rectangle srcRect = rect; + srcRect.Intersect( new Rectangle( 0, 0, sourceData.Width, sourceData.Height ) ); + + int xmin = srcRect.Left; + int ymin = srcRect.Top; + int ymax = srcRect.Bottom - 1; + int copyWidth = srcRect.Width; + + int srcStride = sourceData.Stride; + int dstStride = destinationData.Stride; + int pixelSize = Image.GetPixelFormatSize( sourceData.PixelFormat ) / 8; + int copySize = copyWidth * pixelSize; + + // do the job + byte* src = (byte*) sourceData.ImageData.ToPointer( ) + ymin * srcStride + xmin * pixelSize; + byte* dst = (byte*) destinationData.ImageData.ToPointer( ); + + if ( rect.Top < 0 ) + { + dst -= dstStride * rect.Top; + } + if ( rect.Left < 0 ) + { + dst -= pixelSize * rect.Left; + } + + // for each line + for ( int y = ymin; y <= ymax; y++ ) + { + AForge.SystemTools.CopyUnmanagedMemory( dst, src, copySize ); + src += srcStride; + dst += dstStride; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Transform/Quad.cs b/Sources/Accord.Imaging/AForge/Filters/Transform/Quad.cs new file mode 100644 index 0000000000..347804ab9 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Transform/Quad.cs @@ -0,0 +1,129 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2007-2010 +// andrew.kirillov@aforgenet.com +// + +using System; +using System.Collections.Generic; +using AForge; + +namespace AForge.Imaging.Filters +{ + // The code is based on the code from the below link, which shows + // the idea of mapping any quadrilateral to any other quadrilateral + // http://threeblindmiceandamonkey.com/?p=16 + + internal static class QuadTransformationCalcs + { + private const double TOLERANCE = 1e-13; + + // Caclculates determinant of a 2x2 matrix + private static double Det2( double a, double b, double c, double d ) + { + return ( a * d - b * c ); + } + + // Multiply two 3x3 matrices + private static double[,] MultiplyMatrix( double[,] a, double[,] b ) + { + double[,] c = new double[3, 3]; + + c[0, 0] = a[0, 0] * b[0, 0] + a[0, 1] * b[1, 0] + a[0, 2] * b[2, 0]; + c[0, 1] = a[0, 0] * b[0, 1] + a[0, 1] * b[1, 1] + a[0, 2] * b[2, 1]; + c[0, 2] = a[0, 0] * b[0, 2] + a[0, 1] * b[1, 2] + a[0, 2] * b[2, 2]; + c[1, 0] = a[1, 0] * b[0, 0] + a[1, 1] * b[1, 0] + a[1, 2] * b[2, 0]; + c[1, 1] = a[1, 0] * b[0, 1] + a[1, 1] * b[1, 1] + a[1, 2] * b[2, 1]; + c[1, 2] = a[1, 0] * b[0, 2] + a[1, 1] * b[1, 2] + a[1, 2] * b[2, 2]; + c[2, 0] = a[2, 0] * b[0, 0] + a[2, 1] * b[1, 0] + a[2, 2] * b[2, 0]; + c[2, 1] = a[2, 0] * b[0, 1] + a[2, 1] * b[1, 1] + a[2, 2] * b[2, 1]; + c[2, 2] = a[2, 0] * b[0, 2] + a[2, 1] * b[1, 2] + a[2, 2] * b[2, 2]; + + return c; + } + + // Calculates adjugate 3x3 matrix + private static double[,] AdjugateMatrix( double[,] a ) + { + double[,] b = new double[3, 3]; + b[0, 0] = Det2( a[1, 1], a[1, 2], a[2, 1], a[2, 2] ); + b[1, 0] = Det2( a[1, 2], a[1, 0], a[2, 2], a[2, 0] ); + b[2, 0] = Det2( a[1, 0], a[1, 1], a[2, 0], a[2, 1] ); + b[0, 1] = Det2( a[2, 1], a[2, 2], a[0, 1], a[0, 2] ); + b[1, 1] = Det2( a[2, 2], a[2, 0], a[0, 2], a[0, 0] ); + b[2, 1] = Det2( a[2, 0], a[2, 1], a[0, 0], a[0, 1] ); + b[0, 2] = Det2( a[0, 1], a[0, 2], a[1, 1], a[1, 2] ); + b[1, 2] = Det2( a[0, 2], a[0, 0], a[1, 2], a[1, 0] ); + b[2, 2] = Det2( a[0, 0], a[0, 1], a[1, 0], a[1, 1] ); + + return b; + } + + // Calculate matrix for unit square to quad mapping + private static double[,] MapSquareToQuad( List quad ) + { + double[,] sq = new double[3, 3]; + double px, py; + + px = quad[0].X - quad[1].X + quad[2].X - quad[3].X; + py = quad[0].Y - quad[1].Y + quad[2].Y - quad[3].Y; + + if ( ( px < TOLERANCE ) && ( px > -TOLERANCE ) && + ( py < TOLERANCE ) && ( py > -TOLERANCE ) ) + { + sq[0, 0] = quad[1].X - quad[0].X; + sq[0, 1] = quad[2].X - quad[1].X; + sq[0, 2] = quad[0].X; + + sq[1, 0] = quad[1].Y - quad[0].Y; + sq[1, 1] = quad[2].Y - quad[1].Y; + sq[1, 2] = quad[0].Y; + + sq[2, 0] = 0.0; + sq[2, 1] = 0.0; + sq[2, 2] = 1.0; + } + else + { + double dx1, dx2, dy1, dy2, del; + + dx1 = quad[1].X - quad[2].X; + dx2 = quad[3].X - quad[2].X; + dy1 = quad[1].Y - quad[2].Y; + dy2 = quad[3].Y - quad[2].Y; + + del = Det2( dx1, dx2, dy1, dy2 ); + + if ( del == 0.0 ) + return null; + + sq[2, 0] = Det2( px, dx2, py, dy2 ) / del; + sq[2, 1] = Det2( dx1, px, dy1, py ) / del; + sq[2, 2] = 1.0; + + sq[0, 0] = quad[1].X - quad[0].X + sq[2, 0] * quad[1].X; + sq[0, 1] = quad[3].X - quad[0].X + sq[2, 1] * quad[3].X; + sq[0, 2] = quad[0].X; + + sq[1, 0] = quad[1].Y - quad[0].Y + sq[2, 0] * quad[1].Y; + sq[1, 1] = quad[3].Y - quad[0].Y + sq[2, 1] * quad[3].Y; + sq[1, 2] = quad[0].Y; + } + return sq; + } + + // Calculate matrix for general quad to quad mapping + public static double[,] MapQuadToQuad( List input, List output ) + { + double[,] squareToInpit = MapSquareToQuad( input ); + double[,] squareToOutput = MapSquareToQuad( output ); + + if ( squareToOutput == null ) + return null; + + return MultiplyMatrix( squareToOutput, AdjugateMatrix( squareToInpit ) ); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Transform/QuadrilateralTransformation.cs b/Sources/Accord.Imaging/AForge/Filters/Transform/QuadrilateralTransformation.cs new file mode 100644 index 0000000000..8f44ee40a --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Transform/QuadrilateralTransformation.cs @@ -0,0 +1,410 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2007-2010 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + using AForge; + + /// + /// Performs quadrilateral transformation of an area in a given source image. + /// + /// + /// The class implements quadrilateral transformation algorithm, + /// which allows to transform any quadrilateral from a given source image + /// to a rectangular image. The idea of the algorithm is based on homogeneous + /// transformation and its math is described by Paul Heckbert in his + /// "Projective Mappings for Image Warping" paper. + /// + /// + /// The image processing filter accepts 8 grayscale images and 24/32 bpp + /// color images for processing. + /// + /// Sample usage: + /// + /// // define quadrilateral's corners + /// List<IntPoint> corners = new List<IntPoint>( ); + /// corners.Add( new IntPoint( 99, 99 ) ); + /// corners.Add( new IntPoint( 156, 79 ) ); + /// corners.Add( new IntPoint( 184, 126 ) ); + /// corners.Add( new IntPoint( 122, 150 ) ); + /// // create filter + /// QuadrilateralTransformation filter = + /// new QuadrilateralTransformation( corners, 200, 200 ); + /// // apply the filter + /// Bitmap newImage = filter.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + public class QuadrilateralTransformation : BaseTransformationFilter + { + private bool automaticSizeCalculaton = true; + private bool useInterpolation = true; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + /// + /// See + /// documentation for additional information. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// New image width. + /// + protected int newWidth; + + /// + /// New image height. + /// + protected int newHeight; + + /// + /// Automatic calculation of destination image or not. + /// + /// + /// The property specifies how to calculate size of destination (transformed) + /// image. If the property is set to , then + /// and properties have effect and destination image's size is + /// specified by user. If the property is set to , then setting the above + /// mentioned properties does not have any effect, but destionation image's size is + /// automatically calculated from property - width and height + /// come from length of longest edges. + /// + /// + /// Default value is set to . + /// + /// + public bool AutomaticSizeCalculaton + { + get { return automaticSizeCalculaton; } + set + { + automaticSizeCalculaton = value; + if (value) + { + CalculateDestinationSize(); + } + } + } + + // Quadrilateral's corners in source image. + private List sourceQuadrilateral; + + /// + /// Quadrilateral's corners in source image. + /// + /// + /// The property specifies four corners of the quadrilateral area + /// in the source image to be transformed. + /// + /// + public List SourceQuadrilateral + { + get { return sourceQuadrilateral; } + set + { + sourceQuadrilateral = value; + if (automaticSizeCalculaton) + { + CalculateDestinationSize(); + } + } + } + + /// + /// Width of the new transformed image. + /// + /// + /// The property defines width of the destination image, which gets + /// transformed quadrilateral image. + /// + /// Setting the property does not have any effect, if + /// property is set to . In this case destination image's width + /// is calculated automatically based on property. + /// + /// + public int NewWidth + { + get { return newWidth; } + set + { + if (!automaticSizeCalculaton) + { + newWidth = Math.Max(1, value); + } + } + } + + /// + /// Height of the new transformed image. + /// + /// + /// The property defines height of the destination image, which gets + /// transformed quadrilateral image. + /// + /// Setting the property does not have any effect, if + /// property is set to . In this case destination image's height + /// is calculated automatically based on property. + /// + /// + public int NewHeight + { + get { return newHeight; } + set + { + if (!automaticSizeCalculaton) + { + newHeight = Math.Max(1, value); + } + } + } + + /// + /// Specifies if bilinear interpolation should be used or not. + /// + /// + /// Default value is set to - interpolation + /// is used. + /// + /// + public bool UseInterpolation + { + get { return useInterpolation; } + set { useInterpolation = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public QuadrilateralTransformation() + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + formatTranslations[PixelFormat.Format32bppPArgb] = PixelFormat.Format32bppPArgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Corners of the source quadrilateral area. + /// Width of the new transformed image. + /// Height of the new transformed image. + /// + /// This constructor sets to + /// , which means that destination image will have width and + /// height as specified by user. + /// + public QuadrilateralTransformation(List sourceQuadrilateral, int newWidth, int newHeight) + : this() + { + this.automaticSizeCalculaton = false; + this.sourceQuadrilateral = sourceQuadrilateral; + this.newWidth = newWidth; + this.newHeight = newHeight; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Corners of the source quadrilateral area. + /// + /// This constructor sets to + /// , which means that destination image will have width and + /// height automatically calculated based on property. + /// + public QuadrilateralTransformation(List sourceQuadrilateral) + : this() + { + this.automaticSizeCalculaton = true; + this.sourceQuadrilateral = sourceQuadrilateral; + CalculateDestinationSize(); + } + + /// + /// Calculates new image size. + /// + /// + /// Source image data. + /// + /// New image size - size of the destination image. + /// + /// Source quadrilateral was not set. + /// + protected override System.Drawing.Size CalculateNewImageSize(UnmanagedImage sourceData) + { + if (sourceQuadrilateral == null) + throw new InvalidOperationException("Source quadrilateral was not set."); + + return new Size(newWidth, newHeight); + } + + // Calculates size of destination image + private void CalculateDestinationSize() + { + if (sourceQuadrilateral == null) + throw new InvalidOperationException("Source quadrilateral was not set."); + + newWidth = (int)Math.Max(sourceQuadrilateral[0].DistanceTo(sourceQuadrilateral[1]), + sourceQuadrilateral[2].DistanceTo(sourceQuadrilateral[3])); + newHeight = (int)Math.Max(sourceQuadrilateral[1].DistanceTo(sourceQuadrilateral[2]), + sourceQuadrilateral[3].DistanceTo(sourceQuadrilateral[0])); + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData) + { + // get source and destination images size + int srcWidth = sourceData.Width; + int srcHeight = sourceData.Height; + int dstWidth = destinationData.Width; + int dstHeight = destinationData.Height; + + int pixelSize = Image.GetPixelFormatSize(sourceData.PixelFormat) / 8; + int srcStride = sourceData.Stride; + int dstStride = destinationData.Stride; + int offset = dstStride - dstWidth * pixelSize; + + // calculate tranformation matrix + List dstRect = new List(); + dstRect.Add(new IntPoint(0, 0)); + dstRect.Add(new IntPoint(dstWidth - 1, 0)); + dstRect.Add(new IntPoint(dstWidth - 1, dstHeight - 1)); + dstRect.Add(new IntPoint(0, dstHeight - 1)); + + // calculate tranformation matrix + double[,] matrix = QuadTransformationCalcs.MapQuadToQuad(dstRect, sourceQuadrilateral); + + // do the job + byte* ptr = (byte*)destinationData.ImageData.ToPointer(); + byte* baseSrc = (byte*)sourceData.ImageData.ToPointer(); + + if (!useInterpolation) + { + byte* p; + + // for each row + for (int y = 0; y < dstHeight; y++) + { + // for each pixel + for (int x = 0; x < dstWidth; x++) + { + double factor = matrix[2, 0] * x + matrix[2, 1] * y + matrix[2, 2]; + double srcX = (matrix[0, 0] * x + matrix[0, 1] * y + matrix[0, 2]) / factor; + double srcY = (matrix[1, 0] * x + matrix[1, 1] * y + matrix[1, 2]) / factor; + + if ((srcX >= 0) && (srcY >= 0) && (srcX < srcWidth) && (srcY < srcHeight)) + { + // get pointer to the pixel in the source image + p = baseSrc + (int)srcY * srcStride + (int)srcX * pixelSize; + // copy pixel's values + for (int i = 0; i < pixelSize; i++, ptr++, p++) + { + *ptr = *p; + } + } + else + { + ptr += pixelSize; + } + } + ptr += offset; + } + } + else + { + int srcWidthM1 = srcWidth - 1; + int srcHeightM1 = srcHeight - 1; + + // coordinates of source points + double dx1, dy1, dx2, dy2; + int sx1, sy1, sx2, sy2; + + // temporary pointers + byte* p1, p2, p3, p4; + + // for each row + for (int y = 0; y < dstHeight; y++) + { + // for each pixel + for (int x = 0; x < dstWidth; x++) + { + double factor = matrix[2, 0] * x + matrix[2, 1] * y + matrix[2, 2]; + double srcX = (matrix[0, 0] * x + matrix[0, 1] * y + matrix[0, 2]) / factor; + double srcY = (matrix[1, 0] * x + matrix[1, 1] * y + matrix[1, 2]) / factor; + + if ((srcX >= 0) && (srcY >= 0) && (srcX < srcWidth) && (srcY < srcHeight)) + { + sx1 = (int)srcX; + sx2 = (sx1 == srcWidthM1) ? sx1 : sx1 + 1; + dx1 = srcX - sx1; + dx2 = 1.0 - dx1; + + sy1 = (int)srcY; + sy2 = (sy1 == srcHeightM1) ? sy1 : sy1 + 1; + dy1 = srcY - sy1; + dy2 = 1.0 - dy1; + + // get four points + p1 = p2 = baseSrc + sy1 * srcStride; + p1 += sx1 * pixelSize; + p2 += sx2 * pixelSize; + + p3 = p4 = baseSrc + sy2 * srcStride; + p3 += sx1 * pixelSize; + p4 += sx2 * pixelSize; + + // interpolate using 4 points + for (int i = 0; i < pixelSize; i++, ptr++, p1++, p2++, p3++, p4++) + { + *ptr = (byte)( + dy2 * (dx2 * (*p1) + dx1 * (*p2)) + + dy1 * (dx2 * (*p3) + dx1 * (*p4))); + } + } + else + { + ptr += pixelSize; + } + } + ptr += offset; + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Transform/QuadrilateralTransformationBilinear.cs b/Sources/Accord.Imaging/AForge/Filters/Transform/QuadrilateralTransformationBilinear.cs new file mode 100644 index 0000000000..b5047cfc4 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Transform/QuadrilateralTransformationBilinear.cs @@ -0,0 +1,182 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2007-2010 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + using AForge; + + /// + /// Performs quadrilateral transformation using bilinear algorithm for interpolation. + /// + /// + /// The class is deprecated and should be used instead. + /// + /// + /// + /// + [Obsolete( "The class is deprecated and SimpleQuadrilateralTransformation should be used instead" )] + public class QuadrilateralTransformationBilinear : BaseTransformationFilter + { + private SimpleQuadrilateralTransformation baseFilter = null; + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return baseFilter.FormatTranslations; } + } + + /// + /// Automatic calculation of destination image or not. + /// + /// + /// The property specifies how to calculate size of destination (transformed) + /// image. If the property is set to , then + /// and properties have effect and destination image's size is + /// specified by user. If the property is set to , then setting the above + /// mentioned properties does not have any effect, but destionation image's size is + /// automatically calculated from property - width and height + /// come from length of longest edges. + /// + /// + public bool AutomaticSizeCalculaton + { + get { return baseFilter.AutomaticSizeCalculaton; } + set { baseFilter.AutomaticSizeCalculaton = value; } + } + + /// + /// Quadrilateral's corners in source image. + /// + /// + /// The property specifies four corners of the quadrilateral area + /// in the source image to be transformed. + /// + /// + public List SourceCorners + { + get { return baseFilter.SourceQuadrilateral; } + set { baseFilter.SourceQuadrilateral = value; } + } + + /// + /// Width of the new transformed image. + /// + /// + /// The property defines width of the destination image, which gets + /// transformed quadrilateral image. + /// + /// Setting the property does not have any effect, if + /// property is set to . In this case destination image's width + /// is calculated automatically based on property. + /// + /// + public int NewWidth + { + get { return baseFilter.NewWidth; } + set { baseFilter.NewWidth = value; } + } + + /// + /// Height of the new transformed image. + /// + /// + /// The property defines height of the destination image, which gets + /// transformed quadrilateral image. + /// + /// Setting the property does not have any effect, if + /// property is set to . In this case destination image's height + /// is calculated automatically based on property. + /// + /// + public int NewHeight + { + get { return baseFilter.NewHeight; } + set { baseFilter.NewHeight = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Corners of the source quadrilateral area. + /// Width of the new transformed image. + /// Height of the new transformed image. + /// + /// This constructor sets to + /// , which means that destination image will have width and + /// height as specified by user. + /// + public QuadrilateralTransformationBilinear( List sourceCorners, int newWidth, int newHeight ) + { + baseFilter = new SimpleQuadrilateralTransformation( sourceCorners, newWidth, newHeight ); + baseFilter.UseInterpolation = true; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Corners of the source quadrilateral area. + /// + /// This constructor sets to + /// , which means that destination image will have width and + /// height automatically calculated based on property. + /// + public QuadrilateralTransformationBilinear( List sourceCorners ) + { + baseFilter = new SimpleQuadrilateralTransformation( sourceCorners ); + baseFilter.UseInterpolation = true; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData ) + { + baseFilter.Apply( sourceData, destinationData ); + } + + /// + /// Calculates new image size. + /// + /// + /// Source image data. + /// + /// New image size - size of the destination image. + /// + /// The specified quadrilateral's corners are outside of the given image. + /// + protected override System.Drawing.Size CalculateNewImageSize( UnmanagedImage sourceData ) + { + // perform checking of source corners - they must feet into the image + foreach ( IntPoint point in baseFilter.SourceQuadrilateral ) + { + if ( ( point.X < 0 ) || + ( point.Y < 0 ) || + ( point.X >= sourceData.Width ) || + ( point.Y >= sourceData.Height ) ) + { + throw new ArgumentException( "The specified quadrilateral's corners are outside of the given image." ); + } + } + + return new Size( baseFilter.NewWidth, baseFilter.NewHeight ); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Transform/QuadrilateralTransformationNearestNeighbor.cs b/Sources/Accord.Imaging/AForge/Filters/Transform/QuadrilateralTransformationNearestNeighbor.cs new file mode 100644 index 0000000000..fa7a4b149 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Transform/QuadrilateralTransformationNearestNeighbor.cs @@ -0,0 +1,182 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2007-2010 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + using AForge; + + /// + /// Performs quadrilateral transformation using nearest neighbor algorithm for interpolation. + /// + /// + /// The class is deprecated and should be used instead. + /// + /// + /// + /// + [Obsolete( "The class is deprecated and SimpleQuadrilateralTransformation should be used instead" )] + public class QuadrilateralTransformationNearestNeighbor : BaseTransformationFilter + { + private SimpleQuadrilateralTransformation baseFilter = null; + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return baseFilter.FormatTranslations; } + } + + /// + /// Automatic calculation of destination image or not. + /// + /// + /// The property specifies how to calculate size of destination (transformed) + /// image. If the property is set to , then + /// and properties have effect and destination image's size is + /// specified by user. If the property is set to , then setting the above + /// mentioned properties does not have any effect, but destionation image's size is + /// automatically calculated from property - width and height + /// come from length of longest edges. + /// + /// + public bool AutomaticSizeCalculaton + { + get { return baseFilter.AutomaticSizeCalculaton; } + set { baseFilter.AutomaticSizeCalculaton = value; } + } + + /// + /// Quadrilateral's corners in source image. + /// + /// + /// The property specifies four corners of the quadrilateral area + /// in the source image to be transformed. + /// + /// + public List SourceCorners + { + get { return baseFilter.SourceQuadrilateral; } + set { baseFilter.SourceQuadrilateral = value; } + } + + /// + /// Width of the new transformed image. + /// + /// + /// The property defines width of the destination image, which gets + /// transformed quadrilateral image. + /// + /// Setting the property does not have any effect, if + /// property is set to . In this case destination image's width + /// is calculated automatically based on property. + /// + /// + public int NewWidth + { + get { return baseFilter.NewWidth; } + set { baseFilter.NewWidth = value; } + } + + /// + /// Height of the new transformed image. + /// + /// + /// The property defines height of the destination image, which gets + /// transformed quadrilateral image. + /// + /// Setting the property does not have any effect, if + /// property is set to . In this case destination image's height + /// is calculated automatically based on property. + /// + /// + public int NewHeight + { + get { return baseFilter.NewHeight; } + set { baseFilter.NewHeight = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Corners of the source quadrilateral area. + /// Width of the new transformed image. + /// Height of the new transformed image. + /// + /// This constructor sets to + /// , which means that destination image will have width and + /// height as specified by user. + /// + public QuadrilateralTransformationNearestNeighbor( List sourceCorners, int newWidth, int newHeight ) + { + baseFilter = new SimpleQuadrilateralTransformation( sourceCorners, newWidth, newHeight ); + baseFilter.UseInterpolation = false; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Corners of the source quadrilateral area. + /// + /// This constructor sets to + /// , which means that destination image will have width and + /// height automatically calculated based on property. + /// + public QuadrilateralTransformationNearestNeighbor( List sourceCorners ) + { + baseFilter = new SimpleQuadrilateralTransformation( sourceCorners ); + baseFilter.UseInterpolation = false; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData ) + { + baseFilter.Apply( sourceData, destinationData ); + } + + /// + /// Calculates new image size. + /// + /// + /// Source image data. + /// + /// New image size - size of the destination image. + /// + /// The specified quadrilateral's corners are outside of the given image. + /// + protected override System.Drawing.Size CalculateNewImageSize( UnmanagedImage sourceData ) + { + // perform checking of source corners - they must feet into the image + foreach ( IntPoint point in baseFilter.SourceQuadrilateral ) + { + if ( ( point.X < 0 ) || + ( point.Y < 0 ) || + ( point.X >= sourceData.Width ) || + ( point.Y >= sourceData.Height ) ) + { + throw new ArgumentException( "The specified quadrilateral's corners are outside of the given image." ); + } + } + + return new Size( baseFilter.NewWidth, baseFilter.NewHeight ); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Transform/ResizeBicubic.cs b/Sources/Accord.Imaging/AForge/Filters/Transform/ResizeBicubic.cs new file mode 100644 index 0000000000..8fc30727b --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Transform/ResizeBicubic.cs @@ -0,0 +1,217 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Resize image using bicubic interpolation algorithm. + /// + /// + /// The class implements image resizing filter using bicubic + /// interpolation algorithm. It uses bicubic kernel W(x) as described on + /// Wikipedia + /// (coefficient a is set to -0.5). + /// + /// The filter accepts 8 grayscale images and 24 bpp + /// color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// ResizeBicubic filter = new ResizeBicubic( 400, 300 ); + /// // apply the filter + /// Bitmap newImage = filter.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + public class ResizeBicubic : BaseResizeFilter + { + // format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Width of new image. + /// Height of new image. + /// + public ResizeBicubic( int newWidth, int newHeight ) : + base( newWidth, newHeight ) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData ) + { + // get source image size + int width = sourceData.Width; + int height = sourceData.Height; + + int pixelSize = ( sourceData.PixelFormat == PixelFormat.Format8bppIndexed ) ? 1 : 3; + int srcStride = sourceData.Stride; + int dstOffset = destinationData.Stride - pixelSize * newWidth; + double xFactor = (double) width / newWidth; + double yFactor = (double) height / newHeight; + + // do the job + byte* src = (byte*) sourceData.ImageData.ToPointer( ); + byte* dst = (byte*) destinationData.ImageData.ToPointer( ); + + // coordinates of source points and cooefficiens + double ox, oy, dx, dy, k1, k2; + int ox1, oy1, ox2, oy2; + // destination pixel values + double r, g, b; + // width and height decreased by 1 + int ymax = height - 1; + int xmax = width - 1; + // temporary pointer + byte* p; + + // check pixel format + if ( destinationData.PixelFormat == PixelFormat.Format8bppIndexed ) + { + // grayscale + for ( int y = 0; y < newHeight; y++ ) + { + // Y coordinates + oy = (double) y * yFactor - 0.5; + oy1 = (int) oy; + dy = oy - (double) oy1; + + for ( int x = 0; x < newWidth; x++, dst++ ) + { + // X coordinates + ox = (double) x * xFactor - 0.5f; + ox1 = (int) ox; + dx = ox - (double) ox1; + + // initial pixel value + g = 0; + + for ( int n = -1; n < 3; n++ ) + { + // get Y cooefficient + k1 = Interpolation.BiCubicKernel( dy - (double) n ); + + oy2 = oy1 + n; + if ( oy2 < 0 ) + oy2 = 0; + if ( oy2 > ymax ) + oy2 = ymax; + + for ( int m = -1; m < 3; m++ ) + { + // get X cooefficient + k2 = k1 * Interpolation.BiCubicKernel( (double) m - dx ); + + ox2 = ox1 + m; + if ( ox2 < 0 ) + ox2 = 0; + if ( ox2 > xmax ) + ox2 = xmax; + + g += k2 * src[oy2 * srcStride + ox2]; + } + } + *dst = (byte) Math.Max( 0, Math.Min( 255, g ) ); + } + dst += dstOffset; + } + } + else + { + // RGB + for ( int y = 0; y < newHeight; y++ ) + { + // Y coordinates + oy = (double) y * yFactor - 0.5f; + oy1 = (int) oy; + dy = oy - (double) oy1; + + for ( int x = 0; x < newWidth; x++, dst += 3 ) + { + // X coordinates + ox = (double) x * xFactor - 0.5f; + ox1 = (int) ox; + dx = ox - (double) ox1; + + // initial pixel value + r = g = b = 0; + + for ( int n = -1; n < 3; n++ ) + { + // get Y cooefficient + k1 = Interpolation.BiCubicKernel( dy - (double) n ); + + oy2 = oy1 + n; + if ( oy2 < 0 ) + oy2 = 0; + if ( oy2 > ymax ) + oy2 = ymax; + + for ( int m = -1; m < 3; m++ ) + { + // get X cooefficient + k2 = k1 * Interpolation.BiCubicKernel( (double) m - dx ); + + ox2 = ox1 + m; + if ( ox2 < 0 ) + ox2 = 0; + if ( ox2 > xmax ) + ox2 = xmax; + + // get pixel of original image + p = src + oy2 * srcStride + ox2 * 3; + + r += k2 * p[RGB.R]; + g += k2 * p[RGB.G]; + b += k2 * p[RGB.B]; + } + } + + dst[RGB.R] = (byte) Math.Max( 0, Math.Min( 255, r ) ); + dst[RGB.G] = (byte) Math.Max( 0, Math.Min( 255, g ) ); + dst[RGB.B] = (byte) Math.Max( 0, Math.Min( 255, b ) ); + } + dst += dstOffset; + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Transform/ResizeBilinear.cs b/Sources/Accord.Imaging/AForge/Filters/Transform/ResizeBilinear.cs new file mode 100644 index 0000000000..615a9120c --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Transform/ResizeBilinear.cs @@ -0,0 +1,146 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Resize image using bilinear interpolation algorithm. + /// + /// + /// The class implements image resizing filter using bilinear + /// interpolation algorithm. + /// + /// The filter accepts 8 grayscale images and 24/32 bpp + /// color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// ResizeBilinear filter = new ResizeBilinear( 400, 300 ); + /// // apply the filter + /// Bitmap newImage = filter.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + public class ResizeBilinear : BaseResizeFilter + { + // format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Width of the new image. + /// Height of the new image. + /// + public ResizeBilinear( int newWidth, int newHeight ) : + base( newWidth, newHeight ) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData ) + { + // get source image size + int width = sourceData.Width; + int height = sourceData.Height; + + int pixelSize = Image.GetPixelFormatSize( sourceData.PixelFormat ) / 8; + int srcStride = sourceData.Stride; + int dstOffset = destinationData.Stride - pixelSize * newWidth; + double xFactor = (double) width / newWidth; + double yFactor = (double) height / newHeight; + + // do the job + byte* src = (byte*) sourceData.ImageData.ToPointer( ); + byte* dst = (byte*) destinationData.ImageData.ToPointer( ); + + // coordinates of source points + double ox, oy, dx1, dy1, dx2, dy2; + int ox1, oy1, ox2, oy2; + // width and height decreased by 1 + int ymax = height - 1; + int xmax = width - 1; + // temporary pointers + byte* tp1, tp2; + byte* p1, p2, p3, p4; + + // for each line + for ( int y = 0; y < newHeight; y++ ) + { + // Y coordinates + oy = (double) y * yFactor; + oy1 = (int) oy; + oy2 = ( oy1 == ymax ) ? oy1 : oy1 + 1; + dy1 = oy - (double) oy1; + dy2 = 1.0 - dy1; + + // get temp pointers + tp1 = src + oy1 * srcStride; + tp2 = src + oy2 * srcStride; + + // for each pixel + for ( int x = 0; x < newWidth; x++ ) + { + // X coordinates + ox = (double) x * xFactor; + ox1 = (int) ox; + ox2 = ( ox1 == xmax ) ? ox1 : ox1 + 1; + dx1 = ox - (double) ox1; + dx2 = 1.0 - dx1; + + // get four points + p1 = tp1 + ox1 * pixelSize; + p2 = tp1 + ox2 * pixelSize; + p3 = tp2 + ox1 * pixelSize; + p4 = tp2 + ox2 * pixelSize; + + // interpolate using 4 points + for ( int i = 0; i < pixelSize; i++, dst++, p1++, p2++, p3++, p4++ ) + { + *dst = (byte) ( + dy2 * ( dx2 * ( *p1 ) + dx1 * ( *p2 ) ) + + dy1 * ( dx2 * ( *p3 ) + dx1 * ( *p4 ) ) ); + } + } + dst += dstOffset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Transform/ResizeNearestNeighbor.cs b/Sources/Accord.Imaging/AForge/Filters/Transform/ResizeNearestNeighbor.cs new file mode 100644 index 0000000000..e5edf982a --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Transform/ResizeNearestNeighbor.cs @@ -0,0 +1,117 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Resize image using nearest neighbor algorithm. + /// + /// + /// The class implements image resizing filter using nearest + /// neighbor algorithm, which does not assume any interpolation. + /// + /// The filter accepts 8 and 16 bpp grayscale images and 24, 32, 48 and 64 bpp + /// color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// ResizeNearestNeighbor filter = new ResizeNearestNeighbor( 400, 300 ); + /// // apply the filter + /// Bitmap newImage = filter.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + public class ResizeNearestNeighbor : BaseResizeFilter + { + // format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Width of the new image. + /// Height of the new image. + /// + public ResizeNearestNeighbor( int newWidth, int newHeight ) : + base( newWidth, newHeight ) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + formatTranslations[PixelFormat.Format16bppGrayScale] = PixelFormat.Format16bppGrayScale; + formatTranslations[PixelFormat.Format48bppRgb] = PixelFormat.Format48bppRgb; + formatTranslations[PixelFormat.Format64bppArgb] = PixelFormat.Format64bppArgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData ) + { + // get source image size + int width = sourceData.Width; + int height = sourceData.Height; + + int pixelSize = Image.GetPixelFormatSize( sourceData.PixelFormat ) / 8; + int srcStride = sourceData.Stride; + int dstStride = destinationData.Stride; + double xFactor = (double) width / newWidth; + double yFactor = (double) height / newHeight; + + // do the job + byte* baseSrc = (byte*) sourceData.ImageData.ToPointer( ); + byte* baseDst = (byte*) destinationData.ImageData.ToPointer( ); + + // for each line + for ( int y = 0; y < newHeight; y++ ) + { + byte* dst = baseDst + dstStride * y; + byte* src = baseSrc + srcStride * ( (int) ( y * yFactor ) ); + byte* p; + + // for each pixel + for ( int x = 0; x < newWidth; x++ ) + { + p = src + pixelSize * ( (int) ( x * xFactor ) ); + + for ( int i = 0; i < pixelSize; i++, dst++, p++ ) + { + *dst = *p; + } + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Transform/RotateBicubic.cs b/Sources/Accord.Imaging/AForge/Filters/Transform/RotateBicubic.cs new file mode 100644 index 0000000000..e0675bd56 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Transform/RotateBicubic.cs @@ -0,0 +1,278 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Rotate image using bicubic interpolation. + /// + /// + /// The class implements image rotation filter using bicubic + /// interpolation algorithm. It uses bicubic kernel W(x) as described on + /// Wikipedia + /// (coefficient a is set to -0.5). + /// + /// Rotation is performed in counterclockwise direction. + /// + /// The filter accepts 8 bpp grayscale images and 24 bpp + /// color images for processing. + /// + /// Sample usage: + /// + /// // create filter - rotate for 30 degrees keeping original image size + /// RotateBicubic filter = new RotateBicubic( 30, true ); + /// // apply the filter + /// Bitmap newImage = filter.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + public class RotateBicubic : BaseRotateFilter + { + // format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Rotation angle. + /// + /// This constructor sets property + /// to . + /// + /// + public RotateBicubic( double angle ) : + this( angle, false ) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Rotation angle. + /// Keep image size or not. + /// + public RotateBicubic( double angle, bool keepSize ) : + base( angle, keepSize ) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData ) + { + // get source image size + int width = sourceData.Width; + int height = sourceData.Height; + double oldXradius = (double) ( width - 1 ) / 2; + double oldYradius = (double) ( height - 1 ) / 2; + + // get destination image size + int newWidth = destinationData.Width; + int newHeight = destinationData.Height; + double newXradius = (double) ( newWidth - 1 ) / 2; + double newYradius = (double) ( newHeight - 1 ) / 2; + + // angle's sine and cosine + double angleRad = -angle * Math.PI / 180; + double angleCos = Math.Cos( angleRad ); + double angleSin = Math.Sin( angleRad ); + + int srcStride = sourceData.Stride; + int dstOffset = destinationData.Stride - + ( ( destinationData.PixelFormat == PixelFormat.Format8bppIndexed ) ? newWidth : newWidth * 3 ); + + // fill values + byte fillR = fillColor.R; + byte fillG = fillColor.G; + byte fillB = fillColor.B; + + // do the job + byte* src = (byte*) sourceData.ImageData.ToPointer( ); + byte* dst = (byte*) destinationData.ImageData.ToPointer( ); + + // destination pixel's coordinate relative to image center + double cx, cy; + // coordinates of source points and cooefficiens + double ox, oy, dx, dy, k1, k2; + int ox1, oy1, ox2, oy2; + // destination pixel values + double r, g, b; + // width and height decreased by 1 + int ymax = height - 1; + int xmax = width - 1; + // temporary pointer + byte* p; + + if ( destinationData.PixelFormat == PixelFormat.Format8bppIndexed ) + { + // grayscale + cy = -newYradius; + for ( int y = 0; y < newHeight; y++ ) + { + cx = -newXradius; + for ( int x = 0; x < newWidth; x++, dst++ ) + { + // coordinates of source point + ox = angleCos * cx + angleSin * cy + oldXradius; + oy = -angleSin * cx + angleCos * cy + oldYradius; + + ox1 = (int) ox; + oy1 = (int) oy; + + // validate source pixel's coordinates + if ( ( ox1 < 0 ) || ( oy1 < 0 ) || ( ox1 >= width ) || ( oy1 >= height ) ) + { + // fill destination image with filler + *dst = fillG; + } + else + { + dx = ox - (double) ox1; + dy = oy - (double) oy1; + + // initial pixel value + g = 0; + + for ( int n = -1; n < 3; n++ ) + { + // get Y cooefficient + k1 = Interpolation.BiCubicKernel( dy - (double) n ); + + oy2 = oy1 + n; + if ( oy2 < 0 ) + oy2 = 0; + if ( oy2 > ymax ) + oy2 = ymax; + + for ( int m = -1; m < 3; m++ ) + { + // get X cooefficient + k2 = k1 * Interpolation.BiCubicKernel( (double) m - dx ); + + ox2 = ox1 + m; + if ( ox2 < 0 ) + ox2 = 0; + if ( ox2 > xmax ) + ox2 = xmax; + + g += k2 * src[oy2 * srcStride + ox2]; + } + } + *dst = (byte) Math.Max( 0, Math.Min( 255, g ) ); + } + cx++; + } + cy++; + dst += dstOffset; + } + } + else + { + // RGB + cy = -newYradius; + for ( int y = 0; y < newHeight; y++ ) + { + cx = -newXradius; + for ( int x = 0; x < newWidth; x++, dst += 3 ) + { + // coordinates of source point + ox = angleCos * cx + angleSin * cy + oldXradius; + oy = -angleSin * cx + angleCos * cy + oldYradius; + + ox1 = (int) ox; + oy1 = (int) oy; + + // validate source pixel's coordinates + if ( ( ox1 < 0 ) || ( oy1 < 0 ) || ( ox1 >= width ) || ( oy1 >= height ) ) + { + // fill destination image with filler + dst[RGB.R] = fillR; + dst[RGB.G] = fillG; + dst[RGB.B] = fillB; + } + else + { + dx = ox - (float) ox1; + dy = oy - (float) oy1; + + // initial pixel value + r = g = b = 0; + + for ( int n = -1; n < 3; n++ ) + { + // get Y cooefficient + k1 = Interpolation.BiCubicKernel( dy - (float) n ); + + oy2 = oy1 + n; + if ( oy2 < 0 ) + oy2 = 0; + if ( oy2 > ymax ) + oy2 = ymax; + + for ( int m = -1; m < 3; m++ ) + { + // get X cooefficient + k2 = k1 * Interpolation.BiCubicKernel( (float) m - dx ); + + ox2 = ox1 + m; + if ( ox2 < 0 ) + ox2 = 0; + if ( ox2 > xmax ) + ox2 = xmax; + + // get pixel of original image + p = src + oy2 * srcStride + ox2 * 3; + + r += k2 * p[RGB.R]; + g += k2 * p[RGB.G]; + b += k2 * p[RGB.B]; + } + } + dst[RGB.R] = (byte) Math.Max( 0, Math.Min( 255, r ) ); + dst[RGB.G] = (byte) Math.Max( 0, Math.Min( 255, g ) ); + dst[RGB.B] = (byte) Math.Max( 0, Math.Min( 255, b ) ); + } + cx++; + } + cy++; + dst += dstOffset; + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Transform/RotateBilinear.cs b/Sources/Accord.Imaging/AForge/Filters/Transform/RotateBilinear.cs new file mode 100644 index 0000000000..5fb010d51 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Transform/RotateBilinear.cs @@ -0,0 +1,274 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Rotate image using bilinear interpolation. + /// + /// + /// Rotation is performed in counterclockwise direction. + /// + /// The class implements image rotation filter using bilinear + /// interpolation algorithm. + /// + /// The filter accepts 8 bpp grayscale images and 24 bpp + /// color images for processing. + /// + /// Sample usage: + /// + /// // create filter - rotate for 30 degrees keeping original image size + /// RotateBilinear filter = new RotateBilinear( 30, true ); + /// // apply the filter + /// Bitmap newImage = filter.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + public class RotateBilinear : BaseRotateFilter + { + // format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Rotation angle. + /// + /// This constructor sets property + /// to . + /// + /// + public RotateBilinear( double angle ) : + this( angle, false ) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Rotation angle. + /// Keep image size or not. + /// + public RotateBilinear( double angle, bool keepSize ) : + base( angle, keepSize ) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData ) + { + // get source image size + int width = sourceData.Width; + int height = sourceData.Height; + double oldXradius = (double) ( width - 1 ) / 2; + double oldYradius = (double) ( height - 1 ) / 2; + + // get destination image size + int newWidth = destinationData.Width; + int newHeight = destinationData.Height; + double newXradius = (double) ( newWidth - 1 ) / 2; + double newYradius = (double) ( newHeight - 1 ) / 2; + + // angle's sine and cosine + double angleRad = -angle * Math.PI / 180; + double angleCos = Math.Cos( angleRad ); + double angleSin = Math.Sin( angleRad ); + + int srcStride = sourceData.Stride; + int dstOffset = destinationData.Stride - + ( ( destinationData.PixelFormat == PixelFormat.Format8bppIndexed ) ? newWidth : newWidth * 3 ); + + // fill values + byte fillR = fillColor.R; + byte fillG = fillColor.G; + byte fillB = fillColor.B; + + // do the job + byte* src = (byte*) sourceData.ImageData.ToPointer( ); + byte* dst = (byte*) destinationData.ImageData.ToPointer( ); + + // destination pixel's coordinate relative to image center + double cx, cy; + // coordinates of source points + double ox, oy, tx, ty, dx1, dy1, dx2, dy2; + int ox1, oy1, ox2, oy2; + // width and height decreased by 1 + int ymax = height - 1; + int xmax = width - 1; + // temporary pointers + byte* p1, p2, p3, p4; + + // check pixel format + if ( destinationData.PixelFormat == PixelFormat.Format8bppIndexed ) + { + // grayscale + cy = -newYradius; + for ( int y = 0; y < newHeight; y++ ) + { + // do some pre-calculations of source points' coordinates + // (calculate the part which depends on y-loop, but does not + // depend on x-loop) + tx = angleSin * cy + oldXradius; + ty = angleCos * cy + oldYradius; + + cx = -newXradius; + for ( int x = 0; x < newWidth; x++, dst++ ) + { + // coordinates of source point + ox = tx + angleCos * cx; + oy = ty - angleSin * cx; + + // top-left coordinate + ox1 = (int) ox; + oy1 = (int) oy; + + // validate source pixel's coordinates + if ( ( ox1 < 0 ) || ( oy1 < 0 ) || ( ox1 >= width ) || ( oy1 >= height ) ) + { + // fill destination image with filler + *dst = fillG; + } + else + { + // bottom-right coordinate + ox2 = ( ox1 == xmax ) ? ox1 : ox1 + 1; + oy2 = ( oy1 == ymax ) ? oy1 : oy1 + 1; + + if ( ( dx1 = ox - (double) ox1 ) < 0 ) + dx1 = 0; + dx2 = 1.0 - dx1; + + if ( ( dy1 = oy - (double) oy1 ) < 0 ) + dy1 = 0; + dy2 = 1.0 - dy1; + + p1 = src + oy1 * srcStride; + p2 = src + oy2 * srcStride; + + // interpolate using 4 points + *dst = (byte) ( + dy2 * ( dx2 * p1[ox1] + dx1 * p1[ox2] ) + + dy1 * ( dx2 * p2[ox1] + dx1 * p2[ox2] ) ); + } + cx++; + } + cy++; + dst += dstOffset; + } + } + else + { + // RGB + cy = -newYradius; + for ( int y = 0; y < newHeight; y++ ) + { + // do some pre-calculations of source points' coordinates + // (calculate the part which depends on y-loop, but does not + // depend on x-loop) + tx = angleSin * cy + oldXradius; + ty = angleCos * cy + oldYradius; + + cx = -newXradius; + for ( int x = 0; x < newWidth; x++, dst += 3 ) + { + // coordinates of source point + ox = tx + angleCos * cx; + oy = ty - angleSin * cx; + + // top-left coordinate + ox1 = (int) ox; + oy1 = (int) oy; + + // validate source pixel's coordinates + if ( ( ox1 < 0 ) || ( oy1 < 0 ) || ( ox1 >= width ) || ( oy1 >= height ) ) + { + // fill destination image with filler + dst[RGB.R] = fillR; + dst[RGB.G] = fillG; + dst[RGB.B] = fillB; + } + else + { + // bottom-right coordinate + ox2 = ( ox1 == xmax ) ? ox1 : ox1 + 1; + oy2 = ( oy1 == ymax ) ? oy1 : oy1 + 1; + + if ( ( dx1 = ox - (float) ox1 ) < 0 ) + dx1 = 0; + dx2 = 1.0f - dx1; + + if ( ( dy1 = oy - (float) oy1 ) < 0 ) + dy1 = 0; + dy2 = 1.0f - dy1; + + // get four points + p1 = p2 = src + oy1 * srcStride; + p1 += ox1 * 3; + p2 += ox2 * 3; + + p3 = p4 = src + oy2 * srcStride; + p3 += ox1 * 3; + p4 += ox2 * 3; + + // interpolate using 4 points + + // red + dst[RGB.R] = (byte) ( + dy2 * ( dx2 * p1[RGB.R] + dx1 * p2[RGB.R] ) + + dy1 * ( dx2 * p3[RGB.R] + dx1 * p4[RGB.R] ) ); + + // green + dst[RGB.G] = (byte) ( + dy2 * ( dx2 * p1[RGB.G] + dx1 * p2[RGB.G] ) + + dy1 * ( dx2 * p3[RGB.G] + dx1 * p4[RGB.G] ) ); + + // blue + dst[RGB.B] = (byte) ( + dy2 * ( dx2 * p1[RGB.B] + dx1 * p2[RGB.B] ) + + dy1 * ( dx2 * p3[RGB.B] + dx1 * p4[RGB.B] ) ); + } + cx++; + } + cy++; + dst += dstOffset; + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Transform/RotateNearestNeighbor.cs b/Sources/Accord.Imaging/AForge/Filters/Transform/RotateNearestNeighbor.cs new file mode 100644 index 0000000000..9f600ef5b --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Transform/RotateNearestNeighbor.cs @@ -0,0 +1,379 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2015 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Rotate image using nearest neighbor algorithm. + /// + /// + /// The class implements image rotation filter using nearest + /// neighbor algorithm, which does not assume any interpolation. + /// + /// Rotation is performed in counterclockwise direction. + /// + /// The filter accepts 8/16 bpp grayscale images and 24/48 bpp color image + /// for processing. + /// + /// Sample usage: + /// + /// // create filter - rotate for 30 degrees keeping original image size + /// RotateNearestNeighbor filter = new RotateNearestNeighbor( 30, true ); + /// // apply the filter + /// Bitmap newImage = filter.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + public class RotateNearestNeighbor : BaseRotateFilter + { + // format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Rotation angle. + /// + /// This constructor sets property to + /// . + /// + /// + public RotateNearestNeighbor(double angle) : + this(angle, false) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Rotation angle. + /// Keep image size or not. + /// + public RotateNearestNeighbor(double angle, bool keepSize) : + base(angle, keepSize) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + formatTranslations[PixelFormat.Format16bppGrayScale] = PixelFormat.Format16bppGrayScale; + formatTranslations[PixelFormat.Format48bppRgb] = PixelFormat.Format48bppRgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + protected override void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData) + { + int pixelSize = Bitmap.GetPixelFormatSize(sourceData.PixelFormat) / 8; + + switch (pixelSize) + { + case 1: + case 3: + ProcessFilter8bpc(sourceData, destinationData); + break; + case 2: + case 6: + ProcessFilter16bpc(sourceData, destinationData); + break; + } + } + + // Process the filter on the image with 8 bits per color channel + private unsafe void ProcessFilter8bpc(UnmanagedImage sourceData, UnmanagedImage destinationData) + { + // get source image size + int width = sourceData.Width; + int height = sourceData.Height; + double oldXradius = (double)(width - 1) / 2; + double oldYradius = (double)(height - 1) / 2; + + // get destination image size + int newWidth = destinationData.Width; + int newHeight = destinationData.Height; + double newXradius = (double)(newWidth - 1) / 2; + double newYradius = (double)(newHeight - 1) / 2; + + // angle's sine and cosine + double angleRad = -angle * Math.PI / 180; + double angleCos = Math.Cos(angleRad); + double angleSin = Math.Sin(angleRad); + + int srcStride = sourceData.Stride; + int dstOffset = destinationData.Stride - + ((destinationData.PixelFormat == PixelFormat.Format8bppIndexed) ? newWidth : newWidth * 3); + + // fill values + byte fillA = fillColor.A; + byte fillR = fillColor.R; + byte fillG = fillColor.G; + byte fillB = fillColor.B; + + // do the job + byte* src = (byte*)sourceData.ImageData.ToPointer(); + byte* dst = (byte*)destinationData.ImageData.ToPointer(); + + // destination pixel's coordinate relative to image center + double cx, cy; + // source pixel's coordinates + int ox, oy; + // temporary pointer + byte* p; + + // check pixel format + if (destinationData.PixelFormat == PixelFormat.Format8bppIndexed) + { + // grayscale + cy = -newYradius; + for (int y = 0; y < newHeight; y++) + { + cx = -newXradius; + for (int x = 0; x < newWidth; x++, dst++) + { + // coordinate of the nearest point + ox = (int)(angleCos * cx + angleSin * cy + oldXradius); + oy = (int)(-angleSin * cx + angleCos * cy + oldYradius); + + // validate source pixel's coordinates + if ((ox < 0) || (oy < 0) || (ox >= width) || (oy >= height)) + { + // fill destination image with filler + *dst = fillG; + } + else + { + // fill destination image with pixel from source image + *dst = src[oy * srcStride + ox]; + } + cx++; + } + cy++; + dst += dstOffset; + } + } + else if (destinationData.PixelFormat == PixelFormat.Format24bppRgb + || destinationData.PixelFormat == PixelFormat.Format32bppRgb) + { + // RGB + cy = -newYradius; + for (int y = 0; y < newHeight; y++) + { + cx = -newXradius; + for (int x = 0; x < newWidth; x++, dst += 3) + { + // coordinate of the nearest point + ox = (int)(angleCos * cx + angleSin * cy + oldXradius); + oy = (int)(-angleSin * cx + angleCos * cy + oldYradius); + + // validate source pixel's coordinates + if ((ox < 0) || (oy < 0) || (ox >= width) || (oy >= height)) + { + // fill destination image with filler + dst[RGB.R] = fillR; + dst[RGB.G] = fillG; + dst[RGB.B] = fillB; + } + else + { + // fill destination image with pixel from source image + p = src + oy * srcStride + ox * 3; + + dst[RGB.R] = p[RGB.R]; + dst[RGB.G] = p[RGB.G]; + dst[RGB.B] = p[RGB.B]; + } + cx++; + } + cy++; + dst += dstOffset; + } + } + else if (destinationData.PixelFormat == PixelFormat.Format32bppArgb) + { + // ARGB + cy = -newYradius; + for (int y = 0; y < newHeight; y++) + { + cx = -newXradius; + for (int x = 0; x < newWidth; x++, dst += 3) + { + // coordinate of the nearest point + ox = (int)(angleCos * cx + angleSin * cy + oldXradius); + oy = (int)(-angleSin * cx + angleCos * cy + oldYradius); + + // validate source pixel's coordinates + if ((ox < 0) || (oy < 0) || (ox >= width) || (oy >= height)) + { + // fill destination image with filler + dst[RGB.A] = fillA; + dst[RGB.R] = fillR; + dst[RGB.G] = fillG; + dst[RGB.B] = fillB; + } + else + { + // fill destination image with pixel from source image + p = src + oy * srcStride + ox * 3; + + dst[RGB.A] = p[RGB.A]; + dst[RGB.R] = p[RGB.R]; + dst[RGB.G] = p[RGB.G]; + dst[RGB.B] = p[RGB.B]; + } + cx++; + } + cy++; + dst += dstOffset; + } + } + else + { + throw new UnsupportedImageFormatException(); + } + } + + // Process the filter on the image with 16 bits per color channel. + private unsafe void ProcessFilter16bpc(UnmanagedImage sourceData, UnmanagedImage destinationData) + { + // get source image size + int width = sourceData.Width; + int height = sourceData.Height; + double halfWidth = (double)width / 2; + double halfHeight = (double)height / 2; + + // get destination image size + int newWidth = destinationData.Width; + int newHeight = destinationData.Height; + double halfNewWidth = (double)newWidth / 2; + double halfNewHeight = (double)newHeight / 2; + + // angle's sine and cosine + double angleRad = -angle * Math.PI / 180; + double angleCos = Math.Cos(angleRad); + double angleSin = Math.Sin(angleRad); + + int srcStride = sourceData.Stride; + int dstStride = destinationData.Stride; + + // fill values + ushort fillR = (ushort)(fillColor.R << 8); + ushort fillG = (ushort)(fillColor.G << 8); + ushort fillB = (ushort)(fillColor.B << 8); + + // do the job + byte* src = (byte*)sourceData.ImageData.ToPointer(); + byte* dstBase = (byte*)destinationData.ImageData.ToPointer(); + + // destination pixel's coordinate relative to image center + double cx, cy; + // source pixel's coordinates + int ox, oy; + // temporary pointer + ushort* p; + + // check pixel format + if (destinationData.PixelFormat == PixelFormat.Format16bppGrayScale) + { + // grayscale + cy = -halfNewHeight; + for (int y = 0; y < newHeight; y++) + { + ushort* dst = (ushort*)(dstBase + y * dstStride); + + cx = -halfNewWidth; + for (int x = 0; x < newWidth; x++, dst++) + { + // coordinate of the nearest point + ox = (int)(angleCos * cx + angleSin * cy + halfWidth); + oy = (int)(-angleSin * cx + angleCos * cy + halfHeight); + + // validate source pixel's coordinates + if ((ox < 0) || (oy < 0) || (ox >= width) || (oy >= height)) + { + // fill destination image with filler + *dst = fillG; + } + else + { + // fill destination image with pixel from source image + p = (ushort*)(src + oy * srcStride + ox * 2); + *dst = *p; + } + cx++; + } + cy++; + } + } + else + { + // RGB + cy = -halfNewHeight; + for (int y = 0; y < newHeight; y++) + { + ushort* dst = (ushort*)(dstBase + y * dstStride); + + cx = -halfNewWidth; + for (int x = 0; x < newWidth; x++, dst += 3) + { + // coordinate of the nearest point + ox = (int)(angleCos * cx + angleSin * cy + halfWidth); + oy = (int)(-angleSin * cx + angleCos * cy + halfHeight); + + // validate source pixel's coordinates + if ((ox < 0) || (oy < 0) || (ox >= width) || (oy >= height)) + { + // fill destination image with filler + dst[RGB.R] = fillR; + dst[RGB.G] = fillG; + dst[RGB.B] = fillB; + } + else + { + // fill destination image with pixel from source image + p = (ushort*)(src + oy * srcStride + ox * 6); + + dst[RGB.R] = p[RGB.R]; + dst[RGB.G] = p[RGB.G]; + dst[RGB.B] = p[RGB.B]; + } + cx++; + } + cy++; + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Transform/Shrink.cs b/Sources/Accord.Imaging/AForge/Filters/Transform/Shrink.cs new file mode 100644 index 0000000000..245566fbd --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Transform/Shrink.cs @@ -0,0 +1,217 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Shrink an image by removing specified color from its boundaries. + /// + /// + /// Removes pixels with specified color from image boundaries making + /// the image smaller in size. + /// + /// The filter accepts 8 bpp grayscale and 24 bpp color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// Shrink filter = new Shrink( Color.Black ); + /// // apply the filter + /// Bitmap newImage = filter.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + public class Shrink : BaseTransformationFilter + { + private Color colorToRemove = Color.FromArgb( 0, 0, 0 ); + // top-left coordinates of the object (calculated by CalculateNewImageSize()) + private int minX, minY; + + // format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Color to remove from boundaries. + /// + /// + public Color ColorToRemove + { + get { return colorToRemove; } + set { colorToRemove = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public Shrink( ) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Color to remove from boundaries. + /// + public Shrink( Color colorToRemove ) : this( ) + { + this.colorToRemove = colorToRemove; + } + + /// + /// Calculates new image size. + /// + /// + /// Source image data. + /// + /// New image size - size of the destination image. + /// + protected override System.Drawing.Size CalculateNewImageSize( UnmanagedImage sourceData ) + { + // get source image size + int width = sourceData.Width; + int height = sourceData.Height; + int offset = sourceData.Stride - + ( ( sourceData.PixelFormat == PixelFormat.Format8bppIndexed ) ? width : width * 3 ); + + // color to remove + byte r = colorToRemove.R; + byte g = colorToRemove.G; + byte b = colorToRemove.B; + + minX = width; + minY = height; + int maxX = 0; + int maxY = 0; + + // find rectangle which contains something except color to remove + unsafe + { + byte* src = (byte*) sourceData.ImageData.ToPointer( ); + + if ( sourceData.PixelFormat == PixelFormat.Format8bppIndexed ) + { + // grayscale + for ( int y = 0; y < height; y++ ) + { + for ( int x = 0; x < width; x++, src++ ) + { + if ( *src != g ) + { + if ( x < minX ) + minX = x; + if ( x > maxX ) + maxX = x; + if ( y < minY ) + minY = y; + if ( y > maxY ) + maxY = y; + } + } + src += offset; + } + } + else + { + // RGB + for ( int y = 0; y < height; y++ ) + { + for ( int x = 0; x < width; x++, src += 3 ) + { + if ( + ( src[RGB.R] != r ) || + ( src[RGB.G] != g ) || + ( src[RGB.B] != b ) ) + { + if ( x < minX ) + minX = x; + if ( x > maxX ) + maxX = x; + if ( y < minY ) + minY = y; + if ( y > maxY ) + maxY = y; + } + } + src += offset; + } + } + } + + // check + if ( ( minX == width ) && ( minY == height ) && ( maxX == 0 ) && ( maxY == 0 ) ) + { + minX = minY = 0; + } + + return new Size( maxX - minX + 1, maxY - minY + 1 ); + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData ) + { + // get destination image size + int newWidth = destinationData.Width; + int newHeight = destinationData.Height; + + int srcStride = sourceData.Stride; + int dstStride = destinationData.Stride; + int copySize = newWidth; + + // do the job + byte* src = (byte*) sourceData.ImageData.ToPointer( ); + byte* dst = (byte*) destinationData.ImageData.ToPointer( ); + + src += ( minY * srcStride ); + + if ( destinationData.PixelFormat == PixelFormat.Format8bppIndexed ) + { + src += minX; + } + else + { + src += minX * 3; + copySize *= 3; + } + + // copy image + for ( int y = 0; y < newHeight; y++ ) + { + AForge.SystemTools.CopyUnmanagedMemory( dst, src, copySize ); + dst += dstStride; + src += srcStride; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Transform/SimpleQuadrilateralTransformation.cs b/Sources/Accord.Imaging/AForge/Filters/Transform/SimpleQuadrilateralTransformation.cs new file mode 100644 index 0000000000..a824187ad --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Transform/SimpleQuadrilateralTransformation.cs @@ -0,0 +1,497 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2007-2010 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using AForge; + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Performs quadrilateral transformation of an area in the source image. + /// + /// + /// The class implements simple algorithm described by + /// Olivier Thill + /// for transforming quadrilateral area from a source image into rectangular image. + /// The idea of the algorithm is based on finding for each line of destination + /// rectangular image a corresponding line connecting "left" and "right" sides of + /// quadrilateral in a source image. Then the line is linearly transformed into the + /// line in destination image. + /// + /// Due to simplicity of the algorithm it does not do any correction for perspective. + /// + /// + /// To make sure the algorithm works correctly, it is preferred if the + /// "left-top" corner of the quadrilateral (screen coordinates system) is + /// specified first in the list of quadrilateral's corners. At least + /// user need to make sure that the "left" side (side connecting first and the last + /// corner) and the "right" side (side connecting second and third corners) are + /// not horizontal. + /// + /// Use to avoid the above mentioned limitations, + /// which is a more advanced quadrilateral transformation algorithms (although a bit more + /// computationally expensive). + /// + /// The image processing filter accepts 8 grayscale images and 24/32 bpp + /// color images for processing. + /// + /// Sample usage: + /// + /// // define quadrilateral's corners + /// List<IntPoint> corners = new List<IntPoint>( ); + /// corners.Add( new IntPoint( 99, 99 ) ); + /// corners.Add( new IntPoint( 156, 79 ) ); + /// corners.Add( new IntPoint( 184, 126 ) ); + /// corners.Add( new IntPoint( 122, 150 ) ); + /// // create filter + /// SimpleQuadrilateralTransformation filter = + /// new SimpleQuadrilateralTransformation( corners, 200, 200 ); + /// // apply the filter + /// Bitmap newImage = filter.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + public class SimpleQuadrilateralTransformation : BaseTransformationFilter + { + private bool automaticSizeCalculaton = true; + private bool useInterpolation = true; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + /// + /// See + /// documentation for additional information. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// New image width. + /// + protected int newWidth; + + /// + /// New image height. + /// + protected int newHeight; + + /// + /// Automatic calculation of destination image or not. + /// + /// + /// The property specifies how to calculate size of destination (transformed) + /// image. If the property is set to , then + /// and properties have effect and destination image's size is + /// specified by user. If the property is set to , then setting the above + /// mentioned properties does not have any effect, but destionation image's size is + /// automatically calculated from property - width and height + /// come from length of longest edges. + /// + /// + /// Default value is set to . + /// + /// + public bool AutomaticSizeCalculaton + { + get { return automaticSizeCalculaton; } + set + { + automaticSizeCalculaton = value; + if (value) + { + CalculateDestinationSize(); + } + } + } + + // Quadrilateral's corners in source image. + private List sourceQuadrilateral; + + /// + /// Quadrilateral's corners in source image. + /// + /// + /// The property specifies four corners of the quadrilateral area + /// in the source image to be transformed. + /// + /// See documentation to the + /// class itself for additional information. + /// + /// + public List SourceQuadrilateral + { + get { return sourceQuadrilateral; } + set + { + sourceQuadrilateral = value; + if (automaticSizeCalculaton) + { + CalculateDestinationSize(); + } + } + } + + /// + /// Width of the new transformed image. + /// + /// + /// The property defines width of the destination image, which gets + /// transformed quadrilateral image. + /// + /// Setting the property does not have any effect, if + /// property is set to . In this case destination image's width + /// is calculated automatically based on property. + /// + /// + public int NewWidth + { + get { return newWidth; } + set + { + if (!automaticSizeCalculaton) + { + newWidth = Math.Max(1, value); + } + } + } + + /// + /// Height of the new transformed image. + /// + /// + /// The property defines height of the destination image, which gets + /// transformed quadrilateral image. + /// + /// Setting the property does not have any effect, if + /// property is set to . In this case destination image's height + /// is calculated automatically based on property. + /// + /// + public int NewHeight + { + get { return newHeight; } + set + { + if (!automaticSizeCalculaton) + { + newHeight = Math.Max(1, value); + } + } + } + + /// + /// Specifies if bilinear interpolation should be used or not. + /// + /// + /// Default value is set to - interpolation + /// is used. + /// + /// + public bool UseInterpolation + { + get { return useInterpolation; } + set { useInterpolation = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public SimpleQuadrilateralTransformation() + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + formatTranslations[PixelFormat.Format32bppPArgb] = PixelFormat.Format32bppPArgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Corners of the source quadrilateral area. + /// Width of the new transformed image. + /// Height of the new transformed image. + /// + /// This constructor sets to + /// , which means that destination image will have width and + /// height as specified by user. + /// + public SimpleQuadrilateralTransformation(List sourceQuadrilateral, int newWidth, int newHeight) + : this() + { + this.automaticSizeCalculaton = false; + this.sourceQuadrilateral = sourceQuadrilateral; + this.newWidth = newWidth; + this.newHeight = newHeight; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Corners of the source quadrilateral area. + /// + /// This constructor sets to + /// , which means that destination image will have width and + /// height automatically calculated based on property. + /// + public SimpleQuadrilateralTransformation(List sourceQuadrilateral) + : this() + { + this.automaticSizeCalculaton = true; + this.sourceQuadrilateral = sourceQuadrilateral; + CalculateDestinationSize(); + } + + /// + /// Calculates new image size. + /// + /// + /// Source image data. + /// + /// New image size - size of the destination image. + /// + /// Source quadrilateral was not set. + /// + protected override System.Drawing.Size CalculateNewImageSize(UnmanagedImage sourceData) + { + if (sourceQuadrilateral == null) + throw new InvalidOperationException("Source quadrilateral was not set."); + + return new Size(newWidth, newHeight); + } + + // Calculates size of destination image + private void CalculateDestinationSize() + { + if (sourceQuadrilateral == null) + throw new InvalidOperationException("Source quadrilateral was not set."); + + newWidth = (int)Math.Max(sourceQuadrilateral[0].DistanceTo(sourceQuadrilateral[1]), + sourceQuadrilateral[2].DistanceTo(sourceQuadrilateral[3])); + newHeight = (int)Math.Max(sourceQuadrilateral[1].DistanceTo(sourceQuadrilateral[2]), + sourceQuadrilateral[3].DistanceTo(sourceQuadrilateral[0])); + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData) + { + // get source and destination images size + int srcWidth = sourceData.Width; + int srcHeight = sourceData.Height; + int dstWidth = destinationData.Width; + int dstHeight = destinationData.Height; + + int pixelSize = Image.GetPixelFormatSize(sourceData.PixelFormat) / 8; + int srcStride = sourceData.Stride; + int dstStride = destinationData.Stride; + + // find equations of four quadrilateral's edges ( f(x) = k*x + b ) + double kLeft, bLeft; + double kRight, bRight; + + /* + // top edge + if (sourceQuadrilateral[1].X == sourceQuadrilateral[0].X) + { + kTop = 0; + bTop = sourceQuadrilateral[1].X; + } + else + { + kTop = (double)(sourceQuadrilateral[1].Y - sourceQuadrilateral[0].Y) / + (sourceQuadrilateral[1].X - sourceQuadrilateral[0].X); + bTop = (double) sourceQuadrilateral[0].Y - kTop * sourceQuadrilateral[0].X; + } + + // bottom edge + if (sourceQuadrilateral[2].X == sourceQuadrilateral[3].X) + { + kBottom = 0; + bBottom = sourceQuadrilateral[2].X; + } + else + { + kBottom = (double)(sourceQuadrilateral[2].Y - sourceQuadrilateral[3].Y) / + (sourceQuadrilateral[2].X - sourceQuadrilateral[3].X); + bBottom = (double) sourceQuadrilateral[3].Y - kBottom * sourceQuadrilateral[3].X; + } + */ + + // left edge + if (sourceQuadrilateral[3].X == sourceQuadrilateral[0].X) + { + kLeft = 0; + bLeft = sourceQuadrilateral[3].X; + } + else + { + kLeft = (double)(sourceQuadrilateral[3].Y - sourceQuadrilateral[0].Y) / + (sourceQuadrilateral[3].X - sourceQuadrilateral[0].X); + bLeft = (double)sourceQuadrilateral[0].Y - kLeft * sourceQuadrilateral[0].X; + } + + // right edge + if (sourceQuadrilateral[2].X == sourceQuadrilateral[1].X) + { + kRight = 0; + bRight = sourceQuadrilateral[2].X; + } + else + { + kRight = (double)(sourceQuadrilateral[2].Y - sourceQuadrilateral[1].Y) / + (sourceQuadrilateral[2].X - sourceQuadrilateral[1].X); + bRight = (double)sourceQuadrilateral[1].Y - kRight * sourceQuadrilateral[1].X; + } + + // some precalculated values + double leftFactor = (double)(sourceQuadrilateral[3].Y - sourceQuadrilateral[0].Y) / dstHeight; + double rightFactor = (double)(sourceQuadrilateral[2].Y - sourceQuadrilateral[1].Y) / dstHeight; + + int srcY0 = sourceQuadrilateral[0].Y; + int srcY1 = sourceQuadrilateral[1].Y; + + // do the job + byte* baseSrc = (byte*)sourceData.ImageData.ToPointer(); + byte* baseDst = (byte*)destinationData.ImageData.ToPointer(); + + // source width and height decreased by 1 + int ymax = srcHeight - 1; + int xmax = srcWidth - 1; + + // coordinates of source points + double dx1, dy1, dx2, dy2; + int sx1, sy1, sx2, sy2; + + // temporary pointers + byte* p1, p2, p3, p4, p; + + // for each line + for (int y = 0; y < dstHeight; y++) + { + byte* dst = baseDst + dstStride * y; + + // find corresponding Y on the left edge of the quadrilateral + double yHorizLeft = leftFactor * y + srcY0; + // find corresponding X on the left edge of the quadrilateral + double xHorizLeft = (kLeft == 0) ? bLeft : (yHorizLeft - bLeft) / kLeft; + + // find corresponding Y on the right edge of the quadrilateral + double yHorizRight = rightFactor * y + srcY1; + // find corresponding X on the left edge of the quadrilateral + double xHorizRight = (kRight == 0) ? bRight : (yHorizRight - bRight) / kRight; + + // find equation of the line joining points on the left and right edges + double kHoriz, bHoriz; + + if (xHorizLeft == xHorizRight) + { + kHoriz = 0; + bHoriz = xHorizRight; + } + else + { + kHoriz = (yHorizRight - yHorizLeft) / (xHorizRight - xHorizLeft); + bHoriz = yHorizLeft - kHoriz * xHorizLeft; + } + + double horizFactor = (xHorizRight - xHorizLeft) / dstWidth; + + if (!useInterpolation) + { + for (int x = 0; x < dstWidth; x++) + { + double xs = horizFactor * x + xHorizLeft; + double ys = kHoriz * xs + bHoriz; + + if ((xs >= 0) && (ys >= 0) && (xs < srcWidth) && (ys < srcHeight)) + { + // get pointer to the pixel in the source image + p = baseSrc + ((int)ys * srcStride + (int)xs * pixelSize); + // copy pixel's values + for (int i = 0; i < pixelSize; i++, dst++, p++) + { + *dst = *p; + } + } + else + { + dst += pixelSize; + } + } + } + else + { + for (int x = 0; x < dstWidth; x++) + { + double xs = horizFactor * x + xHorizLeft; + double ys = kHoriz * xs + bHoriz; + + if ((xs >= 0) && (ys >= 0) && (xs < srcWidth) && (ys < srcHeight)) + { + sx1 = (int)xs; + sx2 = (sx1 == xmax) ? sx1 : sx1 + 1; + dx1 = xs - sx1; + dx2 = 1.0 - dx1; + + sy1 = (int)ys; + sy2 = (sy1 == ymax) ? sy1 : sy1 + 1; + dy1 = ys - sy1; + dy2 = 1.0 - dy1; + + // get four points + p1 = p2 = baseSrc + sy1 * srcStride; + p1 += sx1 * pixelSize; + p2 += sx2 * pixelSize; + + p3 = p4 = baseSrc + sy2 * srcStride; + p3 += sx1 * pixelSize; + p4 += sx2 * pixelSize; + + // interpolate using 4 points + for (int i = 0; i < pixelSize; i++, dst++, p1++, p2++, p3++, p4++) + { + *dst = (byte)( + dy2 * (dx2 * (*p1) + dx1 * (*p2)) + + dy1 * (dx2 * (*p3) + dx1 * (*p4))); + } + } + else + { + dst += pixelSize; + } + } + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Transform/TransformFromPolar.cs b/Sources/Accord.Imaging/AForge/Filters/Transform/TransformFromPolar.cs new file mode 100644 index 0000000000..c1183dd52 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Transform/TransformFromPolar.cs @@ -0,0 +1,345 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2010 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Transform polar image into rectangle. + /// + /// + /// The image processing routine is opposite transformation to the one done by + /// routine, i.e. transformation from polar image into rectangle. The produced effect is similar to GIMP's + /// "Polar Coordinates" distortion filter (or its equivalent in Photoshop). + /// + /// The filter accepts 8 bpp grayscale and 24/32 bpp color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// TransformFromPolar filter = new TransformFromPolar( ); + /// filter.OffsetAngle = 0; + /// filter.CirlceDepth = 1; + /// filter.UseOriginalImageSize = false; + /// filter.NewSize = new Size( 360, 120 ); + /// // apply the filter + /// Bitmap newImage = filter.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + public class TransformFromPolar : BaseTransformationFilter + { + private const double Pi2 = Math.PI * 2; + private const double PiHalf = Math.PI / 2; + + private double circleDepth = 1.0; + + /// + /// Circularity coefficient of the mapping, [0, 1]. + /// + /// + /// The property specifies circularity coefficient of the mapping to be done. + /// If the coefficient is set to 1, then destination image will be produced by mapping + /// ideal circle from the source image, which is placed in source image's centre and its + /// radius equals to the minimum distance from centre to the image’s edge. If the coefficient + /// is set to 0, then the mapping will use entire area of the source image (circle will + /// be extended into direction of edges). Changing the property from 0 to 1 user may balance + /// circularity of the produced output. + /// + /// Default value is set to 1. + /// + /// + public double CirlceDepth + { + get { return circleDepth; } + set { circleDepth = Math.Max(0, Math.Min(1, value)); } + } + + + private double offsetAngle = 0; + + /// + /// Offset angle used to shift mapping, [-360, 360] degrees. + /// + /// + /// The property specifies offset angle, which can be used to shift + /// mapping in clockwise direction. For example, if user sets this property to 30, then + /// start of polar mapping is shifted by 30 degrees in clockwise direction. + /// + /// Default value is set to 0. + /// + /// + public double OffsetAngle + { + get { return offsetAngle; } + set { offsetAngle = Math.Max(-360, Math.Min(360, value)); } + } + + private bool mapBackwards = false; + + /// + /// Specifies direction of mapping. + /// + /// + /// The property specifies direction of mapping source image. If the + /// property is set to , the image is mapped in clockwise direction; + /// otherwise in counter clockwise direction. + /// + /// Default value is set to . + /// + /// + public bool MapBackwards + { + get { return mapBackwards; } + set { mapBackwards = value; } + } + + private bool mapFromTop = true; + + /// + /// Specifies if centre of the source image should to top or bottom of the result image. + /// + /// + /// The property specifies position of the source image's centre in the destination image. + /// If the property is set to , then it goes to the top of the result image; + /// otherwise it goes to the bottom. + /// + /// Default value is set to . + /// + /// + public bool MapFromTop + { + get { return mapFromTop; } + set { mapFromTop = value; } + } + + private Size newSize = new Size(200, 200); + private bool useOriginalImageSize = true; + + /// + /// Size of destination image. + /// + /// + /// The property specifies size of result image produced by this image + /// processing routine in the case if property + /// is set to . + /// + /// Both width and height must be in the [1, 10000] range. + /// + /// Default value is set to 200 x 200. + /// + /// + public Size NewSize + { + get { return newSize; } + set + { + newSize = new Size( + Math.Max(1, Math.Min(10000, value.Width)), + Math.Max(1, Math.Min(10000, value.Height))); + } + } + + /// + /// Use source image size for destination or not. + /// + /// + /// The property specifies if the image processing routine should create destination + /// image of the same size as original image or of the size specified by + /// property. + /// + /// Default value is set to . + /// + /// + public bool UseOriginalImageSize + { + get { return useOriginalImageSize; } + set { useOriginalImageSize = value; } + } + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + /// + /// See + /// documentation for additional information. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public TransformFromPolar() + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + formatTranslations[PixelFormat.Format32bppPArgb] = PixelFormat.Format32bppPArgb; + } + + /// + /// Calculates new image size. + /// + /// + /// Source image data. + /// + /// New image size - size of the destination image. + /// + protected override System.Drawing.Size CalculateNewImageSize(UnmanagedImage sourceData) + { + return (useOriginalImageSize) ? new Size(sourceData.Width, sourceData.Height) : newSize; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData) + { + int pixelSize = Bitmap.GetPixelFormatSize(destinationData.PixelFormat) / 8; + + // get source image size + int width = sourceData.Width; + int height = sourceData.Height; + int widthM1 = width - 1; + int heightM1 = height - 1; + + // get destination image size + int newWidth = destinationData.Width; + int newHeight = destinationData.Height; + int newHeightM1 = newHeight - 1; + + // invert circle depth + double circleDisform = 1 - circleDepth; + + // get position of center pixel + double cx = (double)widthM1 / 2; + double cy = (double)heightM1 / 2; + double radius = (cx < cy) ? cx : cy; + radius -= radius * circleDisform; + + // angle of the diagonal + double diagonalAngle = Math.Atan2(cy, cx); + + // offset angle in radians + double offsetAngleR = ((mapBackwards) ? offsetAngle : -offsetAngle) / 180 * Math.PI + PiHalf; + + // do the job + byte* baseSrc = (byte*)sourceData.ImageData.ToPointer(); + byte* dst = (byte*)destinationData.ImageData.ToPointer(); + + int srcStride = sourceData.Stride; + int dstOffset = destinationData.Stride - newWidth * pixelSize; + + // coordinates of source points + int sx1, sy1, sx2, sy2; + double dx1, dy1, dx2, dy2; + + // temporary pointers + byte* p1, p2, p3, p4; + + // precalculate Sin/Cos values and distances from center to edge in the source image + double[] angleCos = new double[newWidth]; + double[] angleSin = new double[newWidth]; + double[] maxDistance = new double[newWidth]; + + for (int x = 0; x < newWidth; x++) + { + double angle = -Pi2 * x / newWidth + offsetAngleR; + + angleCos[x] = Math.Cos(angle); + angleSin[x] = Math.Sin(angle); + + // calculate minimum angle between X axis and the + // line with the above calculated angle + double oxAngle = ((angle > 0) ? angle : -angle) % Math.PI; + if (oxAngle > PiHalf) + { + oxAngle = Math.PI - oxAngle; + } + + // calculate maximum distance from center for this angle - distance to image's edge + maxDistance[x] = circleDisform * ((oxAngle > diagonalAngle) ? (cy / Math.Sin(oxAngle)) : (cx / Math.Cos(oxAngle))); + } + + for (int y = 0; y < newHeight; y++) + { + double yPart = (double)y / newHeightM1; + + if (!mapFromTop) + { + yPart = 1 - yPart; + } + + for (int x = 0; x < newWidth; x++) + { + // calculate maximum allowed distance within wich we need to map Y axis of the destination image + double maxAllowedDistance = radius + maxDistance[x]; + + // source pixel's distance from the center of the source image + double distance = yPart * maxAllowedDistance; + + // calculate pixel coordinates in the source image + double sx = cx + distance * ((mapBackwards) ? -angleCos[x] : angleCos[x]); + double sy = cy - distance * angleSin[x]; + + sx1 = (int)sx; + sy1 = (int)sy; + + sx2 = (sx1 == widthM1) ? sx1 : sx1 + 1; + dx1 = sx - sx1; + dx2 = 1.0 - dx1; + + sy2 = (sy1 == heightM1) ? sy1 : sy1 + 1; + dy1 = sy - sy1; + dy2 = 1.0 - dy1; + + // get four points + p1 = p2 = baseSrc + sy1 * srcStride; + p1 += sx1 * pixelSize; + p2 += sx2 * pixelSize; + + p3 = p4 = baseSrc + sy2 * srcStride; + p3 += sx1 * pixelSize; + p4 += sx2 * pixelSize; + + // interpolate using 4 points + for (int i = 0; i < pixelSize; i++, dst++, p1++, p2++, p3++, p4++) + { + *dst = (byte)( + dy2 * (dx2 * (*p1) + dx1 * (*p2)) + + dy1 * (dx2 * (*p3) + dx1 * (*p4))); + } + } + dst += dstOffset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/Transform/TransformToPolar.cs b/Sources/Accord.Imaging/AForge/Filters/Transform/TransformToPolar.cs new file mode 100644 index 0000000000..eec290e8c --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/Transform/TransformToPolar.cs @@ -0,0 +1,406 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2010 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Transform rectangle image into circle (to polar coordinates). + /// + /// + /// The image processing routine does transformation of the source image into + /// circle (polar transformation). The produced effect is similar to GIMP's "Polar Coordinates" + /// distortion filter (or its equivalent in Photoshop). + /// + /// + /// The filter accepts 8 bpp grayscale and 24/32 bpp color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// TransformToPolar filter = new TransformToPolar( ); + /// filter.OffsetAngle = 0; + /// filter.CirlceDepth = 1; + /// filter.UseOriginalImageSize = false; + /// filter.NewSize = new Size( 200, 200 ); + /// // apply the filter + /// Bitmap newImage = filter.Apply( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + public class TransformToPolar : BaseTransformationFilter + { + private const double Pi2 = Math.PI * 2; + private const double PiHalf = Math.PI / 2; + + private double circleDepth = 1.0; + + /// + /// Circularity coefficient of the mapping, [0, 1]. + /// + /// + /// The property specifies circularity coefficient of the mapping to be done. + /// If the coefficient is set to 1, then the mapping will produce ideal circle. If the coefficient + /// is set to 0, then the mapping will occupy entire area of the destination image (circle will + /// be extended into direction of edges). Changing the property from 0 to 1 user may balance + /// circularity of the produced output. + /// + /// + /// Default value is set to 1. + /// + /// + public double CirlceDepth + { + get { return circleDepth; } + set { circleDepth = Math.Max( 0, Math.Min( 1, value ) ); } + } + + private double offsetAngle = 0; + + /// + /// Offset angle used to shift mapping, [-360, 360] degrees. + /// + /// + /// The property specifies offset angle, which can be used to shift + /// mapping in counter clockwise direction. For example, if user sets this property to 30, then + /// start of polar mapping is shifted by 30 degrees in counter clockwise direction. + /// + /// Default value is set to 0. + /// + /// + public double OffsetAngle + { + get { return offsetAngle; } + set { offsetAngle = Math.Max( -360, Math.Min( 360, value ) ); } + } + + private bool mapBackwards = false; + + /// + /// Specifies direction of mapping. + /// + /// + /// The property specifies direction of mapping source image's X axis. If the + /// property is set to , the image is mapped in clockwise direction; + /// otherwise in counter clockwise direction. + /// + /// Default value is set to . + /// + /// + public bool MapBackwards + { + get { return mapBackwards; } + set { mapBackwards = value; } + } + + private bool mapFromTop = true; + + /// + /// Specifies if top of the source image should go to center or edge of the result image. + /// + /// + /// The property specifies position of the source image's top line in the destination + /// image. If the property is set to , then it goes to the center of the result image; + /// otherwise it goes to the edge. + /// + /// Default value is set to . + /// + /// + public bool MapFromTop + { + get { return mapFromTop; } + set { mapFromTop = value; } + } + + private Color fillColor = Color.White; + + /// + /// Fill color to use for unprocessed areas. + /// + /// + /// The property specifies fill color, which is used to fill unprocessed areas. + /// In the case if is greater than 0, then there will be some areas on + /// the image's edge, which are not filled by the produced "circular" image, but are filled by + /// the specified color. + /// + /// + /// Default value is set to . + /// + /// + public Color FillColor + { + get { return fillColor; } + set { fillColor = value; } + } + + private Size newSize = new Size( 200, 200 ); + private bool useOriginalImageSize = true; + + /// + /// Size of destination image. + /// + /// + /// The property specifies size of result image produced by this image + /// processing routine in the case if property + /// is set to . + /// + /// Both width and height must be in the [1, 10000] range. + /// + /// Default value is set to 200 x 200. + /// + /// + public Size NewSize + { + get { return newSize; } + set + { + newSize = new Size( + Math.Max( 1, Math.Min( 10000, value.Width ) ), + Math.Max( 1, Math.Min( 10000, value.Height ) ) ); + } + } + + /// + /// Use source image size for destination or not. + /// + /// + /// The property specifies if the image processing routine should create destination + /// image of the same size as original image or of the size specified by + /// property. + /// + /// Default value is set to . + /// + /// + public bool UseOriginalImageSize + { + get { return useOriginalImageSize; } + set { useOriginalImageSize = value; } + } + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + /// + /// See + /// documentation for additional information. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public TransformToPolar( ) + { + formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + formatTranslations[PixelFormat.Format32bppPArgb] = PixelFormat.Format32bppPArgb; + } + + /// + /// Calculates new image size. + /// + /// + /// Source image data. + /// + /// New image size - size of the destination image. + /// + protected override System.Drawing.Size CalculateNewImageSize( UnmanagedImage sourceData ) + { + return ( useOriginalImageSize ) ? new Size( sourceData.Width, sourceData.Height ) : newSize; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData ) + { + int pixelSize = Bitmap.GetPixelFormatSize( destinationData.PixelFormat ) / 8; + + // get source image size + int width = sourceData.Width; + int height = sourceData.Height; + int widthM1 = width - 1; + int heightM1 = height - 1; + + // get destination image size + int newWidth = destinationData.Width; + int newHeight = destinationData.Height; + + // invert cirlce depth + double circleDisform = 1 - circleDepth; + + // get position of center pixel + double cx = (double) ( newWidth - 1 ) / 2; + double cy = (double) ( newHeight - 1 ) / 2; + double radius = ( cx < cy ) ? cx : cy; + radius -= radius * circleDisform; + + // angle of the diagonal + double diagonalAngle = Math.Atan2( cy, cx ); + + // offset angle in radians + double offsetAngleR = offsetAngle / 180 * Math.PI; + if ( offsetAngleR < 0 ) + { + offsetAngleR = Pi2 - offsetAngleR; + } + // add extra offset to make sure rotation starts from Y axis and Pi*2 to + // make sure any negative angle will get positive + offsetAngleR += PiHalf + Pi2; + + // do the job + byte* baseSrc = (byte*) sourceData.ImageData.ToPointer( ); + byte* dst = (byte*) destinationData.ImageData.ToPointer( ); + + int srcStride = sourceData.Stride; + int dstOffset = destinationData.Stride - newWidth * pixelSize; + + // coordinates of source points + int sx1, sy1, sx2, sy2; + double dx1, dy1, dx2, dy2; + + // temporary pointers + byte* p1, p2, p3, p4; + + byte fillR = fillColor.R; + byte fillB = fillColor.B; + byte fillG = fillColor.G; + byte fillA = fillColor.A; + byte fillGrey = (byte) ( 0.2125 * fillR + 0.7154 * fillG + 0.0721 * fillB ); + + for ( int y = 0; y < newHeight; y++ ) + { + double dy = y - cy; + double dydy = dy * dy; + + for ( int x = 0; x < newWidth; x++ ) + { + double dx = x - cx; + // distance from the center + double distance = Math.Sqrt( dx * dx + dydy ); + // angle of the line connecting center and the current pixel + double angle = Math.Atan2( dy, dx ); + + // calculate minimum angle between X axis and the + // line connecting center and the current pixel + double oxAngle = ( angle > 0 ) ? angle : -angle; + if ( oxAngle > PiHalf ) + { + oxAngle = Math.PI - oxAngle; + } + + // calculate maximm distance from center for this angle - distance to image's edge + double maxDistance = ( oxAngle > diagonalAngle ) ? ( cy / Math.Sin( oxAngle ) ) : ( cx / Math.Cos( oxAngle ) ); + + // calculate maximum allowed distance within wich we need to map Y axis of the source image + double maxAllowedDistance = radius + maxDistance * circleDisform; + + if ( distance < maxAllowedDistance + 1 ) + { + // add angle offset and make sure it is in the [0, 2PI) range + angle += offsetAngleR; + angle = angle % Pi2; + + // calculate pixel coordinates in the source image + double sy = ( distance / maxAllowedDistance ) * heightM1; + + if ( sy > heightM1 ) + { + sy = heightM1; + } + + if ( !mapFromTop ) + { + sy = heightM1 - sy; + } + + double sx = ( angle / Pi2 ) * widthM1; + + if ( mapBackwards ) + { + sx = widthM1 - sx; + } + + sx1 = (int) sx; + sx2 = ( sx1 == widthM1 ) ? sx1 : sx1 + 1; + dx1 = sx - sx1; + dx2 = 1.0 - dx1; + + sy1 = (int) sy; + sy2 = ( sy1 == heightM1 ) ? sy1 : sy1 + 1; + dy1 = sy - sy1; + dy2 = 1.0 - dy1; + + // get four points + p1 = p2 = baseSrc + sy1 * srcStride; + p1 += sx1 * pixelSize; + p2 += sx2 * pixelSize; + + p3 = p4 = baseSrc + sy2 * srcStride; + p3 += sx1 * pixelSize; + p4 += sx2 * pixelSize; + + // interpolate using 4 points + for ( int i = 0; i < pixelSize; i++, dst++, p1++, p2++, p3++, p4++ ) + { + *dst = (byte) ( + dy2 * ( dx2 * ( *p1 ) + dx1 * ( *p2 ) ) + + dy1 * ( dx2 * ( *p3 ) + dx1 * ( *p4 ) ) ); + } + } + else + { + // fill unprocessed pixel with default color + if ( pixelSize == 1 ) + { + *dst = fillGrey; + } + else + { + dst[RGB.R] = fillR; + dst[RGB.G] = fillG; + dst[RGB.B] = fillB; + + if ( pixelSize > 3 ) + { + dst[RGB.A] = fillA; + } + } + + dst += pixelSize; + } + } + dst += dstOffset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/YCbCr Filters/YCbCrExtractChannel.cs b/Sources/Accord.Imaging/AForge/Filters/YCbCr Filters/YCbCrExtractChannel.cs new file mode 100644 index 0000000000..93dd80e35 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/YCbCr Filters/YCbCrExtractChannel.cs @@ -0,0 +1,160 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Extract YCbCr channel from image. + /// + /// + /// The filter extracts specified YCbCr channel of color image and returns + /// it in the form of grayscale image. + /// + /// The filter accepts 24 and 32 bpp color images and produces + /// 8 bpp grayscale images. + /// + /// Sample usage: + /// + /// // create filter + /// YCbCrExtractChannel filter = new YCbCrExtractChannel( YCbCr.CrIndex ); + /// // apply the filter + /// Bitmap crChannel = filter.Apply( image ); + /// + /// + /// + /// + /// + public class YCbCrExtractChannel : BaseFilter + { + private short channel = YCbCr.YIndex; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// YCbCr channel to extract. + /// + /// + /// Default value is set to (Y channel). + /// + /// Invalid channel was specified. + /// + public short Channel + { + get { return channel; } + set + { + if ( + (value != YCbCr.YIndex) && + (value != YCbCr.CbIndex) && + (value != YCbCr.CrIndex) + ) + { + throw new ArgumentException("Invalid channel was specified."); + } + channel = value; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public YCbCrExtractChannel() + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format8bppIndexed; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format8bppIndexed; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// YCbCr channel to extract. + /// + public YCbCrExtractChannel(short channel) + : this() + { + this.Channel = channel; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Destination image data. + /// + protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData) + { + int pixelSize = Image.GetPixelFormatSize(sourceData.PixelFormat) / 8; + + // get width and height + int width = sourceData.Width; + int height = sourceData.Height; + + int srcOffset = sourceData.Stride - width * pixelSize; + int dstOffset = destinationData.Stride - width; + RGB rgb = new RGB(); + YCbCr ycbcr = new YCbCr(); + + // do the job + byte* src = (byte*)sourceData.ImageData.ToPointer(); + byte* dst = (byte*)destinationData.ImageData.ToPointer(); + byte v = 0; + + // for each row + for (int y = 0; y < height; y++) + { + // for each pixel + for (int x = 0; x < width; x++, src += pixelSize, dst++) + { + rgb.Red = src[RGB.R]; + rgb.Green = src[RGB.G]; + rgb.Blue = src[RGB.B]; + + // convert to YCbCr + AForge.Imaging.YCbCr.FromRGB(rgb, ycbcr); + + switch (channel) + { + case YCbCr.YIndex: + v = (byte)(ycbcr.Y * 255); + break; + + case YCbCr.CbIndex: + v = (byte)((ycbcr.Cb + 0.5) * 255); + break; + + case YCbCr.CrIndex: + v = (byte)((ycbcr.Cr + 0.5) * 255); + break; + } + + *dst = v; + } + src += srcOffset; + dst += dstOffset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/YCbCr Filters/YCbCrFiltering.cs b/Sources/Accord.Imaging/AForge/Filters/YCbCr Filters/YCbCrFiltering.cs new file mode 100644 index 0000000000..4351d61ad --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/YCbCr Filters/YCbCrFiltering.cs @@ -0,0 +1,292 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + using AForge; + + /// + /// Color filtering in YCbCr color space. + /// + /// + /// The filter operates in YCbCr color space and filters + /// pixels, which color is inside/outside of the specified YCbCr range - + /// it keeps pixels with colors inside/outside of the specified range and fills the + /// rest with specified color. + /// + /// The filter accepts 24 and 32 bpp color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// YCbCrFiltering filter = new YCbCrFiltering( ); + /// // set color ranges to keep + /// filter.Cb = new Range( -0.2f, 0.0f ); + /// filter.Cr = new Range( 0.26f, 0.5f ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + public class YCbCrFiltering : BaseInPlacePartialFilter + { + private Range yRange = new Range(0.0f, 1.0f); + private Range cbRange = new Range(-0.5f, 0.5f); + private Range crRange = new Range(-0.5f, 0.5f); + + private float fillY = 0.0f; + private float fillCb = 0.0f; + private float fillCr = 0.0f; + private bool fillOutsideRange = true; + + private bool updateY = true; + private bool updateCb = true; + private bool updateCr = true; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + #region Public properties + + /// + /// Range of Y component, [0, 1]. + /// + /// + public Range Y + { + get { return yRange; } + set { yRange = value; } + } + + /// + /// Range of Cb component, [-0.5, 0.5]. + /// + /// + public Range Cb + { + get { return cbRange; } + set { cbRange = value; } + } + + /// + /// Range of Cr component, [-0.5, 0.5]. + /// + /// + public Range Cr + { + get { return crRange; } + set { crRange = value; } + } + + /// + /// Fill color used to fill filtered pixels. + /// + public YCbCr FillColor + { + get { return new YCbCr(fillY, fillCb, fillCr); } + set + { + fillY = value.Y; + fillCb = value.Cb; + fillCr = value.Cr; + } + } + + /// + /// Determines, if pixels should be filled inside or outside specified + /// color range. + /// + /// + /// Default value is set to , which means + /// the filter removes colors outside of the specified range. + /// + public bool FillOutsideRange + { + get { return fillOutsideRange; } + set { fillOutsideRange = value; } + } + + /// + /// Determines, if Y value of filtered pixels should be updated. + /// + /// + /// The property specifies if Y channel of filtered pixels should be + /// updated with value from fill color or not. + /// + /// Default value is set to . + /// + public bool UpdateY + { + get { return updateY; } + set { updateY = value; } + } + + /// + /// Determines, if Cb value of filtered pixels should be updated. + /// + /// + /// The property specifies if Cb channel of filtered pixels should be + /// updated with value from fill color or not. + /// + /// Default value is set to . + /// + public bool UpdateCb + { + get { return updateCb; } + set { updateCb = value; } + } + + /// + /// Determines, if Cr value of filtered pixels should be updated. + /// + /// + /// The property specifies if Cr channel of filtered pixels should be + /// updated with value from fill color or not. + /// + /// Default value is set to . + /// + public bool UpdateCr + { + get { return updateCr; } + set { updateCr = value; } + } + + #endregion + + + /// + /// Initializes a new instance of the class. + /// + public YCbCrFiltering() + { + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Range of Y component. + /// Range of Cb component. + /// Range of Cr component. + /// + public YCbCrFiltering(Range yRange, Range cbRange, Range crRange) : + this() + { + this.yRange = yRange; + this.cbRange = cbRange; + this.crRange = crRange; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter(UnmanagedImage image, Rectangle rect) + { + // get pixel size + int pixelSize = (image.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4; + + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + int offset = image.Stride - rect.Width * pixelSize; + + RGB rgb = new RGB(); + YCbCr ycbcr = new YCbCr(); + + bool updated; + + // do the job + byte* ptr = (byte*)image.ImageData.ToPointer(); + + // allign pointer to the first pixel to process + ptr += (startY * image.Stride + startX * pixelSize); + + // for each row + for (int y = startY; y < stopY; y++) + { + // for each pixel + for (int x = startX; x < stopX; x++, ptr += pixelSize) + { + updated = false; + rgb.Red = ptr[RGB.R]; + rgb.Green = ptr[RGB.G]; + rgb.Blue = ptr[RGB.B]; + + // convert to YCbCr + AForge.Imaging.YCbCr.FromRGB(rgb, ycbcr); + + // check YCbCr values + if ( + (ycbcr.Y >= yRange.Min) && (ycbcr.Y <= yRange.Max) && + (ycbcr.Cb >= cbRange.Min) && (ycbcr.Cb <= cbRange.Max) && + (ycbcr.Cr >= crRange.Min) && (ycbcr.Cr <= crRange.Max) + ) + { + if (!fillOutsideRange) + { + if (updateY) ycbcr.Y = fillY; + if (updateCb) ycbcr.Cb = fillCb; + if (updateCr) ycbcr.Cr = fillCr; + + updated = true; + } + } + else + { + if (fillOutsideRange) + { + if (updateY) ycbcr.Y = fillY; + if (updateCb) ycbcr.Cb = fillCb; + if (updateCr) ycbcr.Cr = fillCr; + + updated = true; + } + } + + if (updated) + { + // convert back to RGB + AForge.Imaging.YCbCr.ToRGB(ycbcr, rgb); + + ptr[RGB.R] = rgb.Red; + ptr[RGB.G] = rgb.Green; + ptr[RGB.B] = rgb.Blue; + } + } + ptr += offset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/YCbCr Filters/YCbCrLinear.cs b/Sources/Accord.Imaging/AForge/Filters/YCbCr Filters/YCbCrLinear.cs new file mode 100644 index 0000000000..facd4af17 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/YCbCr Filters/YCbCrLinear.cs @@ -0,0 +1,251 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + using AForge; + + /// + /// Linear correction of YCbCr channels. + /// + /// + /// The filter operates in YCbCr color space and provides + /// with the facility of linear correction of its channels - mapping specified channels' + /// input ranges to specified output ranges. + /// + /// The filter accepts 24 and 32 bpp color images for processing. + /// + /// Sample usage: + /// + /// // create filter + /// YCbCrLinear filter = new YCbCrLinear( ); + /// // configure the filter + /// filter.InCb = new Range( -0.276f, 0.163f ); + /// filter.InCr = new Range( -0.202f, 0.500f ); + /// // apply the filter + /// filter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + /// + public class YCbCrLinear : BaseInPlacePartialFilter + { + private Range inY = new Range( 0.0f, 1.0f ); + private Range inCb = new Range( -0.5f, 0.5f ); + private Range inCr = new Range( -0.5f, 0.5f ); + + private Range outY = new Range( 0.0f, 1.0f ); + private Range outCb = new Range( -0.5f, 0.5f ); + private Range outCr = new Range( -0.5f, 0.5f ); + + #region Public Propertis + + /// + /// Y component's input range. + /// + /// + /// Y component is measured in the range of [0, 1]. + /// + public Range InY + { + get { return inY; } + set { inY = value; } + } + + /// + /// Cb component's input range. + /// + /// + /// Cb component is measured in the range of [-0.5, 0.5]. + /// + public Range InCb + { + get { return inCb; } + set { inCb = value; } + } + + /// + /// Cr component's input range. + /// + /// + /// Cr component is measured in the range of [-0.5, 0.5]. + /// + public Range InCr + { + get { return inCr; } + set { inCr = value; } + } + + /// + /// Y component's output range. + /// + /// + /// Y component is measured in the range of [0, 1]. + /// + public Range OutY + { + get { return outY; } + set { outY = value; } + } + + /// + /// Cb component's output range. + /// + /// + /// Cb component is measured in the range of [-0.5, 0.5]. + /// + public Range OutCb + { + get { return outCb; } + set { outCb = value; } + } + + /// + /// Cr component's output range. + /// + /// + /// Cr component is measured in the range of [-0.5, 0.5]. + /// + public Range OutCr + { + get { return outCr; } + set { outCr = value; } + } + + #endregion + + // format translation dictionary + private Dictionary formatTranslations = new Dictionary( ); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public YCbCrLinear( ) + { + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) + { + int pixelSize = Image.GetPixelFormatSize( image.PixelFormat ) / 8; + + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + int offset = image.Stride - rect.Width * pixelSize; + + RGB rgb = new RGB( ); + YCbCr ycbcr = new YCbCr( ); + + float ky = 0, by = 0; + float kcb = 0, bcb = 0; + float kcr = 0, bcr = 0; + + // Y line parameters + if ( inY.Max != inY.Min ) + { + ky = ( outY.Max - outY.Min ) / ( inY.Max - inY.Min ); + by = outY.Min - ky * inY.Min; + } + // Cb line parameters + if ( inCb.Max != inCb.Min ) + { + kcb = ( outCb.Max - outCb.Min ) / ( inCb.Max - inCb.Min ); + bcb = outCb.Min - kcb * inCb.Min; + } + // Cr line parameters + if ( inCr.Max != inCr.Min ) + { + kcr = ( outCr.Max - outCr.Min ) / ( inCr.Max - inCr.Min ); + bcr = outCr.Min - kcr * inCr.Min; + } + + // do the job + byte* ptr = (byte*) image.ImageData.ToPointer( ); + + // allign pointer to the first pixel to process + ptr += ( startY * image.Stride + startX * pixelSize ); + + // for each row + for ( int y = startY; y < stopY; y++ ) + { + // for each pixel + for ( int x = startX; x < stopX; x++, ptr += pixelSize ) + { + rgb.Red = ptr[RGB.R]; + rgb.Green = ptr[RGB.G]; + rgb.Blue = ptr[RGB.B]; + + // convert to YCbCr + AForge.Imaging.YCbCr.FromRGB( rgb, ycbcr ); + + // correct Y + if ( ycbcr.Y >= inY.Max ) + ycbcr.Y = outY.Max; + else if ( ycbcr.Y <= inY.Min ) + ycbcr.Y = outY.Min; + else + ycbcr.Y = ky * ycbcr.Y + by; + + // correct Cb + if ( ycbcr.Cb >= inCb.Max ) + ycbcr.Cb = outCb.Max; + else if ( ycbcr.Cb <= inCb.Min ) + ycbcr.Cb = outCb.Min; + else + ycbcr.Cb = kcb * ycbcr.Cb + bcb; + + // correct Cr + if ( ycbcr.Cr >= inCr.Max ) + ycbcr.Cr = outCr.Max; + else if ( ycbcr.Cr <= inCr.Min ) + ycbcr.Cr = outCr.Min; + else + ycbcr.Cr = kcr * ycbcr.Cr + bcr; + + // convert back to RGB + AForge.Imaging.YCbCr.ToRGB( ycbcr, rgb ); + + ptr[RGB.R] = rgb.Red; + ptr[RGB.G] = rgb.Green; + ptr[RGB.B] = rgb.Blue; + } + ptr += offset; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Filters/YCbCr Filters/YCbCrReplaceChannel.cs b/Sources/Accord.Imaging/AForge/Filters/YCbCr Filters/YCbCrReplaceChannel.cs new file mode 100644 index 0000000000..910e3e521 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Filters/YCbCr Filters/YCbCrReplaceChannel.cs @@ -0,0 +1,314 @@ +// AForge Image Processing Library +// AForge.NET framework +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.Filters +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Replace channel of YCbCr color space. + /// + /// + /// Replaces specified YCbCr channel of color image with + /// specified grayscale imge. + /// + /// The filter is quite useful in conjunction with filter + /// (however may be used alone in some cases). Using the filter + /// it is possible to extract one of YCbCr channel, perform some image processing with it and then + /// put it back into the original color image. + /// + /// The filter accepts 24 and 32 bpp color images for processing. + /// + /// Sample usage: + /// + /// // create YCbCrExtractChannel filter for channel extracting + /// YCbCrExtractChannel extractFilter = new YCbCrExtractChannel( + /// YCbCr.CbIndex ); + /// // extract Cb channel + /// Bitmap cbChannel = extractFilter.Apply( image ); + /// // invert the channel + /// Invert invertFilter = new Invert( ); + /// invertFilter.ApplyInPlace( cbChannel ); + /// // put the channel back into the source image + /// YCbCrReplaceChannel replaceFilter = new YCbCrReplaceChannel( + /// YCbCr.CbIndex, cbChannel ); + /// replaceFilter.ApplyInPlace( image ); + /// + /// + /// Initial image: + /// + /// Result image: + /// + /// + /// + /// + /// + public class YCbCrReplaceChannel : BaseInPlacePartialFilter + { + private short channel = YCbCr.YIndex; + private Bitmap channelImage; + private UnmanagedImage unmanagedChannelImage; + + // private format translation dictionary + private Dictionary formatTranslations = new Dictionary(); + + /// + /// Format translations dictionary. + /// + public override Dictionary FormatTranslations + { + get { return formatTranslations; } + } + + /// + /// YCbCr channel to replace. + /// + /// + /// Default value is set to (Y channel). + /// + /// Invalid channel was specified. + /// + public short Channel + { + get { return channel; } + set + { + if ( + (value != YCbCr.YIndex) && + (value != YCbCr.CbIndex) && + (value != YCbCr.CrIndex) + ) + { + throw new ArgumentException("Invalid YCbCr channel was specified."); + } + channel = value; + } + } + + /// + /// Grayscale image to use for channel replacement. + /// + /// + /// + /// Setting this property will clear the property - + /// only one channel image is allowed: managed or unmanaged. + /// + /// + /// Channel image should be 8bpp indexed image (grayscale). + /// + public Bitmap ChannelImage + { + get { return channelImage; } + set + { + if (value != null) + { + // check for valid format + if (value.PixelFormat != PixelFormat.Format8bppIndexed) + throw new InvalidImagePropertiesException("Channel image should be 8bpp indexed image (grayscale)."); + } + + channelImage = value; + unmanagedChannelImage = null; + } + } + + /// + /// Unmanaged grayscale image to use for channel replacement. + /// + /// + /// + /// Setting this property will clear the property - + /// only one channel image is allowed: managed or unmanaged. + /// + /// + /// Channel image should be 8bpp indexed image (grayscale). + /// + public UnmanagedImage UnmanagedChannelImage + { + get { return unmanagedChannelImage; } + set + { + if (value != null) + { + // check for valid format + if (value.PixelFormat != PixelFormat.Format8bppIndexed) + throw new InvalidImagePropertiesException("Channel image should be 8bpp indexed image (grayscale)."); + } + + channelImage = null; + unmanagedChannelImage = value; + } + } + + // private constructor + private YCbCrReplaceChannel() + { + // initialize format translation dictionary + formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb; + formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb; + formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// YCbCr channel to replace. + /// + public YCbCrReplaceChannel(short channel) + : this() + { + this.Channel = channel; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// YCbCr channel to replace. + /// Channel image to use for replacement. + /// + public YCbCrReplaceChannel(short channel, Bitmap channelImage) + : this() + { + this.Channel = channel; + this.ChannelImage = channelImage; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// YCbCr channel to replace. + /// Unmanaged channel image to use for replacement. + /// + public YCbCrReplaceChannel(short channel, UnmanagedImage channelImage) + : this() + { + this.Channel = channel; + this.UnmanagedChannelImage = channelImage; + } + + /// + /// Process the filter on the specified image. + /// + /// + /// Source image data. + /// Image rectangle for processing by the filter. + /// + /// Channel image was not specified. + /// Channel image size does not match source + /// image size. + /// + protected override unsafe void ProcessFilter(UnmanagedImage image, Rectangle rect) + { + if ((channelImage == null) && (unmanagedChannelImage == null)) + throw new InvalidOperationException("Channel image was not specified."); + + int pixelSize = Image.GetPixelFormatSize(image.PixelFormat) / 8; + + int width = image.Width; + int height = image.Height; + int startX = rect.Left; + int startY = rect.Top; + int stopX = startX + rect.Width; + int stopY = startY + rect.Height; + int offset = image.Stride - rect.Width * pixelSize; + + BitmapData chData = null; + // pointer to channel's data + byte* ch; + // channel's image stride + int chStride = 0; + + // check channel's image type + if (channelImage != null) + { + // check channel's image dimension + if ((width != channelImage.Width) || (height != channelImage.Height)) + throw new InvalidImagePropertiesException("Channel image size does not match source image size."); + + // lock channel image + chData = channelImage.LockBits( + new Rectangle(0, 0, width, height), + ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); + + ch = (byte*)chData.Scan0.ToPointer(); + chStride = chData.Stride; + } + else + { + // check channel's image dimension + if ((width != unmanagedChannelImage.Width) || (height != unmanagedChannelImage.Height)) + throw new InvalidImagePropertiesException("Channel image size does not match source image size."); + + ch = (byte*)unmanagedChannelImage.ImageData; + chStride = unmanagedChannelImage.Stride; + } + + int offsetCh = chStride - rect.Width; + RGB rgb = new RGB(); + YCbCr ycbcr = new YCbCr(); + + // do the job + byte* dst = (byte*)image.ImageData.ToPointer(); + + // allign pointer to the first pixel to process + dst += (startY * image.Stride + startX * pixelSize); + ch += (startY * chStride + startX); + + // for each line + for (int y = startY; y < stopY; y++) + { + // for each pixel + for (int x = startX; x < stopX; x++, dst += pixelSize, ch++) + { + rgb.Red = dst[RGB.R]; + rgb.Green = dst[RGB.G]; + rgb.Blue = dst[RGB.B]; + + // convert to YCbCr + AForge.Imaging.YCbCr.FromRGB(rgb, ycbcr); + + switch (channel) + { + case YCbCr.YIndex: + ycbcr.Y = (float)*ch / 255; + break; + + case YCbCr.CbIndex: + ycbcr.Cb = (float)*ch / 255 - 0.5f; + break; + + case YCbCr.CrIndex: + ycbcr.Cr = (float)*ch / 255 - 0.5f; + break; + } + + // convert back to RGB + AForge.Imaging.YCbCr.ToRGB(ycbcr, rgb); + + dst[RGB.R] = rgb.Red; + dst[RGB.G] = rgb.Green; + dst[RGB.B] = rgb.Blue; + } + dst += offset; + ch += offsetCh; + } + + if (chData != null) + { + // unlock + channelImage.UnlockBits(chData); + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Formats/FITSCodec.cs b/Sources/Accord.Imaging/AForge/Formats/FITSCodec.cs new file mode 100644 index 0000000000..c41ce4ea6 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Formats/FITSCodec.cs @@ -0,0 +1,700 @@ +// AForge Image Formats Library +// AForge.NET framework +// +// Copyright © Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Formats +{ + using System; + using System.IO; + using System.Drawing; + using System.Drawing.Imaging; + using System.Text; + using System.ComponentModel; + + /// + /// Information about FITS image's frame. + /// + public sealed class FITSImageInfo : ImageInfo + { + private int originalBitsPerPixl; + private double minDataValue; + private double maxDataValue; + private string telescope; + private string acquiredObject; + private string observer; + private string instrument; + + /// + /// Original bits per pixel. + /// + /// + /// The property specifies original number of bits per image's pixel. For + /// FITS images the value may be equal to 8, 16, 32, -32 (32 bit image with float data + /// type for pixel encoding), -64 (64 bit image with double data type for pixel encoding). + /// + /// + [Category("FITS Info")] + public int OriginalBitsPerPixl + { + get { return originalBitsPerPixl; } + set { originalBitsPerPixl = value; } + } + + /// + /// Minimum data value found during parsing FITS image. + /// + /// + /// Minimum and maximum data values are used to scale image's data converting + /// them from original bits per pixel format to + /// supported bits per pixel format. + /// + [Category("FITS Info")] + public double MinDataValue + { + get { return minDataValue; } + set { minDataValue = value; } + } + + /// + /// Maximum data value found during parsing FITS image. + /// + /// + /// Minimum and maximum data values are used to scale image's data converting + /// them from original bits per pixel format to + /// supported bits per pixel format. + /// + [Category("FITS Info")] + public double MaxDataValue + { + get { return maxDataValue; } + set { maxDataValue = value; } + } + + /// + /// Telescope used for object's observation. + /// + [Category("FITS Info")] + public string Telescope + { + get { return telescope; } + set { telescope = value; } + } + + /// + /// Object acquired during observation. + /// + [Category("FITS Info")] + public string Object + { + get { return acquiredObject; } + set { acquiredObject = value; } + } + + /// + /// Observer doing object's acquiring. + /// + [Category("FITS Info")] + public string Observer + { + get { return observer; } + set { observer = value; } + } + + /// + /// Instrument used for observation. + /// + [Category("FITS Info")] + public string Instrument + { + get { return instrument; } + set { instrument = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public FITSImageInfo() { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Image's width. + /// Image's height. + /// Number of bits per image's pixel. + /// Frame's index. + /// Total frames in the image. + /// + public FITSImageInfo(int width, int height, int bitsPerPixel, int frameIndex, int totalFrames) : + base(width, height, bitsPerPixel, frameIndex, totalFrames) { } + + /// + /// Creates a new object that is a copy of the current instance. + /// + /// + /// A new object that is a copy of this instance. + /// + public override object Clone() + { + FITSImageInfo clone = new FITSImageInfo(width, height, bitsPerPixel, frameIndex, totalFrames); + + clone.originalBitsPerPixl = originalBitsPerPixl; + clone.minDataValue = minDataValue; + clone.maxDataValue = maxDataValue; + clone.telescope = telescope; + clone.acquiredObject = acquiredObject; + clone.observer = observer; + clone.instrument = instrument; + + return clone; + } + } + + /// + /// FITS image format decoder. + /// + /// + /// The FITS (an acronym derived from "Flexible Image Transport System") format + /// is an astronomical image and table format created and supported by NASA. FITS is the most + /// commonly used in astronomy and is designed specifically for scientific data. Different astronomical + /// organizations keep their images acquired using telescopes and other equipment in FITS format. + /// + /// The class extracts image frames only from the main data section of FITS file. + /// 2D (single frame) and 3D (series of frames) data structures are supported. + /// + /// During image reading/parsing, its data are scaled using minimum and maximum values of + /// the source image data. FITS tags are not used for this purpose - data are scaled from the + /// [min, max] range found to the range of supported image format ([0, 255] for 8 bpp grayscale + /// or [0, 65535] for 16 bpp grayscale image). + /// + /// + public class FITSCodec : IImageDecoder + { + // stream with FITS encoded data + private Stream stream = null; + // information about images retrieved from header + private FITSImageInfo imageInfo = null; + // stream position pointing to beginning of data (or extension) - right after header + private long dataPosition = 0; + + /// + /// Decode first frame of FITS image. + /// + /// + /// Source stream, which contains encoded image. + /// + /// Returns decoded image frame. + /// + /// Not a FITS image format. + /// Format of the FITS image is not supported. + /// The stream contains invalid (broken) FITS image. + /// + public Bitmap DecodeSingleFrame(Stream stream) + { + FITSImageInfo imageInfo = ReadHeader(stream); + + // check if there any image frame + if (imageInfo.TotalFrames == 0) + { + throw new ArgumentException("The FITS stream does not contain any image in main section."); + } + // read and return first frame + return ReadImageFrame(stream, imageInfo); + } + + /// + /// Open specified stream. + /// + /// + /// Stream to open. + /// + /// Returns number of images found in the specified stream. + /// + /// Not a FITS image format. + /// Format of the FITS image is not supported. + /// The stream contains invalid (broken) FITS image. + /// + public int Open(Stream stream) + { + // close previous decoding + Close(); + + this.imageInfo = ReadHeader(stream); + this.stream = stream; + this.dataPosition = stream.Seek(0, SeekOrigin.Current); + + return imageInfo.TotalFrames; + } + + /// + /// Decode specified frame. + /// + /// + /// Image frame to decode. + /// Receives information about decoded frame. + /// + /// Returns decoded frame. + /// + /// No image stream was opened previously. + /// Stream does not contain frame with specified index. + /// The stream contains invalid (broken) FITS image. + /// + public Bitmap DecodeFrame(int frameIndex, out ImageInfo imageInfo) + { + // check requested frame index + if (frameIndex >= this.imageInfo.TotalFrames) + { + throw new ArgumentOutOfRangeException("Currently opened stream does not contain frame with specified index."); + } + + // seek to the required frame + stream.Seek(dataPosition + frameIndex * this.imageInfo.Width * this.imageInfo.Height * + Math.Abs(this.imageInfo.OriginalBitsPerPixl) / 8, SeekOrigin.Begin); + + // read required frame + Bitmap image = ReadImageFrame(stream, this.imageInfo); + + // provide also frame information + imageInfo = (FITSImageInfo)this.imageInfo.Clone(); + imageInfo.FrameIndex = frameIndex; + + return image; + } + + /// + /// Close decoding of previously opened stream. + /// + /// + /// The method does not close stream itself, but just closes + /// decoding cleaning all associated data with it. + /// + public void Close() + { + stream = null; + imageInfo = null; + } + + // Read and process FITS header. After the header is read stream pointer will + // point to data or extension. + private static FITSImageInfo ReadHeader(Stream stream) + { + byte[] headerRecord = new byte[80]; + int recordsRead = 1; + bool endKeyWasFound = false; + + FITSImageInfo imageInfo = new FITSImageInfo(); + + // read first record and check for correct image + if ( + (Tools.ReadStream(stream, headerRecord, 0, 80) < 80) || + (Encoding.ASCII.GetString(headerRecord, 0, 8) != "SIMPLE ")) + { + throw new FormatException("The stream does not contatin FITS image."); + } + else + { + // check if the image has standard FITS format + if (Encoding.ASCII.GetString(headerRecord, 10, 70).Split('/')[0].Trim() != "T") + { + throw new NotSupportedException("The stream contains not standard FITS data file."); + } + } + + // read header and locate data block + while (true) + { + // read next record + if (Tools.ReadStream(stream, headerRecord, 0, 80) < 80) + { + throw new ArgumentException("The stream does not contain valid FITS image."); + } + recordsRead++; + + // get keyword + string keyword = Encoding.ASCII.GetString(headerRecord, 0, 8); + + // skip commenct and history + if ((keyword == "COMMENT ") || (keyword == "HISTORY ")) + continue; + + // check if it is end of header keyword + if (keyword == "END ") + endKeyWasFound = true; + + if (endKeyWasFound) + { + if (recordsRead % 36 == 0) + { + // found data or extension header + + // make a small check of some header values + if ((imageInfo.BitsPerPixel == 0) || (imageInfo.Width == 0) || (imageInfo.Height == 0)) + { + imageInfo.TotalFrames = 0; + } + + // let's return here and let other routines process data + break; + } + } + else + { + // get string representation of value/comments + string strValue = Encoding.ASCII.GetString(headerRecord, 10, 70); + + // check important keywords + if (keyword == "BITPIX ") + { + int value = ExtractIntegerValue(strValue); + + if ((value != 8) && (value != 16) && (value != 32) && (value != -32) && (value != -64)) + { + throw new NotSupportedException("Data format (" + value + ") is not supported."); + } + + // bits per pixel + imageInfo.BitsPerPixel = (value == 8) ? 8 : 16; + imageInfo.OriginalBitsPerPixl = value; + } + else if (Encoding.ASCII.GetString(headerRecord, 0, 5) == "NAXIS") + { + // information about data axis + int value = ExtractIntegerValue(strValue); + + // check axis + switch (headerRecord[5]) + { + // number of axis + case (byte)' ': + switch (value) + { + case 1: + default: + throw new NotSupportedException("FITS files with data dimension of " + value + " are not supported."); + case 0: + // the stream does not have an image, do nothing + break; + case 2: + // the stream has 1 2D image + imageInfo.TotalFrames = 1; + break; + case 3: + // the stream has 3D image - series of 2D images + break; + } + break; + // length of 1st axis + case (byte)'1': + imageInfo.Width = value; + break; + // length of 2nd axis + case (byte)'2': + imageInfo.Height = value; + break; + // length of 3rd axis + case (byte)'3': + imageInfo.TotalFrames = value; + break; + } + } + else if (keyword == "TELESCOP") + { + imageInfo.Telescope = ExtractStringValue(strValue); + } + else if (keyword == "OBJECT ") + { + imageInfo.Object = ExtractStringValue(strValue); + } + else if (keyword == "OBSERVER") + { + imageInfo.Observer = ExtractStringValue(strValue); + } + else if (keyword == "INSTRUME") + { + imageInfo.Instrument = ExtractStringValue(strValue); + } + + // --- for debugging --- + /* if ( keyword[0] != ' ' ) + { + System.Diagnostics.Debug.Write( keyword ); + if ( headerRecord[8] == '=' ) + { + System.Diagnostics.Debug.WriteLine( " = " + strValue ); + } + else + { + System.Diagnostics.Debug.WriteLine( "" ); + } + } */ + // --- --- + } + } + + // scan all available data to find minimum and maximum values, + // which will be used for scaling. the scan is done here (not while + // reading actual frame) because FITS file may have set of images + // packed into data cube, so entire scan of all the data is required. + + // if is stream is seekable + if (!stream.CanSeek) + { + throw new ArgumentException("The stream must be seekable."); + } + + // remember current position + long dataPos = stream.Seek(0, SeekOrigin.Current); + + // data size + int lineLength = imageInfo.Width * (Math.Abs(imageInfo.OriginalBitsPerPixl) / 8); + int totalLines = imageInfo.Height * imageInfo.TotalFrames; + int originalBitsPerPixel = imageInfo.OriginalBitsPerPixl; + + byte[] buffer = new byte[lineLength]; + byte[] temp = new byte[8]; + + // min and max values + double min = double.MaxValue; + double max = double.MinValue; + + for (int i = 0; i < totalLines; i++) + { + // read next line + if (Tools.ReadStream(stream, buffer, 0, lineLength) < lineLength) + throw new ArgumentException("The stream does not contain valid FITS image."); + + // scan the line + for (int j = 0; j < lineLength; ) + { + double value = 0; + + // read values accordint to their format + switch (originalBitsPerPixel) + { + case 8: // 8 bit unsigned integer + value = buffer[j++]; + break; + case 16: // 16 bit signed integer + { + short tempValue = 0; + unchecked + { + tempValue = (short)((buffer[j++] << 8) | buffer[j++]); + } + value = tempValue; + break; + } + case 32: // 32 bit signed integer + { + temp[3] = buffer[j++]; + temp[2] = buffer[j++]; + temp[1] = buffer[j++]; + temp[0] = buffer[j++]; + + value = BitConverter.ToInt32(temp, 0); + + break; + } + case -32: // 32 bit float + { + temp[3] = buffer[j++]; + temp[2] = buffer[j++]; + temp[1] = buffer[j++]; + temp[0] = buffer[j++]; + + value = BitConverter.ToSingle(temp, 0); + break; + } + case -64: // 64 bit double + { + temp[7] = buffer[j++]; + temp[6] = buffer[j++]; + temp[5] = buffer[j++]; + temp[4] = buffer[j++]; + temp[3] = buffer[j++]; + temp[2] = buffer[j++]; + temp[1] = buffer[j++]; + temp[0] = buffer[j++]; + + value = BitConverter.ToDouble(temp, 0); + break; + } + } + + if (value > max) + max = value; + if (value < min) + min = value; + } + } + + imageInfo.MaxDataValue = max; + imageInfo.MinDataValue = min; + + // restore stream position to the begining of data + stream.Seek(dataPos, SeekOrigin.Begin); + + return imageInfo; + } + + // Read image frame from the specified stream (current stream's position is used) + private static unsafe Bitmap ReadImageFrame(Stream stream, FITSImageInfo imageInfo) + { + int width = imageInfo.Width; + int height = imageInfo.Height; + + // create new bitmap + Bitmap image = (imageInfo.BitsPerPixel == 8) ? + Tools.CreateGrayscaleImage(width, height) : + new Bitmap(width, height, PixelFormat.Format16bppGrayScale); + + // lock it + BitmapData imageData = image.LockBits(new Rectangle(0, 0, width, height), + ImageLockMode.ReadWrite, image.PixelFormat); + + int originalBitsPerPixel = imageInfo.OriginalBitsPerPixl; + int stride = imageData.Stride; + byte* ptr = (byte*)imageData.Scan0.ToPointer(); + + double min = imageInfo.MinDataValue; + double max = imageInfo.MaxDataValue; + + // check number of bits per pixel and load image appropriately + if (imageInfo.BitsPerPixel == 16) + { + // 16 bpp grayscale image + double coef = 65535.0 / (max - min); + + // prepare a buffer for one line + int lineSize = width * Math.Abs(originalBitsPerPixel) / 8; + byte[] line = new byte[lineSize]; + byte[] temp = new byte[8]; + + // load all rows + for (int y = height - 1; y >= 0; y--) + { + // load next line + if (Tools.ReadStream(stream, line, 0, lineSize) < lineSize) + throw new ArgumentException("The stream does not contain valid FITS image."); + + // fill next image row + ushort* row = (ushort*)(ptr + stride * y); + + for (int x = 0, i = 0; x < width; x++, row++) + { + double value = 0; + + switch (originalBitsPerPixel) + { + case 16: // 16 bit signed integer + { + short tempValue = 0; + unchecked + { + tempValue = (short)((line[i++] << 8) + line[i++]); + } + value = tempValue; + break; + } + case 32: // 32 bit signed integer + { + temp[3] = line[i++]; + temp[2] = line[i++]; + temp[1] = line[i++]; + temp[0] = line[i++]; + + value = BitConverter.ToInt32(temp, 0); + + break; + } + case -32: // 32 bit float + { + temp[3] = line[i++]; + temp[2] = line[i++]; + temp[1] = line[i++]; + temp[0] = line[i++]; + + value = BitConverter.ToSingle(temp, 0); + break; + } + case -64: // 64 bit double + { + temp[7] = line[i++]; + temp[6] = line[i++]; + temp[5] = line[i++]; + temp[4] = line[i++]; + temp[3] = line[i++]; + temp[2] = line[i++]; + temp[1] = line[i++]; + temp[0] = line[i++]; + + value = BitConverter.ToDouble(temp, 0); + break; + } + } + + *row = (ushort)((value - min) * coef); + } + } + } + else + { + // 8 bpp grayscale image + double coef = 255.0 / (max - min); + + // prepare a buffer for one line + byte[] line = new byte[width]; + + // load all rows + for (int y = height - 1; y >= 0; y--) + { + // load next line + if (Tools.ReadStream(stream, line, 0, width) < width) + throw new ArgumentException("The stream does not contain valid FITS image."); + + // fill next image row + byte* row = ptr + stride * y; + + for (int x = 0; x < width; x++, row++) + { + *row = (byte)(((double)line[x] - min) * coef); + } + } + } + + // unlock image and return it + image.UnlockBits(imageData); + return image; + } + + // Extract integer value from string representation of value/comments + private static int ExtractIntegerValue(string strValue) + { + try + { + // split value from comment + string[] strs = strValue.Split('/'); + + // return value as integer + return int.Parse(strs[0].Trim()); + } + catch + { + throw new ArgumentException("The stream does not contain valid FITS image."); + } + } + + // Extract string value + private static string ExtractStringValue(string strValue) + { + // split value from comment + string[] strs = strValue.Split('/'); + + return strs[0].Replace("''", "``").Replace("'", "").Replace("''", "``").Trim(); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Formats/IImageDecoder.cs b/Sources/Accord.Imaging/AForge/Formats/IImageDecoder.cs new file mode 100644 index 0000000000..b0cf04c5f --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Formats/IImageDecoder.cs @@ -0,0 +1,228 @@ +// AForge Image Formats Library +// AForge.NET framework +// +// Copyright © Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Formats +{ + using System; + using System.IO; + using System.Drawing; + using System.ComponentModel; + + /// + /// Image decoder interface, which specifies set of methods, which should be + /// implemented by image decoders for different file formats. + /// + /// + /// The interface specifies set of methods, which are suitable not + /// only for simple one-frame image formats. The interface also defines methods + /// to work with image formats designed to store multiple frames and image formats + /// which provide different type of image description (like acquisition + /// parameters, etc). + /// + /// + public interface IImageDecoder + { + /// + /// Decode first frame of image from the specified stream. + /// + /// + /// Source stream, which contains encoded image. + /// + /// Returns decoded image frame. + /// + /// + /// For one-frame image formats the method is supposed to decode single + /// available frame. For multi-frame image formats the first frame should be + /// decoded. + /// + /// Implementations of this method may throw + /// exception to report about unrecognized image + /// format, exception to report about incorrectly + /// formatted image or exception to report if + /// certain formats are not supported. + /// + /// + Bitmap DecodeSingleFrame(Stream stream); + + /// + /// Open specified stream. + /// + /// + /// Stream to open. + /// + /// Returns number of images found in the specified stream. + /// + /// Implementation of this method is supposed to read image's header, + /// checking for correct image format and reading its atributes. + /// + /// Implementations of this method may throw + /// exception to report about unrecognized image + /// format, exception to report about incorrectly + /// formatted image or exception to report if + /// certain formats are not supported. + /// + /// + int Open(Stream stream); + + /// + /// Decode specified frame. + /// + /// + /// Image frame to decode. + /// Receives information about decoded frame. + /// + /// Returns decoded frame. + /// + /// Implementations of this method may throw + /// exception in the case if no image + /// stream was opened previously, in the + /// case if stream does not contain frame with specified index or + /// exception to report about incorrectly formatted image. + /// + /// + Bitmap DecodeFrame(int frameIndex, out ImageInfo imageInfo); + + /// + /// Close decoding of previously opened stream. + /// + /// + /// Implementations of this method don't close stream itself, but just close + /// decoding cleaning all associated data with it. + /// + void Close(); + } + + /// + /// Information about image's frame. + /// + /// + /// This is a base class, which keeps basic information about image, like its width, + /// height, etc. Classes, which inherit from this, may define more properties describing certain + /// image formats. + /// + public class ImageInfo : ICloneable + { + /// + /// Image's width. + /// + protected int width; + + /// + /// Image's height. + /// + protected int height; + + /// + /// Number of bits per image's pixel. + /// + protected int bitsPerPixel; + + /// + /// Frame's index. + /// + protected int frameIndex; + + /// + /// Total frames in the image. + /// + protected int totalFrames; + + /// + /// Image's width. + /// + [Category("General")] + public int Width + { + get { return width; } + set { width = value; } + } + + /// + /// Image's height. + /// + [Category("General")] + public int Height + { + get { return height; } + set { height = value; } + } + + /// + /// Number of bits per image's pixel. + /// + [Category("General")] + public int BitsPerPixel + { + get { return bitsPerPixel; } + set { bitsPerPixel = value; } + } + + /// + /// Frame's index. + /// + /// + /// Some image formats support storing multiple frames in one image file. + /// The property specifies index of a particular frame. + /// + [Category("General")] + public int FrameIndex + { + get { return frameIndex; } + set { frameIndex = value; } + } + + /// + /// Total frames in the image. + /// + /// + /// Some image formats support storing multiple frames in one image file. + /// The property specifies total number of frames in image file. + /// + [Category("General")] + public int TotalFrames + { + get { return totalFrames; } + set { totalFrames = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public ImageInfo() { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Image's width. + /// Image's height. + /// Number of bits per image's pixel. + /// Frame's index. + /// Total frames in the image. + /// + public ImageInfo(int width, int height, int bitsPerPixel, int frameIndex, int totalFrames) + { + this.width = width; + this.height = height; + this.bitsPerPixel = bitsPerPixel; + this.frameIndex = frameIndex; + this.totalFrames = totalFrames; + } + + /// + /// Creates a new object that is a copy of the current instance. + /// + /// + /// A new object that is a copy of this instance. + /// + public virtual object Clone() + { + return new ImageInfo(width, height, bitsPerPixel, frameIndex, totalFrames); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Formats/ImageDecoder.cs b/Sources/Accord.Imaging/AForge/Formats/ImageDecoder.cs new file mode 100644 index 0000000000..a8d6bbb25 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Formats/ImageDecoder.cs @@ -0,0 +1,194 @@ +// AForge Image Formats Library +// AForge.NET framework +// +// Copyright © Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Formats +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + using System.Globalization; + using System.IO; + + /// + /// Image decoder to decode different custom image file formats. + /// + /// + /// The class represent a help class, which simplifies decoding of image + /// files finding appropriate image decoder automatically (using list of registered + /// image decoders). Instead of using required image decoder directly, users may use this + /// class, which will find required decoder by file's extension. + /// + /// By default the class registers on its own all decoders, which are available in + /// AForge.Imaging.Formats library. If user has implementation of his own image decoders, he + /// needs to register them using method to be able to use them through + /// the class. + /// + /// If the class can not find appropriate decode in the list of registered + /// decoders, it passes file to .NET's image decoder for decoding. + /// + /// Sample usage: + /// + /// // sample file name + /// string fileName = "myFile.pnm"; + /// // decode image file + /// Bitmap = ImageDecoder.DecodeFromFile( fileName ); + /// + /// + /// + /// + /// + /// + public class ImageDecoder + { + private static Dictionary decoders = new Dictionary(); + + static ImageDecoder() + { + // register PNM file format + IImageDecoder decoder = new PNMCodec(); + + RegisterDecoder("pbm", decoder); + RegisterDecoder("pgm", decoder); + RegisterDecoder("pnm", decoder); + RegisterDecoder("ppm", decoder); + + // register FITS file format + decoder = new FITSCodec(); + + RegisterDecoder("fit", decoder); + RegisterDecoder("fits", decoder); + } + + /// + /// Register image decoder for a specified file extension. + /// + /// + /// File extension to register decoder for ("bmp", for example). + /// Image decoder to use for the specified file extension. + /// + /// The method allows to register image decoder object, which should be used + /// to decode images from files with the specified extension. + /// + public static void RegisterDecoder(string fileExtension, IImageDecoder decoder) + { + System.Diagnostics.Debug.WriteLine("Registering decoder: " + fileExtension); + + decoders.Add(fileExtension.ToUpperInvariant(), decoder); + } + + /// + /// Decode first frame for the specified file. + /// + /// + /// File name to read image from. + /// + /// Return decoded image. In the case if file format support multiple + /// frames, the method return the first frame. + /// + /// The method uses table of registered image decoders to find the one, + /// which should be used for the specified file. If there is not appropriate decoder + /// found, the method uses default .NET's image decoding routine (see + /// ). + /// + public static Bitmap DecodeFromFile(string fileName) + { + ImageInfo imageInfo = null; + + return DecodeFromFile(fileName, out imageInfo); + } + + /// + /// Decode first frame for the specified file. + /// + /// + /// File name to read image from. + /// Information about the decoded image. + /// + /// Return decoded image. In the case if file format support multiple + /// frames, the method return the first frame. + /// + /// The method uses table of registered image decoders to find the one, + /// which should be used for the specified file. If there is not appropriate decoder + /// found, the method uses default .NET's image decoding routine (see + /// ). + /// + public static Bitmap DecodeFromFile(string fileName, out ImageInfo imageInfo) + { + Bitmap bitmap = null; + + string fileExtension = Path.GetExtension(fileName).ToUpperInvariant(); + + if ((fileExtension != string.Empty) && (fileExtension.Length != 0)) + { + fileExtension = fileExtension.Substring(1); + + if (decoders.ContainsKey(fileExtension)) + { + IImageDecoder decoder = decoders[fileExtension]; + + // open stream + using (FileStream stream = new FileStream(fileName, FileMode.Open)) + { + // open decoder + decoder.Open(stream); + + // read the first frame + bitmap = decoder.DecodeFrame(0, out imageInfo); + + decoder.Close(); + } + + return bitmap; + } + } + + // use default .NET's image decoding routine + bitmap = FromFile(fileName); + + imageInfo = new ImageInfo(bitmap.Width, bitmap.Height, Image.GetPixelFormatSize(bitmap.PixelFormat), 0, 1); + + return bitmap; + } + + private static System.Drawing.Bitmap FromFile(string fileName) + { + Bitmap loadedImage = null; + FileStream stream = null; + + try + { + // read image to temporary memory stream + stream = File.OpenRead(fileName); + MemoryStream memoryStream = new MemoryStream(); + + byte[] buffer = new byte[10000]; + while (true) + { + int read = stream.Read(buffer, 0, 10000); + + if (read == 0) + break; + + memoryStream.Write(buffer, 0, read); + } + + loadedImage = (Bitmap)Bitmap.FromStream(memoryStream); + } + finally + { + if (stream != null) + { + stream.Close(); + stream.Dispose(); + } + } + + return loadedImage; + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Formats/PNMCodec.cs b/Sources/Accord.Imaging/AForge/Formats/PNMCodec.cs new file mode 100644 index 0000000000..5a79ea411 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Formats/PNMCodec.cs @@ -0,0 +1,451 @@ +// AForge Image Formats Library +// AForge.NET framework +// +// Copyright © Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Formats +{ + using System; + using System.IO; + using System.Drawing; + using System.Drawing.Imaging; + using System.Text; + using System.ComponentModel; + + /// + /// Information about PNM image's frame. + /// + public sealed class PNMImageInfo : ImageInfo + { + // PNM file version (1-6) + private int version; + // maximum data value + private int maxDataValue; + + /// + /// PNM file version (format), [1, 6]. + /// + [Category("PNM Info")] + public int Version + { + get { return version; } + set { version = value; } + } + + /// + /// Maximum pixel's value in source PNM image. + /// + /// + /// The value is used to scale image's data converting them + /// from original data range to the range of + /// supported bits per pixel format. + /// + [Category("PNM Info")] + public int MaxDataValue + { + get { return maxDataValue; } + set { maxDataValue = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public PNMImageInfo() { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Image's width. + /// Image's height. + /// Number of bits per image's pixel. + /// Frame's index. + /// Total frames in the image. + /// + public PNMImageInfo(int width, int height, int bitsPerPixel, int frameIndex, int totalFrames) : + base(width, height, bitsPerPixel, frameIndex, totalFrames) { } + + /// + /// Creates a new object that is a copy of the current instance. + /// + /// + /// A new object that is a copy of this instance. + /// + public override object Clone() + { + PNMImageInfo clone = new PNMImageInfo(width, height, bitsPerPixel, frameIndex, totalFrames); + + clone.version = version; + clone.maxDataValue = maxDataValue; + + return clone; + } + } + + /// + /// PNM image format decoder. + /// + /// + /// The PNM (an acronym derived from "Portable Any Map") format is an + /// abstraction of the PBM, PGM and PPM formats. I.e. the name "PNM" refers collectively + /// to PBM (binary images), PGM (grayscale images) and PPM (color image) image formats. + /// + /// Image in PNM format can be found in different scientific databases and laboratories, + /// for example Yale Face Database and AT&T Face Database. + /// + /// Only PNM images of P5 (binary encoded PGM) and P6 (binary encoded PPM) formats + /// are supported at this point. + /// + /// The maximum supported pixel value is 255 at this point. + /// + /// The class supports only one-frame PNM images. As it is specified in format + /// specification, the multi-frame PNM images has appeared starting from 2000. + /// + /// + /// + public class PNMCodec : IImageDecoder + { + // stream with PNM encoded data + private Stream stream = null; + // information about images retrieved from header + private PNMImageInfo imageInfo = null; + // stream position pointing to beginning of data - right after header + private long dataPosition = 0; + + /// + /// Decode first frame of PNM image. + /// + /// + /// Source stream, which contains encoded image. + /// + /// Returns decoded image frame. + /// + /// Not a PNM image format. + /// Format of the PNM image is not supported. + /// The stream contains invalid (broken) PNM image. + /// + public Bitmap DecodeSingleFrame(Stream stream) + { + PNMImageInfo imageInfo = ReadHeader(stream); + + return ReadImageFrame(stream, imageInfo); + } + + /// + /// Open specified stream. + /// + /// + /// Stream to open. + /// + /// Returns number of images found in the specified stream. + /// + /// Not a PNM image format. + /// Format of the PNM image is not supported. + /// The stream contains invalid (broken) PNM image. + /// + public int Open(Stream stream) + { + // close previous decoding + Close(); + + this.imageInfo = ReadHeader(stream); + this.stream = stream; + this.dataPosition = stream.Seek(0, SeekOrigin.Current); + + return imageInfo.TotalFrames; + } + + /// + /// Decode specified frame. + /// + /// + /// Image frame to decode. + /// Receives information about decoded frame. + /// + /// Returns decoded frame. + /// + /// No image stream was opened previously. + /// Stream does not contain frame with specified index. + /// The stream contains invalid (broken) PNM image. + /// + public Bitmap DecodeFrame(int frameIndex, out ImageInfo imageInfo) + { + // check requested frame index + if (frameIndex != 0) + { + throw new ArgumentOutOfRangeException("Currently opened stream does not contain frame with specified index."); + } + + // seek to the required frame + stream.Seek(dataPosition, SeekOrigin.Begin); + + // read required frame + Bitmap image = ReadImageFrame(stream, this.imageInfo); + + // provide also frame information + imageInfo = (PNMImageInfo)this.imageInfo.Clone(); + + return image; + } + + /// + /// Close decoding of previously opened stream. + /// + /// + /// The method does not close stream itself, but just closes + /// decoding cleaning all associated data with it. + /// + public void Close() + { + stream = null; + imageInfo = null; + } + + // Read and process PNM header. After the header is read stream pointer will + // point to data. + private PNMImageInfo ReadHeader(Stream stream) + { + // read magic word + byte magic1 = (byte)stream.ReadByte(); + byte magic2 = (byte)stream.ReadByte(); + + // check if it is valid PNM image + if ((magic1 != 'P') || (magic2 < '1') || (magic2 > '6')) + { + throw new FormatException("The stream does not contain PNM image."); + } + + // check if it is P5 or P6 format + if ((magic2 != '5') && (magic2 != '6')) + { + throw new NotSupportedException("Format is not supported yet. Only P5 and P6 are supported for now."); + } + + int width = 0, height = 0, maxValue = 0; + + try + { + // read image's width and height + width = ReadIntegerValue(stream); + height = ReadIntegerValue(stream); + // read pixel's highiest value + maxValue = ReadIntegerValue(stream); + } + catch + { + throw new ArgumentException("The stream does not contain valid PNM image."); + } + + // check if all attributes are valid + if ((width <= 0) || (height <= 0) || (maxValue <= 0)) + { + throw new ArgumentException("The stream does not contain valid PNM image."); + } + + // check maximum pixel's value + if (maxValue > 255) + { + throw new NotSupportedException("255 is the maximum pixel's value, which is supported for now."); + } + + // prepare image information + PNMImageInfo imageInfo = new PNMImageInfo(width, height, (magic2 == '5') ? 8 : 24, 0, 1); + imageInfo.Version = (int)(magic2 - '0'); + imageInfo.MaxDataValue = maxValue; + + return imageInfo; + } + + // Read image frame from the specified stream (current stream's position is used) + private static Bitmap ReadImageFrame(Stream stream, PNMImageInfo imageInfo) + { + try + { + // decode PNM image depending on its format + switch (imageInfo.Version) + { + case 5: + return ReadP5Image(stream, imageInfo.Width, imageInfo.Height, imageInfo.MaxDataValue); + case 6: + return ReadP6Image(stream, imageInfo.Width, imageInfo.Height, imageInfo.MaxDataValue); + } + } + catch + { + throw new ArgumentException("The stream does not contain valid PNM image."); + } + + return null; + } + + // Load P5 PGM image (grayscale PNM image with binary encoding) + private static unsafe Bitmap ReadP5Image(Stream stream, int width, int height, int maxValue) + { + double scalingFactor = (double)255 / maxValue; + + // create new bitmap and lock it + Bitmap image = Tools.CreateGrayscaleImage(width, height); + BitmapData imageData = image.LockBits(new Rectangle(0, 0, width, height), + ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed); + + int stride = imageData.Stride; + byte* ptr = (byte*)imageData.Scan0.ToPointer(); + + // prepare a buffer for one line + byte[] line = new byte[width]; + + int totalBytesRead = 0, bytesRead = 0; + + // load all rows + for (int y = 0; y < height; y++) + { + totalBytesRead = 0; + bytesRead = 0; + + // load next line + while (totalBytesRead != width) + { + bytesRead = stream.Read(line, totalBytesRead, width - totalBytesRead); + + if (bytesRead == 0) + { + // if we've reached the end before complete image is loaded, then there should + // be something wrong + throw new InvalidOperationException("Execution should not reach here."); + } + + totalBytesRead += bytesRead; + } + + // fill next image row + byte* row = ptr + stride * y; + + for (int x = 0; x < width; x++, row++) + { + *row = (byte)(scalingFactor * line[x]); + } + } + + // unlock image and return it + image.UnlockBits(imageData); + return image; + } + + // Load P6 PPM image (color PNM image with binary encoding) + private static unsafe Bitmap ReadP6Image(Stream stream, int width, int height, int maxValue) + { + double scalingFactor = (double)255 / maxValue; + + // create new bitmap and lock it + Bitmap image = new Bitmap(width, height, PixelFormat.Format24bppRgb); + BitmapData imageData = image.LockBits(new Rectangle(0, 0, width, height), + ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); + + int stride = imageData.Stride; + byte* ptr = (byte*)imageData.Scan0.ToPointer(); + + // prepare a buffer for one line + int lineSize = width * 3; + byte[] line = new byte[lineSize]; + + int totalBytesRead = 0, bytesRead = 0; + + // load all rows + for (int y = 0; y < height; y++) + { + totalBytesRead = 0; + bytesRead = 0; + + // load next line + while (totalBytesRead != lineSize) + { + bytesRead = stream.Read(line, totalBytesRead, lineSize - totalBytesRead); + + if (bytesRead == 0) + { + // if we've reached the end before complete image is loaded, then there should + // be something wrong + throw new InvalidOperationException("Execution should not reach here."); + } + + totalBytesRead += bytesRead; + } + + // fill next image row + byte* row = ptr + stride * y; + + for (int x = 0, i = 0; x < width; x++, i += 3, row += 3) + { + row[2] = (byte)(scalingFactor * line[i]); // red + row[1] = (byte)(scalingFactor * line[i + 1]); // green + row[0] = (byte)(scalingFactor * line[i + 2]); // blue + } + } + + // unlock image and return it + image.UnlockBits(imageData); + return image; + } + + // Read integer ASCII value from the source stream. + private int ReadIntegerValue(Stream stream) + { + byte[] buffer = new byte[256]; + int bytesRead = 1; + + // locate something, what is not spacing + buffer[0] = SkipSpaces(stream); + // complete reading useful value + bytesRead += ReadUntilSpace(stream, buffer, 1); + + return int.Parse(Encoding.ASCII.GetString(buffer, 0, bytesRead)); + } + + // Skip spaces (spaces, new lines, tabs and comment lines) in the specified stream + // and return the first non-space byte. Stream's position will point to the next + // byte coming after the first found non-space byte. + private byte SkipSpaces(Stream stream) + { + byte nextByte = (byte)stream.ReadByte(); + + while ((nextByte == ' ') || (nextByte == '\n') || (nextByte == '\r') || (nextByte == '\t')) + { + nextByte = (byte)stream.ReadByte(); + } + + if (nextByte == '#') + { + // read until new line + while (nextByte != '\n') + { + nextByte = (byte)stream.ReadByte(); + } + // skip pending spaces or another comment + return SkipSpaces(stream); + } + + return nextByte; + } + + // Read stream until space is found (space, new line, tab or comment). Returns + // number of bytes read. Stream's position will point to the next + // byte coming after the first found space byte. + private static int ReadUntilSpace(Stream stream, byte[] buffer, int start) + { + byte nextByte = (byte)stream.ReadByte(); + int bytesRead = 0; + + while ((nextByte != ' ') && (nextByte != '\n') && (nextByte != '\r') && (nextByte != '\t') && (nextByte != '#')) + { + buffer[start + bytesRead] = nextByte; + bytesRead++; + nextByte = (byte)stream.ReadByte(); + } + + return bytesRead; + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Formats/Tools.cs b/Sources/Accord.Imaging/AForge/Formats/Tools.cs new file mode 100644 index 0000000000..08d8e038a --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Formats/Tools.cs @@ -0,0 +1,87 @@ +// AForge Image Formats Library +// AForge.NET framework +// +// Copyright © Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Imaging.Formats +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + using System.IO; + + /// + /// Set of tools used internally in AForge.Imaging.Formats library. + /// + internal class Tools + { + /// + /// Create and initialize new grayscale image. + /// + /// + /// Image width. + /// Image height. + /// + /// Returns new created grayscale image. + /// + /// AForge.Imaging.Image.CreateGrayscaleImage() function + /// could be used instead, which does the some. But it was not used to get + /// rid of dependency on AForge.Imaing library. + /// + public static Bitmap CreateGrayscaleImage( int width, int height ) + { + // create new image + Bitmap image = new Bitmap( width, height, PixelFormat.Format8bppIndexed ); + // get palette + ColorPalette cp = image.Palette; + // init palette with grayscale colors + for ( int i = 0; i < 256; i++ ) + { + cp.Entries[i] = Color.FromArgb( i, i, i ); + } + // set palette back + image.Palette = cp; + // return new image + return image; + } + + /// + /// Read specified amount of bytes from the specified stream. + /// + /// + /// Source sream to read data from. + /// Buffer to read data into. + /// Offset in buffer to put data into. + /// Number of bytes to read. + /// + /// Returns total number of bytes read. It may be smaller than requested amount only + /// in the case if end of stream was reached. + /// + /// This tool function guarantees that requested number of bytes + /// was read from the source stream (.NET streams don't guarantee this and may return less bytes + /// than it was requested). Only in the case if end of stream was reached, the function + /// may return with less bytes read. + /// + /// + public static int ReadStream( Stream stream, byte[] buffer, int offset, int count ) + { + int totalBytesRead = 0, bytesRead = 0; + + while ( totalBytesRead != count ) + { + bytesRead = stream.Read( buffer, offset + totalBytesRead, count - totalBytesRead ); + + if ( bytesRead == 0 ) + { + break; + } + + totalBytesRead += bytesRead; + } + + return totalBytesRead; + } + } +} diff --git a/Sources/Accord.Imaging/AForge/HorizontalIntensityStatistics.cs b/Sources/Accord.Imaging/AForge/HorizontalIntensityStatistics.cs new file mode 100644 index 0000000000..23531ba37 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/HorizontalIntensityStatistics.cs @@ -0,0 +1,349 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + using AForge.Math; + + /// + /// Horizontal intensity statistics. + /// + /// + /// The class provides information about horizontal distribution + /// of pixel intensities, which may be used to locate objects, their centers, etc. + /// + /// + /// The class accepts grayscale (8 bpp indexed and 16 bpp) and color (24, 32, 48 and 64 bpp) images. + /// In the case of 32 and 64 bpp color images, the alpha channel is not processed - statistics is not + /// gathered for this channel. + /// + /// Sample usage: + /// + /// // collect statistics + /// HorizontalIntensityStatistics his = new HorizontalIntensityStatistics( sourceImage ); + /// // get gray histogram (for grayscale image) + /// Histogram histogram = his.Gray; + /// // output some histogram's information + /// System.Diagnostics.Debug.WriteLine( "Mean = " + histogram.Mean ); + /// System.Diagnostics.Debug.WriteLine( "Min = " + histogram.Min ); + /// System.Diagnostics.Debug.WriteLine( "Max = " + histogram.Max ); + /// + /// + /// Sample grayscale image with its horizontal intensity histogram: + /// + /// + /// + /// + /// + public class HorizontalIntensityStatistics + { + // histograms for RGB channgels + private Histogram red = null; + private Histogram green = null; + private Histogram blue = null; + // grayscale histogram + private Histogram gray = null; + + /// + /// Histogram for red channel. + /// + /// + public Histogram Red + { + get + { + if (red == null) + { + throw new InvalidImagePropertiesException(ExceptionMessage.ColorHistogramException); + } + return red; + } + } + + /// + /// Histogram for green channel. + /// + /// + public Histogram Green + { + get + { + if (green == null) + { + throw new InvalidImagePropertiesException(ExceptionMessage.ColorHistogramException); + } + return green; + } + } + + /// + /// Histogram for blue channel. + /// + /// + public Histogram Blue + { + get + { + if (blue == null) + throw new InvalidImagePropertiesException(ExceptionMessage.ColorHistogramException); + + return blue; + } + } + + /// + /// Histogram for gray channel (intensities). + /// + /// + public Histogram Gray + { + get + { + if (gray == null) + throw new InvalidImagePropertiesException(ExceptionMessage.GrayHistogramException); + + return gray; + } + } + + /// + /// Value wich specifies if the processed image was color or grayscale. + /// + /// + /// If the property equals to true, then the + /// property should be used to retrieve histogram for the processed grayscale image. + /// Otherwise , and property + /// should be used to retrieve histogram for particular RGB channel of the processed + /// color image. + /// + public bool IsGrayscale + { + get { return (gray != null); } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Source image. + /// + /// Unsupported pixel format of the source image. + /// + public HorizontalIntensityStatistics(Bitmap image) + { + // check image format + if ( + (image.PixelFormat != PixelFormat.Format8bppIndexed) && + (image.PixelFormat != PixelFormat.Format16bppGrayScale) && + (image.PixelFormat != PixelFormat.Format24bppRgb) && + (image.PixelFormat != PixelFormat.Format32bppRgb) && + (image.PixelFormat != PixelFormat.Format32bppArgb) && + (image.PixelFormat != PixelFormat.Format48bppRgb) && + (image.PixelFormat != PixelFormat.Format64bppArgb) + ) + { + throw new UnsupportedImageFormatException("Unsupported pixel format of the source image."); + } + + // lock bitmap data + BitmapData imageData = image.LockBits( + new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, image.PixelFormat); + + try + { + // gather statistics + ProcessImage(new UnmanagedImage(imageData)); + } + finally + { + // unlock image + image.UnlockBits(imageData); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Source image data. + /// + /// Unsupported pixel format of the source image. + /// + public HorizontalIntensityStatistics(BitmapData imageData) + : this(new UnmanagedImage(imageData)) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Source unmanaged image. + /// + /// Unsupported pixel format of the source image. + /// + public HorizontalIntensityStatistics(UnmanagedImage image) + { + // check image format + if ( + (image.PixelFormat != PixelFormat.Format8bppIndexed) && + (image.PixelFormat != PixelFormat.Format16bppGrayScale) && + (image.PixelFormat != PixelFormat.Format24bppRgb) && + (image.PixelFormat != PixelFormat.Format32bppRgb) && + (image.PixelFormat != PixelFormat.Format32bppArgb) && + (image.PixelFormat != PixelFormat.Format48bppRgb) && + (image.PixelFormat != PixelFormat.Format64bppArgb) + ) + { + throw new UnsupportedImageFormatException("Unsupported pixel format of the source image."); + } + + // gather statistics + ProcessImage(image); + } + + /// + /// Gather horizontal intensity statistics for specified image. + /// + /// + /// Source image. + /// + private void ProcessImage(UnmanagedImage image) + { + PixelFormat pixelFormat = image.PixelFormat; + // get image dimension + int width = image.Width; + int height = image.Height; + + red = green = blue = gray = null; + + // do the job + unsafe + { + // check pixel format + if (pixelFormat == PixelFormat.Format8bppIndexed) + { + // 8 bpp grayscale image + byte* p = (byte*)image.ImageData.ToPointer(); + int offset = image.Stride - width; + + // histogram array + int[] g = new int[width]; + + // for each pixel + for (int y = 0; y < height; y++) + { + // for each pixel + for (int x = 0; x < width; x++, p++) + { + g[x] += *p; + } + p += offset; + } + + // create historgram for gray level + gray = new Histogram(g); + } + else if (pixelFormat == PixelFormat.Format16bppGrayScale) + { + // 16 bpp grayscale image + byte* basePtr = (byte*)image.ImageData.ToPointer(); + int stride = image.Stride; + + // histogram array + int[] g = new int[width]; + + // for each pixel + for (int y = 0; y < height; y++) + { + ushort* p = (ushort*)(basePtr + stride * y); + + // for each pixel + for (int x = 0; x < width; x++, p++) + { + g[x] += *p; + } + } + + // create historgram for gray level + gray = new Histogram(g); + } + else if ( + (pixelFormat == PixelFormat.Format24bppRgb) || + (pixelFormat == PixelFormat.Format32bppRgb) || + (pixelFormat == PixelFormat.Format32bppArgb)) + { + // 24/32 bpp color image + byte* p = (byte*)image.ImageData.ToPointer(); + int pixelSize = (pixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4; + int offset = image.Stride - width * pixelSize; + + // histogram arrays + int[] r = new int[width]; + int[] g = new int[width]; + int[] b = new int[width]; + + // for each line + for (int y = 0; y < height; y++) + { + // for each pixel + for (int x = 0; x < width; x++, p += pixelSize) + { + r[x] += p[RGB.R]; + g[x] += p[RGB.G]; + b[x] += p[RGB.B]; + } + p += offset; + } + + // create histograms + red = new Histogram(r); + green = new Histogram(g); + blue = new Histogram(b); + } + else if ( + (pixelFormat == PixelFormat.Format48bppRgb) || + (pixelFormat == PixelFormat.Format64bppArgb)) + { + // 48/64 bpp color image + byte* basePtr = (byte*)image.ImageData.ToPointer(); + int stride = image.Stride; + int pixelSize = (pixelFormat == PixelFormat.Format48bppRgb) ? 3 : 4; + + // histogram arrays + int[] r = new int[width]; + int[] g = new int[width]; + int[] b = new int[width]; + + // for each line + for (int y = 0; y < height; y++) + { + ushort* p = (ushort*)(basePtr + stride * y); + + // for each pixel + for (int x = 0; x < width; x++, p += pixelSize) + { + r[x] += p[RGB.R]; + g[x] += p[RGB.G]; + b[x] += p[RGB.B]; + } + } + + // create histograms + red = new Histogram(r); + green = new Histogram(g); + blue = new Histogram(b); + } + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/HoughCircleTransformation.cs b/Sources/Accord.Imaging/AForge/HoughCircleTransformation.cs new file mode 100644 index 0000000000..2ff800952 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/HoughCircleTransformation.cs @@ -0,0 +1,534 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2010 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging +{ + using System; + using System.Collections; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Hough circle. + /// + /// + /// Represents circle of Hough transform. + /// + /// + /// + public class HoughCircle : IComparable + { + /// + /// Circle center's X coordinate. + /// + public readonly int X; + + /// + /// Circle center's Y coordinate. + /// + public readonly int Y; + + /// + /// Circle's radius. + /// + public readonly int Radius; + + /// + /// Line's absolute intensity. + /// + public readonly short Intensity; + + /// + /// Line's relative intensity. + /// + public readonly double RelativeIntensity; + + /// + /// Initializes a new instance of the class. + /// + /// + /// Circle's X coordinate. + /// Circle's Y coordinate. + /// Circle's radius. + /// Circle's absolute intensity. + /// Circle's relative intensity. + /// + public HoughCircle(int x, int y, int radius, short intensity, double relativeIntensity) + { + X = x; + Y = y; + Radius = radius; + Intensity = intensity; + RelativeIntensity = relativeIntensity; + } + + /// + /// Compare the object with another instance of this class. + /// + /// + /// Object to compare with. + /// + /// A signed number indicating the relative values of this instance and value: 1) greater than zero - + /// this instance is greater than value; 2) zero - this instance is equal to value; + /// 3) greater than zero - this instance is less than value. + /// + /// The sort order is descending. + /// + /// + /// Object are compared using their intensity value. + /// + /// + public int CompareTo(object obj) + { + return (-Intensity.CompareTo(((HoughCircle)obj).Intensity)); + } + } + + /// + /// Hough circle transformation. + /// + /// + /// The class implements Hough circle transformation, which allows to detect + /// circles of specified radius in an image. + /// + /// The class accepts binary images for processing, which are represented by 8 bpp grayscale images. + /// All black pixels (0 pixel's value) are treated as background, but pixels with different value are + /// treated as circles' pixels. + /// + /// Sample usage: + /// + /// HoughCircleTransformation circleTransform = new HoughCircleTransformation( 35 ); + /// // apply Hough circle transform + /// circleTransform.ProcessImage( sourceImage ); + /// Bitmap houghCirlceImage = circleTransform.ToBitmap( ); + /// // get circles using relative intensity + /// HoughCircle[] circles = circleTransform.GetCirclesByRelativeIntensity( 0.5 ); + /// + /// foreach ( HoughCircle circle in circles ) + /// { + /// // ... + /// } + /// + /// + /// Initial image: + /// + /// Hough circle transformation image: + /// + /// + /// + /// + /// + public class HoughCircleTransformation + { + // circle radius to detect + private int radiusToDetect; + + // Hough map + private short[,] houghMap; + private short maxMapIntensity = 0; + + // Hough map's width and height + private int width; + private int height; + + private int localPeakRadius = 4; + private short minCircleIntensity = 10; + private ArrayList circles = new ArrayList(); + + /// + /// Minimum circle's intensity in Hough map to recognize a circle. + /// + /// + /// The value sets minimum intensity level for a circle. If a value in Hough + /// map has lower intensity, then it is not treated as a circle. + /// + /// Default value is set to 10. + /// + public short MinCircleIntensity + { + get { return minCircleIntensity; } + set { minCircleIntensity = value; } + } + + /// + /// Radius for searching local peak value. + /// + /// + /// The value determines radius around a map's value, which is analyzed to determine + /// if the map's value is a local maximum in specified area. + /// + /// Default value is set to 4. Minimum value is 1. Maximum value is 10. + /// + public int LocalPeakRadius + { + get { return localPeakRadius; } + set { localPeakRadius = Math.Max(1, Math.Min(10, value)); } + } + + /// + /// Maximum found intensity in Hough map. + /// + /// + /// The property provides maximum found circle's intensity. + /// + public short MaxIntensity + { + get { return maxMapIntensity; } + } + + /// + /// Found circles count. + /// + /// + /// The property provides total number of found circles, which intensity is higher (or equal to), + /// than the requested minimum intensity. + /// + public int CirclesCount + { + get { return circles.Count; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Circles' radius to detect. + /// + public HoughCircleTransformation(int radiusToDetect) + { + this.radiusToDetect = radiusToDetect; + } + + /// + /// Process an image building Hough map. + /// + /// + /// Source image to process. + /// + /// Unsupported pixel format of the source image. + /// + public void ProcessImage(Bitmap image) + { + // check image format + if (image.PixelFormat != PixelFormat.Format8bppIndexed) + { + throw new UnsupportedImageFormatException("Unsupported pixel format of the source image."); + } + + // lock source image + BitmapData imageData = image.LockBits( + new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); + + try + { + // process the image + ProcessImage(new UnmanagedImage(imageData)); + } + finally + { + // unlock image + image.UnlockBits(imageData); + } + } + + /// + /// Process an image building Hough map. + /// + /// + /// Source image data to process. + /// + /// Unsupported pixel format of the source image. + /// + public void ProcessImage(BitmapData imageData) + { + ProcessImage(new UnmanagedImage(imageData)); + } + + /// + /// Process an image building Hough map. + /// + /// + /// Source unmanaged image to process. + /// + /// Unsupported pixel format of the source image. + /// + public void ProcessImage(UnmanagedImage image) + { + if (image.PixelFormat != PixelFormat.Format8bppIndexed) + { + throw new UnsupportedImageFormatException("Unsupported pixel format of the source image."); + } + + // get source image size + width = image.Width; + height = image.Height; + + int srcOffset = image.Stride - width; + + // allocate Hough map of the same size like image + houghMap = new short[height, width]; + + // do the job + unsafe + { + byte* src = (byte*)image.ImageData.ToPointer(); + + // for each row + for (int y = 0; y < height; y++) + { + // for each pixel + for (int x = 0; x < width; x++, src++) + { + if (*src != 0) + { + DrawHoughCircle(x, y); + } + } + src += srcOffset; + } + } + + // find max value in Hough map + maxMapIntensity = 0; + for (int i = 0; i < height; i++) + { + for (int j = 0; j < width; j++) + { + if (houghMap[i, j] > maxMapIntensity) + { + maxMapIntensity = houghMap[i, j]; + } + } + } + + CollectCircles(); + } + + /// + /// onvert Hough map to bitmap. + /// + /// + /// Returns 8 bppp grayscale bitmap, which shows Hough map. + /// + /// Hough transformation was not yet done by calling + /// ProcessImage() method. + /// + public Bitmap ToBitmap() + { + // check if Hough transformation was made already + if (houghMap == null) + throw new InvalidOperationException("Hough transformation was not done yet."); + + int width = houghMap.GetLength(1); + int height = houghMap.GetLength(0); + + // create new image + Bitmap image = AForge.Imaging.Image.CreateGrayscaleImage(width, height); + + // lock destination bitmap data + BitmapData imageData = image.LockBits( + new Rectangle(0, 0, width, height), + ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed); + + int offset = imageData.Stride - width; + float scale = 255.0f / maxMapIntensity; + + // do the job + unsafe + { + byte* dst = (byte*)imageData.Scan0.ToPointer(); + + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++, dst++) + { + *dst = (byte)System.Math.Min(255, (int)(scale * houghMap[y, x])); + } + dst += offset; + } + } + + // unlock destination images + image.UnlockBits(imageData); + + return image; + } + + /// + /// Get specified amount of circles with highest intensity. + /// + /// + /// Amount of circles to get. + /// + /// Returns arrary of most intesive circles. If there are no circles detected, + /// the returned array has zero length. + /// + public HoughCircle[] GetMostIntensiveCircles(int count) + { + // lines count + int n = Math.Min(count, circles.Count); + + // result array + HoughCircle[] dst = new HoughCircle[n]; + circles.CopyTo(0, dst, 0, n); + + return dst; + } + + /// + /// Get circles with relative intensity higher then specified value. + /// + /// + /// Minimum relative intesity of circles. + /// + /// Returns arrary of most intesive circles. If there are no circles detected, + /// the returned array has zero length. + /// + public HoughCircle[] GetCirclesByRelativeIntensity(double minRelativeIntensity) + { + int count = 0, n = circles.Count; + + while ((count < n) && (((HoughCircle)circles[count]).RelativeIntensity >= minRelativeIntensity)) + count++; + + return GetMostIntensiveCircles(count); + } + + + // Collect circles with intesities greater or equal then specified + private void CollectCircles() + { + short intensity; + bool foundGreater; + + // clean circles collection + circles.Clear(); + + // for each Y coordinate + for (int y = 0; y < height; y++) + { + // for each X coordinate + for (int x = 0; x < width; x++) + { + // get current value + intensity = houghMap[y, x]; + + if (intensity < minCircleIntensity) + continue; + + foundGreater = false; + + // check neighboors + for (int ty = y - localPeakRadius, tyMax = y + localPeakRadius; ty < tyMax; ty++) + { + // continue if the coordinate is out of map + if (ty < 0) + continue; + // break if it is not local maximum or coordinate is out of map + if ((foundGreater == true) || (ty >= height)) + break; + + for (int tx = x - localPeakRadius, txMax = x + localPeakRadius; tx < txMax; tx++) + { + // continue or break if the coordinate is out of map + if (tx < 0) + continue; + if (tx >= width) + break; + + // compare the neighboor with current value + if (houghMap[ty, tx] > intensity) + { + foundGreater = true; + break; + } + } + } + + // was it local maximum ? + if (!foundGreater) + { + // we have local maximum + circles.Add(new HoughCircle(x, y, radiusToDetect, intensity, (double)intensity / maxMapIntensity)); + } + } + } + + circles.Sort(); + } + + // Draw Hough circle: + // http://www.cs.unc.edu/~mcmillan/comp136/Lecture7/circle.html + // + // TODO: more optimizations of circle drawing could be done. + // + private void DrawHoughCircle(int xCenter, int yCenter) + { + int x = 0; + int y = radiusToDetect; + int p = (5 - radiusToDetect * 4) / 4; + + SetHoughCirclePoints(xCenter, yCenter, x, y); + + while (x < y) + { + x++; + if (p < 0) + { + p += 2 * x + 1; + } + else + { + y--; + p += 2 * (x - y) + 1; + } + SetHoughCirclePoints(xCenter, yCenter, x, y); + } + } + + // Set circle points + private void SetHoughCirclePoints(int cx, int cy, int x, int y) + { + if (x == 0) + { + SetHoughPoint(cx, cy + y); + SetHoughPoint(cx, cy - y); + SetHoughPoint(cx + y, cy); + SetHoughPoint(cx - y, cy); + } + else if (x == y) + { + SetHoughPoint(cx + x, cy + y); + SetHoughPoint(cx - x, cy + y); + SetHoughPoint(cx + x, cy - y); + SetHoughPoint(cx - x, cy - y); + } + else if (x < y) + { + SetHoughPoint(cx + x, cy + y); + SetHoughPoint(cx - x, cy + y); + SetHoughPoint(cx + x, cy - y); + SetHoughPoint(cx - x, cy - y); + SetHoughPoint(cx + y, cy + x); + SetHoughPoint(cx - y, cy + x); + SetHoughPoint(cx + y, cy - x); + SetHoughPoint(cx - y, cy - x); + } + } + + // Set point + private void SetHoughPoint(int x, int y) + { + if ((x >= 0) && (y >= 0) && (x < width) && (y < height)) + { + houghMap[y, x]++; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/HoughLineTransformation.cs b/Sources/Accord.Imaging/AForge/HoughLineTransformation.cs new file mode 100644 index 0000000000..d74a2bcc8 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/HoughLineTransformation.cs @@ -0,0 +1,702 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging +{ + using System; + using System.Collections; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Hough line. + /// + /// + /// Represents line of Hough Line transformation using + /// polar coordinates. + /// See Wikipedia + /// for information on how to convert polar coordinates to Cartesian coordinates. + /// + /// + /// Hough Line transformation does not provide + /// information about lines start and end points, only slope and distance from image's center. Using + /// only provided information it is not possible to draw the detected line as it exactly appears on + /// the source image. But it is possible to draw a line through the entire image, which contains the + /// source line (see sample code below). + /// + /// + /// Sample code to draw detected Hough lines: + /// + /// HoughLineTransformation lineTransform = new HoughLineTransformation( ); + /// // apply Hough line transofrm + /// lineTransform.ProcessImage( sourceImage ); + /// Bitmap houghLineImage = lineTransform.ToBitmap( ); + /// // get lines using relative intensity + /// HoughLine[] lines = lineTransform.GetLinesByRelativeIntensity( 0.5 ); + /// + /// foreach ( HoughLine line in lines ) + /// { + /// // get line's radius and theta values + /// int r = line.Radius; + /// double t = line.Theta; + /// + /// // check if line is in lower part of the image + /// if ( r < 0 ) + /// { + /// t += 180; + /// r = -r; + /// } + /// + /// // convert degrees to radians + /// t = ( t / 180 ) * Math.PI; + /// + /// // get image centers (all coordinate are measured relative + /// // to center) + /// int w2 = image.Width /2; + /// int h2 = image.Height / 2; + /// + /// double x0 = 0, x1 = 0, y0 = 0, y1 = 0; + /// + /// if ( line.Theta != 0 ) + /// { + /// // none-vertical line + /// x0 = -w2; // most left point + /// x1 = w2; // most right point + /// + /// // calculate corresponding y values + /// y0 = ( -Math.Cos( t ) * x0 + r ) / Math.Sin( t ); + /// y1 = ( -Math.Cos( t ) * x1 + r ) / Math.Sin( t ); + /// } + /// else + /// { + /// // vertical line + /// x0 = line.Radius; + /// x1 = line.Radius; + /// + /// y0 = h2; + /// y1 = -h2; + /// } + /// + /// // draw line on the image + /// Drawing.Line( sourceData, + /// new IntPoint( (int) x0 + w2, h2 - (int) y0 ), + /// new IntPoint( (int) x1 + w2, h2 - (int) y1 ), + /// Color.Red ); + /// } + /// + /// + /// To clarify meaning of and values + /// of detected Hough lines, let's take a look at the below sample image and + /// corresponding values of radius and theta for the lines on the image: + /// + /// + /// + /// + /// Detected radius and theta values (color in corresponding colors): + /// + /// Theta = 90, R = 125, I = 249; + /// Theta = 0, R = -170, I = 187 (converts to Theta = 180, R = 170); + /// Theta = 90, R = -58, I = 163 (converts to Theta = 270, R = 58); + /// Theta = 101, R = -101, I = 130 (converts to Theta = 281, R = 101); + /// Theta = 0, R = 43, I = 112; + /// Theta = 45, R = 127, I = 82. + /// + /// + /// + /// + /// + /// + /// + public class HoughLine : IComparable + { + /// + /// Line's slope - angle between polar axis and line's radius (normal going + /// from pole to the line). Measured in degrees, [0, 180). + /// + public readonly double Theta; + + /// + /// Line's distance from image center, (−∞, +∞). + /// + /// + /// Negative line's radius means, that the line resides in lower + /// part of the polar coordinates system. This means that value + /// should be increased by 180 degrees and radius should be made positive. + /// + /// + public readonly short Radius; + + /// + /// Line's absolute intensity, (0, +∞). + /// + /// + /// Line's absolute intensity is a measure, which equals + /// to number of pixels detected on the line. This value is bigger for longer + /// lines. + /// + /// The value may not be 100% reliable to measure exact number of pixels + /// on the line. Although these value correlate a lot (which means they are very close + /// in most cases), the intensity value may slightly vary. + /// + /// + public readonly short Intensity; + + /// + /// Line's relative intensity, (0, 1]. + /// + /// + /// Line's relative intensity is relation of line's + /// value to maximum found intensity. For the longest line (line with highest intesity) the + /// relative intensity is set to 1. If line's relative is set 0.5, for example, this means + /// its intensity is half of maximum found intensity. + /// + /// + public readonly double RelativeIntensity; + + /// + /// Initializes a new instance of the class. + /// + /// + /// Line's slope. + /// Line's distance from image center. + /// Line's absolute intensity. + /// Line's relative intensity. + /// + public HoughLine(double theta, short radius, short intensity, double relativeIntensity) + { + Theta = theta; + Radius = radius; + Intensity = intensity; + RelativeIntensity = relativeIntensity; + } + + /// + /// Compare the object with another instance of this class. + /// + /// + /// Object to compare with. + /// + /// A signed number indicating the relative values of this instance and value: 1) greater than zero - + /// this instance is greater than value; 2) zero - this instance is equal to value; + /// 3) greater than zero - this instance is less than value. + /// + /// The sort order is descending. + /// + /// + /// Object are compared using their intensity value. + /// + /// + public int CompareTo(object obj) + { + return (-Intensity.CompareTo(((HoughLine)obj).Intensity)); + } + } + + /// + /// Hough line transformation. + /// + /// + /// The class implements Hough line transformation, which allows to detect + /// straight lines in an image. Lines, which are found by the class, are provided in + /// polar coordinates system - + /// lines' distances from image's center and lines' slopes are provided. + /// The pole of polar coordinates system is put into processing image's center and the polar + /// axis is directed to the right from the pole. Lines' slope is measured in degrees and + /// is actually represented by angle between polar axis and line's radius (normal going + /// from pole to the line), which is measured in counter-clockwise direction. + /// + /// + /// Found lines may have negative radius. + /// This means, that the line resides in lower part of the polar coordinates system + /// and its value should be increased by 180 degrees and + /// radius should be made positive. + /// + /// + /// The class accepts binary images for processing, which are represented by 8 bpp grayscale images. + /// All black pixels (0 pixel's value) are treated as background, but pixels with different value are + /// treated as lines' pixels. + /// + /// See also documentation to class for additional information + /// about Hough Lines. + /// + /// Sample usage: + /// + /// HoughLineTransformation lineTransform = new HoughLineTransformation( ); + /// // apply Hough line transofrm + /// lineTransform.ProcessImage( sourceImage ); + /// Bitmap houghLineImage = lineTransform.ToBitmap( ); + /// // get lines using relative intensity + /// HoughLine[] lines = lineTransform.GetLinesByRelativeIntensity( 0.5 ); + /// + /// foreach ( HoughLine line in lines ) + /// { + /// // ... + /// } + /// + /// + /// Initial image: + /// + /// Hough line transformation image: + /// + /// + /// + /// + /// + public class HoughLineTransformation + { + // Hough transformation quality settings + private int stepsPerDegree; + private int houghHeight; + private double thetaStep; + + // precalculated Sine and Cosine values + private double[] sinMap; + private double[] cosMap; + // Hough map + private short[,] houghMap; + private short maxMapIntensity = 0; + + private int localPeakRadius = 4; + private short minLineIntensity = 10; + private ArrayList lines = new ArrayList(); + + /// + /// Steps per degree. + /// + /// + /// The value defines quality of Hough line transformation and its ability to detect + /// lines' slope precisely. + /// + /// Default value is set to 1. Minimum value is 1. Maximum value is 10. + /// + public int StepsPerDegree + { + get { return stepsPerDegree; } + set + { + stepsPerDegree = Math.Max(1, Math.Min(10, value)); + houghHeight = 180 * stepsPerDegree; + thetaStep = Math.PI / houghHeight; + + // precalculate Sine and Cosine values + sinMap = new double[houghHeight]; + cosMap = new double[houghHeight]; + + for (int i = 0; i < houghHeight; i++) + { + sinMap[i] = Math.Sin(i * thetaStep); + cosMap[i] = Math.Cos(i * thetaStep); + } + } + } + + /// + /// Minimum line's intensity in Hough map to recognize a line. + /// + /// + /// The value sets minimum intensity level for a line. If a value in Hough + /// map has lower intensity, then it is not treated as a line. + /// + /// Default value is set to 10. + /// + public short MinLineIntensity + { + get { return minLineIntensity; } + set { minLineIntensity = value; } + } + + /// + /// Radius for searching local peak value. + /// + /// + /// The value determines radius around a map's value, which is analyzed to determine + /// if the map's value is a local maximum in specified area. + /// + /// Default value is set to 4. Minimum value is 1. Maximum value is 10. + /// + public int LocalPeakRadius + { + get { return localPeakRadius; } + set { localPeakRadius = Math.Max(1, Math.Min(10, value)); } + } + + /// + /// Maximum found intensity in Hough map. + /// + /// + /// The property provides maximum found line's intensity. + /// + public short MaxIntensity + { + get { return maxMapIntensity; } + } + + /// + /// Found lines count. + /// + /// + /// The property provides total number of found lines, which intensity is higher (or equal to), + /// than the requested minimum intensity. + /// + public int LinesCount + { + get { return lines.Count; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public HoughLineTransformation() + { + StepsPerDegree = 1; + } + + /// + /// Process an image building Hough map. + /// + /// + /// Source image to process. + /// + /// Unsupported pixel format of the source image. + /// + public void ProcessImage(Bitmap image) + { + ProcessImage(image, new Rectangle(0, 0, image.Width, image.Height)); + } + + /// + /// Process an image building Hough map. + /// + /// + /// Source image to process. + /// Image's rectangle to process. + /// + /// Unsupported pixel format of the source image. + /// + public void ProcessImage(Bitmap image, Rectangle rect) + { + // check image format + if (image.PixelFormat != PixelFormat.Format8bppIndexed) + { + throw new UnsupportedImageFormatException("Unsupported pixel format of the source image."); + } + + // lock source image + BitmapData imageData = image.LockBits( + new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); + + try + { + // process the image + ProcessImage(new UnmanagedImage(imageData), rect); + } + finally + { + // unlock image + image.UnlockBits(imageData); + } + } + + /// + /// Process an image building Hough map. + /// + /// + /// Source image data to process. + /// + /// Unsupported pixel format of the source image. + /// + public void ProcessImage(BitmapData imageData) + { + ProcessImage(new UnmanagedImage(imageData), + new Rectangle(0, 0, imageData.Width, imageData.Height)); + } + + /// + /// Process an image building Hough map. + /// + /// + /// Source image data to process. + /// Image's rectangle to process. + /// + /// Unsupported pixel format of the source image. + /// + public void ProcessImage(BitmapData imageData, Rectangle rect) + { + ProcessImage(new UnmanagedImage(imageData), rect); + } + + /// + /// Process an image building Hough map. + /// + /// + /// Source unmanaged image to process. + /// + /// Unsupported pixel format of the source image. + /// + public void ProcessImage(UnmanagedImage image) + { + ProcessImage(image, new Rectangle(0, 0, image.Width, image.Height)); + } + + /// + /// Process an image building Hough map. + /// + /// + /// Source unmanaged image to process. + /// Image's rectangle to process. + /// + /// Unsupported pixel format of the source image. + /// + public void ProcessImage(UnmanagedImage image, Rectangle rect) + { + if (image.PixelFormat != PixelFormat.Format8bppIndexed) + { + throw new UnsupportedImageFormatException("Unsupported pixel format of the source image."); + } + + // get source image size + int width = image.Width; + int height = image.Height; + int halfWidth = width / 2; + int halfHeight = height / 2; + + // make sure the specified rectangle recides with the source image + rect.Intersect(new Rectangle(0, 0, width, height)); + + int startX = -halfWidth + rect.Left; + int startY = -halfHeight + rect.Top; + int stopX = width - halfWidth - (width - rect.Right); + int stopY = height - halfHeight - (height - rect.Bottom); + + int offset = image.Stride - rect.Width; + + // calculate Hough map's width + int halfHoughWidth = (int)Math.Sqrt(halfWidth * halfWidth + halfHeight * halfHeight); + int houghWidth = halfHoughWidth * 2; + + houghMap = new short[houghHeight, houghWidth]; + + // do the job + unsafe + { + byte* src = (byte*)image.ImageData.ToPointer() + + rect.Top * image.Stride + rect.Left; + + // for each row + for (int y = startY; y < stopY; y++) + { + // for each pixel + for (int x = startX; x < stopX; x++, src++) + { + if (*src != 0) + { + // for each Theta value + for (int theta = 0; theta < houghHeight; theta++) + { + int radius = (int)Math.Round(cosMap[theta] * x - sinMap[theta] * y) + halfHoughWidth; + + if ((radius < 0) || (radius >= houghWidth)) + continue; + + houghMap[theta, radius]++; + } + } + } + src += offset; + } + } + + // find max value in Hough map + maxMapIntensity = 0; + for (int i = 0; i < houghHeight; i++) + { + for (int j = 0; j < houghWidth; j++) + { + if (houghMap[i, j] > maxMapIntensity) + { + maxMapIntensity = houghMap[i, j]; + } + } + } + + CollectLines(); + } + + /// + /// Convert Hough map to bitmap. + /// + /// + /// Returns 8 bppp grayscale bitmap, which shows Hough map. + /// + /// Hough transformation was not yet done by calling + /// ProcessImage() method. + /// + public Bitmap ToBitmap() + { + // check if Hough transformation was made already + if (houghMap == null) + throw new InvalidOperationException("Hough transformation was not done yet."); + + int width = houghMap.GetLength(1); + int height = houghMap.GetLength(0); + + // create new image + Bitmap image = AForge.Imaging.Image.CreateGrayscaleImage(width, height); + + // lock destination bitmap data + BitmapData imageData = image.LockBits( + new Rectangle(0, 0, width, height), + ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed); + + int offset = imageData.Stride - width; + float scale = 255.0f / maxMapIntensity; + + // do the job + unsafe + { + byte* dst = (byte*)imageData.Scan0.ToPointer(); + + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++, dst++) + { + *dst = (byte)System.Math.Min(255, (int)(scale * houghMap[y, x])); + } + dst += offset; + } + } + + // unlock destination images + image.UnlockBits(imageData); + + return image; + } + + /// + /// Get specified amount of lines with highest intensity. + /// + /// + /// Amount of lines to get. + /// + /// Returns array of most intesive lines. If there are no lines detected, + /// the returned array has zero length. + /// + public HoughLine[] GetMostIntensiveLines(int count) + { + // lines count + int n = Math.Min(count, lines.Count); + + // result array + HoughLine[] dst = new HoughLine[n]; + lines.CopyTo(0, dst, 0, n); + + return dst; + } + + /// + /// Get lines with relative intensity higher then specified value. + /// + /// + /// Minimum relative intesity of lines. + /// + /// Returns array of lines. If there are no lines detected, + /// the returned array has zero length. + /// + public HoughLine[] GetLinesByRelativeIntensity(double minRelativeIntensity) + { + int count = 0, n = lines.Count; + + while ((count < n) && (((HoughLine)lines[count]).RelativeIntensity >= minRelativeIntensity)) + count++; + + return GetMostIntensiveLines(count); + } + + + // Collect lines with intesities greater or equal then specified + private void CollectLines() + { + int maxTheta = houghMap.GetLength(0); + int maxRadius = houghMap.GetLength(1); + + short intensity; + bool foundGreater; + + int halfHoughWidth = maxRadius >> 1; + + // clean lines collection + lines.Clear(); + + // for each Theta value + for (int theta = 0; theta < maxTheta; theta++) + { + // for each Radius value + for (int radius = 0; radius < maxRadius; radius++) + { + // get current value + intensity = houghMap[theta, radius]; + + if (intensity < minLineIntensity) + continue; + + foundGreater = false; + + // check neighboors + for (int tt = theta - localPeakRadius, ttMax = theta + localPeakRadius; tt < ttMax; tt++) + { + // break if it is not local maximum + if (foundGreater == true) + break; + + int cycledTheta = tt; + int cycledRadius = radius; + + // check limits + if (cycledTheta < 0) + { + cycledTheta = maxTheta + cycledTheta; + cycledRadius = maxRadius - cycledRadius; + } + if (cycledTheta >= maxTheta) + { + cycledTheta -= maxTheta; + cycledRadius = maxRadius - cycledRadius; + } + + for (int tr = cycledRadius - localPeakRadius, trMax = cycledRadius + localPeakRadius; tr < trMax; tr++) + { + // skip out of map values + if (tr < 0) + continue; + if (tr >= maxRadius) + break; + + // compare the neighboor with current value + if (houghMap[cycledTheta, tr] > intensity) + { + foundGreater = true; + break; + } + } + } + + // was it local maximum ? + if (!foundGreater) + { + // we have local maximum + lines.Add(new HoughLine((double)theta / stepsPerDegree, (short)(radius - halfHoughWidth), intensity, (double)intensity / maxMapIntensity)); + } + } + } + + lines.Sort(); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/IBlobsFilter.cs b/Sources/Accord.Imaging/AForge/IBlobsFilter.cs new file mode 100644 index 0000000000..f5e6de806 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/IBlobsFilter.cs @@ -0,0 +1,34 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2005-2010 +// andrew.kirillov@aforgenet.com + +namespace AForge.Imaging +{ + /// + /// Interface for custom blobs' filters used for filtering blobs after + /// blob counting. + /// + /// + /// The interface should be implemented by classes, which perform + /// custom blobs' filtering different from default filtering implemented in + /// . See + /// for additional information. + /// + /// + public interface IBlobsFilter + { + /// + /// Check specified blob and decide if should be kept or not. + /// + /// + /// Blob to check. + /// + /// Return if the blob should be kept or + /// if it should be removed. + /// + bool Check( Blob blob ); + } +} diff --git a/Sources/Accord.Imaging/AForge/IBlockMatching.cs b/Sources/Accord.Imaging/AForge/IBlockMatching.cs new file mode 100644 index 0000000000..3e5620ccc --- /dev/null +++ b/Sources/Accord.Imaging/AForge/IBlockMatching.cs @@ -0,0 +1,72 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// +// Copyright Joan Charmant, 2008 +// joan.charmant@gmail.com +// +namespace AForge.Imaging +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Block matching interface. + /// + /// + /// The interface specifies set of methods, which should be implemented by different + /// block matching algorithms. + /// + /// Block matching algorithms work with two images - source and search image - and + /// a set of reference points. For each provided reference point, the algorithm takes + /// a block from source image (reference point is a coordinate of block's center) and finds + /// the best match for it in search image providing its coordinate (search is done within + /// search window of specified size). In other words, block matching algorithm tries to + /// find new coordinates in search image of specified reference points in source image. + /// + /// + /// + public interface IBlockMatching + { + /// + /// Process images matching blocks between them. + /// + /// + /// Source image with reference points. + /// List of reference points to be matched. + /// Image in which the reference points will be looked for. + /// + /// Returns list of found block matches. + /// + List ProcessImage( Bitmap sourceImage, List coordinates, Bitmap searchImage ); + + /// + /// Process images matching blocks between them. + /// + /// + /// Source image with reference points. + /// List of reference points to be matched. + /// Image in which the reference points will be looked for. + /// + /// Returns list of found block matches. + /// + List ProcessImage( BitmapData sourceImageData, List coordinates, BitmapData searchImageData ); + + /// + /// Process images matching blocks between them. + /// + /// + /// Source unmanaged image with reference points. + /// List of reference points to be matched. + /// Unmanaged image in which the reference points will be looked for. + /// + /// Returns list of found block matches. + /// + List ProcessImage( UnmanagedImage sourceImage, List coordinates, UnmanagedImage searchImage ); + } +} diff --git a/Sources/Accord.Imaging/AForge/ICornersDetector.cs b/Sources/Accord.Imaging/AForge/ICornersDetector.cs new file mode 100644 index 0000000000..4f0e06c75 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/ICornersDetector.cs @@ -0,0 +1,56 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + using AForge; + + /// + /// Corners detector's interface. + /// + /// + /// The interface specifies set of methods, which should be implemented by different + /// corners detection algorithms. + /// + public interface ICornersDetector + { + /// + /// Process image looking for corners. + /// + /// + /// Source image to process. + /// + /// Returns list of found corners (X-Y coordinates). + /// + List ProcessImage( Bitmap image ); + + /// + /// Process image looking for corners. + /// + /// + /// Source image data to process. + /// + /// Returns list of found corners (X-Y coordinates). + /// + List ProcessImage( BitmapData imageData ); + + /// + /// Process image looking for corners. + /// + /// + /// Unmanaged source image to process. + /// + /// Returns list of found corners (X-Y coordinates). + /// + List ProcessImage( UnmanagedImage image ); + } +} diff --git a/Sources/Accord.Imaging/AForge/ITemplateMatching.cs b/Sources/Accord.Imaging/AForge/ITemplateMatching.cs new file mode 100644 index 0000000000..cf1b9ed81 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/ITemplateMatching.cs @@ -0,0 +1,61 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Template matching algorithm's interface. + /// + /// + /// The interface specifies set of methods, which should be implemented by different + /// template matching algorithms - algorithms, which search for the given template in specified + /// image. + /// + public interface ITemplateMatching + { + /// + /// Process image looking for matchings with specified template. + /// + /// + /// Source image to process. + /// Template image to search for. + /// Rectangle in source image to search template for. + /// + /// Returns array of found matchings. + /// + TemplateMatch[] ProcessImage( Bitmap image, Bitmap template, Rectangle searchZone ); + + /// + /// Process image looking for matchings with specified template. + /// + /// + /// Source image data to process. + /// Template image to search for. + /// Rectangle in source image to search template for. + /// + /// Returns array of found matchings. + /// + TemplateMatch[] ProcessImage( BitmapData imageData, BitmapData templateData, Rectangle searchZone ); + + /// + /// Process image looking for matchings with specified template. + /// + /// + /// Unmanaged source image to process. + /// Unmanaged template image to search for. + /// Rectangle in source image to search template for. + /// + /// Returns array of found matchings. + /// + TemplateMatch[] ProcessImage( UnmanagedImage image, UnmanagedImage template, Rectangle searchZone ); + } +} diff --git a/Sources/Accord.Imaging/AForge/Image.cs b/Sources/Accord.Imaging/AForge/Image.cs new file mode 100644 index 0000000000..1a73507ec --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Image.cs @@ -0,0 +1,523 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging +{ + using System; + using System.IO; + using System.Drawing; + using System.Drawing.Imaging; + using AForge; + + /// + /// Core image relatad methods. + /// + /// + /// All methods of this class are static and represent general routines + /// used by different image processing classes. + /// + public static class Image + { + /// + /// Check if specified 8 bpp image is grayscale. + /// + /// + /// Image to check. + /// + /// Returns true if the image is grayscale or false otherwise. + /// + /// The methods checks if the image is a grayscale image of 256 gradients. + /// The method first examines if the image's pixel format is + /// Format8bppIndexed + /// and then it examines its palette to check if the image is grayscale or not. + /// + public static bool IsGrayscale(Bitmap image) + { + bool ret = false; + + // check pixel format + if (image.PixelFormat == PixelFormat.Format8bppIndexed) + { + ret = true; + // check palette + ColorPalette cp = image.Palette; + Color c; + // init palette + for (int i = 0; i < 256; i++) + { + c = cp.Entries[i]; + if ((c.R != i) || (c.G != i) || (c.B != i)) + { + ret = false; + break; + } + } + } + return ret; + } + + /// + /// Create and initialize new 8 bpp grayscale image. + /// + /// + /// Image width. + /// Image height. + /// + /// Returns the created grayscale image. + /// + /// The method creates new 8 bpp grayscale image and initializes its palette. + /// Grayscale image is represented as + /// Format8bppIndexed + /// image with palette initialized to 256 gradients of gray color. + /// + public static Bitmap CreateGrayscaleImage(int width, int height) + { + // create new image + Bitmap image = new Bitmap(width, height, PixelFormat.Format8bppIndexed); + // set palette to grayscale + SetGrayscalePalette(image); + // return new image + return image; + } + + /// + /// Set pallete of the 8 bpp indexed image to grayscale. + /// + /// + /// Image to initialize. + /// + /// The method initializes palette of + /// Format8bppIndexed + /// image with 256 gradients of gray color. + /// + /// Provided image is not 8 bpp indexed image. + /// + public static void SetGrayscalePalette(Bitmap image) + { + // check pixel format + if (image.PixelFormat != PixelFormat.Format8bppIndexed) + throw new UnsupportedImageFormatException("Source image is not 8 bpp image."); + + // get palette + ColorPalette cp = image.Palette; + + // init palette + for (int i = 0; i < 256; i++) + cp.Entries[i] = Color.FromArgb(i, i, i); + + // set palette back + image.Palette = cp; + } + + /// + /// Clone image. + /// + /// + /// Source image. + /// Pixel format of result image. + /// + /// Returns clone of the source image with specified pixel format. + /// + /// The original Bitmap.Clone() + /// does not produce the desired result - it does not create a clone with specified pixel format. + /// More of it, the original method does not create an actual clone - it does not create a copy + /// of the image. That is why this method was implemented to provide the functionality. + /// + public static Bitmap Clone(Bitmap source, PixelFormat format) + { + // copy image if pixel format is the same + if (source.PixelFormat == format) + return Clone(source); + + int width = source.Width; + int height = source.Height; + + // create new image with desired pixel format + Bitmap bitmap = new Bitmap(width, height, format); + + // draw source image on the new one using Graphics + Graphics g = Graphics.FromImage(bitmap); + g.DrawImage(source, 0, 0, width, height); + g.Dispose(); + + return bitmap; + } + + /// + /// Clone image. + /// + /// + /// Source image. + /// + /// Return clone of the source image. + /// + /// The original Bitmap.Clone() + /// does not produce the desired result - it does not create an actual clone (it does not create a copy + /// of the image). That is why this method was implemented to provide the functionality. + /// + public static Bitmap Clone(Bitmap source) + { + // lock source bitmap data + BitmapData sourceData = source.LockBits( + new Rectangle(0, 0, source.Width, source.Height), + ImageLockMode.ReadOnly, source.PixelFormat); + + // create new image + Bitmap destination = Clone(sourceData); + + // unlock source image + source.UnlockBits(sourceData); + + // + if ( + (source.PixelFormat == PixelFormat.Format1bppIndexed) || + (source.PixelFormat == PixelFormat.Format4bppIndexed) || + (source.PixelFormat == PixelFormat.Format8bppIndexed) || + (source.PixelFormat == PixelFormat.Indexed)) + { + ColorPalette srcPalette = source.Palette; + ColorPalette dstPalette = destination.Palette; + + int n = srcPalette.Entries.Length; + + // copy pallete + for (int i = 0; i < n; i++) + { + dstPalette.Entries[i] = srcPalette.Entries[i]; + } + + destination.Palette = dstPalette; + } + + return destination; + } + + /// + /// Clone image. + /// + /// + /// Source image data. + /// + /// Clones image from source image data. The message does not clone pallete in the + /// case if the source image has indexed pixel format. + /// + public static Bitmap Clone(BitmapData sourceData) + { + // get source image size + int width = sourceData.Width; + int height = sourceData.Height; + + // create new image + Bitmap destination = new Bitmap(width, height, sourceData.PixelFormat); + + // lock destination bitmap data + BitmapData destinationData = destination.LockBits( + new Rectangle(0, 0, width, height), + ImageLockMode.ReadWrite, destination.PixelFormat); + + AForge.SystemTools.CopyUnmanagedMemory(destinationData.Scan0, sourceData.Scan0, height * sourceData.Stride); + + // unlock destination image + destination.UnlockBits(destinationData); + + return destination; + } + + /// + /// Format an image. + /// + /// + /// Source image to format. + /// + /// Formats the image to one of the formats, which are supported + /// by the AForge.Imaging library. The image is left untouched in the + /// case if it is already of + /// Format24bppRgb or + /// Format32bppRgb or + /// Format32bppArgb or + /// Format48bppRgb or + /// Format64bppArgb + /// format or it is grayscale, otherwise the image + /// is converted to Format24bppRgb + /// format. + /// + /// The method is deprecated and method should + /// be used instead with specifying desired pixel format. + /// + /// + [Obsolete("Use Clone(Bitmap, PixelFormat) method instead and specify desired pixel format")] + public static void FormatImage(ref Bitmap image) + { + if ( + (image.PixelFormat != PixelFormat.Format24bppRgb) && + (image.PixelFormat != PixelFormat.Format32bppRgb) && + (image.PixelFormat != PixelFormat.Format32bppArgb) && + (image.PixelFormat != PixelFormat.Format48bppRgb) && + (image.PixelFormat != PixelFormat.Format64bppArgb) && + (image.PixelFormat != PixelFormat.Format16bppGrayScale) && + (IsGrayscale(image) == false) + ) + { + Bitmap tmp = image; + // convert to 24 bits per pixel + image = Clone(tmp, PixelFormat.Format24bppRgb); + // delete old image + tmp.Dispose(); + } + } + + /// + /// Load bitmap from file. + /// + /// + /// File name to load bitmap from. + /// + /// Returns loaded bitmap. + /// + /// The method is provided as an alternative of + /// method to solve the issues of locked file. The standard .NET's method locks the source file until + /// image's object is disposed, so the file can not be deleted or overwritten. This method workarounds the issue and + /// does not lock the source file. + /// + /// Sample usage: + /// + /// Bitmap image = AForge.Imaging.Image.FromFile( "test.jpg" ); + /// + /// + /// + public static System.Drawing.Bitmap FromFile(string fileName) + { + Bitmap loadedImage = null; + FileStream stream = null; + + try + { + // read image to temporary memory stream + stream = File.OpenRead(fileName); + MemoryStream memoryStream = new MemoryStream(); + + byte[] buffer = new byte[10000]; + while (true) + { + int read = stream.Read(buffer, 0, 10000); + + if (read == 0) + break; + + memoryStream.Write(buffer, 0, read); + } + + loadedImage = (Bitmap)Bitmap.FromStream(memoryStream); + } + finally + { + if (stream != null) + { + stream.Close(); + stream.Dispose(); + } + } + + return loadedImage; + } + + /// + /// Convert bitmap with 16 bits per plane to a bitmap with 8 bits per plane. + /// + /// + /// Source image to convert. + /// + /// Returns new image which is a copy of the source image but with 8 bits per plane. + /// + /// The routine does the next pixel format conversions: + /// + /// Format16bppGrayScale to + /// Format8bppIndexed with grayscale palette; + /// Format48bppRgb to + /// Format24bppRgb; + /// Format64bppArgb to + /// Format32bppArgb; + /// Format64bppPArgb to + /// Format32bppPArgb. + /// + /// + /// + /// Invalid pixel format of the source image. + /// + public static Bitmap Convert16bppTo8bpp(Bitmap bimap) + { + Bitmap newImage = null; + int layers = 0; + + // get image size + int width = bimap.Width; + int height = bimap.Height; + + // create new image depending on source image format + switch (bimap.PixelFormat) + { + case PixelFormat.Format16bppGrayScale: + // create new grayscale image + newImage = CreateGrayscaleImage(width, height); + layers = 1; + break; + + case PixelFormat.Format48bppRgb: + // create new color 24 bpp image + newImage = new Bitmap(width, height, PixelFormat.Format24bppRgb); + layers = 3; + break; + + case PixelFormat.Format64bppArgb: + // create new color 32 bpp image + newImage = new Bitmap(width, height, PixelFormat.Format32bppArgb); + layers = 4; + break; + + case PixelFormat.Format64bppPArgb: + // create new color 32 bpp image + newImage = new Bitmap(width, height, PixelFormat.Format32bppPArgb); + layers = 4; + break; + + default: + throw new UnsupportedImageFormatException("Invalid pixel format of the source image."); + } + + // lock both images + BitmapData sourceData = bimap.LockBits(new Rectangle(0, 0, width, height), + ImageLockMode.ReadOnly, bimap.PixelFormat); + BitmapData newData = newImage.LockBits(new Rectangle(0, 0, width, height), + ImageLockMode.ReadWrite, newImage.PixelFormat); + + unsafe + { + // base pointers + byte* sourceBasePtr = (byte*)sourceData.Scan0.ToPointer(); + byte* newBasePtr = (byte*)newData.Scan0.ToPointer(); + // image strides + int sourceStride = sourceData.Stride; + int newStride = newData.Stride; + + for (int y = 0; y < height; y++) + { + ushort* sourcePtr = (ushort*)(sourceBasePtr + y * sourceStride); + byte* newPtr = (byte*)(newBasePtr + y * newStride); + + for (int x = 0, lineSize = width * layers; x < lineSize; x++, sourcePtr++, newPtr++) + { + *newPtr = (byte)(*sourcePtr >> 8); + } + } + } + + // unlock both image + bimap.UnlockBits(sourceData); + newImage.UnlockBits(newData); + + return newImage; + } + + /// + /// Convert bitmap with 8 bits per plane to a bitmap with 16 bits per plane. + /// + /// + /// Source image to convert. + /// + /// Returns new image which is a copy of the source image but with 16 bits per plane. + /// + /// The routine does the next pixel format conversions: + /// + /// Format8bppIndexed (grayscale palette assumed) to + /// Format16bppGrayScale; + /// Format24bppRgb to + /// Format48bppRgb; + /// Format32bppArgb to + /// Format64bppArgb; + /// Format32bppPArgb to + /// Format64bppPArgb. + /// + /// + /// + /// Invalid pixel format of the source image. + /// + public static Bitmap Convert8bppTo16bpp(Bitmap bimap) + { + Bitmap newImage = null; + int layers = 0; + + // get image size + int width = bimap.Width; + int height = bimap.Height; + + // create new image depending on source image format + switch (bimap.PixelFormat) + { + case PixelFormat.Format8bppIndexed: + // create new grayscale image + newImage = new Bitmap(width, height, PixelFormat.Format16bppGrayScale); + layers = 1; + break; + + case PixelFormat.Format24bppRgb: + // create new color 48 bpp image + newImage = new Bitmap(width, height, PixelFormat.Format48bppRgb); + layers = 3; + break; + + case PixelFormat.Format32bppArgb: + // create new color 64 bpp image + newImage = new Bitmap(width, height, PixelFormat.Format64bppArgb); + layers = 4; + break; + + case PixelFormat.Format32bppPArgb: + // create new color 64 bpp image + newImage = new Bitmap(width, height, PixelFormat.Format64bppPArgb); + layers = 4; + break; + + default: + throw new UnsupportedImageFormatException("Invalid pixel format of the source image."); + } + + // lock both images + BitmapData sourceData = bimap.LockBits(new Rectangle(0, 0, width, height), + ImageLockMode.ReadOnly, bimap.PixelFormat); + BitmapData newData = newImage.LockBits(new Rectangle(0, 0, width, height), + ImageLockMode.ReadWrite, newImage.PixelFormat); + + unsafe + { + // base pointers + byte* sourceBasePtr = (byte*)sourceData.Scan0.ToPointer(); + byte* newBasePtr = (byte*)newData.Scan0.ToPointer(); + // image strides + int sourceStride = sourceData.Stride; + int newStride = newData.Stride; + + for (int y = 0; y < height; y++) + { + byte* sourcePtr = (byte*)(sourceBasePtr + y * sourceStride); + ushort* newPtr = (ushort*)(newBasePtr + y * newStride); + + for (int x = 0, lineSize = width * layers; x < lineSize; x++, sourcePtr++, newPtr++) + { + *newPtr = (ushort)(*sourcePtr << 8); + } + } + } + + // unlock both image + bimap.UnlockBits(sourceData); + newImage.UnlockBits(newData); + + return newImage; + } + } +} diff --git a/Sources/Accord.Imaging/AForge/ImageStatistics.cs b/Sources/Accord.Imaging/AForge/ImageStatistics.cs new file mode 100644 index 0000000000..cab8d791c --- /dev/null +++ b/Sources/Accord.Imaging/AForge/ImageStatistics.cs @@ -0,0 +1,644 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + using AForge.Math; + + /// + /// Gather statistics about image in RGB color space. + /// + /// + /// The class is used to accumulate statistical values about images, + /// like histogram, mean, standard deviation, etc. for each color channel in RGB color + /// space. + /// + /// The class accepts 8 bpp grayscale and 24/32 bpp color images for processing. + /// + /// Sample usage: + /// + /// // gather statistics + /// ImageStatistics stat = new ImageStatistics( image ); + /// // get red channel's histogram + /// Histogram red = stat.Red; + /// // check mean value of red channel + /// if ( red.Mean > 128 ) + /// { + /// // do further processing + /// } + /// + /// + /// + /// + /// + public class ImageStatistics + { + private Histogram red; + private Histogram green; + private Histogram blue; + private Histogram gray; + + private Histogram redWithoutBlack; + private Histogram greenWithoutBlack; + private Histogram blueWithoutBlack; + private Histogram grayWithoutBlack; + + private int pixels; + private int pixelsWithoutBlack; + + /// + /// Histogram of red channel. + /// + /// + /// The property is valid only for color images + /// (see property). + /// + public Histogram Red + { + get + { + if (red == null) + { + throw new InvalidImagePropertiesException(ExceptionMessage.ColorHistogramException); + } + return red; + } + } + + /// + /// Histogram of green channel. + /// + /// + /// The property is valid only for color images + /// (see property). + /// + public Histogram Green + { + get + { + if (green == null) + { + throw new InvalidImagePropertiesException(ExceptionMessage.ColorHistogramException); + } + return green; + } + } + + /// + /// Histogram of blue channel. + /// + /// + /// The property is valid only for color images + /// (see property). + /// + public Histogram Blue + { + get + { + if (blue == null) + { + throw new InvalidImagePropertiesException(ExceptionMessage.ColorHistogramException); + } + return blue; + } + } + + /// + /// Histogram of gray channel. + /// + /// + /// The property is valid only for grayscale images + /// (see property). + /// + public Histogram Gray + { + get + { + if (gray == null) + { + throw new InvalidImagePropertiesException(ExceptionMessage.GrayHistogramException); + } + return gray; + } + } + + /// + /// Histogram of red channel excluding black pixels. + /// + /// + /// The property keeps statistics about red channel, which + /// excludes all black pixels, what affects mean, standard deviation, etc. + /// + /// The property is valid only for color images + /// (see property). + /// + public Histogram RedWithoutBlack + { + get + { + if (redWithoutBlack == null) + { + throw new InvalidImagePropertiesException(ExceptionMessage.ColorHistogramException); + } + return redWithoutBlack; + } + } + + /// + /// Histogram of green channel excluding black pixels. + /// + /// + /// The property keeps statistics about green channel, which + /// excludes all black pixels, what affects mean, standard deviation, etc. + /// + /// The property is valid only for color images + /// (see property). + /// + public Histogram GreenWithoutBlack + { + get + { + if (greenWithoutBlack == null) + { + throw new InvalidImagePropertiesException(ExceptionMessage.ColorHistogramException); + } + return greenWithoutBlack; + } + } + + /// + /// Histogram of blue channel excluding black pixels + /// + /// + /// The property keeps statistics about blue channel, which + /// excludes all black pixels, what affects mean, standard deviation, etc. + /// + /// The property is valid only for color images + /// (see property). + /// + public Histogram BlueWithoutBlack + { + get + { + if (blueWithoutBlack == null) + { + throw new InvalidImagePropertiesException(ExceptionMessage.ColorHistogramException); + } + return blueWithoutBlack; + } + } + + /// + /// Histogram of gray channel channel excluding black pixels. + /// + /// + /// The property keeps statistics about gray channel, which + /// excludes all black pixels, what affects mean, standard deviation, etc. + /// + /// The property is valid only for grayscale images + /// (see property). + /// + public Histogram GrayWithoutBlack + { + get + { + if (grayWithoutBlack == null) + { + throw new InvalidImagePropertiesException(ExceptionMessage.GrayHistogramException); + } + return grayWithoutBlack; + } + } + + /// + /// Total pixels count in the processed image. + /// + /// + public int PixelsCount + { + get { return pixels; } + } + + /// + /// Total pixels count in the processed image excluding black pixels. + /// + /// + public int PixelsCountWithoutBlack + { + get { return pixelsWithoutBlack; } + } + + /// + /// Value wich specifies if the processed image was color or grayscale. + /// + /// + /// If the value is set to then + /// property should be used to get statistics information about image. Otherwise + /// , and properties should be used + /// for color images. + /// + public bool IsGrayscale + { + get { return (gray != null); } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Image to gather statistics about. + /// + /// Source pixel format is not supported. + /// + public ImageStatistics(Bitmap image) + { + CheckSourceFormat(image.PixelFormat); + + // lock bitmap data + BitmapData imageData = image.LockBits( + new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, image.PixelFormat); + + try + { + // gather statistics + unsafe + { + + ProcessImage(new UnmanagedImage(imageData), null, 0); + } + } + finally + { + // unlock image + image.UnlockBits(imageData); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Image to gather statistics about. + /// Mask image which specifies areas to collect statistics for. + /// + /// The mask image must be a grayscale/binary (8bpp) image of the same size as the + /// specified source image, where black pixels (value 0) correspond to areas which should be excluded + /// from processing. So statistics is calculated only for pixels, which are none black in the mask image. + /// + /// + /// Source pixel format is not supported. + /// Mask image must be 8 bpp grayscale image. + /// Mask must have the same size as the source image to get statistics for. + /// + public ImageStatistics(Bitmap image, Bitmap mask) + { + CheckSourceFormat(image.PixelFormat); + CheckMaskProperties(mask.PixelFormat, new Size(mask.Width, mask.Height), new Size(image.Width, image.Height)); + + // lock bitmap and mask data + BitmapData imageData = image.LockBits( + new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, image.PixelFormat); + BitmapData maskData = mask.LockBits( + new Rectangle(0, 0, mask.Width, mask.Height), + ImageLockMode.ReadOnly, mask.PixelFormat); + + try + { + // gather statistics + unsafe + { + ProcessImage(new UnmanagedImage(imageData), (byte*)maskData.Scan0.ToPointer(), maskData.Stride); + } + } + finally + { + // unlock images + image.UnlockBits(imageData); + mask.UnlockBits(maskData); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Image to gather statistics about. + /// Mask array which specifies areas to collect statistics for. + /// + /// The mask array must be of the same size as the specified source image, where 0 values + /// correspond to areas which should be excluded from processing. So statistics is calculated only for pixels, + /// which have none zero corresponding value in the mask. + /// + /// + /// Source pixel format is not supported. + /// Mask must have the same size as the source image to get statistics for. + /// + public ImageStatistics(Bitmap image, byte[,] mask) + { + CheckSourceFormat(image.PixelFormat); + CheckMaskProperties(PixelFormat.Format8bppIndexed, + new Size(mask.GetLength(1), mask.GetLength(0)), new Size(image.Width, image.Height)); + + // lock bitmap data + BitmapData imageData = image.LockBits( + new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, image.PixelFormat); + + try + { + // gather statistics + unsafe + { + fixed (byte* maskPtr = mask) + { + ProcessImage(new UnmanagedImage(imageData), maskPtr, mask.GetLength(1)); + } + } + } + finally + { + // unlock image + image.UnlockBits(imageData); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Unmanaged image to gather statistics about. + /// + /// Source pixel format is not supported. + /// + public ImageStatistics(UnmanagedImage image) + { + CheckSourceFormat(image.PixelFormat); + unsafe + { + ProcessImage(image, null, 0); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Image to gather statistics about. + /// Mask image which specifies areas to collect statistics for. + /// + /// The mask image must be a grayscale/binary (8bpp) image of the same size as the + /// specified source image, where black pixels (value 0) correspond to areas which should be excluded + /// from processing. So statistics is calculated only for pixels, which are none black in the mask image. + /// + /// + /// Source pixel format is not supported. + /// Mask image must be 8 bpp grayscale image. + /// Mask must have the same size as the source image to get statistics for. + /// + public ImageStatistics(UnmanagedImage image, UnmanagedImage mask) + { + CheckSourceFormat(image.PixelFormat); + CheckMaskProperties(mask.PixelFormat, new Size(mask.Width, mask.Height), new Size(image.Width, image.Height)); + + unsafe + { + ProcessImage(image, (byte*)mask.ImageData.ToPointer(), mask.Stride); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Image to gather statistics about. + /// Mask array which specifies areas to collect statistics for. + /// + /// The mask array must be of the same size as the specified source image, where 0 values + /// correspond to areas which should be excluded from processing. So statistics is calculated only for pixels, + /// which have none zero corresponding value in the mask. + /// + /// + /// Source pixel format is not supported. + /// Mask must have the same size as the source image to get statistics for. + /// + public ImageStatistics(UnmanagedImage image, byte[,] mask) + { + CheckSourceFormat(image.PixelFormat); + CheckMaskProperties(PixelFormat.Format8bppIndexed, + new Size(mask.GetLength(1), mask.GetLength(0)), new Size(image.Width, image.Height)); + + unsafe + { + fixed (byte* maskPtr = mask) + { + ProcessImage(image, maskPtr, mask.GetLength(1)); + } + } + } + + // Gather statistics for the specified image + private unsafe void ProcessImage(UnmanagedImage image, byte* mask, int maskLineSize) + { + // get image dimension + int width = image.Width; + int height = image.Height; + + pixels = pixelsWithoutBlack = 0; + + red = green = blue = gray = null; + redWithoutBlack = greenWithoutBlack = blueWithoutBlack = grayWithoutBlack = null; + + int maskOffset = maskLineSize - width; + + // check pixel format + if (image.PixelFormat == PixelFormat.Format8bppIndexed) + { + // alloc arrays + int[] g = new int[256]; + int[] gwb = new int[256]; + + byte value; + int offset = image.Stride - width; + + // do the job + byte* p = (byte*)image.ImageData.ToPointer(); + + if (mask == null) + { + // for each pixel + for (int y = 0; y < height; y++) + { + // for each pixel + for (int x = 0; x < width; x++, p++) + { + // get pixel value + value = *p; + + g[value]++; + pixels++; + + if (value != 0) + { + gwb[value]++; + pixelsWithoutBlack++; + } + } + p += offset; + } + } + else + { + // for each pixel + for (int y = 0; y < height; y++) + { + // for each pixel + for (int x = 0; x < width; x++, p++, mask++) + { + if (*mask == 0) + continue; + + // get pixel value + value = *p; + + g[value]++; + pixels++; + + if (value != 0) + { + gwb[value]++; + pixelsWithoutBlack++; + } + } + p += offset; + mask += maskOffset; + } + } + + // create historgram for gray level + gray = new Histogram(g); + grayWithoutBlack = new Histogram(gwb); + } + else + { + // alloc arrays + int[] r = new int[256]; + int[] g = new int[256]; + int[] b = new int[256]; + + int[] rwb = new int[256]; + int[] gwb = new int[256]; + int[] bwb = new int[256]; + + byte rValue, gValue, bValue; + int pixelSize = (image.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4; + int offset = image.Stride - width * pixelSize; + + // do the job + byte* p = (byte*)image.ImageData.ToPointer(); + + if (mask == null) + { + // for each line + for (int y = 0; y < height; y++) + { + // for each pixel + for (int x = 0; x < width; x++, p += pixelSize) + { + // get pixel values + rValue = p[RGB.R]; + gValue = p[RGB.G]; + bValue = p[RGB.B]; + + r[rValue]++; + g[gValue]++; + b[bValue]++; + pixels++; + + if ((rValue != 0) || (gValue != 0) || (bValue != 0)) + { + rwb[rValue]++; + gwb[gValue]++; + bwb[bValue]++; + pixelsWithoutBlack++; + } + } + p += offset; + } + } + else + { + // for each line + for (int y = 0; y < height; y++) + { + // for each pixel + for (int x = 0; x < width; x++, p += pixelSize, mask++) + { + if (*mask == 0) + continue; + + // get pixel values + rValue = p[RGB.R]; + gValue = p[RGB.G]; + bValue = p[RGB.B]; + + r[rValue]++; + g[gValue]++; + b[bValue]++; + pixels++; + + if ((rValue != 0) || (gValue != 0) || (bValue != 0)) + { + rwb[rValue]++; + gwb[gValue]++; + bwb[bValue]++; + pixelsWithoutBlack++; + } + } + p += offset; + mask += maskOffset; + } + } + + // create histograms + red = new Histogram(r); + green = new Histogram(g); + blue = new Histogram(b); + + redWithoutBlack = new Histogram(rwb); + greenWithoutBlack = new Histogram(gwb); + blueWithoutBlack = new Histogram(bwb); + } + } + + // Check pixel format of the source image + private static void CheckSourceFormat(PixelFormat pixelFormat) + { + if ((pixelFormat != PixelFormat.Format8bppIndexed) && + (pixelFormat != PixelFormat.Format24bppRgb) && + (pixelFormat != PixelFormat.Format32bppRgb) && + (pixelFormat != PixelFormat.Format32bppArgb)) + { + throw new UnsupportedImageFormatException("Source pixel format is not supported."); + } + } + + private static void CheckMaskProperties(PixelFormat maskFormat, Size maskSize, Size sourceImageSize) + { + if (maskFormat != PixelFormat.Format8bppIndexed) + throw new ArgumentException("Mask image must be 8 bpp grayscale image."); + + if ((maskSize.Width != sourceImageSize.Width) || (maskSize.Height != sourceImageSize.Height)) + throw new ArgumentException("Mask must have the same size as the source image to get statistics for."); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/ImageStatisticsHSL.cs b/Sources/Accord.Imaging/AForge/ImageStatisticsHSL.cs new file mode 100644 index 0000000000..afecccc3c --- /dev/null +++ b/Sources/Accord.Imaging/AForge/ImageStatisticsHSL.cs @@ -0,0 +1,428 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + using AForge; + using AForge.Math; + + /// + /// Gather statistics about image in HSL color space. + /// + /// + /// The class is used to accumulate statistical values about images, + /// like histogram, mean, standard deviation, etc. for each HSL color channel. + /// + /// The class accepts 24 and 32 bpp color images for processing. + /// + /// Sample usage: + /// + /// // gather statistics + /// ImageStatisticsHSL stat = new ImageStatisticsHSL( image ); + /// // get saturation channel's histogram + /// ContinuousHistogram saturation = stat.Saturation; + /// // check mean value of saturation channel + /// if ( saturation.Mean > 0.5 ) + /// { + /// // do further processing + /// } + /// + /// + /// + /// + /// + public class ImageStatisticsHSL + { + private ContinuousHistogram luminance; + private ContinuousHistogram saturation; + + private ContinuousHistogram luminanceWithoutBlack; + private ContinuousHistogram saturationWithoutBlack; + + private int pixels; + private int pixelsWithoutBlack; + + /// + /// Histogram of saturation channel. + /// + /// + public ContinuousHistogram Saturation + { + get { return saturation; } + } + + /// + /// Histogram of luminance channel. + /// + /// + public ContinuousHistogram Luminance + { + get { return luminance; } + } + + /// + /// Histogram of saturation channel excluding black pixels. + /// + /// + /// The property keeps statistics about saturation channel, which + /// excludes all black pixels, what affects mean, standard deviation, etc. + /// + /// + public ContinuousHistogram SaturationWithoutBlack + { + get { return saturationWithoutBlack; } + } + + /// + /// Histogram of luminance channel excluding black pixels. + /// + /// + /// The property keeps statistics about luminance channel, which + /// excludes all black pixels, what affects mean, standard deviation, etc. + /// + /// + public ContinuousHistogram LuminanceWithoutBlack + { + get { return luminanceWithoutBlack; } + } + + /// + /// Total pixels count in the processed image. + /// + /// + public int PixelsCount + { + get { return pixels; } + } + + /// + /// Total pixels count in the processed image excluding black pixels. + /// + /// + public int PixelsCountWithoutBlack + { + get { return pixelsWithoutBlack; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Image to gather statistics about. + /// + /// Source pixel format is not supported. + /// + public ImageStatisticsHSL(Bitmap image) + { + CheckSourceFormat(image.PixelFormat); + + // lock bitmap data + BitmapData imageData = image.LockBits( + new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); + + try + { + // gather statistics + unsafe + { + ProcessImage(new UnmanagedImage(imageData), null, 0); + } + } + finally + { + // unlock image + image.UnlockBits(imageData); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Image to gather statistics about. + /// Mask image which specifies areas to collect statistics for. + /// + /// The mask image must be a grayscale/binary (8bpp) image of the same size as the + /// specified source image, where black pixels (value 0) correspond to areas which should be excluded + /// from processing. So statistics is calculated only for pixels, which are none black in the mask image. + /// + /// + /// Source pixel format is not supported. + /// Mask image must be 8 bpp grayscale image. + /// Mask must have the same size as the source image to get statistics for. + /// + public ImageStatisticsHSL(Bitmap image, Bitmap mask) + { + CheckSourceFormat(image.PixelFormat); + CheckMaskProperties(mask.PixelFormat, new Size(mask.Width, mask.Height), new Size(image.Width, image.Height)); + + // lock bitmap and mask data + BitmapData imageData = image.LockBits( + new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, image.PixelFormat); + BitmapData maskData = mask.LockBits( + new Rectangle(0, 0, mask.Width, mask.Height), + ImageLockMode.ReadOnly, mask.PixelFormat); + + try + { + // gather statistics + unsafe + { + ProcessImage(new UnmanagedImage(imageData), (byte*)maskData.Scan0.ToPointer(), maskData.Stride); + } + } + finally + { + // unlock images + image.UnlockBits(imageData); + mask.UnlockBits(maskData); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Image to gather statistics about. + /// Mask array which specifies areas to collect statistics for. + /// + /// The mask array must be of the same size as the specified source image, where 0 values + /// correspond to areas which should be excluded from processing. So statistics is calculated only for pixels, + /// which have none zero corresponding value in the mask. + /// + /// + /// Source pixel format is not supported. + /// Mask must have the same size as the source image to get statistics for. + /// + public ImageStatisticsHSL(Bitmap image, byte[,] mask) + { + CheckSourceFormat(image.PixelFormat); + CheckMaskProperties(PixelFormat.Format8bppIndexed, + new Size(mask.GetLength(1), mask.GetLength(0)), new Size(image.Width, image.Height)); + + // lock bitmap data + BitmapData imageData = image.LockBits( + new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, image.PixelFormat); + + try + { + // gather statistics + unsafe + { + fixed (byte* maskPtr = mask) + { + ProcessImage(new UnmanagedImage(imageData), maskPtr, mask.GetLength(1)); + } + } + } + finally + { + // unlock image + image.UnlockBits(imageData); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Unmanaged image to gather statistics about. + /// + /// Source pixel format is not supported. + /// + public ImageStatisticsHSL(UnmanagedImage image) + { + CheckSourceFormat(image.PixelFormat); + unsafe + { + ProcessImage(image, null, 0); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Image to gather statistics about. + /// Mask image which specifies areas to collect statistics for. + /// + /// The mask image must be a grayscale/binary (8bpp) image of the same size as the + /// specified source image, where black pixels (value 0) correspond to areas which should be excluded + /// from processing. So statistics is calculated only for pixels, which are none black in the mask image. + /// + /// + /// Source pixel format is not supported. + /// Mask image must be 8 bpp grayscale image. + /// Mask must have the same size as the source image to get statistics for. + /// + public ImageStatisticsHSL(UnmanagedImage image, UnmanagedImage mask) + { + CheckSourceFormat(image.PixelFormat); + CheckMaskProperties(mask.PixelFormat, new Size(mask.Width, mask.Height), new Size(image.Width, image.Height)); + + unsafe + { + ProcessImage(image, (byte*)mask.ImageData.ToPointer(), mask.Stride); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Image to gather statistics about. + /// Mask array which specifies areas to collect statistics for. + /// + /// The mask array must be of the same size as the specified source image, where 0 values + /// correspond to areas which should be excluded from processing. So statistics is calculated only for pixels, + /// which have none zero corresponding value in the mask. + /// + /// + /// Source pixel format is not supported. + /// Mask must have the same size as the source image to get statistics for. + /// + public ImageStatisticsHSL(UnmanagedImage image, byte[,] mask) + { + CheckSourceFormat(image.PixelFormat); + CheckMaskProperties(PixelFormat.Format8bppIndexed, + new Size(mask.GetLength(1), mask.GetLength(0)), new Size(image.Width, image.Height)); + + unsafe + { + fixed (byte* maskPtr = mask) + { + ProcessImage(image, maskPtr, mask.GetLength(1)); + } + } + } + + // Gather statistics for the specified image + private unsafe void ProcessImage(UnmanagedImage image, byte* mask, int maskLineSize) + { + // get image dimension + int width = image.Width; + int height = image.Height; + + pixels = pixelsWithoutBlack = 0; + + int[] s = new int[256]; + int[] l = new int[256]; + int[] swb = new int[256]; + int[] lwb = new int[256]; + RGB rgb = new RGB(); + HSL hsl = new HSL(); + + int pixelSize = (image.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4; + int offset = image.Stride - width * pixelSize; + int maskOffset = maskLineSize - width; + + // do the job + byte* p = (byte*)image.ImageData.ToPointer(); + + if (mask == null) + { + // for each line + for (int y = 0; y < height; y++) + { + // for each pixel + for (int x = 0; x < width; x++, p += pixelSize) + { + rgb.Red = p[RGB.R]; + rgb.Green = p[RGB.G]; + rgb.Blue = p[RGB.B]; + + // convert to HSL color space + AForge.Imaging.HSL.FromRGB(rgb, hsl); + + s[(int)(hsl.Saturation * 255)]++; + l[(int)(hsl.Luminance * 255)]++; + pixels++; + + if (hsl.Luminance != 0.0) + { + swb[(int)(hsl.Saturation * 255)]++; + lwb[(int)(hsl.Luminance * 255)]++; + pixelsWithoutBlack++; + } + } + p += offset; + } + } + else + { + // for each line + for (int y = 0; y < height; y++) + { + // for each pixel + for (int x = 0; x < width; x++, p += pixelSize, mask++) + { + if (*mask == 0) + continue; + + rgb.Red = p[RGB.R]; + rgb.Green = p[RGB.G]; + rgb.Blue = p[RGB.B]; + + // convert to HSL color space + AForge.Imaging.HSL.FromRGB(rgb, hsl); + + s[(int)(hsl.Saturation * 255)]++; + l[(int)(hsl.Luminance * 255)]++; + pixels++; + + if (hsl.Luminance != 0.0) + { + swb[(int)(hsl.Saturation * 255)]++; + lwb[(int)(hsl.Luminance * 255)]++; + pixelsWithoutBlack++; + } + } + p += offset; + mask += maskOffset; + } + } + + // create histograms + saturation = new ContinuousHistogram(s, new Range(0, 1)); + luminance = new ContinuousHistogram(l, new Range(0, 1)); + + saturationWithoutBlack = new ContinuousHistogram(swb, new Range(0, 1)); + luminanceWithoutBlack = new ContinuousHistogram(lwb, new Range(0, 1)); + } + + // Check pixel format of the source image + private static void CheckSourceFormat(PixelFormat pixelFormat) + { + if ((pixelFormat != PixelFormat.Format24bppRgb) && + (pixelFormat != PixelFormat.Format32bppRgb) && + (pixelFormat != PixelFormat.Format32bppArgb)) + { + throw new UnsupportedImageFormatException("Source pixel format is not supported."); + } + } + + private static void CheckMaskProperties(PixelFormat maskFormat, Size maskSize, Size sourceImageSize) + { + if (maskFormat != PixelFormat.Format8bppIndexed) + { + throw new ArgumentException("Mask image must be 8 bpp grayscale image."); + } + + if ((maskSize.Width != sourceImageSize.Width) || (maskSize.Height != sourceImageSize.Height)) + { + throw new ArgumentException("Mask must have the same size as the source image to get statistics for."); + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/ImageStatisticsYCbCr.cs b/Sources/Accord.Imaging/AForge/ImageStatisticsYCbCr.cs new file mode 100644 index 0000000000..cbab21518 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/ImageStatisticsYCbCr.cs @@ -0,0 +1,462 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + using AForge; + using AForge.Math; + + /// + /// Gather statistics about image in YCbCr color space. + /// + /// + /// The class is used to accumulate statistical values about images, + /// like histogram, mean, standard deviation, etc. for each YCbCr color channel. + /// + /// The class accepts 24 and 32 bpp color images for processing. + /// + /// Sample usage: + /// + /// // gather statistics + /// ImageStatisticsYCbCr stat = new ImageStatisticsYCbCr( image ); + /// // get Y channel's histogram + /// ContinuousHistogram y = stat.Y; + /// // check mean value of Y channel + /// if ( y.Mean > 0.5 ) + /// { + /// // do further processing + /// } + /// + /// + /// + /// + /// + public class ImageStatisticsYCbCr + { + private ContinuousHistogram yHistogram; + private ContinuousHistogram cbHistogram; + private ContinuousHistogram crHistogram; + + private ContinuousHistogram yHistogramWithoutBlack; + private ContinuousHistogram cbHistogramWithoutBlack; + private ContinuousHistogram crHistogramWithoutBlack; + + private int pixels; + private int pixelsWithoutBlack; + + /// + /// Histogram of Y channel. + /// + /// + public ContinuousHistogram Y + { + get { return yHistogram; } + } + + /// + /// Histogram of Cb channel. + /// + /// + public ContinuousHistogram Cb + { + get { return cbHistogram; } + } + + /// + /// Histogram of Cr channel. + /// + /// + public ContinuousHistogram Cr + { + get { return crHistogram; } + } + + /// + /// Histogram of Y channel excluding black pixels. + /// + /// + /// The property keeps statistics about Y channel, which + /// excludes all black pixels, what affects mean, standard deviation, etc. + /// + /// + public ContinuousHistogram YWithoutBlack + { + get { return yHistogramWithoutBlack; } + } + + /// + /// Histogram of Cb channel excluding black pixels + /// + /// + /// The property keeps statistics about Cb channel, which + /// excludes all black pixels, what affects mean, standard deviation, etc. + /// + /// + public ContinuousHistogram CbWithoutBlack + { + get { return cbHistogramWithoutBlack; } + } + + /// + /// Histogram of Cr channel excluding black pixels + /// + /// + /// The property keeps statistics about Cr channel, which + /// excludes all black pixels, what affects mean, standard deviation, etc. + /// + /// + public ContinuousHistogram CrWithoutBlack + { + get { return crHistogramWithoutBlack; } + } + + /// + /// Total pixels count in the processed image. + /// + /// + public int PixelsCount + { + get { return pixels; } + } + + /// + /// Total pixels count in the processed image excluding black pixels. + /// + /// + public int PixelsCountWithoutBlack + { + get { return pixelsWithoutBlack; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Image to gather statistics about. + /// + /// Source pixel format is not supported. + /// + public ImageStatisticsYCbCr(Bitmap image) + { + CheckSourceFormat(image.PixelFormat); + + // lock bitmap data + BitmapData imageData = image.LockBits( + new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); + + try + { + // gather statistics + unsafe + { + ProcessImage(new UnmanagedImage(imageData), null, 0); + } + } + finally + { + // unlock image + image.UnlockBits(imageData); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Image to gather statistics about. + /// Mask image which specifies areas to collect statistics for. + /// + /// The mask image must be a grayscale/binary (8bpp) image of the same size as the + /// specified source image, where black pixels (value 0) correspond to areas which should be excluded + /// from processing. So statistics is calculated only for pixels, which are none black in the mask image. + /// + /// + /// Source pixel format is not supported. + /// Mask image must be 8 bpp grayscale image. + /// Mask must have the same size as the source image to get statistics for. + /// + public ImageStatisticsYCbCr(Bitmap image, Bitmap mask) + { + CheckSourceFormat(image.PixelFormat); + CheckMaskProperties(mask.PixelFormat, new Size(mask.Width, mask.Height), new Size(image.Width, image.Height)); + + // lock bitmap and mask data + BitmapData imageData = image.LockBits( + new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, image.PixelFormat); + BitmapData maskData = mask.LockBits( + new Rectangle(0, 0, mask.Width, mask.Height), + ImageLockMode.ReadOnly, mask.PixelFormat); + + try + { + // gather statistics + unsafe + { + ProcessImage(new UnmanagedImage(imageData), (byte*)maskData.Scan0.ToPointer(), maskData.Stride); + } + } + finally + { + // unlock images + image.UnlockBits(imageData); + mask.UnlockBits(maskData); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Image to gather statistics about. + /// Mask array which specifies areas to collect statistics for. + /// + /// The mask array must be of the same size as the specified source image, where 0 values + /// correspond to areas which should be excluded from processing. So statistics is calculated only for pixels, + /// which have none zero corresponding value in the mask. + /// + /// + /// Source pixel format is not supported. + /// Mask must have the same size as the source image to get statistics for. + /// + public ImageStatisticsYCbCr(Bitmap image, byte[,] mask) + { + CheckSourceFormat(image.PixelFormat); + CheckMaskProperties(PixelFormat.Format8bppIndexed, + new Size(mask.GetLength(1), mask.GetLength(0)), new Size(image.Width, image.Height)); + + // lock bitmap data + BitmapData imageData = image.LockBits( + new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, image.PixelFormat); + + try + { + // gather statistics + unsafe + { + fixed (byte* maskPtr = mask) + { + ProcessImage(new UnmanagedImage(imageData), maskPtr, mask.GetLength(1)); + } + } + } + finally + { + // unlock image + image.UnlockBits(imageData); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Unmanaged image to gather statistics about. + /// + /// Source pixel format is not supported. + /// + public ImageStatisticsYCbCr(UnmanagedImage image) + { + CheckSourceFormat(image.PixelFormat); + unsafe + { + ProcessImage(image, null, 0); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Image to gather statistics about. + /// Mask image which specifies areas to collect statistics for. + /// + /// The mask image must be a grayscale/binary (8bpp) image of the same size as the + /// specified source image, where black pixels (value 0) correspond to areas which should be excluded + /// from processing. So statistics is calculated only for pixels, which are none black in the mask image. + /// + /// + /// Source pixel format is not supported. + /// Mask image must be 8 bpp grayscale image. + /// Mask must have the same size as the source image to get statistics for. + /// + public ImageStatisticsYCbCr(UnmanagedImage image, UnmanagedImage mask) + { + CheckSourceFormat(image.PixelFormat); + CheckMaskProperties(mask.PixelFormat, new Size(mask.Width, mask.Height), new Size(image.Width, image.Height)); + + unsafe + { + ProcessImage(image, (byte*)mask.ImageData.ToPointer(), mask.Stride); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Image to gather statistics about. + /// Mask array which specifies areas to collect statistics for. + /// + /// The mask array must be of the same size as the specified source image, where 0 values + /// correspond to areas which should be excluded from processing. So statistics is calculated only for pixels, + /// which have none zero corresponding value in the mask. + /// + /// + /// Source pixel format is not supported. + /// Mask must have the same size as the source image to get statistics for. + /// + public ImageStatisticsYCbCr(UnmanagedImage image, byte[,] mask) + { + CheckSourceFormat(image.PixelFormat); + CheckMaskProperties(PixelFormat.Format8bppIndexed, + new Size(mask.GetLength(1), mask.GetLength(0)), new Size(image.Width, image.Height)); + + unsafe + { + fixed (byte* maskPtr = mask) + { + ProcessImage(image, maskPtr, mask.GetLength(1)); + } + } + } + + // Gather statistics for the specified image + private unsafe void ProcessImage(UnmanagedImage image, byte* mask, int maskLineSize) + { + // get image dimension + int width = image.Width; + int height = image.Height; + + pixels = pixelsWithoutBlack = 0; + + int[] yhisto = new int[256]; + int[] cbhisto = new int[256]; + int[] crhisto = new int[256]; + + int[] yhistoWB = new int[256]; + int[] cbhistoWB = new int[256]; + int[] crhistoWB = new int[256]; + + RGB rgb = new RGB(); + YCbCr ycbcr = new YCbCr(); + + int pixelSize = (image.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4; + int offset = image.Stride - width * pixelSize; + int maskOffset = maskLineSize - width; + + // do the job + byte* p = (byte*)image.ImageData.ToPointer(); + + if (mask == null) + { + // for each line + for (int y = 0; y < height; y++) + { + // for each pixel + for (int x = 0; x < width; x++, p += pixelSize) + { + rgb.Red = p[RGB.R]; + rgb.Green = p[RGB.G]; + rgb.Blue = p[RGB.B]; + + // convert to YCbCr color space + AForge.Imaging.YCbCr.FromRGB(rgb, ycbcr); + + yhisto[(int)(ycbcr.Y * 255)]++; + cbhisto[(int)((ycbcr.Cb + 0.5) * 255)]++; + crhisto[(int)((ycbcr.Cr + 0.5) * 255)]++; + + pixels++; + + if ((ycbcr.Y != 0.0) || (ycbcr.Cb != 0.0) || (ycbcr.Cr != 0.0)) + { + yhistoWB[(int)(ycbcr.Y * 255)]++; + cbhistoWB[(int)((ycbcr.Cb + 0.5) * 255)]++; + crhistoWB[(int)((ycbcr.Cr + 0.5) * 255)]++; + + pixelsWithoutBlack++; + } + } + p += offset; + } + } + else + { + // for each line + for (int y = 0; y < height; y++) + { + // for each pixel + for (int x = 0; x < width; x++, p += pixelSize, mask++) + { + if (*mask == 0) + continue; + + rgb.Red = p[RGB.R]; + rgb.Green = p[RGB.G]; + rgb.Blue = p[RGB.B]; + + // convert to YCbCr color space + AForge.Imaging.YCbCr.FromRGB(rgb, ycbcr); + + yhisto[(int)(ycbcr.Y * 255)]++; + cbhisto[(int)((ycbcr.Cb + 0.5) * 255)]++; + crhisto[(int)((ycbcr.Cr + 0.5) * 255)]++; + + pixels++; + + if ((ycbcr.Y != 0.0) || (ycbcr.Cb != 0.0) || (ycbcr.Cr != 0.0)) + { + yhistoWB[(int)(ycbcr.Y * 255)]++; + cbhistoWB[(int)((ycbcr.Cb + 0.5) * 255)]++; + crhistoWB[(int)((ycbcr.Cr + 0.5) * 255)]++; + + pixelsWithoutBlack++; + } + } + p += offset; + mask += maskOffset; + } + } + + // create histograms + yHistogram = new ContinuousHistogram(yhisto, new Range(0.0f, 1.0f)); + cbHistogram = new ContinuousHistogram(cbhisto, new Range(-0.5f, 0.5f)); + crHistogram = new ContinuousHistogram(crhisto, new Range(-0.5f, 0.5f)); + + yHistogramWithoutBlack = new ContinuousHistogram(yhistoWB, new Range(0.0f, 1.0f)); + cbHistogramWithoutBlack = new ContinuousHistogram(cbhistoWB, new Range(-0.5f, 0.5f)); + crHistogramWithoutBlack = new ContinuousHistogram(crhistoWB, new Range(-0.5f, 0.5f)); + } + + // Check pixel format of the source image + private static void CheckSourceFormat(PixelFormat pixelFormat) + { + if ((pixelFormat != PixelFormat.Format24bppRgb) && + (pixelFormat != PixelFormat.Format32bppRgb) && + (pixelFormat != PixelFormat.Format32bppArgb)) + { + throw new UnsupportedImageFormatException("Source pixel format is not supported."); + } + } + + private static void CheckMaskProperties(PixelFormat maskFormat, Size maskSize, Size sourceImageSize) + { + if (maskFormat != PixelFormat.Format8bppIndexed) + throw new ArgumentException("Mask image must be 8 bpp grayscale image."); + + if ((maskSize.Width != sourceImageSize.Width) || (maskSize.Height != sourceImageSize.Height)) + throw new ArgumentException("Mask must have the same size as the source image to get statistics for."); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Images/adaptive_smooth.png b/Sources/Accord.Imaging/AForge/Images/adaptive_smooth.png new file mode 100644 index 0000000000..aae83e0a4 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/adaptive_smooth.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/add.png b/Sources/Accord.Imaging/AForge/Images/add.png new file mode 100644 index 0000000000..167d851bc Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/add.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/additive_noise.jpg b/Sources/Accord.Imaging/AForge/Images/additive_noise.jpg new file mode 100644 index 0000000000..013a9cc81 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/additive_noise.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/anaglyph.png b/Sources/Accord.Imaging/AForge/Images/anaglyph.png new file mode 100644 index 0000000000..5fef26bd2 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/anaglyph.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/anaglyph_glasses.png b/Sources/Accord.Imaging/AForge/Images/anaglyph_glasses.png new file mode 100644 index 0000000000..1c97f6a0d Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/anaglyph_glasses.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/background.jpg b/Sources/Accord.Imaging/AForge/Images/background.jpg new file mode 100644 index 0000000000..854058ebb Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/background.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/backward_quadrilateral.jpg b/Sources/Accord.Imaging/AForge/Images/backward_quadrilateral.jpg new file mode 100644 index 0000000000..d4ac67862 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/backward_quadrilateral.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/bayer_dithering.jpg b/Sources/Accord.Imaging/AForge/Images/bayer_dithering.jpg new file mode 100644 index 0000000000..75810023c Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/bayer_dithering.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/bayer_filter.jpg b/Sources/Accord.Imaging/AForge/Images/bayer_filter.jpg new file mode 100644 index 0000000000..846005b65 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/bayer_filter.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/bg.jpg b/Sources/Accord.Imaging/AForge/Images/bg.jpg new file mode 100644 index 0000000000..4f93a1712 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/bg.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/biggest_blob.jpg b/Sources/Accord.Imaging/AForge/Images/biggest_blob.jpg new file mode 100644 index 0000000000..fccc65bee Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/biggest_blob.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/bilateral.jpg b/Sources/Accord.Imaging/AForge/Images/bilateral.jpg new file mode 100644 index 0000000000..c88803d99 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/bilateral.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/blobs_filtering.jpg b/Sources/Accord.Imaging/AForge/Images/blobs_filtering.jpg new file mode 100644 index 0000000000..f550f0802 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/blobs_filtering.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/blur.jpg b/Sources/Accord.Imaging/AForge/Images/blur.jpg new file mode 100644 index 0000000000..8468f0daf Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/blur.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/bottomhat.png b/Sources/Accord.Imaging/AForge/Images/bottomhat.png new file mode 100644 index 0000000000..372c01020 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/bottomhat.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/bradley_local_thresholding.png b/Sources/Accord.Imaging/AForge/Images/bradley_local_thresholding.png new file mode 100644 index 0000000000..8f58c246c Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/bradley_local_thresholding.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/brightness_correction.jpg b/Sources/Accord.Imaging/AForge/Images/brightness_correction.jpg new file mode 100644 index 0000000000..3e836eaa2 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/brightness_correction.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/burkes.jpg b/Sources/Accord.Imaging/AForge/Images/burkes.jpg new file mode 100644 index 0000000000..66c3d3da0 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/burkes.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/canny_edges.png b/Sources/Accord.Imaging/AForge/Images/canny_edges.png new file mode 100644 index 0000000000..3005c5110 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/canny_edges.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/canvas_crop.jpg b/Sources/Accord.Imaging/AForge/Images/canvas_crop.jpg new file mode 100644 index 0000000000..a8e16f9d3 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/canvas_crop.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/canvas_move.jpg b/Sources/Accord.Imaging/AForge/Images/canvas_move.jpg new file mode 100644 index 0000000000..0afd17398 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/canvas_move.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/channel_filtering.jpg b/Sources/Accord.Imaging/AForge/Images/channel_filtering.jpg new file mode 100644 index 0000000000..0bfa5aa61 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/channel_filtering.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/closing.png b/Sources/Accord.Imaging/AForge/Images/closing.png new file mode 100644 index 0000000000..819c5a682 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/closing.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/clouds_texture.jpg b/Sources/Accord.Imaging/AForge/Images/clouds_texture.jpg new file mode 100644 index 0000000000..9fad06fe1 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/clouds_texture.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/color_burkes.png b/Sources/Accord.Imaging/AForge/Images/color_burkes.png new file mode 100644 index 0000000000..5c0899990 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/color_burkes.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/color_filtering.jpg b/Sources/Accord.Imaging/AForge/Images/color_filtering.jpg new file mode 100644 index 0000000000..906bd6bd6 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/color_filtering.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/color_floyd_steinberg.png b/Sources/Accord.Imaging/AForge/Images/color_floyd_steinberg.png new file mode 100644 index 0000000000..0b8361291 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/color_floyd_steinberg.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/color_jarvis_judice_ninke.png b/Sources/Accord.Imaging/AForge/Images/color_jarvis_judice_ninke.png new file mode 100644 index 0000000000..184023f57 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/color_jarvis_judice_ninke.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/color_remapping.jpg b/Sources/Accord.Imaging/AForge/Images/color_remapping.jpg new file mode 100644 index 0000000000..754386d88 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/color_remapping.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/color_sierra.png b/Sources/Accord.Imaging/AForge/Images/color_sierra.png new file mode 100644 index 0000000000..cbed5e770 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/color_sierra.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/color_stucki.png b/Sources/Accord.Imaging/AForge/Images/color_stucki.png new file mode 100644 index 0000000000..ff5a4bc75 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/color_stucki.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/conservative_smoothing.png b/Sources/Accord.Imaging/AForge/Images/conservative_smoothing.png new file mode 100644 index 0000000000..3bd6964ef Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/conservative_smoothing.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/contrast_correction.jpg b/Sources/Accord.Imaging/AForge/Images/contrast_correction.jpg new file mode 100644 index 0000000000..6d5c32272 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/contrast_correction.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/contrast_stretch.jpg b/Sources/Accord.Imaging/AForge/Images/contrast_stretch.jpg new file mode 100644 index 0000000000..41414a1af Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/contrast_stretch.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/crop.jpg b/Sources/Accord.Imaging/AForge/Images/crop.jpg new file mode 100644 index 0000000000..629d85f03 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/crop.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/deskew.png b/Sources/Accord.Imaging/AForge/Images/deskew.png new file mode 100644 index 0000000000..b33da3368 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/deskew.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/difference.png b/Sources/Accord.Imaging/AForge/Images/difference.png new file mode 100644 index 0000000000..02b8bb026 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/difference.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/difference_edges.png b/Sources/Accord.Imaging/AForge/Images/difference_edges.png new file mode 100644 index 0000000000..83e09a375 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/difference_edges.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/dilatation.png b/Sources/Accord.Imaging/AForge/Images/dilatation.png new file mode 100644 index 0000000000..929fa1df0 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/dilatation.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/ebm_result.png b/Sources/Accord.Imaging/AForge/Images/ebm_result.png new file mode 100644 index 0000000000..9d7a987c8 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/ebm_result.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/ebm_sample1.png b/Sources/Accord.Imaging/AForge/Images/ebm_sample1.png new file mode 100644 index 0000000000..3a27d210b Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/ebm_sample1.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/ebm_sample2.png b/Sources/Accord.Imaging/AForge/Images/ebm_sample2.png new file mode 100644 index 0000000000..1913c397e Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/ebm_sample2.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/edges.png b/Sources/Accord.Imaging/AForge/Images/edges.png new file mode 100644 index 0000000000..31366fb8d Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/edges.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/emboss.jpg b/Sources/Accord.Imaging/AForge/Images/emboss.jpg new file mode 100644 index 0000000000..57e6e36ac Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/emboss.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/equalized.jpg b/Sources/Accord.Imaging/AForge/Images/equalized.jpg new file mode 100644 index 0000000000..384042c22 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/equalized.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/erosion.png b/Sources/Accord.Imaging/AForge/Images/erosion.png new file mode 100644 index 0000000000..2140fcfd9 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/erosion.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/euclidean_filtering.jpg b/Sources/Accord.Imaging/AForge/Images/euclidean_filtering.jpg new file mode 100644 index 0000000000..bbf2e90a8 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/euclidean_filtering.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/extract_channel.jpg b/Sources/Accord.Imaging/AForge/Images/extract_channel.jpg new file mode 100644 index 0000000000..629aacb2c Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/extract_channel.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/filled_holes.png b/Sources/Accord.Imaging/AForge/Images/filled_holes.png new file mode 100644 index 0000000000..958d62be2 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/filled_holes.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/flat_field.jpg b/Sources/Accord.Imaging/AForge/Images/flat_field.jpg new file mode 100644 index 0000000000..fe15b20bf Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/flat_field.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/floyd_steinberg.jpg b/Sources/Accord.Imaging/AForge/Images/floyd_steinberg.jpg new file mode 100644 index 0000000000..51f6e8734 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/floyd_steinberg.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/fourier.jpg b/Sources/Accord.Imaging/AForge/Images/fourier.jpg new file mode 100644 index 0000000000..4fc455828 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/fourier.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/frequency_filter.jpg b/Sources/Accord.Imaging/AForge/Images/frequency_filter.jpg new file mode 100644 index 0000000000..fa316df2b Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/frequency_filter.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/from_polar.png b/Sources/Accord.Imaging/AForge/Images/from_polar.png new file mode 100644 index 0000000000..23bdaf2fc Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/from_polar.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/gamma.jpg b/Sources/Accord.Imaging/AForge/Images/gamma.jpg new file mode 100644 index 0000000000..ffeae15be Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/gamma.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/gaussian_blur.jpg b/Sources/Accord.Imaging/AForge/Images/gaussian_blur.jpg new file mode 100644 index 0000000000..88d24e3de Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/gaussian_blur.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/gaussian_sharpen.jpg b/Sources/Accord.Imaging/AForge/Images/gaussian_sharpen.jpg new file mode 100644 index 0000000000..1914b4022 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/gaussian_sharpen.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/grayscale.jpg b/Sources/Accord.Imaging/AForge/Images/grayscale.jpg new file mode 100644 index 0000000000..b9e45e732 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/grayscale.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/hit-and-miss.png b/Sources/Accord.Imaging/AForge/Images/hit-and-miss.png new file mode 100644 index 0000000000..cd4107ad4 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/hit-and-miss.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/homogenity_edges.png b/Sources/Accord.Imaging/AForge/Images/homogenity_edges.png new file mode 100644 index 0000000000..8c2041fdf Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/homogenity_edges.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/hor_histogram.jpg b/Sources/Accord.Imaging/AForge/Images/hor_histogram.jpg new file mode 100644 index 0000000000..f6feefac0 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/hor_histogram.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/hough_circles.jpg b/Sources/Accord.Imaging/AForge/Images/hough_circles.jpg new file mode 100644 index 0000000000..b44706f2d Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/hough_circles.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/hough_lines.jpg b/Sources/Accord.Imaging/AForge/Images/hough_lines.jpg new file mode 100644 index 0000000000..3e28c7f7e Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/hough_lines.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/hrls.png b/Sources/Accord.Imaging/AForge/Images/hrls.png new file mode 100644 index 0000000000..8329d8ae5 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/hrls.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/hsl_filtering.jpg b/Sources/Accord.Imaging/AForge/Images/hsl_filtering.jpg new file mode 100644 index 0000000000..a73ee9d4b Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/hsl_filtering.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/hsl_filtering2.jpg b/Sources/Accord.Imaging/AForge/Images/hsl_filtering2.jpg new file mode 100644 index 0000000000..60003abe7 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/hsl_filtering2.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/hsl_linear.jpg b/Sources/Accord.Imaging/AForge/Images/hsl_linear.jpg new file mode 100644 index 0000000000..d785e8a8d Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/hsl_linear.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/hue_modifier.jpg b/Sources/Accord.Imaging/AForge/Images/hue_modifier.jpg new file mode 100644 index 0000000000..6932a0854 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/hue_modifier.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/icon.png b/Sources/Accord.Imaging/AForge/Images/icon.png new file mode 100644 index 0000000000..58dde97b3 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/icon.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/image_warp.png b/Sources/Accord.Imaging/AForge/Images/image_warp.png new file mode 100644 index 0000000000..0dde51ad9 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/image_warp.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/intersect.png b/Sources/Accord.Imaging/AForge/Images/intersect.png new file mode 100644 index 0000000000..89d25758b Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/intersect.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/invert.jpg b/Sources/Accord.Imaging/AForge/Images/invert.jpg new file mode 100644 index 0000000000..780a944cd Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/invert.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/iterative_threshold.png b/Sources/Accord.Imaging/AForge/Images/iterative_threshold.png new file mode 100644 index 0000000000..509574e2f Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/iterative_threshold.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/jarvis_judice_ninke.jpg b/Sources/Accord.Imaging/AForge/Images/jarvis_judice_ninke.jpg new file mode 100644 index 0000000000..9745cf541 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/jarvis_judice_ninke.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/jitter.jpg b/Sources/Accord.Imaging/AForge/Images/jitter.jpg new file mode 100644 index 0000000000..966ef1a70 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/jitter.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/labeling.jpg b/Sources/Accord.Imaging/AForge/Images/labeling.jpg new file mode 100644 index 0000000000..f2cddb941 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/labeling.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/labyrinth_texture.jpg b/Sources/Accord.Imaging/AForge/Images/labyrinth_texture.jpg new file mode 100644 index 0000000000..9249b67f0 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/labyrinth_texture.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/levels_linear.jpg b/Sources/Accord.Imaging/AForge/Images/levels_linear.jpg new file mode 100644 index 0000000000..67337aacc Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/levels_linear.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/marble_texture.jpg b/Sources/Accord.Imaging/AForge/Images/marble_texture.jpg new file mode 100644 index 0000000000..46e130769 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/marble_texture.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/mask.png b/Sources/Accord.Imaging/AForge/Images/mask.png new file mode 100644 index 0000000000..6b1321342 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/mask.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/masked_image.jpg b/Sources/Accord.Imaging/AForge/Images/masked_image.jpg new file mode 100644 index 0000000000..673432aae Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/masked_image.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/mean.png b/Sources/Accord.Imaging/AForge/Images/mean.png new file mode 100644 index 0000000000..6e44cd169 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/mean.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/median.png b/Sources/Accord.Imaging/AForge/Images/median.png new file mode 100644 index 0000000000..aaceed41e Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/median.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/merge.png b/Sources/Accord.Imaging/AForge/Images/merge.png new file mode 100644 index 0000000000..cde7bdcb0 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/merge.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/mirror.jpg b/Sources/Accord.Imaging/AForge/Images/mirror.jpg new file mode 100644 index 0000000000..229d32279 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/mirror.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/morph.png b/Sources/Accord.Imaging/AForge/Images/morph.png new file mode 100644 index 0000000000..34f786a06 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/morph.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/move_towards.png b/Sources/Accord.Imaging/AForge/Images/move_towards.png new file mode 100644 index 0000000000..e1906c506 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/move_towards.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/object.jpg b/Sources/Accord.Imaging/AForge/Images/object.jpg new file mode 100644 index 0000000000..1154e3342 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/object.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/oil_painting.jpg b/Sources/Accord.Imaging/AForge/Images/oil_painting.jpg new file mode 100644 index 0000000000..399c88f7b Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/oil_painting.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/opening.png b/Sources/Accord.Imaging/AForge/Images/opening.png new file mode 100644 index 0000000000..fa991fa99 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/opening.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/ordered_color_dithering.png b/Sources/Accord.Imaging/AForge/Images/ordered_color_dithering.png new file mode 100644 index 0000000000..4d3f902cf Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/ordered_color_dithering.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/ordered_dithering.jpg b/Sources/Accord.Imaging/AForge/Images/ordered_dithering.jpg new file mode 100644 index 0000000000..8a4c3bb91 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/ordered_dithering.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/otsu_threshold.png b/Sources/Accord.Imaging/AForge/Images/otsu_threshold.png new file mode 100644 index 0000000000..394fbbf79 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/otsu_threshold.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/pixellate.jpg b/Sources/Accord.Imaging/AForge/Images/pixellate.jpg new file mode 100644 index 0000000000..d77e459a3 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/pixellate.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/pointed_color_fill.jpg b/Sources/Accord.Imaging/AForge/Images/pointed_color_fill.jpg new file mode 100644 index 0000000000..8014ecb44 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/pointed_color_fill.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/pointed_mean_fill.jpg b/Sources/Accord.Imaging/AForge/Images/pointed_mean_fill.jpg new file mode 100644 index 0000000000..053d5e88a Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/pointed_mean_fill.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/polar.png b/Sources/Accord.Imaging/AForge/Images/polar.png new file mode 100644 index 0000000000..d6217e8fe Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/polar.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/posterization.png b/Sources/Accord.Imaging/AForge/Images/posterization.png new file mode 100644 index 0000000000..87e0f71f3 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/posterization.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/quadrilateral_bilinear.png b/Sources/Accord.Imaging/AForge/Images/quadrilateral_bilinear.png new file mode 100644 index 0000000000..34c98face Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/quadrilateral_bilinear.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/quadrilateral_ex_bilinear.png b/Sources/Accord.Imaging/AForge/Images/quadrilateral_ex_bilinear.png new file mode 100644 index 0000000000..e582c0185 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/quadrilateral_ex_bilinear.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/quadrilateral_finder.png b/Sources/Accord.Imaging/AForge/Images/quadrilateral_finder.png new file mode 100644 index 0000000000..9392825bc Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/quadrilateral_finder.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/quadrilateral_nearest.png b/Sources/Accord.Imaging/AForge/Images/quadrilateral_nearest.png new file mode 100644 index 0000000000..fe929876c Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/quadrilateral_nearest.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/reduced_colors.png b/Sources/Accord.Imaging/AForge/Images/reduced_colors.png new file mode 100644 index 0000000000..ce76c2516 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/reduced_colors.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/replace_channel.jpg b/Sources/Accord.Imaging/AForge/Images/replace_channel.jpg new file mode 100644 index 0000000000..21dc4fa96 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/replace_channel.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/resize_bicubic.png b/Sources/Accord.Imaging/AForge/Images/resize_bicubic.png new file mode 100644 index 0000000000..3b6be16da Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/resize_bicubic.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/resize_bilinear.png b/Sources/Accord.Imaging/AForge/Images/resize_bilinear.png new file mode 100644 index 0000000000..0395178d9 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/resize_bilinear.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/resize_nearest.png b/Sources/Accord.Imaging/AForge/Images/resize_nearest.png new file mode 100644 index 0000000000..a7748c9f9 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/resize_nearest.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/rotate_bicubic.png b/Sources/Accord.Imaging/AForge/Images/rotate_bicubic.png new file mode 100644 index 0000000000..6a8bc9280 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/rotate_bicubic.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/rotate_bilinear.png b/Sources/Accord.Imaging/AForge/Images/rotate_bilinear.png new file mode 100644 index 0000000000..de9189bd4 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/rotate_bilinear.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/rotate_channels.jpg b/Sources/Accord.Imaging/AForge/Images/rotate_channels.jpg new file mode 100644 index 0000000000..d5c8aae2d Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/rotate_channels.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/rotate_nearest.png b/Sources/Accord.Imaging/AForge/Images/rotate_nearest.png new file mode 100644 index 0000000000..9f9c99fe7 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/rotate_nearest.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/salt_noise.jpg b/Sources/Accord.Imaging/AForge/Images/salt_noise.jpg new file mode 100644 index 0000000000..14b1d51cb Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/salt_noise.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/sample1.jpg b/Sources/Accord.Imaging/AForge/Images/sample1.jpg new file mode 100644 index 0000000000..909fa4fc5 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sample1.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/sample10.png b/Sources/Accord.Imaging/AForge/Images/sample10.png new file mode 100644 index 0000000000..68f3b0d9c Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sample10.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/sample11.png b/Sources/Accord.Imaging/AForge/Images/sample11.png new file mode 100644 index 0000000000..8c336f951 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sample11.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/sample12.png b/Sources/Accord.Imaging/AForge/Images/sample12.png new file mode 100644 index 0000000000..a84612eda Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sample12.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/sample13.png b/Sources/Accord.Imaging/AForge/Images/sample13.png new file mode 100644 index 0000000000..f35fdf726 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sample13.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/sample14.png b/Sources/Accord.Imaging/AForge/Images/sample14.png new file mode 100644 index 0000000000..a7f5ad9f6 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sample14.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/sample15.png b/Sources/Accord.Imaging/AForge/Images/sample15.png new file mode 100644 index 0000000000..d11df2750 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sample15.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/sample16_left.png b/Sources/Accord.Imaging/AForge/Images/sample16_left.png new file mode 100644 index 0000000000..1b47a2772 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sample16_left.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/sample16_right.png b/Sources/Accord.Imaging/AForge/Images/sample16_right.png new file mode 100644 index 0000000000..8b4d48463 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sample16_right.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/sample17.png b/Sources/Accord.Imaging/AForge/Images/sample17.png new file mode 100644 index 0000000000..9e5f881c4 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sample17.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/sample18.jpg b/Sources/Accord.Imaging/AForge/Images/sample18.jpg new file mode 100644 index 0000000000..c124f8f23 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sample18.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/sample19.png b/Sources/Accord.Imaging/AForge/Images/sample19.png new file mode 100644 index 0000000000..1d0214888 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sample19.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/sample2.jpg b/Sources/Accord.Imaging/AForge/Images/sample2.jpg new file mode 100644 index 0000000000..623daed99 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sample2.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/sample20.png b/Sources/Accord.Imaging/AForge/Images/sample20.png new file mode 100644 index 0000000000..8aea767ab Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sample20.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/sample21.png b/Sources/Accord.Imaging/AForge/Images/sample21.png new file mode 100644 index 0000000000..d42df7d83 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sample21.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/sample22.png b/Sources/Accord.Imaging/AForge/Images/sample22.png new file mode 100644 index 0000000000..f7871b4c1 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sample22.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/sample23.png b/Sources/Accord.Imaging/AForge/Images/sample23.png new file mode 100644 index 0000000000..88fdc6900 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sample23.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/sample24.png b/Sources/Accord.Imaging/AForge/Images/sample24.png new file mode 100644 index 0000000000..b3cc13f71 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sample24.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/sample3.jpg b/Sources/Accord.Imaging/AForge/Images/sample3.jpg new file mode 100644 index 0000000000..576b0f28b Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sample3.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/sample4.jpg b/Sources/Accord.Imaging/AForge/Images/sample4.jpg new file mode 100644 index 0000000000..06f627681 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sample4.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/sample5.jpg b/Sources/Accord.Imaging/AForge/Images/sample5.jpg new file mode 100644 index 0000000000..7b4be68c8 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sample5.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/sample6.png b/Sources/Accord.Imaging/AForge/Images/sample6.png new file mode 100644 index 0000000000..11977912c Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sample6.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/sample7.png b/Sources/Accord.Imaging/AForge/Images/sample7.png new file mode 100644 index 0000000000..eb49967ce Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sample7.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/sample8.jpg b/Sources/Accord.Imaging/AForge/Images/sample8.jpg new file mode 100644 index 0000000000..564b5b6bf Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sample8.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/sample9.png b/Sources/Accord.Imaging/AForge/Images/sample9.png new file mode 100644 index 0000000000..8cdb3e87d Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sample9.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/saturation_correction.jpg b/Sources/Accord.Imaging/AForge/Images/saturation_correction.jpg new file mode 100644 index 0000000000..654e6505d Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/saturation_correction.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/sepia.jpg b/Sources/Accord.Imaging/AForge/Images/sepia.jpg new file mode 100644 index 0000000000..549333bb5 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sepia.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/sharpen.jpg b/Sources/Accord.Imaging/AForge/Images/sharpen.jpg new file mode 100644 index 0000000000..5b1d8c0ad Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sharpen.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/shrink.jpg b/Sources/Accord.Imaging/AForge/Images/shrink.jpg new file mode 100644 index 0000000000..284220b13 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/shrink.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/sierra.jpg b/Sources/Accord.Imaging/AForge/Images/sierra.jpg new file mode 100644 index 0000000000..05a8d7c87 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sierra.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/simple_skeletonization.png b/Sources/Accord.Imaging/AForge/Images/simple_skeletonization.png new file mode 100644 index 0000000000..4cde20ff8 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/simple_skeletonization.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/sis_threshold.png b/Sources/Accord.Imaging/AForge/Images/sis_threshold.png new file mode 100644 index 0000000000..2478efd19 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sis_threshold.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/sobel_edges.png b/Sources/Accord.Imaging/AForge/Images/sobel_edges.png new file mode 100644 index 0000000000..8a8e13466 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/sobel_edges.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/stucki.jpg b/Sources/Accord.Imaging/AForge/Images/stucki.jpg new file mode 100644 index 0000000000..fcbd456bf Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/stucki.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/subtract.png b/Sources/Accord.Imaging/AForge/Images/subtract.png new file mode 100644 index 0000000000..989093400 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/subtract.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/susan_corners.png b/Sources/Accord.Imaging/AForge/Images/susan_corners.png new file mode 100644 index 0000000000..df6afa97e Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/susan_corners.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/textile_texture.jpg b/Sources/Accord.Imaging/AForge/Images/textile_texture.jpg new file mode 100644 index 0000000000..d2a8cba92 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/textile_texture.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/textured_filter1.jpg b/Sources/Accord.Imaging/AForge/Images/textured_filter1.jpg new file mode 100644 index 0000000000..ceda6495b Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/textured_filter1.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/textured_filter2.jpg b/Sources/Accord.Imaging/AForge/Images/textured_filter2.jpg new file mode 100644 index 0000000000..e24417fe9 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/textured_filter2.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/textured_merge1.jpg b/Sources/Accord.Imaging/AForge/Images/textured_merge1.jpg new file mode 100644 index 0000000000..e47ec45d8 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/textured_merge1.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/textured_merge2.jpg b/Sources/Accord.Imaging/AForge/Images/textured_merge2.jpg new file mode 100644 index 0000000000..552cdade1 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/textured_merge2.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/texturer.jpg b/Sources/Accord.Imaging/AForge/Images/texturer.jpg new file mode 100644 index 0000000000..f52b4667e Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/texturer.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/thinning.png b/Sources/Accord.Imaging/AForge/Images/thinning.png new file mode 100644 index 0000000000..6af5d81b5 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/thinning.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/threshold.jpg b/Sources/Accord.Imaging/AForge/Images/threshold.jpg new file mode 100644 index 0000000000..86185d6e6 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/threshold.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/threshold_carry.jpg b/Sources/Accord.Imaging/AForge/Images/threshold_carry.jpg new file mode 100644 index 0000000000..029a8902c Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/threshold_carry.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/thresholded_difference.png b/Sources/Accord.Imaging/AForge/Images/thresholded_difference.png new file mode 100644 index 0000000000..81d9c04e4 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/thresholded_difference.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/thresholded_euclidean_difference.png b/Sources/Accord.Imaging/AForge/Images/thresholded_euclidean_difference.png new file mode 100644 index 0000000000..d732f0a44 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/thresholded_euclidean_difference.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/tophat.png b/Sources/Accord.Imaging/AForge/Images/tophat.png new file mode 100644 index 0000000000..1aaea3708 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/tophat.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/ver_histogram.jpg b/Sources/Accord.Imaging/AForge/Images/ver_histogram.jpg new file mode 100644 index 0000000000..d8d33ad9a Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/ver_histogram.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/vrls.png b/Sources/Accord.Imaging/AForge/Images/vrls.png new file mode 100644 index 0000000000..986f3914a Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/vrls.png differ diff --git a/Sources/Accord.Imaging/AForge/Images/water_wave.jpg b/Sources/Accord.Imaging/AForge/Images/water_wave.jpg new file mode 100644 index 0000000000..eb38f4e14 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/water_wave.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/wood_texture.jpg b/Sources/Accord.Imaging/AForge/Images/wood_texture.jpg new file mode 100644 index 0000000000..97570bbc5 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/wood_texture.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/ycbcr_filtering.jpg b/Sources/Accord.Imaging/AForge/Images/ycbcr_filtering.jpg new file mode 100644 index 0000000000..4602ef809 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/ycbcr_filtering.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/ycbcr_linear.jpg b/Sources/Accord.Imaging/AForge/Images/ycbcr_linear.jpg new file mode 100644 index 0000000000..947838253 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/ycbcr_linear.jpg differ diff --git a/Sources/Accord.Imaging/AForge/Images/ycbcr_replace_channel.jpg b/Sources/Accord.Imaging/AForge/Images/ycbcr_replace_channel.jpg new file mode 100644 index 0000000000..702534d01 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Images/ycbcr_replace_channel.jpg differ diff --git a/Sources/Accord.Imaging/AForge/IntegralImage.cs b/Sources/Accord.Imaging/AForge/IntegralImage.cs new file mode 100644 index 0000000000..a30ded860 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/IntegralImage.cs @@ -0,0 +1,455 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2010 +// contacts@aforgenet.com +// + +namespace AForge.Imaging +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Integral image. + /// + /// + /// The class implements integral image concept, which is described by + /// Viola and Jones in: P. Viola and M. J. Jones, "Robust real-time face detection", + /// Int. Journal of Computer Vision 57(2), pp. 137154, 2004. + /// + /// "An integral image I of an input image G 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." + /// + /// The intensity at position (x, y) can be written as: + /// + /// x y + /// I(x,y) = SUM( SUM( G(i,j) ) ) + /// i=0 j=0 + /// + /// + /// The class uses 32-bit integers to represent integral image. + /// + /// The class processes only grayscale (8 bpp indexed) images. + /// + /// 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. + /// + /// Sample usage: + /// + /// // create integral image + /// IntegralImage im = IntegralImage.FromBitmap( image ); + /// // get pixels' mean value in the specified rectangle + /// float mean = im.GetRectangleMean( 10, 10, 20, 30 ) + /// + /// + /// + public class IntegralImage + { + /// + /// Intergral image's array. + /// + /// + /// See remarks to property. + /// + protected uint[,] integralImage = null; + + // image's width and height + private int width; + private int height; + + /// + /// Width of the source image the integral image was constructed for. + /// + public int Width + { + get { return width; } + } + + /// + /// Height of the source image the integral image was constructed for. + /// + public int Height + { + get { return height; } + } + + /// + /// Provides access to internal array keeping integral image data. + /// + /// + /// + /// The array should be accessed by [y, x] indexing. + /// + /// The array's size is [+1, +1]. The first + /// row and column are filled with zeros, what is done for more efficient calculation of + /// rectangles' sums. + /// + /// + public uint[,] InternalData + { + get { return integralImage; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Image width. + /// Image height. + /// + /// The constractor is protected, what makes it imposible to instantiate this + /// class directly. To create an instance of this class or + /// method should be used. + /// + protected IntegralImage(int width, int height) + { + this.width = width; + this.height = height; + integralImage = new uint[height + 1, width + 1]; + } + + /// + /// Construct integral image from source grayscale image. + /// + /// + /// Source grayscale image. + /// + /// Returns integral image. + /// + /// The source image has incorrect pixel format. + /// + public static IntegralImage FromBitmap(Bitmap image) + { + // check image format + if (image.PixelFormat != PixelFormat.Format8bppIndexed) + { + throw new UnsupportedImageFormatException("Source image can be graysclae (8 bpp indexed) image only."); + } + + // lock source image + BitmapData imageData = image.LockBits( + new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); + + // process the image + IntegralImage im = FromBitmap(imageData); + + // unlock image + image.UnlockBits(imageData); + + return im; + } + + /// + /// Construct integral image from source grayscale image. + /// + /// + /// Source image data. + /// + /// Returns integral image. + /// + /// The source image has incorrect pixel format. + /// + public static IntegralImage FromBitmap(BitmapData imageData) + { + return FromBitmap(new UnmanagedImage(imageData)); + } + + /// + /// Construct integral image from source grayscale image. + /// + /// + /// Source unmanaged image. + /// + /// Returns integral image. + /// + /// The source image has incorrect pixel format. + /// + public static IntegralImage FromBitmap(UnmanagedImage image) + { + // check image format + if (image.PixelFormat != PixelFormat.Format8bppIndexed) + { + throw new ArgumentException("Source image can be graysclae (8 bpp indexed) image only."); + } + + // get source image size + int width = image.Width; + int height = image.Height; + int offset = image.Stride - width; + + // create integral image + var im = new IntegralImage(width, height); + uint[,] integralImage = im.integralImage; + + // do the job + unsafe + { + byte* src = (byte*)image.ImageData.ToPointer(); + + // for each line + for (int y = 1; y <= height; y++) + { + uint rowSum = 0; + + // for each pixel + for (int x = 1; x <= width; x++, src++) + { + rowSum += *src; + + integralImage[y, x] = rowSum + integralImage[y - 1, x]; + } + src += offset; + } + } + + return im; + } + + /// + /// Calculate sum of pixels in the specified rectangle. + /// + /// + /// X coordinate of left-top rectangle's corner. + /// Y coordinate of left-top rectangle's corner. + /// X coordinate of right-bottom rectangle's corner. + /// Y coordinate of right-bottom rectangle's corner. + /// + /// Returns sum of pixels in the specified rectangle. + /// + /// Both specified points are included into the calculation rectangle. + /// + public uint GetRectangleSum(int x1, int y1, int x2, int y2) + { + // check if requested rectangle is out of the image + if ((x2 < 0) || (y2 < 0) || (x1 >= width) || (y1 >= height)) + return 0; + + if (x1 < 0) x1 = 0; + if (y1 < 0) y1 = 0; + + x2++; + y2++; + + if (x2 > width) x2 = width; + if (y2 > height) y2 = height; + + return integralImage[y2, x2] + integralImage[y1, x1] - integralImage[y2, x1] - integralImage[y1, x2]; + } + + /// + /// Calculate horizontal (X) haar wavelet at the specified point. + /// + /// + /// X coordinate of the point to calculate wavelet at. + /// Y coordinate of the point to calculate wavelet at. + /// Wavelet size to calculate. + /// + /// Returns value of the horizontal wavelet at the specified point. + /// + /// The method calculates horizontal wavelet, which is a difference + /// of two horizontally adjacent boxes' sums, i.e. A-B. A is the sum of rectangle with coordinates + /// (x, y-radius, x+radius-1, y+radius-1). B is the sum of rectangle with coordinates + /// (x-radius, y-radius, x-1, y+radiys-1). + /// + public int GetHaarXWavelet(int x, int y, int radius) + { + int y1 = y - radius; + int y2 = y + radius - 1; + + long a = GetRectangleSum(x, y1, x + radius - 1, y2); + long b = GetRectangleSum(x - radius, y1, x - 1, y2); + + return (int)(a - b); + } + + /// + /// Calculate vertical (Y) haar wavelet at the specified point. + /// + /// + /// X coordinate of the point to calculate wavelet at. + /// Y coordinate of the point to calculate wavelet at. + /// Wavelet size to calculate. + /// + /// Returns value of the vertical wavelet at the specified point. + /// + /// The method calculates vertical wavelet, which is a difference + /// of two vertical adjacent boxes' sums, i.e. A-B. A is the sum of rectangle with coordinates + /// (x-radius, y, x+radius-1, y+radius-1). B is the sum of rectangle with coordinates + /// (x-radius, y-radius, x+radius-1, y-1). + /// + public int GetHaarYWavelet(int x, int y, int radius) + { + int x1 = x - radius; + int x2 = x + radius - 1; + + float a = GetRectangleSum(x1, y, x2, y + radius - 1); + float b = GetRectangleSum(x1, y - radius, x2, y - 1); + + return (int)(a - b); + } + + /// + /// Calculate sum of pixels in the specified rectangle without checking it's coordinates. + /// + /// + /// X coordinate of left-top rectangle's corner. + /// Y coordinate of left-top rectangle's corner. + /// X coordinate of right-bottom rectangle's corner. + /// Y coordinate of right-bottom rectangle's corner. + /// + /// Returns sum of pixels in the specified rectangle. + /// + /// Both specified points are included into the calculation rectangle. + /// + public uint GetRectangleSumUnsafe(int x1, int y1, int x2, int y2) + { + x2++; + y2++; + + return integralImage[y2, x2] + integralImage[y1, x1] - integralImage[y2, x1] - integralImage[y1, x2]; + } + + /// + /// Calculate sum of pixels in the specified rectangle. + /// + /// + /// X coordinate of central point of the rectangle. + /// Y coordinate of central point of the rectangle. + /// Radius of the rectangle. + /// + /// Returns sum of pixels in the specified rectangle. + /// + /// The method calculates sum of pixels in square rectangle with + /// odd width and height. In the case if it is required to calculate sum of + /// 3x3 rectangle, then it is required to specify its center and radius equal to 1. + /// + /// + public uint GetRectangleSum(int x, int y, int radius) + { + return GetRectangleSum(x - radius, y - radius, x + radius, y + radius); + } + + /// + /// Calculate sum of pixels in the specified rectangle without checking it's coordinates. + /// + /// + /// X coordinate of central point of the rectangle. + /// Y coordinate of central point of the rectangle. + /// Radius of the rectangle. + /// + /// Returns sum of pixels in the specified rectangle. + /// + /// The method calculates sum of pixels in square rectangle with + /// odd width and height. In the case if it is required to calculate sum of + /// 3x3 rectangle, then it is required to specify its center and radius equal to 1. + /// + /// + public uint GetRectangleSumUnsafe(int x, int y, int radius) + { + return GetRectangleSumUnsafe(x - radius, y - radius, x + radius, y + radius); + } + + /// + /// Calculate mean value of pixels in the specified rectangle. + /// + /// + /// X coordinate of left-top rectangle's corner. + /// Y coordinate of left-top rectangle's corner. + /// X coordinate of right-bottom rectangle's corner. + /// Y coordinate of right-bottom rectangle's corner. + /// + /// Returns mean value of pixels in the specified rectangle. + /// + /// Both specified points are included into the calculation rectangle. + /// + public float GetRectangleMean(int x1, int y1, int x2, int y2) + { + // check if requested rectangle is out of the image + if ((x2 < 0) || (y2 < 0) || (x1 >= width) || (y1 >= height)) + return 0; + + if (x1 < 0) x1 = 0; + if (y1 < 0) y1 = 0; + + x2++; + y2++; + + if (x2 > width) x2 = width; + if (y2 > height) y2 = height; + + // return sum divided by actual rectangles size + return (float)((double)(integralImage[y2, x2] + integralImage[y1, x1] - integralImage[y2, x1] - integralImage[y1, x2]) / + (double)((x2 - x1) * (y2 - y1))); + } + + /// + /// Calculate mean value of pixels in the specified rectangle without checking it's coordinates. + /// + /// + /// X coordinate of left-top rectangle's corner. + /// Y coordinate of left-top rectangle's corner. + /// X coordinate of right-bottom rectangle's corner. + /// Y coordinate of right-bottom rectangle's corner. + /// + /// Returns mean value of pixels in the specified rectangle. + /// + /// Both specified points are included into the calculation rectangle. + /// + public float GetRectangleMeanUnsafe(int x1, int y1, int x2, int y2) + { + x2++; + y2++; + + // return sum divided by actual rectangles size + return (float)((double)(integralImage[y2, x2] + integralImage[y1, x1] - integralImage[y2, x1] - integralImage[y1, x2]) / + (double)((x2 - x1) * (y2 - y1))); + } + + /// + /// Calculate mean value of pixels in the specified rectangle. + /// + /// + /// X coordinate of central point of the rectangle. + /// Y coordinate of central point of the rectangle. + /// Radius of the rectangle. + /// + /// Returns mean value of pixels in the specified rectangle. + /// + /// The method calculates mean value of pixels in square rectangle with + /// odd width and height. In the case if it is required to calculate mean value of + /// 3x3 rectangle, then it is required to specify its center and radius equal to 1. + /// + /// + public float GetRectangleMean(int x, int y, int radius) + { + return GetRectangleMean(x - radius, y - radius, x + radius, y + radius); + } + + /// + /// Calculate mean value of pixels in the specified rectangle without checking it's coordinates. + /// + /// + /// X coordinate of central point of the rectangle. + /// Y coordinate of central point of the rectangle. + /// Radius of the rectangle. + /// + /// Returns mean value of pixels in the specified rectangle. + /// + /// The method calculates mean value of pixels in square rectangle with + /// odd width and height. In the case if it is required to calculate mean value of + /// 3x3 rectangle, then it is required to specify its center and radius equal to 1. + /// + /// + public float GetRectangleMeanUnsafe(int x, int y, int radius) + { + return GetRectangleMeanUnsafe(x - radius, y - radius, x + radius, y + radius); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Interpolation.cs b/Sources/Accord.Imaging/AForge/Interpolation.cs new file mode 100644 index 0000000000..cd3cb5d18 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Interpolation.cs @@ -0,0 +1,52 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging +{ + using System; + + /// + /// Interpolation routines. + /// + /// + internal static class Interpolation + { + /// + /// Bicubic kernel. + /// + /// + /// X value. + /// + /// Bicubic cooefficient. + /// + /// The function implements bicubic kernel W(x) as described on + /// Wikipedia + /// (coefficient a is set to -0.5). + /// + public static double BiCubicKernel( double x ) + { + if ( x < 0 ) + { + x = -x; + } + + double biCoef = 0; + + if ( x <= 1 ) + { + biCoef = ( 1.5 * x - 2.5 ) * x * x + 1; + } + else if ( x < 2 ) + { + biCoef = ( ( -0.5 * x + 2.5 ) * x - 4 ) * x + 2; + } + + return biCoef; + } + } +} diff --git a/Sources/Accord.Imaging/AForge/MemoryManager.cs b/Sources/Accord.Imaging/AForge/MemoryManager.cs new file mode 100644 index 0000000000..cebc39a26 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/MemoryManager.cs @@ -0,0 +1,305 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging +{ + using System; + using System.Collections.Generic; + using System.Runtime.InteropServices; + + /// + /// Internal memory manager used by image processing routines. + /// + /// + /// The memory manager supports memory allocation/deallocation + /// caching. Caching means that memory blocks may be not freed on request, but + /// kept for later reuse. + /// + public static class MemoryManager + { + // maximum memory blocks to cache + private static int maximumCacheSize = 3; + // current cache size + private static int currentCacheSize = 0; + // busy blocks in cache + private static int busyBlocks = 0; + // amount of cached memory + private static int cachedMemory = 0; + + // maximum block size to cache + private static int maxSizeToCache = 20 * 1024 * 1024; + // minimum block size to cache + private static int minSizeToCache = 10 * 1024; + + // cache structure + private class CacheBlock + { + public IntPtr MemoryBlock; + public int Size; + public bool Free; + + public CacheBlock( IntPtr memoryBlock, int size ) + { + this.MemoryBlock = memoryBlock; + this.Size = size; + this.Free = false; + } + } + + private static List memoryBlocks = new List( ); + + /// + /// Maximum amount of memory blocks to keep in cache. + /// + /// + /// The value specifies the amount of memory blocks, which could be + /// cached by the memory manager. + /// + /// Default value is set to 3. Maximum value is 10. + /// + /// + public static int MaximumCacheSize + { + get + { + lock ( memoryBlocks ) + { + return maximumCacheSize; + } + } + set + { + lock ( memoryBlocks ) + { + maximumCacheSize = Math.Max( 0, Math.Min( 10, value ) ); + } + } + } + + /// + /// Current amount of memory blocks in cache. + /// + /// + public static int CurrentCacheSize + { + get + { + lock ( memoryBlocks ) + { + return currentCacheSize; + } + } + } + + /// + /// Amount of busy memory blocks in cache (which were not freed yet by user). + /// + /// + public static int BusyMemoryBlocks + { + get + { + lock ( memoryBlocks ) + { + return busyBlocks; + } + } + } + + /// + /// Amount of free memory blocks in cache (which are not busy by users). + /// + /// + public static int FreeMemoryBlocks + { + get + { + lock ( memoryBlocks ) + { + return currentCacheSize - busyBlocks; + } + } + } + + /// + /// Amount of cached memory in bytes. + /// + /// + public static int CachedMemory + { + get + { + lock ( memoryBlocks ) + { + return cachedMemory; + } + } + } + + /// + /// Maximum memory block's size in bytes, which could be cached. + /// + /// + /// Memory blocks, which size is greater than this value, are not cached. + /// + public static int MaxSizeToCache + { + get { return maxSizeToCache; } + set { maxSizeToCache = value; } + } + + /// + /// Minimum memory block's size in bytes, which could be cached. + /// + /// + /// Memory blocks, which size is less than this value, are not cached. + /// + public static int MinSizeToCache + { + get { return minSizeToCache; } + set { minSizeToCache = value; } + } + + /// + /// Allocate unmanaged memory. + /// + /// + /// Memory size to allocate. + /// + /// Return's pointer to the allocated memory buffer. + /// + /// The method allocates requested amount of memory and returns pointer to it. It may avoid allocation + /// in the case some caching scheme is uses and there is already enough allocated memory available. + /// + /// There is insufficient memory to satisfy the request. + /// + public static IntPtr Alloc( int size ) + { + lock ( memoryBlocks ) + { + // allocate memory block without caching if cache is not available + if ( ( busyBlocks >= maximumCacheSize ) || ( size > maxSizeToCache ) || ( size < minSizeToCache ) ) + return Marshal.AllocHGlobal( size ); + + // if all cached blocks are busy, create new cache block + if ( currentCacheSize == busyBlocks ) + { + IntPtr memoryBlock = Marshal.AllocHGlobal( size ); + memoryBlocks.Add( new CacheBlock( memoryBlock, size ) ); + + busyBlocks++; + currentCacheSize++; + cachedMemory += size; + + return memoryBlock; + } + + // find free memory block with enough memory + for ( int i = 0; i < currentCacheSize; i++ ) + { + CacheBlock block = memoryBlocks[i]; + + if ( ( block.Free == true ) && ( block.Size >= size ) ) + { + block.Free = false; + busyBlocks++; + return block.MemoryBlock; + } + } + + // finaly find first free memory block and resize it + for ( int i = 0; i < currentCacheSize; i++ ) + { + CacheBlock block = memoryBlocks[i]; + + if ( block.Free == true ) + { + // remove this block cache + Marshal.FreeHGlobal( block.MemoryBlock ); + memoryBlocks.RemoveAt( i ); + currentCacheSize--; + cachedMemory -= block.Size; + + // add new one + IntPtr memoryBlock = Marshal.AllocHGlobal( size ); + memoryBlocks.Add( new CacheBlock( memoryBlock, size ) ); + + busyBlocks++; + currentCacheSize++; + cachedMemory += size; + + return memoryBlock; + } + } + + return IntPtr.Zero; + } + } + + /// + /// Free unmanaged memory. + /// + /// + /// Pointer to memory buffer to free. + /// + /// This method may skip actual deallocation of memory and keep it for future requests, + /// if some caching scheme is used. + /// + public static void Free( IntPtr pointer ) + { + lock ( memoryBlocks ) + { + // find the memory block in cache + for ( int i = 0; i < currentCacheSize; i++ ) + { + if ( memoryBlocks[i].MemoryBlock == pointer ) + { + // mark the block as free + memoryBlocks[i].Free = true; + busyBlocks--; + return; + } + } + + // the block was not cached, so lets just free it + Marshal.FreeHGlobal( pointer ); + } + } + + /// + /// Force freeing unused memory. + /// + /// + /// Frees and removes from cache memory blocks, which are not used by users. + /// + /// Returns number of freed memory blocks. + /// + public static int FreeUnusedMemory( ) + { + lock ( memoryBlocks ) + { + int freedBlocks = 0; + + // free all unused memory + for ( int i = currentCacheSize - 1; i >= 0; i-- ) + { + if ( memoryBlocks[i].Free ) + { + Marshal.FreeHGlobal( memoryBlocks[i].MemoryBlock ); + cachedMemory -= memoryBlocks[i].Size; + memoryBlocks.RemoveAt( i ); + freedBlocks++; + } + } + currentCacheSize -= freedBlocks; + + return freedBlocks; + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/MoravecCornersDetector.cs b/Sources/Accord.Imaging/AForge/MoravecCornersDetector.cs new file mode 100644 index 0000000000..03853b70a --- /dev/null +++ b/Sources/Accord.Imaging/AForge/MoravecCornersDetector.cs @@ -0,0 +1,322 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + using System.Collections.Generic; + + /// + /// Moravec corners detector. + /// + /// + /// The class implements Moravec corners detector. For information about algorithm's + /// details its description + /// should be studied. + /// + /// Due to limitations of Moravec corners detector (anisotropic response, etc.) its usage is limited + /// to certain cases only. + /// + /// The class processes only grayscale 8 bpp and color 24/32 bpp images. + /// + /// Sample usage: + /// + /// // create corner detector's instance + /// MoravecCornersDetector mcd = new MoravecCornersDetector( ); + /// // process image searching for corners + /// List<IntPoint> corners = scd.ProcessImage( image ); + /// // process points + /// foreach ( IntPoint corner in corners ) + /// { + /// // ... + /// } + /// + /// + /// + /// + /// + public class MoravecCornersDetector : ICornersDetector + { + // window size + private int windowSize = 3; + // threshold which is used to filter interest points + private int threshold = 500; + + /// + /// Window size used to determine if point is interesting, [3, 15]. + /// + /// + /// The value specifies window size, which is used for initial searching of + /// corners candidates and then for searching local maximums. + /// + /// Default value is set to 3. + /// + /// + /// Setting value is not odd. + /// + public int WindowSize + { + get { return windowSize; } + set + { + // check if value is odd + if ( ( value & 1 ) == 0 ) + throw new ArgumentException( "The value shoule be odd." ); + + windowSize = Math.Max( 3, Math.Min( 15, value ) ); + } + } + + /// + /// Threshold value, which is used to filter out uninteresting points. + /// + /// + /// The value is used to filter uninteresting points - points which have value below + /// specified threshold value are treated as not corners candidates. Increasing this value decreases + /// the amount of detected point. + /// + /// Default value is set to 500. + /// + /// + public int Threshold + { + get { return threshold; } + set { threshold = value; } + } + + private static int[] xDelta = new int[8] { -1, 0, 1, 1, 1, 0, -1, -1 }; + private static int[] yDelta = new int[8] { -1, -1, -1, 0, 1, 1, 1, 0 }; + + /// + /// Initializes a new instance of the class. + /// + public MoravecCornersDetector( ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Threshold value, which is used to filter out uninteresting points. + /// + public MoravecCornersDetector( int threshold ) : + this( threshold, 3 ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Threshold value, which is used to filter out uninteresting points. + /// Window size used to determine if point is interesting. + /// + public MoravecCornersDetector( int threshold, int windowSize ) + { + this.Threshold = threshold; + this.WindowSize = windowSize; + } + + /// + /// Process image looking for corners. + /// + /// + /// Source image to process. + /// + /// Returns array of found corners (X-Y coordinates). + /// + /// The source image has incorrect pixel format. + /// + public List ProcessImage( Bitmap image ) + { + // check image format + if ( + ( image.PixelFormat != PixelFormat.Format8bppIndexed ) && + ( image.PixelFormat != PixelFormat.Format24bppRgb ) && + ( image.PixelFormat != PixelFormat.Format32bppRgb ) && + ( image.PixelFormat != PixelFormat.Format32bppArgb ) + ) + { + throw new UnsupportedImageFormatException( "Unsupported pixel format of the source image." ); + } + + // lock source image + BitmapData imageData = image.LockBits( + new Rectangle( 0, 0, image.Width, image.Height ), + ImageLockMode.ReadOnly, image.PixelFormat ); + + List corners; + + try + { + // process the image + corners = ProcessImage( new UnmanagedImage( imageData ) ); + } + finally + { + // unlock image + image.UnlockBits( imageData ); + } + + return corners; + } + + /// + /// Process image looking for corners. + /// + /// + /// Source image data to process. + /// + /// Returns array of found corners (X-Y coordinates). + /// + /// The source image has incorrect pixel format. + /// + public List ProcessImage( BitmapData imageData ) + { + return ProcessImage( new UnmanagedImage( imageData ) ); + } + + /// + /// Process image looking for corners. + /// + /// + /// Unmanaged source image to process. + /// + /// Returns array of found corners (X-Y coordinates). + /// + /// The source image has incorrect pixel format. + /// + public List ProcessImage( UnmanagedImage image ) + { + // check image format + if ( + ( image.PixelFormat != PixelFormat.Format8bppIndexed ) && + ( image.PixelFormat != PixelFormat.Format24bppRgb ) && + ( image.PixelFormat != PixelFormat.Format32bppRgb ) && + ( image.PixelFormat != PixelFormat.Format32bppArgb ) + ) + { + throw new UnsupportedImageFormatException( "Unsupported pixel format of the source image." ); + } + + // get source image size + int width = image.Width; + int height = image.Height; + int stride = image.Stride; + int pixelSize = Bitmap.GetPixelFormatSize( image.PixelFormat ) / 8; + // window radius + int windowRadius = windowSize / 2; + + // offset + int offset = stride - windowSize * pixelSize; + + // create moravec cornerness map + int[,] moravecMap = new int[height, width]; + + // do the job + unsafe + { + byte* ptr = (byte*) image.ImageData.ToPointer( ); + + // for each row + for ( int y = windowRadius, maxY = height - windowRadius; y < maxY; y++ ) + { + // for each pixel + for ( int x = windowRadius, maxX = width - windowRadius; x < maxX; x++ ) + { + int minSum = int.MaxValue; + + // go through 8 possible shifting directions + for ( int k = 0; k < 8; k++ ) + { + // calculate center of shifted window + int sy = y + yDelta[k]; + int sx = x + xDelta[k]; + + // check if shifted window is within the image + if ( + ( sy < windowRadius ) || ( sy >= maxY ) || + ( sx < windowRadius ) || ( sx >= maxX ) + ) + { + // skip this shifted window + continue; + } + + int sum = 0; + + byte* ptr1 = ptr + ( y - windowRadius ) * stride + ( x - windowRadius ) * pixelSize; + byte* ptr2 = ptr + ( sy - windowRadius ) * stride + ( sx - windowRadius ) * pixelSize; + + // for each windows' rows + for ( int i = 0; i < windowSize; i++ ) + { + // for each windows' pixels + for ( int j = 0, maxJ = windowSize * pixelSize; j < maxJ; j++, ptr1++, ptr2++ ) + { + int dif = *ptr1 - *ptr2; + sum += dif * dif; + } + ptr1 += offset; + ptr2 += offset; + } + + // check if the sum is mimimal + if ( sum < minSum ) + { + minSum = sum; + } + } + + // threshold the minimum sum + if ( minSum < threshold ) + { + minSum = 0; + } + + moravecMap[y, x] = minSum; + } + } + } + + // collect interesting points - only those points, which are local maximums + List cornersList = new List( ); + + // for each row + for ( int y = windowRadius, maxY = height - windowRadius; y < maxY; y++ ) + { + // for each pixel + for ( int x = windowRadius, maxX = width - windowRadius; x < maxX; x++ ) + { + int currentValue = moravecMap[y, x]; + + // for each windows' rows + for ( int i = -windowRadius; ( currentValue != 0 ) && ( i <= windowRadius ); i++ ) + { + // for each windows' pixels + for ( int j = -windowRadius; j <= windowRadius; j++ ) + { + if ( moravecMap[y + i, x + j] > currentValue ) + { + currentValue = 0; + break; + } + } + } + + // check if this point is really interesting + if ( currentValue != 0 ) + { + cornersList.Add( new IntPoint( x, y ) ); + } + } + } + + return cornersList; + } + } +} diff --git a/Sources/Accord.Imaging/AForge/QuadrilateralFinder.cs b/Sources/Accord.Imaging/AForge/QuadrilateralFinder.cs new file mode 100644 index 0000000000..00034b958 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/QuadrilateralFinder.cs @@ -0,0 +1,239 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2007-2009 +// andrew.kirillov@aforgenet.com +// + + +namespace AForge.Imaging +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + + using AForge; + using AForge.Math.Geometry; + + /// + /// Searching of quadrilateral/triangle corners. + /// + /// + /// The class searches for quadrilateral's/triangle's corners on the specified image. + /// It first collects edge points of the object and then uses + /// to find corners + /// the quadrilateral/triangle. + /// + /// The class treats all black pixels as background (none-object) and + /// all none-black pixels as object. + /// + /// The class processes grayscale 8 bpp and color 24/32 bpp images. + /// + /// Sample usage: + /// + /// // get corners of the quadrilateral + /// QuadrilateralFinder qf = new QuadrilateralFinder( ); + /// List<IntPoint> corners = qf.ProcessImage( image ); + /// + /// // lock image to draw on it with AForge.NET's methods + /// // (or draw directly on image without locking if it is unmanaged image) + /// BitmapData data = image.LockBits( new Rectangle( 0, 0, image.Width, image.Height ), + /// ImageLockMode.ReadWrite, image.PixelFormat ); + /// + /// Drawing.Polygon( data, corners, Color.Red ); + /// for ( int i = 0; i < corners.Count; i++ ) + /// { + /// Drawing.FillRectangle( data, + /// new Rectangle( corners[i].X - 2, corners[i].Y - 2, 5, 5 ), + /// Color.FromArgb( i * 32 + 127 + 32, i * 64, i * 64 ) ); + /// } + /// + /// image.UnlockBits( data ); + /// + /// + /// Source image: + /// + /// Result image: + /// + /// + /// + public class QuadrilateralFinder + { + /// + /// Find corners of quadrilateral/triangular area in the specified image. + /// + /// + /// Source image to search quadrilateral for. + /// + /// Returns a list of points, which are corners of the quadrilateral/triangular area found + /// in the specified image. The first point in the list is the point with lowest + /// X coordinate (and with lowest Y if there are several points with the same X value). + /// Points are in clockwise order (screen coordinates system). + /// + /// Unsupported pixel format of the source image. + /// + public List ProcessImage(Bitmap image) + { + CheckPixelFormat(image.PixelFormat); + + // lock source image + BitmapData imageData = image.LockBits( + new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, image.PixelFormat); + + List corners = null; + + try + { + // process the image + corners = ProcessImage(new UnmanagedImage(imageData)); + } + finally + { + // unlock image + image.UnlockBits(imageData); + } + + return corners; + } + + /// + /// Find corners of quadrilateral/triangular area in the specified image. + /// + /// + /// Source image data to search quadrilateral for. + /// + /// Returns a list of points, which are corners of the quadrilateral/triangular area found + /// in the specified image. The first point in the list is the point with lowest + /// X coordinate (and with lowest Y if there are several points with the same X value). + /// Points are in clockwise order (screen coordinates system). + /// + /// Unsupported pixel format of the source image. + /// + public List ProcessImage(BitmapData imageData) + { + return ProcessImage(new UnmanagedImage(imageData)); + } + + /// + /// Find corners of quadrilateral/triangular area in the specified image. + /// + /// + /// Source image to search quadrilateral for. + /// + /// Returns a list of points, which are corners of the quadrilateral/triangular area found + /// in the specified image. The first point in the list is the point with lowest + /// X coordinate (and with lowest Y if there are several points with the same X value). + /// Points are in clockwise order (screen coordinates system). + /// + /// Unsupported pixel format of the source image. + /// + public List ProcessImage(UnmanagedImage image) + { + CheckPixelFormat(image.PixelFormat); + + // get source image size + int width = image.Width; + int height = image.Height; + + // collection of points + List points = new List(); + + // collect edge points + unsafe + { + byte* src = (byte*)image.ImageData.ToPointer(); + int stride = image.Stride; + + bool lineIsEmpty; + + if (image.PixelFormat == PixelFormat.Format8bppIndexed) + { + // for each row + for (int y = 0; y < height; y++) + { + lineIsEmpty = true; + + // scan from left to right + for (int x = 0; x < width; x++) + { + if (src[x] != 0) + { + points.Add(new IntPoint(x, y)); + lineIsEmpty = false; + break; + } + } + if (!lineIsEmpty) + { + // scan from right to left + for (int x = width - 1; x >= 0; x--) + { + if (src[x] != 0) + { + points.Add(new IntPoint(x, y)); + break; + } + } + } + src += stride; + } + } + else + { + // 24 or 32 bpp color image + int pixelSize = System.Drawing.Image.GetPixelFormatSize(image.PixelFormat) / 8; + + byte* ptr = null; + + // for each row + for (int y = 0; y < height; y++) + { + lineIsEmpty = true; + // scan from left to right + ptr = src; + for (int x = 0; x < width; x++, ptr += pixelSize) + { + if ((ptr[RGB.R] != 0) || (ptr[RGB.G] != 0) || (ptr[RGB.B] != 0)) + { + points.Add(new IntPoint(x, y)); + lineIsEmpty = false; + break; + } + } + if (!lineIsEmpty) + { + // scan from right to left + ptr = src + width * pixelSize - pixelSize; + for (int x = width - 1; x >= 0; x--, ptr -= pixelSize) + { + if ((ptr[RGB.R] != 0) || (ptr[RGB.G] != 0) || (ptr[RGB.B] != 0)) + { + points.Add(new IntPoint(x, y)); + break; + } + } + } + src += stride; + } + } + } + + return PointsCloud.FindQuadrilateralCorners(points); + } + + private static void CheckPixelFormat(PixelFormat format) + { + // check image format + if ((format != PixelFormat.Format8bppIndexed) && + (format != PixelFormat.Format24bppRgb) && + (format != PixelFormat.Format32bppArgb) && + (format != PixelFormat.Format32bppPArgb)) + { + throw new UnsupportedImageFormatException("Unsupported pixel format of the source image."); + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/RecursiveBlobCounter.cs b/Sources/Accord.Imaging/AForge/RecursiveBlobCounter.cs new file mode 100644 index 0000000000..906d17c3d --- /dev/null +++ b/Sources/Accord.Imaging/AForge/RecursiveBlobCounter.cs @@ -0,0 +1,269 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2012 +// contacts@aforgenet.com +// + +namespace AForge.Imaging +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Blob counter based on recursion. + /// + /// + /// The class counts and extracts stand alone objects in + /// images using recursive version of connected components labeling + /// algorithm. + /// + /// The algorithm treats all pixels with values less or equal to + /// as background, but pixels with higher values are treated as objects' pixels. + /// + /// Since this algorithm is based on recursion, it is + /// required to be careful with its application to big images with big blobs, + /// because in this case recursion will require big stack size and may lead + /// to stack overflow. The recursive version may be applied (and may be even + /// faster than ) to an image with small blobs - + /// "star sky" image (or small cells, for example, etc). + /// + /// For blobs' searching the class supports 8 bpp indexed grayscale images and + /// 24/32 bpp color images. + /// See documentation about for information about which + /// pixel formats are supported for extraction of blobs. + /// + /// Sample usage: + /// + /// // create an instance of blob counter algorithm + /// RecursiveBlobCounter bc = new RecursiveBlobCounter( ); + /// // process binary image + /// bc.ProcessImage( image ); + /// Rectangle[] rects = bc.GetObjectsRectangles( ); + /// // process blobs + /// foreach ( Rectangle rect in rects ) + /// { + /// // ... + /// } + /// + /// + /// + public class RecursiveBlobCounter : BlobCounterBase + { + // temporary variable + private int[] tempLabels; + private int stride; + private int pixelSize; + + private byte backgroundThresholdR = 0; + private byte backgroundThresholdG = 0; + private byte backgroundThresholdB = 0; + + /// + /// Background threshold's value. + /// + /// + /// The property sets threshold value for distinguishing between background + /// pixel and objects' pixels. All pixel with values less or equal to this property are + /// treated as background, but pixels with higher values are treated as objects' pixels. + /// + /// In the case of colour images a pixel is treated as objects' pixel if any of its + /// RGB values are higher than corresponding values of this threshold. + /// + /// For processing grayscale image, set the property with all RGB components eqaul. + /// + /// Default value is set to (0, 0, 0) - black colour. + /// + public Color BackgroundThreshold + { + get { return Color.FromArgb( backgroundThresholdR, backgroundThresholdG, backgroundThresholdB ); } + set + { + backgroundThresholdR = value.R; + backgroundThresholdG = value.G; + backgroundThresholdB = value.B; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Creates new instance of the class with + /// an empty objects map. Before using methods, which provide information about blobs + /// or extract them, the , + /// or + /// method should be called to collect objects map. + /// + public RecursiveBlobCounter( ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Image to look for objects in. + /// + public RecursiveBlobCounter( Bitmap image ) : base( image ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Image data to look for objects in. + /// + public RecursiveBlobCounter( BitmapData imageData ) : base( imageData ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Unmanaged image to look for objects in. + /// + public RecursiveBlobCounter( UnmanagedImage image ) : base( image ) { } + + /// + /// Actual objects map building. + /// + /// + /// Unmanaged image to process. + /// + /// The method supports 8 bpp indexed grayscale images and 24/32 bpp color images. + /// + /// Unsupported pixel format of the source image. + /// + protected override void BuildObjectsMap( UnmanagedImage image ) + { + this.stride = image.Stride; + + // check pixel format + if ( ( image.PixelFormat != PixelFormat.Format8bppIndexed ) && + ( image.PixelFormat != PixelFormat.Format24bppRgb ) && + ( image.PixelFormat != PixelFormat.Format32bppRgb ) && + ( image.PixelFormat != PixelFormat.Format32bppArgb ) && + ( image.PixelFormat != PixelFormat.Format32bppPArgb ) ) + { + throw new UnsupportedImageFormatException( "Unsupported pixel format of the source image." ); + } + + // allocate temporary labels array + tempLabels = new int[( imageWidth + 2 ) * ( imageHeight + 2 )]; + // fill boundaries with reserved value + for ( int x = 0, mx = imageWidth + 2; x < mx; x++ ) + { + tempLabels[x] = -1; + tempLabels[x + ( imageHeight + 1 ) * ( imageWidth + 2 )] = -1; + } + for ( int y = 0, my = imageHeight + 2; y < my; y++ ) + { + tempLabels[y * ( imageWidth + 2 )] = -1; + tempLabels[y * ( imageWidth + 2 ) + imageWidth + 1] = -1; + } + + // initial objects count + objectsCount = 0; + + // do the job + unsafe + { + byte* src = (byte*) image.ImageData.ToPointer( ); + int p = imageWidth + 2 + 1; + + if ( image.PixelFormat == PixelFormat.Format8bppIndexed ) + { + int offset = stride - imageWidth; + + // for each line + for ( int y = 0; y < imageHeight; y++ ) + { + // for each pixel + for ( int x = 0; x < imageWidth; x++, src++, p++ ) + { + // check for non-labeled pixel + if ( ( *src > backgroundThresholdG ) && ( tempLabels[p] == 0 ) ) + { + objectsCount++; + LabelPixel( src, p ); + } + } + src += offset; + p += 2; + } + } + else + { + pixelSize = Bitmap.GetPixelFormatSize( image.PixelFormat ) / 8; + int offset = stride - imageWidth * pixelSize; + + // for each line + for ( int y = 0; y < imageHeight; y++ ) + { + // for each pixel + for ( int x = 0; x < imageWidth; x++, src += pixelSize, p++ ) + { + // check for non-labeled pixel + if ( ( + ( src[RGB.R] > backgroundThresholdR ) || + ( src[RGB.G] > backgroundThresholdG ) || + ( src[RGB.B] > backgroundThresholdB ) + ) && + ( tempLabels[p] == 0 ) ) + { + objectsCount++; + LabelColorPixel( src, p ); + } + } + src += offset; + p += 2; + } + } + } + + // allocate labels array + objectLabels = new int[imageWidth * imageHeight]; + + for ( int y = 0; y < imageHeight; y++ ) + { + Array.Copy( tempLabels, ( y + 1 ) * ( imageWidth + 2 ) + 1, objectLabels, y * imageWidth, imageWidth ); + } + } + + private unsafe void LabelPixel( byte* pixel, int labelPointer ) + { + if ( ( tempLabels[labelPointer] == 0 ) && ( *pixel > backgroundThresholdG ) ) + { + tempLabels[labelPointer] = objectsCount; + + LabelPixel( pixel + 1, labelPointer + 1 ); // x + 1, y + LabelPixel( pixel + 1 + stride, labelPointer + 1 + 2 + imageWidth ); // x + 1, y + 1 + LabelPixel( pixel + stride, labelPointer + 2 + imageWidth ); // x , y + 1 + LabelPixel( pixel - 1 + stride, labelPointer - 1 + 2 + imageWidth ); // x - 1, y + 1 + LabelPixel( pixel - 1, labelPointer - 1 ); // x - 1, y + LabelPixel( pixel - 1 - stride, labelPointer - 1 - 2 - imageWidth ); // x - 1, y - 1 + LabelPixel( pixel - stride, labelPointer - 2 - imageWidth ); // x , y - 1 + LabelPixel( pixel + 1 - stride, labelPointer + 1 - 2 - imageWidth ); // x + 1, y - 1 + } + } + + private unsafe void LabelColorPixel( byte* pixel, int labelPointer ) + { + if ( ( tempLabels[labelPointer] == 0 ) && ( + ( pixel[RGB.R] > backgroundThresholdR ) || + ( pixel[RGB.G] > backgroundThresholdG ) || + ( pixel[RGB.B] > backgroundThresholdB ) ) ) + { + tempLabels[labelPointer] = objectsCount; + + LabelColorPixel( pixel + pixelSize, labelPointer + 1 ); // x + 1, y + LabelColorPixel( pixel + pixelSize + stride, labelPointer + 1 + 2 + imageWidth ); // x + 1, y + 1 + LabelColorPixel( pixel + stride, labelPointer + 2 + imageWidth ); // x , y + 1 + LabelColorPixel( pixel - pixelSize + stride, labelPointer - 1 + 2 + imageWidth ); // x - 1, y + 1 + LabelColorPixel( pixel - pixelSize, labelPointer - 1 ); // x - 1, y + LabelColorPixel( pixel - pixelSize - stride, labelPointer - 1 - 2 - imageWidth ); // x - 1, y - 1 + LabelColorPixel( pixel - stride, labelPointer - 2 - imageWidth ); // x , y - 1 + LabelColorPixel( pixel + pixelSize - stride, labelPointer + 1 - 2 - imageWidth ); // x + 1, y - 1 + } + } + } +} diff --git a/Sources/Accord.Imaging/AForge/SusanCornersDetector.cs b/Sources/Accord.Imaging/AForge/SusanCornersDetector.cs new file mode 100644 index 0000000000..5e61385bd --- /dev/null +++ b/Sources/Accord.Imaging/AForge/SusanCornersDetector.cs @@ -0,0 +1,352 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// +// Copyright Frank Nagl, 2007 +// admin@franknagl.de +// +namespace AForge.Imaging +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + using System.Collections.Generic; + using AForge.Imaging.Filters; + + /// + /// Susan corners detector. + /// + /// + /// The class implements Susan corners detector, which is described by + /// S.M. Smith in: S.M. Smith, "SUSAN - a new approach to low level image processing", + /// Internal Technical Report TR95SMS1, Defense Research Agency, Chobham Lane, Chertsey, + /// Surrey, UK, 1995. + /// + /// Some implementation notes: + /// + /// Analyzing each pixel and searching for its USAN area, the 7x7 mask is used, + /// which is comprised of 37 pixels. The mask has circle shape: + /// + /// xxx + /// xxxxx + /// xxxxxxx + /// xxxxxxx + /// xxxxxxx + /// xxxxx + /// xxx + /// + /// + /// In the case if USAN's center of mass has the same coordinates as nucleus + /// (central point), the pixel is not a corner. + /// For noise suppression the 5x5 square window is used. + /// + /// The class processes only grayscale 8 bpp and color 24/32 bpp images. + /// In the case of color image, it is converted to grayscale internally using + /// filter. + /// + /// Sample usage: + /// + /// // create corners detector's instance + /// SusanCornersDetector scd = new SusanCornersDetector( ); + /// // process image searching for corners + /// List<IntPoint> corners = scd.ProcessImage( image ); + /// // process points + /// foreach ( IntPoint corner in corners ) + /// { + /// // ... + /// } + /// + /// + /// + /// + /// + public class SusanCornersDetector : ICornersDetector + { + // brightness difference threshold + private int differenceThreshold = 25; + // geometrical threshold + private int geometricalThreshold = 18; + + /// + /// Brightness difference threshold. + /// + /// + /// The brightness difference threshold controls the amount + /// of pixels, which become part of USAN area. If difference between central + /// pixel (nucleus) and surrounding pixel is not higher than difference threshold, + /// then that pixel becomes part of USAN. + /// + /// Increasing this value decreases the amount of detected corners. + /// + /// Default value is set to 25. + /// + /// + public int DifferenceThreshold + { + get { return differenceThreshold; } + set { differenceThreshold = value; } + } + + /// + /// Geometrical threshold. + /// + /// + /// The geometrical threshold sets the maximum number of pixels + /// in USAN area around corner. If potential corner has USAN with more pixels, than + /// it is not a corner. + /// + /// Decreasing this value decreases the amount of detected corners - only sharp corners + /// are detected. Increasing this value increases the amount of detected corners, but + /// also increases amount of flat corners, which may be not corners at all. + /// + /// Default value is set to 18, which is half of maximum amount of pixels in USAN. + /// + /// + public int GeometricalThreshold + { + get { return geometricalThreshold; } + set { geometricalThreshold = value; } + } + + private static int[] rowRadius = new int[7] { 1, 2, 3, 3, 3, 2, 1 }; + + /// + /// Initializes a new instance of the class. + /// + public SusanCornersDetector( ) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Brightness difference threshold. + /// Geometrical threshold. + /// + public SusanCornersDetector( int differenceThreshold, int geometricalThreshold ) + { + this.differenceThreshold = differenceThreshold; + this.geometricalThreshold = geometricalThreshold; + } + + /// + /// Process image looking for corners. + /// + /// + /// Source image to process. + /// + /// Returns list of found corners (X-Y coordinates). + /// + /// The source image has incorrect pixel format. + /// + public List ProcessImage( Bitmap image ) + { + // check image format + if ( + ( image.PixelFormat != PixelFormat.Format8bppIndexed ) && + ( image.PixelFormat != PixelFormat.Format24bppRgb ) && + ( image.PixelFormat != PixelFormat.Format32bppRgb ) && + ( image.PixelFormat != PixelFormat.Format32bppArgb ) + ) + { + throw new UnsupportedImageFormatException( "Unsupported pixel format of the source image." ); + } + + // lock source image + BitmapData imageData = image.LockBits( + new Rectangle( 0, 0, image.Width, image.Height ), + ImageLockMode.ReadOnly, image.PixelFormat ); + + List corners; + + try + { + // process the image + corners = ProcessImage( new UnmanagedImage( imageData ) ); + } + finally + { + // unlock image + image.UnlockBits( imageData ); + } + + return corners; + } + + /// + /// Process image looking for corners. + /// + /// + /// Source image data to process. + /// + /// Returns list of found corners (X-Y coordinates). + /// + /// The source image has incorrect pixel format. + /// + public List ProcessImage( BitmapData imageData ) + { + return ProcessImage( new UnmanagedImage( imageData ) ); + } + + /// + /// Process image looking for corners. + /// + /// + /// Unmanaged source image to process. + /// + /// Returns array of found corners (X-Y coordinates). + /// + /// The source image has incorrect pixel format. + /// + public List ProcessImage( UnmanagedImage image ) + { + // check image format + if ( + ( image.PixelFormat != PixelFormat.Format8bppIndexed ) && + ( image.PixelFormat != PixelFormat.Format24bppRgb ) && + ( image.PixelFormat != PixelFormat.Format32bppRgb ) && + ( image.PixelFormat != PixelFormat.Format32bppArgb ) + ) + { + throw new UnsupportedImageFormatException( "Unsupported pixel format of the source image." ); + } + + // get source image size + int width = image.Width; + int height = image.Height; + + // make sure we have grayscale image + UnmanagedImage grayImage = null; + + if ( image.PixelFormat == PixelFormat.Format8bppIndexed ) + { + grayImage = image; + } + else + { + // create temporary grayscale image + grayImage = Grayscale.CommonAlgorithms.BT709.Apply( image ); + } + + int[,] susanMap = new int[height, width]; + + // do the job + unsafe + { + int stride = grayImage.Stride; + int offset = stride - width; + + byte* src = (byte*) grayImage.ImageData.ToPointer( ) + stride * 3 + 3; + + // for each row + for ( int y = 3, maxY = height - 3; y < maxY; y++ ) + { + // for each pixel + for ( int x = 3, maxX = width - 3; x < maxX; x++, src++ ) + { + // get value of the nucleus + byte nucleusValue = *src; + // usan - number of pixels with similar brightness + int usan = 0; + // center of gravity + int cx = 0, cy = 0; + + // for each row of the mask + for ( int i = -3; i <= 3; i++ ) + { + // determine row's radius + int r = rowRadius[i + 3]; + + // get pointer to the central pixel of the row + byte* ptr = (byte*)((int)src + stride * i); + + // for each element of the mask's row + for ( int j = -r; j <= r; j++ ) + { + // differenceThreshold + if ( System.Math.Abs( nucleusValue - ptr[j] ) <= differenceThreshold ) + { + usan++; + + cx += x + j; + cy += y + i; + } + } + } + + // check usan size + if ( usan < geometricalThreshold ) + { + cx /= usan; + cy /= usan; + + if ( ( x != cx ) || ( y != cy ) ) + { + // cornersList.Add( new Point( x, y ) ); + usan = ( geometricalThreshold - usan ); + } + else + { + usan = 0; + } + } + else + { + usan = 0; + } + + // usan = ( usan < geometricalThreshold ) ? ( geometricalThreshold - usan ) : 0; + susanMap[y, x] = usan; + } + + src += 6 + offset; + } + } + + if ( image.PixelFormat != PixelFormat.Format8bppIndexed ) + { + // free grayscale image + grayImage.Dispose( ); + } + + // collect interesting points - only those points, which are local maximums + List cornersList = new List( ); + + // for each row + for ( int y = 2, maxY = height - 2; y < maxY; y++ ) + { + // for each pixel + for ( int x = 2, maxX = width - 2; x < maxX; x++ ) + { + int currentValue = susanMap[y, x]; + + // for each windows' row + for ( int i = -2; ( currentValue != 0 ) && ( i <= 2 ); i++ ) + { + // for each windows' pixel + for ( int j = -2; j <= 2; j++ ) + { + if ( susanMap[y + i, x + j] > currentValue ) + { + currentValue = 0; + break; + } + } + } + + // check if this point is really interesting + if ( currentValue != 0 ) + { + cornersList.Add( new IntPoint( x, y ) ); + } + } + } + + return cornersList; + } + } +} diff --git a/Sources/Accord.Imaging/AForge/TemplateMatch.cs b/Sources/Accord.Imaging/AForge/TemplateMatch.cs new file mode 100644 index 0000000000..c6be63960 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/TemplateMatch.cs @@ -0,0 +1,53 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging +{ + using System; + using System.Drawing; + + /// + /// Template match class keeps information about found template match. The class is + /// used with template matching algorithms implementing + /// interface. + /// + public class TemplateMatch + { + private Rectangle rect; + private float similarity; + + /// + /// Rectangle of the matching area. + /// + public Rectangle Rectangle + { + get { return rect; } + } + + /// + /// Similarity between template and found matching, [0..1]. + /// + public float Similarity + { + get { return similarity; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Rectangle of the matching area. + /// Similarity between template and found matching, [0..1]. + /// + public TemplateMatch( Rectangle rect, float similarity ) + { + this.rect = rect; + this.similarity = similarity; + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Textures/CloudsTexture.cs b/Sources/Accord.Imaging/AForge/Textures/CloudsTexture.cs new file mode 100644 index 0000000000..ae7df0369 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Textures/CloudsTexture.cs @@ -0,0 +1,93 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2010 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Textures +{ + using System; + + /// + /// Clouds texture. + /// + /// + /// The texture generator creates textures with effect of clouds. + /// + /// The generator is based on the Perlin noise function. + /// + /// Sample usage: + /// + /// // create texture generator + /// CloudsTexture textureGenerator = new CloudsTexture( ); + /// // generate new texture + /// float[,] texture = textureGenerator.Generate( 320, 240 ); + /// // convert it to image to visualize + /// Bitmap textureImage = TextureTools.ToBitmap( texture ); + /// + /// + /// Result image: + /// + /// + /// + public class CloudsTexture : ITextureGenerator + { + // Perlin noise function used for texture generation + private AForge.Math.PerlinNoise noise = new AForge.Math.PerlinNoise( 8, 0.5, 1.0 / 32, 1.0 ); + + // randmom number generator + private Random rand = new Random( ); + private int r; + + /// + /// Initializes a new instance of the class. + /// + /// + public CloudsTexture( ) + { + Reset( ); + } + + /// + /// Generate texture. + /// + /// + /// Texture's width. + /// Texture's height. + /// + /// Two dimensional array of intensities. + /// + /// Generates new texture of the specified size. + /// + public float[,] Generate( int width, int height ) + { + float[,] texture = new float[height, width]; + + for ( int y = 0; y < height; y++ ) + { + for ( int x = 0; x < width; x++ ) + { + texture[y, x] = + Math.Max( 0.0f, Math.Min( 1.0f, + (float) noise.Function2D( x + r, y + r ) * 0.5f + 0.5f + ) ); + + } + } + return texture; + } + + /// + /// Reset generator. + /// + /// + /// Regenerates internal random numbers. + /// + public void Reset( ) + { + r = rand.Next( 5000 ); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Textures/ITextureGenerator.cs b/Sources/Accord.Imaging/AForge/Textures/ITextureGenerator.cs new file mode 100644 index 0000000000..d75907cd4 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Textures/ITextureGenerator.cs @@ -0,0 +1,45 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Textures +{ + using System; + + /// + /// Texture generator interface. + /// + /// + /// Each texture generator generates a 2-D texture of the specified size and returns + /// it as two dimensional array of intensities in the range of [0, 1] - texture's values. + /// + /// + public interface ITextureGenerator + { + /// + /// Generate texture. + /// + /// + /// Texture's width. + /// Texture's height. + /// + /// Two dimensional array of texture's intensities. + /// + /// Generates new texture of the specified size. + /// + float[,] Generate( int width, int height ); + + /// + /// Reset generator. + /// + /// + /// Resets the generator - resets all internal variables, regenerates + /// internal random numbers, etc. + /// + void Reset( ); + } +} diff --git a/Sources/Accord.Imaging/AForge/Textures/LabyrinthTexture.cs b/Sources/Accord.Imaging/AForge/Textures/LabyrinthTexture.cs new file mode 100644 index 0000000000..f6ac348b5 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Textures/LabyrinthTexture.cs @@ -0,0 +1,93 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Textures +{ + using System; + + /// + /// Labirinth texture. + /// + /// + /// The texture generator creates textures with effect of labyrinth. + /// + /// The generator is based on the Perlin noise function. + /// + /// Sample usage: + /// + /// // create texture generator + /// LabyrinthTexture textureGenerator = new LabyrinthTexture( ); + /// // generate new texture + /// float[,] texture = textureGenerator.Generate( 320, 240 ); + /// // convert it to image to visualize + /// Bitmap textureImage = TextureTools.ToBitmap( texture ); + /// + /// + /// Result image: + /// + /// + /// + public class LabyrinthTexture : ITextureGenerator + { + // Perlin noise function used for texture generation + private AForge.Math.PerlinNoise noise = new AForge.Math.PerlinNoise( 1, 0.65, 1.0 / 16, 1.0 ); + + // randmom number generator + private Random rand = new Random( ); + private int r; + + /// + /// Initializes a new instance of the class. + /// + /// + public LabyrinthTexture( ) + { + Reset( ); + } + + /// + /// Generate texture. + /// + /// + /// Texture's width. + /// Texture's height. + /// + /// Two dimensional array of intensities. + /// + /// Generates new texture of the specified size. + /// + public float[,] Generate( int width, int height ) + { + float[,] texture = new float[height, width]; + + for ( int y = 0; y < height; y++ ) + { + for ( int x = 0; x < width; x++ ) + { + texture[y, x] = + Math.Min( 1.0f, + (float) Math.Abs( noise.Function2D( x + r, y + r ) ) + ); + + } + } + return texture; + } + + /// + /// Reset generator. + /// + /// + /// Regenerates internal random numbers. + /// + public void Reset( ) + { + r = rand.Next( 5000 ); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Textures/MarbleTexture.cs b/Sources/Accord.Imaging/AForge/Textures/MarbleTexture.cs new file mode 100644 index 0000000000..364c31ff2 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Textures/MarbleTexture.cs differ diff --git a/Sources/Accord.Imaging/AForge/Textures/TextileTexture.cs b/Sources/Accord.Imaging/AForge/Textures/TextileTexture.cs new file mode 100644 index 0000000000..4a32d355f --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Textures/TextileTexture.cs @@ -0,0 +1,96 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2010 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Textures +{ + using System; + + /// + /// Textile texture. + /// + /// + /// The texture generator creates textures with effect of textile. + /// + /// The generator is based on the Perlin noise function. + /// + /// Sample usage: + /// + /// // create texture generator + /// TextileTexture textureGenerator = new TextileTexture( ); + /// // generate new texture + /// float[,] texture = textureGenerator.Generate( 320, 240 ); + /// // convert it to image to visualize + /// Bitmap textureImage = TextureTools.ToBitmap( texture ); + /// + /// + /// Result image: + /// + /// + /// + public class TextileTexture : ITextureGenerator + { + // Perlin noise function used for texture generation + private AForge.Math.PerlinNoise noise = new AForge.Math.PerlinNoise( 3, 0.65, 1.0 / 8, 1.0 ); + + // randmom number generator + private Random rand = new Random( ); + private int r; + + /// + /// Initializes a new instance of the class. + /// + /// + public TextileTexture( ) + { + Reset( ); + } + + /// + /// Generate texture. + /// + /// + /// Texture's width. + /// Texture's height. + /// + /// Two dimensional array of intensities. + /// + /// Generates new texture of the specified size. + /// + public float[,] Generate( int width, int height ) + { + float[,] texture = new float[height, width]; + + for ( int y = 0; y < height; y++ ) + { + for ( int x = 0; x < width; x++ ) + { + texture[y, x] = + Math.Max( 0.0f, Math.Min( 1.0f, + ( + (float) Math.Sin( x + noise.Function2D( x + r, y + r ) ) + + (float) Math.Sin( y + noise.Function2D( x + r, y + r ) ) + ) * 0.25f + 0.5f + ) ); + + } + } + return texture; + } + + /// + /// Reset generator. + /// + /// + /// Regenerates internal random numbers. + /// + public void Reset( ) + { + r = rand.Next( 5000 ); + } + } +} diff --git a/Sources/Accord.Imaging/AForge/Textures/Texture.cs b/Sources/Accord.Imaging/AForge/Textures/Texture.cs new file mode 100644 index 0000000000..a63878c49 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/Textures/Texture.cs @@ -0,0 +1,169 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2010 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Imaging.Textures +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + /// + /// Texture tools. + /// + /// + /// The class represents collection of different texture tools, like + /// converting a texture to/from grayscale image. + /// + /// Sample usage: + /// + /// // create texture generator + /// WoodTexture textureGenerator = new WoodTexture( ); + /// // generate new texture + /// float[,] texture = textureGenerator.Generate( 320, 240 ); + /// // convert it to image to visualize + /// Bitmap textureImage = TextureTools.ToBitmap( texture ); + /// + /// + /// + public class TextureTools + { + // Avoid class instantiation + private TextureTools( ) { } + + /// + /// Convert texture to grayscale bitmap. + /// + /// + /// Texture to convert to bitmap. + /// + /// Returns bitmap of the texture. + /// + public static Bitmap ToBitmap( float[,] texture ) + { + // get texture dimension + int width = texture.GetLength( 1 ); + int height = texture.GetLength( 0 ); + + // create new grawscale image + Bitmap dstImage = AForge.Imaging.Image.CreateGrayscaleImage( width, height ); + + // lock destination bitmap data + BitmapData dstData = dstImage.LockBits( + new Rectangle( 0, 0, width, height ), + ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed ); + + // do the job + unsafe + { + byte* dst = (byte*) dstData.Scan0.ToPointer( ); + int offset = dstData.Stride - width; + + // for each line + for ( int y = 0; y < height; y++ ) + { + // for each pixel + for ( int x = 0; x < width; x++, dst++ ) + { + *dst = (byte) ( texture[y, x] * 255.0f ); + } + dst += offset; + } + } + + // unlock destination images + dstImage.UnlockBits( dstData ); + + return dstImage; + } + + /// + /// Convert grayscale bitmap to texture. + /// + /// + /// Image to convert to texture. + /// + /// Returns texture as 2D float array. + /// + /// Only grayscale (8 bpp indexed images) are supported. + /// + public static float[,] FromBitmap( Bitmap image ) + { + // lock source bitmap data + BitmapData imageData = image.LockBits( + new Rectangle( 0, 0, image.Width, image.Height ), + ImageLockMode.ReadOnly, image.PixelFormat ); + + // process the image + float[,] texture = FromBitmap( imageData ); + + // unlock source image + image.UnlockBits( imageData ); + + return texture; + } + + /// + /// Convert grayscale bitmap to texture + /// + /// + /// Image data to convert to texture + /// + /// Returns texture as 2D float array. + /// + /// Only grayscale (8 bpp indexed images) are supported. + /// + public static float[,] FromBitmap( BitmapData imageData ) + { + return FromBitmap( new UnmanagedImage( imageData ) ); + } + + /// + /// Convert grayscale bitmap to texture. + /// + /// + /// Image data to convert to texture. + /// + /// Returns texture as 2D float array. + /// + /// Only grayscale (8 bpp indexed images) are supported. + /// + public static float[,] FromBitmap( UnmanagedImage image ) + { + // check source image + if ( image.PixelFormat != PixelFormat.Format8bppIndexed ) + throw new UnsupportedImageFormatException( "Only grayscale (8 bpp indexed images) are supported." ); + + // get source image dimension + int width = image.Width; + int height = image.Height; + + // create texture array + float[,] texture = new float[height, width]; + + // do the job + unsafe + { + byte* src = (byte*) image.ImageData.ToPointer( ); + int offset = image.Stride - width; + + // for each line + for ( int y = 0; y < height; y++ ) + { + // for each pixel + for ( int x = 0; x < width; x++, src++ ) + { + texture[y, x] = (float) *src / 255.0f; + } + src += offset; + } + } + + return texture; + } + } +} \ No newline at end of file diff --git a/Sources/Accord.Imaging/AForge/Textures/WoodTexture.cs b/Sources/Accord.Imaging/AForge/Textures/WoodTexture.cs new file mode 100644 index 0000000000..b17199f76 Binary files /dev/null and b/Sources/Accord.Imaging/AForge/Textures/WoodTexture.cs differ diff --git a/Sources/Accord.Imaging/AForge/UnmanagedImage.cs b/Sources/Accord.Imaging/AForge/UnmanagedImage.cs new file mode 100644 index 0000000000..0e12ffca9 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/UnmanagedImage.cs @@ -0,0 +1,1106 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2012 +// contacts@aforgenet.com +// + +namespace AForge.Imaging +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + using System.Collections.Generic; + + /// + /// Image in unmanaged memory. + /// + /// + /// + /// The class represents wrapper of an image in unmanaged memory. Using this class + /// it is possible as to allocate new image in unmanaged memory, as to just wrap provided + /// pointer to unmanaged memory, where an image is stored. + /// + /// Usage of unmanaged images is mostly beneficial when it is required to apply multiple + /// image processing routines to a single image. In such scenario usage of .NET managed images + /// usually leads to worse performance, because each routine needs to lock managed image + /// before image processing is done and then unlock it after image processing is done. Without + /// these lock/unlock there is no way to get direct access to managed image's data, which means + /// there is no way to do fast image processing. So, usage of managed images lead to overhead, which + /// is caused by locks/unlock. Unmanaged images are represented internally using unmanaged memory + /// buffer. This means that it is not required to do any locks/unlocks in order to get access to image + /// data (no overhead). + /// + /// Sample usage: + /// + /// // sample 1 - wrapping .NET image into unmanaged without + /// // making extra copy of image in memory + /// BitmapData imageData = image.LockBits( + /// new Rectangle( 0, 0, image.Width, image.Height ), + /// ImageLockMode.ReadWrite, image.PixelFormat ); + /// + /// try + /// { + /// UnmanagedImage unmanagedImage = new UnmanagedImage( imageData ) ); + /// // apply several routines to the unmanaged image + /// } + /// finally + /// { + /// image.UnlockBits( imageData ); + /// } + /// + /// + /// // sample 2 - converting .NET image into unmanaged + /// UnmanagedImage unmanagedImage = UnmanagedImage.FromManagedImage( image ); + /// // apply several routines to the unmanaged image + /// ... + /// // conver to managed image if it is required to display it at some point of time + /// Bitmap managedImage = unmanagedImage.ToManagedImage( ); + /// + /// + /// + public class UnmanagedImage : IDisposable + { + // pointer to image data in unmanaged memory + private IntPtr imageData; + // image size + private int width, height; + // image stride (line size) + private int stride; + // image pixel format + private PixelFormat pixelFormat; + // flag which indicates if the image should be disposed or not + private bool mustBeDisposed = false; + + /// + /// Pointer to image data in unmanaged memory. + /// + public IntPtr ImageData + { + get { return imageData; } + } + + /// + /// Image width in pixels. + /// + public int Width + { + get { return width; } + } + + /// + /// Image height in pixels. + /// + public int Height + { + get { return height; } + } + + /// + /// Image stride (line size in bytes). + /// + public int Stride + { + get { return stride; } + } + + /// + /// Image pixel format. + /// + public PixelFormat PixelFormat + { + get { return pixelFormat; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Pointer to image data in unmanaged memory. + /// Image width in pixels. + /// Image height in pixels. + /// Image stride (line size in bytes). + /// Image pixel format. + /// + /// Using this constructor, make sure all specified image attributes are correct + /// and correspond to unmanaged memory buffer. If some attributes are specified incorrectly, + /// this may lead to exceptions working with the unmanaged memory. + /// + public UnmanagedImage(IntPtr imageData, int width, int height, int stride, PixelFormat pixelFormat) + { + this.imageData = imageData; + this.width = width; + this.height = height; + this.stride = stride; + this.pixelFormat = pixelFormat; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Locked bitmap data. + /// + /// Unlike method, this constructor does not make + /// copy of managed image. This means that managed image must stay locked for the time of using the instance + /// of unamanged image. + /// + public UnmanagedImage(BitmapData bitmapData) + { + this.imageData = bitmapData.Scan0; + this.width = bitmapData.Width; + this.height = bitmapData.Height; + this.stride = bitmapData.Stride; + this.pixelFormat = bitmapData.PixelFormat; + } + + /// + /// Destroys the instance of the class. + /// + /// + ~UnmanagedImage() + { + Dispose(false); + } + + /// + /// Dispose the object. + /// + /// + /// Frees unmanaged resources used by the object. The object becomes unusable + /// after that. + /// + /// The method needs to be called only in the case if unmanaged image was allocated + /// using method. In the case if the class instance was created using constructor, + /// this method does not free unmanaged memory. + /// + /// + public void Dispose() + { + Dispose(true); + // remove me from the Finalization queue + GC.SuppressFinalize(this); + } + + /// + /// Dispose the object. + /// + /// + /// Indicates if disposing was initiated manually. + /// + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + // dispose managed resources + } + // free image memory if the image was allocated using this class + if ((mustBeDisposed) && (imageData != IntPtr.Zero)) + { + System.Runtime.InteropServices.Marshal.FreeHGlobal(imageData); + System.GC.RemoveMemoryPressure(stride * height); + imageData = IntPtr.Zero; + } + } + + /// + /// Clone the unmanaged images. + /// + /// + /// Returns clone of the unmanaged image. + /// + /// The method does complete cloning of the object. + /// + public UnmanagedImage Clone() + { + // allocate memory for the image + IntPtr newImageData = System.Runtime.InteropServices.Marshal.AllocHGlobal(stride * height); + System.GC.AddMemoryPressure(stride * height); + + UnmanagedImage newImage = new UnmanagedImage(newImageData, width, height, stride, pixelFormat); + newImage.mustBeDisposed = true; + + AForge.SystemTools.CopyUnmanagedMemory(newImageData, imageData, stride * height); + + return newImage; + } + + /// + /// Copy unmanaged image. + /// + /// + /// Destination image to copy this image to. + /// + /// The method copies current unmanaged image to the specified image. + /// Size and pixel format of the destination image must be exactly the same. + /// + /// Destination image has different size or pixel format. + /// + public void Copy(UnmanagedImage destImage) + { + if ( + (width != destImage.width) || (height != destImage.height) || + (pixelFormat != destImage.pixelFormat)) + { + throw new InvalidImagePropertiesException("Destination image has different size or pixel format."); + } + + if (stride == destImage.stride) + { + // copy entire image + AForge.SystemTools.CopyUnmanagedMemory(destImage.imageData, imageData, stride * height); + } + else + { + unsafe + { + int dstStride = destImage.stride; + int copyLength = (stride < dstStride) ? stride : dstStride; + + byte* src = (byte*)imageData.ToPointer(); + byte* dst = (byte*)destImage.imageData.ToPointer(); + + // copy line by line + for (int i = 0; i < height; i++) + { + AForge.SystemTools.CopyUnmanagedMemory(dst, src, copyLength); + + dst += dstStride; + src += stride; + } + } + } + } + + /// + /// Allocate new image in unmanaged memory. + /// + /// + /// Image width. + /// Image height. + /// Image pixel format. + /// + /// Return image allocated in unmanaged memory. + /// + /// Allocate new image with specified attributes in unmanaged memory. + /// + /// The method supports only + /// Format8bppIndexed, + /// Format16bppGrayScale, + /// Format24bppRgb, + /// Format32bppRgb, + /// Format32bppArgb, + /// Format32bppPArgb, + /// Format48bppRgb, + /// Format64bppArgb and + /// Format64bppPArgb pixel formats. + /// In the case if Format8bppIndexed + /// format is specified, pallete is not not created for the image (supposed that it is + /// 8 bpp grayscale image). + /// + /// + /// + /// Unsupported pixel format was specified. + /// Invalid image size was specified. + /// + public static UnmanagedImage Create(int width, int height, PixelFormat pixelFormat) + { + int bytesPerPixel = 0; + + // calculate bytes per pixel + switch (pixelFormat) + { + case PixelFormat.Format8bppIndexed: + bytesPerPixel = 1; + break; + case PixelFormat.Format16bppGrayScale: + bytesPerPixel = 2; + break; + case PixelFormat.Format24bppRgb: + bytesPerPixel = 3; + break; + case PixelFormat.Format32bppRgb: + case PixelFormat.Format32bppArgb: + case PixelFormat.Format32bppPArgb: + bytesPerPixel = 4; + break; + case PixelFormat.Format48bppRgb: + bytesPerPixel = 6; + break; + case PixelFormat.Format64bppArgb: + case PixelFormat.Format64bppPArgb: + bytesPerPixel = 8; + break; + default: + throw new UnsupportedImageFormatException("Can not create image with specified pixel format."); + } + + // check image size + if ((width <= 0) || (height <= 0)) + { + throw new InvalidImagePropertiesException("Invalid image size specified."); + } + + // calculate stride + int stride = width * bytesPerPixel; + + if (stride % 4 != 0) + { + stride += (4 - (stride % 4)); + } + + // allocate memory for the image + IntPtr imageData = System.Runtime.InteropServices.Marshal.AllocHGlobal(stride * height); + AForge.SystemTools.SetUnmanagedMemory(imageData, 0, stride * height); + System.GC.AddMemoryPressure(stride * height); + + UnmanagedImage image = new UnmanagedImage(imageData, width, height, stride, pixelFormat); + image.mustBeDisposed = true; + + return image; + } + + /// + /// Create managed image from the unmanaged. + /// + /// + /// Returns managed copy of the unmanaged image. + /// + /// The method creates a managed copy of the unmanaged image with the + /// same size and pixel format (it calls specifying + /// for the makeCopy parameter). + /// + public Bitmap ToManagedImage() + { + return ToManagedImage(true); + } + + /// + /// Create managed image from the unmanaged. + /// + /// + /// Make a copy of the unmanaged image or not. + /// + /// Returns managed copy of the unmanaged image. + /// + /// If the is set to , then the method + /// creates a managed copy of the unmanaged image, so the managed image stays valid even when the unmanaged + /// image gets disposed. However, setting this parameter to creates a managed image which is + /// just a wrapper around the unmanaged image. So if unmanaged image is disposed, the + /// managed image becomes no longer valid and accessing it will generate an exception. + /// + /// The unmanaged image has some invalid properties, which results + /// in failure of converting it to managed image. This may happen if user used the + /// constructor specifying some + /// invalid parameters. + /// + public Bitmap ToManagedImage(bool makeCopy) + { + Bitmap dstImage = null; + + try + { + if (!makeCopy) + { + dstImage = new Bitmap(width, height, stride, pixelFormat, imageData); + if (pixelFormat == PixelFormat.Format8bppIndexed) + { + Image.SetGrayscalePalette(dstImage); + } + } + else + { + // create new image of required format + dstImage = (pixelFormat == PixelFormat.Format8bppIndexed) ? + AForge.Imaging.Image.CreateGrayscaleImage(width, height) : + new Bitmap(width, height, pixelFormat); + + // lock destination bitmap data + BitmapData dstData = dstImage.LockBits( + new Rectangle(0, 0, width, height), + ImageLockMode.ReadWrite, pixelFormat); + + int dstStride = dstData.Stride; + int lineSize = Math.Min(stride, dstStride); + + unsafe + { + byte* dst = (byte*)dstData.Scan0.ToPointer(); + byte* src = (byte*)imageData.ToPointer(); + + if (stride != dstStride) + { + // copy image + for (int y = 0; y < height; y++) + { + AForge.SystemTools.CopyUnmanagedMemory(dst, src, lineSize); + dst += dstStride; + src += stride; + } + } + else + { + AForge.SystemTools.CopyUnmanagedMemory(dst, src, stride * height); + } + } + + // unlock destination images + dstImage.UnlockBits(dstData); + } + + return dstImage; + } + catch (Exception) + { + if (dstImage != null) + { + dstImage.Dispose(); + } + + throw new InvalidImagePropertiesException("The unmanaged image has some invalid properties, which results in failure of converting it to managed image."); + } + } + + /// + /// Create unmanaged image from the specified managed image. + /// + /// + /// Source managed image. + /// + /// Returns new unmanaged image, which is a copy of source managed image. + /// + /// The method creates an exact copy of specified managed image, but allocated + /// in unmanaged memory. + /// + /// Unsupported pixel format of source image. + /// + public static UnmanagedImage FromManagedImage(Bitmap image) + { + UnmanagedImage dstImage = null; + + BitmapData sourceData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, image.PixelFormat); + + try + { + dstImage = FromManagedImage(sourceData); + } + finally + { + image.UnlockBits(sourceData); + } + + return dstImage; + } + + /// + /// Create unmanaged image from the specified managed image. + /// + /// + /// Source locked image data. + /// + /// Returns new unmanaged image, which is a copy of source managed image. + /// + /// The method creates an exact copy of specified managed image, but allocated + /// in unmanaged memory. This means that managed image may be unlocked right after call to this + /// method. + /// + /// Unsupported pixel format of source image. + /// + public static UnmanagedImage FromManagedImage(BitmapData imageData) + { + PixelFormat pixelFormat = imageData.PixelFormat; + + // check source pixel format + if ( + (pixelFormat != PixelFormat.Format8bppIndexed) && + (pixelFormat != PixelFormat.Format16bppGrayScale) && + (pixelFormat != PixelFormat.Format24bppRgb) && + (pixelFormat != PixelFormat.Format32bppRgb) && + (pixelFormat != PixelFormat.Format32bppArgb) && + (pixelFormat != PixelFormat.Format32bppPArgb) && + (pixelFormat != PixelFormat.Format48bppRgb) && + (pixelFormat != PixelFormat.Format64bppArgb) && + (pixelFormat != PixelFormat.Format64bppPArgb)) + { + throw new UnsupportedImageFormatException("Unsupported pixel format of the source image."); + } + + // allocate memory for the image + IntPtr dstImageData = System.Runtime.InteropServices.Marshal.AllocHGlobal(imageData.Stride * imageData.Height); + System.GC.AddMemoryPressure(imageData.Stride * imageData.Height); + + UnmanagedImage image = new UnmanagedImage(dstImageData, imageData.Width, imageData.Height, imageData.Stride, pixelFormat); + AForge.SystemTools.CopyUnmanagedMemory(dstImageData, imageData.Scan0, imageData.Stride * imageData.Height); + image.mustBeDisposed = true; + + return image; + } + + /// + /// Collect pixel values from the specified list of coordinates. + /// + /// + /// List of coordinates to collect pixels' value from. + /// + /// Returns array of pixels' values from the specified coordinates. + /// + /// The method goes through the specified list of points and for each point retrievs + /// corresponding pixel's value from the unmanaged image. + /// + /// For grayscale image the output array has the same length as number of points in the + /// specified list of points. For color image the output array has triple length, containing pixels' + /// values in RGB order. + /// + /// The method does not make any checks for valid coordinates and leaves this up to user. + /// If specified coordinates are out of image's bounds, the result is not predictable (crash in most cases). + /// + /// + /// This method is supposed for images with 8 bpp channels only (8 bpp grayscale image and + /// 24/32 bpp color images). + /// + /// + /// Unsupported pixel format of the source image. Use Collect16bppPixelValues() method for + /// images with 16 bpp channels. + /// + public byte[] Collect8bppPixelValues(List points) + { + int pixelSize = Bitmap.GetPixelFormatSize(pixelFormat) / 8; + + if ((pixelFormat == PixelFormat.Format16bppGrayScale) || (pixelSize > 4)) + { + throw new UnsupportedImageFormatException("Unsupported pixel format of the source image. Use Collect16bppPixelValues() method for it."); + } + + byte[] pixelValues = new byte[points.Count * ((pixelFormat == PixelFormat.Format8bppIndexed) ? 1 : 3)]; + + unsafe + { + byte* basePtr = (byte*)imageData.ToPointer(); + byte* ptr; + + if (pixelFormat == PixelFormat.Format8bppIndexed) + { + int i = 0; + + foreach (IntPoint point in points) + { + ptr = basePtr + stride * point.Y + point.X; + pixelValues[i++] = *ptr; + } + } + else + { + int i = 0; + + foreach (IntPoint point in points) + { + ptr = basePtr + stride * point.Y + point.X * pixelSize; + pixelValues[i++] = ptr[RGB.R]; + pixelValues[i++] = ptr[RGB.G]; + pixelValues[i++] = ptr[RGB.B]; + } + } + } + + return pixelValues; + } + + /// + /// Collect coordinates of none black pixels in the image. + /// + /// + /// Returns list of points, which have other than black color. + /// + public List CollectActivePixels() + { + return CollectActivePixels(new Rectangle(0, 0, width, height)); + } + + /// + /// Collect coordinates of none black pixels within specified rectangle of the image. + /// + /// + /// Image's rectangle to process. + /// + /// Returns list of points, which have other than black color. + /// + public List CollectActivePixels(Rectangle rect) + { + List pixels = new List(); + + int pixelSize = Bitmap.GetPixelFormatSize(pixelFormat) / 8; + + // correct rectangle + rect.Intersect(new Rectangle(0, 0, width, height)); + + int startX = rect.X; + int startY = rect.Y; + int stopX = rect.Right; + int stopY = rect.Bottom; + + unsafe + { + byte* basePtr = (byte*)imageData.ToPointer(); + + if ((pixelFormat == PixelFormat.Format16bppGrayScale) || (pixelSize > 4)) + { + int pixelWords = pixelSize >> 1; + + for (int y = startY; y < stopY; y++) + { + ushort* ptr = (ushort*)(basePtr + y * stride + startX * pixelSize); + + if (pixelWords == 1) + { + // grayscale images + for (int x = startX; x < stopX; x++, ptr++) + { + if (*ptr != 0) + { + pixels.Add(new IntPoint(x, y)); + } + } + } + else + { + // color images + for (int x = startX; x < stopX; x++, ptr += pixelWords) + { + if ((ptr[RGB.R] != 0) || (ptr[RGB.G] != 0) || (ptr[RGB.B] != 0)) + { + pixels.Add(new IntPoint(x, y)); + } + } + } + } + } + else + { + for (int y = startY; y < stopY; y++) + { + byte* ptr = basePtr + y * stride + startX * pixelSize; + + if (pixelSize == 1) + { + // grayscale images + for (int x = startX; x < stopX; x++, ptr++) + { + if (*ptr != 0) + { + pixels.Add(new IntPoint(x, y)); + } + } + } + else + { + // color images + for (int x = startX; x < stopX; x++, ptr += pixelSize) + { + if ((ptr[RGB.R] != 0) || (ptr[RGB.G] != 0) || (ptr[RGB.B] != 0)) + { + pixels.Add(new IntPoint(x, y)); + } + } + } + } + } + } + + return pixels; + } + + /// + /// Set pixels with the specified coordinates to the specified color. + /// + /// + /// List of points to set color for. + /// Color to set for the specified points. + /// + /// For images having 16 bpp per color plane, the method extends the specified color + /// value to 16 bit by multiplying it by 256. + /// + public void SetPixels(List coordinates, Color color) + { + unsafe + { + int pixelSize = Bitmap.GetPixelFormatSize(pixelFormat) / 8; + byte* basePtr = (byte*)imageData.ToPointer(); + + byte red = color.R; + byte green = color.G; + byte blue = color.B; + byte alpha = color.A; + + switch (pixelFormat) + { + case PixelFormat.Format8bppIndexed: + { + byte grayValue = (byte)(0.2125 * red + 0.7154 * green + 0.0721 * blue); + + foreach (IntPoint point in coordinates) + { + if ((point.X >= 0) && (point.Y >= 0) && (point.X < width) && (point.Y < height)) + { + byte* ptr = basePtr + point.Y * stride + point.X; + *ptr = grayValue; + } + } + } + break; + + case PixelFormat.Format24bppRgb: + case PixelFormat.Format32bppRgb: + { + + + foreach (IntPoint point in coordinates) + { + if ((point.X >= 0) && (point.Y >= 0) && (point.X < width) && (point.Y < height)) + { + byte* ptr = basePtr + point.Y * stride + point.X * pixelSize; + ptr[RGB.R] = red; + ptr[RGB.G] = green; + ptr[RGB.B] = blue; + } + } + } + break; + + case PixelFormat.Format32bppArgb: + { + foreach (IntPoint point in coordinates) + { + if ((point.X >= 0) && (point.Y >= 0) && (point.X < width) && (point.Y < height)) + { + byte* ptr = basePtr + point.Y * stride + point.X * pixelSize; + ptr[RGB.R] = red; + ptr[RGB.G] = green; + ptr[RGB.B] = blue; + ptr[RGB.A] = alpha; + } + } + } + break; + + case PixelFormat.Format16bppGrayScale: + { + ushort grayValue = (ushort)((ushort)(0.2125 * red + 0.7154 * green + 0.0721 * blue) << 8); + + foreach (IntPoint point in coordinates) + { + if ((point.X >= 0) && (point.Y >= 0) && (point.X < width) && (point.Y < height)) + { + ushort* ptr = (ushort*)(basePtr + point.Y * stride) + point.X; + *ptr = grayValue; + } + } + } + break; + + case PixelFormat.Format48bppRgb: + { + ushort red16 = (ushort)(red << 8); + ushort green16 = (ushort)(green << 8); + ushort blue16 = (ushort)(blue << 8); + + foreach (IntPoint point in coordinates) + { + if ((point.X >= 0) && (point.Y >= 0) && (point.X < width) && (point.Y < height)) + { + ushort* ptr = (ushort*)(basePtr + point.Y * stride + point.X * pixelSize); + ptr[RGB.R] = red16; + ptr[RGB.G] = green16; + ptr[RGB.B] = blue16; + } + } + } + break; + + case PixelFormat.Format64bppArgb: + { + ushort red16 = (ushort)(red << 8); + ushort green16 = (ushort)(green << 8); + ushort blue16 = (ushort)(blue << 8); + ushort alpha16 = (ushort)(alpha << 8); + + foreach (IntPoint point in coordinates) + { + if ((point.X >= 0) && (point.Y >= 0) && (point.X < width) && (point.Y < height)) + { + ushort* ptr = (ushort*)(basePtr + point.Y * stride + point.X * pixelSize); + ptr[RGB.R] = red16; + ptr[RGB.G] = green16; + ptr[RGB.B] = blue16; + ptr[RGB.A] = alpha16; + } + } + } + break; + + default: + throw new UnsupportedImageFormatException("The pixel format is not supported: " + pixelFormat); + } + } + } + + /// + /// Set pixel with the specified coordinates to the specified color. + /// + /// + /// Point's coordiates to set color for. + /// Color to set for the pixel. + /// + /// See for more information. + /// + public void SetPixel(IntPoint point, Color color) + { + SetPixel(point.X, point.Y, color); + } + + /// + /// Set pixel with the specified coordinates to the specified color. + /// + /// + /// X coordinate of the pixel to set. + /// Y coordinate of the pixel to set. + /// Color to set for the pixel. + /// + /// For images having 16 bpp per color plane, the method extends the specified color + /// value to 16 bit by multiplying it by 256. + /// + /// For grayscale images this method will calculate intensity value based on the below formula: + /// + /// 0.2125 * Red + 0.7154 * Green + 0.0721 * Blue + /// + /// + /// + /// + public void SetPixel(int x, int y, Color color) + { + SetPixel(x, y, color.R, color.G, color.B, color.A); + } + + /// + /// Set pixel with the specified coordinates to the specified value. + /// + /// + /// X coordinate of the pixel to set. + /// Y coordinate of the pixel to set. + /// Pixel value to set. + /// + /// The method sets all color components of the pixel to the specified value. + /// If it is a grayscale image, then pixel's intensity is set to the specified value. + /// If it is a color image, then pixel's R/G/B components are set to the same specified value + /// (if an image has alpha channel, then it is set to maximum value - 255 or 65535). + /// + /// For images having 16 bpp per color plane, the method extends the specified color + /// value to 16 bit by multiplying it by 256. + /// + /// + public void SetPixel(int x, int y, byte value) + { + SetPixel(x, y, value, value, value, 255); + } + + private void SetPixel(int x, int y, byte r, byte g, byte b, byte a) + { + if ((x >= 0) && (y >= 0) && (x < width) && (y < height)) + { + unsafe + { + int pixelSize = Bitmap.GetPixelFormatSize(pixelFormat) / 8; + byte* ptr = (byte*)imageData.ToPointer() + y * stride + x * pixelSize; + ushort* ptr2 = (ushort*)ptr; + + switch (pixelFormat) + { + case PixelFormat.Format8bppIndexed: + *ptr = (byte)(0.2125 * r + 0.7154 * g + 0.0721 * b); + break; + + case PixelFormat.Format24bppRgb: + case PixelFormat.Format32bppRgb: + ptr[RGB.R] = r; + ptr[RGB.G] = g; + ptr[RGB.B] = b; + break; + + case PixelFormat.Format32bppArgb: + ptr[RGB.R] = r; + ptr[RGB.G] = g; + ptr[RGB.B] = b; + ptr[RGB.A] = a; + break; + + case PixelFormat.Format16bppGrayScale: + *ptr2 = (ushort)((ushort)(0.2125 * r + 0.7154 * g + 0.0721 * b) << 8); + break; + + case PixelFormat.Format48bppRgb: + ptr2[RGB.R] = (ushort)(r << 8); + ptr2[RGB.G] = (ushort)(g << 8); + ptr2[RGB.B] = (ushort)(b << 8); + break; + + case PixelFormat.Format64bppArgb: + ptr2[RGB.R] = (ushort)(r << 8); + ptr2[RGB.G] = (ushort)(g << 8); + ptr2[RGB.B] = (ushort)(b << 8); + ptr2[RGB.A] = (ushort)(a << 8); + break; + + default: + throw new UnsupportedImageFormatException("The pixel format is not supported: " + pixelFormat); + } + } + } + } + + /// + /// Get color of the pixel with the specified coordinates. + /// + /// + /// Point's coordiates to get color of. + /// + /// Return pixel's color at the specified coordinates. + /// + /// See for more information. + /// + public Color GetPixel(IntPoint point) + { + return GetPixel(point.X, point.Y); + } + + /// + /// Get color of the pixel with the specified coordinates. + /// + /// + /// X coordinate of the pixel to get. + /// Y coordinate of the pixel to get. + /// + /// Return pixel's color at the specified coordinates. + /// + /// + /// In the case if the image has 8 bpp grayscale format, the method will return a color with + /// all R/G/B components set to same value, which is grayscale intensity. + /// + /// The method supports only 8 bpp grayscale images and 24/32 bpp color images so far. + /// + /// + /// The specified pixel coordinate is out of image's bounds. + /// Pixel format of this image is not supported by the method. + /// + public Color GetPixel(int x, int y) + { + if ((x < 0) || (y < 0)) + { + throw new ArgumentOutOfRangeException("x", "The specified pixel coordinate is out of image's bounds."); + } + + if ((x >= width) || (y >= height)) + { + throw new ArgumentOutOfRangeException("y", "The specified pixel coordinate is out of image's bounds."); + } + + Color color = new Color(); + + unsafe + { + int pixelSize = Bitmap.GetPixelFormatSize(pixelFormat) / 8; + byte* ptr = (byte*)imageData.ToPointer() + y * stride + x * pixelSize; + + switch (pixelFormat) + { + case PixelFormat.Format8bppIndexed: + color = Color.FromArgb(*ptr, *ptr, *ptr); + break; + + case PixelFormat.Format24bppRgb: + case PixelFormat.Format32bppRgb: + color = Color.FromArgb(ptr[RGB.R], ptr[RGB.G], ptr[RGB.B]); + break; + + case PixelFormat.Format32bppArgb: + color = Color.FromArgb(ptr[RGB.A], ptr[RGB.R], ptr[RGB.G], ptr[RGB.B]); + break; + + default: + throw new UnsupportedImageFormatException("The pixel format is not supported: " + pixelFormat); + } + } + + return color; + } + + /// + /// Collect pixel values from the specified list of coordinates. + /// + /// + /// List of coordinates to collect pixels' value from. + /// + /// Returns array of pixels' values from the specified coordinates. + /// + /// The method goes through the specified list of points and for each point retrievs + /// corresponding pixel's value from the unmanaged image. + /// + /// For grayscale image the output array has the same length as number of points in the + /// specified list of points. For color image the output array has triple length, containing pixels' + /// values in RGB order. + /// + /// The method does not make any checks for valid coordinates and leaves this up to user. + /// If specified coordinates are out of image's bounds, the result is not predictable (crash in most cases). + /// + /// + /// This method is supposed for images with 16 bpp channels only (16 bpp grayscale image and + /// 48/64 bpp color images). + /// + /// + /// Unsupported pixel format of the source image. Use Collect8bppPixelValues() method for + /// images with 8 bpp channels. + /// + public ushort[] Collect16bppPixelValues(List points) + { + int pixelSize = Bitmap.GetPixelFormatSize(pixelFormat) / 8; + + if ((pixelFormat == PixelFormat.Format8bppIndexed) || (pixelSize == 3) || (pixelSize == 4)) + { + throw new UnsupportedImageFormatException("Unsupported pixel format of the source image. Use Collect8bppPixelValues() method for it."); + } + + ushort[] pixelValues = new ushort[points.Count * ((pixelFormat == PixelFormat.Format16bppGrayScale) ? 1 : 3)]; + + unsafe + { + byte* basePtr = (byte*)imageData.ToPointer(); + ushort* ptr; + + if (pixelFormat == PixelFormat.Format16bppGrayScale) + { + int i = 0; + + foreach (IntPoint point in points) + { + ptr = (ushort*)(basePtr + stride * point.Y + point.X * pixelSize); + pixelValues[i++] = *ptr; + } + } + else + { + int i = 0; + + foreach (IntPoint point in points) + { + ptr = (ushort*)(basePtr + stride * point.Y + point.X * pixelSize); + pixelValues[i++] = ptr[RGB.R]; + pixelValues[i++] = ptr[RGB.G]; + pixelValues[i++] = ptr[RGB.B]; + } + } + } + + return pixelValues; + } + } +} diff --git a/Sources/Accord.Imaging/AForge/VerticalIntensityStatistics.cs b/Sources/Accord.Imaging/AForge/VerticalIntensityStatistics.cs new file mode 100644 index 0000000000..e260fb7f6 --- /dev/null +++ b/Sources/Accord.Imaging/AForge/VerticalIntensityStatistics.cs @@ -0,0 +1,372 @@ +// AForge Image Processing Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + using AForge.Math; + + /// + /// Vertical intensity statistics. + /// + /// + /// The class provides information about vertical distribution + /// of pixel intensities, which may be used to locate objects, their centers, etc. + /// + /// + /// The class accepts grayscale (8 bpp indexed and 16 bpp) and color (24, 32, 48 and 64 bpp) images. + /// In the case of 32 and 64 bpp color images, the alpha channel is not processed - statistics is not + /// gathered for this channel. + /// + /// Sample usage: + /// + /// // collect statistics + /// VerticalIntensityStatistics vis = new VerticalIntensityStatistics( sourceImage ); + /// // get gray histogram (for grayscale image) + /// Histogram histogram = vis.Gray; + /// // output some histogram's information + /// System.Diagnostics.Debug.WriteLine( "Mean = " + histogram.Mean ); + /// System.Diagnostics.Debug.WriteLine( "Min = " + histogram.Min ); + /// System.Diagnostics.Debug.WriteLine( "Max = " + histogram.Max ); + /// + /// + /// Sample grayscale image with its vertical intensity histogram: + /// + /// + /// + /// + /// + public class VerticalIntensityStatistics + { + // histograms for RGB channgels + private Histogram red = null; + private Histogram green = null; + private Histogram blue = null; + // grayscale histogram + private Histogram gray = null; + + /// + /// Histogram for red channel. + /// + /// + public Histogram Red + { + get + { + if ( red == null ) + { + throw new InvalidImagePropertiesException( ExceptionMessage.ColorHistogramException ); + } + return red; + } + } + + /// + /// Histogram for green channel. + /// + /// + public Histogram Green + { + get + { + if ( green == null ) + { + throw new InvalidImagePropertiesException( ExceptionMessage.ColorHistogramException ); + } + return green; + } + } + + /// + /// Histogram for blue channel. + /// + /// + public Histogram Blue + { + get + { + if ( blue == null ) + { + throw new InvalidImagePropertiesException( ExceptionMessage.ColorHistogramException ); + } + return blue; + } + } + + /// + /// Histogram for gray channel (intensities). + /// + /// + public Histogram Gray + { + get + { + if ( gray == null ) + { + throw new InvalidImagePropertiesException( ExceptionMessage.GrayHistogramException ); + } + return gray; + } + } + + /// + /// Value wich specifies if the processed image was color or grayscale. + /// + /// + /// If the property equals to true, then the + /// property should be used to retrieve histogram for the processed grayscale image. + /// Otherwise , and property + /// should be used to retrieve histogram for particular RGB channel of the processed + /// color image. + /// + public bool IsGrayscale + { + get { return ( gray != null ); } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Source image. + /// + /// Unsupported pixel format of the source image. + /// + public VerticalIntensityStatistics( Bitmap image ) + { + // check image format + if ( + ( image.PixelFormat != PixelFormat.Format8bppIndexed ) && + ( image.PixelFormat != PixelFormat.Format16bppGrayScale ) && + ( image.PixelFormat != PixelFormat.Format24bppRgb ) && + ( image.PixelFormat != PixelFormat.Format32bppRgb ) && + ( image.PixelFormat != PixelFormat.Format32bppArgb ) && + ( image.PixelFormat != PixelFormat.Format48bppRgb ) && + ( image.PixelFormat != PixelFormat.Format64bppArgb ) + ) + { + throw new UnsupportedImageFormatException( "Unsupported pixel format of the source image." ); + } + + // lock bitmap data + BitmapData imageData = image.LockBits( + new Rectangle( 0, 0, image.Width, image.Height ), + ImageLockMode.ReadOnly, image.PixelFormat ); + + try + { + // gather statistics + ProcessImage( new UnmanagedImage( imageData ) ); + } + finally + { + // unlock image + image.UnlockBits( imageData ); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Source image data. + /// + /// Unsupported pixel format of the source image. + /// + public VerticalIntensityStatistics( BitmapData imageData ) + : this( new UnmanagedImage( imageData ) ) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Source unmanaged image. + /// + /// Unsupported pixel format of the source image. + /// + public VerticalIntensityStatistics( UnmanagedImage image ) + { + // check image format + if ( + ( image.PixelFormat != PixelFormat.Format8bppIndexed ) && + ( image.PixelFormat != PixelFormat.Format16bppGrayScale ) && + ( image.PixelFormat != PixelFormat.Format24bppRgb ) && + ( image.PixelFormat != PixelFormat.Format32bppRgb ) && + ( image.PixelFormat != PixelFormat.Format32bppArgb ) && + ( image.PixelFormat != PixelFormat.Format48bppRgb ) && + ( image.PixelFormat != PixelFormat.Format64bppArgb ) + ) + { + throw new UnsupportedImageFormatException( "Unsupported pixel format of the source image." ); + } + + // gather statistics + ProcessImage( image ); + } + + /// + /// Gather vertical intensity statistics for specified image. + /// + /// + /// Source image. + /// + private void ProcessImage( UnmanagedImage image ) + { + PixelFormat pixelFormat = image.PixelFormat; + // get image dimension + int width = image.Width; + int height = image.Height; + + red = green = blue = gray = null; + + // do the job + unsafe + { + // check pixel format + if ( pixelFormat == PixelFormat.Format8bppIndexed ) + { + // 8 bpp grayscale image + byte* p = (byte*) image.ImageData.ToPointer( ); + int offset = image.Stride - width; + + // histogram array + int[] g = new int[height]; + + // for each pixel + for ( int y = 0; y < height; y++ ) + { + int lineSum = 0; + + // for each pixel + for ( int x = 0; x < width; x++, p++ ) + { + lineSum += *p; + } + g[y] = lineSum; + + p += offset; + } + + // create historgram for gray level + gray = new Histogram( g ); + } + else if ( pixelFormat == PixelFormat.Format16bppGrayScale ) + { + // 16 bpp grayscale image + byte* basePtr = (byte*) image.ImageData.ToPointer( ); + int stride = image.Stride; + + // histogram array + int[] g = new int[height]; + + // for each pixel + for ( int y = 0; y < height; y++ ) + { + ushort* p = (ushort*) ( basePtr + stride * y ); + int lineSum = 0; + + // for each pixel + for ( int x = 0; x < width; x++, p++ ) + { + lineSum += *p; + } + g[y] = lineSum; + } + + // create historgram for gray level + gray = new Histogram( g ); + } + else if ( + ( pixelFormat == PixelFormat.Format24bppRgb ) || + ( pixelFormat == PixelFormat.Format32bppRgb ) || + ( pixelFormat == PixelFormat.Format32bppArgb ) ) + { + // 24/32 bpp color image + byte* p = (byte*) image.ImageData.ToPointer( ); + int pixelSize = ( pixelFormat == PixelFormat.Format24bppRgb ) ? 3 : 4; + int offset = image.Stride - width * pixelSize; + + // histogram arrays + int[] r = new int[height]; + int[] g = new int[height]; + int[] b = new int[height]; + + // for each line + for ( int y = 0; y < height; y++ ) + { + int lineRSum = 0; + int lineGSum = 0; + int lineBSum = 0; + + // for each pixel + for ( int x = 0; x < width; x++, p += pixelSize ) + { + lineRSum += p[RGB.R]; + lineGSum += p[RGB.G]; + lineBSum += p[RGB.B]; + } + r[y] = lineRSum; + g[y] = lineGSum; + b[y] = lineBSum; + + p += offset; + } + + // create histograms + red = new Histogram( r ); + green = new Histogram( g ); + blue = new Histogram( b ); + } + else if ( + ( pixelFormat == PixelFormat.Format48bppRgb ) || + ( pixelFormat == PixelFormat.Format64bppArgb ) ) + { + // 48/64 bpp color image + byte* basePtr = (byte*) image.ImageData.ToPointer( ); + int stride = image.Stride; + int pixelSize = ( pixelFormat == PixelFormat.Format48bppRgb ) ? 3 : 4; + + // histogram arrays + int[] r = new int[height]; + int[] g = new int[height]; + int[] b = new int[height]; + + // for each line + for ( int y = 0; y < height; y++ ) + { + ushort* p = (ushort*) ( basePtr + stride * y ); + + int lineRSum = 0; + int lineGSum = 0; + int lineBSum = 0; + + // for each pixel + for ( int x = 0; x < width; x++, p += pixelSize ) + { + lineRSum += p[RGB.R]; + lineGSum += p[RGB.G]; + lineBSum += p[RGB.B]; + } + r[y] = lineRSum; + g[y] = lineGSum; + b[y] = lineBSum; + } + + // create histograms + red = new Histogram( r ); + green = new Histogram( g ); + blue = new Histogram( b ); + } + } + } + } +} diff --git a/Sources/Accord.Imaging/Accord.Imaging.cd b/Sources/Accord.Imaging/Accord.Imaging.cd index 576ba7375..f8e55b478 100644 --- a/Sources/Accord.Imaging/Accord.Imaging.cd +++ b/Sources/Accord.Imaging/Accord.Imaging.cd @@ -1,648 +1,648 @@ - - - - - - - - - - - - AAAAAgAAAAAAAAAAgAAAgAAAAAAIAAQAAAAEAAAAAAA= - CorrelationMatching.cs - - - - - - - - - - - - gAAAAAAAAAAAIAAAAIEAAAAAABQAACAQgAAhAIAAIAI= - Interest Points\HarrisCornersDetector.cs - - - - - - - - - - - - - - - - AAAAAAAAACAACAggAAAAEAAAAFAAEAEABAAAAAAAAAA= - RansacHomographyEstimator.cs - - - - - - - - - - - - AAAAAAAIgJAAAAACEQABBAEABAAEAAAEAAAAgACIAAU= - Tools.cs - - - - - - - - - - - - - AJIgAABADCEAABQAQAAAAEQAAAAABBQBBAAGBgAgAIA= - IntegralImage2.cs - - - - - - - - - - - - - AAAARAAAAIAABFAAoAIRAAAAAAIAAIDAQAAAAAigAAA= - MatrixH.cs - - - - - - - - - - - AAQAAIAkQAAAAAgAAAAIAAAAAAAAACAAAAAhAAAAAAA= - Interest Points\FastCornersDetector.cs - - - - - - - - - - - - AAAAAEAABAAAAQBEAAEAAAABAAAEBGABIAAhAABAAAA= - Interest Points\SURF\SpeededUpRobustFeaturesDetector.cs - - - - - - - - - - AAAAAAAAAWBAAAAAAAIAAAAAAADAAAAAAAAACAEAYAA= - Interest Points\SURF\SpeededUpRobustFeaturePoint.cs - - - - - - - - - AEDgAQAAAAABAACBAAAAAAAAAAAQAAAAAAgAAAAAAAA= - Moments\CentralMoments.cs - - - - - - - - - AEBAAAAAAAEABAAAGAAAACAAAAAAABIAAAgAAQAAAAA= - Moments\RawMoments.cs - - - - - - - - - QAIAAACAAAAAAACAAAAAAAAAAAAAAAAAAAAgAAAAAAA= - Contour\BorderFollowing.cs - - - - - - - - - AEAAAGAACAAAAA4AAAAAAAAAAQAQJhCBAAAggAAAAhA= - Interest Points\SURF\SpeededUpRobustFeaturesDescriptor.cs - - - - - - - AAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAA= - BagOfVisualWords.cs - - - - - - - - AAAAAAAAACAAAAggAAAAEAAAAFAAAAEABAAAAAAAAAA= - RansacFundamentalEstimator.cs - - - - - - AAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAA= - Interest Points\CornerFeaturePoint.cs - - - - - - - - - AAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAABAAEAAAA= - Interest Points\CornerFeaturesDetector.cs - - - - - - - - - - - - BAAAAAAAAAgQIAAAUSAAQBEAAEAAAAAAIQABACUAAAA= - Interest Points\HistogramsOfOrientedGradients.cs - - - - - - - - - AEAABAAAAAAAAAAAAAAABAIAAAAAAAEQAAAAgAAIAAA= - Moments\HuMoments.cs - - - - - - - AEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= - Moments\MomentsBase.cs - - - - - - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= - BagOfVisualWords`1.cs - - - - - - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= - KNearestNeighborMatching.cs - - - - - - AEAAQIAAAAAAAAAQAAAAgAAAAAAAAAAAAAAAAAEAAAA= - BagOfVisualWords`2.cs - - - - - - - - - AEAAEAAAAAAQAAAAUCABAAAQAUAAEABAAAAAAAAAAAA= - GrayLevelCooccurrenceMatrix.cs - - - - - - - - AEAAEAAAAAAABAAAAAABIAAQAQAAEAAAAAAAAAAAAAA= - GrayLevelRunLength.cs - - - - - - - - AEAAEAAAAAAAAAAAAAABAAAQAQAAEAAAAAAAAAAAAAA= - GrayLevelDifferenceMethod.cs - - - - - - IAAAAAAAAWAAAAAAAEIAAIAAAADAAAAAAAAACAAAYAA= - Interest Points\FREAK\FastRetinaKeypoint.cs - - - - - - - - - AEAAAAAAAAAAAAgAAAAAAQAAAAUAEBAAAAAAAgAAAAA= - Interest Points\FREAK\FastRetinaKeypointDescriptor.cs - - - - - - - - AAAAAAAAAAAAAQBAAAMAAAADAAAAFkIBAAABAAEAAAA= - Interest Points\FREAK\FastRetinaKeypointDetector.cs - - - - - - - - - AAAAAAAAAIAQAgGAUAABwCAAAUIgAAICAAABAAAAAAA= - Interest Points\Haralick\Haralick.cs - - - - - - - - - - - - - - - - - SAQAREAtARB0owCgAJIAqDIpASQiEIEOCCgLBohxABQ= - Interest Points\Haralick\HaralickDescriptor.cs - - - - - - ACAAAAAAAAAAAAAAEAAEAAAAAAAAAAAAAAABAAAAAAA= - Interest Points\Haralick\HaralickDescriptor.cs - - - - - - - - BAIAAAACAAAQAAAAUQAAQBAAAEAAAAAAIAABACQAAAA= - Interest Points\LocalBinaryPattern.cs - - - - - - - - - AEQAEEAAAAAAABQAQAEAAAAAAAAgAAAEAAAAAAAEAAA= - Interest Points\SURF\ResponseLayer.cs - - - - - - - AEQAAAAABABAgAAAAAAAAEAAAAAAAAAAIAAAAAEAAAA= - Interest Points\SURF\ResponseLayer.cs - - - - - - - - - - - - QAJAAAAAAAAAAACA8AMDAAcAAABAgIAAgAAAAEJIYiA= - PointH.cs - - - - - - - - AAAAAQAAAEAAAABAgAAAAAAAAgAAAIAEAACAAAAAAiA= - Interest Points\FeatureDescriptor.cs - - - - - - - - - AAAAAAAAAEAAAABAgAAAAAAAAAAAAIAABAAAAAAAAiA= - Interest Points\FeatureDescriptor.cs - - - - - - - AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= - Contour\IContourExtractionAlgorithm.cs - - - - - - AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= - Moments\IMoments.cs - - - - - - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= - Interest Points\Base\IFeatureDetector.cs - - - - - - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= - Interest Points\Base\IFeaturePoint.cs - - - - - - AAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= - Interest Points\Base\IFeatureDescriptor.cs - - - - - - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAA= - Interest Points\Base\IFeatureDetector.cs - - - - - - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAA= - Interest Points\Base\IFeaturePoint.cs - - - - - - AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAABAA= - Interest Points\HarrisCornersDetector.cs - - - - - - AAAAAAAAAAAAAAgAAAAAAAAAAIAAAAAAAAAAAAEAAAA= - Interest Points\SURF\SpeededUpRobustFeaturesDetector.cs - - - - - - AACIAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAABA= - GrayLevelCooccurrenceMatrix.cs - - - - - - AAAAAAAAAAAAAAgAAAAAAAAAAIAAAAAAAAAAAAEAAAA= - Interest Points\FREAK\FastRetinaKeypointDetector.cs - - - - - - ACAAAAAAAAAAAAAAAAAEAAAAAAAAEAAAAAABAAAAAAA= - Interest Points\Haralick\Haralick.cs - - - + + + + + + + + + + + + AAAAAgAAAAAAAAAAgAAAgAAAEAAIAAQAAAAEAAAAAAA= + Interest Points\Matching\CorrelationMatching.cs + + + + + + + + + + + + gAAAAAAAAAAAIAAAAIEAAAAAABQAACAQgAAhAIAAIAI= + Interest Points\HarrisCornersDetector.cs + + + + + + + + + + + + + + + + AAAAAAAAACAACAggAAAAEAAAAFAAEAEABAAAAAAAAAA= + RansacHomographyEstimator.cs + + + + + + + + + + + + AAAAAAAIgJAAAAACEQABBAEABgAEAAAEAAAAgACIAAU= + Tools.cs + + + + + + + + + + + + + AJIgAABADCEAABQAQAAAAEQAAAAABBQBBAAGBgAgAIA= + IntegralImage2.cs + + + + + + + + + + + + + AAAARAAAAIAABFAAoAIRAAAAAAIAAIDAQAAAAAigAAA= + MatrixH.cs + + + + + + + + + + + AAQAAIAkQAAAAAgAAAAIAAAAAAAAACAAAAAhAAAAAAA= + Interest Points\FastCornersDetector.cs + + + + + + + + + + + + AAAAAEAABAAAAQBEAAEAAAABAAAEBGABIAAhAABAAQA= + Interest Points\SURF\SpeededUpRobustFeaturesDetector.cs + + + + + + + + + + AAAAAAAAAWBAAAAAAAIAAAAAAADAAAAAAAAACAEAYAA= + Interest Points\SURF\SpeededUpRobustFeaturePoint.cs + + + + + + + + + AEDgAQAAAAABAACBAAAAAAAAAAAQAAAAAAgAAAAAAAA= + Moments\CentralMoments.cs + + + + + + + + + AEBAAAAAAAEABAAAGAAAACAAAAAAABIAAAgAAQAAAAA= + Moments\RawMoments.cs + + + + + + + + + QAIAAACAAAAAAACAAAAAAAAAAAAAAAAAAAAgAAAAAAA= + Contour\BorderFollowing.cs + + + + + + + + + AEAAAGAACAAAAA4AAAAAAAAAAQAQJhCBAAAggAAAAhA= + Interest Points\SURF\SpeededUpRobustFeaturesDescriptor.cs + + + + + + + AAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAA= + BagOfVisualWords.cs + + + + + + + + AAAAAAAAACAAAAggAAAAEAAAAFAAAAEABAAAAAAAAAA= + RansacFundamentalEstimator.cs + + + + + + AAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAA= + Interest Points\CornerFeaturePoint.cs + + + + + + + + + AAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAABAAEAAAA= + Interest Points\CornerFeaturesDetector.cs + + + + + + + + + + + + BAAAAAAAAAgQIAAAUSAAQBEAAEAAAAAAIQABACUAAAA= + Interest Points\HistogramsOfOrientedGradients.cs + + + + + + + + + AEAABAAAAAAAAAAAAAAABAIAAAAAAAEQAAAAgAAIAAA= + Moments\HuMoments.cs + + + + + + + AEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + Moments\MomentsBase.cs + + + + + + AAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAA= + BagOfVisualWords`1.cs + + + + + + AAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAA= + Interest Points\Matching\KNearestNeighborMatching.cs + + + + + + AEAAQIAAAAAAAAAQAAAAgAAAAAAAAAAAAAAAAAEAAAA= + BagOfVisualWords`2.cs + + + + + + + + + AEAAEAAAAAAQAAAAUCABAAAQAUAAEABAAAAAAAAAAAA= + GrayLevelCooccurrenceMatrix.cs + + + + + + + + AEAAEAAAAAAABAAAAAABIAAQAQAAEAAAAAAAAAAAAAA= + GrayLevelRunLength.cs + + + + + + + + AEAAEAAAAAAAAAAAAAABAAAQAQAAEAAAAAAAAAAAAAA= + GrayLevelDifferenceMethod.cs + + + + + + IAAAAAAAAWAAAAAAAEIAAIAAAADAAAAAAAAACAAAYAA= + Interest Points\FREAK\FastRetinaKeypoint.cs + + + + + + + + + AEAAAAAAAAAAAAgAAAAAAQAAAAUAEBAAAAAAAgAAAAA= + Interest Points\FREAK\FastRetinaKeypointDescriptor.cs + + + + + + + + AAAAAAAAAAAAAQBAAAMAAAADAAAAFkIBAAABAAEAAAA= + Interest Points\FREAK\FastRetinaKeypointDetector.cs + + + + + + + + + AAAAAAAAAIAQAgGAUAABwCAAAUIgAAICAAABAAAAAAA= + Interest Points\Haralick\Haralick.cs + + + + + + + + + + + + + + + + + SAQAREAtARB0owCgAJIAqDIpASQiEIEOCCgLBohxABQ= + Interest Points\Haralick\HaralickDescriptor.cs + + + + + + ACAAAAAAAAAAAAAAEAAEAAAAAAAAAAAAAAABAAAAAAA= + Interest Points\Haralick\HaralickDescriptor.cs + + + + + + + + BAIAAAACAAAQAAAAUQAAQBAAAEAAAAAAIAABACQAAAA= + Interest Points\LocalBinaryPattern.cs + + + + + + + + + AEQAEEAAAAAAABQAQAEAAAAAAAAgAAAEAAAAAAAEAAA= + Interest Points\SURF\ResponseLayer.cs + + + + + + + AEQAAAAABABAgAAAAAAAAEAAAAAAAAAAIAAAAAEAAAA= + Interest Points\SURF\ResponseLayer.cs + + + + + + + + + + + + QAJAAAAAAAAAAACA8AMDAAcAAABAgIAAgAAAAEJIYiA= + PointH.cs + + + + + + + + AAAAAQAAAEAAAABAgAAAAAAAAgAAAIAEAACAAAAAAiA= + Interest Points\FeatureDescriptor.cs + + + + + + + + + AAAAAAAAAEAAAABAgAAAAAAAAAAAAIAABAAAAAAAAiA= + Interest Points\FeatureDescriptor.cs + + + + + + + AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + Contour\IContourExtractionAlgorithm.cs + + + + + + AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + Moments\IMoments.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + Interest Points\Base\IFeatureDetector.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + Interest Points\Base\IFeaturePoint.cs + + + + + + AAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + Interest Points\Base\IFeatureDescriptor.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAA= + Interest Points\Base\IFeatureDetector.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAA= + Interest Points\Base\IFeaturePoint.cs + + + + + + AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAABAA= + Interest Points\HarrisCornersDetector.cs + + + + + + AAAAAAAAAAAAAAgAAAAAAAAAAIAAAAAAAAAAAAEAAAA= + Interest Points\SURF\SpeededUpRobustFeaturesDetector.cs + + + + + + AACIAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAABA= + GrayLevelCooccurrenceMatrix.cs + + + + + + AAAAAAAAAAAAAAgAAAAAAAAAAIAAAAAAAAAAAAEAAAA= + Interest Points\FREAK\FastRetinaKeypointDetector.cs + + + + + + ACAAAAAAAAAAAAAAAAAEAAAAAAAAEAAAAAABAAAAAAA= + Interest Points\Haralick\Haralick.cs + + + \ No newline at end of file diff --git a/Sources/Accord.Imaging/Accord.Imaging.csproj b/Sources/Accord.Imaging/Accord.Imaging.csproj index 1049260f0..97788d628 100644 --- a/Sources/Accord.Imaging/Accord.Imaging.csproj +++ b/Sources/Accord.Imaging/Accord.Imaging.csproj @@ -1,227 +1,416 @@ - - - - {4959A83D-F78F-439E-80A5-41583ECEAAC6} - Accord.Imaging - Accord.Imaging - Debug - AnyCPU - AnyCPU - Library - Properties - True - 4 - True - true - Accord.snk - 3.5 - False - true - ..\Accord.NET.ruleset - false - true - 4096 - true - pdbonly - true - true - true - GlobalSuppressions.cs - - - v4.5 - bin\Debug\ - Full - False - False - True - DEBUG;TRACE - ..\..\Debug\ - - - ..\..\Release\net35 - TRACE;CODE_ANALYSIS;NET35 - v3.5 - ..\..\Release\net35\Accord.Imaging.XML - ..\..\Release\net35\Accord.Imaging.dll.CodeAnalysisLog.xml - - - ..\..\Release\net40 - TRACE;CODE_ANALYSIS;NET40 - v4.0 - ..\..\Release\net40\Accord.Imaging.XML - ..\..\Release\net40\Accord.Imaging.dll.CodeAnalysisLog.xml - - - ..\..\Release\net45 - TRACE;CODE_ANALYSIS;NET45 - v4.5 - ..\..\Release\net45\Accord.Imaging.XML - ..\..\Release\net45\Accord.Imaging.dll.CodeAnalysisLog.xml - - - - ..\..\Externals\AForge.NET\AForge.dll - False - - - ..\..\Externals\AForge.NET\AForge.Imaging.dll - False - - - ..\..\Externals\AForge.NET\AForge.Math.dll - False - - - - 3.5 - - - - - - - - Properties\VersionInfo.cs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Code - - - - - - {A177A90C-8207-466A-AF70-F2B8452A42AC} - Accord.Core - False - - - {7AB4BBCC-6222-423D-9FF9-BA9CB7C09199} - Accord.MachineLearning - False - - - {F718E9A8-DB62-4785-8C49-4333A60D256A} - Accord.Math - False - - - {FD8101DD-C95D-42D6-AD44-AE01C25F2811} - Accord.Statistics - False - - - - - - - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - - - - \ No newline at end of file + + + + {4959A83D-F78F-439E-80A5-41583ECEAAC6} + Accord.Imaging + Accord.Imaging + Debug + AnyCPU + AnyCPU + Library + Properties + True + 4 + True + true + Accord.snk + 3.5 + False + true + ..\Accord.NET.ruleset + false + true + 4096 + true + pdbonly + true + true + true + GlobalSuppressions.cs + + + v4.5 + bin\Debug\ + Full + False + False + True + DEBUG;TRACE + $(SolutionDir)..\Debug\ + + + $(SolutionDir)..\Release\net35 + TRACE;CODE_ANALYSIS;NET35 + v3.5 + $(SolutionDir)..\Release\net35\Accord.Imaging.XML + $(SolutionDir)..\Release\net35\Accord.Imaging.dll.CodeAnalysisLog.xml + + + $(SolutionDir)..\Release\net40 + TRACE;CODE_ANALYSIS;NET40 + v4.0 + $(SolutionDir)..\Release\net40\Accord.Imaging.XML + $(SolutionDir)..\Release\net40\Accord.Imaging.dll.CodeAnalysisLog.xml + + + $(SolutionDir)..\Release\net45 + TRACE;CODE_ANALYSIS;NET45 + v4.5 + $(SolutionDir)..\Release\net45\Accord.Imaging.XML + $(SolutionDir)..\Release\net45\Accord.Imaging.dll.CodeAnalysisLog.xml + + + + + 3.5 + + + + + + + + + Properties\VersionInfo.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Code + + + + + + {A177A90C-8207-466A-AF70-F2B8452A42AC} + Accord.Core + False + + + {7AB4BBCC-6222-423D-9FF9-BA9CB7C09199} + Accord.MachineLearning + False + + + {F718E9A8-DB62-4785-8C49-4333A60D256A} + Accord.Math + False + + + {FD8101DD-C95D-42D6-AD44-AE01C25F2811} + Accord.Statistics + False + + + + + + + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + diff --git a/Sources/Accord.Imaging/Contour/BorderFollowing.cs b/Sources/Accord.Imaging/Contour/BorderFollowing.cs index 422dbb02e..d16865f0c 100644 --- a/Sources/Accord.Imaging/Contour/BorderFollowing.cs +++ b/Sources/Accord.Imaging/Contour/BorderFollowing.cs @@ -137,7 +137,7 @@ public List FindContour(BitmapData image) /// A grayscale image. /// A list of s defining a contour. /// - public unsafe List FindContour(UnmanagedImage image) + public List FindContour(UnmanagedImage image) { CheckPixelFormat(image.PixelFormat); @@ -145,124 +145,127 @@ public unsafe List FindContour(UnmanagedImage image) int height = image.Height; int stride = image.Stride; - byte* src = (byte*)image.ImageData.ToPointer(); + List contour = new List(); + unsafe + { + byte* src = (byte*)image.ImageData.ToPointer(); - byte* start = null; - List contour = new List(); + byte* start = null; - IntPoint prevPosition = new IntPoint(); + IntPoint prevPosition = new IntPoint(); - // 1. Find the lowest point in the image + // 1. Find the lowest point in the image - // The lowest point is searched first by lowest X, then lowest Y, to use - // the same ordering of AForge.NET's GrahamConvexHull. Unfortunately, this - // means we have to search our image by inspecting columns rather than rows. + // The lowest point is searched first by lowest X, then lowest Y, to use + // the same ordering of AForge.NET's GrahamConvexHull. Unfortunately, this + // means we have to search our image by inspecting columns rather than rows. - bool found = false; + bool found = false; - byte* col = src; - for (int x = 0; x < width && !found; x++, col++) - { - byte* row = col; - for (int y = 0; y < height && !found; y++, row += stride) + byte* col = src; + for (int x = 0; x < width && !found; x++, col++) { - if (*row > Threshold) + byte* row = col; + for (int y = 0; y < height && !found; y++, row += stride) { - start = row; - prevPosition = new IntPoint(x, y); - contour.Add(prevPosition); - found = true; + if (*row > Threshold) + { + start = row; + prevPosition = new IntPoint(x, y); + contour.Add(prevPosition); + found = true; + } } } - } - if (contour.Count == 0) - { - // Empty image - return contour; - } + if (contour.Count == 0) + { + // Empty image + return contour; + } - // 2. Beginning on the first point, starting from left - // neighbor and going into counter-clockwise direction, - // find a neighbor pixel which is black. - - int[] windowOffset = - { - +1, // 0: Right - -stride + 1, // 1: Top-Right - -stride, // 2: Top - -stride - 1, // 3: Top-Left - -1, // 4: Left - +stride - 1, // 5: Bottom-Left - +stride, // 6: Bottom - +stride + 1, // 7: Bottom-Right - }; + // 2. Beginning on the first point, starting from left + // neighbor and going into counter-clockwise direction, + // find a neighbor pixel which is black. - int direction = 4; // 4: Left - byte* current = start; - byte* previous = null; + int[] windowOffset = + { + +1, // 0: Right + -stride + 1, // 1: Top-Right + -stride, // 2: Top + -stride - 1, // 3: Top-Left + -1, // 4: Left + +stride - 1, // 5: Bottom-Left + +stride, // 6: Bottom + +stride + 1, // 7: Bottom-Right + }; + int direction = 4; // 4: Left + byte* current = start; + byte* previous = null; - do // Search until we find a dead end (or the starting pixel) - { - found = false; - // Search in the neighborhood window - for (int i = 0; i < windowOffset.Length; i++) + do // Search until we find a dead end (or the starting pixel) { - // Find the next candidate neighbor point - IntPoint next = prevPosition + positionOffset[direction]; + found = false; - // Check if it is inside the blob area - if (next.X < 0 || next.X >= width || - next.Y < 0 || next.Y >= height) + // Search in the neighborhood window + for (int i = 0; i < windowOffset.Length; i++) { - // It isn't. Change direction and continue. - direction = (direction + 1) % windowOffset.Length; - continue; + // Find the next candidate neighbor point + IntPoint next = prevPosition + positionOffset[direction]; + + // Check if it is inside the blob area + if (next.X < 0 || next.X >= width || + next.Y < 0 || next.Y >= height) + { + // It isn't. Change direction and continue. + direction = (direction + 1) % windowOffset.Length; + continue; + } + + // Find the next candidate neighbor pixel + byte* neighbor = unchecked(current + windowOffset[direction]); + + // Check if it is a colored pixel + if (*neighbor <= Threshold) + { + // It isn't. Change direction and continue. + direction = (direction + 1) % windowOffset.Length; + continue; + } + + // Check if it is a previously found pixel + if (neighbor == previous || neighbor == start) + { + // We found a dead end. + found = false; break; + } + + // If we reached until here, we have + // found a neighboring black pixel. + found = true; break; } - // Find the next candidate neighbor pixel - byte* neighbor = unchecked(current + windowOffset[direction]); - - // Check if it is a colored pixel - if (*neighbor <= Threshold) + if (found) { - // It isn't. Change direction and continue. - direction = (direction + 1) % windowOffset.Length; - continue; - } - - // Check if it is a previously found pixel - if (neighbor == previous || neighbor == start) - { - // We found a dead end. - found = false; break; - } - - // If we reached until here, we have - // found a neighboring black pixel. - found = true; break; - } + // Navigate to neighbor pixel + previous = current; + current = unchecked(current + windowOffset[direction]); - if (found) - { - // Navigate to neighbor pixel - previous = current; - current = unchecked(current + windowOffset[direction]); - - // Add to the contour - prevPosition += positionOffset[direction]; - contour.Add(prevPosition); + // Add to the contour + prevPosition += positionOffset[direction]; + contour.Add(prevPosition); - // Continue counter-clockwise search - // from the most promising direction - direction = nextDirection[direction]; - } + // Continue counter-clockwise search + // from the most promising direction + direction = nextDirection[direction]; + } - } while (found); + } while (found); + } return contour; diff --git a/Sources/Accord.Imaging/Converters/ImageToArray.cs b/Sources/Accord.Imaging/Converters/ImageToArray.cs index 608e4e43a..d78422cd2 100644 --- a/Sources/Accord.Imaging/Converters/ImageToArray.cs +++ b/Sources/Accord.Imaging/Converters/ImageToArray.cs @@ -305,7 +305,7 @@ public void Convert(UnmanagedImage input, out float[][] output) /// The input image to be converted. /// The converted image. /// - public unsafe void Convert(UnmanagedImage input, out double[] output) + public void Convert(UnmanagedImage input, out double[] output) { int width = input.Width; int height = input.Height; @@ -314,32 +314,35 @@ public unsafe void Convert(UnmanagedImage input, out double[] output) output = new double[width * height]; - if (input.PixelFormat == PixelFormat.Format16bppGrayScale) + unsafe { - short* src = (short*)input.ImageData.ToPointer(); - int dst = 0; - - for (int y = 0; y < height; y++) + if (input.PixelFormat == PixelFormat.Format16bppGrayScale) { - for (int x = 0; x < width; x++, dst++, src++) - output[dst] = Accord.Math.Tools.Scale(0, 65535, Min, Max, *src); + short* src = (short*)input.ImageData.ToPointer(); + int dst = 0; - src += offset; - } - } - else - { - byte* src = (byte*)input.ImageData.ToPointer() + Channel; - int dst = 0; + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++, dst++, src++) + output[dst] = Accord.Math.Tools.Scale(0, 65535, Min, Max, *src); - for (int y = 0; y < height; y++) + src += offset; + } + } + else { - for (int x = 0; x < width; x++, dst++, src += pixelSize) - output[dst] = Accord.Math.Tools.Scale(0, 255, Min, Max, *src); + byte* src = (byte*)input.ImageData.ToPointer() + Channel; + int dst = 0; - src += offset; - } - } + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++, dst++, src += pixelSize) + output[dst] = Accord.Math.Tools.Scale(0, 255, Min, Max, *src); + + src += offset; + } + } + } } /// @@ -349,7 +352,7 @@ public unsafe void Convert(UnmanagedImage input, out double[] output) /// The input image to be converted. /// The converted image. /// - public unsafe void Convert(UnmanagedImage input, out float[] output) + public void Convert(UnmanagedImage input, out float[] output) { int width = input.Width; int height = input.Height; @@ -361,32 +364,35 @@ public unsafe void Convert(UnmanagedImage input, out float[] output) float min = (float)Min; float max = (float)Max; - if (input.PixelFormat == PixelFormat.Format16bppGrayScale) + unsafe { - short* src = (short*)input.ImageData.ToPointer(); - int dst = 0; - - for (int y = 0; y < height; y++) + if (input.PixelFormat == PixelFormat.Format16bppGrayScale) { - for (int x = 0; x < width; x++, dst++, src++) - output[dst] = Accord.Math.Tools.Scale(0, 65535, min, max, *src); + short* src = (short*)input.ImageData.ToPointer(); + int dst = 0; - src += offset; - } - } - else - { - byte* src = (byte*)input.ImageData.ToPointer() + Channel; - int dst = 0; + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++, dst++, src++) + output[dst] = Accord.Math.Tools.Scale(0, 65535, min, max, *src); - for (int y = 0; y < height; y++) + src += offset; + } + } + else { - for (int x = 0; x < width; x++, dst++, src += pixelSize) - output[dst] = Accord.Math.Tools.Scale(0, 255, min, max, *src); + byte* src = (byte*)input.ImageData.ToPointer() + Channel; + int dst = 0; - src += offset; - } - } + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++, dst++, src += pixelSize) + output[dst] = Accord.Math.Tools.Scale(0, 255, min, max, *src); + + src += offset; + } + } + } } /// @@ -396,7 +402,7 @@ public unsafe void Convert(UnmanagedImage input, out float[] output) /// The input image to be converted. /// The converted image. /// - public unsafe void Convert(UnmanagedImage input, out Color[] output) + public void Convert(UnmanagedImage input, out Color[] output) { int width = input.Width; int height = input.Height; @@ -407,44 +413,47 @@ public unsafe void Convert(UnmanagedImage input, out Color[] output) output = new Color[input.Width * input.Height]; int dst = 0; - if (input.PixelFormat == PixelFormat.Format8bppIndexed) + unsafe { - byte* src = (byte*)input.ImageData.ToPointer(); - - for (int y = 0; y < height; y++) + if (input.PixelFormat == PixelFormat.Format8bppIndexed) { - for (int x = 0; x < width; x++, src += pixelSize, dst++) - output[dst] = Color.FromArgb(*src, *src, *src); - src += offset; - } - } - else if (input.PixelFormat == PixelFormat.Format24bppRgb - || input.PixelFormat == PixelFormat.Format32bppRgb) - { - byte* src = (byte*)input.ImageData.ToPointer(); + byte* src = (byte*)input.ImageData.ToPointer(); - for (int y = 0; y < height; y++) - { - for (int x = 0; x < width; x++, src += pixelSize, dst++) - output[dst] = Color.FromArgb(src[RGB.R], src[RGB.G], src[RGB.B]); - src += offset; + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++, src += pixelSize, dst++) + output[dst] = Color.FromArgb(*src, *src, *src); + src += offset; + } } - } - else if (input.PixelFormat == PixelFormat.Format32bppArgb) - { - byte* src = (byte*)input.ImageData.ToPointer(); + else if (input.PixelFormat == PixelFormat.Format24bppRgb + || input.PixelFormat == PixelFormat.Format32bppRgb) + { + byte* src = (byte*)input.ImageData.ToPointer(); - for (int y = 0; y < height; y++) + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++, src += pixelSize, dst++) + output[dst] = Color.FromArgb(src[RGB.R], src[RGB.G], src[RGB.B]); + src += offset; + } + } + else if (input.PixelFormat == PixelFormat.Format32bppArgb) { - for (int x = 0; x < width; x++, src += pixelSize, dst++) - output[dst] = Color.FromArgb(src[RGB.A], src[RGB.R], src[RGB.G], src[RGB.B]); - src += offset; + byte* src = (byte*)input.ImageData.ToPointer(); + + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++, src += pixelSize, dst++) + output[dst] = Color.FromArgb(src[RGB.A], src[RGB.R], src[RGB.G], src[RGB.B]); + src += offset; + } } - } - else - { - throw new UnsupportedImageFormatException("Pixel format is not supported."); - } + else + { + throw new UnsupportedImageFormatException("Pixel format is not supported."); + } + } } } diff --git a/Sources/Accord.Imaging/Converters/ImageToMatrix.cs b/Sources/Accord.Imaging/Converters/ImageToMatrix.cs index be9f4689b..9c7e75f1e 100644 --- a/Sources/Accord.Imaging/Converters/ImageToMatrix.cs +++ b/Sources/Accord.Imaging/Converters/ImageToMatrix.cs @@ -239,7 +239,7 @@ public void Convert(Bitmap input, out Color[,] output) /// The input image to be converted. /// The converted image. /// - public unsafe void Convert(UnmanagedImage input, out double[,] output) + public void Convert(UnmanagedImage input, out double[,] output) { int width = input.Width; int height = input.Height; @@ -248,18 +248,21 @@ public unsafe void Convert(UnmanagedImage input, out double[,] output) output = new double[height, width]; - fixed (double* ptrData = output) + unsafe { - double* dst = ptrData; - byte* src = (byte*)input.ImageData.ToPointer() + Channel; - - for (int y = 0; y < height; y++) + fixed (double* ptrData = output) { - for (int x = 0; x < width; x++, src += pixelSize, dst++) - *dst = Accord.Math.Tools.Scale(0, 255, Min, Max, *src); - src += offset; - } - } + double* dst = ptrData; + byte* src = (byte*)input.ImageData.ToPointer() + Channel; + + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++, src += pixelSize, dst++) + *dst = Accord.Math.Tools.Scale(0, 255, Min, Max, *src); + src += offset; + } + } + } } /// @@ -307,7 +310,7 @@ public void Convert(UnmanagedImage input, out float[,] output) /// The input image to be converted. /// The converted image. /// - public unsafe void Convert(UnmanagedImage input, out byte[,] output) + public void Convert(UnmanagedImage input, out byte[,] output) { int width = input.Width; int height = input.Height; @@ -316,18 +319,21 @@ public unsafe void Convert(UnmanagedImage input, out byte[,] output) output = new byte[height, width]; - fixed (byte* ptrData = output) + unsafe { - byte* dst = ptrData; - byte* src = (byte*)input.ImageData.ToPointer() + Channel; - - for (int y = 0; y < height; y++) + fixed (byte* ptrData = output) { - for (int x = 0; x < width; x++, src += pixelSize, dst++) - *dst = *src; - src += offset; - } - } + byte* dst = ptrData; + byte* src = (byte*)input.ImageData.ToPointer() + Channel; + + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++, src += pixelSize, dst++) + *dst = *src; + src += offset; + } + } + } } /// @@ -339,7 +345,7 @@ public unsafe void Convert(UnmanagedImage input, out byte[,] output) /// The input image to be converted. /// The converted image. /// - public unsafe void Convert(UnmanagedImage input, out Color[,] output) + public void Convert(UnmanagedImage input, out Color[,] output) { int width = input.Width; int height = input.Height; @@ -349,44 +355,47 @@ public unsafe void Convert(UnmanagedImage input, out Color[,] output) output = new Color[input.Height, input.Width]; - if (input.PixelFormat == PixelFormat.Format8bppIndexed) + unsafe { - byte* src = (byte*)input.ImageData.ToPointer(); - - for (int y = 0; y < height; y++) + if (input.PixelFormat == PixelFormat.Format8bppIndexed) { - for (int x = 0; x < width; x++, src += pixelSize) - output[y, x] = Color.FromArgb(*src, *src, *src); - src += offset; - } - } - else if (input.PixelFormat == PixelFormat.Format24bppRgb - || input.PixelFormat == PixelFormat.Format32bppRgb) - { - byte* src = (byte*)input.ImageData.ToPointer(); + byte* src = (byte*)input.ImageData.ToPointer(); - for (int y = 0; y < height; y++) - { - for (int x = 0; x < width; x++, src += pixelSize) - output[y, x] = Color.FromArgb(src[RGB.R], src[RGB.G], src[RGB.B]); - src += offset; + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++, src += pixelSize) + output[y, x] = Color.FromArgb(*src, *src, *src); + src += offset; + } } - } - else if (input.PixelFormat == PixelFormat.Format32bppArgb) - { - byte* src = (byte*)input.ImageData.ToPointer(); + else if (input.PixelFormat == PixelFormat.Format24bppRgb + || input.PixelFormat == PixelFormat.Format32bppRgb) + { + byte* src = (byte*)input.ImageData.ToPointer(); - for (int y = 0; y < height; y++) + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++, src += pixelSize) + output[y, x] = Color.FromArgb(src[RGB.R], src[RGB.G], src[RGB.B]); + src += offset; + } + } + else if (input.PixelFormat == PixelFormat.Format32bppArgb) { - for (int x = 0; x < width; x++, src += pixelSize) - output[y, x] = Color.FromArgb(src[RGB.A], src[RGB.R], src[RGB.G], src[RGB.B]); - src += offset; + byte* src = (byte*)input.ImageData.ToPointer(); + + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++, src += pixelSize) + output[y, x] = Color.FromArgb(src[RGB.A], src[RGB.R], src[RGB.G], src[RGB.B]); + src += offset; + } } - } - else - { - throw new UnsupportedImageFormatException("Pixel format is not supported."); - } + else + { + throw new UnsupportedImageFormatException("Pixel format is not supported."); + } + } } } diff --git a/Sources/Accord.Imaging/GlobalSuppressions.cs b/Sources/Accord.Imaging/GlobalSuppressions.cs index 9d77deabc..fe0218a28 100644 --- a/Sources/Accord.Imaging/GlobalSuppressions.cs +++ b/Sources/Accord.Imaging/GlobalSuppressions.cs @@ -42,3 +42,12 @@ [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2151:FieldsWithCriticalTypesShouldBeCriticalFxCopRule", Scope = "member", Target = "Accord.Imaging.IntegralImage2.#nSum")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2151:FieldsWithCriticalTypesShouldBeCriticalFxCopRule", Scope = "member", Target = "Accord.Imaging.IntegralImage2.#sSum")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2151:FieldsWithCriticalTypesShouldBeCriticalFxCopRule", Scope = "member", Target = "Accord.Imaging.IntegralImage2.#tSum")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Scope = "member", Target = "AForge.Imaging.Filters.Grayscale+CommonAlgorithms.#Y")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Scope = "member", Target = "AForge.Imaging.Filters.Grayscale+CommonAlgorithms.#RMY")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Scope = "member", Target = "AForge.Imaging.Filters.Grayscale+CommonAlgorithms.#BT709")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Cr", Scope = "member", Target = "AForge.Imaging.ImageStatisticsYCbCr.#CrWithoutBlack")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Cr", Scope = "member", Target = "AForge.Imaging.Filters.YCbCrLinear.#InCr")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Cb", Scope = "member", Target = "AForge.Imaging.Filters.YCbCrLinear.#OutCb")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Cr", Scope = "member", Target = "AForge.Imaging.Filters.YCbCrLinear.#OutCr")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Cr", Scope = "member", Target = "AForge.Imaging.Filters.YCbCrFiltering.#Cr")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Cb", Scope = "member", Target = "AForge.Imaging.Filters.YCbCrFiltering.#Cb")] diff --git a/Sources/Accord.Imaging/GrayLevelCooccurrenceMatrix.cs b/Sources/Accord.Imaging/GrayLevelCooccurrenceMatrix.cs index 8bbc56ca4..3e4525aa5 100644 --- a/Sources/Accord.Imaging/GrayLevelCooccurrenceMatrix.cs +++ b/Sources/Accord.Imaging/GrayLevelCooccurrenceMatrix.cs @@ -208,7 +208,7 @@ public GrayLevelCooccurrenceMatrix(int distance, CooccurrenceDegree degree, /// A square matrix of double-precision values containing the GLCM for the /// of the given . /// - public unsafe double[,] Compute(UnmanagedImage source, Rectangle region) + public double[,] Compute(UnmanagedImage source, Rectangle region) { int width = region.Width; int height = region.Height; @@ -219,80 +219,85 @@ public GrayLevelCooccurrenceMatrix(int distance, CooccurrenceDegree degree, int startX = region.X; int startY = region.Y; - byte* src = (byte*)source.ImageData.ToPointer() + startY * stride + startX; + double[,] cooccurrence; - if (autoGray) - maxGray = max(width, height, offset, src); + unsafe + { + byte* src = (byte*)source.ImageData.ToPointer() + startY * stride + startX; - numPairs = 0; - int size = maxGray + 1; - double[,] cooccurrence = new double[size, size]; + if (autoGray) + maxGray = max(width, height, offset, src); + numPairs = 0; + int size = maxGray + 1; + cooccurrence = new double[size, size]; - switch (degree) - { - case CooccurrenceDegree.Degree0: - for (int y = startY; y < height; y++) - { - for (int x = startX + distance; x < width; x++) + + switch (degree) + { + case CooccurrenceDegree.Degree0: + for (int y = startY; y < height; y++) { - byte a = src[stride * y + (x - distance)]; - byte b = src[stride * y + x]; - cooccurrence[a, b]++; - numPairs++; + for (int x = startX + distance; x < width; x++) + { + byte a = src[stride * y + (x - distance)]; + byte b = src[stride * y + x]; + cooccurrence[a, b]++; + numPairs++; + } } - } - break; + break; - case CooccurrenceDegree.Degree45: - for (int y = startY + distance; y < height; y++) - { - for (int x = startX; x < width - distance; x++) + case CooccurrenceDegree.Degree45: + for (int y = startY + distance; y < height; y++) { - byte a = src[stride * y + x]; - byte b = src[stride * (y - distance) + (x + distance)]; - cooccurrence[a, b]++; - numPairs++; + for (int x = startX; x < width - distance; x++) + { + byte a = src[stride * y + x]; + byte b = src[stride * (y - distance) + (x + distance)]; + cooccurrence[a, b]++; + numPairs++; + } } - } - break; + break; - case CooccurrenceDegree.Degree90: - for (int y = startY + distance; y < height; y++) - { - for (int x = startX; x < width; x++) + case CooccurrenceDegree.Degree90: + for (int y = startY + distance; y < height; y++) { - byte a = src[stride * (y - distance) + x]; - byte b = src[stride * y + x]; - cooccurrence[a, b]++; - numPairs++; + for (int x = startX; x < width; x++) + { + byte a = src[stride * (y - distance) + x]; + byte b = src[stride * y + x]; + cooccurrence[a, b]++; + numPairs++; + } } - } - break; + break; - case CooccurrenceDegree.Degree135: - for (int y = startY + distance; y < height; y++) - { - int steps = width - 1; - for (int x = startX; x < width - distance; x++) + case CooccurrenceDegree.Degree135: + for (int y = startY + distance; y < height; y++) { - byte a = src[stride * y + (steps - x)]; - byte b = src[stride * (y - distance) + (steps - distance - x)]; - cooccurrence[a, b]++; - numPairs++; + int steps = width - 1; + for (int x = startX; x < width - distance; x++) + { + byte a = src[stride * y + (steps - x)]; + byte b = src[stride * (y - distance) + (steps - distance - x)]; + cooccurrence[a, b]++; + numPairs++; + } } - } - break; - } + break; + } - if (normalize && numPairs > 0) - { - fixed (double* ptrMatrix = cooccurrence) + if (normalize && numPairs > 0) { - double* c = ptrMatrix; - for (int i = 0; i < cooccurrence.Length; i++, c++) - *c /= numPairs; - } + fixed (double* ptrMatrix = cooccurrence) + { + double* c = ptrMatrix; + for (int i = 0; i < cooccurrence.Length; i++, c++) + *c /= numPairs; + } + } } return cooccurrence; diff --git a/Sources/Accord.Imaging/GrayLevelDifferenceMethod.cs b/Sources/Accord.Imaging/GrayLevelDifferenceMethod.cs index e0eb9d2fc..45aa716d8 100644 --- a/Sources/Accord.Imaging/GrayLevelDifferenceMethod.cs +++ b/Sources/Accord.Imaging/GrayLevelDifferenceMethod.cs @@ -102,7 +102,7 @@ public GrayLevelDifferenceMethod(CooccurrenceDegree degree, bool autoGray) /// An histogram containing co-occurrences /// for every gray level in . /// - public unsafe int[] Compute(UnmanagedImage source) + public int[] Compute(UnmanagedImage source) { int width = source.Width; int height = source.Height; @@ -110,68 +110,73 @@ public unsafe int[] Compute(UnmanagedImage source) int offset = stride - width; int maxGray = 255; - byte* src = (byte*)source.ImageData.ToPointer(); + int[] hist; - if (autoGray) - maxGray = max(width, height, offset, src); + unsafe + { + byte* src = (byte*)source.ImageData.ToPointer(); + if (autoGray) + maxGray = max(width, height, offset, src); - int[] hist = new int[maxGray + 1]; - switch (degree) - { - case CooccurrenceDegree.Degree0: - for (int y = 0; y < height; y++) - { - for (int x = 1; x < width; x++) + hist = new int[maxGray + 1]; + + switch (degree) + { + case CooccurrenceDegree.Degree0: + for (int y = 0; y < height; y++) { - byte a = src[stride * y + (x - 1)]; - byte b = src[stride * y + x]; - int bin = Math.Abs(a - b); - hist[bin]++; + for (int x = 1; x < width; x++) + { + byte a = src[stride * y + (x - 1)]; + byte b = src[stride * y + x]; + int bin = Math.Abs(a - b); + hist[bin]++; + } } - } - break; + break; - case CooccurrenceDegree.Degree45: - for (int y = 1; y < height; y++) - { - for (int x = 0; x < width - 1; x++) + case CooccurrenceDegree.Degree45: + for (int y = 1; y < height; y++) { - byte a = src[stride * y + x]; - byte b = src[stride * (y - 1) + (x + 1)]; - int bin = Math.Abs(a - b); - hist[bin]++; + for (int x = 0; x < width - 1; x++) + { + byte a = src[stride * y + x]; + byte b = src[stride * (y - 1) + (x + 1)]; + int bin = Math.Abs(a - b); + hist[bin]++; + } } - } - break; + break; - case CooccurrenceDegree.Degree90: - for (int y = 1; y < height; y++) - { - for (int x = 0; x < width; x++) + case CooccurrenceDegree.Degree90: + for (int y = 1; y < height; y++) { - byte a = src[stride * (y - 1) + x]; - byte b = src[stride * y + x]; - int bin = Math.Abs(a - b); - hist[bin]++; + for (int x = 0; x < width; x++) + { + byte a = src[stride * (y - 1) + x]; + byte b = src[stride * y + x]; + int bin = Math.Abs(a - b); + hist[bin]++; + } } - } - break; - - case CooccurrenceDegree.Degree135: - for (int y = 1; y < height; y++) - { - int steps = width - 1; - for (int x = 0; x < width - 1; x++) + break; + + case CooccurrenceDegree.Degree135: + for (int y = 1; y < height; y++) { - byte a = src[stride * y + (steps - x)]; - byte b = src[stride * (y - 1) + (steps - 1 - x)]; - int bin = Math.Abs(a - b); - hist[bin]++; + int steps = width - 1; + for (int x = 0; x < width - 1; x++) + { + byte a = src[stride * y + (steps - x)]; + byte b = src[stride * (y - 1) + (steps - 1 - x)]; + int bin = Math.Abs(a - b); + hist[bin]++; + } } - } - break; + break; + } } return hist; diff --git a/Sources/Accord.Imaging/GrayLevelRunLength.cs b/Sources/Accord.Imaging/GrayLevelRunLength.cs index 4ef0a49dd..33c069c9d 100644 --- a/Sources/Accord.Imaging/GrayLevelRunLength.cs +++ b/Sources/Accord.Imaging/GrayLevelRunLength.cs @@ -106,7 +106,7 @@ public GrayLevelRunLengthMatrix(CooccurrenceDegree degree, bool autoGray) /// An array of run-length vectors containing level counts /// for every width pixel in . /// - public unsafe double[][] Compute(UnmanagedImage source) + public double[][] Compute(UnmanagedImage source) { int width = source.Width; int height = source.Height; @@ -114,185 +114,190 @@ public unsafe double[][] Compute(UnmanagedImage source) int offset = stride - width; int maxGray = 255; - byte* src = (byte*)source.ImageData.ToPointer(); + double[][] runMatrix; - if (autoGray) - maxGray = max(width, height, offset, src); + unsafe + { + byte* src = (byte*)source.ImageData.ToPointer(); - numPrimitives = 0; - double[][] runMatrix = new double[maxGray + 1][]; - for (int i = 0; i < runMatrix.Length; i++) - runMatrix[i] = new double[width + 1]; + if (autoGray) + maxGray = max(width, height, offset, src); + numPrimitives = 0; + runMatrix = new double[maxGray + 1][]; + for (int i = 0; i < runMatrix.Length; i++) + runMatrix[i] = new double[width + 1]; - switch (degree) - { - case CooccurrenceDegree.Degree0: - for (int y = 0; y < height; y++) - { - int runs = 1; - for (int x = 1; x < width; x++) + + switch (degree) + { + case CooccurrenceDegree.Degree0: + for (int y = 0; y < height; y++) { - byte a = src[stride * y + (x - 1)]; - byte b = src[stride * y + x]; + int runs = 1; + for (int x = 1; x < width; x++) + { + byte a = src[stride * y + (x - 1)]; + byte b = src[stride * y + x]; - if (a == b) - runs++; + if (a == b) + runs++; - else - { - runMatrix[a][runs]++; - numPrimitives++; - runs = 1; - } + else + { + runMatrix[a][runs]++; + numPrimitives++; + runs = 1; + } - if ((a == b) && (x == width - 1)) runMatrix[a][runs]++; - if ((a != b) && (x == width - 1)) runMatrix[b][1]++; + if ((a == b) && (x == width - 1)) runMatrix[a][runs]++; + if ((a != b) && (x == width - 1)) runMatrix[b][1]++; + } } - } - break; + break; - case CooccurrenceDegree.Degree45: + case CooccurrenceDegree.Degree45: - // Compute I(0,0) and I(height,width) - runMatrix[0][1]++; - runMatrix[height - 1][width - 1]++; + // Compute I(0,0) and I(height,width) + runMatrix[0][1]++; + runMatrix[height - 1][width - 1]++; - // Compute height - for (int i = 1; i < height; i++) - { - int runs = 1; - int steps = i; - for (int j = 0; j < steps; j++) + // Compute height + for (int i = 1; i < height; i++) { - byte a = src[stride * (i - j) + j]; - byte b = src[stride * (i - j - 1) + j + 1]; + int runs = 1; + int steps = i; + for (int j = 0; j < steps; j++) + { + byte a = src[stride * (i - j) + j]; + byte b = src[stride * (i - j - 1) + j + 1]; - if (a == b) - runs++; + if (a == b) + runs++; - else - { - runMatrix[a][runs]++; - numPrimitives++; - runs = 1; - } + else + { + runMatrix[a][runs]++; + numPrimitives++; + runs = 1; + } - if ((a == b) && (j == steps - 1)) runMatrix[a][runs]++; - if ((a != b) && (j == steps - 1)) runMatrix[b][1]++; + if ((a == b) && (j == steps - 1)) runMatrix[a][runs]++; + if ((a != b) && (j == steps - 1)) runMatrix[b][1]++; + } } - } - - // Compute width - for (int j = 1; j < width - 1; j++) - { - int runs = 1; - int steps = height - j; - for (int i = 1; i < steps; i++) + + // Compute width + for (int j = 1; j < width - 1; j++) { - byte a = src[stride * (height - i) + j + i - 1]; - byte b = src[stride * (height - i - 1) + j + i]; + int runs = 1; + int steps = height - j; + for (int i = 1; i < steps; i++) + { + byte a = src[stride * (height - i) + j + i - 1]; + byte b = src[stride * (height - i - 1) + j + i]; - if (a == b) - runs++; + if (a == b) + runs++; - else - { - runMatrix[a][runs]++; - numPrimitives++; - runs = 1; - } + else + { + runMatrix[a][runs]++; + numPrimitives++; + runs = 1; + } - if ((a == b) && (i == steps - 1)) runMatrix[a][runs]++; - if ((a != b) && (i == steps - 1)) runMatrix[b][1]++; + if ((a == b) && (i == steps - 1)) runMatrix[a][runs]++; + if ((a != b) && (i == steps - 1)) runMatrix[b][1]++; + } } - } - break; - - case CooccurrenceDegree.Degree90: - for (int j = 0; j < width; j++) - { - int runs = 1; - for (int i = 0; i < height - 1; i++) + break; + + case CooccurrenceDegree.Degree90: + for (int j = 0; j < width; j++) { - byte a = src[stride * (height - i - 1) + j]; - byte b = src[stride * (height - i - 2) + j]; + int runs = 1; + for (int i = 0; i < height - 1; i++) + { + byte a = src[stride * (height - i - 1) + j]; + byte b = src[stride * (height - i - 2) + j]; - if (a == b) - runs++; + if (a == b) + runs++; - else - { - runMatrix[a][runs]++; - numPrimitives++; - runs = 1; - } + else + { + runMatrix[a][runs]++; + numPrimitives++; + runs = 1; + } - if ((a == b) && (i == height - 2)) runMatrix[a][runs]++; - if ((a != b) && (i == height - 2)) runMatrix[b][1]++; + if ((a == b) && (i == height - 2)) runMatrix[a][runs]++; + if ((a != b) && (i == height - 2)) runMatrix[b][1]++; + } } - } - break; - - case CooccurrenceDegree.Degree135: - - // Compute I(0,width) and I(height,0) - runMatrix[0][width - 1]++; - runMatrix[height - 1][0]++; - - // Compute height - for (int i = 1; i < width; i++) - { - int runs = 1; - int steps = i; - int w = width - 1; - for (int j = 0; j < steps; j++) - { - byte a = src[stride * (i - j) + (w)]; - byte b = src[stride * (i - j - 1) + (--w)]; + break; + + case CooccurrenceDegree.Degree135: - if (a == b) - runs++; + // Compute I(0,width) and I(height,0) + runMatrix[0][width - 1]++; + runMatrix[height - 1][0]++; - else + // Compute height + for (int i = 1; i < width; i++) + { + int runs = 1; + int steps = i; + int w = width - 1; + for (int j = 0; j < steps; j++) { - runMatrix[a][runs]++; - numPrimitives++; - runs = 1; - } + byte a = src[stride * (i - j) + (w)]; + byte b = src[stride * (i - j - 1) + (--w)]; - if ((a == b) && (j == steps - 1)) runMatrix[a][runs]++; - if ((a != b) && (j == steps - 1)) runMatrix[b][1]++; + if (a == b) + runs++; + + else + { + runMatrix[a][runs]++; + numPrimitives++; + runs = 1; + } + + if ((a == b) && (j == steps - 1)) runMatrix[a][runs]++; + if ((a != b) && (j == steps - 1)) runMatrix[b][1]++; + } } - } - - // Compute width - for (int j = 1; j < width - 1; j++) - { - int runs = 1; - int steps = height - j; - int w = width - 1 - j; - for (int i = 1; i < steps; i++) + + // Compute width + for (int j = 1; j < width - 1; j++) { - byte a = src[stride * (height - i) + (w)]; - byte b = src[stride * (height - i - 1) + (--w)]; + int runs = 1; + int steps = height - j; + int w = width - 1 - j; + for (int i = 1; i < steps; i++) + { + byte a = src[stride * (height - i) + (w)]; + byte b = src[stride * (height - i - 1) + (--w)]; - if (a == b) - runs++; + if (a == b) + runs++; - else - { - runMatrix[a][runs]++; - numPrimitives++; - runs = 1; - } + else + { + runMatrix[a][runs]++; + numPrimitives++; + runs = 1; + } - if ((a == b) && (i == steps - 1)) runMatrix[a][runs]++; - if ((a != b) && (i == steps - 1)) runMatrix[b][1]++; + if ((a == b) && (i == steps - 1)) runMatrix[a][runs]++; + if ((a != b) && (i == steps - 1)) runMatrix[b][1]++; + } } - } - break; + break; + } } return runMatrix; diff --git a/Sources/Accord.Imaging/Interest Points/Haralick/Haralick.cs b/Sources/Accord.Imaging/Interest Points/Haralick/Haralick.cs index 72897bccb..e5aeeeb7e 100644 --- a/Sources/Accord.Imaging/Interest Points/Haralick/Haralick.cs +++ b/Sources/Accord.Imaging/Interest Points/Haralick/Haralick.cs @@ -241,7 +241,7 @@ private void init(int size, bool norm, CooccurrenceDegree[] deg) /// The source image has incorrect pixel format. /// /// - public unsafe List ProcessImage(UnmanagedImage image) + public List ProcessImage(UnmanagedImage image) { // check image format diff --git a/Sources/Accord.Imaging/Interest Points/HarrisCornersDetector.cs b/Sources/Accord.Imaging/Interest Points/HarrisCornersDetector.cs index 3c7c906ed..1545ae6f8 100644 --- a/Sources/Accord.Imaging/Interest Points/HarrisCornersDetector.cs +++ b/Sources/Accord.Imaging/Interest Points/HarrisCornersDetector.cs @@ -275,7 +275,7 @@ private void createGaussian() /// The source image has incorrect pixel format. /// /// - public unsafe List ProcessImage(UnmanagedImage image) + public List ProcessImage(UnmanagedImage image) { // check image format @@ -315,49 +315,51 @@ public unsafe List ProcessImage(UnmanagedImage image) float[,] diffy = new float[height, width]; float[,] diffxy = new float[height, width]; - - fixed (float* pdx = diffx, pdy = diffy, pdxy = diffxy) + unsafe { - // Begin skipping first line - byte* src = (byte*)grayImage.ImageData.ToPointer() + stride; - float* dx = pdx + width; - float* dy = pdy + width; - float* dxy = pdxy + width; - - // for each line - for (int y = 1; y < height - 1; y++) + fixed (float* pdx = diffx, pdy = diffy, pdxy = diffxy) { - // skip first column - dx++; dy++; dxy++; src++; - - // for each inner pixel in line (skipping first and last) - for (int x = 1; x < width - 1; x++, src++, dx++, dy++, dxy++) + // Begin skipping first line + byte* src = (byte*)grayImage.ImageData.ToPointer() + stride; + float* dx = pdx + width; + float* dy = pdy + width; + float* dxy = pdxy + width; + + // for each line + for (int y = 1; y < height - 1; y++) { - // Retrieve the pixel neighborhood - byte a11 = src[+stride + 1], a12 = src[+1], a13 = src[-stride + 1]; - byte a21 = src[+stride + 0], /* a22 */ a23 = src[-stride + 0]; - byte a31 = src[+stride - 1], a32 = src[-1], a33 = src[-stride - 1]; + // skip first column + dx++; dy++; dxy++; src++; + + // for each inner pixel in line (skipping first and last) + for (int x = 1; x < width - 1; x++, src++, dx++, dy++, dxy++) + { + // Retrieve the pixel neighborhood + byte a11 = src[+stride + 1], a12 = src[+1], a13 = src[-stride + 1]; + byte a21 = src[+stride + 0], /* a22 */ a23 = src[-stride + 0]; + byte a31 = src[+stride - 1], a32 = src[-1], a33 = src[-stride - 1]; + + // Convolution with horizontal differentiation kernel mask + float h = ((a11 + a12 + a13) - (a31 + a32 + a33)) * 0.166666667f; - // Convolution with horizontal differentiation kernel mask - float h = ((a11 + a12 + a13) - (a31 + a32 + a33)) * 0.166666667f; + // Convolution with vertical differentiation kernel mask + float v = ((a11 + a21 + a31) - (a13 + a23 + a33)) * 0.166666667f; - // Convolution with vertical differentiation kernel mask - float v = ((a11 + a21 + a31) - (a13 + a23 + a33)) * 0.166666667f; + // Store squared differences directly + *dx = h * h; + *dy = v * v; + *dxy = h * v; + } - // Store squared differences directly - *dx = h * h; - *dy = v * v; - *dxy = h * v; + // Skip last column + dx++; dy++; dxy++; + src += offset + 1; } - // Skip last column - dx++; dy++; dxy++; - src += offset + 1; + // Free some resources which wont be needed anymore + if (image.PixelFormat != PixelFormat.Format8bppIndexed) + grayImage.Dispose(); } - - // Free some resources which wont be needed anymore - if (image.PixelFormat != PixelFormat.Format8bppIndexed) - grayImage.Dispose(); } @@ -376,36 +378,39 @@ public unsafe List ProcessImage(UnmanagedImage image) // 3. Compute Harris Corner Response Map float[,] map = new float[height, width]; - fixed (float* pdx = diffx, pdy = diffy, pdxy = diffxy, pmap = map) + unsafe { - float* dx = pdx; - float* dy = pdy; - float* dxy = pdxy; - float* H = pmap; - float M, A, B, C; - - for (int y = 0; y < height; y++) + fixed (float* pdx = diffx, pdy = diffy, pdxy = diffxy, pmap = map) { - for (int x = 0; x < width; x++, dx++, dy++, dxy++, H++) - { - A = *dx; - B = *dy; - C = *dxy; + float* dx = pdx; + float* dy = pdy; + float* dxy = pdxy; + float* H = pmap; + float M, A, B, C; - if (measure == HarrisCornerMeasure.Harris) - { - // Original Harris corner measure - M = (A * B - C * C) - (k * ((A + B) * (A + B))); - } - else + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++, dx++, dy++, dxy++, H++) { - // Harris-Noble corner measure - M = (A * B - C * C) / (A + B + Constants.SingleEpsilon); - } + A = *dx; + B = *dy; + C = *dxy; - if (M > threshold) - { - *H = M; // insert value in the map + if (measure == HarrisCornerMeasure.Harris) + { + // Original Harris corner measure + M = (A * B - C * C) - (k * ((A + B) * (A + B))); + } + else + { + // Harris-Noble corner measure + M = (A * B - C * C) / (A + B + Constants.SingleEpsilon); + } + + if (M > threshold) + { + *H = M; // insert value in the map + } } } } diff --git a/Sources/Accord.Imaging/Interest Points/HistogramsOfOrientedGradients.cs b/Sources/Accord.Imaging/Interest Points/HistogramsOfOrientedGradients.cs index 87b74f179..958a3380b 100644 --- a/Sources/Accord.Imaging/Interest Points/HistogramsOfOrientedGradients.cs +++ b/Sources/Accord.Imaging/Interest Points/HistogramsOfOrientedGradients.cs @@ -142,7 +142,7 @@ public HistogramsOfOrientedGradients(int numberOfBins = 9, int blockSize = 3, in /// The source image has incorrect pixel format. /// /// - public unsafe List ProcessImage(UnmanagedImage image) + public List ProcessImage(UnmanagedImage image) { // check image format @@ -181,41 +181,44 @@ public unsafe List ProcessImage(UnmanagedImage image) direction = new float[height, width]; magnitude = new float[height, width]; - fixed (float* ptrDir = direction, ptrMag = magnitude) + unsafe { - // Begin skipping first line - byte* src = (byte*)grayImage.ImageData.ToPointer() + stride; - float* dir = ptrDir + width; - float* mag = ptrMag + width; - - // for each line - for (int y = 1; y < height - 1; y++) + fixed (float* ptrDir = direction, ptrMag = magnitude) { - // skip first column - dir++; mag++; src++; + // Begin skipping first line + byte* src = (byte*)grayImage.ImageData.ToPointer() + stride; + float* dir = ptrDir + width; + float* mag = ptrMag + width; - // for each inner pixel in line (skipping first and last) - for (int x = 1; x < width - 1; x++, src++, dir++, mag++) + // for each line + for (int y = 1; y < height - 1; y++) { - // Retrieve the pixel neighborhood - byte a11 = src[+stride + 1], a12 = src[+1], a13 = src[-stride + 1]; - byte a21 = src[+stride + 0], /* a22 */ a23 = src[-stride + 0]; - byte a31 = src[+stride - 1], a32 = src[-1], a33 = src[-stride - 1]; + // skip first column + dir++; mag++; src++; - // Convolution with horizontal differentiation kernel mask - float h = ((a11 + a12 + a13) - (a31 + a32 + a33)) * 0.166666667f; + // for each inner pixel in line (skipping first and last) + for (int x = 1; x < width - 1; x++, src++, dir++, mag++) + { + // Retrieve the pixel neighborhood + byte a11 = src[+stride + 1], a12 = src[+1], a13 = src[-stride + 1]; + byte a21 = src[+stride + 0], /* a22 */ a23 = src[-stride + 0]; + byte a31 = src[+stride - 1], a32 = src[-1], a33 = src[-stride - 1]; - // Convolution with vertical differentiation kernel mask - float v = ((a11 + a21 + a31) - (a13 + a23 + a33)) * 0.166666667f; + // Convolution with horizontal differentiation kernel mask + float h = ((a11 + a12 + a13) - (a31 + a32 + a33)) * 0.166666667f; - // Store angles and magnitudes directly - *dir = (float)Math.Atan2(v, h); - *mag = (float)Math.Sqrt(h * h + v * v); - } + // Convolution with vertical differentiation kernel mask + float v = ((a11 + a21 + a31) - (a13 + a23 + a33)) * 0.166666667f; - // Skip last column - dir++; mag++; src += offset + 1; - } + // Store angles and magnitudes directly + *dir = (float)Math.Atan2(v, h); + *mag = (float)Math.Sqrt(h * h + v * v); + } + + // Skip last column + dir++; mag++; src += offset + 1; + } + } } // Free some resources which wont be needed anymore diff --git a/Sources/Accord.Imaging/Interest Points/LocalBinaryPattern.cs b/Sources/Accord.Imaging/Interest Points/LocalBinaryPattern.cs index c0a2607c9..ad34e5fe4 100644 --- a/Sources/Accord.Imaging/Interest Points/LocalBinaryPattern.cs +++ b/Sources/Accord.Imaging/Interest Points/LocalBinaryPattern.cs @@ -138,7 +138,7 @@ public LocalBinaryPattern(int blockSize = 3, int cellSize = 6, bool normalize = /// The source image has incorrect pixel format. /// /// - public unsafe List ProcessImage(UnmanagedImage image) + public List ProcessImage(UnmanagedImage image) { // check image format @@ -175,42 +175,45 @@ public unsafe List ProcessImage(UnmanagedImage image) // 1. Calculate 8-pixel neighborhood binary patterns patterns = new int[height, width]; - fixed (int* ptrPatterns = patterns) + unsafe { - // Begin skipping first line - byte* src = (byte*)grayImage.ImageData.ToPointer() + stride; - int* neighbors = ptrPatterns + width; - - // for each line - for (int y = 1; y < height - 1; y++) + fixed (int* ptrPatterns = patterns) { - // skip first column - neighbors++; src++; + // Begin skipping first line + byte* src = (byte*)grayImage.ImageData.ToPointer() + stride; + int* neighbors = ptrPatterns + width; - // for each inner pixel in line (skipping first and last) - for (int x = 1; x < width - 1; x++, src++, neighbors++) + // for each line + for (int y = 1; y < height - 1; y++) { - // Retrieve the pixel neighborhood - byte a11 = src[+stride + 1], a12 = src[+1], a13 = src[-stride + 1]; - byte a21 = src[+stride + 0], a22 = src[0], a23 = src[-stride + 0]; - byte a31 = src[+stride - 1], a32 = src[-1], a33 = src[-stride - 1]; - - int sum = 0; - if (a22 < a11) sum += 1 << 0; - if (a22 < a12) sum += 1 << 1; - if (a22 < a13) sum += 1 << 2; - if (a22 < a21) sum += 1 << 3; - if (a22 < a23) sum += 1 << 4; - if (a22 < a31) sum += 1 << 5; - if (a22 < a32) sum += 1 << 6; - if (a22 < a33) sum += 1 << 7; - - *neighbors = sum; - } + // skip first column + neighbors++; src++; - // Skip last column - neighbors++; src += offset + 1; - } + // for each inner pixel in line (skipping first and last) + for (int x = 1; x < width - 1; x++, src++, neighbors++) + { + // Retrieve the pixel neighborhood + byte a11 = src[+stride + 1], a12 = src[+1], a13 = src[-stride + 1]; + byte a21 = src[+stride + 0], a22 = src[0], a23 = src[-stride + 0]; + byte a31 = src[+stride - 1], a32 = src[-1], a33 = src[-stride - 1]; + + int sum = 0; + if (a22 < a11) sum += 1 << 0; + if (a22 < a12) sum += 1 << 1; + if (a22 < a13) sum += 1 << 2; + if (a22 < a21) sum += 1 << 3; + if (a22 < a23) sum += 1 << 4; + if (a22 < a31) sum += 1 << 5; + if (a22 < a32) sum += 1 << 6; + if (a22 < a33) sum += 1 << 7; + + *neighbors = sum; + } + + // Skip last column + neighbors++; src += offset + 1; + } + } } // Free some resources which wont be needed anymore diff --git a/Sources/Accord.Imaging/Moments/RawMoments.cs b/Sources/Accord.Imaging/Moments/RawMoments.cs index 516871630..5101983d0 100644 --- a/Sources/Accord.Imaging/Moments/RawMoments.cs +++ b/Sources/Accord.Imaging/Moments/RawMoments.cs @@ -245,7 +245,7 @@ public void Compute(float[,] image, Rectangle area, bool secondOrder) /// The image. /// The region of interest in the image to compute moments for. /// - public unsafe override void Compute(float[,] image, Rectangle area) + public override void Compute(float[,] image, Rectangle area) { int height = image.GetLength(0); int width = image.GetLength(1); @@ -263,45 +263,48 @@ public unsafe override void Compute(float[,] image, Rectangle area) int offset = width - (windowWidth - windowX); - fixed (float* ptrImage = image) + unsafe { - float* src = ptrImage + windowY * width + windowX; - - // TODO: Walk using x and y directly instead of i and j. - - for (int j = windowY; j < windowHeight; j++) + fixed (float* ptrImage = image) { - float y = j - windowY; + float* src = ptrImage + windowY * width + windowX; + + // TODO: Walk using x and y directly instead of i and j. - for (int i = windowX; i < windowWidth; i++, src++) + for (int j = windowY; j < windowHeight; j++) { - float x = i - windowX; + float y = j - windowY; - float v = *src; + for (int i = windowX; i < windowWidth; i++, src++) + { + float x = i - windowX; - M00 += v; - M01 += y * v; - M10 += x * v; + float v = *src; - if (Order >= 2) - { - M11 += x * y * v; - M02 += y * y * v; - M20 += x * x * v; - } + M00 += v; + M01 += y * v; + M10 += x * v; - if (Order >= 3) - { - M12 += x * y * y * v; - M21 += x * x * y * v; + if (Order >= 2) + { + M11 += x * y * v; + M02 += y * y * v; + M20 += x * x * v; + } - M30 += x * x * x * v; - M03 += y * y * y * v; + if (Order >= 3) + { + M12 += x * y * y * v; + M21 += x * x * y * v; + + M30 += x * x * x * v; + M03 += y * y * y * v; + } } - } - src += offset; - } + src += offset; + } + } } InvM00 = 1f / M00; @@ -316,7 +319,7 @@ public unsafe override void Compute(float[,] image, Rectangle area) /// The image. /// The region of interest in the image to compute moments for. /// - public unsafe override void Compute(UnmanagedImage image, Rectangle area) + public override void Compute(UnmanagedImage image, Rectangle area) { int height = image.Height; int width = image.Width; @@ -334,89 +337,91 @@ public unsafe override void Compute(UnmanagedImage image, Rectangle area) int windowWidth = Math.Min(windowX + area.Width, width); int windowHeight = Math.Min(windowY + area.Height, height); - - if (image.PixelFormat == PixelFormat.Format8bppIndexed) + unsafe { - int offset = stride - (windowWidth - windowX); - - byte* src = (byte*)image.ImageData.ToPointer() + windowY * stride + windowX; - - for (int j = windowY; j < windowHeight; j++) + if (image.PixelFormat == PixelFormat.Format8bppIndexed) { - float y = j - windowY; + int offset = stride - (windowWidth - windowX); + + byte* src = (byte*)image.ImageData.ToPointer() + windowY * stride + windowX; - for (int i = windowX; i < windowWidth; i++, src++) + for (int j = windowY; j < windowHeight; j++) { - float x = i - windowX; + float y = j - windowY; - float v = *src; + for (int i = windowX; i < windowWidth; i++, src++) + { + float x = i - windowX; - M00 += v; - M01 += y * v; - M10 += x * v; + float v = *src; - if (Order >= 2) - { - M11 += x * y * v; - M02 += y * y * v; - M20 += x * x * v; - } + M00 += v; + M01 += y * v; + M10 += x * v; - if (Order >= 3) - { - M12 += x * y * y * v; - M21 += x * x * y * v; + if (Order >= 2) + { + M11 += x * y * v; + M02 += y * y * v; + M20 += x * x * v; + } + + if (Order >= 3) + { + M12 += x * y * y * v; + M21 += x * x * y * v; - M30 += x * x * x * v; - M03 += y * y * y * v; + M30 += x * x * x * v; + M03 += y * y * y * v; + } } - } - src += offset; + src += offset; + } } - } - else - { - // color images - int pixelSize = Bitmap.GetPixelFormatSize(image.PixelFormat) / 8; - int offset = stride - (windowWidth - windowX) * pixelSize; - - byte* src = (byte*)image.ImageData.ToPointer() + windowY * stride + windowX * pixelSize; - - for (int j = windowY; j < windowHeight; j++) + else { - float y = j - windowY; + // color images + int pixelSize = Bitmap.GetPixelFormatSize(image.PixelFormat) / 8; + int offset = stride - (windowWidth - windowX) * pixelSize; - for (int i = windowX; i < windowWidth; i++, src += pixelSize) - { - float x = i - windowX; - - // BT709 - 0.2125, 0.7154, 0.0721 - float v = (float)(0.2125 * src[RGB.R] + 0.7154 * src[RGB.G] + 0.0721 * src[RGB.B]); + byte* src = (byte*)image.ImageData.ToPointer() + windowY * stride + windowX * pixelSize; - M00 += v; - M01 += y * v; - M10 += x * v; + for (int j = windowY; j < windowHeight; j++) + { + float y = j - windowY; - if (Order >= 2) + for (int i = windowX; i < windowWidth; i++, src += pixelSize) { - M11 += x * y * v; - M02 += y * y * v; - M20 += x * x * v; + float x = i - windowX; + + // BT709 - 0.2125, 0.7154, 0.0721 + float v = (float)(0.2125 * src[RGB.R] + 0.7154 * src[RGB.G] + 0.0721 * src[RGB.B]); + + M00 += v; + M01 += y * v; + M10 += x * v; + + if (Order >= 2) + { + M11 += x * y * v; + M02 += y * y * v; + M20 += x * x * v; + } + + if (Order >= 3) + { + M12 += x * y * y * v; + M21 += x * x * y * v; + + M30 += x * x * x * v; + M03 += y * y * y * v; + } } - if (Order >= 3) - { - M12 += x * y * y * v; - M21 += x * x * y * v; - - M30 += x * x * x * v; - M03 += y * y * y * v; - } + src += offset; } - - src += offset; - } + } } diff --git a/Sources/Accord.Imaging/ObjectiveFidelity.cs b/Sources/Accord.Imaging/ObjectiveFidelity.cs index d056c3598..a78f5c5fd 100644 --- a/Sources/Accord.Imaging/ObjectiveFidelity.cs +++ b/Sources/Accord.Imaging/ObjectiveFidelity.cs @@ -51,7 +51,7 @@ namespace Accord.Imaging /// Bitmap ori = ... // Original picture /// Bitmap recon = ... // Reconstructed picture /// - /// // Create a new Wolf-Joulion threshold: + /// // Create a new Objective fidelity comparer: /// var of = new ObjectiveFidelity(ori, recon); /// /// // Get the results @@ -194,7 +194,7 @@ public ObjectiveFidelity(UnmanagedImage a, UnmanagedImage b) /// The first image to be compared. /// The second image that will be compared. /// - public unsafe void Compute(Bitmap a, Bitmap b) + public void Compute(Bitmap a, Bitmap b) { // lock source image BitmapData dataOriginal = a.LockBits( @@ -218,7 +218,7 @@ public unsafe void Compute(Bitmap a, Bitmap b) /// The first image to be compared. /// The second image that will be compared. /// - public unsafe void Compute(BitmapData a, BitmapData b) + public void Compute(BitmapData a, BitmapData b) { Compute(new UnmanagedImage(a), new UnmanagedImage(b)); } @@ -230,7 +230,7 @@ public unsafe void Compute(BitmapData a, BitmapData b) /// The first image to be compared. /// The second image that will be compared. /// - public unsafe void Compute(UnmanagedImage a, UnmanagedImage b) + public void Compute(UnmanagedImage a, UnmanagedImage b) { // check image format if (!(a.PixelFormat == PixelFormat.Format8bppIndexed || @@ -260,39 +260,41 @@ public unsafe void Compute(UnmanagedImage a, UnmanagedImage b) int stride = a.Stride; int offset = stride - a.Width * pixelSize; - byte* ptrA = (byte*)a.ImageData.ToPointer(); - byte* ptrB = (byte*)b.ImageData.ToPointer(); - - // Total error long sum = 0; double sumOfSquares = 0; double imageSumOfSquares = 0; - - // Compute all metrics above - for (int y = 0; y < height; y++) + unsafe { - for (int x = 0; x < width; x++, ptrA++, ptrB++) + byte* ptrA = (byte*)a.ImageData.ToPointer(); + byte* ptrB = (byte*)b.ImageData.ToPointer(); + + + // Compute all metrics above + for (int y = 0; y < height; y++) { - long pA = *ptrA; - long pB = *ptrB; + for (int x = 0; x < width; x++, ptrA++, ptrB++) + { + long pA = *ptrA; + long pB = *ptrB; - long error = pB - pA; - long square = error * error; + long error = pB - pA; + long square = error * error; - // total error - sum += error; + // total error + sum += error; - // root mean square - sumOfSquares += square; + // root mean square + sumOfSquares += square; - // signal to noise ratio - imageSumOfSquares += pB * pB; - } + // signal to noise ratio + imageSumOfSquares += pB * pB; + } - ptrA += offset; - ptrB += offset; + ptrA += offset; + ptrB += offset; + } } diff --git a/Sources/Accord.Imaging/Tools.cs b/Sources/Accord.Imaging/Tools.cs index 5d4d4a3df..1d85d7335 100644 --- a/Sources/Accord.Imaging/Tools.cs +++ b/Sources/Accord.Imaging/Tools.cs @@ -581,7 +581,7 @@ public static int Sum(this Bitmap image) /// Computes the sum of the pixels in a given image. /// /// - public unsafe static int Sum(this BitmapData image) + public static int Sum(this BitmapData image) { return Sum(new UnmanagedImage(image)); } @@ -589,7 +589,7 @@ public unsafe static int Sum(this BitmapData image) /// /// Computes the sum of the pixels in a given image. /// - public unsafe static int Sum(this UnmanagedImage image) + public static int Sum(this UnmanagedImage image) { if (image.PixelFormat != PixelFormat.Format8bppIndexed && image.PixelFormat != PixelFormat.Format16bppGrayScale) @@ -601,27 +601,30 @@ public unsafe static int Sum(this UnmanagedImage image) int sum = 0; - if (image.PixelFormat == PixelFormat.Format8bppIndexed) + unsafe { - byte* src = (byte*)image.ImageData.ToPointer(); - - for (int y = 0; y < height; y++) + if (image.PixelFormat == PixelFormat.Format8bppIndexed) { - for (int x = 0; x < width; x++, src++) - sum += (*src); - src += offset; - } - } - else - { - short* src = (short*)image.ImageData.ToPointer(); + byte* src = (byte*)image.ImageData.ToPointer(); - for (int y = 0; y < height; y++) - { - for (int x = 0; x < width; x++, src++) - sum += (*src); - src += offset; + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++, src++) + sum += (*src); + src += offset; + } } + else + { + short* src = (short*)image.ImageData.ToPointer(); + + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++, src++) + sum += (*src); + src += offset; + } + } } return sum; @@ -655,7 +658,7 @@ public static int Sum(this BitmapData image, Rectangle rectangle) /// /// Computes the sum of the pixels in a given image. /// - public unsafe static int Sum(this UnmanagedImage image, Rectangle rectangle) + public static int Sum(this UnmanagedImage image, Rectangle rectangle) { if ((image.PixelFormat != PixelFormat.Format8bppIndexed) && (image.PixelFormat != PixelFormat.Format16bppGrayScale)) @@ -671,29 +674,32 @@ public unsafe static int Sum(this UnmanagedImage image, Rectangle rectangle) int ry = rectangle.Y; int sum = 0; - if (image.PixelFormat == PixelFormat.Format8bppIndexed) + unsafe { - byte* src = (byte*)image.ImageData.ToPointer(); - - for (int y = 0; y < rheight; y++) + if (image.PixelFormat == PixelFormat.Format8bppIndexed) { - byte* p = src + stride * (ry + y) + rx; + byte* src = (byte*)image.ImageData.ToPointer(); - for (int x = 0; x < rwidth; x++) - sum += (*p++); - } - } - else - { - ushort* src = (ushort*)image.ImageData.ToPointer(); + for (int y = 0; y < rheight; y++) + { + byte* p = src + stride * (ry + y) + rx; - for (int y = 0; y < rheight; y++) + for (int x = 0; x < rwidth; x++) + sum += (*p++); + } + } + else { - ushort* p = src + stride * (ry + y) + rx; + ushort* src = (ushort*)image.ImageData.ToPointer(); - for (int x = 0; x < rwidth; x++) - sum += (*p++); - } + for (int y = 0; y < rheight; y++) + { + ushort* p = src + stride * (ry + y) + rx; + + for (int x = 0; x < rwidth; x++) + sum += (*p++); + } + } } return sum; @@ -786,7 +792,7 @@ public static double StandardDeviation(this BitmapData image, double mean) /// Computes the standard deviation of image pixels. /// /// - public unsafe static double StandardDeviation(this UnmanagedImage image, double mean) + public static double StandardDeviation(this UnmanagedImage image, double mean) { if (image.PixelFormat != PixelFormat.Format8bppIndexed && image.PixelFormat != PixelFormat.Format16bppGrayScale) @@ -798,33 +804,36 @@ public unsafe static double StandardDeviation(this UnmanagedImage image, double double sum = 0; - if (image.PixelFormat == PixelFormat.Format8bppIndexed) + unsafe { - byte* src = (byte*)image.ImageData.ToPointer(); - - for (int y = 0; y < height; y++) + if (image.PixelFormat == PixelFormat.Format8bppIndexed) { - for (int x = 0; x < width; x++, src++) + byte* src = (byte*)image.ImageData.ToPointer(); + + for (int y = 0; y < height; y++) { - double u = (*src) - mean; - sum += u * u; + for (int x = 0; x < width; x++, src++) + { + double u = (*src) - mean; + sum += u * u; + } + src += offset; } - src += offset; } - } - else - { - short* src = (short*)image.ImageData.ToPointer(); - - for (int y = 0; y < height; y++) + else { - for (int x = 0; x < width; x++, src++) + short* src = (short*)image.ImageData.ToPointer(); + + for (int y = 0; y < height; y++) { - double u = (*src) - mean; - sum += u * u; + for (int x = 0; x < width; x++, src++) + { + double u = (*src) - mean; + sum += u * u; + } + src += offset; } - src += offset; - } + } } return Math.Sqrt(sum / (width * height - 1)); @@ -859,7 +868,7 @@ public static double StandardDeviation(this BitmapData image, Rectangle rectangl /// Computes the standard deviation of image pixels. /// /// - public unsafe static double StandardDeviation(this UnmanagedImage image, Rectangle rectangle, double mean) + public static double StandardDeviation(this UnmanagedImage image, Rectangle rectangle, double mean) { if (image.PixelFormat != PixelFormat.Format8bppIndexed && image.PixelFormat != PixelFormat.Format16bppGrayScale) @@ -877,37 +886,40 @@ public unsafe static double StandardDeviation(this UnmanagedImage image, Rectang double sum = 0; - if (image.PixelFormat == PixelFormat.Format8bppIndexed) + unsafe { - byte* src = (byte*)image.ImageData.ToPointer(); - - for (int y = 0; y < rheight; y++) + if (image.PixelFormat == PixelFormat.Format8bppIndexed) { - byte* p = src + stride * (ry + y) + rx; + byte* src = (byte*)image.ImageData.ToPointer(); - for (int x = 0; x < rwidth; x++) + for (int y = 0; y < rheight; y++) { - double u = (*p++) - mean; - sum += u * u; + byte* p = src + stride * (ry + y) + rx; + + for (int x = 0; x < rwidth; x++) + { + double u = (*p++) - mean; + sum += u * u; + } + src += offset; } - src += offset; } - } - else - { - short* src = (short*)image.ImageData.ToPointer(); - - for (int y = 0; y < rheight; y++) + else { - short* p = src + stride * (ry + y) + rx; + short* src = (short*)image.ImageData.ToPointer(); - for (int x = 0; x < rwidth; x++) + for (int y = 0; y < rheight; y++) { - double u = (*p++) - mean; - sum += u * u; + short* p = src + stride * (ry + y) + rx; + + for (int x = 0; x < rwidth; x++) + { + double u = (*p++) - mean; + sum += u * u; + } + src += offset; } - src += offset; - } + } } return Math.Sqrt(sum / (rwidth * rheight - 1)); @@ -974,7 +986,7 @@ public static int Max(this BitmapData image, Rectangle rectangle) /// Computes the maximum pixel value in the given image. /// /// - public unsafe static int Max(this UnmanagedImage image, Rectangle rectangle) + public static int Max(this UnmanagedImage image, Rectangle rectangle) { if ((image.PixelFormat != PixelFormat.Format8bppIndexed) && (image.PixelFormat != PixelFormat.Format16bppGrayScale)) @@ -991,29 +1003,32 @@ public unsafe static int Max(this UnmanagedImage image, Rectangle rectangle) int max = 0; - if (image.PixelFormat == PixelFormat.Format8bppIndexed) + unsafe { - byte* src = (byte*)image.ImageData.ToPointer(); - - for (int y = 0; y < rheight; y++) + if (image.PixelFormat == PixelFormat.Format8bppIndexed) { - byte* p = src + stride * (ry + y) + rx; + byte* src = (byte*)image.ImageData.ToPointer(); - for (int x = 0; x < rwidth; x++, p++) - if (*p > max) max = *p; - } - } - else - { - ushort* src = (ushort*)image.ImageData.ToPointer(); + for (int y = 0; y < rheight; y++) + { + byte* p = src + stride * (ry + y) + rx; - for (int y = 0; y < rheight; y++) + for (int x = 0; x < rwidth; x++, p++) + if (*p > max) max = *p; + } + } + else { - ushort* p = src + 2 * stride * (ry + y) + 2 * rx; + ushort* src = (ushort*)image.ImageData.ToPointer(); - for (int x = 0; x < rwidth; x++, p++) - if (*p > max) max = *p; - } + for (int y = 0; y < rheight; y++) + { + ushort* p = src + 2 * stride * (ry + y) + 2 * rx; + + for (int x = 0; x < rwidth; x++, p++) + if (*p > max) max = *p; + } + } } return max; @@ -1023,7 +1038,7 @@ public unsafe static int Max(this UnmanagedImage image, Rectangle rectangle) /// Computes the maximum pixel value in the given image. /// /// - public unsafe static int Max(this UnmanagedImage image) + public static int Max(this UnmanagedImage image) { if ((image.PixelFormat != PixelFormat.Format8bppIndexed) && (image.PixelFormat != PixelFormat.Format16bppGrayScale)) @@ -1035,21 +1050,24 @@ public unsafe static int Max(this UnmanagedImage image) int max = 0; - if (image.PixelFormat == PixelFormat.Format8bppIndexed) + unsafe { - byte* src = (byte*)image.ImageData.ToPointer(); + if (image.PixelFormat == PixelFormat.Format8bppIndexed) + { + byte* src = (byte*)image.ImageData.ToPointer(); - for (int y = 0; y < height; y++) - for (int x = 0; x < width; x++, src++) - if (*src > max) max = *src; - } - else - { - ushort* src = (ushort*)image.ImageData.ToPointer(); + for (int y = 0; y < height; y++) + for (int x = 0; x < width; x++, src++) + if (*src > max) max = *src; + } + else + { + ushort* src = (ushort*)image.ImageData.ToPointer(); - for (int y = 0; y < height; y++) - for (int x = 0; x < width; x++, src++) - if (*src > max) max = *src; + for (int y = 0; y < height; y++) + for (int x = 0; x < width; x++, src++) + if (*src > max) max = *src; + } } return max; @@ -1059,7 +1077,7 @@ public unsafe static int Max(this UnmanagedImage image) /// Computes the maximum pixel value in the given image. /// /// - public unsafe static int Max(this UnmanagedImage image, int channel) + public static int Max(this UnmanagedImage image, int channel) { if ((image.PixelFormat != PixelFormat.Format32bppArgb) && (image.PixelFormat != PixelFormat.Format24bppRgb)) @@ -1072,11 +1090,14 @@ public unsafe static int Max(this UnmanagedImage image, int channel) int max = 0; - byte* src = (byte*)image.ImageData.ToPointer() + channel; + unsafe + { + byte* src = (byte*)image.ImageData.ToPointer() + channel; - for (int y = 0; y < height; y++) - for (int x = 0; x < width; x++, src += pixelSize) - if (*src > max) max = *src; + for (int y = 0; y < height; y++) + for (int x = 0; x < width; x++, src += pixelSize) + if (*src > max) max = *src; + } return max; @@ -1086,7 +1107,7 @@ public unsafe static int Max(this UnmanagedImage image, int channel) /// Computes the maximum pixel value in the given image. /// /// - public unsafe static int Min(this UnmanagedImage image, int channel) + public static int Min(this UnmanagedImage image, int channel) { if ((image.PixelFormat != PixelFormat.Format32bppArgb) && (image.PixelFormat != PixelFormat.Format24bppRgb)) @@ -1099,12 +1120,14 @@ public unsafe static int Min(this UnmanagedImage image, int channel) int min = int.MaxValue; - byte* src = (byte*)image.ImageData.ToPointer() + channel; - - for (int y = 0; y < height; y++) - for (int x = 0; x < width; x++, src += pixelSize) - if (*src < min) min = *src; + unsafe + { + byte* src = (byte*)image.ImageData.ToPointer() + channel; + for (int y = 0; y < height; y++) + for (int x = 0; x < width; x++, src += pixelSize) + if (*src < min) min = *src; + } return min; } diff --git a/Sources/Accord.MachineLearning/AForge/Exploration Policy/BoltzmannExploration.cs b/Sources/Accord.MachineLearning/AForge/Exploration Policy/BoltzmannExploration.cs new file mode 100644 index 0000000000..47970ad7f --- /dev/null +++ b/Sources/Accord.MachineLearning/AForge/Exploration Policy/BoltzmannExploration.cs @@ -0,0 +1,123 @@ +// AForge Machine Learning Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2007-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.MachineLearning +{ + using System; + + /// + /// Boltzmann distribution exploration policy. + /// + /// + /// The class implements exploration policy base on Boltzmann distribution. + /// Acording to the policy, action a at state s is selected with the next probability: + /// + /// exp( Q( s, a ) / t ) + /// p( s, a ) = ----------------------------- + /// SUM( exp( Q( s, b ) / t ) ) + /// b + /// + /// where Q(s, a) is action's a estimation (usefulness) at state s and + /// t is . + /// + /// + /// + /// + /// + /// + public class BoltzmannExploration : IExplorationPolicy + { + // termperature parameter of Boltzmann distribution + private double temperature; + + // random number generator + private Random rand = new Random( ); + + /// + /// Termperature parameter of Boltzmann distribution, >0. + /// + /// + /// The property sets the balance between exploration and greedy actions. + /// If temperature is low, then the policy tends to be more greedy. + /// + public double Temperature + { + get { return temperature; } + set { temperature = Math.Max( 0, value ); } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Termperature parameter of Boltzmann distribution. + /// + public BoltzmannExploration( double temperature ) + { + Temperature = temperature; + } + + /// + /// Choose an action. + /// + /// + /// Action estimates. + /// + /// Returns selected action. + /// + /// The method chooses an action depending on the provided estimates. The + /// estimates can be any sort of estimate, which values usefulness of the action + /// (expected summary reward, discounted reward, etc). + /// + public int ChooseAction( double[] actionEstimates ) + { + // actions count + int actionsCount = actionEstimates.Length; + // action probabilities + double[] actionProbabilities = new double[actionsCount]; + // actions sum + double sum = 0, probabilitiesSum = 0; + + for ( int i = 0; i < actionsCount; i++ ) + { + double actionProbability = Math.Exp( actionEstimates[i] / temperature ); + + actionProbabilities[i] = actionProbability; + probabilitiesSum += actionProbability; + } + + if ( ( double.IsInfinity( probabilitiesSum ) ) || ( probabilitiesSum == 0 ) ) + { + // do greedy selection in the case of infinity or zero + double maxReward = actionEstimates[0]; + int greedyAction = 0; + + for ( int i = 1; i < actionsCount; i++ ) + { + if ( actionEstimates[i] > maxReward ) + { + maxReward = actionEstimates[i]; + greedyAction = i; + } + } + return greedyAction; + } + + // get random number, which determines which action to choose + double actionRandomNumber = rand.NextDouble( ); + + for ( int i = 0; i < actionsCount; i++ ) + { + sum += actionProbabilities[i] / probabilitiesSum; + if ( actionRandomNumber <= sum ) + return i; + } + + return actionsCount - 1; + } + } +} diff --git a/Sources/Accord.MachineLearning/AForge/Exploration Policy/EpsilonGreedyExploration.cs b/Sources/Accord.MachineLearning/AForge/Exploration Policy/EpsilonGreedyExploration.cs new file mode 100644 index 0000000000..4982e50c2 --- /dev/null +++ b/Sources/Accord.MachineLearning/AForge/Exploration Policy/EpsilonGreedyExploration.cs @@ -0,0 +1,107 @@ +// AForge Machine Learning Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2007-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.MachineLearning +{ + using System; + + /// + /// Epsilon greedy exploration policy. + /// + /// + /// The class implements epsilon greedy exploration policy. Acording to the policy, + /// the best action is chosen with probability 1-epsilon. Otherwise, + /// with probability epsilon, any other action, except the best one, is + /// chosen randomly. + /// + /// According to the policy, the epsilon value is known also as exploration rate. + /// + /// + /// + /// + /// + /// + public class EpsilonGreedyExploration : IExplorationPolicy + { + // exploration rate + private double epsilon; + + // random number generator + private Random rand = new Random( ); + + /// + /// Epsilon value (exploration rate), [0, 1]. + /// + /// + /// The value determines the amount of exploration driven by the policy. + /// If the value is high, then the policy drives more to exploration - choosing random + /// action, which excludes the best one. If the value is low, then the policy is more + /// greedy - choosing the beat so far action. + /// + /// + public double Epsilon + { + get { return epsilon; } + set { epsilon = Math.Max( 0.0, Math.Min( 1.0, value ) ); } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Epsilon value (exploration rate). + /// + public EpsilonGreedyExploration( double epsilon ) + { + Epsilon = epsilon; + } + + /// + /// Choose an action. + /// + /// + /// Action estimates. + /// + /// Returns selected action. + /// + /// The method chooses an action depending on the provided estimates. The + /// estimates can be any sort of estimate, which values usefulness of the action + /// (expected summary reward, discounted reward, etc). + /// + public int ChooseAction( double[] actionEstimates ) + { + // actions count + int actionsCount = actionEstimates.Length; + + // find the best action (greedy) + double maxReward = actionEstimates[0]; + int greedyAction = 0; + + for ( int i = 1; i < actionsCount; i++ ) + { + if ( actionEstimates[i] > maxReward ) + { + maxReward = actionEstimates[i]; + greedyAction = i; + } + } + + // try to do exploration + if ( rand.NextDouble( ) < epsilon ) + { + int randomAction = rand.Next( actionsCount - 1 ); + + if ( randomAction >= greedyAction ) + randomAction++; + + return randomAction; + } + + return greedyAction; + } + } +} diff --git a/Sources/Accord.MachineLearning/AForge/Exploration Policy/IExplorationPolicy.cs b/Sources/Accord.MachineLearning/AForge/Exploration Policy/IExplorationPolicy.cs new file mode 100644 index 0000000000..7e1903b6c --- /dev/null +++ b/Sources/Accord.MachineLearning/AForge/Exploration Policy/IExplorationPolicy.cs @@ -0,0 +1,35 @@ +// AForge Machine Learning Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2007-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.MachineLearning +{ + using System; + + /// + /// Exploration policy interface. + /// + /// + /// The interface describes exploration policies, which are used in Reinforcement + /// Learning to explore state space. + /// + public interface IExplorationPolicy + { + /// + /// Choose an action. + /// + /// + /// Action estimates. + /// + /// Returns selected action. + /// + /// The method chooses an action depending on the provided estimates. The + /// estimates can be any sort of estimate, which values usefulness of the action + /// (expected summary reward, discounted reward, etc). + /// + int ChooseAction( double[] actionEstimates ); + } +} diff --git a/Sources/Accord.MachineLearning/AForge/Exploration Policy/RouletteWheelExploration.cs b/Sources/Accord.MachineLearning/AForge/Exploration Policy/RouletteWheelExploration.cs new file mode 100644 index 0000000000..026ff7ec4 --- /dev/null +++ b/Sources/Accord.MachineLearning/AForge/Exploration Policy/RouletteWheelExploration.cs @@ -0,0 +1,82 @@ +// AForge Machine Learning Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2007-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.MachineLearning +{ + using System; + + /// + /// Roulette wheel exploration policy. + /// + /// + /// The class implements roulette whell exploration policy. Acording to the policy, + /// action a at state s is selected with the next probability: + /// + /// Q( s, a ) + /// p( s, a ) = ------------------ + /// SUM( Q( s, b ) ) + /// b + /// + /// where Q(s, a) is action's a estimation (usefulness) at state s. + /// + /// The exploration policy may be applied only in cases, when action estimates (usefulness) + /// are represented with positive value greater then 0. + /// + /// + /// + /// + /// + /// + public class RouletteWheelExploration : IExplorationPolicy + { + // random number generator + private Random rand = new Random( ); + + /// + /// Initializes a new instance of the class. + /// + /// + public RouletteWheelExploration( ) { } + + /// + /// Choose an action. + /// + /// + /// Action estimates. + /// + /// Returns selected action. + /// + /// The method chooses an action depending on the provided estimates. The + /// estimates can be any sort of estimate, which values usefulness of the action + /// (expected summary reward, discounted reward, etc). + /// + public int ChooseAction( double[] actionEstimates ) + { + // actions count + int actionsCount = actionEstimates.Length; + // actions sum + double sum = 0, estimateSum = 0; + + for ( int i = 0; i < actionsCount; i++ ) + { + estimateSum += actionEstimates[i]; + } + + // get random number, which determines which action to choose + double actionRandomNumber = rand.NextDouble( ); + + for ( int i = 0; i < actionsCount; i++ ) + { + sum += actionEstimates[i] / estimateSum; + if ( actionRandomNumber <= sum ) + return i; + } + + return actionsCount - 1; + } + } +} diff --git a/Sources/Accord.MachineLearning/AForge/Exploration Policy/TabuSearchExploration.cs b/Sources/Accord.MachineLearning/AForge/Exploration Policy/TabuSearchExploration.cs new file mode 100644 index 0000000000..9984fb7bb --- /dev/null +++ b/Sources/Accord.MachineLearning/AForge/Exploration Policy/TabuSearchExploration.cs @@ -0,0 +1,134 @@ +// AForge Machine Learning Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2007-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.MachineLearning +{ + using System; + + /// + /// Tabu search exploration policy. + /// + /// + /// The class implements simple tabu search exploration policy, + /// allowing to set certain actions as tabu for a specified amount of + /// iterations. The actual exploration and choosing from non-tabu actions + /// is done by base exploration policy. + /// + /// + /// + /// + /// + public class TabuSearchExploration : IExplorationPolicy + { + // total actions count + private int actions; + // list of tabu actions + private int[] tabuActions = null; + // base exploration policy + private IExplorationPolicy basePolicy; + + /// + /// Base exploration policy. + /// + /// + /// Base exploration policy is the policy, which is used + /// to choose from non-tabu actions. + /// + public IExplorationPolicy BasePolicy + { + get { return basePolicy; } + set { basePolicy = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Total actions count. + /// Base exploration policy. + /// + public TabuSearchExploration( int actions, IExplorationPolicy basePolicy ) + { + this.actions = actions; + this.basePolicy = basePolicy; + + // create tabu list + tabuActions = new int[actions]; + } + + /// + /// Choose an action. + /// + /// + /// Action estimates. + /// + /// Returns selected action. + /// + /// The method chooses an action depending on the provided estimates. The + /// estimates can be any sort of estimate, which values usefulness of the action + /// (expected summary reward, discounted reward, etc). The action is choosed from + /// non-tabu actions only. + /// + public int ChooseAction( double[] actionEstimates ) + { + // get amount of non-tabu actions + int nonTabuActions = actions; + for ( int i = 0; i < actions; i++ ) + { + if ( tabuActions[i] != 0 ) + { + nonTabuActions--; + } + } + + // allowed actions + double[] allowedActionEstimates = new double[nonTabuActions]; + int[] allowedActionMap = new int[nonTabuActions]; + + for ( int i = 0, j = 0; i < actions; i++ ) + { + if ( tabuActions[i] == 0 ) + { + // allowed action + allowedActionEstimates[j] = actionEstimates[i]; + allowedActionMap[j] = i; + j++; + } + else + { + // decrease tabu time of tabu action + tabuActions[i]--; + } + } + + return allowedActionMap[basePolicy.ChooseAction( allowedActionEstimates )]; ; + } + + /// + /// Reset tabu list. + /// + /// + /// Clears tabu list making all actions allowed. + /// + public void ResetTabuList( ) + { + Array.Clear( tabuActions, 0, actions ); + } + + /// + /// Set tabu action. + /// + /// + /// Action to set tabu for. + /// Tabu time in iterations. + /// + public void SetTabuAction( int action, int tabuTime ) + { + tabuActions[action] = tabuTime; + } + } +} diff --git a/Sources/Accord.MachineLearning/AForge/QLearning.cs b/Sources/Accord.MachineLearning/AForge/QLearning.cs new file mode 100644 index 0000000000..8d42f130e --- /dev/null +++ b/Sources/Accord.MachineLearning/AForge/QLearning.cs @@ -0,0 +1,199 @@ +// AForge Machine Learning Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2007-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.MachineLearning +{ + using System; + + /// + /// QLearning learning algorithm. + /// + /// + /// The class provides implementation of Q-Learning algorithm, known as + /// off-policy Temporal Difference control. + /// + /// + /// + public class QLearning + { + // amount of possible states + private int states; + // amount of possible actions + private int actions; + // q-values + private double[][] qvalues; + // exploration policy + private IExplorationPolicy explorationPolicy; + + // discount factor + private double discountFactor = 0.95; + // learning rate + private double learningRate = 0.25; + + /// + /// Amount of possible states. + /// + /// + public int StatesCount + { + get { return states; } + } + + /// + /// Amount of possible actions. + /// + /// + public int ActionsCount + { + get { return actions; } + } + + /// + /// Exploration policy. + /// + /// + /// Policy, which is used to select actions. + /// + public IExplorationPolicy ExplorationPolicy + { + get { return explorationPolicy; } + set { explorationPolicy = value; } + } + + /// + /// Learning rate, [0, 1]. + /// + /// + /// The value determines the amount of updates Q-function receives + /// during learning. The greater the value, the more updates the function receives. + /// The lower the value, the less updates it receives. + /// + public double LearningRate + { + get { return learningRate; } + set { learningRate = Math.Max( 0.0, Math.Min( 1.0, value ) ); } + } + + /// + /// Discount factor, [0, 1]. + /// + /// + /// Discount factor for the expected summary reward. The value serves as + /// multiplier for the expected reward. So if the value is set to 1, + /// then the expected summary reward is not discounted. If the value is getting + /// smaller, then smaller amount of the expected reward is used for actions' + /// estimates update. + /// + public double DiscountFactor + { + get { return discountFactor; } + set { discountFactor = Math.Max( 0.0, Math.Min( 1.0, value ) ); } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Amount of possible states. + /// Amount of possible actions. + /// Exploration policy. + /// + /// Action estimates are randomized in the case of this constructor + /// is used. + /// + public QLearning( int states, int actions, IExplorationPolicy explorationPolicy ) : + this( states, actions, explorationPolicy, true ) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Amount of possible states. + /// Amount of possible actions. + /// Exploration policy. + /// Randomize action estimates or not. + /// + /// The randomize parameter specifies if initial action estimates should be randomized + /// with small values or not. Randomization of action values may be useful, when greedy exploration + /// policies are used. In this case randomization ensures that actions of the same type are not chosen always. + /// + public QLearning( int states, int actions, IExplorationPolicy explorationPolicy, bool randomize ) + { + this.states = states; + this.actions = actions; + this.explorationPolicy = explorationPolicy; + + // create Q-array + qvalues = new double[states][]; + for ( int i = 0; i < states; i++ ) + { + qvalues[i] = new double[actions]; + } + + // do randomization + if ( randomize ) + { + Random rand = new Random( ); + + for ( int i = 0; i < states; i++ ) + { + for ( int j = 0; j < actions; j++ ) + { + qvalues[i][j] = rand.NextDouble( ) / 10; + } + } + } + } + + /// + /// Get next action from the specified state. + /// + /// + /// Current state to get an action for. + /// + /// Returns the action for the state. + /// + /// The method returns an action according to current + /// exploration policy. + /// + public int GetAction( int state ) + { + return explorationPolicy.ChooseAction( qvalues[state] ); + } + + /// + /// Update Q-function's value for the previous state-action pair. + /// + /// + /// Previous state. + /// Action, which leads from previous to the next state. + /// Reward value, received by taking specified action from previous state. + /// Next state. + /// + public void UpdateState( int previousState, int action, double reward, int nextState ) + { + // next state's action estimations + double[] nextActionEstimations = qvalues[nextState]; + // find maximum expected summary reward from the next state + double maxNextExpectedReward = nextActionEstimations[0]; + + for ( int i = 1; i < actions; i++ ) + { + if ( nextActionEstimations[i] > maxNextExpectedReward ) + maxNextExpectedReward = nextActionEstimations[i]; + } + + // previous state's action estimations + double[] previousActionEstimations = qvalues[previousState]; + // update expexted summary reward of the previous state + previousActionEstimations[action] *= ( 1.0 - learningRate ); + previousActionEstimations[action] += ( learningRate * ( reward + discountFactor * maxNextExpectedReward ) ); + } + } +} \ No newline at end of file diff --git a/Sources/Accord.MachineLearning/AForge/Sarsa.cs b/Sources/Accord.MachineLearning/AForge/Sarsa.cs new file mode 100644 index 0000000000..0a3bd1b05 --- /dev/null +++ b/Sources/Accord.MachineLearning/AForge/Sarsa.cs @@ -0,0 +1,214 @@ +// AForge Machine Learning Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2007-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.MachineLearning +{ + using System; + + /// + /// Sarsa learning algorithm. + /// + /// + /// The class provides implementation of Sarse algorithm, known as + /// on-policy Temporal Difference control. + /// + /// + /// + public class Sarsa + { + // amount of possible states + private int states; + // amount of possible actions + private int actions; + // q-values + private double[][] qvalues; + // exploration policy + private IExplorationPolicy explorationPolicy; + + // discount factor + private double discountFactor = 0.95; + // learning rate + private double learningRate = 0.25; + + /// + /// Amount of possible states. + /// + /// + public int StatesCount + { + get { return states; } + } + + /// + /// Amount of possible actions. + /// + /// + public int ActionsCount + { + get { return actions; } + } + + /// + /// Exploration policy. + /// + /// + /// Policy, which is used to select actions. + /// + public IExplorationPolicy ExplorationPolicy + { + get { return explorationPolicy; } + set { explorationPolicy = value; } + } + + /// + /// Learning rate, [0, 1]. + /// + /// + /// The value determines the amount of updates Q-function receives + /// during learning. The greater the value, the more updates the function receives. + /// The lower the value, the less updates it receives. + /// + public double LearningRate + { + get { return learningRate; } + set { learningRate = Math.Max( 0.0, Math.Min( 1.0, value ) ); } + } + + /// + /// Discount factor, [0, 1]. + /// + /// + /// Discount factor for the expected summary reward. The value serves as + /// multiplier for the expected reward. So if the value is set to 1, + /// then the expected summary reward is not discounted. If the value is getting + /// smaller, then smaller amount of the expected reward is used for actions' + /// estimates update. + /// + public double DiscountFactor + { + get { return discountFactor; } + set { discountFactor = Math.Max( 0.0, Math.Min( 1.0, value ) ); } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Amount of possible states. + /// Amount of possible actions. + /// Exploration policy. + /// + /// Action estimates are randomized in the case of this constructor + /// is used. + /// + public Sarsa( int states, int actions, IExplorationPolicy explorationPolicy ) : + this( states, actions, explorationPolicy, true ) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Amount of possible states. + /// Amount of possible actions. + /// Exploration policy. + /// Randomize action estimates or not. + /// + /// The randomize parameter specifies if initial action estimates should be randomized + /// with small values or not. Randomization of action values may be useful, when greedy exploration + /// policies are used. In this case randomization ensures that actions of the same type are not chosen always. + /// + public Sarsa( int states, int actions, IExplorationPolicy explorationPolicy, bool randomize ) + { + this.states = states; + this.actions = actions; + this.explorationPolicy = explorationPolicy; + + // create Q-array + qvalues = new double[states][]; + for ( int i = 0; i < states; i++ ) + { + qvalues[i] = new double[actions]; + } + + // do randomization + if ( randomize ) + { + Random rand = new Random( ); + + for ( int i = 0; i < states; i++ ) + { + for ( int j = 0; j < actions; j++ ) + { + qvalues[i][j] = rand.NextDouble( ) / 10; + } + } + } + } + + /// + /// Get next action from the specified state. + /// + /// + /// Current state to get an action for. + /// + /// Returns the action for the state. + /// + /// The method returns an action according to current + /// exploration policy. + /// + public int GetAction( int state ) + { + return explorationPolicy.ChooseAction( qvalues[state] ); + } + + /// + /// Update Q-function's value for the previous state-action pair. + /// + /// + /// Curren state. + /// Action, which lead from previous to the next state. + /// Reward value, received by taking specified action from previous state. + /// Next state. + /// Next action. + /// + /// Updates Q-function's value for the previous state-action pair in + /// the case if the next state is non terminal. + /// + public void UpdateState( int previousState, int previousAction, double reward, int nextState, int nextAction ) + { + // previous state's action estimations + double[] previousActionEstimations = qvalues[previousState]; + // update expexted summary reward of the previous state + previousActionEstimations[previousAction] *= ( 1.0 - learningRate ); + previousActionEstimations[previousAction] += ( learningRate * ( reward + discountFactor * + qvalues[nextState][nextAction] ) ); + + } + + /// + /// Update Q-function's value for the previous state-action pair. + /// + /// + /// Curren state. + /// Action, which lead from previous to the next state. + /// Reward value, received by taking specified action from previous state. + /// + /// Updates Q-function's value for the previous state-action pair in + /// the case if the next state is terminal. + /// + public void UpdateState( int previousState, int previousAction, double reward ) + { + // previous state's action estimations + double[] previousActionEstimations = qvalues[previousState]; + // update expexted summary reward of the previous state + previousActionEstimations[previousAction] *= ( 1.0 - learningRate ); + previousActionEstimations[previousAction] += ( learningRate * reward ); + } + } +} diff --git a/Sources/Accord.MachineLearning/Accord.MachineLearning.csproj b/Sources/Accord.MachineLearning/Accord.MachineLearning.csproj index fc21ed583..65891d33d 100644 --- a/Sources/Accord.MachineLearning/Accord.MachineLearning.csproj +++ b/Sources/Accord.MachineLearning/Accord.MachineLearning.csproj @@ -36,46 +36,37 @@ False True DEBUG;TRACE - ..\..\Debug\ + $(SolutionDir)..\Debug\ - ..\..\Release\net35 + $(SolutionDir)..\Release\net35 TRACE;CODE_ANALYSIS;NET35 v3.5 true - ..\..\Release\net35\Accord.MachineLearning.XML - ..\..\Release\net35\Accord.MachineLearning.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net35\Accord.MachineLearning.XML + $(SolutionDir)..\Release\net35\Accord.MachineLearning.dll.CodeAnalysisLog.xml - ..\..\Release\net40 + $(SolutionDir)..\Release\net40 TRACE;CODE_ANALYSIS;NET40 v4.0 - ..\..\Release\net40\Accord.MachineLearning.XML - ..\..\Release\net40\Accord.MachineLearning.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net40\Accord.MachineLearning.XML + $(SolutionDir)..\Release\net40\Accord.MachineLearning.dll.CodeAnalysisLog.xml - ..\..\Release\net45 + $(SolutionDir)..\Release\net45 TRACE;CODE_ANALYSIS;NET45 v4.5 - ..\..\Release\net45\Accord.MachineLearning.XML - ..\..\Release\net45\Accord.MachineLearning.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net45\Accord.MachineLearning.XML + $(SolutionDir)..\Release\net45\Accord.MachineLearning.dll.CodeAnalysisLog.xml - - False - ..\..\Externals\AForge.NET\AForge.dll - False - - - False - ..\..\Externals\AForge.NET\AForge.Math.dll - False - 3.5 + @@ -113,6 +104,11 @@ Code + + + + + @@ -147,9 +143,11 @@ + + @@ -233,11 +231,11 @@ - - \ No newline at end of file + diff --git a/Sources/Accord.MachineLearning/Bayes/NaiveBayes.cs b/Sources/Accord.MachineLearning/Bayes/NaiveBayes.cs index 3cb3a4671..6b1d8d9f8 100644 --- a/Sources/Accord.MachineLearning/Bayes/NaiveBayes.cs +++ b/Sources/Accord.MachineLearning/Bayes/NaiveBayes.cs @@ -47,7 +47,7 @@ namespace Accord.MachineLearning.Bayes /// /// /// This class implements a discrete (integer-valued) Naive-Bayes classifier. There is also a - /// special named constructor to create classifiers assuming normal + /// special named constructor to create classifiers assuming normal /// distributions for each variable. For arbitrary distribution classifiers, please see /// . /// diff --git a/Sources/Accord.MachineLearning/Bayes/NaiveBayes`1.cs b/Sources/Accord.MachineLearning/Bayes/NaiveBayes`1.cs index 5c31dbae5..b62b7af74 100644 --- a/Sources/Accord.MachineLearning/Bayes/NaiveBayes`1.cs +++ b/Sources/Accord.MachineLearning/Bayes/NaiveBayes`1.cs @@ -161,7 +161,14 @@ namespace Accord.MachineLearning.Bayes /// /// /// // We will be computing the output label for a sunny, cool, humid and windy day: - /// double[] instance = codebook.Translate("Sunny", "Cool", "High", "Strong").ToDouble(); + /// + /// double[] instance = new double[] + /// { + /// codebook.Translate(columnName:"Outlook", value:"Sunny"), + /// 12.0, + /// 90.0, + /// codebook.Translate(columnName:"Wind", value:"Strong") + /// }; /// /// // Now, we can feed this instance to our model /// int output = model.Compute(instance, out logLikelihood); @@ -576,6 +583,21 @@ public int Compute(double[] input) return Compute(input, out logLikelihood, out responses); } + /// + /// Computes the most likely class for a given instance. + /// + /// + /// The input instance. + /// The log-likelihood for the instance. + /// + /// The most likely class for the instance. + /// + public int Compute(double[] input, out double logLikelihood) + { + double[] responses; + return Compute(input, out logLikelihood, out responses); + } + /// /// Computes the most likely class for a given instance. /// @@ -583,6 +605,7 @@ public int Compute(double[] input) /// The input instance. /// The log-likelihood for the instance. /// The response probabilities for each class. + /// /// The most likely class for the instance. /// public int Compute(double[] input, out double logLikelihood, out double[] responses) diff --git a/Sources/Accord.MachineLearning/Clustering/BinarySplit.cs b/Sources/Accord.MachineLearning/Clustering/BinarySplit.cs index 64a29759e..d3ce7d13d 100644 --- a/Sources/Accord.MachineLearning/Clustering/BinarySplit.cs +++ b/Sources/Accord.MachineLearning/Clustering/BinarySplit.cs @@ -196,10 +196,6 @@ public int[] Compute(double[][] points, double threshold) } - /// - /// Gets the collection of clusters currently modeled by the clustering algorithm. - /// - /// IClusterCollection IClusteringAlgorithm.Clusters { get { return clusters; } diff --git a/Sources/Accord.MachineLearning/Clustering/GaussianMixtureModel.cs b/Sources/Accord.MachineLearning/Clustering/GaussianMixtureModel.cs index 998252d30..a09c56a7a 100644 --- a/Sources/Accord.MachineLearning/Clustering/GaussianMixtureModel.cs +++ b/Sources/Accord.MachineLearning/Clustering/GaussianMixtureModel.cs @@ -381,27 +381,12 @@ public double Compute(double[][] data, GaussianMixtureModelOptions options) return model.LogLikelihood(data); } - /// - /// Gets the collection of clusters currently modeled by the clustering algorithm. - /// - /// + IClusterCollection IClusteringAlgorithm.Clusters { get { return clusters; } } - /// - /// Divides the input data into a number of clusters. - /// - /// - /// The data where to compute the algorithm. - /// The relative convergence threshold - /// for the algorithm. Default is 1e-5. - /// - /// - /// The labellings for the input data. - /// - /// int[] IClusteringAlgorithm.Compute(double[][] data, double threshold) { Compute(data, threshold); diff --git a/Sources/Accord.MachineLearning/Clustering/KMeans.cs b/Sources/Accord.MachineLearning/Clustering/KMeans.cs index 14f3ab822..c63ef539f 100644 --- a/Sources/Accord.MachineLearning/Clustering/KMeans.cs +++ b/Sources/Accord.MachineLearning/Clustering/KMeans.cs @@ -682,10 +682,6 @@ private bool converged(double[][] centroids, double[][] newCentroids, double thr return true; } - /// - /// Gets the collection of clusters currently modeled by the clustering algorithm. - /// - /// IClusterCollection IClusteringAlgorithm.Clusters { get { return clusters; } diff --git a/Sources/Accord.MachineLearning/DecisionTrees/Learning/C45Learning.cs b/Sources/Accord.MachineLearning/DecisionTrees/Learning/C45Learning.cs index 9cbaa7744..9855ebc76 100644 --- a/Sources/Accord.MachineLearning/DecisionTrees/Learning/C45Learning.cs +++ b/Sources/Accord.MachineLearning/DecisionTrees/Learning/C45Learning.cs @@ -686,7 +686,7 @@ private void checkArgs(double[][] inputs, int[] outputs) if (outputs[i] < 0 || outputs[i] >= tree.OutputClasses) { throw new ArgumentOutOfRangeException("outputs", - "The output label at index " + i + " should be equal to or higher than zero," + + "The output label at index " + i + " should be equal to or higher than zero, " + "and should be lesser than the number of output classes expected by the tree."); } } diff --git a/Sources/Accord.MachineLearning/DecisionTrees/Learning/ID3Learning.cs b/Sources/Accord.MachineLearning/DecisionTrees/Learning/ID3Learning.cs index 47d79e317..0c7e76dc3 100644 --- a/Sources/Accord.MachineLearning/DecisionTrees/Learning/ID3Learning.cs +++ b/Sources/Accord.MachineLearning/DecisionTrees/Learning/ID3Learning.cs @@ -95,7 +95,8 @@ namespace Accord.MachineLearning.DecisionTrees.Learning /// /// // Create a new codification codebook to /// // convert strings into integer symbols - /// Codification codebook = new Codification(data); + /// Codification codebook = new Codification(data, + /// "Outlook", "Temperature", "Humidity", "Wind", "PlayTennis"); /// /// // Translate our training data into integer symbols using our codebook: /// DataTable symbols = codebook.Apply(data); diff --git a/Sources/Accord.MachineLearning/VectorMachines/Learning/MulticlassSupportVectorLearning.cs b/Sources/Accord.MachineLearning/VectorMachines/Learning/MulticlassSupportVectorLearning.cs index 8256b5e1f..989fa9fef 100644 --- a/Sources/Accord.MachineLearning/VectorMachines/Learning/MulticlassSupportVectorLearning.cs +++ b/Sources/Accord.MachineLearning/VectorMachines/Learning/MulticlassSupportVectorLearning.cs @@ -26,6 +26,7 @@ namespace Accord.MachineLearning.VectorMachines.Learning using Accord.Math; using System.Threading.Tasks; using System.Threading; + using System.Collections.Concurrent; /// /// Configuration function to configure the learning algorithms @@ -383,59 +384,67 @@ public double Run(bool computeError, CancellationToken token) msvm.Reset(); + // Save exceptions but process all machines + var exceptions = new ConcurrentBag(); - try + // For each class i + Parallel.For(0, total, k => { - // For each class i - Parallel.For(0, total, k => - { - if (token.IsCancellationRequested) - return; + if (token.IsCancellationRequested) + return; - int i = pairs[k].Item1; - int j = pairs[k].Item2; + int i = pairs[k].Item1; + int j = pairs[k].Item2; - // We will start the binary sub-problem - var args = new SubproblemEventArgs(i, j); - OnSubproblemStarted(args); + // We will start the binary sub-problem + var args = new SubproblemEventArgs(i, j); + OnSubproblemStarted(args); - // Retrieve the associated machine - KernelSupportVectorMachine machine = msvm[i, j]; + // Retrieve the associated machine + KernelSupportVectorMachine machine = msvm[i, j]; - // Retrieve the associated classes - int[] idx = outputs.Find(x => x == i || x == j); + // Retrieve the associated classes + int[] idx = outputs.Find(x => x == i || x == j); - double[][] subInputs = inputs.Submatrix(idx); - int[] subOutputs = outputs.Submatrix(idx); + double[][] subInputs = inputs.Submatrix(idx); + int[] subOutputs = outputs.Submatrix(idx); - // Transform it into a two-class problem - subOutputs.ApplyInPlace(x => x = (x == i) ? -1 : +1); + // Transform it into a two-class problem + subOutputs.ApplyInPlace(x => x = (x == i) ? -1 : +1); - // Train the machine on the two-class problem. - var subproblem = configure(machine, subInputs, subOutputs, i, j); + // Train the machine on the two-class problem. + var subproblem = configure(machine, subInputs, subOutputs, i, j); - var canCancel = (subproblem as ISupportCancellation); + var canCancel = (subproblem as ISupportCancellation); + try + { if (canCancel != null) canCancel.Run(false, token); else subproblem.Run(false); + } + catch (Exception ex) + { + exceptions.Add(ex); + } + // Update and report progress + args.Progress = Interlocked.Increment(ref progress); + args.Maximum = total; - // Update and report progress - args.Progress = Interlocked.Increment(ref progress); - args.Maximum = total; + OnSubproblemFinished(args); + }); - OnSubproblemFinished(args); - }); - } - catch (AggregateException ae) + + if (exceptions.Count > 0) { - if (ae.InnerException is ConvergenceException) - throw ae.InnerException; - throw; + throw new AggregateException("One or more exceptions were thrown when teaching " + + "the machines. Please check the InnerException property of this AggregateException " + + "to discover what exactly caused this error.", exceptions); } + // Compute error if required. return (computeError) ? ComputeError(inputs, outputs) : 0.0; } diff --git a/Sources/Accord.MachineLearning/VectorMachines/MulticlassSupportVectorMachine.cs b/Sources/Accord.MachineLearning/VectorMachines/MulticlassSupportVectorMachine.cs index 76b3b7a03..6e5d61554 100644 --- a/Sources/Accord.MachineLearning/VectorMachines/MulticlassSupportVectorMachine.cs +++ b/Sources/Accord.MachineLearning/VectorMachines/MulticlassSupportVectorMachine.cs @@ -1,26 +1,26 @@ -// Accord Machine Learning Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.MachineLearning.VectorMachines +// Accord Machine Learning Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.MachineLearning.VectorMachines { using Accord.Math; using Accord.Statistics.Kernels; @@ -30,103 +30,103 @@ namespace Accord.MachineLearning.VectorMachines using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Threading; - using System.Threading.Tasks; - - /// - /// Decision strategies for - /// Multi-class Support Vector Machines. - /// - /// - public enum MulticlassComputeMethod - { - /// - /// Max-voting method (also known as 1vs1 decision). - /// - /// - Voting, - - /// - /// Elimination method (also known as DAG decision). - /// - /// - Elimination, - } - - /// - /// One-against-one Multi-class Kernel Support Vector Machine Classifier. - /// - /// - /// - /// - /// The Support Vector Machine is by nature a binary classifier. One of the ways - /// to extend the original SVM algorithm to multiple classes is to build a one- - /// against-one scheme where multiple SVMs specialize to recognize each of the - /// available classes. By using a competition scheme, the original multi-class - /// classification problem is then reduced to n*(n/2) smaller binary problems. - /// - /// Currently this class supports only Kernel machines as the underlying classifiers. - /// If a Linear Support Vector Machine is needed, specify a Linear kernel in the - /// constructor at the moment of creation. - /// - /// - /// References: - /// - /// - /// - /// http://courses.media.mit.edu/2006fall/mas622j/Projects/aisen-project/index.html - /// - /// - /// http://nlp.stanford.edu/IR-book/html/htmledition/multiclass-svms-1.html - /// - /// - /// - /// - /// - /// - /// // Sample data - /// // The following is simple auto association function - /// // where each input correspond to its own class. This - /// // problem should be easily solved by a Linear kernel. - /// - /// // Sample input data - /// double[][] inputs = - /// { - /// new double[] { 0 }, - /// new double[] { 3 }, - /// new double[] { 1 }, - /// new double[] { 2 }, - /// }; - /// - /// // Output for each of the inputs - /// int[] outputs = { 0, 3, 1, 2 }; - /// - /// - /// // Create a new Linear kernel - /// IKernel kernel = new Linear(); - /// - /// // Create a new Multi-class Support Vector Machine with one input, - /// // using the linear kernel and for four disjoint classes. - /// var machine = new MulticlassSupportVectorMachine(1, kernel, 4); - /// - /// // Create the Multi-class learning algorithm for the machine - /// var teacher = new MulticlassSupportVectorLearning(machine, inputs, outputs); - /// - /// // Configure the learning algorithm to use SMO to train the - /// // underlying SVMs in each of the binary class subproblems. - /// teacher.Algorithm = (svm, classInputs, classOutputs, i, j) => - /// new SequentialMinimalOptimization(svm, classInputs, classOutputs); - /// + using System.Threading.Tasks; + + /// + /// Decision strategies for + /// Multi-class Support Vector Machines. + /// + /// + public enum MulticlassComputeMethod + { + /// + /// Max-voting method (also known as 1vs1 decision). + /// + /// + Voting, + + /// + /// Elimination method (also known as DAG decision). + /// + /// + Elimination, + } + + /// + /// One-against-one Multi-class Kernel Support Vector Machine Classifier. + /// + /// + /// + /// + /// The Support Vector Machine is by nature a binary classifier. One of the ways + /// to extend the original SVM algorithm to multiple classes is to build a one- + /// against-one scheme where multiple SVMs specialize to recognize each of the + /// available classes. By using a competition scheme, the original multi-class + /// classification problem is then reduced to n*(n/2) smaller binary problems. + /// + /// Currently this class supports only Kernel machines as the underlying classifiers. + /// If a Linear Support Vector Machine is needed, specify a Linear kernel in the + /// constructor at the moment of creation. + /// + /// + /// References: + /// + /// + /// + /// http://courses.media.mit.edu/2006fall/mas622j/Projects/aisen-project/index.html + /// + /// + /// http://nlp.stanford.edu/IR-book/html/htmledition/multiclass-svms-1.html + /// + /// + /// + /// + /// + /// + /// // Sample data + /// // The following is simple auto association function + /// // where each input correspond to its own class. This + /// // problem should be easily solved by a Linear kernel. + /// + /// // Sample input data + /// double[][] inputs = + /// { + /// new double[] { 0 }, + /// new double[] { 3 }, + /// new double[] { 1 }, + /// new double[] { 2 }, + /// }; + /// + /// // Output for each of the inputs + /// int[] outputs = { 0, 3, 1, 2 }; + /// + /// + /// // Create a new Linear kernel + /// IKernel kernel = new Linear(); + /// + /// // Create a new Multi-class Support Vector Machine with one input, + /// // using the linear kernel and for four disjoint classes. + /// var machine = new MulticlassSupportVectorMachine(1, kernel, 4); + /// + /// // Create the Multi-class learning algorithm for the machine + /// var teacher = new MulticlassSupportVectorLearning(machine, inputs, outputs); + /// + /// // Configure the learning algorithm to use SMO to train the + /// // underlying SVMs in each of the binary class subproblems. + /// teacher.Algorithm = (svm, classInputs, classOutputs, i, j) => + /// new SequentialMinimalOptimization(svm, classInputs, classOutputs); + /// /// // Run the learning algorithm - /// double error = teacher.Run(); // output should be 0 + /// double error = teacher.Run(); // output should be 0 /// /// // Compute the decision output for one of the input vectors - /// int decision = machine.Compute(new double[] { 3 }); // result should be 3 - /// - /// - /// - /// The next example is a simple 3 classes classification problem. - /// It shows how to use a different kernel function, such as the - /// polynomial kernel of degree 2. + /// int decision = machine.Compute(new double[] { 3 }); // result should be 3 + /// + /// + /// + /// The next example is a simple 3 classes classification problem. + /// It shows how to use a different kernel function, such as the + /// polynomial kernel of degree 2. /// /// /// // Sample input data @@ -165,1130 +165,1133 @@ public enum MulticlassComputeMethod /// /// // Compute the decision output for one of the input vectors /// int decision = machine.Compute( new double[] { -1, 3, 2 }); - /// - /// - /// - /// - /// - /// - /// - /// - /// - [Serializable] - public class MulticlassSupportVectorMachine : ISupportVectorMachine, - IEnumerable, KernelSupportVectorMachine>>, IDisposable - { - - // List of underlying binary classifiers - private KernelSupportVectorMachine[][] machines; - - // Multi-class statistics - private int? totalVectorsCount; - private int? uniqueVectorsCount; - private int? sharedVectorsCount; - - - // Performance optimizations - [NonSerialized] - private Lazy sharedVectors; - - [NonSerialized] - private ThreadLocal vectorCache; - - - /// - /// Constructs a new Multi-class Kernel Support Vector Machine - /// - /// - /// The number of inputs for the machine. If sequences have - /// varying length, pass zero to this parameter and pass a suitable sequence - /// kernel to this constructor, such as . - /// The number of classes in the classification problem. - /// - /// - /// If the number of inputs is zero, this means the machine - /// accepts a indefinite number of inputs. This is often the - /// case for kernel vector machines using a sequence kernel. - /// - /// - public MulticlassSupportVectorMachine(int inputs, int classes) - : this(inputs, new Linear(), classes) - { - } - - /// - /// Constructs a new Multi-class Kernel Support Vector Machine - /// - /// - /// The chosen kernel for the machine. Default is to - /// use the kernel. - /// The number of inputs for the machine. If sequences have - /// varying length, pass zero to this parameter and pass a suitable sequence - /// kernel to this constructor, such as . - /// The number of classes in the classification problem. - /// - /// - /// If the number of inputs is zero, this means the machine - /// accepts a indefinite number of inputs. This is often the - /// case for kernel vector machines using a sequence kernel. - /// - /// - public MulticlassSupportVectorMachine(int inputs, IKernel kernel, int classes) - { - if (classes <= 1) - throw new ArgumentException("The machine must have at least two classes.", "classes"); - - // Create the kernel machines - machines = new KernelSupportVectorMachine[classes - 1][]; - for (int i = 0; i < machines.Length; i++) - { - machines[i] = new KernelSupportVectorMachine[i + 1]; - - for (int j = 0; j <= i; j++) - machines[i][j] = new KernelSupportVectorMachine(kernel, inputs); - } - - this.initialize(); - } - - /// - /// Constructs a new Multi-class Kernel Support Vector Machine - /// - /// - /// - /// The machines to be used in each of the pair-wise class subproblems. - /// - /// - public MulticlassSupportVectorMachine(KernelSupportVectorMachine[][] machines) - { - if (machines == null) - throw new ArgumentNullException("machines"); - - this.machines = machines; - this.initialize(); - } - - private void initialize() - { - this.vectorCache = new ThreadLocal(() => new Cache()); - this.sharedVectors = new Lazy(computeSharedVectors, true); - } - - - - - #region Properties - /// - /// Gets the classifier for against . - /// - /// - /// - /// If the index of is greater than , - /// the classifier for the against - /// will be returned instead. If both indices are equal, null will be - /// returned instead. - /// - /// - public KernelSupportVectorMachine this[int class1, int class2] - { - get - { - if (class1 == class2) - return null; - if (class1 > class2) - return machines[class1 - 1][class2]; - else - return machines[class2 - 1][class1]; - } - } - - /// - /// Gets the total number of machines - /// in this multi-class classifier. - /// - /// - public int MachinesCount - { - get { return ((machines.Length + 1) * machines.Length) / 2; } - } - - /// - /// Gets the total number of support vectors - /// in the entire multi-class machine. - /// - /// - public int SupportVectorCount - { - get - { - if (totalVectorsCount == null) - { - int count = 0; - for (int i = 0; i < machines.Length; i++) - for (int j = 0; j < machines[i].Length; j++) - if (machines[i][j].SupportVectors != null) - count += machines[i][j].SupportVectors.Length; - totalVectorsCount = count; - } - - return totalVectorsCount.Value; - } - } - - /// - /// Gets the number of unique support - /// vectors in the multi-class machine. - /// - /// - public int SupportVectorUniqueCount - { - get - { - if (uniqueVectorsCount == null) - { - HashSet unique = new HashSet(); - for (int i = 0; i < machines.Length; i++) - { - for (int j = 0; j < machines[i].Length; j++) - { - if (machines[i][j].SupportVectors != null) - { - for (int k = 0; k < machines[i][j].SupportVectors.Length; k++) - unique.Add(machines[i][j].SupportVectors[k]); - } - } - } - - uniqueVectorsCount = unique.Count; - } - - return uniqueVectorsCount.Value; - } - } - - /// - /// Gets the number of shared support - /// vectors in the multi-class machine. - /// - /// - public int SupportVectorSharedCount - { - get - { - if (sharedVectorsCount == null) - { - var v = sharedVectors.Value; - } - return sharedVectorsCount.Value; - } - } - - /// - /// Gets the number of classes. - /// - /// - public int Classes - { - get { return machines.Length + 1; } - } - - /// - /// Gets the number of inputs of the machines. - /// - /// - public int Inputs - { - get { return machines[0][0].Inputs; } - } - - /// - /// Gets a value indicating whether this machine produces probabilistic outputs. - /// - /// - /// - /// true if this machine produces probabilistic outputs; otherwise, false. - /// - /// - public bool IsProbabilistic - { - get { return machines[0][0].IsProbabilistic; } - } - - /// - /// Gets the subproblems classifiers. - /// - /// - public KernelSupportVectorMachine[][] Machines - { - get { return machines; } - } - #endregion - - - #region Public Compute Overloads - /// - /// Computes the given input to produce the corresponding output. - /// - /// - /// An input vector. - /// - /// The decision label for the given input. - /// - public int Compute(params double[] inputs) - { - double output; // Compute using elimination method as default. - return Compute(inputs, MulticlassComputeMethod.Elimination, out output); - } - - /// - /// Computes the given input to produce the corresponding output. - /// - /// - /// An input vector. - /// The output of the machine. If this is a - /// probabilistic machine, the - /// output is the probability of the positive class. If this is - /// a standard machine, the output is the distance to the decision - /// hyperplane in feature space. - /// - /// The decision label for the given input. - /// - /// - public int Compute(double[] inputs, out double output) - { - // Compute using elimination method as default. - return Compute(inputs, MulticlassComputeMethod.Elimination, out output); - } - - /// - /// Computes the given input to produce the corresponding output. - /// - /// - /// An input vector. - /// The output of the machine. If this is a - /// probabilistic machine, the - /// output is the probability of the positive class. If this is - /// a standard machine, the output is the distance to the decision - /// hyperplane in feature space. - /// The decision path followed by the Decision - /// Directed Acyclic Graph used by the - /// elimination method. - /// - /// The decision label for the given input. - /// - /// - public int Compute(double[] inputs, out double output, out Tuple[] decisionPath) - { - double[] responses; - decisionPath = new Tuple[Classes - 1]; - return computeElimination(inputs, out responses, out output, decisionPath); - } - - /// - /// Computes the given input to produce the corresponding output. - /// - /// - /// An input vector. - /// The model response for each class. - /// - /// The decision label for the given input. - /// - public int Compute(double[] inputs, out double[] responses) - { - double output; // Compute using elimination method as default. - return Compute(inputs, MulticlassComputeMethod.Elimination, out responses, out output); - } - - /// - /// Computes the given input to produce the corresponding output. - /// - /// - /// An input vector. - /// The - /// multi-class classification method to use. - /// The model response for each class. - /// The output of the machine. If this is a - /// probabilistic machine, the - /// output is the probability of the positive class. If this is - /// a standard machine, the output is the distance to the decision - /// hyperplane in feature space. - /// - /// The decision label for the given input. - /// - public int Compute(double[] inputs, MulticlassComputeMethod method, out double[] responses, out double output) - { - if (method == MulticlassComputeMethod.Voting) - { - int[] votes; - int result = computeVoting(inputs, out votes, out output); - - responses = new double[votes.Length]; - for (int i = 0; i < responses.Length; i++) - responses[i] = votes[i] * (2.0 / (Classes * (Classes - 1))); - - return result; - } - else - { - return computeElimination(inputs, out responses, out output, null); - } - } - - /// - /// Computes the given input to produce the corresponding output. - /// - /// - /// An input vector. - /// The - /// multi-class classification method to use. - /// The model response for each class. - /// - /// The class decision for the given input. - /// - public int Compute(double[] inputs, MulticlassComputeMethod method, out double[] responses) - { - double output; - return Compute(inputs, method, out responses, out output); - } - - /// - /// Computes the given input to produce the corresponding output. - /// - /// - /// An input vector. - /// The - /// multi-class classification method to use. - /// The output of the machine. If this is a - /// probabilistic machine, the - /// output is the probability of the positive class. If this is - /// a standard machine, the output is the distance to the decision - /// hyperplane in feature space. - /// - /// The class decision for the given input. - /// - public int Compute(double[] inputs, MulticlassComputeMethod method, out double output) - { - if (method == MulticlassComputeMethod.Voting) - { - int[] votes; - return computeVoting(inputs, out votes, out output); - } - else - { - double[] responses; - return computeElimination(inputs, out responses, out output, null); - } - } - - /// - /// Computes the given input to produce the corresponding output. - /// - /// - /// An input vector. - /// The - /// multi-class classification method to use. - /// - /// The class decision for the given input. - /// - public int Compute(double[] inputs, MulticlassComputeMethod method) - { - double output; - return Compute(inputs, method, out output); - } - #endregion - - - #region Private Multi-class Decision - /// - /// Computes the given input to produce the corresponding output. - /// - /// - /// An input vector. - /// A vector containing the number of votes for each class. - /// The output of the machine. If this is a - /// probabilistic machine, the - /// output is the probability of the positive class. If this is - /// a standard machine, the output is the distance to the decision - /// hyperplane in feature space. - /// - /// The decision label for the given input. - /// - private int computeVoting(double[] inputs, out int[] votes, out double output) - { - // Compute decision by Voting - - // Get a list of the shared vectors (lazy) - int[][][] vectors = this.sharedVectors.Value; - - // Get the cache for this thread - Cache cache = createOrResetCache(); - - // out variables cannot be passed into delegates, - // so will be creating a copy for the vote array. - int[] voting = new int[Classes]; - - // For each class - Parallel.For(0, Classes, i => - { - // For each other class - for (int j = 0; j < i; j++) - { - double machineOutput; - - // Retrieve and compute the two-class problem for classes i x j - int answer = computeSequential(i, j, inputs, out machineOutput, cache); - - // Determine the winner class - int y = (answer == -1) ? i : j; - - // Increment votes for the winner - Interlocked.Increment(ref voting[y]); - } - }); - - // Voting finished. - votes = voting; - - // Select class which maximum number of votes - int imax; output = Matrix.Max(votes, out imax); - - // Determine output probability using no. of votes - output = output * (2.0 / (Classes * (Classes - 1))); - - return imax; // Return the winner as the output. - } - - /// - /// Computes the given input to produce the corresponding output. - /// - /// - /// - /// This method computes the decision for a one-against-one multiclass - /// support vector machine using the Directed Acyclic Graph method by - /// Platt, Cristianini and Shawe-Taylor. Details are given on the - /// original paper "Large Margin DAGs for Multiclass Classification", 2000. - /// - /// - /// An input vector. - /// The model response for each class. - /// The output of the machine. If this is a - /// probabilistic machine, the - /// output is the probability of the positive class. If this is - /// a standard machine, the output is the distance to the decision - /// hyperplane in feature space. - /// The decision path followed by the Decision - /// Directed Acyclic Graph used by the - /// elimination method. - /// - /// The decision label for the given input. - /// - private int computeElimination(double[] inputs, out double[] responses, - out double output, Tuple[] decisionPath) - { - // Compute decision by Directed Acyclic Graph - - // Get a list of the shared vectors - int[][][] vectors = this.sharedVectors.Value; - - // Get the cache for this thread - Cache cache = createOrResetCache(); - - output = 0; - - // Initialize metrics - responses = new double[Classes]; - bool probabilistic = IsProbabilistic; - - if (probabilistic) - { - for (int i = 0; i < responses.Length; i++) - responses[i] = 1.0; - } - - // Start with first and last classes - int classA = Classes - 1, classB = 0; - int progress = 0; - - // Navigate decision path - while (classA != classB) - { - - // Compute the two-class decision problem to decide for A x B - int answer = computeParallel(classA, classB, inputs, out output, cache); - - if (decisionPath != null) - decisionPath[progress++] = Tuple.Create(classA, classB); - - // Check who won and update - - if (answer == -1) - { - // The class A has won and class B has lost - - if (probabilistic) - { - // Decrease loser likelihood - responses[classB] *= output; - - // Increase for all other classes - for (int i = 0; i < responses.Length; i++) - if (i != classB) responses[i] *= 1.0 - output; - } - else - { - // Store the distance to the - // answer for the loser class - responses[classB] = -output; - } - - // Advance classB towards - // the middle of the list - classB++; - } - - else // answer == +1 - { - // The class A has lost and class B has won - - if (probabilistic) - { - // Decrease loser likelihood - responses[classA] *= 1.0 - output; - - // Increase for all other classes - for (int i = 0; i < responses.Length; i++) - if (i != classA) responses[i] *= output; - } - else - { - // Store the distance to the - // answer for the loser class - responses[classA] = output; - } - - // Advance classA towards - // the middle of the list - classA--; - } - } - - // At this point, classA = classB is the winner - if (!probabilistic) responses[classA] = output; - -#if DEBUG - else - { - int imax; responses.Max(out imax); - if (imax != classA) throw new Exception(); - } -#endif - - // Return output for winner class - output = responses[classA]; - - return classA; - } - - #endregion - - - #region Private Single machine Decision - /// - /// Compute SVM output with support vector sharing. - /// - /// - private int computeSequential(int classA, int classB, double[] input, out double output, Cache cache) - { - // Get the machine for this problem - KernelSupportVectorMachine machine = machines[classA - 1][classB]; - - // Get the vectors shared among all machines - int[] vectors = cache.Vectors[classA - 1][classB]; - double[] values = cache.Products; - - double sum = machine.Threshold; - - - if (machine.IsCompact) - { - // For linear machines, computation is simpler - for (int i = 0; i < machine.Weights.Length; i++) - sum += machine.Weights[i] * input[i]; - } - else - { - // For each support vector in the machine - for (int i = 0; i < vectors.Length; i++) - { - double value; - - // Check if it is a shared vector - int j = vectors[i]; - - if (j >= 0) - { - // This is a shared vector. Check - // if it has already been computed - - if (!Double.IsNaN(values[j])) - { - // Yes, it has. Retrieve the value from the cache - value = values[j]; - } - else - { - // No, it has not. Compute and store the computed value in the cache - value = values[j] = machine.Kernel.Function(machine.SupportVectors[i], input); - Interlocked.Increment(ref cache.Evaluations); - } - } - else - { - // This vector is not shared by any other machine. No need to cache - value = machine.Kernel.Function(machine.SupportVectors[i], input); - Interlocked.Increment(ref cache.Evaluations); - } - - sum += machine.Weights[i] * value; - } - } - - - // Produce probabilities if required - if (machine.IsProbabilistic) - { - output = machine.Link.Inverse(sum); - return output >= 0.5 ? +1 : -1; - } - else - { - output = sum; - return output >= 0 ? +1 : -1; - } - } - - /// - /// Compute SVM output with support vector sharing. - /// - /// - private int computeParallel(int classA, int classB, double[] input, out double output, Cache cache) - { - // Get the machine for this problem - KernelSupportVectorMachine machine = machines[classA - 1][classB]; - - // Get the vectors shared among all machines - int[] vectors = cache.Vectors[classA - 1][classB]; - - double[] values = cache.Products; -#if !NET35 - SpinLock[] locks = cache.SyncObjects; -#endif - double sum = machine.Threshold; - - - if (machine.IsCompact) - { - // For linear machines, computation is simpler - for (int i = 0; i < machine.Weights.Length; i++) - sum += machine.Weights[i] * input[i]; - } - else - { - -#if NET35 - #region Backward compatibility - for (int i = 0; i < vectors.Length; i++) - { - double value; - - // Check if it is a shared vector - int j = vectors[i]; - - if (j >= 0) - { - // This is a shared vector. Check - // if it has already been computed - - if (!Double.IsNaN(values[j])) - { - // Yes, it has. Retrieve the value from the cache - value = values[j]; - } - else - { - // No, it has not. Compute and store the computed value in the cache - value = values[j] = machine.Kernel.Function(machine.SupportVectors[i], input); - Interlocked.Increment(ref cache.Evaluations); - } - } - else - { - // This vector is not shared by any other machine. No need to cache - value = machine.Kernel.Function(machine.SupportVectors[i], input); - Interlocked.Increment(ref cache.Evaluations); - } - - sum += machine.Weights[i] * value; - } - #endregion -#else - // For each support vector in the machine - Parallel.For(0, vectors.Length, - - // Init - () => 0.0, - - // Map - (i, state, partialSum) => - { - double value; - - // Check if it is a shared vector - int j = vectors[i]; - - if (j >= 0) - { - // This is a shared vector. Check - // if it has already been computed - - bool taken = false; - locks[j].Enter(ref taken); - - if (!Double.IsNaN(values[j])) - { - // Yes, it has. Retrieve the value from the cache - value = values[j]; - } - else - { - // No, it has not. Compute and store the computed value in the cache - value = values[j] = machine.Kernel.Function(machine.SupportVectors[i], input); - Interlocked.Increment(ref cache.Evaluations); - } - - locks[j].Exit(); - } - else - { - // This vector is not shared by any other machine. No need to cache - value = machine.Kernel.Function(machine.SupportVectors[i], input); - Interlocked.Increment(ref cache.Evaluations); - } - - return partialSum + machine.Weights[i] * value; - }, - - // Reduce - (partialSum) => { lock (locks) sum += partialSum; } - ); -#endif - } - - // Produce probabilities if required - if (machine.IsProbabilistic) - { - output = machine.Link.Inverse(sum); - return output >= 0.5 ? +1 : -1; - } - else - { - output = sum; - return output >= 0 ? +1 : -1; - } - } - #endregion - - - - - - /// - /// Resets the cache and machine statistics - /// so they can be recomputed on next evaluation. - /// - /// - public void Reset() - { - if (this.vectorCache != null) - this.vectorCache.Dispose(); - - this.sharedVectors = null; - this.totalVectorsCount = null; - this.uniqueVectorsCount = null; - this.sharedVectorsCount = null; - - this.initialize(); - } - - /// - /// Gets the total kernel evaluations performed - /// in the last call to any of the - /// functions in the current thread. - /// - /// - /// The number of total kernel evaluations. - /// - public int GetLastKernelEvaluations() - { - return vectorCache.Value.Evaluations; - } - - - #region Loading & Saving - - /// - /// Saves the machine to a stream. - /// - /// - /// The stream to which the machine is to be serialized. - /// - public void Save(Stream stream) - { - BinaryFormatter b = new BinaryFormatter(); - b.Serialize(stream, this); - } - - /// - /// Saves the machine to a file. - /// - /// - /// The path to the file to which the machine is to be serialized. - /// - public void Save(string path) - { - using (FileStream fs = new FileStream(path, FileMode.Create)) - { - Save(fs); - } - } - - /// - /// Loads a machine from a stream. - /// - /// - /// The stream from which the machine is to be deserialized. - /// - /// The deserialized machine. - /// - public static MulticlassSupportVectorMachine Load(Stream stream) - { - BinaryFormatter b = new BinaryFormatter(); - return (MulticlassSupportVectorMachine)b.Deserialize(stream); - } - - /// - /// Loads a machine from a file. - /// - /// - /// The path to the file from which the machine is to be deserialized. - /// - /// The deserialized machine. - /// - public static MulticlassSupportVectorMachine Load(string path) - { - using (FileStream fs = new FileStream(path, FileMode.Open)) - { - return Load(fs); - } - } - - [OnDeserialized] - private void onDeserialized(StreamingContext context) - { - initialize(); - } - #endregion - - #region IEnumerable members - /// - /// Returns an enumerator that iterates through all machines - /// contained inside this multi-class support vector machine. - /// - /// - public IEnumerator, KernelSupportVectorMachine>> GetEnumerator() - { - for (int i = 0; i < machines.Length; i++) - { - for (int j = 0; j < machines[i].Length; j++) - { - yield return new KeyValuePair, KernelSupportVectorMachine>( - Tuple.Create(i + 1, j), machines[i][j]); - } - } - } - - /// - /// Returns an enumerator that iterates through all machines - /// contained inside this multi-class support vector machine. - /// - /// - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - #endregion - - #region IDisposable members - /// - /// Performs application-defined tasks associated with - /// freeing, releasing, or resetting unmanaged resources. - /// - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// Releases unmanaged and - optionally - managed resources - /// - /// - /// - /// true to release both managed and unmanaged resources; - /// false to release only unmanaged resources. - /// - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - // free managed resources - if (vectorCache != null) - { - vectorCache.Dispose(); - vectorCache = null; - } - } - } - #endregion - - - - #region Cache - private Cache createOrResetCache() - { - Cache cache = vectorCache.Value; - - // First of all, check if the shared vectors in this machine - // already have been identified. If they don't, identify them. - - cache.Vectors = sharedVectors.Value; // use lazy instantiation - int vectorCount = SupportVectorSharedCount; - - // Now, check if a cache has already been created for this - // thread and has adequate size. If it has not, create it. - - if (cache.Products == null || cache.Products.Length < vectorCount) - { - // The cache has not been created - cache.Products = new double[vectorCount]; - -#if !NET35 // Create synchronization objects - cache.SyncObjects = new SpinLock[vectorCount]; - for (int i = 0; i < cache.SyncObjects.Length; i++) - cache.SyncObjects[i] = new SpinLock(); -#endif - } - - // Initialize (or reset) the cache. A value of Not-a-Number - // indicates that the value of corresponding vector has not - // been computed yet. - for (int i = 0; i < cache.Products.Length; i++) - cache.Products[i] = Double.NaN; - - - cache.Evaluations = 0; - - return cache; - } - - - private int[][][] computeSharedVectors() - { - // This method should only be called once after the machine has - // been learned. If the inner machines or they Support Vectors - // change, this method will need to be recomputed. - - // Detect all vectors which are being shared along the machines - var shared = new Dictionary>>(); - - // for all machines - for (int i = 0; i < machines.Length; i++) - { - for (int j = 0; j < machines[i].Length; j++) - { - // if the machine is not in compact form - if (machines[i][j].SupportVectors != null) - { - // register the support vector on the shared cache collection - for (int k = 0; k < machines[i][j].SupportVectors.Length; k++) - { - double[] sv = machines[i][j].SupportVectors[k]; - - List> count; - bool success = shared.TryGetValue(sv, out count); - - if (success) - { - // Value is already in the dictionary - count.Add(Tuple.Create(i, j, k)); - } - else - { - count = new List>(); - count.Add(Tuple.Create(i, j, k)); - shared[sv] = count; - } - } - } - } - } - - // Create a table of indices for shared vectors - int idx = 0; - - var indices = new Dictionary(); - foreach (double[] sv in shared.Keys) - indices[sv] = idx++; - - // Create a lookup table for the machines - int[][][] sharedVectors = new int[machines.Length][][]; - for (int i = 0; i < sharedVectors.Length; i++) - { - sharedVectors[i] = new int[machines[i].Length][]; - for (int j = 0; j < sharedVectors[i].Length; j++) - { - if (machines[i][j].SupportVectors != null) - { - sharedVectors[i][j] = new int[machines[i][j].SupportVectors.Length]; - - for (int k = 0; k < machines[i][j].SupportVectors.Length; k++) - { - double[] sv = machines[i][j].SupportVectors[k]; - if (shared.ContainsKey(sv)) - sharedVectors[i][j][k] = indices[sv]; - else - sharedVectors[i][j][k] = -1; - } - } - } - } - - sharedVectorsCount = shared.Count; - return sharedVectors; - } - - private class Cache - { - public int Evaluations; - public double[] Products; - public int[][][] Vectors; -#if !NET35 - public SpinLock[] SyncObjects; -#endif - } - - #endregion - - } -} + /// + /// + /// + /// + /// + /// + /// + /// + /// + [Serializable] + public class MulticlassSupportVectorMachine : ISupportVectorMachine, + IEnumerable, KernelSupportVectorMachine>>, IDisposable + { + + // List of underlying binary classifiers + private KernelSupportVectorMachine[][] machines; + + // Multi-class statistics + private int? totalVectorsCount; + private int? uniqueVectorsCount; + private int? sharedVectorsCount; + + + // Performance optimizations + [NonSerialized] + private Lazy sharedVectors; + + [NonSerialized] + private ThreadLocal vectorCache; + + + /// + /// Constructs a new Multi-class Kernel Support Vector Machine + /// + /// + /// The number of inputs for the machine. If sequences have + /// varying length, pass zero to this parameter and pass a suitable sequence + /// kernel to this constructor, such as . + /// The number of classes in the classification problem. + /// + /// + /// If the number of inputs is zero, this means the machine + /// accepts a indefinite number of inputs. This is often the + /// case for kernel vector machines using a sequence kernel. + /// + /// + public MulticlassSupportVectorMachine(int inputs, int classes) + : this(inputs, new Linear(), classes) + { + } + + /// + /// Constructs a new Multi-class Kernel Support Vector Machine + /// + /// + /// The chosen kernel for the machine. Default is to + /// use the kernel. + /// The number of inputs for the machine. If sequences have + /// varying length, pass zero to this parameter and pass a suitable sequence + /// kernel to this constructor, such as . + /// The number of classes in the classification problem. + /// + /// + /// If the number of inputs is zero, this means the machine + /// accepts a indefinite number of inputs. This is often the + /// case for kernel vector machines using a sequence kernel. + /// + /// + public MulticlassSupportVectorMachine(int inputs, IKernel kernel, int classes) + { + if (classes <= 1) + throw new ArgumentException("The machine must have at least two classes.", "classes"); + + // Create the kernel machines + machines = new KernelSupportVectorMachine[classes - 1][]; + for (int i = 0; i < machines.Length; i++) + { + machines[i] = new KernelSupportVectorMachine[i + 1]; + + for (int j = 0; j <= i; j++) + machines[i][j] = new KernelSupportVectorMachine(kernel, inputs); + } + + this.initialize(); + } + + /// + /// Constructs a new Multi-class Kernel Support Vector Machine + /// + /// + /// + /// The machines to be used in each of the pair-wise class subproblems. + /// + /// + public MulticlassSupportVectorMachine(KernelSupportVectorMachine[][] machines) + { + if (machines == null) + throw new ArgumentNullException("machines"); + + this.machines = machines; + this.initialize(); + } + + private void initialize() + { + this.vectorCache = new ThreadLocal(() => new Cache()); + this.sharedVectors = new Lazy(computeSharedVectors, true); + } + + + + + #region Properties + /// + /// Gets the classifier for against . + /// + /// + /// + /// If the index of is greater than , + /// the classifier for the against + /// will be returned instead. If both indices are equal, null will be + /// returned instead. + /// + /// + public KernelSupportVectorMachine this[int class1, int class2] + { + get + { + if (class1 == class2) + return null; + if (class1 > class2) + return machines[class1 - 1][class2]; + else + return machines[class2 - 1][class1]; + } + } + + /// + /// Gets the total number of machines + /// in this multi-class classifier. + /// + /// + public int MachinesCount + { + get { return ((machines.Length + 1) * machines.Length) / 2; } + } + + /// + /// Gets the total number of support vectors + /// in the entire multi-class machine. + /// + /// + public int SupportVectorCount + { + get + { + if (totalVectorsCount == null) + { + int count = 0; + for (int i = 0; i < machines.Length; i++) + for (int j = 0; j < machines[i].Length; j++) + if (machines[i][j].SupportVectors != null) + count += machines[i][j].SupportVectors.Length; + totalVectorsCount = count; + } + + return totalVectorsCount.Value; + } + } + + /// + /// Gets the number of unique support + /// vectors in the multi-class machine. + /// + /// + public int SupportVectorUniqueCount + { + get + { + if (uniqueVectorsCount == null) + { + HashSet unique = new HashSet(); + for (int i = 0; i < machines.Length; i++) + { + for (int j = 0; j < machines[i].Length; j++) + { + if (machines[i][j].SupportVectors != null) + { + for (int k = 0; k < machines[i][j].SupportVectors.Length; k++) + unique.Add(machines[i][j].SupportVectors[k]); + } + } + } + + uniqueVectorsCount = unique.Count; + } + + return uniqueVectorsCount.Value; + } + } + + /// + /// Gets the number of shared support + /// vectors in the multi-class machine. + /// + /// + public int SupportVectorSharedCount + { + get + { + if (sharedVectorsCount == null) + { + var v = sharedVectors.Value; + } + return sharedVectorsCount.Value; + } + } + + /// + /// Gets the number of classes. + /// + /// + public int Classes + { + get { return machines.Length + 1; } + } + + /// + /// Gets the number of inputs of the machines. + /// + /// + public int Inputs + { + get { return machines[0][0].Inputs; } + } + + /// + /// Gets a value indicating whether this machine produces probabilistic outputs. + /// + /// + /// + /// true if this machine produces probabilistic outputs; otherwise, false. + /// + /// + public bool IsProbabilistic + { + get { return machines[0][0].IsProbabilistic; } + } + + /// + /// Gets the subproblems classifiers. + /// + /// + public KernelSupportVectorMachine[][] Machines + { + get { return machines; } + } + #endregion + + + #region Public Compute Overloads + /// + /// Computes the given input to produce the corresponding output. + /// + /// + /// An input vector. + /// + /// The decision label for the given input. + /// + public int Compute(params double[] inputs) + { + double output; // Compute using elimination method as default. + return Compute(inputs, MulticlassComputeMethod.Elimination, out output); + } + + /// + /// Computes the given input to produce the corresponding output. + /// + /// + /// An input vector. + /// The output of the machine. If this is a + /// probabilistic machine, the + /// output is the probability of the positive class. If this is + /// a standard machine, the output is the distance to the decision + /// hyperplane in feature space. + /// + /// The decision label for the given input. + /// + /// + public int Compute(double[] inputs, out double output) + { + // Compute using elimination method as default. + return Compute(inputs, MulticlassComputeMethod.Elimination, out output); + } + + /// + /// Computes the given input to produce the corresponding output. + /// + /// + /// An input vector. + /// The output of the machine. If this is a + /// probabilistic machine, the + /// output is the probability of the positive class. If this is + /// a standard machine, the output is the distance to the decision + /// hyperplane in feature space. + /// The decision path followed by the Decision + /// Directed Acyclic Graph used by the + /// elimination method. + /// + /// The decision label for the given input. + /// + /// + public int Compute(double[] inputs, out double output, out Tuple[] decisionPath) + { + double[] responses; + decisionPath = new Tuple[Classes - 1]; + return computeElimination(inputs, out responses, out output, decisionPath); + } + + /// + /// Computes the given input to produce the corresponding output. + /// + /// + /// An input vector. + /// The model response for each class. + /// + /// The decision label for the given input. + /// + public int Compute(double[] inputs, out double[] responses) + { + double output; // Compute using elimination method as default. + return Compute(inputs, MulticlassComputeMethod.Elimination, out responses, out output); + } + + /// + /// Computes the given input to produce the corresponding output. + /// + /// + /// An input vector. + /// The + /// multi-class classification method to use. + /// The model response for each class. + /// The output of the machine. If this is a + /// probabilistic machine, the + /// output is the probability of the positive class. If this is + /// a standard machine, the output is the distance to the decision + /// hyperplane in feature space. + /// + /// The decision label for the given input. + /// + public int Compute(double[] inputs, MulticlassComputeMethod method, out double[] responses, out double output) + { + if (method == MulticlassComputeMethod.Voting) + { + int[] votes; + int result = computeVoting(inputs, out votes, out output); + + responses = new double[votes.Length]; + for (int i = 0; i < responses.Length; i++) + responses[i] = votes[i] * (2.0 / (Classes * (Classes - 1))); + + return result; + } + else + { + return computeElimination(inputs, out responses, out output, null); + } + } + + /// + /// Computes the given input to produce the corresponding output. + /// + /// + /// An input vector. + /// The + /// multi-class classification method to use. + /// The model response for each class. + /// + /// The class decision for the given input. + /// + public int Compute(double[] inputs, MulticlassComputeMethod method, out double[] responses) + { + double output; + return Compute(inputs, method, out responses, out output); + } + + /// + /// Computes the given input to produce the corresponding output. + /// + /// + /// An input vector. + /// The + /// multi-class classification method to use. + /// The output of the machine. If this is a + /// probabilistic machine, the + /// output is the probability of the positive class. If this is + /// a standard machine, the output is the distance to the decision + /// hyperplane in feature space. + /// + /// The class decision for the given input. + /// + public int Compute(double[] inputs, MulticlassComputeMethod method, out double output) + { + if (method == MulticlassComputeMethod.Voting) + { + int[] votes; + return computeVoting(inputs, out votes, out output); + } + else + { + double[] responses; + return computeElimination(inputs, out responses, out output, null); + } + } + + /// + /// Computes the given input to produce the corresponding output. + /// + /// + /// An input vector. + /// The + /// multi-class classification method to use. + /// + /// The class decision for the given input. + /// + public int Compute(double[] inputs, MulticlassComputeMethod method) + { + double output; + return Compute(inputs, method, out output); + } + #endregion + + + #region Private Multi-class Decision + /// + /// Computes the given input to produce the corresponding output. + /// + /// + /// An input vector. + /// A vector containing the number of votes for each class. + /// The output of the machine. If this is a + /// probabilistic machine, the + /// output is the probability of the positive class. If this is + /// a standard machine, the output is the distance to the decision + /// hyperplane in feature space. + /// + /// The decision label for the given input. + /// + private int computeVoting(double[] inputs, out int[] votes, out double output) + { + // Compute decision by Voting + + // Get a list of the shared vectors (lazy) + int[][][] vectors = this.sharedVectors.Value; + + // Get the cache for this thread + Cache cache = createOrResetCache(); + + // out variables cannot be passed into delegates, + // so will be creating a copy for the vote array. + int[] voting = new int[Classes]; + + // For each class + Parallel.For(0, Classes, i => + { + // For each other class + for (int j = 0; j < i; j++) + { + double machineOutput; + + // Retrieve and compute the two-class problem for classes i x j + int answer = computeSequential(i, j, inputs, out machineOutput, cache); + + // Determine the winner class + int y = (answer == -1) ? i : j; + + // Increment votes for the winner + Interlocked.Increment(ref voting[y]); + } + }); + + // Voting finished. + votes = voting; + + // Select class which maximum number of votes + int imax; output = Matrix.Max(votes, out imax); + + // Determine output probability using no. of votes + output = output * (2.0 / (Classes * (Classes - 1))); + + return imax; // Return the winner as the output. + } + + /// + /// Computes the given input to produce the corresponding output. + /// + /// + /// + /// This method computes the decision for a one-against-one multiclass + /// support vector machine using the Directed Acyclic Graph method by + /// Platt, Cristianini and Shawe-Taylor. Details are given on the + /// original paper "Large Margin DAGs for Multiclass Classification", 2000. + /// + /// + /// An input vector. + /// The model response for each class. + /// The output of the machine. If this is a + /// probabilistic machine, the + /// output is the probability of the positive class. If this is + /// a standard machine, the output is the distance to the decision + /// hyperplane in feature space. + /// The decision path followed by the Decision + /// Directed Acyclic Graph used by the + /// elimination method. + /// + /// The decision label for the given input. + /// + private int computeElimination(double[] inputs, out double[] responses, + out double output, Tuple[] decisionPath) + { + // Compute decision by Directed Acyclic Graph + + // Get a list of the shared vectors + int[][][] vectors = this.sharedVectors.Value; + + // Get the cache for this thread + Cache cache = createOrResetCache(); + + output = 0; + + // Initialize metrics + responses = new double[Classes]; + bool probabilistic = IsProbabilistic; + + if (probabilistic) + { + for (int i = 0; i < responses.Length; i++) + responses[i] = 1.0; + } + + // Start with first and last classes + int classA = Classes - 1, classB = 0; + int progress = 0; + + // Navigate decision path + while (classA != classB) + { + + // Compute the two-class decision problem to decide for A x B + int answer = computeParallel(classA, classB, inputs, out output, cache); + + if (decisionPath != null) + decisionPath[progress++] = Tuple.Create(classA, classB); + + // Check who won and update + + if (answer == -1) + { + // The class A has won and class B has lost + + if (probabilistic) + { + // Decrease loser likelihood + responses[classB] *= output; + + // Increase for all other classes + for (int i = 0; i < responses.Length; i++) + if (i != classB) responses[i] *= 1.0 - output; + } + else + { + // Store the distance to the + // answer for the loser class + responses[classB] = -output; + } + + // Advance classB towards + // the middle of the list + classB++; + } + + else // answer == +1 + { + // The class A has lost and class B has won + + if (probabilistic) + { + // Decrease loser likelihood + responses[classA] *= 1.0 - output; + + // Increase for all other classes + for (int i = 0; i < responses.Length; i++) + if (i != classA) responses[i] *= output; + } + else + { + // Store the distance to the + // answer for the loser class + responses[classA] = output; + } + + // Advance classA towards + // the middle of the list + classA--; + } + } + + // At this point, classA = classB is the winner + if (!probabilistic) responses[classA] = output; + +#if DEBUG + else + { + int imax; responses.Max(out imax); + if (imax != classA) throw new Exception(); + } +#endif + + // Return output for winner class + output = responses[classA]; + + return classA; + } + + #endregion + + + #region Private Single machine Decision + /// + /// Compute SVM output with support vector sharing. + /// + /// + private int computeSequential(int classA, int classB, double[] input, out double output, Cache cache) + { + // Get the machine for this problem + KernelSupportVectorMachine machine = machines[classA - 1][classB]; + + // Get the vectors shared among all machines + int[] vectors = cache.Vectors[classA - 1][classB]; + double[] values = cache.Products; + + double sum = machine.Threshold; + + + if (machine.IsCompact) + { + // For linear machines, computation is simpler + for (int i = 0; i < machine.Weights.Length; i++) + sum += machine.Weights[i] * input[i]; + } + else + { + // For each support vector in the machine + for (int i = 0; i < vectors.Length; i++) + { + double value; + + // Check if it is a shared vector + int j = vectors[i]; + + if (j >= 0) + { + // This is a shared vector. Check + // if it has already been computed + + if (!Double.IsNaN(values[j])) + { + // Yes, it has. Retrieve the value from the cache + value = values[j]; + } + else + { + // No, it has not. Compute and store the computed value in the cache + value = values[j] = machine.Kernel.Function(machine.SupportVectors[i], input); + Interlocked.Increment(ref cache.Evaluations); + } + } + else + { + // This vector is not shared by any other machine. No need to cache + value = machine.Kernel.Function(machine.SupportVectors[i], input); + Interlocked.Increment(ref cache.Evaluations); + } + + sum += machine.Weights[i] * value; + } + } + + + // Produce probabilities if required + if (machine.IsProbabilistic) + { + output = machine.Link.Inverse(sum); + return output >= 0.5 ? +1 : -1; + } + else + { + output = sum; + return output >= 0 ? +1 : -1; + } + } + + /// + /// Compute SVM output with support vector sharing. + /// + /// + private int computeParallel(int classA, int classB, double[] input, out double output, Cache cache) + { + // Get the machine for this problem + KernelSupportVectorMachine machine = machines[classA - 1][classB]; + + // Get the vectors shared among all machines + int[] vectors = cache.Vectors[classA - 1][classB]; + + double[] values = cache.Products; +#if !NET35 + SpinLock[] locks = cache.SyncObjects; +#endif + double sum = machine.Threshold; + + + if (machine.IsCompact) + { + if (machine.Weights == null) + throw new Exception(); + + // For linear machines, computation is simpler + for (int i = 0; i < machine.Weights.Length; i++) + sum += machine.Weights[i] * input[i]; + } + else + { + +#if NET35 + #region Backward compatibility + for (int i = 0; i < vectors.Length; i++) + { + double value; + + // Check if it is a shared vector + int j = vectors[i]; + + if (j >= 0) + { + // This is a shared vector. Check + // if it has already been computed + + if (!Double.IsNaN(values[j])) + { + // Yes, it has. Retrieve the value from the cache + value = values[j]; + } + else + { + // No, it has not. Compute and store the computed value in the cache + value = values[j] = machine.Kernel.Function(machine.SupportVectors[i], input); + Interlocked.Increment(ref cache.Evaluations); + } + } + else + { + // This vector is not shared by any other machine. No need to cache + value = machine.Kernel.Function(machine.SupportVectors[i], input); + Interlocked.Increment(ref cache.Evaluations); + } + + sum += machine.Weights[i] * value; + } + #endregion +#else + // For each support vector in the machine + Parallel.For(0, vectors.Length, + + // Init + () => 0.0, + + // Map + (i, state, partialSum) => + { + double value; + + // Check if it is a shared vector + int j = vectors[i]; + + if (j >= 0) + { + // This is a shared vector. Check + // if it has already been computed + + bool taken = false; + locks[j].Enter(ref taken); + + if (!Double.IsNaN(values[j])) + { + // Yes, it has. Retrieve the value from the cache + value = values[j]; + } + else + { + // No, it has not. Compute and store the computed value in the cache + value = values[j] = machine.Kernel.Function(machine.SupportVectors[i], input); + Interlocked.Increment(ref cache.Evaluations); + } + + locks[j].Exit(); + } + else + { + // This vector is not shared by any other machine. No need to cache + value = machine.Kernel.Function(machine.SupportVectors[i], input); + Interlocked.Increment(ref cache.Evaluations); + } + + return partialSum + machine.Weights[i] * value; + }, + + // Reduce + (partialSum) => { lock (locks) sum += partialSum; } + ); +#endif + } + + // Produce probabilities if required + if (machine.IsProbabilistic) + { + output = machine.Link.Inverse(sum); + return output >= 0.5 ? +1 : -1; + } + else + { + output = sum; + return output >= 0 ? +1 : -1; + } + } + #endregion + + + + + + /// + /// Resets the cache and machine statistics + /// so they can be recomputed on next evaluation. + /// + /// + public void Reset() + { + if (this.vectorCache != null) + this.vectorCache.Dispose(); + + this.sharedVectors = null; + this.totalVectorsCount = null; + this.uniqueVectorsCount = null; + this.sharedVectorsCount = null; + + this.initialize(); + } + + /// + /// Gets the total kernel evaluations performed + /// in the last call to any of the + /// functions in the current thread. + /// + /// + /// The number of total kernel evaluations. + /// + public int GetLastKernelEvaluations() + { + return vectorCache.Value.Evaluations; + } + + + #region Loading & Saving + + /// + /// Saves the machine to a stream. + /// + /// + /// The stream to which the machine is to be serialized. + /// + public void Save(Stream stream) + { + BinaryFormatter b = new BinaryFormatter(); + b.Serialize(stream, this); + } + + /// + /// Saves the machine to a file. + /// + /// + /// The path to the file to which the machine is to be serialized. + /// + public void Save(string path) + { + using (FileStream fs = new FileStream(path, FileMode.Create)) + { + Save(fs); + } + } + + /// + /// Loads a machine from a stream. + /// + /// + /// The stream from which the machine is to be deserialized. + /// + /// The deserialized machine. + /// + public static MulticlassSupportVectorMachine Load(Stream stream) + { + BinaryFormatter b = new BinaryFormatter(); + return (MulticlassSupportVectorMachine)b.Deserialize(stream); + } + + /// + /// Loads a machine from a file. + /// + /// + /// The path to the file from which the machine is to be deserialized. + /// + /// The deserialized machine. + /// + public static MulticlassSupportVectorMachine Load(string path) + { + using (FileStream fs = new FileStream(path, FileMode.Open)) + { + return Load(fs); + } + } + + [OnDeserialized] + private void onDeserialized(StreamingContext context) + { + initialize(); + } + #endregion + + #region IEnumerable members + /// + /// Returns an enumerator that iterates through all machines + /// contained inside this multi-class support vector machine. + /// + /// + public IEnumerator, KernelSupportVectorMachine>> GetEnumerator() + { + for (int i = 0; i < machines.Length; i++) + { + for (int j = 0; j < machines[i].Length; j++) + { + yield return new KeyValuePair, KernelSupportVectorMachine>( + Tuple.Create(i + 1, j), machines[i][j]); + } + } + } + + /// + /// Returns an enumerator that iterates through all machines + /// contained inside this multi-class support vector machine. + /// + /// + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + #endregion + + #region IDisposable members + /// + /// Performs application-defined tasks associated with + /// freeing, releasing, or resetting unmanaged resources. + /// + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Releases unmanaged and - optionally - managed resources + /// + /// + /// + /// true to release both managed and unmanaged resources; + /// false to release only unmanaged resources. + /// + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + // free managed resources + if (vectorCache != null) + { + vectorCache.Dispose(); + vectorCache = null; + } + } + } + #endregion + + + + #region Cache + private Cache createOrResetCache() + { + Cache cache = vectorCache.Value; + + // First of all, check if the shared vectors in this machine + // already have been identified. If they don't, identify them. + + cache.Vectors = sharedVectors.Value; // use lazy instantiation + int vectorCount = SupportVectorSharedCount; + + // Now, check if a cache has already been created for this + // thread and has adequate size. If it has not, create it. + + if (cache.Products == null || cache.Products.Length < vectorCount) + { + // The cache has not been created + cache.Products = new double[vectorCount]; + +#if !NET35 // Create synchronization objects + cache.SyncObjects = new SpinLock[vectorCount]; + for (int i = 0; i < cache.SyncObjects.Length; i++) + cache.SyncObjects[i] = new SpinLock(); +#endif + } + + // Initialize (or reset) the cache. A value of Not-a-Number + // indicates that the value of corresponding vector has not + // been computed yet. + for (int i = 0; i < cache.Products.Length; i++) + cache.Products[i] = Double.NaN; + + + cache.Evaluations = 0; + + return cache; + } + + + private int[][][] computeSharedVectors() + { + // This method should only be called once after the machine has + // been learned. If the inner machines or they Support Vectors + // change, this method will need to be recomputed. + + // Detect all vectors which are being shared along the machines + var shared = new Dictionary>>(); + + // for all machines + for (int i = 0; i < machines.Length; i++) + { + for (int j = 0; j < machines[i].Length; j++) + { + // if the machine is not in compact form + if (machines[i][j].SupportVectors != null) + { + // register the support vector on the shared cache collection + for (int k = 0; k < machines[i][j].SupportVectors.Length; k++) + { + double[] sv = machines[i][j].SupportVectors[k]; + + List> count; + bool success = shared.TryGetValue(sv, out count); + + if (success) + { + // Value is already in the dictionary + count.Add(Tuple.Create(i, j, k)); + } + else + { + count = new List>(); + count.Add(Tuple.Create(i, j, k)); + shared[sv] = count; + } + } + } + } + } + + // Create a table of indices for shared vectors + int idx = 0; + + var indices = new Dictionary(); + foreach (double[] sv in shared.Keys) + indices[sv] = idx++; + + // Create a lookup table for the machines + int[][][] sharedVectors = new int[machines.Length][][]; + for (int i = 0; i < sharedVectors.Length; i++) + { + sharedVectors[i] = new int[machines[i].Length][]; + for (int j = 0; j < sharedVectors[i].Length; j++) + { + if (machines[i][j].SupportVectors != null) + { + sharedVectors[i][j] = new int[machines[i][j].SupportVectors.Length]; + + for (int k = 0; k < machines[i][j].SupportVectors.Length; k++) + { + double[] sv = machines[i][j].SupportVectors[k]; + if (shared.ContainsKey(sv)) + sharedVectors[i][j][k] = indices[sv]; + else + sharedVectors[i][j][k] = -1; + } + } + } + } + + sharedVectorsCount = shared.Count; + return sharedVectors; + } + + private class Cache + { + public int Evaluations; + public double[] Products; + public int[][][] Vectors; +#if !NET35 + public SpinLock[] SyncObjects; +#endif + } + + #endregion + + } +} diff --git a/Sources/Accord.Math/AForge/ContinuousHistogram.cs b/Sources/Accord.Math/AForge/ContinuousHistogram.cs new file mode 100644 index 0000000000..eba999f96 --- /dev/null +++ b/Sources/Accord.Math/AForge/ContinuousHistogram.cs @@ -0,0 +1,334 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Math +{ + using System; + + /// + /// Histogram for continuous random values. + /// + /// + /// The class wraps histogram for continuous stochastic function, which is represented + /// by integer array and range of the function. Values of the integer array are treated + /// as total amount of hits on the corresponding subranges, which are calculated by splitting the + /// specified range into required amount of consequent ranges. + /// + /// For example, if the integer array is equal to { 1, 2, 4, 8, 16 } and the range is set + /// to [0, 1], then the histogram consists of next subranges: + /// + /// [0.0, 0.2] - 1 hit; + /// [0.2, 0.4] - 2 hits; + /// [0.4, 0.6] - 4 hits; + /// [0.6, 0.8] - 8 hits; + /// [0.8, 1.0] - 16 hits. + /// + /// + /// + /// Sample usage: + /// + /// // create histogram + /// ContinuousHistogram histogram = new ContinuousHistogram( + /// new int[] { 0, 0, 8, 4, 2, 4, 7, 1, 0 }, new Range( 0.0f, 1.0f ) ); + /// // get mean and standard deviation values + /// Console.WriteLine( "mean = " + histogram.Mean + ", std.dev = " + histogram.StdDev ); + /// + /// + /// + [Serializable] + public class ContinuousHistogram + { + private int[] values; + private Range range; + + private float mean; + private float stdDev; + private float median; + private float min; + private float max; + private int total; + + /// + /// Values of the histogram. + /// + /// + public int[] Values + { + get { return values; } + } + + /// + /// Range of random values. + /// + /// + public Range Range + { + get { return range; } + } + + /// + /// Mean value. + /// + /// + /// The property allows to retrieve mean value of the histogram. + /// + /// Sample usage: + /// + /// // create histogram + /// ContinuousHistogram histogram = new ContinuousHistogram( + /// new int[] { 0, 0, 8, 4, 2, 4, 7, 1, 0 }, new Range( 0.0f, 1.0f ) ); + /// // get mean value (= 0.505 ) + /// Console.WriteLine( "mean = " + histogram.Mean.ToString( "F3" ) ); + /// + /// + /// + public float Mean + { + get { return mean; } + } + + /// + /// Standard deviation. + /// + /// + /// The property allows to retrieve standard deviation value of the histogram. + /// + /// Sample usage: + /// + /// // create histogram + /// ContinuousHistogram histogram = new ContinuousHistogram( + /// new int[] { 0, 0, 8, 4, 2, 4, 7, 1, 0 }, new Range( 0.0f, 1.0f ) ); + /// // get std.dev. value (= 0.215) + /// Console.WriteLine( "std.dev. = " + histogram.StdDev.ToString( "F3" ) ); + /// + /// + /// + public float StdDev + { + get { return stdDev; } + } + + /// + /// Median value. + /// + /// + /// The property allows to retrieve median value of the histogram. + /// + /// Sample usage: + /// + /// // create histogram + /// ContinuousHistogram histogram = new ContinuousHistogram( + /// new int[] { 0, 0, 8, 4, 2, 4, 7, 1, 0 }, new Range( 0.0f, 1.0f ) ); + /// // get median value (= 0.500) + /// Console.WriteLine( "median = " + histogram.Median.ToString( "F3" ) ); + /// + /// + /// + public float Median + { + get { return median; } + } + + /// + /// Minimum value. + /// + /// + /// The property allows to retrieve minimum value of the histogram with non zero + /// hits count. + /// + /// Sample usage: + /// + /// // create histogram + /// ContinuousHistogram histogram = new ContinuousHistogram( + /// new int[] { 0, 0, 8, 4, 2, 4, 7, 1, 0 }, new Range( 0.0f, 1.0f ) ); + /// // get min value (= 0.250) + /// Console.WriteLine( "min = " + histogram.Min.ToString( "F3" ) ); + /// + /// + public float Min + { + get { return min; } + } + + /// + /// Maximum value. + /// + /// + /// The property allows to retrieve maximum value of the histogram with non zero + /// hits count. + /// + /// Sample usage: + /// + /// // create histogram + /// ContinuousHistogram histogram = new ContinuousHistogram( + /// new int[] { 0, 0, 8, 4, 2, 4, 7, 1, 0 }, new Range( 0.0f, 1.0f ) ); + /// // get max value (= 0.875) + /// Console.WriteLine( "max = " + histogram.Max.ToString( "F3" ) ); + /// + /// + /// + public float Max + { + get { return max; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Values of the histogram. + /// Range of random values. + /// + /// Values of the integer array are treated as total amount of hits on the + /// corresponding subranges, which are calculated by splitting the specified range into + /// required amount of consequent ranges (see class + /// description for more information). + /// + /// + public ContinuousHistogram( int[] values, Range range ) + { + this.values = values; + this.range = range; + + Update( ); + } + + /// + /// Get range around median containing specified percentage of values. + /// + /// + /// Values percentage around median. + /// + /// Returns the range which containes specifies percentage of values. + /// + /// The method calculates range of stochastic variable, which summary probability + /// comprises the specified percentage of histogram's hits. + /// + /// Sample usage: + /// + /// // create histogram + /// ContinuousHistogram histogram = new ContinuousHistogram( + /// new int[] { 0, 0, 8, 4, 2, 4, 7, 1, 0 }, new Range( 0.0f, 1.0f ) ); + /// // get 50% range + /// Range range = histogram.GetRange( 0.5f ); + /// // show the range ([0.25, 0.75]) + /// Console.WriteLine( "50% range = [" + range.Min + ", " + range.Max + "]" ); + /// + /// + /// + public Range GetRange( float percent ) + { + int min, max, hits; + int h = (int) ( total * ( percent + ( 1 - percent ) / 2 ) ); + int n = values.Length; + int nM1 = n - 1; + + // skip left portion + for ( min = 0, hits = total; min < n; min++ ) + { + hits -= values[min]; + if ( hits < h ) + break; + } + // skip right portion + for ( max = nM1, hits = total; max >= 0; max-- ) + { + hits -= values[max]; + if ( hits < h ) + break; + } + // return range between left and right boundaries + return new Range( + ( (float) min / nM1 ) * range.Length + range.Min, + ( (float) max / nM1 ) * range.Length + range.Min ); + } + + /// + /// Update statistical value of the histogram. + /// + /// + /// The method recalculates statistical values of the histogram, like mean, + /// standard deviation, etc. The method should be called only in the case if histogram + /// values were retrieved through property and updated after that. + /// + /// + public void Update( ) + { + int hits; + int i, n = values.Length; + int nM1 = n - 1; + + float rangeLength = range.Length; + float rangeMin = range.Min; + + max = 0; + min = n; + mean = 0; + stdDev = 0; + total = 0; + + double sum = 0; + + // calculate mean, min, max + for ( i = 0; i < n; i++ ) + { + hits = values[i]; + + if ( hits != 0 ) + { + // max + if ( i > max ) + max = i; + // min + if ( i < min ) + min = i; + } + + // accumulate total value + total += hits; + // accumulate mean value + sum += ( ( (double) i / nM1 ) * rangeLength + rangeMin ) * hits; + } + + if ( total != 0 ) + { + mean = (float) ( sum / total ); + } + + min = ( min / nM1 ) * rangeLength + rangeMin; + max = ( max / nM1 ) * rangeLength + rangeMin; + + // calculate stadard deviation + sum = 0; + double diff; + + for ( i = 0; i < n; i++ ) + { + hits = values[i]; + diff = ( ( (double) i / nM1 ) * rangeLength + rangeMin ) - mean; + sum += diff * diff * hits; + } + + if ( total != 0 ) + { + stdDev = (float) Math.Sqrt( sum / total ); + } + + // calculate median + int m, halfTotal = total / 2; + + for ( m = 0, hits = 0; m < n; m++ ) + { + hits += values[m]; + if ( hits >= halfTotal ) + break; + } + median = ( (float) m / nM1 ) * rangeLength + rangeMin; + } + } +} diff --git a/Sources/Accord.Math/AForge/FourierTransform.cs b/Sources/Accord.Math/AForge/FourierTransform.cs new file mode 100644 index 0000000000..378c38f36 --- /dev/null +++ b/Sources/Accord.Math/AForge/FourierTransform.cs @@ -0,0 +1,390 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// +// FFT idea from Exocortex.DSP library +// http://www.exocortex.org/dsp/ +// + +namespace AForge.Math +{ + using System; + using System.Numerics; + + /// + /// Fourier transformation. + /// + /// + /// The class implements one dimensional and two dimensional + /// Discrete and Fast Fourier Transformation. + /// + public static class FourierTransform + { + /// + /// Fourier transformation direction. + /// + public enum Direction + { + /// + /// Forward direction of Fourier transformation. + /// + /// + Forward = 1, + + /// + /// Backward direction of Fourier transformation. + /// + /// + Backward = -1 + }; + + /// + /// One dimensional Discrete Fourier Transform. + /// + /// + /// Data to transform. + /// Transformation direction. + /// + public static void DFT(Complex[] data, Direction direction) + { + int n = data.Length; + double arg, cos, sin; + var dst = new Complex[n]; + + // for each destination element + for (int i = 0; i < dst.Length; i++) + { + dst[i] = Complex.Zero; + + arg = -(int)direction * 2.0 * System.Math.PI * (double)i / (double)n; + + // sum source elements + for (int j = 0; j < data.Length; j++) + { + cos = System.Math.Cos(j * arg); + sin = System.Math.Sin(j * arg); + + double re = data[j].Real * cos - data[j].Imaginary * sin; + double im = data[j].Real * sin + data[j].Imaginary * cos; + + dst[i] += new Complex(re, im); + } + } + + // copy elements + if (direction == Direction.Forward) + { + // devide also for forward transform + for (int i = 0; i < data.Length; i++) + data[i] /= n; + } + else + { + for (int i = 0; i < data.Length; i++) + data[i] = dst[i]; + } + } + + /// + /// Two dimensional Discrete Fourier Transform. + /// + /// + /// Data to transform. + /// Transformation direction. + /// + public static void DFT2(Complex[,] data, Direction direction) + { + int n = data.GetLength(0); // rows + int m = data.GetLength(1); // columns + double arg, cos, sin; + var dst = new Complex[System.Math.Max(n, m)]; + + // process rows + for (int i = 0; i < n; i++) + { + for (int j = 0; j < dst.Length; j++) + { + dst[j] = Complex.Zero; + + arg = -(int)direction * 2.0 * System.Math.PI * (double)j / (double)m; + + // sum source elements + for (int k = 0; k < m; k++) + { + cos = System.Math.Cos(k * arg); + sin = System.Math.Sin(k * arg); + + double re = data[i, k].Real * cos - data[i, k].Imaginary * sin; + double im = data[i, k].Real * sin + data[i, k].Imaginary * cos; + + dst[j] += new Complex(re, im); + } + } + + // copy elements + if (direction == Direction.Forward) + { + // devide also for forward transform + for (int j = 0; j < dst.Length; j++) + data[i, j] = dst[j] / m; + } + else + { + for (int j = 0; j < dst.Length; j++) + data[i, j] = dst[j]; + } + } + + // process columns + for (int j = 0; j < m; j++) + { + for (int i = 0; i < n; i++) + { + dst[i] = Complex.Zero; + + arg = -(int)direction * 2.0 * System.Math.PI * (double)i / (double)n; + + // sum source elements + for (int k = 0; k < n; k++) + { + cos = System.Math.Cos(k * arg); + sin = System.Math.Sin(k * arg); + + double re = data[k, j].Real * cos - data[k, j].Imaginary * sin; + double im = data[k, j].Real * sin + data[k, j].Imaginary * cos; + + dst[i] += new Complex(re, im); + } + } + + // copy elements + if (direction == Direction.Forward) + { + // devide also for forward transform + for (int i = 0; i < dst.Length; i++) + data[i, j] = dst[i] / n; + } + else + { + for (int i = 0; i < dst.Length; i++) + data[i, j] = dst[i]; + } + } + } + + + /// + /// One dimensional Fast Fourier Transform. + /// + /// + /// Data to transform. + /// Transformation direction. + /// + /// The method accepts array of 2n size + /// only, where n may vary in the [1, 14] range. + /// + /// Incorrect data length. + /// + public static void FFT(Complex[] data, Direction direction) + { + int n = data.Length; + int m = Tools.Log2(n); + + // reorder data first + ReorderData(data); + + // compute FFT + int tn = 1, tm; + + for (int k = 1; k <= m; k++) + { + Complex[] rotation = FourierTransform.GetComplexRotation(k, direction); + + tm = tn; + tn <<= 1; + + for (int i = 0; i < tm; i++) + { + Complex t = rotation[i]; + + for (int even = i; even < n; even += tn) + { + int odd = even + tm; + Complex ce = data[even]; + Complex co = data[odd]; + + double tr = co.Real * t.Real - co.Imaginary * t.Imaginary; + double ti = co.Real * t.Imaginary + co.Imaginary * t.Real; + + data[even] += new Complex(tr, ti); + data[odd] = new Complex(ce.Real - tr, ce.Imaginary - ti); + } + } + } + + if (direction == Direction.Forward) + { + for (int i = 0; i < data.Length; i++) + data[i] /= (double)n; + } + } + + /// + /// Two dimensional Fast Fourier Transform. + /// + /// + /// Data to transform. + /// Transformation direction. + /// + /// The method accepts array of 2n size + /// only in each dimension, where n may vary in the [1, 14] range. For example, 16x16 array + /// is valid, but 15x15 is not. + /// + /// Incorrect data length. + /// + public static void FFT2(Complex[,] data, Direction direction) + { + int k = data.GetLength(0); + int n = data.GetLength(1); + + // check data size + if (!Tools.IsPowerOf2(k) || !Tools.IsPowerOf2(n)) + throw new ArgumentException("The matrix rows and columns must be a power of 2."); + + if (k < minLength || k > maxLength || n < minLength || n > maxLength) + throw new ArgumentException("Incorrect data length."); + + // process rows + var row = new Complex[n]; + + for (int i = 0; i < k; i++) + { + // copy row + for (int j = 0; j < row.Length; j++) + row[j] = data[i, j]; + + // transform it + FourierTransform.FFT(row, direction); + + // copy back + for (int j = 0; j < row.Length; j++) + data[i, j] = row[j]; + } + + // process columns + var col = new Complex[k]; + + for (int j = 0; j < n; j++) + { + // copy column + for (int i = 0; i < k; i++) + col[i] = data[i, j]; + + // transform it + FourierTransform.FFT(col, direction); + + // copy back + for (int i = 0; i < k; i++) + data[i, j] = col[i]; + } + } + + #region Private Region + + private const int minLength = 2; + private const int maxLength = 16384; + private const int minBits = 1; + private const int maxBits = 14; + private static int[][] reversedBits = new int[maxBits][]; + private static Complex[,][] complexRotation = new Complex[maxBits, 2][]; + + // Get array, indicating which data members should be swapped before FFT + private static int[] GetReversedBits(int numberOfBits) + { + if ((numberOfBits < minBits) || (numberOfBits > maxBits)) + throw new ArgumentOutOfRangeException(); + + // check if the array is already calculated + if (reversedBits[numberOfBits - 1] == null) + { + int n = Tools.Pow2(numberOfBits); + int[] rBits = new int[n]; + + // calculate the array + for (int i = 0; i < n; i++) + { + int oldBits = i; + int newBits = 0; + + for (int j = 0; j < numberOfBits; j++) + { + newBits = (newBits << 1) | (oldBits & 1); + oldBits = (oldBits >> 1); + } + rBits[i] = newBits; + } + reversedBits[numberOfBits - 1] = rBits; + } + return reversedBits[numberOfBits - 1]; + } + + // Get rotation of complex number + private static Complex[] GetComplexRotation(int numberOfBits, Direction direction) + { + int directionIndex = (direction == Direction.Forward) ? 0 : 1; + + // check if the array is already calculated + if (complexRotation[numberOfBits - 1, directionIndex] == null) + { + int n = 1 << (numberOfBits - 1); + double uR = 1.0; + double uI = 0.0; + double angle = System.Math.PI / n * (int)direction; + double wR = System.Math.Cos(angle); + double wI = System.Math.Sin(angle); + double t; + Complex[] rotation = new Complex[n]; + + for (int i = 0; i < n; i++) + { + rotation[i] = new Complex(uR, uI); + t = uR * wI + uI * wR; + uR = uR * wR - uI * wI; + uI = t; + } + + complexRotation[numberOfBits - 1, directionIndex] = rotation; + } + return complexRotation[numberOfBits - 1, directionIndex]; + } + + // Reorder data for FFT using + private static void ReorderData(Complex[] data) + { + int len = data.Length; + + // check data length + if ((len < minLength) || (len > maxLength) || (!Tools.IsPowerOf2(len))) + throw new ArgumentException("Incorrect data length."); + + int[] rBits = GetReversedBits(Tools.Log2(len)); + + for (int i = 0; i < len; i++) + { + int s = rBits[i]; + + if (s > i) + { + Complex t = data[i]; + data[i] = data[s]; + data[s] = t; + } + } + } + + #endregion + } +} diff --git a/Sources/Accord.Math/AForge/Gaussian.cs b/Sources/Accord.Math/AForge/Gaussian.cs new file mode 100644 index 0000000000..cd717f397 --- /dev/null +++ b/Sources/Accord.Math/AForge/Gaussian.cs @@ -0,0 +1,189 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Math +{ + using System; + + /// + /// Gaussian function. + /// + /// + /// The class is used to calculate 1D and 2D Gaussian functions for + /// specified (s) value: + /// + /// + /// 1-D: f(x) = exp( x * x / ( -2 * s * s ) ) / ( s * sqrt( 2 * PI ) ) + /// + /// 2-D: f(x, y) = exp( x * x + y * y / ( -2 * s * s ) ) / ( s * s * 2 * PI ) + /// + /// + /// + /// + public class Gaussian + { + // sigma value + private double sigma = 1.0; + // squared sigma + private double sqrSigma = 1.0; + + /// + /// Sigma value. + /// + /// + /// Sigma property of Gaussian function. + /// + /// Default value is set to 1. Minimum allowed value is 0.00000001. + /// + /// + public double Sigma + { + get { return sigma; } + set + { + sigma = Math.Max( 0.00000001, value ); + sqrSigma = sigma * sigma; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public Gaussian( ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Sigma value. + /// + public Gaussian( double sigma ) + { + Sigma = sigma; + } + + /// + /// 1-D Gaussian function. + /// + /// + /// x value. + /// + /// Returns function's value at point . + /// + /// The function calculates 1-D Gaussian function: + /// + /// + /// f(x) = exp( x * x / ( -2 * s * s ) ) / ( s * sqrt( 2 * PI ) ) + /// + /// + /// + public double Function( double x ) + { + return Math.Exp( x * x / ( -2 * sqrSigma ) ) / ( Math.Sqrt( 2 * Math.PI ) * sigma ); + } + + /// + /// 2-D Gaussian function. + /// + /// + /// x value. + /// y value. + /// + /// Returns function's value at point (, ). + /// + /// The function calculates 2-D Gaussian function: + /// + /// + /// f(x, y) = exp( x * x + y * y / ( -2 * s * s ) ) / ( s * s * 2 * PI ) + /// + /// + /// + public double Function2D( double x, double y ) + { + return Math.Exp( ( x * x + y * y ) / ( -2 * sqrSigma ) ) / ( 2 * Math.PI * sqrSigma ); + } + + /// + /// 1-D Gaussian kernel. + /// + /// + /// Kernel size (should be odd), [3, 101]. + /// + /// Returns 1-D Gaussian kernel of the specified size. + /// + /// The function calculates 1-D Gaussian kernel, which is array + /// of Gaussian function's values in the [-r, r] range of x value, where + /// r=floor(/2). + /// + /// + /// Wrong kernel size. + /// + public double[] Kernel( int size ) + { + // check for evem size and for out of range + if ( ( ( size % 2 ) == 0 ) || ( size < 3 ) || ( size > 101 ) ) + { + throw new ArgumentException( "Wrong kernal size." ); + } + + // raduis + int r = size / 2; + // kernel + double[] kernel = new double[size]; + + // compute kernel + for ( int x = -r, i = 0; i < size; x++, i++ ) + { + kernel[i] = Function( x ); + } + + return kernel; + } + + /// + /// 2-D Gaussian kernel. + /// + /// + /// Kernel size (should be odd), [3, 101]. + /// + /// Returns 2-D Gaussian kernel of specified size. + /// + /// The function calculates 2-D Gaussian kernel, which is array + /// of Gaussian function's values in the [-r, r] range of x,y values, where + /// r=floor(/2). + /// + /// + /// Wrong kernel size. + /// + public double[,] Kernel2D( int size ) + { + // check for evem size and for out of range + if ( ( ( size % 2 ) == 0 ) || ( size < 3 ) || ( size > 101 ) ) + { + throw new ArgumentException( "Wrong kernal size." ); + } + + // raduis + int r = size / 2; + // kernel + double[,] kernel = new double[size, size]; + + // compute kernel + for ( int y = -r, i = 0; i < size; y++, i++ ) + { + for ( int x = -r, j = 0; j < size; x++, j++ ) + { + kernel[i, j] = Function2D( x, y ); + } + } + + return kernel; + } + } +} diff --git a/Sources/Accord.Math/AForge/Geometry/ClosePointsMergingOptimizer.cs b/Sources/Accord.Math/AForge/Geometry/ClosePointsMergingOptimizer.cs new file mode 100644 index 0000000000..f8137bd9d --- /dev/null +++ b/Sources/Accord.Math/AForge/Geometry/ClosePointsMergingOptimizer.cs @@ -0,0 +1,137 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Math.Geometry +{ + using System; + using System.Collections.Generic; + using AForge; + + /// + /// Shape optimizer, which merges points within close distance to each other. + /// + /// + /// This shape optimizing algorithm checks all points of a shape + /// and merges any two points which are within specified distance + /// to each other. Two close points are replaced by a single point, which has + /// mean coordinates of the removed points. + /// + /// Because of the fact that the algorithm performs points merging + /// while it goes through a shape, it may merge several points (more than 2) into a + /// single point, where distance between extreme points may be bigger + /// than the specified limit. For example, suppose + /// a case with 3 points, where 1st and 2nd points are close enough to be merged, but the + /// 3rd point is a little bit further. During merging of 1st and 2nd points, it may + /// happen that the new point with mean coordinates will get closer to the 3rd point, + /// so they will be merged also on next iteration of the algorithm. + /// + /// + /// For example, the below circle shape comprised of 65 points, can be optimized to 8 points + /// by setting to 28.
+ /// + ///
+ ///
+ /// + public class ClosePointsMergingOptimizer : IShapeOptimizer + { + private float maxDistanceToMerge = 10; + + /// + /// Maximum allowed distance between points, which are merged during optimization, [0, ∞). + /// + /// + /// The property sets maximum allowed distance between two points of + /// a shape, which are replaced by single point with mean coordinates. + /// + /// Default value is set to 10. + /// + public float MaxDistanceToMerge + { + get { return maxDistanceToMerge; } + set { maxDistanceToMerge = Math.Max( 0, value ); } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public ClosePointsMergingOptimizer( ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Maximum allowed distance between points, which are + /// merged during optimization (see ). + /// + public ClosePointsMergingOptimizer( float maxDistanceToMerge ) + { + this.maxDistanceToMerge = maxDistanceToMerge; + } + + /// + /// Optimize specified shape. + /// + /// + /// Shape to be optimized. + /// + /// Returns final optimized shape, which may have reduced amount of points. + /// + public List OptimizeShape( List shape ) + { + // optimized shape + List optimizedShape = new List( ); + + if ( shape.Count <= 3 ) + { + // do nothing if shape has 3 points or less + optimizedShape.AddRange( shape ); + } + else + { + float distance = 0; + + // add first point to the new shape + optimizedShape.Add( shape[0] ); + int pointsInOptimizedHull = 1; + + for ( int i = 1, n = shape.Count; i < n; i++ ) + { + distance = optimizedShape[pointsInOptimizedHull - 1].DistanceTo( shape[i] ); + + if ( ( distance <= maxDistanceToMerge ) && + ( pointsInOptimizedHull + ( n - i ) > 3 ) ) + { + // merge + optimizedShape[pointsInOptimizedHull - 1] = ( optimizedShape[pointsInOptimizedHull - 1] + shape[i] ) / 2; + } + else + { + optimizedShape.Add( shape[i] ); + pointsInOptimizedHull++; + } + } + + if ( pointsInOptimizedHull > 3 ) + { + // check the last and first points + distance = optimizedShape[pointsInOptimizedHull - 1].DistanceTo( optimizedShape[0] ); + + if ( distance <= maxDistanceToMerge ) + { + // merge + optimizedShape[0] = ( optimizedShape[pointsInOptimizedHull - 1] + optimizedShape[0] ) / 2; + optimizedShape.RemoveAt( pointsInOptimizedHull - 1 ); + } + } + } + + return optimizedShape; + } + } +} diff --git a/Sources/Accord.Math/AForge/Geometry/CoplanarPosit.cs b/Sources/Accord.Math/AForge/Geometry/CoplanarPosit.cs new file mode 100644 index 0000000000..ec45f3d57 --- /dev/null +++ b/Sources/Accord.Math/AForge/Geometry/CoplanarPosit.cs @@ -0,0 +1,505 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Math.Geometry +{ + using System; + using AForge; + using AForge.Math; + + /// + /// 3D pose estimation algorithm (coplanar case). + /// + /// + /// The class implements an algorithm for 3D object's pose estimation from it's + /// 2D coordinates obtained by perspective projection, when the object is described coplanar points. + /// The idea of the implemented math and algorithm is described in "Iterative Pose Estimation using + /// Coplanar Feature Points" paper written by Oberkampf, Daniel DeMenthon and Larry Davis + /// (the implementation of the algorithm is very close translation of the pseudo code given by the + /// paper, so should be easy to follow). + /// + /// At this point the implementation works only with models described by 4 points, which is + /// the minimum number of points enough for 3D pose estimation. + /// + /// The 4 model's point are supposed to be coplanar, i.e. supposed to reside all within + /// same planer. See for none coplanar case. + /// + /// Read 3D Pose Estimation article for + /// additional information and samples. + /// + /// Sample usage: + /// + /// // points of real object - model + /// Vector3[] copositObject = new Vector3[4] + /// { + /// new Vector3( -56.5f, 0, 56.5f ), + /// new Vector3( 56.5f, 0, 56.5f ), + /// new Vector3( 56.5f, 0, -56.5f ), + /// new Vector3( -56.5f, 0, -56.5f ), + /// }; + /// // focal length of camera used to capture the object + /// float focalLength = 640; // depends on your camera or projection system + /// // initialize CoPOSIT object + /// CoplanarPosit coposit = new CoplanarPosit( copositObject, focalLength ); + /// + /// // 2D points of te object - projection + /// AForge.Point[] projectedPoints = new AForge.Point[4] + /// { + /// new AForge.Point( -77, 48 ), + /// new AForge.Point( 44, 66 ), + /// new AForge.Point( 75, -36 ), + /// new AForge.Point( -61, -58 ), + /// }; + /// // estimate pose + /// Matrix3x3 rotationMatrix; + /// Vector3 translationVector; + /// coposit.EstimatePose( projectedPoints, + /// out rotationMatrix, out translationVector ); + /// + /// + /// + /// + /// + public class CoplanarPosit + { + // camera's focal length + private float focalLength; + + // points of the model to estimate position for + private Vector3[] modelPoints; + // 3 vectors of the model kept as a matrix + private Matrix3x3 modelVectors; + // pseudoinverse of the model vectors matrix + private Matrix3x3 modelPseudoInverse; + // unit normal to the model + private Vector3 modelNormal; + + private Matrix3x3 alternateRotation = new Matrix3x3( ); + private Vector3 alternateTranslation = new Vector3( ); + private float alternatePoseError = 0; + + private Matrix3x3 bestRotation = new Matrix3x3( ); + private Vector3 bestTranslation = new Vector3( ); + private float bestPoseError = 0; + + /// + /// Best estimated pose recently found. + /// + /// + /// The property keeps best estimated pose found by the latest call to . + /// The same estimated pose is provided by that method also and can be accessed through this property + /// for convenience. + /// + /// See also and . + /// + /// + public Matrix3x3 BestEstimatedRotation + { + get { return bestRotation; } + } + + /// + /// Best estimated translation recently found. + /// + /// + /// The property keeps best estimated translation found by the latest call to . + /// The same estimated translation is provided by that method also and can be accessed through this property + /// for convenience. + /// + /// See also and . + /// + /// + public Vector3 BestEstimatedTranslation + { + get { return bestTranslation; } + } + + /// + /// Error of the best pose estimation. + /// + /// + /// The property keeps error of the best pose estimation, which is calculated as average + /// error between real angles of the specified quadrilateral and angles of the quadrilateral which + /// is a projection of the best pose estimation. The error is measured degrees in (angle). + /// + /// + public float BestEstimationError + { + get { return bestPoseError; } + } + + /// + /// Alternate estimated pose recently found. + /// + /// + /// The property keeps alternate estimated pose found by the latest call to . + /// + /// See also and . + /// + /// + public Matrix3x3 AlternateEstimatedRotation + { + get { return alternateRotation; } + } + + /// + /// Alternated estimated translation recently found. + /// + /// + /// The property keeps alternate estimated translation found by the latest call to . + /// + /// See also and . + /// + /// + public Vector3 AlternateEstimatedTranslation + { + get { return alternateTranslation; } + } + + /// + /// Error of the alternate pose estimation. + /// + /// + /// The property keeps error of the alternate pose estimation, which is calculated as average + /// error between real angles of the specified quadrilateral and angles of the quadrilateral which + /// is a projection of the alternate pose estimation. The error is measured in degrees (angle). + /// + /// + public float AlternateEstimationError + { + get { return alternatePoseError; } + } + + /// + /// Coordinates of the model points which pose should be estimated. + /// + public Vector3[] Model + { + get { return (Vector3[]) modelPoints.Clone( ); } + } + + /// + /// Effective focal length of the camera used to capture the model. + /// + public float FocalLength + { + get { return focalLength; } + set { focalLength = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Array of vectors containing coordinates of four real model's point. + /// Effective focal length of the camera used to capture the model. + /// + /// The model must have 4 points. + /// + public CoplanarPosit( Vector3[] model, float focalLength ) + { + if ( model.Length != 4 ) + { + throw new ArgumentException( "The model must have 4 points." ); + } + + this.focalLength = focalLength; + modelPoints = (Vector3[]) model.Clone( ); + + // compute model vectors + modelVectors = Matrix3x3.CreateFromRows( + model[1] - model[0], + model[2] - model[0], + model[3] - model[0] ); + + // compute pseudo inverse of the model matrix + Matrix3x3 u, v; + Vector3 e; + + modelVectors.SVD( out u, out e, out v ); + modelPseudoInverse = v * Matrix3x3.CreateDiagonal( e.Inverse( ) ) * u.Transpose( ); + + // computer unit vector normal to the model + modelNormal = v.GetColumn( e.MinIndex ); + } + + /// + /// Estimate pose of a model from it's projected 2D coordinates. + /// + /// + /// 4 2D points of the model's projection. + /// Gets best estimation of object's rotation. + /// Gets best estimation of object's translation. + /// + /// 4 points must be be given for pose estimation. + /// + /// Because of the Coplanar POSIT algorithm's nature, it provides two pose estimations, + /// which are valid from the algorithm's math point of view. For each pose an error is calculated, + /// which specifies how good estimation fits to the specified real 2D coordinated. The method + /// provides the best estimation through its output parameters and + /// . This may be enough for many of the pose estimation application. + /// For those, who require checking the alternate pose estimation, it can be obtained using + /// and properties. + /// The calculated error is provided for both estimations through and + /// properties. + /// + /// + public void EstimatePose( Point[] points, out Matrix3x3 rotation, out Vector3 translation ) + { + if ( points.Length != 4 ) + { + throw new ArgumentException( "4 points must be be given for pose estimation." ); + } + + Matrix3x3 rotation1, rotation2; + Vector3 translation1, translation2; + + // find initial rotation + POS( points, new Vector3( 1 ), out rotation1, out rotation2, out translation1, out translation2 ); + + // iterate further and fine tune the solution + float error1 = Iterate( points, ref rotation1, ref translation1 ); + float error2 = Iterate( points, ref rotation2, ref translation2 ); + + // take the best found pose + if ( error1 < error2 ) + { + bestRotation = rotation1; + bestTranslation = translation1; + bestPoseError = error1; + + alternateRotation = rotation2; + alternateTranslation = translation2; + alternatePoseError = error2; + } + else + { + bestRotation = rotation2; + bestTranslation = translation2; + bestPoseError = error2; + + alternateRotation = rotation1; + alternateTranslation = translation1; + alternatePoseError = error1; + } + + rotation = bestRotation; + translation = bestTranslation; + } + + private const float ErrorLimit = 2; + + // Iterate POS algorithm starting from the specified rotation and translation and fine tune it + private float Iterate( Point[] points, ref Matrix3x3 rotation, ref Vector3 translation ) + { + float prevError = float.MaxValue; + float error = 0; + + // run maximum 100 iterations (seems to be overkill, since typicaly it requires around 1-2 iterations) + for ( int count = 0; count < 100; count++ ) + { + Matrix3x3 rotation1, rotation2; + Vector3 translation1, translation2; + + // calculates new epsilon values + Vector3 eps = ( modelVectors * rotation.GetRow( 2 ) ) / translation.Z + 1; + // and new pose + POS( points, eps, out rotation1, out rotation2, out translation1, out translation2 ); + + // calculate error for both new poses + float error1 = GetError( points, rotation1, translation1 ); + float error2 = GetError( points, rotation2, translation2 ); + + // select the pose which gives smaller error + if ( error1 < error2 ) + { + rotation = rotation1; + translation = translation1; + error = error1; + } + else + { + rotation = rotation2; + translation = translation2; + error = error2; + } + + // stop if error is small enough or started to grow + if ( ( error <= ErrorLimit ) || ( error > prevError ) ) + break; + + prevError = error; + } + + return error; + } + + // Perform single iteration of POS (pos estimations) algorithm to find possible rotations and translation vectors + private void POS( Point[] imagePoints, Vector3 eps, out Matrix3x3 rotation1, out Matrix3x3 rotation2, out Vector3 translation1, out Vector3 translation2 ) + { + // create vectors keeping all X and Y coordinates for the 1st, 2nd and 3rd points + Vector3 XI = new Vector3( imagePoints[1].X, imagePoints[2].X, imagePoints[3].X ); + Vector3 YI = new Vector3( imagePoints[1].Y, imagePoints[2].Y, imagePoints[3].Y ); + + // calculate scale orthographic projection (SOP) + Vector3 imageXs = XI * eps - imagePoints[0].X; + Vector3 imageYs = YI * eps - imagePoints[0].Y; + + // calculate I0 and J0 vectors + Vector3 I0Vector = modelPseudoInverse * imageXs; + Vector3 J0Vector = modelPseudoInverse * imageYs; + + Vector3 iVector = new Vector3( ); + Vector3 jVector = new Vector3( ); + Vector3 kVector = new Vector3( ); + + // find roots of complex number C^2 + float j2i2dif = J0Vector.Square - I0Vector.Square; + float ij = Vector3.Dot( I0Vector, J0Vector ); + + float r = 0, theta = 0; + + if ( j2i2dif == 0 ) + { + theta = (float) ( ( -System.Math.PI / 2 ) * System.Math.Sign( ij ) ); + r = (float) System.Math.Sqrt( System.Math.Abs( 2 * ij ) ); + } + else + { + r = (float) System.Math.Sqrt( System.Math.Sqrt( j2i2dif * j2i2dif + 4 * ij * ij ) ); + theta = (float) System.Math.Atan( -2 * ij / j2i2dif ); + + if ( j2i2dif < 0 ) + theta += (float) System.Math.PI; + + theta /= 2; + } + + float lambda = (float) ( r * System.Math.Cos( theta ) ); + float mu = (float) ( r * System.Math.Sin( theta ) ); + + // first possible rotation + iVector = I0Vector + ( modelNormal * lambda ); + jVector = J0Vector + ( modelNormal * mu ); + + float iNorm = iVector.Normalize( ); + float jNorm = jVector.Normalize( ); + kVector = Vector3.Cross( iVector, jVector ); + + rotation1 = Matrix3x3.CreateFromRows( iVector, jVector, kVector ); + + // calculate translation vector + float scale = ( iNorm + jNorm ) / 2; + + Vector3 temp = rotation1 * modelPoints[0]; + translation1 = new Vector3( imagePoints[0].X / scale - temp.X, imagePoints[0].Y / scale - temp.Y, focalLength / scale ); + + // second possible rotation + iVector = I0Vector - ( modelNormal * lambda ); + jVector = J0Vector - ( modelNormal * mu ); + + iNorm = iVector.Normalize( ); + jNorm = jVector.Normalize( ); + kVector = Vector3.Cross( iVector, jVector ); + + rotation2 = Matrix3x3.CreateFromRows( iVector, jVector, kVector ); + + scale = ( iNorm + jNorm ) / 2; + + temp = rotation2 * modelPoints[0]; + translation2 = new Vector3( imagePoints[0].X / scale - temp.X, imagePoints[0].Y / scale - temp.Y, focalLength / scale ); + } + + // Calculate average error between real angles of the specified quadrilateral and angles of the + // quadrilateral which is the projection of currently estimated pose + private float GetError( Point[] imagePoints, Matrix3x3 rotation, Vector3 translation ) + { + Vector3 v1 = rotation * modelPoints[0] + translation; + v1.X = v1.X * focalLength / v1.Z; + v1.Y = v1.Y * focalLength / v1.Z; + + Vector3 v2 = rotation * modelPoints[1] + translation; + v2.X = v2.X * focalLength / v2.Z; + v2.Y = v2.Y * focalLength / v2.Z; + + Vector3 v3 = rotation * modelPoints[2] + translation; + v3.X = v3.X * focalLength / v3.Z; + v3.Y = v3.Y * focalLength / v3.Z; + + Vector3 v4 = rotation * modelPoints[3] + translation; + v4.X = v4.X * focalLength / v4.Z; + v4.Y = v4.Y * focalLength / v4.Z; + + Point[] modeledPoints = new Point[4] + { + new Point( v1.X, v1.Y ), + new Point( v2.X, v2.Y ), + new Point( v3.X, v3.Y ), + new Point( v4.X, v4.Y ), + }; + + float ia1 = GeometryTools.GetAngleBetweenVectors( imagePoints[0], imagePoints[1], imagePoints[3] ); + float ia2 = GeometryTools.GetAngleBetweenVectors( imagePoints[1], imagePoints[2], imagePoints[0] ); + float ia3 = GeometryTools.GetAngleBetweenVectors( imagePoints[2], imagePoints[3], imagePoints[1] ); + float ia4 = GeometryTools.GetAngleBetweenVectors( imagePoints[3], imagePoints[0], imagePoints[2] ); + + float ma1 = GeometryTools.GetAngleBetweenVectors( modeledPoints[0], modeledPoints[1], modeledPoints[3] ); + float ma2 = GeometryTools.GetAngleBetweenVectors( modeledPoints[1], modeledPoints[2], modeledPoints[0] ); + float ma3 = GeometryTools.GetAngleBetweenVectors( modeledPoints[2], modeledPoints[3], modeledPoints[1] ); + float ma4 = GeometryTools.GetAngleBetweenVectors( modeledPoints[3], modeledPoints[0], modeledPoints[2] ); + + return ( + System.Math.Abs( ia1 - ma1 ) + + System.Math.Abs( ia2 - ma2 ) + + System.Math.Abs( ia3 - ma3 ) + + System.Math.Abs( ia4 - ma4 ) + ) / 4; + } + + // This function calculates error value as it is mentioned in theory - average distance + // between image points and projected model's points. However, if translation is not + // calculated very precisely (because of inaccurate focal length, for example), this function + // may return big error value for both estimated poses. So the above function uses + // angles between objects' side instead of corners' coordinates. + /* + private float _GetError( Point[] imagePoints, Matrix3x3 rotation, Vector3 translation ) + { + Vector3 v1 = rotation * modelPoints[0] + translation; + v1.X = v1.X * focalLength / v1.Z; + v1.Y = v1.Y * focalLength / v1.Z; + + Vector3 v2 = rotation * modelPoints[1] + translation; + v2.X = v2.X * focalLength / v2.Z; + v2.Y = v2.Y * focalLength / v2.Z; + + Vector3 v3 = rotation * modelPoints[2] + translation; + v3.X = v3.X * focalLength / v3.Z; + v3.Y = v3.Y * focalLength / v3.Z; + + Vector3 v4 = rotation * modelPoints[3] + translation; + v4.X = v4.X * focalLength / v4.Z; + v4.Y = v4.Y * focalLength / v4.Z; + + Point[] modeledPoints = new Point[4] + { + new Point( v1.X, v1.Y ), + new Point( v2.X, v2.Y ), + new Point( v3.X, v3.Y ), + new Point( v4.X, v4.Y ), + }; + + return ( + imagePoints[0].DistanceTo( modeledPoints[0] ) + + imagePoints[1].DistanceTo( modeledPoints[1] ) + + imagePoints[2].DistanceTo( modeledPoints[2] ) + + imagePoints[3].DistanceTo( modeledPoints[3] ) + ) / 4; + } + */ + } +} diff --git a/Sources/Accord.Math/AForge/Geometry/FlatAnglesOptimizer.cs b/Sources/Accord.Math/AForge/Geometry/FlatAnglesOptimizer.cs new file mode 100644 index 0000000000..c040046f6 --- /dev/null +++ b/Sources/Accord.Math/AForge/Geometry/FlatAnglesOptimizer.cs @@ -0,0 +1,146 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Math.Geometry +{ + using System; + using System.Collections.Generic; + using AForge; + + /// + /// Shape optimizer, which removes obtuse angles (close to flat) from a shape. + /// + /// + /// This shape optimizing algorithm checks all adjacent edges of a shape + /// and substitutes any 2 edges with a single edge if angle between them is greater than + /// . The algorithm makes sure there are not obtuse angles in + /// a shape, which are very close to flat line. + /// + /// The shape optimizer does not optimize shapes to less than 3 points, so optimized + /// shape always will have at least 3 points. + /// + /// + /// For example, the below circle shape comprised of 65 points, can be optimized to 10 points + /// by setting to 160.
+ /// + ///
+ ///
+ /// + public class FlatAnglesOptimizer : IShapeOptimizer + { + private float maxAngleToKeep = 160; + + /// + /// Maximum angle between adjacent edges to keep in a shape, [140, 180]. + /// + /// + /// The property sets maximum angle between adjacent edges, which is kept + /// during optimization. All edges, which have a greater angle between them, are substituted + /// by a single edge. + /// + /// Default value is set to 160. + /// + public float MaxAngleToKeep + { + get { return maxAngleToKeep; } + set { maxAngleToKeep = Math.Min( 180, Math.Max( 140, value ) ); } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public FlatAnglesOptimizer( ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Maximum acceptable angle between two edges of a shape (see ). + /// + public FlatAnglesOptimizer( float maxAngleToKeep ) + { + this.maxAngleToKeep = maxAngleToKeep; + } + + /// + /// Optimize specified shape. + /// + /// + /// Shape to be optimized. + /// + /// Returns final optimized shape, which may have reduced amount of points. + /// + public List OptimizeShape( List shape ) + { + // optimized shape + List optimizedShape = new List( ); + + if ( shape.Count <= 3 ) + { + // do nothing if shape has 3 points or less + optimizedShape.AddRange( shape ); + } + else + { + float angle = 0; + + // add first 2 points to the new shape + optimizedShape.Add( shape[0] ); + optimizedShape.Add( shape[1] ); + int pointsInOptimizedHull = 2; + + for ( int i = 2, n = shape.Count; i < n; i++ ) + { + // add new point + optimizedShape.Add( shape[i] ); + pointsInOptimizedHull++; + + // get angle between 2 vectors, which start from the next to last point + angle = GeometryTools.GetAngleBetweenVectors( optimizedShape[pointsInOptimizedHull - 2], + optimizedShape[pointsInOptimizedHull - 3], optimizedShape[pointsInOptimizedHull - 1] ); + + if ( ( angle > maxAngleToKeep ) && + ( ( pointsInOptimizedHull > 3 ) || ( i < n - 1 ) ) ) + { + // remove the next to last point + optimizedShape.RemoveAt( pointsInOptimizedHull - 2 ); + pointsInOptimizedHull--; + } + } + + if ( pointsInOptimizedHull > 3 ) + { + // check the last point + angle = GeometryTools.GetAngleBetweenVectors( optimizedShape[pointsInOptimizedHull - 1], + optimizedShape[pointsInOptimizedHull - 2], optimizedShape[0] ); + + if ( angle > maxAngleToKeep ) + { + optimizedShape.RemoveAt( pointsInOptimizedHull - 1 ); + pointsInOptimizedHull--; + } + + if ( pointsInOptimizedHull > 3 ) + { + // check the first point + angle = GeometryTools.GetAngleBetweenVectors( optimizedShape[0], + optimizedShape[pointsInOptimizedHull - 1], optimizedShape[1] ); + + if ( angle > maxAngleToKeep ) + { + optimizedShape.RemoveAt( 0 ); + } + } + } + } + + return optimizedShape; + } + } +} diff --git a/Sources/Accord.Math/AForge/Geometry/GeometryTools.cs b/Sources/Accord.Math/AForge/Geometry/GeometryTools.cs new file mode 100644 index 0000000000..97acfa204 --- /dev/null +++ b/Sources/Accord.Math/AForge/Geometry/GeometryTools.cs @@ -0,0 +1,63 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Math.Geometry +{ + using System; + + /// + /// Collection of some gemetry tool methods. + /// + /// + public static class GeometryTools + { + /// + /// Calculate angle between to vectors measured in [0, 180] degrees range. + /// + /// + /// Starting point of both vectors. + /// Ending point of the first vector. + /// Ending point of the second vector. + /// + /// Returns angle between specified vectors measured in degrees. + /// + public static float GetAngleBetweenVectors( Point startPoint, Point vector1end, Point vector2end ) + { + float x1 = vector1end.X - startPoint.X; + float y1 = vector1end.Y - startPoint.Y; + + float x2 = vector2end.X - startPoint.X; + float y2 = vector2end.Y - startPoint.Y; + + return (float) ( Math.Acos( ( x1 * x2 + y1 * y2 ) / ( Math.Sqrt( x1 * x1 + y1 * y1 ) * Math.Sqrt( x2 * x2 + y2 * y2 ) ) ) * 180.0 / Math.PI ); + } + + /// + /// Calculate minimum angle between two lines measured in [0, 90] degrees range. + /// + /// + /// A point on the first line. + /// Another point on the first line. + /// A point on the second line. + /// Another point on the second line. + /// + /// Returns minimum angle between two lines. + /// + /// It is preferred to use if it is required to calculate angle + /// multiple times for one of the lines. + /// + /// and are the same, + /// -OR- and are the same. + /// + public static float GetAngleBetweenLines( Point a1, Point a2, Point b1, Point b2 ) + { + Line line1 = Line.FromPoints( a1, a2 ); + return line1.GetAngleBetweenLines( Line.FromPoints( b1, b2 ) ); + } + } +} diff --git a/Sources/Accord.Math/AForge/Geometry/GrahamConvexHull.cs b/Sources/Accord.Math/AForge/Geometry/GrahamConvexHull.cs new file mode 100644 index 0000000000..0cb341b8f --- /dev/null +++ b/Sources/Accord.Math/AForge/Geometry/GrahamConvexHull.cs @@ -0,0 +1,190 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Math.Geometry +{ + using System; + using System.Collections.Generic; + + /// + /// Graham scan algorithm for finding convex hull. + /// + /// + /// The class implements + /// Graham scan algorithm for finding convex hull + /// of a given set of points. + /// + /// Sample usage: + /// + /// // generate some random points + /// Random rand = new Random( ); + /// List<IntPoint> points = new List<IntPoint>( ); + /// + /// for ( int i = 0; i < 10; i++ ) + /// { + /// points.Add( new IntPoint( + /// rand.Next( 200 ) - 100, + /// rand.Next( 200 ) - 100 ) ); + /// } + /// + /// // find the convex hull + /// IConvexHullAlgorithm hullFinder = new GrahamConvexHull( ); + /// List<IntPoint> hull = hullFinder.FindHull( points ); + /// + /// + /// + public class GrahamConvexHull : IConvexHullAlgorithm + { + /// + /// Find convex hull for the given set of points. + /// + /// + /// Set of points to search convex hull for. + /// + /// Returns set of points, which form a convex hull for the given . + /// The first point in the list is the point with lowest X coordinate (and with lowest Y if there are + /// several points with the same X value). Points are provided in counter clockwise order + /// (Cartesian + /// coordinate system). + /// + public List FindHull( List points ) + { + // do nothing if there 3 points or less + if ( points.Count <= 3 ) + { + return new List( points ); + } + + List pointsToProcess = new List( ); + + // convert input points to points we can process + foreach ( IntPoint point in points ) + { + pointsToProcess.Add( new PointToProcess( point ) ); + } + + // find a point, with lowest X and lowest Y + int firstCornerIndex = 0; + PointToProcess firstCorner = pointsToProcess[0]; + + for ( int i = 1, n = pointsToProcess.Count; i < n; i++ ) + { + if ( ( pointsToProcess[i].X < firstCorner.X ) || + ( ( pointsToProcess[i].X == firstCorner.X ) && ( pointsToProcess[i].Y < firstCorner.Y ) ) ) + { + firstCorner = pointsToProcess[i]; + firstCornerIndex = i; + } + } + + // remove the just found point + pointsToProcess.RemoveAt( firstCornerIndex ); + + // find K (tangent of line's angle) and distance to the first corner + for ( int i = 0, n = pointsToProcess.Count; i < n; i++ ) + { + int dx = pointsToProcess[i].X - firstCorner.X; + int dy = pointsToProcess[i].Y - firstCorner.Y; + + // don't need square root, since it is not important in our case + pointsToProcess[i].Distance = dx * dx + dy * dy; + // tangent of lines angle + pointsToProcess[i].K = ( dx == 0 ) ? float.PositiveInfinity : (float) dy / dx; + } + + // sort points by angle and distance + pointsToProcess.Sort( ); + + List convexHullTemp = new List( ); + + // add first corner, which is always on the hull + convexHullTemp.Add( firstCorner ); + // add another point, which forms a line with lowest slope + convexHullTemp.Add( pointsToProcess[0] ); + pointsToProcess.RemoveAt( 0 ); + + PointToProcess lastPoint = convexHullTemp[1]; + PointToProcess prevPoint = convexHullTemp[0]; + + while ( pointsToProcess.Count != 0 ) + { + PointToProcess newPoint = pointsToProcess[0]; + + // skip any point, which has the same slope as the last one or + // has 0 distance to the first point + if ( ( newPoint.K == lastPoint.K ) || ( newPoint.Distance == 0 ) ) + { + pointsToProcess.RemoveAt( 0 ); + continue; + } + + // check if current point is on the left side from two last points + if ( ( newPoint.X - prevPoint.X ) * ( lastPoint.Y - newPoint.Y ) - ( lastPoint.X - newPoint.X ) * ( newPoint.Y - prevPoint.Y ) < 0 ) + { + // add the point to the hull + convexHullTemp.Add( newPoint ); + // and remove it from the list of points to process + pointsToProcess.RemoveAt( 0 ); + + prevPoint = lastPoint; + lastPoint = newPoint; + } + else + { + // remove the last point from the hull + convexHullTemp.RemoveAt( convexHullTemp.Count - 1 ); + + lastPoint = prevPoint; + prevPoint = convexHullTemp[convexHullTemp.Count - 2]; + } + } + + // convert points back + List convexHull = new List( ); + + foreach ( PointToProcess pt in convexHullTemp ) + { + convexHull.Add( pt.ToPoint( ) ); + } + + return convexHull; + } + + // Internal comparer for sorting points + private class PointToProcess : IComparable + { + public int X; + public int Y; + public float K; + public float Distance; + + public PointToProcess( IntPoint point ) + { + X = point.X; + Y = point.Y; + + K = 0; + Distance = 0; + } + + public int CompareTo( object obj ) + { + PointToProcess another = (PointToProcess) obj; + + return ( K < another.K ) ? -1 : ( K > another.K ) ? 1 : + ( ( Distance > another.Distance ) ? -1 : ( Distance < another.Distance ) ? 1 : 0 ); + } + + public IntPoint ToPoint( ) + { + return new IntPoint( X, Y ); + } + } + + } +} diff --git a/Sources/Accord.Math/AForge/Geometry/IConvexHullAlgorithm.cs b/Sources/Accord.Math/AForge/Geometry/IConvexHullAlgorithm.cs new file mode 100644 index 0000000000..7f5c5dcc6 --- /dev/null +++ b/Sources/Accord.Math/AForge/Geometry/IConvexHullAlgorithm.cs @@ -0,0 +1,46 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Math.Geometry +{ + using System; + using System.Collections.Generic; + + using AForge; + + /// + /// Interface defining methods for algorithms, which search for convex hull of the specified points' set. + /// + /// + /// The interface defines a method, which should be implemented by different classes + /// performing convex hull search for specified set of points. + /// + /// All algorithms, implementing this interface, should follow two rules for the found convex hull: + /// + /// the first point in the returned list is the point with lowest X coordinate (and with lowest Y if + /// there are several points with the same X value); + /// points in the returned list are given in counter clockwise order + /// (Cartesian + /// coordinate system). + /// + /// + /// + /// + public interface IConvexHullAlgorithm + { + /// + /// Find convex hull for the given set of points. + /// + /// + /// Set of points to search convex hull for. + /// + /// Returns set of points, which form a convex hull for the given . + /// + List FindHull( List points ); + } +} diff --git a/Sources/Accord.Math/AForge/Geometry/IShapeOptimizer.cs b/Sources/Accord.Math/AForge/Geometry/IShapeOptimizer.cs new file mode 100644 index 0000000000..2be3621bc --- /dev/null +++ b/Sources/Accord.Math/AForge/Geometry/IShapeOptimizer.cs @@ -0,0 +1,44 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Math.Geometry +{ + using System; + using System.Collections.Generic; + using AForge; + + /// + /// Interface for shape optimizing algorithms. + /// + /// + /// The interface defines set of methods, which should be implemented + /// by shape optimizing algorithms. These algorithms take input shape, which is defined + /// by a set of points (corners of convex hull, etc.), and remove some insignificant points from it, + /// which has little influence on the final shape's look. + /// + /// The shape optimizing algorithms can be useful in conjunction with such algorithms + /// like convex hull searching, which usually may provide many hull points, where some + /// of them are insignificant and could be removed. + /// + /// For additional details about shape optimizing algorithms, documentation of + /// particular algorithm should be studied. + /// + /// + public interface IShapeOptimizer + { + /// + /// Optimize specified shape. + /// + /// + /// Shape to be optimized. + /// + /// Returns final optimized shape, which may have reduced amount of points. + /// + List OptimizeShape( List shape ); + } +} diff --git a/Sources/Accord.Math/AForge/Geometry/Line.cs b/Sources/Accord.Math/AForge/Geometry/Line.cs new file mode 100644 index 0000000000..89581e847 --- /dev/null +++ b/Sources/Accord.Math/AForge/Geometry/Line.cs @@ -0,0 +1,448 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Math.Geometry +{ + using System; + using AForge; + + /// + /// The class encapsulates 2D line and provides some tool methods related to lines. + /// + /// + /// The class provides some methods which are related to lines: + /// angle between lines, distance to point, finding intersection point, etc. + /// + /// + /// Generally, the equation of the line is y = * x + + /// . However, when is an Infinity, + /// would normally be meaningless, and it would be + /// impossible to distinguish the line x = 5 from the line x = -5. Therefore, + /// if is or + /// , the line's equation is instead + /// x = . + /// + /// Sample usage: + /// + /// // create a line + /// Line line = Line.FromPoints( new Point( 0, 0 ), new Point( 3, 4 ) ); + /// // check if it is vertical or horizontal + /// if ( line.IsVertical || line.IsHorizontal ) + /// { + /// // ... + /// } + /// + /// // get intersection point with another line + /// Point intersection = line.GetIntersectionWith( + /// Line.FromPoints( new Point( 3, 0 ), new Point( 0, 4 ) ) ); + /// + /// + /// + public sealed class Line + { + // line's parameters from its equation: y = k * x + b; + // If k is an Infinity, the equation is x = b. + private readonly float k; // line's slope + private readonly float b; // Y-coordinate where line intersects Y-axis + + /// + /// Checks if the line vertical or not. + /// + /// + public bool IsVertical + { + get { return float.IsInfinity(k); } + } + + /// + /// Checks if the line horizontal or not. + /// + public bool IsHorizontal + { + get { return (k == 0); } + } + + /// + /// Gets the slope of the line. + /// + public float Slope { get { return k; } } + + /// + /// If not , gets the Line's Y-intercept. + /// If gets the line's X-intercept. + /// + public float Intercept { get { return b; } } + + /// + /// Creates a that goes through the two specified points. + /// + /// + /// One point on the line. + /// Another point on the line. + /// + /// Returns a representing the line between + /// and . + /// + /// Thrown if the two points are the same. + /// + public static Line FromPoints(Point point1, Point point2) + { + return new Line(point1, point2); + } + + /// + /// Creates a with the specified slope and intercept. + /// + /// + /// The slope of the line + /// The Y-intercept of the line, unless the slope is an + /// infinity, in which case the line's equation is "x = intercept" instead. + /// + /// Returns a representing the specified line. + /// + /// The construction here follows the same rules as for the rest of this class. + /// Most lines are expressed as y = slope * x + intercept. Vertical lines, however, are + /// x = intercept. This is indicated by being true or by + /// returning or + /// . + /// + public static Line FromSlopeIntercept(float slope, float intercept) + { + return new Line(slope, intercept); + } + + /// + /// Constructs a from a radius and an angle (in degrees). + /// + /// + /// The minimum distance from the line to the origin. + /// The angle of the vector from the origin to the line. + /// + /// Returns a representing the specified line. + /// + /// is the minimum distance from the origin + /// to the line, and is the counterclockwise rotation from + /// the positive X axis to the vector through the origin and normal to the line. + /// This means that if is in [0,180), the point on the line + /// closest to the origin is on the positive X or Y axes, or in quadrants I or II. Likewise, + /// if is in [180,360), the point on the line closest to the + /// origin is on the negative X or Y axes, or in quadrants III or IV. + /// + /// Thrown if radius is negative. + /// + public static Line FromRTheta(float radius, float theta) + { + return new Line(radius, theta, false); + } + + /// + /// Constructs a from a point and an angle (in degrees). + /// + /// + /// The minimum distance from the line to the origin. + /// The angle of the normal vector from the origin to the line. + /// + /// is the counterclockwise rotation from + /// the positive X axis to the vector through the origin and normal to the line. + /// This means that if is in [0,180), the point on the line + /// closest to the origin is on the positive X or Y axes, or in quadrants I or II. Likewise, + /// if is in [180,360), the point on the line closest to the + /// origin is on the negative X or Y axes, or in quadrants III or IV. + /// + /// Returns a representing the specified line. + /// + public static Line FromPointTheta(Point point, float theta) + { + return new Line(point, theta); + } + + #region Private Constructors + private Line(Point start, Point end) + { + if (start == end) + { + throw new ArgumentException("Start point of the line cannot be the same as its end point."); + } + + k = (end.Y - start.Y) / (end.X - start.X); + b = float.IsInfinity(k) ? start.X : start.Y - k * start.X; + } + + private Line(float slope, float intercept) + { + k = slope; + b = intercept; + } + + private Line(float radius, float theta, bool unused) + { + if (radius < 0) + throw new ArgumentOutOfRangeException("radius", radius, "Must be non-negative"); + + theta *= (float)(Math.PI / 180); + + float sine = (float)Math.Sin(theta), cosine = (float)Math.Cos(theta); + Point pt1 = new Point(radius * cosine, radius * sine); + + // -1/tan, to get the slope of the line, and not the slope of the normal + k = -cosine / sine; + + if (!float.IsInfinity(k)) + { + b = pt1.Y - k * pt1.X; + } + else + { + b = Math.Abs(radius); + } + } + + private Line(Point point, float theta) + { + theta *= (float)(Math.PI / 180); + + k = (float)(-1.0f / Math.Tan(theta)); + + if (!float.IsInfinity(k)) + { + b = point.Y - k * point.X; + } + else + { + b = point.X; + } + } + #endregion + + /// + /// Calculate minimum angle between this line and the specified line measured in [0, 90] degrees range. + /// + /// + /// The line to find angle between. + /// + /// Returns minimum angle between lines. + /// + public float GetAngleBetweenLines(Line secondLine) + { + float k2 = secondLine.k; + + bool isVertical1 = IsVertical; + bool isVertical2 = secondLine.IsVertical; + + // check if lines are parallel + if ((k == k2) || (isVertical1 && isVertical2)) + return 0; + + float angle = 0; + + if ((!isVertical1) && (!isVertical2)) + { + float tanPhi = ((k2 > k) ? (k2 - k) : (k - k2)) / (1 + k * k2); + angle = (float)Math.Atan(tanPhi); + } + else + { + // one of the lines is parallel to Y axis + + if (isVertical1) + { + angle = (float)(Math.PI / 2 - Math.Atan(k2) * Math.Sign(k2)); + } + else + { + angle = (float)(Math.PI / 2 - Math.Atan(k) * Math.Sign(k)); + } + } + + // convert radians to degrees + angle *= (float)(180.0 / Math.PI); + + if (angle < 0) + { + angle = -angle; + } + + return angle; + } + + /// + /// Finds intersection point with the specified line. + /// + /// + /// Line to find intersection with. + /// + /// Returns intersection point with the specified line, or + /// if the lines are parallel and distinct. + /// + /// Thrown if the specified line is the same line as this line. + /// + public Point? GetIntersectionWith(Line secondLine) + { + float k2 = secondLine.k; + float b2 = secondLine.b; + + bool isVertical1 = IsVertical; + bool isVertical2 = secondLine.IsVertical; + + Point? intersection = null; + + if ((k == k2) || (isVertical1 && isVertical2)) + { + if (b == b2) + { + throw new InvalidOperationException("Identical lines do not have an intersection point."); + } + } + else + { + if (isVertical1) + { + intersection = new Point(b, k2 * b + b2); + } + else if (isVertical2) + { + intersection = new Point(b2, k * b2 + b); + } + else + { + // the intersection is at x=(b2-b1)/(k1-k2), and y=k1*x+b1 + float x = (b2 - b) / (k - k2); + intersection = new Point(x, k * x + b); + } + } + + return intersection; + } + + /// + /// Finds, provided it exists, the intersection point with the specified . + /// + /// + /// to find intersection with. + /// + /// Returns intersection point with the specified , or , + /// if this line does not intersect with the segment. + /// + /// If the line and segment do not intersect, the method returns . + /// If the line and segment share multiple points, the method throws an . + /// + /// + /// Thrown if is a portion + /// of this line. + /// + public Point? GetIntersectionWith(LineSegment other) + { + return other.GetIntersectionWith(this); + } + + /// + /// Calculate Euclidean distance between a point and a line. + /// + /// + /// The point to calculate distance to. + /// + /// Returns the Euclidean distance between this line and the specified point. Unlike + /// , this returns the distance from the infinite line. (0,0) is 0 units + /// from the line defined by (0,5) and (0,8), but is 5 units from the segment with those endpoints. + /// + public float DistanceToPoint(Point point) + { + float distance; + + if (!IsVertical) + { + float div = (float)Math.Sqrt(k * k + 1); + distance = Math.Abs((k * point.X + b - point.Y) / div); + } + else + { + distance = Math.Abs(b - point.X); + } + + return distance; + } + + /// + /// Equality operator - checks if two lines have equal parameters. + /// + /// + /// First line to check. + /// Second line to check. + /// + /// Returns if parameters of specified + /// lines are equal. + /// + public static bool operator ==(Line line1, Line line2) + { + if (System.Object.ReferenceEquals(line1, line2)) + { + return true; + } + + if (((object)line1 == null) || ((object)line2 == null)) + { + return false; + } + + return ((line1.k == line2.k) && (line1.b == line2.b)); + } + + /// + /// Inequality operator - checks if two lines have different parameters. + /// + /// + /// First line to check. + /// Second line to check. + /// + /// Returns if parameters of specified + /// lines are not equal. + /// + public static bool operator !=(Line line1, Line line2) + { + return !(line1 == line2); + } + + /// + /// Check if this instance of equals to the specified one. + /// + /// + /// Another line to check equalty to. + /// + /// Return if objects are equal. + /// + public override bool Equals(object obj) + { + var line = obj as Line; + if (line == null) + return false; + return this == line; + } + + /// + /// Get hash code for this instance. + /// + /// + /// Returns the hash code for this instance. + /// + public override int GetHashCode() + { + return k.GetHashCode() + b.GetHashCode(); + } + + /// + /// Get string representation of the class. + /// + /// + /// Returns string, which contains values of the like in readable form. + /// + public override string ToString() + { + return string.Format(System.Globalization.CultureInfo.InvariantCulture, "k = {0}, b = {1}", k, b); + } + } +} diff --git a/Sources/Accord.Math/AForge/Geometry/LineSegment.cs b/Sources/Accord.Math/AForge/Geometry/LineSegment.cs new file mode 100644 index 0000000000..2b6a36a41 --- /dev/null +++ b/Sources/Accord.Math/AForge/Geometry/LineSegment.cs @@ -0,0 +1,375 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Math.Geometry +{ + using System; + + /// + /// The class encapsulates 2D line segment and provides some tool methods related to lines. + /// + /// + /// The class provides some methods which are related to line segments: + /// distance to point, finding intersection point, etc. + /// + /// + /// A line segment may be converted to a . + /// + /// Sample usage: + /// + /// // create a segment + /// LineSegment segment = new LineSegment( new Point( 0, 0 ), new Point( 3, 4 ) ); + /// // get segment's length + /// float length = segment.Length; + /// + /// // get intersection point with a line + /// Point? intersection = segment.GetIntersectionWith( + /// new Line( new Point( -3, 8 ), new Point( 0, 4 ) ) ); + /// + /// + /// + public sealed class LineSegment + { + // segment's start/end point + private readonly Point start; + private readonly Point end; + + private readonly Line line; + + /// + /// Start point of the line segment. + /// + public Point Start + { + get { return start; } + } + + /// + /// End point of the line segment. + /// + public Point End + { + get { return end; } + } + + /// + /// Get segment's length - Euclidean distance between its and points. + /// + public float Length + { + get { return start.DistanceTo(end); } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Segment's start point. + /// Segment's end point. + /// + /// Thrown if the two points are the same. + /// + public LineSegment(Point start, Point end) + { + line = Line.FromPoints(start, end); + this.start = start; + this.end = end; + } + + /// + /// Converts this to a by discarding + /// its endpoints and extending it infinitely in both directions. + /// + /// + /// The segment to convert to a . + /// + /// Returns a that contains this . + /// + public static explicit operator Line(LineSegment segment) + { + return segment.line; + } + + /// + /// Calculate Euclidean distance between a point and a finite line segment. + /// + /// + /// The point to calculate the distance to. + /// + /// Returns the Euclidean distance between this line segment and the specified point. Unlike + /// , this returns the distance from the finite segment. (0,0) is 5 units + /// from the segment (0,5)-(0,8), but is 0 units from the line through those points. + /// + public float DistanceToPoint(Point point) + { + float segmentDistance; + + switch (LocateProjection(point)) + { + case ProjectionLocation.RayA: + segmentDistance = point.DistanceTo(start); + break; + case ProjectionLocation.RayB: + segmentDistance = point.DistanceTo(end); + break; + default: + segmentDistance = line.DistanceToPoint(point); + break; + }; + + return segmentDistance; + } + + /// + /// Finds, provided it exists, the intersection point with the specified . + /// + /// + /// to find intersection with. + /// + /// Returns intersection point with the specified , or , if + /// the two segments do not intersect. + /// + /// If the two segments do not intersect, the method returns . If the two + /// segments share multiple points, this throws an . + /// + /// + /// Thrown if the segments overlap - if they have + /// multiple points in common. + /// + public Point? GetIntersectionWith(LineSegment other) + { + Point? result = null; + + if ((line.Slope == other.line.Slope) || (line.IsVertical && other.line.IsVertical)) + { + if (line.Intercept == other.line.Intercept) + { + // Collinear segments. Inspect and handle. + // Consider this segment AB and other as CD. (start/end in both cases) + // There are three cases: + // 0 shared points: C and D both project onto the same ray of AB + // 1 shared point: One of A or B equals one of C or D, and the other of C/D + // projects on the correct ray. + // Many shared points. + + ProjectionLocation projC = LocateProjection(other.start), projD = LocateProjection(other.end); + + if ((projC != ProjectionLocation.SegmentAB) && (projC == projD)) + { + // no shared points + result = null; + } + else if (((start == other.start) && (projD == ProjectionLocation.RayA)) || + ((start == other.end) && (projC == ProjectionLocation.RayA))) + { + // shared start point + result = start; + } + else if (((end == other.start) && (projD == ProjectionLocation.RayB)) || + ((end == other.end) && (projC == ProjectionLocation.RayB))) + { + // shared end point + result = end; + } + else + { + // overlapping + throw new InvalidOperationException("Overlapping segments do not have a single intersection point."); + } + } + } + else + { + result = GetIntersectionWith(other.line); + + if ((result.HasValue) && (other.LocateProjection(result.Value) != ProjectionLocation.SegmentAB)) + { + // the intersection is on the extended line of this segment + result = null; + } + } + + return result; + } + + /// + /// Finds, provided it exists, the intersection point with the specified . + /// + /// + /// to find intersection with. + /// + /// Returns intersection point with the specified , or , if + /// the line does not intersect with this segment. + /// + /// If the line and the segment do not intersect, the method returns . If the line + /// and the segment share multiple points, the method throws an . + /// + /// + /// Thrown if this segment is a portion of + /// line. + /// + public Point? GetIntersectionWith(Line other) + { + Point? result; + + if ((line.Slope == other.Slope) || (line.IsVertical && other.IsVertical)) + { + if (line.Intercept == other.Intercept) throw new InvalidOperationException("Segment is a portion of the specified line."); + + // unlike Line.GetIntersectionWith(Line), this does not throw on parallel distinct lines + result = null; + } + else + { + result = line.GetIntersectionWith(other); + } + + if ((result.HasValue) && (LocateProjection(result.Value) != ProjectionLocation.SegmentAB)) + { + // the intersection is on this segment's extended line, but not on the segment itself + result = null; + } + + return result; + } + + // Represents the location of a projection of a point on the line that contains this segment. + // If the point projects to A,B, or anything between them, it is SegmentAB. + // If it projects beyond A, it's RayA; if it projects beyond B, it's RayB. + private enum ProjectionLocation { RayA, SegmentAB, RayB } + + // Get type of point's projections to this line segment + private ProjectionLocation LocateProjection(Point point) + { + // Modified from http://www.codeguru.com/forum/showthread.php?t=194400 + + /* How do I find the distance from a point to a line segment? + + Let the point be C (Cx,Cy) and the line be AB (Ax,Ay) to (Bx,By). + Let P be the point of perpendicular projection of C on AB. The parameter + r, which indicates P's position along AB, is computed by the dot product + of AC and AB divided by the square of the length of AB: + + (1) AC dot AB + r = --------- + ||AB||^2 + + r has the following meaning: + + r=0 P = A + r=1 P = B + r<0 P is on the backward extension of AB (and distance C-AB is distance C-A) + r>1 P is on the forward extension of AB (and distance C-AB is distance C-B) + 0 denomenator) ? ProjectionLocation.RayB : ProjectionLocation.SegmentAB; + + return result; + } + + /// + /// Equality operator - checks if two line segments have equal parameters. + /// + /// + /// First line segment to check. + /// Second line segment to check. + /// + /// Returns if parameters of specified + /// line segments are equal. + /// + public static bool operator ==(LineSegment line1, LineSegment line2) + { + if (System.Object.ReferenceEquals(line1, line2)) + { + return true; + } + + if (((object)line1 == null) || ((object)line2 == null)) + { + return false; + } + + return ((line1.start == line2.start) && (line1.end == line2.end)); + } + + /// + /// Inequality operator - checks if two lines have different parameters. + /// + /// + /// First line segment to check. + /// Second line segment to check. + /// + /// Returns if parameters of specified + /// line segments are not equal. + /// + public static bool operator !=(LineSegment line1, LineSegment line2) + { + return !(line1 == line2); + } + + /// + /// Check if this instance of equals to the specified one. + /// + /// + /// Another line segment to check equalty to. + /// + /// Return if objects are equal. + /// + public override bool Equals(object obj) + { + var line = obj as LineSegment; + if (line == null) + return false; + return this == line; + } + + /// + /// Get hash code for this instance. + /// + /// + /// Returns the hash code for this instance. + /// + public override int GetHashCode() + { + return start.GetHashCode() + end.GetHashCode(); + } + + /// + /// Get string representation of the class. + /// + /// + /// Returns string, which contains values of the like in readable form. + /// + public override string ToString() + { + return string.Format(System.Globalization.CultureInfo.InvariantCulture, "({0}) -> ({1})", start, end); + } + } +} diff --git a/Sources/Accord.Math/AForge/Geometry/LineStraighteningOptimizer.cs b/Sources/Accord.Math/AForge/Geometry/LineStraighteningOptimizer.cs new file mode 100644 index 0000000000..167907091 --- /dev/null +++ b/Sources/Accord.Math/AForge/Geometry/LineStraighteningOptimizer.cs @@ -0,0 +1,173 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Math.Geometry +{ + using System; + using System.Collections.Generic; + using AForge; + + /// + /// Shape optimizer, which removes points within close range to shapes' body. + /// + /// + /// This shape optimizing algorithm checks all points of the shape and + /// removes those of them, which are in a certain distance to a line connecting previous and + /// the next points. In other words, it goes through all adjacent edges of a shape and checks + /// what is the distance between the corner formed by these two edges and a possible edge, which + /// could be used as substitution of these edges. If the distance is equal or smaller than + /// the specified value, then the point is removed, + /// so the two edges are substituted by a single one. When optimization process is done, + /// the new shape has reduced amount of points and none of the removed points are further away + /// from the new shape than the specified limit. + /// + /// The shape optimizer does not optimize shapes to less than 3 points, so optimized + /// shape always will have at least 3 points. + /// + /// + /// For example, the below circle shape comprised of 65 points, can be optimized to 8 points + /// by setting to 10.
+ /// + ///
+ ///
+ /// + public class LineStraighteningOptimizer : IShapeOptimizer + { + private float maxDistanceToRemove = 5; + + /// + /// Maximum allowed distance between removed points and optimized shape, [0, ∞). + /// + /// + /// The property sets maximum allowed distance between points removed from original + /// shape and optimized shape - none of the removed points are further away + /// from the new shape than the specified limit. + /// + /// + /// Default value is set to 5. + /// + public float MaxDistanceToRemove + { + get { return maxDistanceToRemove; } + set { maxDistanceToRemove = Math.Max( 0, value ); } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public LineStraighteningOptimizer( ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Maximum allowed distance between removed points + /// and optimized shape (see ). + /// + public LineStraighteningOptimizer( float maxDistanceToRemove ) + { + this.maxDistanceToRemove = maxDistanceToRemove; + } + + /// + /// Optimize specified shape. + /// + /// + /// Shape to be optimized. + /// + /// Returns final optimized shape, which may have reduced amount of points. + /// + public List OptimizeShape( List shape ) + { + // optimized shape + List optimizedShape = new List( ); + // list of recently removed points + List recentlyRemovedPoints = new List( ); + + if ( shape.Count <= 3 ) + { + // do nothing if shape has 3 points or less + optimizedShape.AddRange( shape ); + } + else + { + float distance = 0; + + // add first 2 points to the new shape + optimizedShape.Add( shape[0] ); + optimizedShape.Add( shape[1] ); + int pointsInOptimizedHull = 2; + + for ( int i = 2, n = shape.Count; i < n; i++ ) + { + // add new point + optimizedShape.Add( shape[i] ); + pointsInOptimizedHull++; + + // add new candidate for removing to the list + recentlyRemovedPoints.Add( optimizedShape[pointsInOptimizedHull - 2] ); + + // calculate maximum distance between new candidate line and recently removed point + PointsCloud.GetFurthestPointFromLine( recentlyRemovedPoints, + optimizedShape[pointsInOptimizedHull - 3], optimizedShape[pointsInOptimizedHull - 1], + out distance ); + + if ( ( distance <= maxDistanceToRemove ) && + ( ( pointsInOptimizedHull > 3 ) || ( i < n - 1 ) ) ) + { + optimizedShape.RemoveAt( pointsInOptimizedHull - 2 ); + pointsInOptimizedHull--; + } + else + { + // don't need to remove the last candidate point + recentlyRemovedPoints.Clear( ); + } + } + + if ( pointsInOptimizedHull > 3 ) + { + // check the last point + recentlyRemovedPoints.Add( optimizedShape[pointsInOptimizedHull - 1] ); + + PointsCloud.GetFurthestPointFromLine( recentlyRemovedPoints, + optimizedShape[pointsInOptimizedHull - 2], optimizedShape[0], + out distance ); + + if ( distance <= maxDistanceToRemove ) + { + optimizedShape.RemoveAt( pointsInOptimizedHull - 1 ); + pointsInOptimizedHull--; + } + else + { + recentlyRemovedPoints.Clear( ); + } + + if ( pointsInOptimizedHull > 3 ) + { + // check the first point + recentlyRemovedPoints.Add( optimizedShape[0] ); + + PointsCloud.GetFurthestPointFromLine( recentlyRemovedPoints, + optimizedShape[pointsInOptimizedHull - 1], optimizedShape[1], + out distance ); + + if ( distance <= maxDistanceToRemove ) + { + optimizedShape.RemoveAt( 0 ); + } + } + } + } + + return optimizedShape; + } + } +} diff --git a/Sources/Accord.Math/AForge/Geometry/POSIT.cs b/Sources/Accord.Math/AForge/Geometry/POSIT.cs new file mode 100644 index 0000000000..5b35816d6 --- /dev/null +++ b/Sources/Accord.Math/AForge/Geometry/POSIT.cs @@ -0,0 +1,203 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Math.Geometry +{ + using System; + using AForge; + using AForge.Math; + + /// + /// 3D pose estimation algorithm. + /// + /// + /// The class implements an algorithm for 3D object's pose estimation from it's + /// 2D coordinates obtained by perspective projection, when the object is described none coplanar points. + /// The idea of the implemented math and algorithm is described in "Model-Based Object Pose in 25 + /// Lines of Code" paper written by Daniel F. DeMenthon and Larry S. Davis (the implementation of + /// the algorithm is almost 1 to 1 translation of the pseudo code given by the paper, so should + /// be easy to follow). + /// + /// At this point the implementation works only with models described by 4 points, which is + /// the minimum number of points enough for 3D pose estimation. + /// + /// The 4 model's point must not be coplanar, i.e. must not reside all within + /// same planer. See for coplanar case. + /// + /// Read 3D Pose Estimation article for + /// additional information and samples. + /// + /// Sample usage: + /// + /// // points of real object - model + /// Vector3[] positObject = new Vector3[4] + /// { + /// new Vector3( 28, 28, -28 ), + /// new Vector3( -28, 28, -28 ), + /// new Vector3( 28, -28, -28 ), + /// new Vector3( 28, 28, 28 ), + /// }; + /// // focal length of camera used to capture the object + /// float focalLength = 640; // depends on your camera or projection system + /// // initialize POSIT object + /// Posit posit = new Posit( positObject, focalLength ); + /// + /// // 2D points of te object - projection + /// AForge.Point[] projectedPoints = new AForge.Point[4] + /// { + /// new AForge.Point( -4, 29 ), + /// new AForge.Point( -180, 86 ), + /// new AForge.Point( -5, -102 ), + /// new AForge.Point( 76, 137 ), + /// }; + /// // estimate pose + /// Matrix3x3 rotationMatrix; + /// Vector3 translationVector; + /// posit.EstimatePose( projectedPoints, + /// out rotationMatrix, out translationVector ); + /// + /// + /// + /// + /// + public class Posit + { + // camera's focal length + private float focalLength; + + // points of the model to estimate position for + private Vector3[] modelPoints; + // 3 vectors of the model kept as a matrix + private Matrix3x3 modelVectors; + // pseudoinverse of the model vectors matrix + private Matrix3x3 modelPseudoInverse; + + /// + /// Coordinates of the model points which pose should be estimated. + /// + public Vector3[] Model + { + get { return (Vector3[]) modelPoints.Clone( ); } + } + + /// + /// Effective focal length of the camera used to capture the model. + /// + public float FocalLength + { + get { return focalLength; } + set { focalLength = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Array of vectors containing coordinates of four real model's point (points + /// must not be on the same plane). + /// Effective focal length of the camera used to capture the model. + /// + /// The model must have 4 points. + /// + public Posit( Vector3[] model, float focalLength ) + { + if ( model.Length != 4 ) + { + throw new ArgumentException( "The model must have 4 points." ); + } + + this.focalLength = focalLength; + modelPoints = (Vector3[]) model.Clone( ); + + // compute model vectors + modelVectors = Matrix3x3.CreateFromRows( + model[1] - model[0], + model[2] - model[0], + model[3] - model[0] ); + + // compute pseudo inverse matrix + modelPseudoInverse = modelVectors.PseudoInverse( ); + } + + private const float stop_epsilon = 1.0e-4f; + + /// + /// Estimate pose of a model from it's projected 2D coordinates. + /// + /// + /// 4 2D points of the model's projection. + /// Gets object's rotation. + /// Gets object's translation. + /// + /// 4 points must be be given for pose estimation. + /// + public void EstimatePose( Point[] points, out Matrix3x3 rotation, out Vector3 translation ) + { + if ( points.Length != 4 ) + { + throw new ArgumentException( "4 points must be be given for pose estimation." ); + } + + float Z0 = 0, scale = 1; + + Vector3 X0 = new Vector3( points[0].X ); + Vector3 Y0 = new Vector3( points[0].Y ); + + Vector3 XI = new Vector3( points[1].X, points[2].X, points[3].X ); + Vector3 YI = new Vector3( points[1].Y, points[2].Y, points[3].Y ); + + int count = 0; + + Vector3 iVector = new Vector3( ); + Vector3 jVector = new Vector3( ); + Vector3 kVector = new Vector3( ); + Vector3 imageXs = new Vector3( ); + Vector3 imageYs = new Vector3( ); + + Vector3 eps = new Vector3( 1 ); + + for ( ; count < 100; count++ ) + { + // calculate new scale orthographic projection (SOP) + imageXs = XI * eps - X0; + imageYs = YI * eps - Y0; + + // calculate I and J vectors + iVector = modelPseudoInverse * imageXs; + jVector = modelPseudoInverse * imageYs; + // convert them to unit vectors i and j + float iNorm = iVector.Normalize( ); + float jNorm = jVector.Normalize( ); + // scale of projection + scale = ( iNorm + jNorm ) / 2; + // calculate n vector k + kVector = Vector3.Cross( iVector, jVector ); + // z-coordinate Z0 of the translation vector + Z0 = focalLength / scale; + + // calculate new epsilon values + Vector3 oldEps = eps; + eps = ( modelVectors * kVector ) / Z0 + 1; + + // check if it is time to stop + if ( ( eps - oldEps ).Abs( ).Max < stop_epsilon ) + break; + } + + // create rotation matrix + rotation = Matrix3x3.CreateFromRows( iVector, jVector, kVector ); + + // create translation vector + Vector3 temp = rotation * modelPoints[0]; + translation = new Vector3( + points[0].X / scale - temp.X, + points[0].Y / scale - temp.Y, + focalLength / scale ); + } + } +} diff --git a/Sources/Accord.Math/AForge/Geometry/PointsCloud.cs b/Sources/Accord.Math/AForge/Geometry/PointsCloud.cs new file mode 100644 index 0000000000..37611b1a4 --- /dev/null +++ b/Sources/Accord.Math/AForge/Geometry/PointsCloud.cs @@ -0,0 +1,608 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Math.Geometry +{ + using System; + using System.Collections.Generic; + using AForge; + + /// + /// Set of tools for processing collection of points in 2D space. + /// + /// + /// The static class contains set of routines, which provide different + /// operations with collection of points in 2D space. For example, finding the + /// furthest point from a specified point or line. + /// + /// Sample usage: + /// + /// // create points' list + /// List<IntPoint> points = new List<IntPoint>( ); + /// points.Add( new IntPoint( 10, 10 ) ); + /// points.Add( new IntPoint( 20, 15 ) ); + /// points.Add( new IntPoint( 15, 30 ) ); + /// points.Add( new IntPoint( 40, 12 ) ); + /// points.Add( new IntPoint( 30, 20 ) ); + /// // get furthest point from the specified point + /// IntPoint p1 = PointsCloud.GetFurthestPoint( points, new IntPoint( 15, 15 ) ); + /// Console.WriteLine( p1.X + ", " + p1.Y ); + /// // get furthest point from line + /// IntPoint p2 = PointsCloud.GetFurthestPointFromLine( points, + /// new IntPoint( 50, 0 ), new IntPoint( 0, 50 ) ); + /// Console.WriteLine( p2.X + ", " + p2.Y ); + /// + /// + /// + public static class PointsCloud + { + /// + /// Shift cloud by adding specified value to all points in the collection. + /// + /// + /// Collection of points to shift their coordinates. + /// Point to shift by. + /// + public static void Shift( IList cloud, IntPoint shift ) + { + for ( int i = 0, n = cloud.Count; i < n; i++ ) + { + cloud[i] = cloud[i] + shift; + } + } + + /// + /// Get bounding rectangle of the specified list of points. + /// + /// + /// Collection of points to get bounding rectangle for. + /// Point comprised of smallest X and Y coordinates. + /// Point comprised of biggest X and Y coordinates. + /// + public static void GetBoundingRectangle( IEnumerable cloud, out IntPoint minXY, out IntPoint maxXY ) + { + int minX = int.MaxValue; + int maxX = int.MinValue; + int minY = int.MaxValue; + int maxY = int.MinValue; + + foreach ( IntPoint pt in cloud ) + { + int x = pt.X; + int y = pt.Y; + + // check X coordinate + if ( x < minX ) + minX = x; + if ( x > maxX ) + maxX = x; + + // check Y coordinate + if ( y < minY ) + minY = y; + if ( y > maxY ) + maxY = y; + } + + if ( minX > maxX ) // if no point appeared to set either minX or maxX + throw new ArgumentException( "List of points can not be empty." ); + + minXY = new IntPoint( minX, minY ); + maxXY = new IntPoint( maxX, maxY ); + } + + /// + /// Get center of gravity for the specified list of points. + /// + /// + /// List of points to calculate center of gravity for. + /// + /// Returns center of gravity (mean X-Y values) for the specified list of points. + /// + public static Point GetCenterOfGravity( IEnumerable cloud ) + { + int numberOfPoints = 0; + float xSum = 0, ySum = 0; + + foreach ( IntPoint pt in cloud ) + { + xSum += pt.X; + ySum += pt.Y; + numberOfPoints++; + } + + xSum /= numberOfPoints; + ySum /= numberOfPoints; + + return new Point( xSum, ySum ); + } + + /// + /// Find furthest point from the specified point. + /// + /// + /// Collection of points to search furthest point in. + /// The point to search furthest point from. + /// + /// Returns a point, which is the furthest away from the . + /// + public static IntPoint GetFurthestPoint( IEnumerable cloud, IntPoint referencePoint ) + { + IntPoint furthestPoint = referencePoint; + float maxDistance = -1; + + int rx = referencePoint.X; + int ry = referencePoint.Y; + + foreach ( IntPoint point in cloud ) + { + int dx = rx - point.X; + int dy = ry - point.Y; + // we are not calculating square root for finding "real" distance, + // since it is really not important for finding furthest point + float distance = dx * dx + dy * dy; + + if ( distance > maxDistance ) + { + maxDistance = distance; + furthestPoint = point; + } + } + + return furthestPoint; + } + + /// + /// Find two furthest points from the specified line. + /// + /// + /// Collection of points to search furthest points in. + /// First point forming the line. + /// Second point forming the line. + /// First found furthest point. + /// Second found furthest point (which is on the + /// opposite side from the line compared to the ); + /// + /// The method finds two furthest points from the specified line, + /// where one point is on one side from the line and the second point is on + /// another side from the line. + /// + public static void GetFurthestPointsFromLine( IEnumerable cloud, IntPoint linePoint1, IntPoint linePoint2, + out IntPoint furthestPoint1, out IntPoint furthestPoint2 ) + { + float d1, d2; + + GetFurthestPointsFromLine( cloud, linePoint1, linePoint2, + out furthestPoint1, out d1, out furthestPoint2, out d2 ); + } + + /// + /// Find two furthest points from the specified line. + /// + /// + /// Collection of points to search furthest points in. + /// First point forming the line. + /// Second point forming the line. + /// First found furthest point. + /// Distance between the first found point and the given line. + /// Second found furthest point (which is on the + /// opposite side from the line compared to the ); + /// Distance between the second found point and the given line. + /// + /// The method finds two furthest points from the specified line, + /// where one point is on one side from the line and the second point is on + /// another side from the line. + /// + public static void GetFurthestPointsFromLine( IEnumerable cloud, IntPoint linePoint1, IntPoint linePoint2, + out IntPoint furthestPoint1, out float distance1, out IntPoint furthestPoint2, out float distance2 ) + { + furthestPoint1 = linePoint1; + distance1 = 0; + + furthestPoint2 = linePoint2; + distance2 = 0; + + if ( linePoint2.X != linePoint1.X ) + { + // line's equation y(x) = k * x + b + float k = (float) ( linePoint2.Y - linePoint1.Y ) / ( linePoint2.X - linePoint1.X ); + float b = linePoint1.Y - k * linePoint1.X; + + float div = (float) Math.Sqrt( k * k + 1 ); + float distance = 0; + + foreach ( IntPoint point in cloud ) + { + distance = ( k * point.X + b - point.Y ) / div; + + if ( distance > distance1 ) + { + distance1 = distance; + furthestPoint1 = point; + } + if ( distance < distance2 ) + { + distance2 = distance; + furthestPoint2 = point; + } + } + } + else + { + int lineX = linePoint1.X; + float distance = 0; + + foreach ( IntPoint point in cloud ) + { + distance = lineX - point.X; + + if ( distance > distance1 ) + { + distance1 = distance; + furthestPoint1 = point; + } + if ( distance < distance2 ) + { + distance2 = distance; + furthestPoint2 = point; + } + } + } + + distance2 = -distance2; + } + + /// + /// Find the furthest point from the specified line. + /// + /// + /// Collection of points to search furthest point in. + /// First point forming the line. + /// Second point forming the line. + /// + /// Returns a point, which is the furthest away from the + /// specified line. + /// + /// The method finds the furthest point from the specified line. + /// Unlike the + /// method, this method find only one point, which is the furthest away from the line + /// regardless of side from the line. + /// + public static IntPoint GetFurthestPointFromLine( IEnumerable cloud, IntPoint linePoint1, IntPoint linePoint2 ) + { + float d; + + return GetFurthestPointFromLine( cloud, linePoint1, linePoint2, out d ); + } + + /// + /// Find the furthest point from the specified line. + /// + /// + /// Collection of points to search furthest points in. + /// First point forming the line. + /// Second point forming the line. + /// Distance between the furthest found point and the given line. + /// + /// Returns a point, which is the furthest away from the + /// specified line. + /// + /// The method finds the furthest point from the specified line. + /// Unlike the + /// method, this method find only one point, which is the furthest away from the line + /// regardless of side from the line. + /// + public static IntPoint GetFurthestPointFromLine( IEnumerable cloud, IntPoint linePoint1, IntPoint linePoint2, out float distance ) + { + IntPoint furthestPoint = linePoint1; + distance = 0; + + if ( linePoint2.X != linePoint1.X ) + { + // line's equation y(x) = k * x + b + float k = (float) ( linePoint2.Y - linePoint1.Y ) / ( linePoint2.X - linePoint1.X ); + float b = linePoint1.Y - k * linePoint1.X; + + float div = (float) Math.Sqrt( k * k + 1 ); + float pointDistance = 0; + + foreach ( IntPoint point in cloud ) + { + pointDistance = Math.Abs( ( k * point.X + b - point.Y ) / div ); + + if ( pointDistance > distance ) + { + distance = pointDistance; + furthestPoint = point; + } + } + } + else + { + int lineX = linePoint1.X; + float pointDistance = 0; + + foreach ( IntPoint point in cloud ) + { + distance = Math.Abs( lineX - point.X ); + + if ( pointDistance > distance ) + { + distance = pointDistance; + furthestPoint = point; + } + } + } + + return furthestPoint; + } + + /// + /// Relative distortion limit allowed for quadrilaterals, [0.0, 0.25]. + /// + /// + /// The value of this property is used to calculate distortion limit used by + /// , when processing potential corners and making decision + /// if the provided points form a quadrilateral or a triangle. The distortion limit is + /// calculated as: + /// + /// distrtionLimit = RelativeDistortionLimit * ( W * H ) / 2, + /// + /// where W and H are width and height of the "points cloud" passed to the + /// . + /// + /// + /// To explain the idea behind distortion limit, let’s suppose that quadrilateral finder routine found + /// the next candidates for corners:
+ ///
+ /// As we can see on the above picture, the shape there potentially can be a triangle, but not quadrilateral + /// (suppose that points list comes from a hand drawn picture or acquired from camera, so some + /// inaccuracy may exist). It may happen that the D point is just a distortion (noise, etc). + /// So the check what is the distance between a potential corner + /// (D in this case) and a line connecting two adjacent points (AB in this case). If the distance is smaller + /// then the distortion limit, then the point may be rejected, so the shape turns into triangle. + ///
+ /// + /// An exception is the case when both C and D points are very close to the AB line, + /// so both their distances are less than distortion limit. In this case both points will be accepted as corners - + /// the shape is just a flat quadrilateral. + /// + /// Default value is set to 0.1. + ///
+ /// + public static float QuadrilateralRelativeDistortionLimit + { + get { return quadrilateralRelativeDistortionLimit; } + set { quadrilateralRelativeDistortionLimit = Math.Max( 0.0f, Math.Min( 0.25f, value ) ); } + } + private static float quadrilateralRelativeDistortionLimit = 0.1f; + + /// + /// Find corners of quadrilateral or triangular area, which contains the specified collection of points. + /// + /// + /// Collection of points to search quadrilateral for. + /// + /// Returns a list of 3 or 4 points, which are corners of the quadrilateral or + /// triangular area filled by specified collection of point. The first point in the list + /// is the point with lowest X coordinate (and with lowest Y if there are several points + /// with the same X value). The corners are provided in counter clockwise order + /// (Cartesian + /// coordinate system). + /// + /// The method makes an assumption that the specified collection of points + /// form some sort of quadrilateral/triangular area. With this assumption it tries to find corners + /// of the area. + /// + /// The method does not search for bounding quadrilateral/triangular area, + /// where all specified points are inside of the found quadrilateral/triangle. Some of the + /// specified points potentially may be outside of the found quadrilateral/triangle, since the + /// method takes corners only from the specified collection of points, but does not calculate such + /// to form true bounding quadrilateral/triangle. + /// + /// See property for additional information. + /// + /// + public static List FindQuadrilateralCorners( IEnumerable cloud ) + { + // quadrilateral's corners + List corners = new List( ); + + // get bounding rectangle of the points list + IntPoint minXY, maxXY; + PointsCloud.GetBoundingRectangle( cloud, out minXY, out maxXY ); + // get cloud's size + IntPoint cloudSize = maxXY - minXY; + // calculate center point + IntPoint center = minXY + cloudSize / 2; + // acceptable deviation limit + float distortionLimit = quadrilateralRelativeDistortionLimit * ( cloudSize.X + cloudSize.Y ) / 2; + + // get the furthest point from (0,0) + IntPoint point1 = PointsCloud.GetFurthestPoint( cloud, center ); + // get the furthest point from the first point + IntPoint point2 = PointsCloud.GetFurthestPoint( cloud, point1 ); + + corners.Add( point1 ); + corners.Add( point2 ); + + // get two furthest points from line + IntPoint point3, point4; + float distance3, distance4; + + PointsCloud.GetFurthestPointsFromLine( cloud, point1, point2, + out point3, out distance3, out point4, out distance4 ); + + // ideally points 1 and 2 form a diagonal of the + // quadrilateral area, and points 3 and 4 form another diagonal + + // but if one of the points (3 or 4) is very close to the line + // connecting points 1 and 2, then it is one the same line ... + // which means corner was not found. + // in this case we deal with a trapezoid or triangle, where + // (1-2) line is one of it sides. + + // another interesting case is when both points (3) and (4) are + // very close the (1-2) line. in this case we may have just a flat + // quadrilateral. + + if ( + ( ( distance3 >= distortionLimit ) && ( distance4 >= distortionLimit ) ) || + + ( ( distance3 < distortionLimit ) && ( distance3 != 0 ) && + ( distance4 < distortionLimit ) && ( distance4 != 0 ) ) ) + { + // don't add one of the corners, if the point is already in the corners list + // (this may happen when both #3 and #4 points are very close to the line + // connecting #1 and #2) + if ( !corners.Contains( point3 ) ) + { + corners.Add( point3 ); + } + if ( !corners.Contains( point4 ) ) + { + corners.Add( point4 ); + } + } + else + { + // it seems that we deal with kind of trapezoid, + // where point 1 and 2 are on the same edge + + IntPoint tempPoint = ( distance3 > distance4 ) ? point3 : point4; + + // try to find 3rd point + PointsCloud.GetFurthestPointsFromLine( cloud, point1, tempPoint, + out point3, out distance3, out point4, out distance4 ); + + bool thirdPointIsFound = false; + + if ( ( distance3 >= distortionLimit ) && ( distance4 >= distortionLimit ) ) + { + if ( point4.DistanceTo( point2 ) > point3.DistanceTo( point2 ) ) + point3 = point4; + + thirdPointIsFound = true; + } + else + { + PointsCloud.GetFurthestPointsFromLine( cloud, point2, tempPoint, + out point3, out distance3, out point4, out distance4 ); + + if ( ( distance3 >= distortionLimit ) && ( distance4 >= distortionLimit ) ) + { + if ( point4.DistanceTo( point1 ) > point3.DistanceTo( point1 ) ) + point3 = point4; + + thirdPointIsFound = true; + } + } + + if ( !thirdPointIsFound ) + { + // failed to find 3rd edge point, which is away enough from the temp point. + // this means that the clound looks more like triangle + corners.Add( tempPoint ); + } + else + { + corners.Add( point3 ); + + // try to find 4th point + float tempDistance; + + PointsCloud.GetFurthestPointsFromLine( cloud, point1, point3, + out tempPoint, out tempDistance, out point4, out distance4 ); + + if ( ( distance4 >= distortionLimit ) && ( tempDistance >= distortionLimit ) ) + { + if ( tempPoint.DistanceTo( point2 ) > point4.DistanceTo( point2 ) ) + point4 = tempPoint; + } + else + { + PointsCloud.GetFurthestPointsFromLine( cloud, point2, point3, + out tempPoint, out tempDistance, out point4, out distance4 ); + + if ( ( tempPoint.DistanceTo( point1 ) > point4.DistanceTo( point1 ) ) && + ( tempPoint != point2 ) && ( tempPoint != point3 ) ) + { + point4 = tempPoint; + } + } + + if ( ( point4 != point1 ) && ( point4 != point2 ) && ( point4 != point3 ) ) + corners.Add( point4 ); + } + } + + // put the point with lowest X as the first + for ( int i = 1, n = corners.Count; i < n; i++ ) + { + if ( ( corners[i].X < corners[0].X ) || + ( ( corners[i].X == corners[0].X ) && ( corners[i].Y < corners[0].Y ) ) ) + { + IntPoint temp = corners[i]; + corners[i] = corners[0]; + corners[0] = temp; + } + } + + + // sort other points in counter clockwise order + float k1 = ( corners[1].X != corners[0].X ) ? + ( (float) ( corners[1].Y - corners[0].Y ) / ( corners[1].X - corners[0].X ) ) : + ( ( corners[1].Y > corners[0].Y ) ? float.PositiveInfinity : float.NegativeInfinity ); + + float k2 = ( corners[2].X != corners[0].X ) ? + ( (float) ( corners[2].Y - corners[0].Y ) / ( corners[2].X - corners[0].X ) ) : + ( ( corners[2].Y > corners[0].Y ) ? float.PositiveInfinity : float.NegativeInfinity ); + + if ( k2 < k1 ) + { + IntPoint temp = corners[1]; + corners[1] = corners[2]; + corners[2] = temp; + + float tk = k1; + k1 = k2; + k2 = tk; + } + + if ( corners.Count == 4 ) + { + float k3 = ( corners[3].X != corners[0].X ) ? + ( (float) ( corners[3].Y - corners[0].Y ) / ( corners[3].X - corners[0].X ) ) : + ( ( corners[3].Y > corners[0].Y ) ? float.PositiveInfinity : float.NegativeInfinity ); + + if ( k3 < k1 ) + { + IntPoint temp = corners[1]; + corners[1] = corners[3]; + corners[3] = temp; + + float tk = k1; + k1 = k3; + k3 = tk; + } + if ( k3 < k2 ) + { + IntPoint temp = corners[2]; + corners[2] = corners[3]; + corners[3] = temp; + + float tk = k2; + k2 = k3; + k3 = tk; + } + } + + return corners; + } + } +} diff --git a/Sources/Accord.Math/AForge/Geometry/ShapeType.cs b/Sources/Accord.Math/AForge/Geometry/ShapeType.cs new file mode 100644 index 0000000000..c08131e3f --- /dev/null +++ b/Sources/Accord.Math/AForge/Geometry/ShapeType.cs @@ -0,0 +1,95 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Math.Geometry +{ + using System; + + /// + /// Enumeration of some basic shape types. + /// + public enum ShapeType + { + /// + /// Unknown shape type. + /// + Unknown, + + /// + /// Circle shape. + /// + Circle, + + /// + /// Triangle shape. + /// + Triangle, + + /// + /// Quadrilateral shape. + /// + Quadrilateral, + } + + /// + /// Some common sub types of some basic shapes. + /// + public enum PolygonSubType + { + /// + /// Unrecognized sub type of a shape (generic shape which does not have + /// any specific sub type). + /// + Unknown, + + /// + /// Quadrilateral with one pair of parallel sides. + /// + Trapezoid, + + /// + /// Quadrilateral with two pairs of parallel sides. + /// + Parallelogram, + + /// + /// Parallelogram with perpendicular adjacent sides. + /// + Rectangle, + + /// + /// Parallelogram with all sides equal. + /// + Rhombus, + + /// + /// Rectangle with all sides equal. + /// + Square, + + /// + /// Triangle with all sides/angles equal. + /// + EquilateralTriangle, + + /// + /// Triangle with two sides/angles equal. + /// + IsoscelesTriangle, + + /// + /// Triangle with a 90 degrees angle. + /// + RectangledTriangle, + + /// + /// Triangle with a 90 degrees angle and other two angles are equal. + /// + RectangledIsoscelesTriangle + } +} diff --git a/Sources/Accord.Math/AForge/Geometry/SimpleShapeChecker.cs b/Sources/Accord.Math/AForge/Geometry/SimpleShapeChecker.cs new file mode 100644 index 0000000000..010e51f8e --- /dev/null +++ b/Sources/Accord.Math/AForge/Geometry/SimpleShapeChecker.cs @@ -0,0 +1,559 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Math.Geometry +{ + using System; + using System.Collections.Generic; + using AForge; + + /// + /// A class for checking simple geometrical shapes. + /// + /// + /// The class performs checking/detection of some simple geometrical + /// shapes for provided set of points (shape's edge points). During the check + /// the class goes through the list of all provided points and checks how accurately + /// they fit into assumed shape. + /// + /// All the shape checks allow some deviation of + /// points from the shape with assumed parameters. In other words it is allowed + /// that specified set of points may form a little bit distorted shape, which may be + /// still recognized. The allowed amount of distortion is controlled by two + /// properties ( and ), + /// which allow higher distortion level for bigger shapes and smaller amount of + /// distortion for smaller shapes. Checking specified set of points, the class + /// calculates mean distance between specified set of points and edge of the assumed + /// shape. If the mean distance is equal to or less than maximum allowed distance, + /// then a shape is recognized. The maximum allowed distance is calculated as: + /// + /// maxDistance = max( minAcceptableDistortion, relativeDistortionLimit * ( width + height ) / 2 ) + /// + /// , where width and height is the size of bounding rectangle for the + /// specified points. + /// + /// + /// See also and properties, + /// which set acceptable errors for polygon sub type checking done by + /// method. + /// + /// See the next article for details about the implemented algorithms: + /// Detecting some simple shapes in images. + /// + /// + /// Sample usage: + /// + /// private List<IntPoint> idealCicle = new List<IntPoint>( ); + /// private List<IntPoint> distorredCircle = new List<IntPoint>( ); + /// System.Random rand = new System.Random( ); + /// + /// // generate sample circles + /// float radius = 100; + /// + /// for ( int i = 0; i < 360; i += 10 ) + /// { + /// float angle = (float) ( (float) i / 180 * System.Math.PI ); + /// + /// // add point to ideal circle + /// idealCicle.Add( new IntPoint( + /// (int) ( radius * System.Math.Cos( angle ) ), + /// (int) ( radius * System.Math.Sin( angle ) ) ) ); + /// + /// // add a bit distortion for distorred cirlce + /// float distorredRadius = radius + rand.Next( 7 ) - 3; + /// + /// distorredCircle.Add( new IntPoint( + /// (int) ( distorredRadius * System.Math.Cos( angle ) ), + /// (int) ( distorredRadius * System.Math.Sin( angle ) ) ) ); + /// } + /// + /// // check shape + /// SimpleShapeChecker shapeChecker = new SimpleShapeChecker( ); + /// + /// if ( shapeChecker.IsCircle( idealCicle ) ) + /// { + /// // ... + /// } + /// + /// if ( shapeChecker.CheckShapeType( distorredCircle ) == ShapeType.Circle ) + /// { + /// // ... + /// } + /// + /// + /// + public class SimpleShapeChecker + { + private FlatAnglesOptimizer shapeOptimizer = new FlatAnglesOptimizer( 160 ); + + private float minAcceptableDistortion = 0.5f; + private float relativeDistortionLimit = 0.03f; + + private float angleError = 7; + private float lengthError = 0.1f; + + /// + /// Minimum value of allowed shapes' distortion. + /// + /// + /// The property sets minimum value for allowed shapes' + /// distortion (in pixels). See documentation to + /// class for more details about this property. + /// + /// Default value is set to 0.5. + /// + /// + public float MinAcceptableDistortion + { + get { return minAcceptableDistortion; } + set { minAcceptableDistortion = Math.Max( 0, value ); } + } + + /// + /// Maximum value of allowed shapes' distortion, [0, 1]. + /// + /// + /// The property sets maximum value for allowed shapes' + /// distortion. The value is measured in [0, 1] range, which corresponds + /// to [0%, 100%] range, which means that maximum allowed shapes' + /// distortion is calculated relatively to shape's size. This results to + /// higher allowed distortion level for bigger shapes and smaller allowed + /// distortion for smaller shapers. See documentation to + /// class for more details about this property. + /// + /// Default value is set to 0.03 (3%). + /// + /// + public float RelativeDistortionLimit + { + get { return relativeDistortionLimit; } + set { relativeDistortionLimit = Math.Max( 0, Math.Min( 1, value ) ); } + } + + /// + /// Maximum allowed angle error in degrees, [0, 20]. + /// + /// + /// The value sets maximum allowed difference between two angles to + /// treat them as equal. It is used by method to + /// check for parallel lines and angles of triangles and quadrilaterals. + /// For example, if angle between two lines equals 5 degrees and this properties value + /// is set to 7, then two compared lines are treated as parallel. + /// + /// Default value is set to 7. + /// + /// + public float AngleError + { + get { return angleError; } + set { angleError = Math.Max( 0, Math.Min( 20, value ) ); } + } + + /// + /// Maximum allowed difference in sides' length (relative to shapes' size), [0, 1]. + /// + /// + /// The values sets maximum allowed difference between two sides' length + /// to treat them as equal. The error value is set relative to shapes size and measured + /// in [0, 1] range, which corresponds to [0%, 100%] range. Absolute length error in pixels + /// is calculated as: + /// + /// LengthError * ( width + height ) / 2 + /// + /// , where width and height is the size of bounding rectangle for the + /// specified shape. + /// + /// + /// Default value is set to 0.1 (10%). + /// + /// + public float LengthError + { + get { return lengthError; } + set { lengthError = Math.Max( 0, Math.Min( 1, value ) ); } + } + + /// + /// Check type of the shape formed by specified points. + /// + /// + /// Shape's points to check. + /// + /// Returns type of the detected shape. + /// + public ShapeType CheckShapeType( List edgePoints ) + { + if ( IsCircle( edgePoints ) ) + { + return ShapeType.Circle; + } + + // check for convex polygon + List corners; + + if ( IsConvexPolygon( edgePoints, out corners ) ) + { + return ( corners.Count == 4 ) ? ShapeType.Quadrilateral : ShapeType.Triangle; + } + + return ShapeType.Unknown; + } + + /// + /// Check if the specified set of points form a circle shape. + /// + /// + /// Shape's points to check. + /// + /// Returns if the specified set of points form a + /// circle shape or otherwise. + /// + /// Circle shape must contain at least 8 points to be recognized. + /// The method returns always, of number of points in the specified + /// shape is less than 8. + /// + public bool IsCircle( List edgePoints ) + { + Point center; + float radius; + + return IsCircle( edgePoints, out center, out radius ); + } + + /// + /// Check if the specified set of points form a circle shape. + /// + /// + /// Shape's points to check. + /// Receives circle's center on successful return. + /// Receives circle's radius on successful return. + /// + /// Returns if the specified set of points form a + /// circle shape or otherwise. + /// + /// Circle shape must contain at least 8 points to be recognized. + /// The method returns always, of number of points in the specified + /// shape is less than 8. + /// + public bool IsCircle( List edgePoints, out Point center, out float radius ) + { + // make sure we have at least 8 points for curcle shape + if ( edgePoints.Count < 8 ) + { + center = new Point( 0, 0 ); + radius = 0; + return false; + } + + // get bounding rectangle of the points list + IntPoint minXY, maxXY; + PointsCloud.GetBoundingRectangle( edgePoints, out minXY, out maxXY ); + // get cloud's size + IntPoint cloudSize = maxXY - minXY; + // calculate center point + center = minXY + (Point) cloudSize / 2; + + radius = ( (float) cloudSize.X + cloudSize.Y ) / 4; + + // calculate mean distance between provided edge points and estimated circle’s edge + float meanDistance = 0; + + for ( int i = 0, n = edgePoints.Count; i < n; i++ ) + { + meanDistance += (float) Math.Abs( center.DistanceTo( edgePoints[i] ) - radius ); + } + meanDistance /= edgePoints.Count; + + float maxDitance = Math.Max( minAcceptableDistortion, + ( (float) cloudSize.X + cloudSize.Y ) / 2 * relativeDistortionLimit ); + + return ( meanDistance <= maxDitance ); + } + + /// + /// Check if the specified set of points form a quadrilateral shape. + /// + /// + /// Shape's points to check. + /// + /// Returns if the specified set of points form a + /// quadrilateral shape or otherwise. + /// + public bool IsQuadrilateral( List edgePoints ) + { + List corners; + return IsQuadrilateral( edgePoints, out corners ); + } + + /// + /// Check if the specified set of points form a quadrilateral shape. + /// + /// + /// Shape's points to check. + /// List of quadrilateral corners on successful return. + /// + /// Returns if the specified set of points form a + /// quadrilateral shape or otherwise. + /// + public bool IsQuadrilateral( List edgePoints, out List corners ) + { + corners = GetShapeCorners( edgePoints ); + + if ( corners.Count != 4 ) + return false; + + return CheckIfPointsFitShape( edgePoints, corners ); + } + + /// + /// Check if the specified set of points form a triangle shape. + /// + /// + /// Shape's points to check. + /// + /// Returns if the specified set of points form a + /// triangle shape or otherwise. + /// + public bool IsTriangle( List edgePoints ) + { + List corners; + return IsTriangle( edgePoints, out corners ); + } + + /// + /// Check if the specified set of points form a triangle shape. + /// + /// + /// Shape's points to check. + /// List of triangle corners on successful return. + /// + /// Returns if the specified set of points form a + /// triangle shape or otherwise. + /// + public bool IsTriangle( List edgePoints, out List corners ) + { + corners = GetShapeCorners( edgePoints ); + + if ( corners.Count != 3 ) + return false; + + return CheckIfPointsFitShape( edgePoints, corners ); + } + + /// + /// Check if the specified set of points form a convex polygon shape. + /// + /// + /// Shape's points to check. + /// List of polygon corners on successful return. + /// + /// Returns if the specified set of points form a + /// convex polygon shape or otherwise. + /// + /// The method is able to detect only triangles and quadrilaterals + /// for now. Check number of detected corners to resolve type of the detected polygon. + /// + /// + public bool IsConvexPolygon( List edgePoints, out List corners ) + { + corners = GetShapeCorners( edgePoints ); + return CheckIfPointsFitShape( edgePoints, corners ); + } + + /// + /// Check sub type of a convex polygon. + /// + /// + /// Corners of the convex polygon to check. + /// + /// Return detected sub type of the specified shape. + /// + /// The method check corners of a convex polygon detecting + /// its subtype. Polygon's corners are usually retrieved using + /// method, but can be any list of 3-4 points (only sub types of triangles and + /// quadrilateral are checked). + /// + /// See and properties, + /// which set acceptable errors for polygon sub type checking. + /// + /// + public PolygonSubType CheckPolygonSubType( List corners ) + { + PolygonSubType subType = PolygonSubType.Unknown; + + // get bounding rectangle of the points list + IntPoint minXY, maxXY; + PointsCloud.GetBoundingRectangle( corners, out minXY, out maxXY ); + // get cloud's size + IntPoint cloudSize = maxXY - minXY; + + float maxLengthDiff = lengthError * ( cloudSize.X + cloudSize.Y ) / 2; + + if ( corners.Count == 3 ) + { + // get angles of the triangle + float angle1 = GeometryTools.GetAngleBetweenVectors( corners[0], corners[1], corners[2] ); + float angle2 = GeometryTools.GetAngleBetweenVectors( corners[1], corners[2], corners[0] ); + float angle3 = GeometryTools.GetAngleBetweenVectors( corners[2], corners[0], corners[1] ); + + // check for equilateral triangle + if ( ( Math.Abs( angle1 - 60 ) <= angleError ) && + ( Math.Abs( angle2 - 60 ) <= angleError ) && + ( Math.Abs( angle3 - 60 ) <= angleError ) ) + { + subType = PolygonSubType.EquilateralTriangle; + } + else + { + // check for isosceles triangle + if ( ( Math.Abs( angle1 - angle2 ) <= angleError ) || + ( Math.Abs( angle2 - angle3 ) <= angleError ) || + ( Math.Abs( angle3 - angle1 ) <= angleError ) ) + { + subType = PolygonSubType.IsoscelesTriangle; + } + + // check for rectangled triangle + if ( ( Math.Abs( angle1 - 90 ) <= angleError ) || + ( Math.Abs( angle2 - 90 ) <= angleError ) || + ( Math.Abs( angle3 - 90 ) <= angleError ) ) + { + subType = ( subType == PolygonSubType.IsoscelesTriangle ) ? + PolygonSubType.RectangledIsoscelesTriangle : PolygonSubType.RectangledTriangle; + } + } + } + else if ( corners.Count == 4 ) + { + // get angles between 2 pairs of opposite sides + float angleBetween1stPair = GeometryTools.GetAngleBetweenLines( corners[0], corners[1], corners[2], corners[3] ); + float angleBetween2ndPair = GeometryTools.GetAngleBetweenLines( corners[1], corners[2], corners[3], corners[0] ); + + // check 1st pair for parallelism + if ( angleBetween1stPair <= angleError ) + { + subType = PolygonSubType.Trapezoid; + + // check 2nd pair for parallelism + if ( angleBetween2ndPair <= angleError ) + { + subType = PolygonSubType.Parallelogram; + + // check angle between adjacent sides + if ( Math.Abs( GeometryTools.GetAngleBetweenVectors( corners[1], corners[0], corners[2] ) - 90 ) <= angleError ) + { + subType = PolygonSubType.Rectangle; + } + + // get length of 2 adjacent sides + float side1Length = (float) corners[0].DistanceTo( corners[1] ); + float side2Length = (float) corners[0].DistanceTo( corners[3] ); + + if ( Math.Abs( side1Length - side2Length ) <= maxLengthDiff ) + { + subType = ( subType == PolygonSubType.Parallelogram ) ? + PolygonSubType.Rhombus : PolygonSubType.Square; + } + } + } + else + { + // check 2nd pair for parallelism - last chence to detect trapezoid + if ( angleBetween2ndPair <= angleError ) + { + subType = PolygonSubType.Trapezoid; + } + } + } + + return subType; + } + + /// + /// Check if a shape specified by the set of points fits a convex polygon + /// specified by the set of corners. + /// + /// + /// Shape's points to check. + /// Corners of convex polygon to check fitting into. + /// + /// Returns if the specified shape fits + /// the specified convex polygon or otherwise. + /// + /// The method checks if the set of specified points form the same shape + /// as the set of provided corners. + /// + public bool CheckIfPointsFitShape( List edgePoints, List corners ) + { + int cornersCount = corners.Count; + + // lines coefficients (for representation as y(x)=k*x+b) + float[] k = new float[cornersCount]; + float[] b = new float[cornersCount]; + float[] div = new float[cornersCount]; // precalculated divisor + bool[] isVert = new bool[cornersCount]; + + for ( int i = 0; i < cornersCount; i++ ) + { + IntPoint currentPoint = corners[i]; + IntPoint nextPoint = ( i + 1 == cornersCount ) ? corners[0] : corners[i + 1]; + + if ( !( isVert[i] = nextPoint.X == currentPoint.X ) ) + { + k[i] = (float) ( nextPoint.Y - currentPoint.Y ) / ( nextPoint.X - currentPoint.X ); + b[i] = currentPoint.Y - k[i] * currentPoint.X; + div[i] = (float) Math.Sqrt( k[i] * k[i] + 1 ); + } + } + + // calculate distances between edge points and polygon sides + float meanDistance = 0; + + for ( int i = 0, n = edgePoints.Count; i < n; i++ ) + { + float minDistance = float.MaxValue; + + for ( int j = 0; j < cornersCount; j++ ) + { + float distance = 0; + + if ( !isVert[j] ) + { + distance = (float) Math.Abs( ( k[j] * edgePoints[i].X + b[j] - edgePoints[i].Y ) / div[j] ); + } + else + { + distance = Math.Abs( edgePoints[i].X - corners[j].X ); + } + + if ( distance < minDistance ) + minDistance = distance; + } + + meanDistance += minDistance; + } + meanDistance /= edgePoints.Count; + + // get bounding rectangle of the corners list + IntPoint minXY, maxXY; + PointsCloud.GetBoundingRectangle( corners, out minXY, out maxXY ); + IntPoint rectSize = maxXY - minXY; + + float maxDitance = Math.Max( minAcceptableDistortion, + ( (float) rectSize.X + rectSize.Y ) / 2 * relativeDistortionLimit ); + + return ( meanDistance <= maxDitance ); + } + + // Get optimized quadrilateral area + private List GetShapeCorners( List edgePoints ) + { + return shapeOptimizer.OptimizeShape( PointsCloud.FindQuadrilateralCorners( edgePoints ) ); + } + } +} diff --git a/Sources/Accord.Math/AForge/Histogram.cs b/Sources/Accord.Math/AForge/Histogram.cs new file mode 100644 index 0000000000..f28ad1483 --- /dev/null +++ b/Sources/Accord.Math/AForge/Histogram.cs @@ -0,0 +1,260 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Math +{ + using System; + + /// + /// Histogram for discrete random values. + /// + /// + /// The class wraps histogram for discrete stochastic function, which is represented + /// by integer array, where indexes of the array are treated as values of the stochastic function, + /// but array values are treated as "probabilities" (total amount of hits). + /// + /// + /// Sample usage: + /// + /// // create histogram + /// Histogram histogram = new Histogram( new int[10] { 0, 0, 1, 3, 6, 8, 11, 0, 0, 0 } ); + /// // get mean and standard deviation values + /// Console.WriteLine( "mean = " + histogram.Mean + ", std.dev = " + histogram.StdDev ); + /// + /// + /// + [Serializable] + public class Histogram + { + private int[] values; + private double mean = 0; + private double stdDev = 0; + private int median = 0; + private int min; + private int max; + private long total; + + /// + /// Values of the histogram. + /// + /// + /// Indexes of this array are treated as values of stochastic function, + /// but array values are treated as "probabilities" (total amount of hits). + /// + /// + public int[] Values + { + get { return values; } + } + + /// + /// Mean value. + /// + /// + /// The property allows to retrieve mean value of the histogram. + /// + /// Sample usage: + /// + /// // create histogram + /// Histogram histogram = new Histogram( new int[10] { 0, 0, 1, 3, 6, 8, 11, 0, 0, 0 } ); + /// // get mean value (= 4.862) + /// Console.WriteLine( "mean = " + histogram.Mean.ToString( "F3" ) ); + /// + /// + /// + public double Mean + { + get { return mean; } + } + + /// + /// Standard deviation. + /// + /// + /// The property allows to retrieve standard deviation value of the histogram. + /// + /// Sample usage: + /// + /// // create histogram + /// Histogram histogram = new Histogram( new int[10] { 0, 0, 1, 3, 6, 8, 11, 0, 0, 0 } ); + /// // get std.dev. value (= 1.136) + /// Console.WriteLine( "std.dev. = " + histogram.StdDev.ToString( "F3" ) ); + /// + /// + /// + public double StdDev + { + get { return stdDev; } + } + + /// + /// Median value. + /// + /// + /// The property allows to retrieve median value of the histogram. + /// + /// Sample usage: + /// + /// // create histogram + /// Histogram histogram = new Histogram( new int[10] { 0, 0, 1, 3, 6, 8, 11, 0, 0, 0 } ); + /// // get median value (= 5) + /// Console.WriteLine( "median = " + histogram.Median ); + /// + /// + /// + public int Median + { + get { return median; } + } + + /// + /// Minimum value. + /// + /// + /// The property allows to retrieve minimum value of the histogram with non zero + /// hits count. + /// + /// Sample usage: + /// + /// // create histogram + /// Histogram histogram = new Histogram( new int[10] { 0, 0, 1, 3, 6, 8, 11, 0, 0, 0 } ); + /// // get min value (= 2) + /// Console.WriteLine( "min = " + histogram.Min ); + /// + /// + /// + public int Min + { + get { return min; } + } + + /// + /// Maximum value. + /// + /// + /// The property allows to retrieve maximum value of the histogram with non zero + /// hits count. + /// + /// Sample usage: + /// + /// // create histogram + /// Histogram histogram = new Histogram( new int[10] { 0, 0, 1, 3, 6, 8, 11, 0, 0, 0 } ); + /// // get max value (= 6) + /// Console.WriteLine( "max = " + histogram.Max ); + /// + /// + /// + public int Max + { + get { return max; } + } + + /// + /// Total count of values. + /// + /// + /// The property represents total count of values contributed to the histogram, which is + /// essentially sum of the array. + /// + /// Sample usage: + /// + /// // create histogram + /// Histogram histogram = new Histogram( new int[10] { 0, 0, 1, 3, 6, 8, 11, 0, 0, 0 } ); + /// // get total value (= 29) + /// Console.WriteLine( "total = " + histogram.TotalCount ); + /// + /// + /// + public long TotalCount + { + get { return total; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Values of the histogram. + /// + /// Indexes of the input array are treated as values of stochastic function, + /// but array values are treated as "probabilities" (total amount of hits). + /// + /// + public Histogram( int[] values ) + { + this.values = values; + Update( ); + } + + /// + /// Get range around median containing specified percentage of values. + /// + /// + /// Values percentage around median. + /// + /// Returns the range which containes specifies percentage of values. + /// + /// The method calculates range of stochastic variable, which summary probability + /// comprises the specified percentage of histogram's hits. + /// + /// Sample usage: + /// + /// // create histogram + /// Histogram histogram = new Histogram( new int[10] { 0, 0, 1, 3, 6, 8, 11, 0, 0, 0 } ); + /// // get 50% range + /// IntRange range = histogram.GetRange( 0.5 ); + /// // show the range ([4, 6]) + /// Console.WriteLine( "50% range = [" + range.Min + ", " + range.Max + "]" ); + /// + /// + /// + public IntRange GetRange( double percent ) + { + return Statistics.GetRange( values, percent ); + } + + /// + /// Update statistical value of the histogram. + /// + /// + /// The method recalculates statistical values of the histogram, like mean, + /// standard deviation, etc., in the case if histogram's values were changed directly. + /// The method should be called only in the case if histogram's values were retrieved + /// through property and updated after that. + /// + /// + public void Update( ) + { + int i, n = values.Length; + + max = 0; + min = n; + total = 0; + + // calculate min and max + for ( i = 0; i < n; i++ ) + { + if ( values[i] != 0 ) + { + // max + if ( i > max ) + max = i; + // min + if ( i < min ) + min = i; + + total += values[i]; + } + } + + mean = Statistics.Mean( values ); + stdDev = Statistics.StdDev( values, mean ); + median = Statistics.Median( values ); + } + } +} diff --git a/Sources/Accord.Math/AForge/Matrix3x3.cs b/Sources/Accord.Math/AForge/Matrix3x3.cs new file mode 100644 index 0000000000..c5220f827 --- /dev/null +++ b/Sources/Accord.Math/AForge/Matrix3x3.cs @@ -0,0 +1,901 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Math +{ + using System; + + /// + /// A structure representing 3x3 matrix. + /// + /// + /// The structure incapsulates elements of a 3x3 matrix and + /// provides some operations with it. + /// + [Serializable] + public struct Matrix3x3 + { + /// + /// Row 0 column 0 element of the matrix. + /// + public float V00; + /// + /// Row 0 column 1 element of the matrix. + /// + public float V01; + /// + /// Row 0 column 2 element of the matrix. + /// + public float V02; + + /// + /// Row 1 column 0 element of the matrix. + /// + public float V10; + /// + /// Row 1 column 1 element of the matrix. + /// + public float V11; + /// + /// Row 1 column 2 element of the matrix. + /// + public float V12; + + /// + /// Row 2 column 0 element of the matrix. + /// + public float V20; + /// + /// Row 2 column 1 element of the matrix. + /// + public float V21; + /// + /// Row 2 column 2 element of the matrix. + /// + public float V22; + + /// + /// Provides an identity matrix with all diagonal elements set to 1. + /// + public static Matrix3x3 Identity + { + get + { + Matrix3x3 m = new Matrix3x3( ); + m.V00 = m.V11 = m.V22 = 1; + return m; + } + } + + /// + /// Calculates determinant of the matrix. + /// + public float Determinant + { + get + { + return + V00 * V11 * V22 + V01 * V12 * V20 + V02 * V10 * V21 - + V00 * V12 * V21 - V01 * V10 * V22 - V02 * V11 * V20; + } + } + + /// + /// Returns array representation of the matrix. + /// + /// + /// Returns array which contains all elements of the matrix in the row-major order. + /// + public float[] ToArray( ) + { + return new float[] + { + V00, V01, V02, V10, V11, V12, V20, V21, V22 + }; + } + + /// + /// Creates rotation matrix around Y axis. + /// + /// + /// Rotation angle around Y axis in radians. + /// + /// Returns rotation matrix to rotate an object around Y axis. + /// + public static Matrix3x3 CreateRotationY( float radians ) + { + Matrix3x3 m = new Matrix3x3( ); + + float cos = (float) System.Math.Cos( radians ); + float sin = (float) System.Math.Sin( radians ); + + m.V00 = m.V22 = cos; + m.V02 = sin; + m.V20 = -sin; + m.V11 = 1; + + return m; + } + + /// + /// Creates rotation matrix around X axis. + /// + /// + /// Rotation angle around X axis in radians. + /// + /// Returns rotation matrix to rotate an object around X axis. + /// + public static Matrix3x3 CreateRotationX( float radians ) + { + Matrix3x3 m = new Matrix3x3( ); + + float cos = (float) System.Math.Cos( radians ); + float sin = (float) System.Math.Sin( radians ); + + m.V11 = m.V22 = cos; + m.V12 = -sin; + m.V21 = sin; + m.V00 = 1; + + return m; + } + + /// + /// Creates rotation matrix around Z axis. + /// + /// + /// Rotation angle around Z axis in radians. + /// + /// Returns rotation matrix to rotate an object around Z axis. + /// + public static Matrix3x3 CreateRotationZ( float radians ) + { + Matrix3x3 m = new Matrix3x3( ); + + float cos = (float) System.Math.Cos( radians ); + float sin = (float) System.Math.Sin( radians ); + + m.V00 = m.V11 = cos; + m.V01 = -sin; + m.V10 = sin; + m.V22 = 1; + + return m; + } + + /// + /// Creates rotation matrix to rotate an object around X, Y and Z axes. + /// + /// + /// Rotation angle around Y axis in radians. + /// Rotation angle around X axis in radians. + /// Rotation angle around Z axis in radians. + /// + /// Returns rotation matrix to rotate an object around all 3 axes. + /// + /// + /// The routine assumes roll-pitch-yaw rotation order, when creating rotation + /// matrix, i.e. an object is first rotated around Z axis, then around X axis and finally around + /// Y axis. + /// + /// + public static Matrix3x3 CreateFromYawPitchRoll( float yaw, float pitch, float roll ) + { + return ( CreateRotationY( yaw ) * CreateRotationX( pitch ) ) * CreateRotationZ( roll ); + } + + /// + /// Extract rotation angles from the rotation matrix. + /// + /// + /// Extracted rotation angle around Y axis in radians. + /// Extracted rotation angle around X axis in radians. + /// Extracted rotation angle around Z axis in radians. + /// + /// The routine assumes roll-pitch-yaw rotation order when extracting rotation angle. + /// Using extracted angles with the should provide same rotation matrix. + /// + /// + /// The method assumes the provided matrix represent valid rotation matrix. + /// + /// Sample usage: + /// + /// // assume we have a rotation matrix created like this + /// float yaw = 10.0f / 180 * Math.PI; + /// float pitch = 30.0f / 180 * Math.PI; + /// float roll = 45.0f / 180 * Math.PI; + /// + /// Matrix3x3 rotationMatrix = Matrix3x3.CreateFromYawPitchRoll( yaw, pitch, roll ); + /// // ... + /// + /// // now somewhere in the code you may want to get rotation + /// // angles back from a matrix assuming same rotation order + /// float extractedYaw; + /// float extractedPitch; + /// float extractedRoll; + /// + /// rotation.ExtractYawPitchRoll( out extractedYaw, out extractedPitch, out extractedRoll ); + /// + /// + /// + public void ExtractYawPitchRoll( out float yaw, out float pitch, out float roll ) + { + yaw = (float) Math.Atan2( V02, V22 ); + pitch = (float) Math.Asin( -V12 ); + roll = (float) Math.Atan2( V10, V11 ); + } + + /// + /// Creates a matrix from 3 rows specified as vectors. + /// + /// + /// First row of the matrix to create. + /// Second row of the matrix to create. + /// Third row of the matrix to create. + /// + /// Returns a matrix from specified rows. + /// + public static Matrix3x3 CreateFromRows( Vector3 row0, Vector3 row1, Vector3 row2 ) + { + Matrix3x3 m = new Matrix3x3( ); + + m.V00 = row0.X; + m.V01 = row0.Y; + m.V02 = row0.Z; + + m.V10 = row1.X; + m.V11 = row1.Y; + m.V12 = row1.Z; + + m.V20 = row2.X; + m.V21 = row2.Y; + m.V22 = row2.Z; + + return m; + } + + /// + /// Creates a matrix from 3 columns specified as vectors. + /// + /// + /// First column of the matrix to create. + /// Second column of the matrix to create. + /// Third column of the matrix to create. + /// + /// Returns a matrix from specified columns. + /// + public static Matrix3x3 CreateFromColumns( Vector3 column0, Vector3 column1, Vector3 column2 ) + { + Matrix3x3 m = new Matrix3x3( ); + + m.V00 = column0.X; + m.V10 = column0.Y; + m.V20 = column0.Z; + + m.V01 = column1.X; + m.V11 = column1.Y; + m.V21 = column1.Z; + + m.V02 = column2.X; + m.V12 = column2.Y; + m.V22 = column2.Z; + + return m; + } + + /// + /// Creates a diagonal matrix using the specified vector as diagonal elements. + /// + /// + /// Vector to use for diagonal elements of the matrix. + /// + /// Returns a diagonal matrix. + /// + public static Matrix3x3 CreateDiagonal( Vector3 vector ) + { + Matrix3x3 m = new Matrix3x3( ); + + m.V00 = vector.X; + m.V11 = vector.Y; + m.V22 = vector.Z; + + return m; + } + + /// + /// Get row of the matrix. + /// + /// + /// Row index to get, [0, 2]. + /// + /// Returns specified row of the matrix as a vector. + /// + /// Invalid row index was specified. + /// + public Vector3 GetRow( int index ) + { + if ( ( index < 0 ) || ( index > 2 ) ) + throw new ArgumentException( "Invalid row index was specified.", "index" ); + + return ( index == 0 ) ? new Vector3( V00, V01, V02 ) : + ( index == 1 ) ? new Vector3( V10, V11, V12 ) : new Vector3( V20, V21, V22 ); + } + + /// + /// Get column of the matrix. + /// + /// + /// Column index to get, [0, 2]. + /// + /// Returns specified column of the matrix as a vector. + /// + /// Invalid column index was specified. + /// + public Vector3 GetColumn( int index ) + { + if ( ( index < 0 ) || ( index > 2 ) ) + throw new ArgumentException( "Invalid column index was specified.", "index" ); + + return ( index == 0 ) ? new Vector3( V00, V10, V20 ) : + ( index == 1 ) ? new Vector3( V01, V11, V21 ) : new Vector3( V02, V12, V22 ); + } + + /// + /// Multiplies two specified matrices. + /// + /// + /// Matrix to multiply. + /// Matrix to multiply by. + /// + /// Return new matrix, which the result of multiplication of the two specified matrices. + /// + public static Matrix3x3 operator *( Matrix3x3 matrix1, Matrix3x3 matrix2 ) + { + Matrix3x3 m = new Matrix3x3( ); + + m.V00 = matrix1.V00 * matrix2.V00 + matrix1.V01 * matrix2.V10 + matrix1.V02 * matrix2.V20; + m.V01 = matrix1.V00 * matrix2.V01 + matrix1.V01 * matrix2.V11 + matrix1.V02 * matrix2.V21; + m.V02 = matrix1.V00 * matrix2.V02 + matrix1.V01 * matrix2.V12 + matrix1.V02 * matrix2.V22; + + m.V10 = matrix1.V10 * matrix2.V00 + matrix1.V11 * matrix2.V10 + matrix1.V12 * matrix2.V20; + m.V11 = matrix1.V10 * matrix2.V01 + matrix1.V11 * matrix2.V11 + matrix1.V12 * matrix2.V21; + m.V12 = matrix1.V10 * matrix2.V02 + matrix1.V11 * matrix2.V12 + matrix1.V12 * matrix2.V22; + + m.V20 = matrix1.V20 * matrix2.V00 + matrix1.V21 * matrix2.V10 + matrix1.V22 * matrix2.V20; + m.V21 = matrix1.V20 * matrix2.V01 + matrix1.V21 * matrix2.V11 + matrix1.V22 * matrix2.V21; + m.V22 = matrix1.V20 * matrix2.V02 + matrix1.V21 * matrix2.V12 + matrix1.V22 * matrix2.V22; + + return m; + } + + /// + /// Multiplies two specified matrices. + /// + /// + /// Matrix to multiply. + /// Matrix to multiply by. + /// + /// Return new matrix, which the result of multiplication of the two specified matrices. + /// + public static Matrix3x3 Multiply( Matrix3x3 matrix1, Matrix3x3 matrix2 ) + { + return matrix1 * matrix2; + } + + /// + /// Adds corresponding components of two matrices. + /// + /// + /// The matrix to add to. + /// The matrix to add to the first matrix. + /// + /// Returns a matrix which components are equal to sum of corresponding + /// components of the two specified matrices. + /// + public static Matrix3x3 operator +( Matrix3x3 matrix1, Matrix3x3 matrix2 ) + { + Matrix3x3 m = new Matrix3x3( ); + + m.V00 = matrix1.V00 + matrix2.V00; + m.V01 = matrix1.V01 + matrix2.V01; + m.V02 = matrix1.V02 + matrix2.V02; + + m.V10 = matrix1.V10 + matrix2.V10; + m.V11 = matrix1.V11 + matrix2.V11; + m.V12 = matrix1.V12 + matrix2.V12; + + m.V20 = matrix1.V20 + matrix2.V20; + m.V21 = matrix1.V21 + matrix2.V21; + m.V22 = matrix1.V22 + matrix2.V22; + + return m; + } + + /// + /// Adds corresponding components of two matrices. + /// + /// + /// The matrix to add to. + /// The matrix to add to the first matrix. + /// + /// Returns a matrix which components are equal to sum of corresponding + /// components of the two specified matrices. + /// + public static Matrix3x3 Add( Matrix3x3 matrix1, Matrix3x3 matrix2 ) + { + return matrix1 + matrix2; + } + + /// + /// Subtracts corresponding components of two matrices. + /// + /// + /// The matrix to subtract from. + /// The matrix to subtract from the first matrix. + /// + /// Returns a matrix which components are equal to difference of corresponding + /// components of the two specified matrices. + /// + public static Matrix3x3 operator -( Matrix3x3 matrix1, Matrix3x3 matrix2 ) + { + Matrix3x3 m = new Matrix3x3( ); + + m.V00 = matrix1.V00 - matrix2.V00; + m.V01 = matrix1.V01 - matrix2.V01; + m.V02 = matrix1.V02 - matrix2.V02; + + m.V10 = matrix1.V10 - matrix2.V10; + m.V11 = matrix1.V11 - matrix2.V11; + m.V12 = matrix1.V12 - matrix2.V12; + + m.V20 = matrix1.V20 - matrix2.V20; + m.V21 = matrix1.V21 - matrix2.V21; + m.V22 = matrix1.V22 - matrix2.V22; + + return m; + } + + /// + /// Subtracts corresponding components of two matrices. + /// + /// + /// The matrix to subtract from. + /// The matrix to subtract from the first matrix. + /// + /// Returns a matrix which components are equal to difference of corresponding + /// components of the two specified matrices. + /// + public static Matrix3x3 Subtract( Matrix3x3 matrix1, Matrix3x3 matrix2 ) + { + return matrix1 - matrix2; + } + + /// + /// Multiplies specified matrix by the specified vector. + /// + /// + /// Matrix to multiply by vector. + /// Vector to multiply matrix by. + /// + /// Returns new vector which is the result of multiplication of the specified matrix + /// by the specified vector. + /// + public static Vector3 operator *( Matrix3x3 matrix, Vector3 vector ) + { + return new Vector3( + matrix.V00 * vector.X + matrix.V01 * vector.Y + matrix.V02 * vector.Z, + matrix.V10 * vector.X + matrix.V11 * vector.Y + matrix.V12 * vector.Z, + matrix.V20 * vector.X + matrix.V21 * vector.Y + matrix.V22 * vector.Z ); + } + + /// + /// Multiplies specified matrix by the specified vector. + /// + /// + /// Matrix to multiply by vector. + /// Vector to multiply matrix by. + /// + /// Returns new vector which is the result of multiplication of the specified matrix + /// by the specified vector. + /// + public static Vector3 Multiply( Matrix3x3 matrix, Vector3 vector ) + { + return matrix * vector; + } + + /// + /// Multiplies matrix by the specified factor. + /// + /// + /// Matrix to multiply. + /// Factor to multiple the specified matrix by. + /// + /// Returns new matrix with all components equal to corresponding components of the + /// specified matrix multiples by the specified factor. + /// + public static Matrix3x3 operator *( Matrix3x3 matrix, float factor ) + { + Matrix3x3 m = new Matrix3x3( ); + + m.V00 = matrix.V00 * factor; + m.V01 = matrix.V01 * factor; + m.V02 = matrix.V02 * factor; + + m.V10 = matrix.V10 * factor; + m.V11 = matrix.V11 * factor; + m.V12 = matrix.V12 * factor; + + m.V20 = matrix.V20 * factor; + m.V21 = matrix.V21 * factor; + m.V22 = matrix.V22 * factor; + + return m; + } + + /// + /// Multiplies matrix by the specified factor. + /// + /// + /// Matrix to multiply. + /// Factor to multiple the specified matrix by. + /// + /// Returns new matrix with all components equal to corresponding components of the + /// specified matrix multiples by the specified factor. + /// + public static Matrix3x3 Multiply( Matrix3x3 matrix, float factor ) + { + return matrix * factor; + } + + /// + /// Adds specified value to all components of the specified matrix. + /// + /// + /// Matrix to add value to. + /// Value to add to all components of the specified matrix. + /// + /// Returns new matrix with all components equal to corresponding components of the + /// specified matrix increased by the specified value. + /// + public static Matrix3x3 operator +( Matrix3x3 matrix, float value ) + { + Matrix3x3 m = new Matrix3x3( ); + + m.V00 = matrix.V00 + value; + m.V01 = matrix.V01 + value; + m.V02 = matrix.V02 + value; + + m.V10 = matrix.V10 + value; + m.V11 = matrix.V11 + value; + m.V12 = matrix.V12 + value; + + m.V20 = matrix.V20 + value; + m.V21 = matrix.V21 + value; + m.V22 = matrix.V22 + value; + + return m; + } + + /// + /// Adds specified value to all components of the specified matrix. + /// + /// + /// Matrix to add value to. + /// Value to add to all components of the specified matrix. + /// + /// Returns new matrix with all components equal to corresponding components of the + /// specified matrix increased by the specified value. + /// + public static Matrix3x3 Add( Matrix3x3 matrix, float value ) + { + return matrix + value; + } + + /// + /// Tests whether two specified matrices are equal. + /// + /// + /// The left-hand matrix. + /// The right-hand matrix. + /// + /// Returns if the two matrices are equal or otherwise. + /// + public static bool operator ==( Matrix3x3 matrix1, Matrix3x3 matrix2 ) + { + return ( + ( matrix1.V00 == matrix2.V00 ) && + ( matrix1.V01 == matrix2.V01 ) && + ( matrix1.V02 == matrix2.V02 ) && + + ( matrix1.V10 == matrix2.V10 ) && + ( matrix1.V11 == matrix2.V11 ) && + ( matrix1.V12 == matrix2.V12 ) && + + ( matrix1.V20 == matrix2.V20 ) && + ( matrix1.V21 == matrix2.V21 ) && + ( matrix1.V22 == matrix2.V22 ) + ); + } + + /// + /// Tests whether two specified matrices are not equal. + /// + /// + /// The left-hand matrix. + /// The right-hand matrix. + /// + /// Returns if the two matrices are not equal or otherwise. + /// + public static bool operator !=( Matrix3x3 matrix1, Matrix3x3 matrix2 ) + { + return ( + ( matrix1.V00 != matrix2.V00 ) || + ( matrix1.V01 != matrix2.V01 ) || + ( matrix1.V02 != matrix2.V02 ) || + + ( matrix1.V10 != matrix2.V10 ) || + ( matrix1.V11 != matrix2.V11 ) || + ( matrix1.V12 != matrix2.V12 ) || + + ( matrix1.V20 != matrix2.V20 ) || + ( matrix1.V21 != matrix2.V21 ) || + ( matrix1.V22 != matrix2.V22 ) + ); + } + + /// + /// Tests whether the matrix equals to the specified one. + /// + /// + /// The matrix to test equality with. + /// + /// Returns if the two matrices are equal or otherwise. + /// + public bool Equals( Matrix3x3 matrix ) + { + return ( this == matrix ); + } + + /// + /// Tests whether the matrix equals to the specified object. + /// + /// + /// The object to test equality with. + /// + /// Returns if the matrix equals to the specified object or otherwise. + /// + public override bool Equals( Object obj ) + { + if ( obj is Matrix3x3 ) + { + return Equals( (Matrix3x3) obj ); + } + return false; + } + + /// + /// Returns the hashcode for this instance. + /// + /// + /// A 32-bit signed integer hash code. + /// + public override int GetHashCode( ) + { + return + V00.GetHashCode( ) + V01.GetHashCode( ) + V02.GetHashCode( ) + + V10.GetHashCode( ) + V11.GetHashCode( ) + V12.GetHashCode( ) + + V20.GetHashCode( ) + V21.GetHashCode( ) + V22.GetHashCode( ); + } + + /// + /// Transpose the matrix, AT. + /// + /// + /// Return a matrix which equals to transposition of this matrix. + /// + public Matrix3x3 Transpose( ) + { + Matrix3x3 m = new Matrix3x3( ); + + m.V00 = V00; + m.V01 = V10; + m.V02 = V20; + + m.V10 = V01; + m.V11 = V11; + m.V12 = V21; + + m.V20 = V02; + m.V21 = V12; + m.V22 = V22; + + return m; + } + + /// + /// Multiply the matrix by its transposition, A*AT. + /// + /// + /// Returns a matrix which is the result of multiplying this matrix by its transposition. + /// + public Matrix3x3 MultiplySelfByTranspose( ) + { + Matrix3x3 m = new Matrix3x3( ); + + m.V00 = V00 * V00 + V01 * V01 + V02 * V02; + m.V10 = m.V01 = V00 * V10 + V01 * V11 + V02 * V12; + m.V20 = m.V02 = V00 * V20 + V01 * V21 + V02 * V22; + + m.V11 = V10 * V10 + V11 * V11 + V12 * V12; + m.V21 = m.V12 = V10 * V20 + V11 * V21 + V12 * V22; + + m.V22 = V20 * V20 + V21 * V21 + V22 * V22; + + return m; + } + + /// + /// Multiply transposition of this matrix by itself, AT*A. + /// + /// + /// Returns a matrix which is the result of multiplying this matrix's transposition by itself. + /// + public Matrix3x3 MultiplyTransposeBySelf( ) + { + Matrix3x3 m = new Matrix3x3( ); + + m.V00 = V00 * V00 + V10 * V10 + V20 * V20; + m.V10 = m.V01 = V00 * V01 + V10 * V11 + V20 * V21; + m.V20 = m.V02 = V00 * V02 + V10 * V12 + V20 * V22; + + m.V11 = V01 * V01 + V11 * V11 + V21 * V21; + m.V21 = m.V12 = V01 * V02 + V11 * V12 + V21 * V22; + + m.V22 = V02 * V02 + V12 * V12 + V22 * V22; + + return m; + } + + /// + /// Calculate adjugate of the matrix, adj(A). + /// + /// + /// Returns adjugate of the matrix. + /// + public Matrix3x3 Adjugate( ) + { + Matrix3x3 m = new Matrix3x3( ); + + m.V00 = V11 * V22 - V12 * V21; + m.V01 = -( V01 * V22 - V02 * V21 ); + m.V02 = V01 * V12 - V02 * V11; + + m.V10 = -( V10 * V22 - V12 * V20 ); + m.V11 = V00 * V22 - V02 * V20; + m.V12 = -( V00 * V12 - V02 * V10 ); + + m.V20 = V10 * V21 - V11 * V20; + m.V21 = -( V00 * V21 - V01 * V20 ); + m.V22 = V00 * V11 - V01 * V10; + + return m; + } + + /// + /// Calculate inverse of the matrix, A-1. + /// + /// + /// Returns inverse of the matrix. + /// + /// Cannot calculate inverse of the matrix since it is singular. + /// + public Matrix3x3 Inverse( ) + { + float det = Determinant; + + if ( det == 0 ) + { + throw new ArgumentException( "Cannot calculate inverse of the matrix since it is singular." ); + } + + float detInv = 1 / det; + Matrix3x3 m = Adjugate( ); + + m.V00 *= detInv; + m.V01 *= detInv; + m.V02 *= detInv; + + m.V10 *= detInv; + m.V11 *= detInv; + m.V12 *= detInv; + + m.V20 *= detInv; + m.V21 *= detInv; + m.V22 *= detInv; + + return m; + } + + /// + /// Calculate pseudo inverse of the matrix, A+. + /// + /// + /// Returns pseudo inverse of the matrix. + /// + /// The pseudo inverse of the matrix is calculate through its + /// as V*E+*UT. + /// + public Matrix3x3 PseudoInverse( ) + { + Matrix3x3 u, v; + Vector3 e; + + SVD( out u, out e, out v ); + + return v * CreateDiagonal( e.Inverse( ) ) * u.Transpose( ); + } + + /// + /// Calculate Singular Value Decomposition (SVD) of the matrix, such as A=U*E*VT. + /// + /// + /// Output parameter which gets 3x3 U matrix. + /// Output parameter which gets diagonal elements of the E matrix. + /// Output parameter which gets 3x3 V matrix. + /// + /// Having components U, E and V the source matrix can be reproduced using below code: + /// + /// Matrix3x3 source = u * Matrix3x3.Diagonal( e ) * v.Transpose( ); + /// + /// + /// + public void SVD( out Matrix3x3 u, out Vector3 e, out Matrix3x3 v ) + { + double[,] uArray = new double[3, 3] + { + { V00, V01, V02 }, + { V10, V11, V12 }, + { V20, V21, V22 } + }; + double[,] vArray; + double[] eArray; + + svd.svdcmp( uArray, out eArray, out vArray ); + + // build U matrix + u = new Matrix3x3( ); + u.V00 = (float) uArray[0, 0]; + u.V01 = (float) uArray[0, 1]; + u.V02 = (float) uArray[0, 2]; + u.V10 = (float) uArray[1, 0]; + u.V11 = (float) uArray[1, 1]; + u.V12 = (float) uArray[1, 2]; + u.V20 = (float) uArray[2, 0]; + u.V21 = (float) uArray[2, 1]; + u.V22 = (float) uArray[2, 2]; + + // build V matrix + v = new Matrix3x3( ); + v.V00 = (float) vArray[0, 0]; + v.V01 = (float) vArray[0, 1]; + v.V02 = (float) vArray[0, 2]; + v.V10 = (float) vArray[1, 0]; + v.V11 = (float) vArray[1, 1]; + v.V12 = (float) vArray[1, 2]; + v.V20 = (float) vArray[2, 0]; + v.V21 = (float) vArray[2, 1]; + v.V22 = (float) vArray[2, 2]; + + // build E Vector3 + e = new Vector3( ); + e.X = (float) eArray[0]; + e.Y = (float) eArray[1]; + e.Z = (float) eArray[2]; + } + } +} diff --git a/Sources/Accord.Math/AForge/Matrix4x4.cs b/Sources/Accord.Math/AForge/Matrix4x4.cs new file mode 100644 index 0000000000..8b567fd09 --- /dev/null +++ b/Sources/Accord.Math/AForge/Matrix4x4.cs @@ -0,0 +1,842 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Math +{ + using System; + + /// + /// A structure representing 4x4 matrix. + /// + /// + /// The structure incapsulates elements of a 4x4 matrix and + /// provides some operations with it. + /// + [Serializable] + public struct Matrix4x4 + { + /// + /// Row 0 column 0 element of the matrix. + /// + /// + public float V00; + + /// + /// Row 0 column 1 element of the matrix. + /// + public float V01; + + /// + /// Row 0 column 2 element of the matrix. + /// + public float V02; + + /// + /// Row 0 column 3 element of the matrix. + /// + /// + public float V03; + + /// + /// Row 1 column 0 element of the matrix. + /// + /// + public float V10; + + /// + /// Row 1 column 1 element of the matrix. + /// + /// + public float V11; + + /// + /// Row 1 column 2 element of the matrix. + /// + /// + public float V12; + + /// + /// Row 1 column 3 element of the matrix. + /// + /// + public float V13; + + /// + /// Row 2 column 0 element of the matrix. + /// + /// + public float V20; + + /// + /// Row 2 column 1 element of the matrix. + /// + /// + public float V21; + + /// + /// Row 2 column 2 element of the matrix. + /// + public float V22; + + /// + /// Row 2 column 3 element of the matrix. + /// + public float V23; + + /// + /// Row 3 column 0 element of the matrix. + /// + /// + public float V30; + + /// + /// Row 3 column 1 element of the matrix. + /// + /// + public float V31; + + /// + /// Row 3 column 2 element of the matrix. + /// + /// + public float V32; + + /// + /// Row 3 column 3 element of the matrix. + /// + /// + public float V33; + + /// + /// Provides an identity matrix with all diagonal elements set to 1. + /// + /// + public static Matrix4x4 Identity + { + get + { + Matrix4x4 m = new Matrix4x4(); + m.V00 = m.V11 = m.V22 = m.V33 = 1; + return m; + } + } + + /// + /// Returns array representation of the matrix. + /// + /// + /// Returns array which contains all elements of the matrix in the row-major order. + /// + public float[] ToArray() + { + return new float[] + { + V00, V01, V02, V03, V10, V11, V12, V13, V20, V21, V22, V23, V30, V31, V32, V33 + }; + } + + /// + /// Creates rotation matrix around Y axis. + /// + /// + /// Rotation angle around Y axis in radians. + /// + /// Returns rotation matrix to rotate an object around Y axis. + /// + public static Matrix4x4 CreateRotationY(float radians) + { + Matrix4x4 m = Matrix4x4.Identity; + + float cos = (float)System.Math.Cos(radians); + float sin = (float)System.Math.Sin(radians); + + m.V00 = m.V22 = cos; + m.V02 = sin; + m.V20 = -sin; + + return m; + } + + /// + /// Creates rotation matrix around X axis. + /// + /// + /// Rotation angle around X axis in radians. + /// + /// Returns rotation matrix to rotate an object around X axis. + /// + public static Matrix4x4 CreateRotationX(float radians) + { + Matrix4x4 m = Matrix4x4.Identity; + + float cos = (float)System.Math.Cos(radians); + float sin = (float)System.Math.Sin(radians); + + m.V11 = m.V22 = cos; + m.V12 = -sin; + m.V21 = sin; + + return m; + } + + /// + /// Creates rotation matrix around Z axis. + /// + /// + /// Rotation angle around Z axis in radians. + /// + /// Returns rotation matrix to rotate an object around Z axis. + /// + public static Matrix4x4 CreateRotationZ(float radians) + { + Matrix4x4 m = Matrix4x4.Identity; + + float cos = (float)System.Math.Cos(radians); + float sin = (float)System.Math.Sin(radians); + + m.V00 = m.V11 = cos; + m.V01 = -sin; + m.V10 = sin; + + return m; + } + + /// + /// Creates rotation matrix to rotate an object around X, Y and Z axes. + /// + /// + /// Rotation angle around Y axis in radians. + /// Rotation angle around X axis in radians. + /// Rotation angle around Z axis in radians. + /// + /// Returns rotation matrix to rotate an object around all 3 axes. + /// + /// + /// The routine assumes roll-pitch-yaw rotation order, when creating rotation + /// matrix, i.e. an object is first rotated around Z axis, then around X axis and finally around + /// Y axis. + /// + /// + public static Matrix4x4 CreateFromYawPitchRoll(float yaw, float pitch, float roll) + { + return (CreateRotationY(yaw) * CreateRotationX(pitch)) * CreateRotationZ(roll); + } + + /// + /// Extract rotation angles from the rotation matrix. + /// + /// + /// Extracted rotation angle around Y axis in radians. + /// Extracted rotation angle around X axis in radians. + /// Extracted rotation angle around Z axis in radians. + /// + /// The routine assumes roll-pitch-yaw rotation order when extracting rotation angle. + /// Using extracted angles with the should provide same rotation matrix. + /// + /// + /// The method assumes the provided matrix represent valid rotation matrix. + /// + /// Sample usage: + /// + /// // assume we have a rotation matrix created like this + /// float yaw = 10.0f / 180 * Math.PI; + /// float pitch = 30.0f / 180 * Math.PI; + /// float roll = 45.0f / 180 * Math.PI; + /// + /// Matrix4x4 rotationMatrix = Matrix3x3.CreateFromYawPitchRoll( yaw, pitch, roll ); + /// // ... + /// + /// // now somewhere in the code you may want to get rotation + /// // angles back from a matrix assuming same rotation order + /// float extractedYaw; + /// float extractedPitch; + /// float extractedRoll; + /// + /// rotation.ExtractYawPitchRoll( out extractedYaw, out extractedPitch, out extractedRoll ); + /// + /// + /// + public void ExtractYawPitchRoll(out float yaw, out float pitch, out float roll) + { + yaw = (float)Math.Atan2(V02, V22); + pitch = (float)Math.Asin(-V12); + roll = (float)Math.Atan2(V10, V11); + } + + /// + /// Creates 4x4 tranformation matrix from 3x3 rotation matrix. + /// + /// + /// Source 3x3 rotation matrix. + /// + /// Returns 4x4 rotation matrix. + /// + /// The source 3x3 rotation matrix is copied into the top left corner of the result 4x4 matrix, + /// i.e. it represents 0th, 1st and 2nd row/column. The element is set to 1 and the rest + /// elements of 3rd row and 3rd column are set to zeros. + /// + public static Matrix4x4 CreateFromRotation(Matrix3x3 rotationMatrix) + { + Matrix4x4 m = Matrix4x4.Identity; + + m.V00 = rotationMatrix.V00; + m.V01 = rotationMatrix.V01; + m.V02 = rotationMatrix.V02; + + m.V10 = rotationMatrix.V10; + m.V11 = rotationMatrix.V11; + m.V12 = rotationMatrix.V12; + + m.V20 = rotationMatrix.V20; + m.V21 = rotationMatrix.V21; + m.V22 = rotationMatrix.V22; + + return m; + } + + /// + /// Creates translation matrix for the specified movement amount. + /// + /// + /// Vector which set direction and amount of movement. + /// + /// Returns translation matrix. + /// + /// The specified vector is copied to the 3rd column of the result matrix. + /// All diagonal elements are set to 1. The rest of matrix is initialized with zeros. + /// + public static Matrix4x4 CreateTranslation(Vector3 position) + { + Matrix4x4 m = Matrix4x4.Identity; + + m.V03 = position.X; + m.V13 = position.Y; + m.V23 = position.Z; + + return m; + } + + /// + /// Creates a view matrix for the specified camera position and target point. + /// + /// + /// Position of camera. + /// Target point towards which camera is pointing. + /// + /// Returns a view matrix. + /// + /// Camera's "up" vector is supposed to be (0, 1, 0). + /// + public static Matrix4x4 CreateLookAt(Vector3 cameraPosition, Vector3 cameraTarget) + { + Matrix4x4 m = new Matrix4x4(); + + Vector3 vector = cameraPosition - cameraTarget; + vector.Normalize(); + + Vector3 vector2 = Vector3.Cross(new Vector3(0, 1, 0), vector); + vector2.Normalize(); + + Vector3 vector3 = Vector3.Cross(vector, vector2); + + m.V00 = vector2.X; + m.V01 = vector2.Y; + m.V02 = vector2.Z; + + m.V10 = vector3.X; + m.V11 = vector3.Y; + m.V12 = vector3.Z; + + m.V20 = vector.X; + m.V21 = vector.Y; + m.V22 = vector.Z; + + m.V03 = -Vector3.Dot(cameraPosition, vector2); + m.V13 = -Vector3.Dot(cameraPosition, vector3); + m.V23 = -Vector3.Dot(cameraPosition, vector); + m.V33 = 1; + + return m; + } + + /// + /// Creates a perspective projection matrix. + /// + /// + /// Width of the view volume at the near view plane. + /// Height of the view volume at the near view plane. + /// Distance to the near view plane. + /// Distance to the far view plane. + /// + /// Return a perspective projection matrix. + /// + /// Both near and far view planes' distances must be greater than zero. + /// Near plane must be closer than the far plane. + /// + public static Matrix4x4 CreatePerspective(float width, float height, float nearPlaneDistance, float farPlaneDistance) + { + if (nearPlaneDistance <= 0) + throw new ArgumentOutOfRangeException("nearPlaneDistance ", "Near plane distance must be greater than zero."); + + if (farPlaneDistance <= 0) + throw new ArgumentOutOfRangeException("farPlaneDistance", "Far view plane distance must be greater than zero."); + + if (nearPlaneDistance >= farPlaneDistance) + throw new ArgumentException("Near plane must be closer than the far plane.", "farPlaneDistance"); + + Matrix4x4 m = new Matrix4x4(); + + m.V00 = 2.0f * nearPlaneDistance / width; + m.V11 = 2.0f * nearPlaneDistance / height; + m.V22 = farPlaneDistance / (nearPlaneDistance - farPlaneDistance); + + m.V32 = -1; + m.V23 = (nearPlaneDistance * farPlaneDistance) / (nearPlaneDistance - farPlaneDistance); + + return m; + } + + /// + /// Creates a matrix from 4 rows specified as vectors. + /// + /// + /// First row of the matrix to create. + /// Second row of the matrix to create. + /// Third row of the matrix to create. + /// Fourth row of the matrix to create. + /// + /// Returns a matrix from specified rows. + /// + public static Matrix4x4 CreateFromRows(Vector4 row0, Vector4 row1, Vector4 row2, Vector4 row3) + { + Matrix4x4 m = new Matrix4x4(); + + m.V00 = row0.X; + m.V01 = row0.Y; + m.V02 = row0.Z; + m.V03 = row0.W; + + m.V10 = row1.X; + m.V11 = row1.Y; + m.V12 = row1.Z; + m.V13 = row1.W; + + m.V20 = row2.X; + m.V21 = row2.Y; + m.V22 = row2.Z; + m.V23 = row2.W; + + m.V30 = row3.X; + m.V31 = row3.Y; + m.V32 = row3.Z; + m.V33 = row3.W; + + return m; + } + + /// + /// Creates a matrix from 4 columns specified as vectors. + /// + /// + /// First column of the matrix to create. + /// Second column of the matrix to create. + /// Third column of the matrix to create. + /// Fourth column of the matrix to create. + /// + /// Returns a matrix from specified columns. + /// + public static Matrix4x4 CreateFromColumns(Vector4 column0, Vector4 column1, Vector4 column2, Vector4 column3) + { + Matrix4x4 m = new Matrix4x4(); + + m.V00 = column0.X; + m.V10 = column0.Y; + m.V20 = column0.Z; + m.V30 = column0.W; + + m.V01 = column1.X; + m.V11 = column1.Y; + m.V21 = column1.Z; + m.V31 = column1.W; + + m.V02 = column2.X; + m.V12 = column2.Y; + m.V22 = column2.Z; + m.V32 = column2.W; + + m.V03 = column3.X; + m.V13 = column3.Y; + m.V23 = column3.Z; + m.V33 = column3.W; + + return m; + } + + /// + /// Creates a diagonal matrix using the specified vector as diagonal elements. + /// + /// + /// Vector to use for diagonal elements of the matrix. + /// + /// Returns a diagonal matrix. + /// + public static Matrix4x4 CreateDiagonal(Vector4 vector) + { + Matrix4x4 m = new Matrix4x4(); + + m.V00 = vector.X; + m.V11 = vector.Y; + m.V22 = vector.Z; + m.V33 = vector.W; + + return m; + } + + /// + /// Get row of the matrix. + /// + /// + /// Row index to get, [0, 3]. + /// + /// Returns specified row of the matrix as a vector. + /// + /// Invalid row index was specified. + /// + public Vector4 GetRow(int index) + { + if ((index < 0) || (index > 3)) + throw new ArgumentException("Invalid row index was specified.", "index"); + + return (index == 0) ? new Vector4(V00, V01, V02, V03) : + (index == 1) ? new Vector4(V10, V11, V12, V13) : + (index == 2) ? new Vector4(V20, V21, V22, V23) : new Vector4(V30, V31, V32, V33); + } + + /// + /// Get column of the matrix. + /// + /// + /// Column index to get, [0, 3]. + /// + /// Returns specified column of the matrix as a vector. + /// + /// Invalid column index was specified. + /// + public Vector4 GetColumn(int index) + { + if ((index < 0) || (index > 3)) + throw new ArgumentException("Invalid column index was specified.", "index"); + + return (index == 0) ? new Vector4(V00, V10, V20, V30) : + (index == 1) ? new Vector4(V01, V11, V21, V31) : + (index == 2) ? new Vector4(V02, V12, V22, V32) : new Vector4(V03, V13, V23, V33); + } + + /// + /// Multiplies two specified matrices. + /// + /// + /// Matrix to multiply. + /// Matrix to multiply by. + /// + /// Return new matrix, which the result of multiplication of the two specified matrices. + /// + public static Matrix4x4 operator *(Matrix4x4 matrix1, Matrix4x4 matrix2) + { + Matrix4x4 m = new Matrix4x4(); + + m.V00 = matrix1.V00 * matrix2.V00 + matrix1.V01 * matrix2.V10 + matrix1.V02 * matrix2.V20 + matrix1.V03 * matrix2.V30; + m.V01 = matrix1.V00 * matrix2.V01 + matrix1.V01 * matrix2.V11 + matrix1.V02 * matrix2.V21 + matrix1.V03 * matrix2.V31; + m.V02 = matrix1.V00 * matrix2.V02 + matrix1.V01 * matrix2.V12 + matrix1.V02 * matrix2.V22 + matrix1.V03 * matrix2.V32; + m.V03 = matrix1.V00 * matrix2.V03 + matrix1.V01 * matrix2.V13 + matrix1.V02 * matrix2.V23 + matrix1.V03 * matrix2.V33; + + m.V10 = matrix1.V10 * matrix2.V00 + matrix1.V11 * matrix2.V10 + matrix1.V12 * matrix2.V20 + matrix1.V13 * matrix2.V30; + m.V11 = matrix1.V10 * matrix2.V01 + matrix1.V11 * matrix2.V11 + matrix1.V12 * matrix2.V21 + matrix1.V13 * matrix2.V31; + m.V12 = matrix1.V10 * matrix2.V02 + matrix1.V11 * matrix2.V12 + matrix1.V12 * matrix2.V22 + matrix1.V13 * matrix2.V32; + m.V13 = matrix1.V10 * matrix2.V03 + matrix1.V11 * matrix2.V13 + matrix1.V12 * matrix2.V23 + matrix1.V13 * matrix2.V33; + + m.V20 = matrix1.V20 * matrix2.V00 + matrix1.V21 * matrix2.V10 + matrix1.V22 * matrix2.V20 + matrix1.V23 * matrix2.V30; + m.V21 = matrix1.V20 * matrix2.V01 + matrix1.V21 * matrix2.V11 + matrix1.V22 * matrix2.V21 + matrix1.V23 * matrix2.V31; + m.V22 = matrix1.V20 * matrix2.V02 + matrix1.V21 * matrix2.V12 + matrix1.V22 * matrix2.V22 + matrix1.V23 * matrix2.V32; + m.V23 = matrix1.V20 * matrix2.V03 + matrix1.V21 * matrix2.V13 + matrix1.V22 * matrix2.V23 + matrix1.V23 * matrix2.V33; + + m.V30 = matrix1.V30 * matrix2.V00 + matrix1.V31 * matrix2.V10 + matrix1.V32 * matrix2.V20 + matrix1.V33 * matrix2.V30; + m.V31 = matrix1.V30 * matrix2.V01 + matrix1.V31 * matrix2.V11 + matrix1.V32 * matrix2.V21 + matrix1.V33 * matrix2.V31; + m.V32 = matrix1.V30 * matrix2.V02 + matrix1.V31 * matrix2.V12 + matrix1.V32 * matrix2.V22 + matrix1.V33 * matrix2.V32; + m.V33 = matrix1.V30 * matrix2.V03 + matrix1.V31 * matrix2.V13 + matrix1.V32 * matrix2.V23 + matrix1.V33 * matrix2.V33; + + return m; + } + + /// + /// Multiplies two specified matrices. + /// + /// + /// Matrix to multiply. + /// Matrix to multiply by. + /// + /// Return new matrix, which the result of multiplication of the two specified matrices. + /// + public static Matrix4x4 Multiply(Matrix4x4 matrix1, Matrix4x4 matrix2) + { + return matrix1 * matrix2; + } + + /// + /// Adds corresponding components of two matrices. + /// + /// + /// The matrix to add to. + /// The matrix to add to the first matrix. + /// + /// Returns a matrix which components are equal to sum of corresponding + /// components of the two specified matrices. + /// + public static Matrix4x4 operator +(Matrix4x4 matrix1, Matrix4x4 matrix2) + { + Matrix4x4 m = new Matrix4x4(); + + m.V00 = matrix1.V00 + matrix2.V00; + m.V01 = matrix1.V01 + matrix2.V01; + m.V02 = matrix1.V02 + matrix2.V02; + m.V03 = matrix1.V03 + matrix2.V03; + + m.V10 = matrix1.V10 + matrix2.V10; + m.V11 = matrix1.V11 + matrix2.V11; + m.V12 = matrix1.V12 + matrix2.V12; + m.V13 = matrix1.V13 + matrix2.V13; + + m.V20 = matrix1.V20 + matrix2.V20; + m.V21 = matrix1.V21 + matrix2.V21; + m.V22 = matrix1.V22 + matrix2.V22; + m.V23 = matrix1.V23 + matrix2.V23; + + m.V30 = matrix1.V30 + matrix2.V30; + m.V31 = matrix1.V31 + matrix2.V31; + m.V32 = matrix1.V32 + matrix2.V32; + m.V33 = matrix1.V33 + matrix2.V33; + + return m; + } + + /// + /// Adds corresponding components of two matrices. + /// + /// + /// The matrix to add to. + /// The matrix to add to the first matrix. + /// + /// Returns a matrix which components are equal to sum of corresponding + /// components of the two specified matrices. + /// + public static Matrix4x4 Add(Matrix4x4 matrix1, Matrix4x4 matrix2) + { + return matrix1 + matrix2; + } + + /// + /// Subtracts corresponding components of two matrices. + /// + /// + /// The matrix to subtract from. + /// The matrix to subtract from the first matrix. + /// + /// Returns a matrix which components are equal to difference of corresponding + /// components of the two specified matrices. + /// + public static Matrix4x4 operator -(Matrix4x4 matrix1, Matrix4x4 matrix2) + { + Matrix4x4 m = new Matrix4x4(); + + m.V00 = matrix1.V00 - matrix2.V00; + m.V01 = matrix1.V01 - matrix2.V01; + m.V02 = matrix1.V02 - matrix2.V02; + m.V03 = matrix1.V03 - matrix2.V03; + + m.V10 = matrix1.V10 - matrix2.V10; + m.V11 = matrix1.V11 - matrix2.V11; + m.V12 = matrix1.V12 - matrix2.V12; + m.V13 = matrix1.V13 - matrix2.V13; + + m.V20 = matrix1.V20 - matrix2.V20; + m.V21 = matrix1.V21 - matrix2.V21; + m.V22 = matrix1.V22 - matrix2.V22; + m.V23 = matrix1.V23 - matrix2.V23; + + m.V30 = matrix1.V30 - matrix2.V30; + m.V31 = matrix1.V31 - matrix2.V31; + m.V32 = matrix1.V32 - matrix2.V32; + m.V33 = matrix1.V33 - matrix2.V33; + + return m; + } + + /// + /// Subtracts corresponding components of two matrices. + /// + /// + /// The matrix to subtract from. + /// The matrix to subtract from the first matrix. + /// + /// Returns a matrix which components are equal to difference of corresponding + /// components of the two specified matrices. + /// + public static Matrix4x4 Subtract(Matrix4x4 matrix1, Matrix4x4 matrix2) + { + return matrix1 - matrix2; + } + + /// + /// Multiplies specified matrix by the specified vector. + /// + /// + /// Matrix to multiply by vector. + /// Vector to multiply matrix by. + /// + /// Returns new vector which is the result of multiplication of the specified matrix + /// by the specified vector. + /// + public static Vector4 operator *(Matrix4x4 matrix, Vector4 vector) + { + return new Vector4( + matrix.V00 * vector.X + matrix.V01 * vector.Y + matrix.V02 * vector.Z + matrix.V03 * vector.W, + matrix.V10 * vector.X + matrix.V11 * vector.Y + matrix.V12 * vector.Z + matrix.V13 * vector.W, + matrix.V20 * vector.X + matrix.V21 * vector.Y + matrix.V22 * vector.Z + matrix.V23 * vector.W, + matrix.V30 * vector.X + matrix.V31 * vector.Y + matrix.V32 * vector.Z + matrix.V33 * vector.W + ); + } + + /// + /// Multiplies specified matrix by the specified vector. + /// + /// + /// Matrix to multiply by vector. + /// Vector to multiply matrix by. + /// + /// Returns new vector which is the result of multiplication of the specified matrix + /// by the specified vector. + /// + public static Vector4 Multiply(Matrix4x4 matrix, Vector4 vector) + { + return matrix * vector; + } + + /// + /// Tests whether two specified matrices are equal. + /// + /// + /// The left-hand matrix. + /// The right-hand matrix. + /// + /// Returns if the two matrices are equal or otherwise. + /// + public static bool operator ==(Matrix4x4 matrix1, Matrix4x4 matrix2) + { + return ( + (matrix1.V00 == matrix2.V00) && + (matrix1.V01 == matrix2.V01) && + (matrix1.V02 == matrix2.V02) && + (matrix1.V03 == matrix2.V03) && + + (matrix1.V10 == matrix2.V10) && + (matrix1.V11 == matrix2.V11) && + (matrix1.V12 == matrix2.V12) && + (matrix1.V13 == matrix2.V13) && + + (matrix1.V20 == matrix2.V20) && + (matrix1.V21 == matrix2.V21) && + (matrix1.V22 == matrix2.V22) && + (matrix1.V23 == matrix2.V23) && + + (matrix1.V30 == matrix2.V30) && + (matrix1.V31 == matrix2.V31) && + (matrix1.V32 == matrix2.V32) && + (matrix1.V33 == matrix2.V33) + ); + } + + /// + /// Tests whether two specified matrices are not equal. + /// + /// + /// The left-hand matrix. + /// The right-hand matrix. + /// + /// Returns if the two matrices are not equal or otherwise. + /// + public static bool operator !=(Matrix4x4 matrix1, Matrix4x4 matrix2) + { + return ( + (matrix1.V00 != matrix2.V00) || + (matrix1.V01 != matrix2.V01) || + (matrix1.V02 != matrix2.V02) || + (matrix1.V03 != matrix2.V03) || + + (matrix1.V10 != matrix2.V10) || + (matrix1.V11 != matrix2.V11) || + (matrix1.V12 != matrix2.V12) || + (matrix1.V13 != matrix2.V13) || + + (matrix1.V20 != matrix2.V20) || + (matrix1.V21 != matrix2.V21) || + (matrix1.V22 != matrix2.V22) || + (matrix1.V23 != matrix2.V23) || + + (matrix1.V30 != matrix2.V30) || + (matrix1.V31 != matrix2.V31) || + (matrix1.V32 != matrix2.V32) || + (matrix1.V33 != matrix2.V33) + ); + } + + /// + /// Tests whether the matrix equals to the specified one. + /// + /// + /// The matrix to test equality with. + /// + /// Returns if the two matrices are equal or otherwise. + /// + public bool Equals(Matrix4x4 matrix) + { + return (this == matrix); + } + + /// + /// Tests whether the matrix equals to the specified object. + /// + /// + /// The object to test equality with. + /// + /// Returns if the matrix equals to the specified object or otherwise. + /// + public override bool Equals(Object obj) + { + if (obj is Matrix4x4) + { + return Equals((Matrix4x4)obj); + } + return false; + } + + /// + /// Returns the hashcode for this instance. + /// + /// + /// A 32-bit signed integer hash code. + /// + public override int GetHashCode() + { + return + V00.GetHashCode() + V01.GetHashCode() + V02.GetHashCode() + V03.GetHashCode() + + V10.GetHashCode() + V11.GetHashCode() + V12.GetHashCode() + V13.GetHashCode() + + V20.GetHashCode() + V21.GetHashCode() + V22.GetHashCode() + V23.GetHashCode() + + V30.GetHashCode() + V31.GetHashCode() + V32.GetHashCode() + V33.GetHashCode(); + } + } +} diff --git a/Sources/Accord.Math/AForge/Metrics/CosineDistance.cs b/Sources/Accord.Math/AForge/Metrics/CosineDistance.cs new file mode 100644 index 0000000000..ba61dc068 --- /dev/null +++ b/Sources/Accord.Math/AForge/Metrics/CosineDistance.cs @@ -0,0 +1,57 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2010 +// contacts@aforgenet.com +// + +namespace AForge.Math.Metrics +{ + using System; + + /// + /// Cosine distance metric. + /// + /// + /// This class represents the cosine distance metric (1 - cosine similarity) + /// . + /// + /// + /// Sample usage: + /// + /// // instantiate new distance class + /// CosineDistance dist = new CosineDistance(); + /// // create two vectors for inputs + /// double[] p = new double[] { 2.5, 3.5, 3.0, 3.5, 2.5, 3.0 }; + /// double[] q = new double[] { 3.0, 3.5, 1.5, 5.0, 3.5, 3.0 }; + /// // get distance between the two vectors + /// double distance = dist.GetDistance( p, q ); + /// + /// + /// + public sealed class CosineDistance : IDistance + { + /// + /// Returns distance between two N-dimensional double vectors. + /// + /// + /// 1st point vector. + /// 2nd point vector. + /// + /// Returns Cosine distance between two supplied vectors. + /// + /// Thrown if the two vectors are of different dimensions (if specified + /// array have different length). + /// + public double GetDistance( double[] p, double[] q ) + { + double distance; + + CosineSimilarity dist = new CosineSimilarity( ); + distance = (double) 1 - dist.GetSimilarityScore( p, q ); + + return distance; + } + } +} diff --git a/Sources/Accord.Math/AForge/Metrics/CosineSimilarity.cs b/Sources/Accord.Math/AForge/Metrics/CosineSimilarity.cs new file mode 100644 index 0000000000..9c39b4934 --- /dev/null +++ b/Sources/Accord.Math/AForge/Metrics/CosineSimilarity.cs @@ -0,0 +1,69 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2010 +// contacts@aforgenet.com +// + +namespace AForge.Math.Metrics +{ + using System; + + /// + /// Cosine similarity metric. + /// + /// + /// This class represents the + /// Cosine Similarity metric. + /// + /// Sample usage: + /// + /// // instantiate new similarity class + /// CosineSimilarity sim = new CosineSimilarity( ); + /// // create two vectors for inputs + /// double[] p = new double[] { 2.5, 3.5, 3.0, 3.5, 2.5, 3.0 }; + /// double[] q = new double[] { 3.0, 3.5, 1.5, 5.0, 3.5, 3.0 }; + /// // get similarity between the two vectors + /// double similarityScore = sim.GetSimilarityScore( p, q ); + /// + /// + /// + public sealed class CosineSimilarity : ISimilarity + { + /// + /// Returns similarity score for two N-dimensional double vectors. + /// + /// + /// 1st point vector. + /// 2nd point vector. + /// + /// Returns Cosine similarity between two supplied vectors. + /// + /// Thrown if the two vectors are of different dimensions (if specified + /// array have different length). + /// + public double GetSimilarityScore( double[] p, double[] q ) + { + double denominator = 0, numerator = 0, pSumSq = 0, qSumSq = 0; + double pValue, qValue; + + if ( p.Length != q.Length ) + throw new ArgumentException( "Input vectors must be of the same dimension." ); + + for ( int x = 0, len = p.Length; x < len; x++ ) + { + pValue = p[x]; + qValue = q[x]; + + numerator += pValue * qValue; + pSumSq += pValue * pValue; + qSumSq += qValue * qValue; + } + + denominator = Math.Sqrt( pSumSq ) * Math.Sqrt( qSumSq ); + + return ( denominator == 0 ) ? 0 : numerator / denominator; + } + } +} diff --git a/Sources/Accord.Math/AForge/Metrics/EuclideanDistance.cs b/Sources/Accord.Math/AForge/Metrics/EuclideanDistance.cs new file mode 100644 index 0000000000..934c4a188 --- /dev/null +++ b/Sources/Accord.Math/AForge/Metrics/EuclideanDistance.cs @@ -0,0 +1,63 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2010 +// contacts@aforgenet.com +// + +namespace AForge.Math.Metrics +{ + using System; + + /// + /// Euclidean distance metric. + /// + /// + /// This class represents the + /// Euclidean distance metric. + /// + /// Sample usage: + /// + /// // instantiate new distance class + /// EuclideanDistance dist = new EuclideanDistance( ); + /// // create two vectors for inputs + /// double[] p = new double[] { 2.5, 3.5, 3.0, 3.5, 2.5, 3.0 }; + /// double[] q = new double[] { 3.0, 3.5, 1.5, 5.0, 3.5, 3.0 }; + /// // get distance between the two vectors + /// double distance = dist.GetDistance( p, q ); + /// + /// + /// + public sealed class EuclideanDistance : IDistance + { + /// + /// Returns distance between two N-dimensional double vectors. + /// + /// + /// 1st point vector. + /// 2nd point vector. + /// + /// Returns Euclidean distance between two supplied vectors. + /// + /// Thrown if the two vectors are of different dimensions (if specified + /// array have different length). + /// + public double GetDistance( double[] p, double[] q ) + { + double distance = 0; + double diff = 0; + + if ( p.Length != q.Length ) + throw new ArgumentException( "Input vectors must be of the same dimension." ); + + for ( int x = 0, len = p.Length; x < len; x++ ) + { + diff = p[x] - q[x]; + distance += diff * diff; + } + + return Math.Sqrt( distance ); + } + } +} diff --git a/Sources/Accord.Math/AForge/Metrics/EuclideanSimilarity.cs b/Sources/Accord.Math/AForge/Metrics/EuclideanSimilarity.cs new file mode 100644 index 0000000000..ede99d3a9 --- /dev/null +++ b/Sources/Accord.Math/AForge/Metrics/EuclideanSimilarity.cs @@ -0,0 +1,57 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2010 +// contacts@aforgenet.com +// + +namespace AForge.Math.Metrics +{ + using System; + + /// + /// Euclidean similarity metric. + /// + /// + /// This class represents the + /// Euclidean Similarity metric, + /// which is calculated as 1.0 / ( 1.0 + EuclideanDistance ). + /// + /// Sample usage: + /// + /// // instantiate new similarity class + /// EuclideanSimilarity sim = new EuclideanSimilarity( ); + /// // create two vectors for inputs + /// double[] p = new double[] { 2.5, 3.5, 3.0, 3.5, 2.5, 3.0 }; + /// double[] q = new double[] { 3.0, 3.5, 1.5, 5.0, 3.5, 3.0 }; + /// // get simirarity between the two vectors + /// double similarityScore = sim.GetSimilarityScore( p, q ); + /// + /// + /// + public sealed class EuclideanSimilarity : ISimilarity + { + /// + /// Returns similarity score for two N-dimensional double vectors. + /// + /// + /// 1st point vector. + /// 2nd point vector. + /// + /// Returns Euclidean similarity between two supplied vectors. + /// + /// Thrown if the two vectors are of different dimensions (if specified + /// array have different length). + /// + public double GetSimilarityScore( double[] p, double[] q ) + { + double distance = 0; + + EuclideanDistance dist = new EuclideanDistance( ); + distance = 1.0 / ( 1.0 + dist.GetDistance( p, q ) ); + + return distance; + } + } +} diff --git a/Sources/Accord.Math/AForge/Metrics/HammingDistance.cs b/Sources/Accord.Math/AForge/Metrics/HammingDistance.cs new file mode 100644 index 0000000000..d169256c4 --- /dev/null +++ b/Sources/Accord.Math/AForge/Metrics/HammingDistance.cs @@ -0,0 +1,62 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2010 +// contacts@aforgenet.com +// + +namespace AForge.Math.Metrics +{ + using System; + + /// + /// Hamming distance metric. + /// + /// + /// This class represents the + /// Hamming distance metric. + /// + /// Sample usage: + /// + /// // instantiate new distance class + /// HammingDistance dist = new HammingDistance( ); + /// // create two vectors for inputs + /// double[] p = new double[] { 2.5, 3.5, 3.0, 3.5, 2.5, 3.0 }; + /// double[] q = new double[] { 3.0, 3.5, 1.5, 5.0, 3.5, 3.0 }; + /// // get distance between the two vectors + /// double distance = dist.GetDistance( p, q ); + /// + /// + /// + public sealed class HammingDistance : IDistance + { + /// + /// Returns distance between two N-dimensional double vectors. + /// + /// + /// 1st point vector. + /// 2nd point vector. + /// + /// Returns Hamming distance between two supplied vectors. + /// + /// Thrown if the two vectors are of different dimensions (if specified + /// array have different length). + /// + public double GetDistance( double[] p, double[] q ) + { + double distance = 0; + + if ( p.Length != q.Length ) + throw new ArgumentException( "Input vectors must be of the same dimension." ); + + for ( int x = 0, len = p.Length; x < len; x++ ) + { + if ( p[x] != q[x] ) + distance++; + } + + return distance; + } + } +} diff --git a/Sources/Accord.Math/AForge/Metrics/IDistance.cs b/Sources/Accord.Math/AForge/Metrics/IDistance.cs new file mode 100644 index 0000000000..08dd444d6 --- /dev/null +++ b/Sources/Accord.Math/AForge/Metrics/IDistance.cs @@ -0,0 +1,41 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2010 +// contacts@aforgenet.com +// + +namespace AForge.Math.Metrics +{ + using System; + + /// + /// Interface for distance metric algorithms. + /// + /// + /// The interface defines a set of methods implemented + /// by distance metric algorithms. These algorithms typically take a set of points and return a + /// distance measure of the x and y coordinates. In this case, the points are represented by two vectors. + /// + /// Distance metric algorithms are used in many machine learning algorithms e.g K-nearest neighbor + /// and K-means clustering. + /// + /// For additional details about distance metrics, documentation of the + /// particular algorithms should be studied. + /// + /// + public interface IDistance + { + /// + /// Returns distance between two N-dimensional double vectors. + /// + /// + /// 1st point vector. + /// 2nd point vector. + /// + /// Returns distance measurement determined by the given algorithm. + /// + double GetDistance( double[] p, double[] q ); + } +} diff --git a/Sources/Accord.Math/AForge/Metrics/ISimilarity.cs b/Sources/Accord.Math/AForge/Metrics/ISimilarity.cs new file mode 100644 index 0000000000..cdd015b91 --- /dev/null +++ b/Sources/Accord.Math/AForge/Metrics/ISimilarity.cs @@ -0,0 +1,41 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2010 +// contacts@aforgenet.com +// + +namespace AForge.Math.Metrics +{ + using System; + + /// + /// Interface for similarity algorithms. + /// + /// + /// The interface defines a set of methods implemented + /// by similarity and correlation algorithms. These algorithms typically take a set of points and return a + /// similarity score for the two vectors. + /// + /// Similarity and correlation algorithms are used in many machine learning and collaborative + /// filtering algorithms. + /// + /// For additional details about similarity metrics, documentation of the + /// particular algorithms should be studied. + /// + /// + public interface ISimilarity + { + /// + /// Returns similarity score for two N-dimensional double vectors. + /// + /// + /// 1st point vector. + /// 2nd point vector. + /// + /// Returns similarity score determined by the given algorithm. + /// + double GetSimilarityScore( double[] p, double[] q ); + } +} diff --git a/Sources/Accord.Math/AForge/Metrics/JaccardDistance.cs b/Sources/Accord.Math/AForge/Metrics/JaccardDistance.cs new file mode 100644 index 0000000000..ca197eb57 --- /dev/null +++ b/Sources/Accord.Math/AForge/Metrics/JaccardDistance.cs @@ -0,0 +1,75 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2010 +// contacts@aforgenet.com +// + +namespace AForge.Math.Metrics +{ + using System; + + /// + /// Jaccard distance metric. + /// + /// + /// This class represents the + /// Jaccard distance metric. + /// + /// Sample usage: + /// + /// // instantiate new distance class + /// JaccardDistance dist = new JaccardDistance( ); + /// // create two vectors for inputs + /// double[] p = new double[] { 2.5, 3.5, 3.0, 3.5, 2.5, 3.0 }; + /// double[] q = new double[] { 3.0, 3.5, 1.5, 5.0, 3.5, 3.0 }; + /// // get distance between the two vectors + /// double distance = dist.GetDistance( p, q ); + /// + /// + /// + public sealed class JaccardDistance : IDistance + { + /// + /// Returns distance between two N-dimensional double vectors. + /// + /// + /// 1st point vector. + /// 2nd point vector. + /// + /// Returns Jaccard distance between two supplied vectors. + /// + /// Thrown if the two vectors are of different dimensions (if specified + /// array have different length). + /// + public double GetDistance( double[] p, double[] q ) + { + double distance = 0; + int intersection = 0, union = 0; + + if ( p.Length != q.Length ) + throw new ArgumentException( "Input vectors must be of the same dimension." ); + + for ( int x = 0, len = p.Length; x < len; x++ ) + { + if ( ( p[x] != 0 ) || ( q[x] != 0 ) ) + { + if ( p[x] == q[x] ) + { + intersection++; + } + + union++; + } + } + + if ( union != 0 ) + distance = 1.0 - ( (double) intersection / (double) union ); + else + distance = 0; + + return distance; + } + } +} diff --git a/Sources/Accord.Math/AForge/Metrics/ManhattanDistance.cs b/Sources/Accord.Math/AForge/Metrics/ManhattanDistance.cs new file mode 100644 index 0000000000..ac15cd07b --- /dev/null +++ b/Sources/Accord.Math/AForge/Metrics/ManhattanDistance.cs @@ -0,0 +1,62 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2010 +// contacts@aforgenet.com +// + +namespace AForge.Math.Metrics +{ + using System; + + /// + /// Manhattan distance metric. + /// + /// + /// This class represents the + /// Manhattan distance metric + /// (aka City Block and Taxi Cab distance). + /// + /// Sample usage: + /// + /// // instantiate new distance class + /// ManhattanDistance dist = new ManhattanDistance( ); + /// // create two vectors for inputs + /// double[] p = new double[] { 2.5, 3.5, 3.0, 3.5, 2.5, 3.0 }; + /// double[] q = new double[] { 3.0, 3.5, 1.5, 5.0, 3.5, 3.0 }; + /// // get distance between the two vectors + /// double distance = dist.GetDistance( p, q ); + /// + /// + /// + public sealed class ManhattanDistance : IDistance + { + /// + /// Returns distance between two N-dimensional double vectors. + /// + /// + /// 1st point vector. + /// 2nd point vector. + /// + /// Returns Manhattan distance between two supplied vectors. + /// + /// Thrown if the two vectors are of different dimensions (if specified + /// array have different length). + /// + public double GetDistance( double[] p, double[] q ) + { + double distance = 0; + + if ( p.Length != q.Length ) + throw new ArgumentException( "Input vectors must be of the same dimension." ); + + for ( int x = 0, len = p.Length; x < len; x++ ) + { + distance += Math.Abs( p[x] - q[x] ); + } + + return distance; + } + } +} diff --git a/Sources/Accord.Math/AForge/Metrics/PearsonCorrelation.cs b/Sources/Accord.Math/AForge/Metrics/PearsonCorrelation.cs new file mode 100644 index 0000000000..f452f3869 --- /dev/null +++ b/Sources/Accord.Math/AForge/Metrics/PearsonCorrelation.cs @@ -0,0 +1,73 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2010 +// contacts@aforgenet.com +// + +namespace AForge.Math.Metrics +{ + using System; + + /// + /// Pearson correlation metric. + /// + /// + /// This class represents the + /// Pearson correlation metric. + /// + /// Sample usage: + /// + /// // instantiate new pearson correlation class + /// PearsonCorrelation cor = new PearsonCorrelation( ); + /// // create two vectors for inputs + /// double[] p = new double[] { 2.5, 3.5, 3.0, 3.5, 2.5, 3.0 }; + /// double[] q = new double[] { 3.0, 3.5, 1.5, 5.0, 3.5, 3.0 }; + /// // get correlation between the two vectors + /// double correlation = cor.GetSimilarityScore( p, q ); + /// + /// + /// + public sealed class PearsonCorrelation : ISimilarity + { + /// + /// Returns the pearson correlation for two N-dimensional double vectors. + /// + /// + /// 1st point vector. + /// 2nd point vector. + /// + /// Returns Pearson correlation between two supplied vectors. + /// + /// Thrown if the two vectors are of different dimensions (if specified + /// array have different length). + /// + public double GetSimilarityScore( double[] p, double[] q ) + { + double pSum = 0, qSum = 0, pSumSq = 0, qSumSq = 0, productSum = 0; + double pValue, qValue; + int n = p.Length; + + if ( n != q.Length ) + throw new ArgumentException( "Input vectors must be of the same dimension." ); + + for ( int x = 0; x < n; x++ ) + { + pValue = p[x]; + qValue = q[x]; + + pSum += pValue; + qSum += qValue; + pSumSq += pValue * pValue; + qSumSq += qValue * qValue; + productSum += pValue * qValue; + } + + double numerator = productSum - ( ( pSum * qSum ) / (double) n ); + double denominator = Math.Sqrt( ( pSumSq - ( pSum * pSum ) / (double) n ) * ( qSumSq - ( qSum * qSum ) / (double) n ) ); + + return ( denominator == 0 ) ? 0 : numerator / denominator; + } + } +} diff --git a/Sources/Accord.Math/AForge/PerlinNoise.cs b/Sources/Accord.Math/AForge/PerlinNoise.cs new file mode 100644 index 0000000000..950cec69f --- /dev/null +++ b/Sources/Accord.Math/AForge/PerlinNoise.cs @@ -0,0 +1,275 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Math +{ + using System; + + /// + /// Perlin noise function. + /// + /// + /// The class implements 1-D and 2-D Perlin noise functions, which represent + /// sum of several smooth noise functions with different frequency and amplitude. The description + /// of Perlin noise function and its calculation may be found on + /// Hugo Elias's page. + /// + /// + /// The number of noise functions, which comprise the resulting Perlin noise function, is + /// set by property. Amplitude and frequency values for each octave + /// start from values, which are set by and + /// properties. + /// + /// Sample usage (clouds effect): + /// + /// // create Perlin noise function + /// PerlinNoise noise = new PerlinNoise( 8, 0.5, 1.0 / 32 ); + /// // generate clouds effect + /// float[,] texture = new float[height, width]; + /// + /// for ( int y = 0; y < height; y++ ) + /// { + /// for ( int x = 0; x < width; x++ ) + /// { + /// texture[y, x] = + /// Math.Max( 0.0f, Math.Min( 1.0f, + /// (float) noise.Function2D( x, y ) * 0.5f + 0.5f + /// ) ); + /// } + /// } + /// + /// + /// + public class PerlinNoise + { + private double initFrequency = 1.0; + private double initAmplitude = 1.0; + private double persistence = 0.65; + private int octaves = 4; + + /// + /// Initial frequency. + /// + /// + /// The property sets initial frequency of the first octave. Frequencies for + /// next octaves are calculated using the next equation:
+ /// frequencyi = * 2i, + /// where i = [0, ). + ///
+ /// + /// Default value is set to 1. + ///
+ /// + public double InitFrequency + { + get { return initFrequency; } + set { initFrequency = value; } + } + + /// + /// Initial amplitude. + /// + /// + /// The property sets initial amplitude of the first octave. Amplitudes for + /// next octaves are calculated using the next equation:
+ /// amplitudei = * i, + /// where i = [0, ). + ///
+ /// + /// Default value is set to 1. + ///
+ /// + public double InitAmplitude + { + get { return initAmplitude; } + set { initAmplitude = value; } + } + + /// + /// Persistence value. + /// + /// + /// The property sets so called persistence value, which controls the way + /// how amplitude is calculated for each octave comprising + /// the Perlin noise function. + /// + /// Default value is set to 0.65. + /// + /// + public double Persistence + { + get { return persistence; } + set { persistence = value; } + } + + /// + /// Number of octaves, [1, 32]. + /// + /// + /// The property sets the number of noise functions, which sum up the resulting + /// Perlin noise function. + /// + /// Default value is set to 4. + /// + /// + public int Octaves + { + get { return octaves; } + set { octaves = System.Math.Max(1, System.Math.Min(32, value)); } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public PerlinNoise() { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Number of octaves (see property). + /// Persistence value (see property). + /// + public PerlinNoise(int octaves, double persistence) + { + this.octaves = octaves; + this.persistence = persistence; + } + /// + /// Initializes a new instance of the class. + /// + /// + /// Number of octaves (see property). + /// Persistence value (see property). + /// Initial frequency (see property). + /// Initial amplitude (see property). + /// + public PerlinNoise(int octaves, double persistence, double initFrequency, double initAmplitude) + { + this.octaves = octaves; + this.persistence = persistence; + this.initFrequency = initFrequency; + this.initAmplitude = initAmplitude; + } + + /// + /// 1-D Perlin noise function. + /// + /// + /// x value. + /// + /// Returns function's value at point . + /// + public double Function(double x) + { + double frequency = initFrequency; + double amplitude = initAmplitude; + double sum = 0; + + // octaves + for (int i = 0; i < octaves; i++) + { + sum += SmoothedNoise(x * frequency) * amplitude; + + frequency *= 2; + amplitude *= persistence; + } + return sum; + } + + /// + /// 2-D Perlin noise function. + /// + /// + /// x value. + /// y value. + /// + /// Returns function's value at point (, ). + /// + public double Function2D(double x, double y) + { + double frequency = initFrequency; + double amplitude = initAmplitude; + double sum = 0; + + // octaves + for (int i = 0; i < octaves; i++) + { + sum += SmoothedNoise(x * frequency, y * frequency) * amplitude; + + frequency *= 2; + amplitude *= persistence; + } + return sum; + } + + + /// + /// Ordinary noise function + /// + /// + private static double Noise(int x) + { + int n = (x << 13) ^ x; + + return (1.0 - ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0); + } + + private static double Noise(int x, int y) + { + int n = x + y * 57; + n = (n << 13) ^ n; + + return (1.0 - ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0); + } + + + /// + /// Smoothed noise. + /// + private static double SmoothedNoise(double x) + { + int xInt = (int)x; + double xFrac = x - xInt; + + return CosineInterpolate(Noise(xInt), Noise(xInt + 1), xFrac); + } + + private static double SmoothedNoise(double x, double y) + { + int xInt = (int)x; + int yInt = (int)y; + double xFrac = x - xInt; + double yFrac = y - yInt; + + // get four noise values + double x0y0 = Noise(xInt, yInt); + double x1y0 = Noise(xInt + 1, yInt); + double x0y1 = Noise(xInt, yInt + 1); + double x1y1 = Noise(xInt + 1, yInt + 1); + + // x interpolation + double v1 = CosineInterpolate(x0y0, x1y0, xFrac); + double v2 = CosineInterpolate(x0y1, x1y1, xFrac); + + // y interpolation + return CosineInterpolate(v1, v2, yFrac); + } + + /// + /// Cosine interpolation. + /// + private static double CosineInterpolate(double x1, double x2, double a) + { + double f = (1 - Math.Cos(a * Math.PI)) * 0.5; + + return x1 * (1 - f) + x2 * f; + } + } +} diff --git a/Sources/Accord.Math/AForge/Random/ExponentialGenerator.cs b/Sources/Accord.Math/AForge/Random/ExponentialGenerator.cs new file mode 100644 index 0000000000..af9034d4d --- /dev/null +++ b/Sources/Accord.Math/AForge/Random/ExponentialGenerator.cs @@ -0,0 +1,124 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Math.Random +{ + using System; + + /// + /// Exponential random numbers generator. + /// + /// + /// The random number generator generates exponential + /// random numbers with specified rate value (lambda). + /// + /// The generator uses generator as a base + /// to generate random numbers. + /// + /// Sample usage: + /// + /// // create instance of random generator + /// IRandomNumberGenerator generator = new ExponentialGenerator( 5 ); + /// // generate random number + /// float randomNumber = generator.Next( ); + /// + /// + /// + public class ExponentialGenerator : IRandomNumberGenerator + { + private UniformOneGenerator rand = null; + + private float rate = 0; + + /// + /// Rate value (inverse mean). + /// + /// + /// The rate value should be positive and non zero. + /// + public float Rate + { + get { return rate; } + } + + /// + /// Mean value of the generator. + /// + /// + public float Mean + { + get { return 1.0f / rate; } + } + + /// + /// Variance value of the generator. + /// + /// + public float Variance + { + get { return 1f / ( rate * rate ); } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Rate value. + /// + /// Rate value should be greater than zero. + /// + public ExponentialGenerator( float rate ) : + this( rate, 0 ) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Rate value (inverse mean). + /// Seed value to initialize random numbers generator. + /// + /// Rate value should be greater than zero. + /// + public ExponentialGenerator( float rate, int seed ) + { + // check rate value + if ( rate <= 0 ) + throw new ArgumentException( "Rate value should be greater than zero." ); + + this.rand = new UniformOneGenerator( seed ); + this.rate = rate; + } + + /// + /// Generate next random number + /// + /// + /// Returns next random number. + /// + public float Next( ) + { + return - (float) Math.Log( rand.Next( ) ) / rate; + } + + /// + /// Set seed of the random numbers generator. + /// + /// + /// Seed value. + /// + /// Resets random numbers generator initializing it with + /// specified seed value. + /// + public void SetSeed( int seed ) + { + rand = new UniformOneGenerator( seed ); + } + } +} diff --git a/Sources/Accord.Math/AForge/Random/GaussianGenerator.cs b/Sources/Accord.Math/AForge/Random/GaussianGenerator.cs new file mode 100644 index 0000000000..29a6fc94f --- /dev/null +++ b/Sources/Accord.Math/AForge/Random/GaussianGenerator.cs @@ -0,0 +1,121 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Math.Random +{ + using System; + + /// + /// Gaussian random numbers generator. + /// + /// + /// The random number generator generates gaussian + /// random numbers with specified mean and standard deviation values. + /// + /// The generator uses generator as base + /// to generate random numbers. + /// + /// Sample usage: + /// + /// // create instance of random generator + /// IRandomNumberGenerator generator = new GaussianGenerator( 5.0, 1.5 ); + /// // generate random number + /// float randomNumber = generator.Next( ); + /// + /// + /// + public class GaussianGenerator : IRandomNumberGenerator + { + // standard numbers generator + private StandardGenerator rand = null; + // mean value + private float mean; + // standard deviation value + private float stdDev; + + /// + /// Mean value of the generator. + /// + /// + public float Mean + { + get { return mean; } + } + + /// + /// Variance value of the generator. + /// + /// + public float Variance + { + get { return stdDev * stdDev; } + } + + /// + /// Standard deviation value. + /// + /// + public float StdDev + { + get { return stdDev; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Mean value. + /// Standard deviation value. + /// + public GaussianGenerator( float mean, float stdDev ) : + this( mean, stdDev, 0 ) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Mean value. + /// Standard deviation value. + /// Seed value to initialize random numbers generator. + /// + public GaussianGenerator( float mean, float stdDev, int seed ) + { + this.mean = mean; + this.stdDev = stdDev; + + rand = new StandardGenerator( seed ); + } + + /// + /// Generate next random number. + /// + /// + /// Returns next random number. + /// + public float Next( ) + { + return (float) rand.Next( ) * stdDev + mean; + } + + /// + /// Set seed of the random numbers generator. + /// + /// + /// Seed value. + /// + /// Resets random numbers generator initializing it with + /// specified seed value. + /// + public void SetSeed( int seed ) + { + rand = new StandardGenerator( seed ); + } + } +} diff --git a/Sources/Accord.Math/AForge/Random/IRandomNumberGenerator.cs b/Sources/Accord.Math/AForge/Random/IRandomNumberGenerator.cs new file mode 100644 index 0000000000..0bd253434 --- /dev/null +++ b/Sources/Accord.Math/AForge/Random/IRandomNumberGenerator.cs @@ -0,0 +1,51 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Math.Random +{ + using System; + + /// + /// Interface for random numbers generators. + /// + /// + /// The interface defines set of methods and properties, which should + /// be implemented by different algorithms for random numbers generatation. + /// + /// + public interface IRandomNumberGenerator + { + /// + /// Mean value of generator. + /// + /// + float Mean { get; } + + /// + /// Variance value of generator. + /// + /// + float Variance { get; } + + /// + /// Generate next random number. + /// + /// + /// Returns next random number. + /// + float Next( ); + + /// + /// Set seed of the random numbers generator. + /// + /// + /// Seed value. + /// + void SetSeed( int seed ); + } +} diff --git a/Sources/Accord.Math/AForge/Random/StandardGenerator.cs b/Sources/Accord.Math/AForge/Random/StandardGenerator.cs new file mode 100644 index 0000000000..f9b0130fb --- /dev/null +++ b/Sources/Accord.Math/AForge/Random/StandardGenerator.cs @@ -0,0 +1,132 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Math.Random +{ + using System; + + /// + /// Standard random numbers generator. + /// + /// + /// The random number generator generates gaussian + /// random numbers with zero mean and standard deviation of one. The generator + /// implements polar form of the Box-Muller transformation. + /// + /// The generator uses generator as a base + /// to generate random numbers. + /// + /// Sample usage: + /// + /// // create instance of random generator + /// IRandomNumberGenerator generator = new StandardGenerator( ); + /// // generate random number + /// float randomNumber = generator.Next( ); + /// + /// + /// + public class StandardGenerator : IRandomNumberGenerator + { + private UniformOneGenerator rand = null; + + private float secondValue; + private bool useSecond = false; + + /// + /// Mean value of the generator. + /// + /// + public float Mean + { + get { return 0; } + } + + /// + /// Variance value of the generator. + /// + /// + public float Variance + { + get { return 1; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public StandardGenerator( ) + { + rand = new UniformOneGenerator( ); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Seed value to initialize random numbers generator. + /// + public StandardGenerator( int seed ) + { + rand = new UniformOneGenerator( seed ); + } + + /// + /// Generate next random number. + /// + /// + /// Returns next random number. + /// + public float Next( ) + { + // check if we can use second value + if ( useSecond ) + { + // return the second number + useSecond = false; + return secondValue; + } + + float x1, x2, w, firstValue; + + // generate new numbers + do + { + x1 = (float) rand.Next( ) * 2.0f - 1.0f; + x2 = (float) rand.Next( ) * 2.0f - 1.0f; + w = x1 * x1 + x2 * x2; + } + while ( w >= 1.0f ); + + w = (float) Math.Sqrt( ( -2.0f * Math.Log( w ) ) / w ); + + // get two standard random numbers + firstValue = x1 * w; + secondValue = x2 * w; + + useSecond = true; + + // return the first number + return firstValue; + } + + /// + /// Set seed of the random numbers generator. + /// + /// + /// Seed value. + /// + /// Resets random numbers generator initializing it with + /// specified seed value. + /// + public void SetSeed( int seed ) + { + rand = new UniformOneGenerator( seed ); + useSecond = false; + } + } +} diff --git a/Sources/Accord.Math/AForge/Random/UniformGenerator.cs b/Sources/Accord.Math/AForge/Random/UniformGenerator.cs new file mode 100644 index 0000000000..fcda92354 --- /dev/null +++ b/Sources/Accord.Math/AForge/Random/UniformGenerator.cs @@ -0,0 +1,128 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Math.Random +{ + using System; + using AForge; + + /// + /// Uniform random numbers generator. + /// + /// + /// The random numbers generator generates uniformly + /// distributed numbers in the specified range - values + /// are greater or equal to minimum range's value and less than maximum range's + /// value. + /// + /// The generator uses generator + /// to generate random numbers. + /// + /// Sample usage: + /// + /// // create instance of random generator + /// IRandomNumberGenerator generator = new UniformGenerator( new Range( 50, 100 ) ); + /// // generate random number + /// float randomNumber = generator.Next( ); + /// + /// + /// + public class UniformGenerator : IRandomNumberGenerator + { + private UniformOneGenerator rand = null; + + // generator's range + private float min; + private float length; + + /// + /// Mean value of the generator. + /// + /// + public float Mean + { + get { return ( min + min + length ) / 2; } + } + + /// + /// Variance value of the generator. + /// + /// + public float Variance + { + get { return length * length / 12; } + } + + /// + /// Random numbers range. + /// + /// + /// Range of random numbers to generate. Generated numbers are + /// greater or equal to minimum range's value and less than maximum range's + /// value. + /// + /// + public Range Range + { + get { return new Range( min, min + length ); } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Random numbers range. + /// + /// Initializes random numbers generator with zero seed. + /// + public UniformGenerator( Range range ) : + this( range, 0 ) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Random numbers range. + /// Seed value to initialize random numbers generator. + /// + public UniformGenerator( Range range, int seed ) + { + rand = new UniformOneGenerator( seed ); + + min = range.Min; + length = range.Length; + } + + /// + /// Generate next random number. + /// + /// + /// Returns next random number. + /// + public float Next( ) + { + return (float) rand.Next( ) * length + min; + } + + /// + /// Set seed of the random numbers generator. + /// + /// + /// Seed value. + /// + /// Resets random numbers generator initializing it with + /// specified seed value. + /// + public void SetSeed( int seed ) + { + rand = new UniformOneGenerator( seed ); + } + } +} diff --git a/Sources/Accord.Math/AForge/Random/UniformOneGenerator.cs b/Sources/Accord.Math/AForge/Random/UniformOneGenerator.cs new file mode 100644 index 0000000000..bf34c7080 --- /dev/null +++ b/Sources/Accord.Math/AForge/Random/UniformOneGenerator.cs @@ -0,0 +1,105 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Math.Random +{ + using System; + using AForge; + + /// + /// Uniform random numbers generator in the range of [0, 1). + /// + /// + /// The random number generator generates uniformly + /// distributed numbers in the range of [0, 1) - greater or equal to 0.0 + /// and less than 1.0. + /// + /// At this point the generator is based on the + /// internal .NET generator, but may be rewritten to + /// use faster generation algorithm. + /// + /// Sample usage: + /// + /// // create instance of random generator + /// IRandomNumberGenerator generator = new UniformOneGenerator( ); + /// // generate random number + /// float randomNumber = generator.Next( ); + /// + /// + /// + public class UniformOneGenerator : IRandomNumberGenerator + { + // .NET random generator as a base + private ThreadSafeRandom rand = null; + + /// + /// Mean value of the generator. + /// + /// + public float Mean + { + get { return 0.5f; } + } + + /// + /// Variance value of the generator. + /// + /// + public float Variance + { + get { return 1f / 12; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Initializes random numbers generator with zero seed. + /// + public UniformOneGenerator( ) + { + rand = new ThreadSafeRandom( 0 ); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Seed value to initialize random numbers generator. + /// + public UniformOneGenerator( int seed ) + { + rand = new ThreadSafeRandom( seed ); + } + + /// + /// Generate next random number. + /// + /// + /// Returns next random number. + /// + public float Next( ) + { + return (float) rand.NextDouble( ); + } + + /// + /// Set seed of the random numbers generator. + /// + /// + /// Seed value. + /// + /// Resets random numbers generator initializing it with + /// specified seed value. + /// + public void SetSeed( int seed ) + { + rand = new ThreadSafeRandom( seed ); + } + } +} diff --git a/Sources/Accord.Math/AForge/SVD.cs b/Sources/Accord.Math/AForge/SVD.cs new file mode 100644 index 0000000000..7e37689d3 --- /dev/null +++ b/Sources/Accord.Math/AForge/SVD.cs @@ -0,0 +1,397 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2014 +// aforge.net@gmail.com +// + +namespace AForge.Math +{ + using System; + + // Just a copy-paste of SVD algorithm from Numerical Recipes but updated for C# + // (as authors state, the code is aimed to be machine readable, so blame them + // for all those c/f/g/h/s variable) + internal class svd + { + public static void svdcmp(double[,] a, out double[] w, out double[,] v) + { + // number of rows in A + int m = a.GetLength(0); + // number of columns in A + int n = a.GetLength(1); + + if (m < n) + { + throw new ArgumentException("Number of rows in A must be greater or equal to number of columns"); + } + + w = new double[n]; + v = new double[n, n]; + + + int flag, i, its, j, jj, k, l = 0, nm = 0; + double anorm, c, f, g, h, s, scale, x, y, z; + + double[] rv1 = new double[n]; + + // householder reduction to bidiagonal form + g = scale = anorm = 0.0; + + for (i = 0; i < n; i++) + { + l = i + 1; + rv1[i] = scale * g; + g = s = scale = 0; + + if (i < m) + { + for (k = i; k < m; k++) + { + scale += System.Math.Abs(a[k, i]); + } + + if (scale != 0.0) + { + for (k = i; k < m; k++) + { + a[k, i] /= scale; + s += a[k, i] * a[k, i]; + } + + f = a[i, i]; + g = -Sign(System.Math.Sqrt(s), f); + h = f * g - s; + a[i, i] = f - g; + + if (i != n - 1) + { + for (j = l; j < n; j++) + { + for (s = 0.0, k = i; k < m; k++) + { + s += a[k, i] * a[k, j]; + } + + f = s / h; + + for (k = i; k < m; k++) + { + a[k, j] += f * a[k, i]; + } + } + } + + for (k = i; k < m; k++) + { + a[k, i] *= scale; + } + } + } + + w[i] = scale * g; + g = s = scale = 0.0; + + if ((i < m) && (i != n - 1)) + { + for (k = l; k < n; k++) + { + scale += System.Math.Abs(a[i, k]); + } + + if (scale != 0.0) + { + for (k = l; k < n; k++) + { + a[i, k] /= scale; + s += a[i, k] * a[i, k]; + } + + f = a[i, l]; + g = -Sign(System.Math.Sqrt(s), f); + h = f * g - s; + a[i, l] = f - g; + + for (k = l; k < n; k++) + { + rv1[k] = a[i, k] / h; + } + + if (i != m - 1) + { + for (j = l; j < m; j++) + { + for (s = 0.0, k = l; k < n; k++) + { + s += a[j, k] * a[i, k]; + } + for (k = l; k < n; k++) + { + a[j, k] += s * rv1[k]; + } + } + } + + for (k = l; k < n; k++) + { + a[i, k] *= scale; + } + } + } + anorm = System.Math.Max(anorm, (System.Math.Abs(w[i]) + System.Math.Abs(rv1[i]))); + } + + // accumulation of right-hand transformations + for (i = n - 1; i >= 0; i--) + { + if (i < n - 1) + { + if (g != 0.0) + { + for (j = l; j < n; j++) + { + v[j, i] = (a[i, j] / a[i, l]) / g; + } + + for (j = l; j < n; j++) + { + for (s = 0, k = l; k < n; k++) + { + s += a[i, k] * v[k, j]; + } + for (k = l; k < n; k++) + { + v[k, j] += s * v[k, i]; + } + } + } + for (j = l; j < n; j++) + { + v[i, j] = v[j, i] = 0; + } + } + v[i, i] = 1; + g = rv1[i]; + l = i; + } + + // accumulation of left-hand transformations + for (i = n - 1; i >= 0; i--) + { + l = i + 1; + g = w[i]; + + if (i < n - 1) + { + for (j = l; j < n; j++) + { + a[i, j] = 0.0; + } + } + + if (g != 0) + { + g = 1.0 / g; + + if (i != n - 1) + { + for (j = l; j < n; j++) + { + for (s = 0, k = l; k < m; k++) + { + s += a[k, i] * a[k, j]; + } + + f = (s / a[i, i]) * g; + + for (k = i; k < m; k++) + { + a[k, j] += f * a[k, i]; + } + } + } + + for (j = i; j < m; j++) + { + a[j, i] *= g; + } + } + else + { + for (j = i; j < m; j++) + { + a[j, i] = 0; + } + } + ++a[i, i]; + } + + // diagonalization of the bidiagonal form: Loop over singular values + // and over allowed iterations + for (k = n - 1; k >= 0; k--) + { + for (its = 1; its <= 30; its++) + { + flag = 1; + + for (l = k; l >= 0; l--) + { + // test for splitting + nm = l - 1; + + if (System.Math.Abs(rv1[l]) + anorm == anorm) + { + flag = 0; + break; + } + + if (System.Math.Abs(w[nm]) + anorm == anorm) + break; + } + + if (flag != 0) + { + c = 0.0; + s = 1.0; + for (i = l; i <= k; i++) + { + f = s * rv1[i]; + + if (System.Math.Abs(f) + anorm != anorm) + { + g = w[i]; + h = Pythag(f, g); + w[i] = h; + h = 1.0 / h; + c = g * h; + s = -f * h; + + for (j = 0; j < m; j++) + { + y = a[j, nm]; + z = a[j, i]; + a[j, nm] = y * c + z * s; + a[j, i] = z * c - y * s; + } + } + } + } + + z = w[k]; + + if (l == k) + { + // convergence + if (z < 0.0) + { + // singular value is made nonnegative + w[k] = -z; + + for (j = 0; j < n; j++) + { + v[j, k] = -v[j, k]; + } + } + break; + } + + if (its == 30) + { + throw new InvalidOperationException("No convergence in 30 svdcmp iterations"); + } + + // shift from bottom 2-by-2 minor + x = w[l]; + nm = k - 1; + y = w[nm]; + g = rv1[nm]; + h = rv1[k]; + f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0 * h * y); + g = Pythag(f, 1.0); + f = ((x - z) * (x + z) + h * ((y / (f + Sign(g, f))) - h)) / x; + + // next QR transformation + c = s = 1.0; + + for (j = l; j <= nm; j++) + { + i = j + 1; + g = rv1[i]; + y = w[i]; + h = s * g; + g = c * g; + z = Pythag(f, h); + rv1[j] = z; + c = f / z; + s = h / z; + f = x * c + g * s; + g = g * c - x * s; + h = y * s; + y *= c; + + for (jj = 0; jj < n; jj++) + { + x = v[jj, j]; + z = v[jj, i]; + v[jj, j] = x * c + z * s; + v[jj, i] = z * c - x * s; + } + + z = Pythag(f, h); + w[j] = z; + + if (z != 0) + { + z = 1.0 / z; + c = f * z; + s = h * z; + } + + f = c * g + s * y; + x = c * y - s * g; + + for (jj = 0; jj < m; jj++) + { + y = a[jj, j]; + z = a[jj, i]; + a[jj, j] = y * c + z * s; + a[jj, i] = z * c - y * s; + } + } + + rv1[l] = 0.0; + rv1[k] = f; + w[k] = x; + } + } + } + + private static double Sign(double a, double b) + { + return (b >= 0.0) ? System.Math.Abs(a) : -System.Math.Abs(a); + } + + private static double Pythag(double a, double b) + { + double at = System.Math.Abs(a), bt = System.Math.Abs(b), ct, result; + + if (at > bt) + { + ct = bt / at; + result = at * System.Math.Sqrt(1.0 + ct * ct); + } + else if (bt > 0.0) + { + ct = at / bt; + result = bt * System.Math.Sqrt(1.0 + ct * ct); + } + else + { + result = 0.0; + } + + return result; + } + } +} diff --git a/Sources/Accord.Math/AForge/Statistics.cs b/Sources/Accord.Math/AForge/Statistics.cs new file mode 100644 index 0000000000..4daa82018 --- /dev/null +++ b/Sources/Accord.Math/AForge/Statistics.cs @@ -0,0 +1,358 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Math +{ + using System; + using AForge; + + /// + /// Set of statistics functions. + /// + /// + /// The class represents collection of simple functions used + /// in statistics. + /// + public static class Statistics + { + /// + /// Calculate mean value. + /// + /// + /// Histogram array. + /// + /// Returns mean value. + /// + /// The input array is treated as histogram, i.e. its + /// indexes are treated as values of stochastic function, but + /// array values are treated as "probabilities" (total amount of + /// hits). + /// + /// Sample usage: + /// + /// // create histogram array + /// int[] histogram = new int[] { 1, 1, 2, 3, 6, 8, 11, 12, 7, 3 }; + /// // calculate mean value + /// double mean = Statistics.Mean( histogram ); + /// // output it (5.759) + /// Console.WriteLine( "mean = " + mean.ToString( "F3" ) ); + /// + /// + /// + public static double Mean( int[] values ) + { + int hits; + double total = 0; + double mean = 0; + + // for all values + for ( int i = 0, n = values.Length; i < n; i++ ) + { + hits = values[i]; + // accumulate mean + mean += (double) i * hits; + // accumalate total + total += hits; + } + return ( total == 0 ) ? 0 : mean / total; + } + + /// + /// Calculate standard deviation. + /// + /// + /// Histogram array. + /// + /// Returns value of standard deviation. + /// + /// The input array is treated as histogram, i.e. its + /// indexes are treated as values of stochastic function, but + /// array values are treated as "probabilities" (total amount of + /// hits). + /// + /// Sample usage: + /// + /// // create histogram array + /// int[] histogram = new int[] { 1, 1, 2, 3, 6, 8, 11, 12, 7, 3 }; + /// // calculate standard deviation value + /// double stdDev = Statistics.StdDev( histogram ); + /// // output it (1.999) + /// Console.WriteLine( "std.dev. = " + stdDev.ToString( "F3" ) ); + /// + /// + /// + public static double StdDev( int[] values ) + { + return StdDev( values, Mean( values ) ); + } + + /// + /// Calculate standard deviation. + /// + /// + /// Histogram array. + /// Mean value of the histogram. + /// + /// Returns value of standard deviation. + /// + /// The input array is treated as histogram, i.e. its + /// indexes are treated as values of stochastic function, but + /// array values are treated as "probabilities" (total amount of + /// hits). + /// + /// The method is an equevalent to the method, + /// but it relieas on the passed mean value, which is previously calculated + /// using method. + /// + /// + public static double StdDev( int[] values, double mean ) + { + double stddev = 0; + double diff; + int hits; + int total = 0; + + // for all values + for ( int i = 0, n = values.Length; i < n; i++ ) + { + hits = values[i]; + diff = (double) i - mean; + // accumulate std.dev. + stddev += diff * diff * hits; + // accumalate total + total += hits; + } + + return ( total == 0 ) ? 0 : Math.Sqrt( stddev / total ); + } + + /// + /// Calculate median value. + /// + /// + /// Histogram array. + /// + /// Returns value of median. + /// + /// + /// The input array is treated as histogram, i.e. its + /// indexes are treated as values of stochastic function, but + /// array values are treated as "probabilities" (total amount of + /// hits). + /// + /// The median value is calculated accumulating histogram's + /// values starting from the left point until the sum reaches 50% of + /// histogram's sum. + /// + /// Sample usage: + /// + /// // create histogram array + /// int[] histogram = new int[] { 1, 1, 2, 3, 6, 8, 11, 12, 7, 3 }; + /// // calculate median value + /// int median = Statistics.Median( histogram ); + /// // output it (6) + /// Console.WriteLine( "median = " + median ); + /// + /// + /// + public static int Median( int[] values ) + { + int total = 0, n = values.Length; + + // for all values + for ( int i = 0; i < n; i++ ) + { + // accumalate total + total += values[i]; + } + + int halfTotal = total / 2; + int median = 0, v = 0; + + // find median value + for ( ; median < n; median++ ) + { + v += values[median]; + if ( v >= halfTotal ) + break; + } + + return median; + } + + /// + /// Get range around median containing specified percentage of values. + /// + /// + /// Histogram array. + /// Values percentage around median. + /// + /// Returns the range which containes specifies percentage + /// of values. + /// + /// + /// The input array is treated as histogram, i.e. its + /// indexes are treated as values of stochastic function, but + /// array values are treated as "probabilities" (total amount of + /// hits). + /// + /// The method calculates range of stochastic variable, which summary probability + /// comprises the specified percentage of histogram's hits. + /// + /// Sample usage: + /// + /// // create histogram array + /// int[] histogram = new int[] { 1, 1, 2, 3, 6, 8, 11, 12, 7, 3 }; + /// // get 75% range around median + /// IntRange range = Statistics.GetRange( histogram, 0.75 ); + /// // output it ([4, 8]) + /// Console.WriteLine( "range = [" + range.Min + ", " + range.Max + "]" ); + /// + /// + /// + public static IntRange GetRange( int[] values, double percent ) + { + int total = 0, n = values.Length; + + // for all values + for ( int i = 0; i < n; i++ ) + { + // accumalate total + total += values[i]; + } + + int min, max, hits; + int h = (int) ( total * ( percent + ( 1 - percent ) / 2 ) ); + + // get range min value + for ( min = 0, hits = total; min < n; min++ ) + { + hits -= values[min]; + if ( hits < h ) + break; + } + // get range max value + for ( max = n - 1, hits = total; max >= 0; max-- ) + { + hits -= values[max]; + if ( hits < h ) + break; + } + return new IntRange( min, max ); + } + + /// + /// Calculate entropy value. + /// + /// + /// Histogram array. + /// + /// Returns entropy value of the specified histagram array. + /// + /// The input array is treated as histogram, i.e. its + /// indexes are treated as values of stochastic function, but + /// array values are treated as "probabilities" (total amount of + /// hits). + /// + /// Sample usage: + /// + /// // create histogram array with 2 values of equal probabilities + /// int[] histogram1 = new int[2] { 3, 3 }; + /// // calculate entropy + /// double entropy1 = Statistics.Entropy( histogram1 ); + /// // output it (1.000) + /// Console.WriteLine( "entropy1 = " + entropy1.ToString( "F3" ) ); + /// + /// // create histogram array with 4 values of equal probabilities + /// int[] histogram2 = new int[4] { 1, 1, 1, 1 }; + /// // calculate entropy + /// double entropy2 = Statistics.Entropy( histogram2 ); + /// // output it (2.000) + /// Console.WriteLine( "entropy2 = " + entropy2.ToString( "F3" ) ); + /// + /// // create histogram array with 4 values of different probabilities + /// int[] histogram3 = new int[4] { 1, 2, 3, 4 }; + /// // calculate entropy + /// double entropy3 = Statistics.Entropy( histogram3 ); + /// // output it (1.846) + /// Console.WriteLine( "entropy3 = " + entropy3.ToString( "F3" ) ); + /// + /// + /// + public static double Entropy( int[] values ) + { + int n = values.Length; + int total = 0; + double entropy = 0; + double p; + + // calculate total amount of hits + for ( int i = 0; i < n; i++ ) + { + total += values[i]; + } + + if ( total != 0 ) + { + // for all values + for ( int i = 0; i < n; i++ ) + { + // get item's probability + p = (double) values[i] / total; + // calculate entropy + if ( p != 0 ) + entropy += ( -p * Math.Log( p, 2 ) ); + } + } + return entropy; + } + + /// + /// Calculate mode value. + /// + /// + /// Histogram array. + /// + /// Returns mode value of the histogram array. + /// + /// + /// The input array is treated as histogram, i.e. its + /// indexes are treated as values of stochastic function, but + /// array values are treated as "probabilities" (total amount of + /// hits). + /// + /// Returns the minimum mode value if the specified histogram is multimodal. + /// + /// Sample usage: + /// + /// // create array + /// int[] values = new int[] { 1, 1, 2, 3, 6, 8, 11, 12, 7, 3 }; + /// // calculate mode value + /// int mode = Statistics.Mode( values ); + /// // output it (7) + /// Console.WriteLine( "mode = " + mode ); + /// + /// + /// + public static int Mode( int[] values ) + { + int mode = 0, curMax = 0; + + for ( int i = 0, length = values.Length; i < length; i++ ) + { + if ( values[i] > curMax ) + { + curMax = values[i]; + mode = i; + } + } + + return mode; + } + } +} diff --git a/Sources/Accord.Math/AForge/Tools.cs b/Sources/Accord.Math/AForge/Tools.cs new file mode 100644 index 0000000000..77c3cd36f --- /dev/null +++ b/Sources/Accord.Math/AForge/Tools.cs @@ -0,0 +1,157 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Math +{ + using System; + + /// + /// Set of tool functions. + /// + /// + /// The class contains different utility functions. + /// + public static class Tools + { + /// + /// Calculates power of 2. + /// + /// + /// Power to raise in. + /// + /// Returns specified power of 2 in the case if power is in the range of + /// [0, 30]. Otherwise returns 0. + /// + public static int Pow2( int power ) + { + return ( ( power >= 0 ) && ( power <= 30 ) ) ? ( 1 << power ) : 0; + } + + /// + /// Checks if the specified integer is power of 2. + /// + /// + /// Integer number to check. + /// + /// Returns true if the specified number is power of 2. + /// Otherwise returns false. + /// + public static bool IsPowerOf2( int x ) + { + return ( x > 0 ) ? ( ( x & ( x - 1 ) ) == 0 ) : false; + } + + /// + /// Get base of binary logarithm. + /// + /// + /// Source integer number. + /// + /// Power of the number (base of binary logarithm). + /// + public static int Log2( int x ) + { + if ( x <= 65536 ) + { + if ( x <= 256 ) + { + if ( x <= 16 ) + { + if ( x <= 4 ) + { + if ( x <= 2 ) + { + if ( x <= 1 ) + return 0; + return 1; + } + return 2; + } + if ( x <= 8 ) + return 3; + return 4; + } + if ( x <= 64 ) + { + if ( x <= 32 ) + return 5; + return 6; + } + if ( x <= 128 ) + return 7; + return 8; + } + if ( x <= 4096 ) + { + if ( x <= 1024 ) + { + if ( x <= 512 ) + return 9; + return 10; + } + if ( x <= 2048 ) + return 11; + return 12; + } + if ( x <= 16384 ) + { + if ( x <= 8192 ) + return 13; + return 14; + } + if ( x <= 32768 ) + return 15; + return 16; + } + + if ( x <= 16777216 ) + { + if ( x <= 1048576 ) + { + if ( x <= 262144 ) + { + if ( x <= 131072 ) + return 17; + return 18; + } + if ( x <= 524288 ) + return 19; + return 20; + } + if ( x <= 4194304 ) + { + if ( x <= 2097152 ) + return 21; + return 22; + } + if ( x <= 8388608 ) + return 23; + return 24; + } + if ( x <= 268435456 ) + { + if ( x <= 67108864 ) + { + if ( x <= 33554432 ) + return 25; + return 26; + } + if ( x <= 134217728 ) + return 27; + return 28; + } + if ( x <= 1073741824 ) + { + if ( x <= 536870912 ) + return 29; + return 30; + } + return 31; + } + } +} diff --git a/Sources/Accord.Math/AForge/Vector3.cs b/Sources/Accord.Math/AForge/Vector3.cs new file mode 100644 index 0000000000..6586fdbfa --- /dev/null +++ b/Sources/Accord.Math/AForge/Vector3.cs @@ -0,0 +1,568 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Math +{ + using System; + + /// + /// 3D Vector structure with X, Y and Z coordinates. + /// + /// + /// The structure incapsulates X, Y and Z coordinates of a 3D vector and + /// provides some operations with it. + /// + [Serializable] + public struct Vector3 + { + /// + /// X coordinate of the vector. + /// + public float X; + /// + /// Y coordinate of the vector. + /// + public float Y; + /// + /// Z coordinate of the vector. + /// + public float Z; + + /// + /// Returns maximum value of the vector. + /// + /// + /// Returns maximum value of all 3 vector's coordinates. + /// + public float Max + { + get + { + return ( X > Y ) ? ( ( X > Z ) ? X : Z ) : ( ( Y > Z ) ? Y : Z ); + } + } + + /// + /// Returns minimum value of the vector. + /// + /// + /// Returns minimum value of all 3 vector's coordinates. + /// + public float Min + { + get + { + return ( X < Y ) ? ( ( X < Z ) ? X : Z ) : ( ( Y < Z ) ? Y : Z ); + } + } + + /// + /// Returns index of the coordinate with maximum value. + /// + /// + /// Returns index of the coordinate, which has the maximum value - 0 for X, + /// 1 for Y or 2 for Z. + /// + /// If there are multiple coordinates which have the same maximum value, the + /// property returns smallest index. + /// + /// + public int MaxIndex + { + get + { + return ( X >= Y ) ? ( ( X >= Z ) ? 0 : 2 ) : ( ( Y >= Z ) ? 1 : 2 ); + } + } + + /// + /// Returns index of the coordinate with minimum value. + /// + /// + /// Returns index of the coordinate, which has the minimum value - 0 for X, + /// 1 for Y or 2 for Z. + /// + /// If there are multiple coordinates which have the same minimum value, the + /// property returns smallest index. + /// + /// + public int MinIndex + { + get + { + return ( X <= Y ) ? ( ( X <= Z ) ? 0 : 2 ) : ( ( Y <= Z ) ? 1 : 2 ); + } + } + + /// + /// Returns vector's norm. + /// + /// + /// Returns Euclidean norm of the vector, which is a + /// square root of the sum: X2+Y2+Z2. + /// + /// + public float Norm + { + get { return (float) System.Math.Sqrt( X * X + Y * Y + Z * Z ); } + } + + /// + /// Returns square of the vector's norm. + /// + /// + /// Return X2+Y2+Z2, which is + /// a square of vector's norm or a dot product of this vector + /// with itself. + /// + public float Square + { + get { return X * X + Y * Y + Z * Z; } + } + + /// + /// Initializes a new instance of the structure. + /// + /// + /// X coordinate of the vector. + /// Y coordinate of the vector. + /// Z coordinate of the vector. + /// + public Vector3( float x, float y, float z ) + { + X = x; + Y = y; + Z = z; + } + + /// + /// Initializes a new instance of the structure. + /// + /// + /// Value, which is set to all 3 coordinates of the vector. + /// + public Vector3( float value ) + { + X = Y = Z = value; + } + + /// + /// Returns a string representation of this object. + /// + /// + /// A string representation of this object. + /// + public override string ToString( ) + { + return string.Format( System.Globalization.CultureInfo.InvariantCulture, + "{0}, {1}, {2}", X, Y, Z ); + } + + /// + /// Returns array representation of the vector. + /// + /// + /// Array with 3 values containing X/Y/Z coordinates. + /// + public float[] ToArray( ) + { + return new float[3] { X, Y, Z }; + } + + /// + /// Adds corresponding coordinates of two vectors. + /// + /// + /// The vector to add to. + /// The vector to add to the first vector. + /// + /// Returns a vector which coordinates are equal to sum of corresponding + /// coordinates of the two specified vectors. + /// + public static Vector3 operator +( Vector3 vector1, Vector3 vector2 ) + { + return new Vector3( vector1.X + vector2.X, vector1.Y + vector2.Y, vector1.Z + vector2.Z ); + } + + /// + /// Adds corresponding coordinates of two vectors. + /// + /// + /// The vector to add to. + /// The vector to add to the first vector. + /// + /// Returns a vector which coordinates are equal to sum of corresponding + /// coordinates of the two specified vectors. + /// + public static Vector3 Add( Vector3 vector1, Vector3 vector2 ) + { + return vector1 + vector2; + } + + /// + /// Adds a value to all coordinates of the specified vector. + /// + /// + /// Vector to add the specified value to. + /// Value to add to all coordinates of the vector. + /// + /// Returns new vector with all coordinates increased by the specified value. + /// + public static Vector3 operator +( Vector3 vector, float value ) + { + return new Vector3( vector.X + value, vector.Y + value, vector.Z + value ); + } + + /// + /// Adds a value to all coordinates of the specified vector. + /// + /// + /// Vector to add the specified value to. + /// Value to add to all coordinates of the vector. + /// + /// Returns new vector with all coordinates increased by the specified value. + /// + public static Vector3 Add( Vector3 vector, float value ) + { + return vector + value; + } + + /// + /// Subtracts corresponding coordinates of two vectors. + /// + /// + /// The vector to subtract from. + /// The vector to subtract from the first vector. + /// + /// Returns a vector which coordinates are equal to difference of corresponding + /// coordinates of the two specified vectors. + /// + public static Vector3 operator -( Vector3 vector1, Vector3 vector2 ) + { + return new Vector3( vector1.X - vector2.X, vector1.Y - vector2.Y, vector1.Z - vector2.Z ); + } + + /// + /// Subtracts corresponding coordinates of two vectors. + /// + /// + /// The vector to subtract from. + /// The vector to subtract from the first vector. + /// + /// Returns a vector which coordinates are equal to difference of corresponding + /// coordinates of the two specified vectors. + /// + public static Vector3 Subtract( Vector3 vector1, Vector3 vector2 ) + { + return vector1 - vector2; + } + + /// + /// Subtracts a value from all coordinates of the specified vector. + /// + /// + /// Vector to subtract the specified value from. + /// Value to subtract from all coordinates of the vector. + /// + /// Returns new vector with all coordinates decreased by the specified value. + /// + public static Vector3 operator -( Vector3 vector, float value ) + { + return new Vector3( vector.X - value, vector.Y - value, vector.Z - value ); + } + + /// + /// Subtracts a value from all coordinates of the specified vector. + /// + /// + /// Vector to subtract the specified value from. + /// Value to subtract from all coordinates of the vector. + /// + /// Returns new vector with all coordinates decreased by the specified value. + /// + public static Vector3 Subtract( Vector3 vector, float value ) + { + return vector - value; + } + + /// + /// Multiplies corresponding coordinates of two vectors. + /// + /// + /// The first vector to multiply. + /// The second vector to multiply. + /// + /// Returns a vector which coordinates are equal to multiplication of corresponding + /// coordinates of the two specified vectors. + /// + public static Vector3 operator *( Vector3 vector1, Vector3 vector2 ) + { + return new Vector3( vector1.X * vector2.X, vector1.Y * vector2.Y, vector1.Z * vector2.Z ); + } + + /// + /// Multiplies corresponding coordinates of two vectors. + /// + /// + /// The first vector to multiply. + /// The second vector to multiply. + /// + /// Returns a vector which coordinates are equal to multiplication of corresponding + /// coordinates of the two specified vectors. + /// + public static Vector3 Multiply( Vector3 vector1, Vector3 vector2 ) + { + return vector1 * vector2; + } + + /// + /// Multiplies coordinates of the specified vector by the specified factor. + /// + /// + /// Vector to multiply coordinates of. + /// Factor to multiple coordinates of the specified vector by. + /// + /// Returns new vector with all coordinates multiplied by the specified factor. + /// + public static Vector3 operator *( Vector3 vector, float factor ) + { + return new Vector3( vector.X * factor, vector.Y * factor, vector.Z * factor ); + } + + /// + /// Multiplies coordinates of the specified vector by the specified factor. + /// + /// + /// Vector to multiply coordinates of. + /// Factor to multiple coordinates of the specified vector by. + /// + /// Returns new vector with all coordinates multiplied by the specified factor. + /// + public static Vector3 Multiply( Vector3 vector, float factor ) + { + return vector * factor; + } + + /// + /// Divides corresponding coordinates of two vectors. + /// + /// + /// The first vector to divide. + /// The second vector to devide. + /// + /// Returns a vector which coordinates are equal to coordinates of the first vector divided by + /// corresponding coordinates of the second vector. + /// + public static Vector3 operator /( Vector3 vector1, Vector3 vector2 ) + { + return new Vector3( vector1.X / vector2.X, vector1.Y / vector2.Y, vector1.Z / vector2.Z ); + } + + /// + /// Divides corresponding coordinates of two vectors. + /// + /// + /// The first vector to divide. + /// The second vector to devide. + /// + /// Returns a vector which coordinates are equal to coordinates of the first vector divided by + /// corresponding coordinates of the second vector. + /// + public static Vector3 Divide( Vector3 vector1, Vector3 vector2 ) + { + return vector1 / vector2; + } + + /// + /// Divides coordinates of the specified vector by the specified factor. + /// + /// + /// Vector to divide coordinates of. + /// Factor to divide coordinates of the specified vector by. + /// + /// Returns new vector with all coordinates divided by the specified factor. + /// + public static Vector3 operator /( Vector3 vector, float factor ) + { + return new Vector3( vector.X / factor, vector.Y / factor, vector.Z / factor ); + } + + /// + /// Divides coordinates of the specified vector by the specified factor. + /// + /// + /// Vector to divide coordinates of. + /// Factor to divide coordinates of the specified vector by. + /// + /// Returns new vector with all coordinates divided by the specified factor. + /// + public static Vector3 Divide( Vector3 vector, float factor ) + { + return vector / factor; + } + + /// + /// Tests whether two specified vectors are equal. + /// + /// + /// The left-hand vector. + /// The right-hand vector. + /// + /// Returns if the two vectors are equal or otherwise. + /// + public static bool operator ==( Vector3 vector1, Vector3 vector2 ) + { + return ( ( vector1.X == vector2.X ) && ( vector1.Y == vector2.Y ) && ( vector1.Z == vector2.Z ) ); + } + + /// + /// Tests whether two specified vectors are not equal. + /// + /// + /// The left-hand vector. + /// The right-hand vector. + /// + /// Returns if the two vectors are not equal or otherwise. + /// + public static bool operator !=( Vector3 vector1, Vector3 vector2 ) + { + return ( ( vector1.X != vector2.X ) || ( vector1.Y != vector2.Y ) || ( vector1.Z != vector2.Z ) ); + } + + /// + /// Tests whether the vector equals to the specified one. + /// + /// + /// The vector to test equality with. + /// + /// Returns if the two vectors are equal or otherwise. + /// + public bool Equals( Vector3 vector ) + { + return ( ( vector.X == X ) && ( vector.Y == Y ) && ( vector.Z == Z ) ); + } + + /// + /// Tests whether the vector equals to the specified object. + /// + /// + /// The object to test equality with. + /// + /// Returns if the vector equals to the specified object or otherwise. + /// + public override bool Equals( Object obj ) + { + if ( obj is Vector3 ) + { + return Equals( (Vector3) obj ); + } + return false; + } + + /// + /// Returns the hashcode for this instance. + /// + /// + /// A 32-bit signed integer hash code. + /// + public override int GetHashCode( ) + { + return X.GetHashCode( ) + Y.GetHashCode( ) + Z.GetHashCode( ); + } + + /// + /// Normalizes the vector by dividing it’s all coordinates with the vector's norm. + /// + /// + /// Returns the value of vectors’ norm before normalization. + /// + public float Normalize( ) + { + float norm = (float) System.Math.Sqrt( X * X + Y * Y + Z * Z ); + float invNorm = 1.0f / norm; + + X *= invNorm; + Y *= invNorm; + Z *= invNorm; + + return norm; + } + + /// + /// Inverse the vector. + /// + /// + /// Returns a vector with all coordinates equal to 1.0 divided by the value of corresponding coordinate + /// in this vector (or equal to 0.0 if this vector has corresponding coordinate also set to 0.0). + /// + public Vector3 Inverse( ) + { + return new Vector3( + ( X == 0 ) ? 0 : 1.0f / X, + ( Y == 0 ) ? 0 : 1.0f / Y, + ( Z == 0 ) ? 0 : 1.0f / Z ); + } + + /// + /// Calculate absolute values of the vector. + /// + /// + /// Returns a vector with all coordinates equal to absolute values of this vector's coordinates. + /// + public Vector3 Abs( ) + { + return new Vector3( System.Math.Abs( X ), System.Math.Abs( Y ), System.Math.Abs( Z ) ); + } + + /// + /// Calculates cross product of two vectors. + /// + /// + /// First vector to use for cross product calculation. + /// Second vector to use for cross product calculation. + /// + /// Returns cross product of the two specified vectors. + /// + public static Vector3 Cross( Vector3 vector1, Vector3 vector2 ) + { + return new Vector3( + vector1.Y * vector2.Z - vector1.Z * vector2.Y, + vector1.Z * vector2.X - vector1.X * vector2.Z, + vector1.X * vector2.Y - vector1.Y * vector2.X ); + } + + /// + /// Calculates dot product of two vectors. + /// + /// + /// First vector to use for dot product calculation. + /// Second vector to use for dot product calculation. + /// + /// Returns dot product of the two specified vectors. + /// + public static float Dot( Vector3 vector1, Vector3 vector2 ) + { + return vector1.X * vector2.X + vector1.Y * vector2.Y + vector1.Z * vector2.Z; + } + + /// + /// Converts the vector to a 4D vector. + /// + /// + /// Returns 4D vector which is an extension of the 3D vector. + /// + /// The method returns a 4D vector which has X, Y and Z coordinates equal to the + /// coordinates of this 3D vector and W coordinate set to 1.0. + /// + /// + public Vector4 ToVector4( ) + { + return new Vector4( X, Y, Z, 1 ); + } + } +} diff --git a/Sources/Accord.Math/AForge/Vector4.cs b/Sources/Accord.Math/AForge/Vector4.cs new file mode 100644 index 0000000000..ee97924eb --- /dev/null +++ b/Sources/Accord.Math/AForge/Vector4.cs @@ -0,0 +1,623 @@ +// AForge Math Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Math +{ + using System; + + /// + /// 4D Vector structure with X, Y, Z and W coordinates. + /// + /// + /// The structure incapsulates X, Y, Z and W coordinates of a 4D vector and + /// provides some operations with it. + /// + [Serializable] + public struct Vector4 + { + /// + /// X coordinate of the vector. + /// + public float X; + /// + /// Y coordinate of the vector. + /// + public float Y; + /// + /// Z coordinate of the vector. + /// + public float Z; + /// + /// W coordinate of the vector. + /// + public float W; + + /// + /// Returns maximum value of the vector. + /// + /// + /// Returns maximum value of all 4 vector's coordinates. + /// + public float Max + { + get + { + float v1 = ( X > Y ) ? X : Y; + float v2 = ( Z > W ) ? Z : W; + + return ( v1 > v2 ) ? v1 : v2; + } + } + + /// + /// Returns minimum value of the vector. + /// + /// + /// Returns minimum value of all 4 vector's coordinates. + /// + public float Min + { + get + { + float v1 = ( X < Y ) ? X : Y; + float v2 = ( Z < W ) ? Z : W; + + return ( v1 < v2 ) ? v1 : v2; + } + } + + /// + /// Returns index of the coordinate with maximum value. + /// + /// + /// Returns index of the coordinate, which has the maximum value - 0 for X, + /// 1 for Y, 2 for Z or 3 for W. + /// + /// If there are multiple coordinates which have the same maximum value, the + /// property returns smallest index. + /// + /// + public int MaxIndex + { + get + { + float v1 = 0; + float v2 = 0; + int i1 = 0; + int i2 = 0; + + if ( X >= Y ) + { + v1 = X; + i1 = 0; + } + else + { + v1 = Y; + i1 = 1; + } + + if ( Z >= W ) + { + v2 = Z; + i2 = 2; + } + else + { + v2 = W; + i2 = 3; + } + + return ( v1 >= v2 ) ? i1 : i2; + } + } + + /// + /// Returns index of the coordinate with minimum value. + /// + /// + /// Returns index of the coordinate, which has the minimum value - 0 for X, + /// 1 for Y, 2 for Z or 3 for W. + /// + /// If there are multiple coordinates which have the same minimum value, the + /// property returns smallest index. + /// + /// + public int MinIndex + { + get + { + float v1 = 0; + float v2 = 0; + int i1 = 0; + int i2 = 0; + + if ( X <= Y ) + { + v1 = X; + i1 = 0; + } + else + { + v1 = Y; + i1 = 1; + } + + if ( Z <= W ) + { + v2 = Z; + i2 = 2; + } + else + { + v2 = W; + i2 = 3; + } + + return ( v1 <= v2 ) ? i1 : i2; + } + } + + /// + /// Returns vector's norm. + /// + /// + /// Returns Euclidean norm of the vector, which is a + /// square root of the sum: X2+Y2+Z2+W2. + /// + /// + public float Norm + { + get { return (float) System.Math.Sqrt( X * X + Y * Y + Z * Z + W * W ); } + } + + /// + /// Returns square of the vector's norm. + /// + /// + /// Return X2+Y2+Z2+W2, which is + /// a square of vector's norm or a dot product of this vector + /// with itself. + /// + public float Square + { + get { return X * X + Y * Y + Z * Z + W * W; } + } + + /// + /// Initializes a new instance of the structure. + /// + /// + /// X coordinate of the vector. + /// Y coordinate of the vector. + /// Z coordinate of the vector. + /// W coordinate of the vector. + /// + public Vector4( float x, float y, float z, float w ) + { + X = x; + Y = y; + Z = z; + W = w; + } + + /// + /// Initializes a new instance of the structure. + /// + /// + /// Value, which is set to all 4 coordinates of the vector. + /// + public Vector4( float value ) + { + X = Y = Z = W = value; + } + + /// + /// Returns a string representation of this object. + /// + /// + /// A string representation of this object. + /// + public override string ToString( ) + { + return string.Format( System.Globalization.CultureInfo.InvariantCulture, + "{0}, {1}, {2}, {3}", X, Y, Z, W ); + } + + /// + /// Returns array representation of the vector. + /// + /// + /// Array with 4 values containing X/Y/Z/W coordinates. + /// + public float[] ToArray( ) + { + return new float[4] { X, Y, Z, W }; + } + + /// + /// Adds corresponding coordinates of two vectors. + /// + /// + /// The vector to add to. + /// The vector to add to the first vector. + /// + /// Returns a vector which coordinates are equal to sum of corresponding + /// coordinates of the two specified vectors. + /// + public static Vector4 operator +( Vector4 vector1, Vector4 vector2 ) + { + return new Vector4( vector1.X + vector2.X, vector1.Y + vector2.Y, + vector1.Z + vector2.Z, vector1.W + vector2.W ); + } + + /// + /// Adds corresponding coordinates of two vectors. + /// + /// + /// The vector to add to. + /// The vector to add to the first vector. + /// + /// Returns a vector which coordinates are equal to sum of corresponding + /// coordinates of the two specified vectors. + /// + public static Vector4 Add( Vector4 vector1, Vector4 vector2 ) + { + return vector1 + vector2; + } + + /// + /// Adds a value to all coordinates of the specified vector. + /// + /// + /// Vector to add the specified value to. + /// Value to add to all coordinates of the vector. + /// + /// Returns new vector with all coordinates increased by the specified value. + /// + public static Vector4 operator +( Vector4 vector, float value ) + { + return new Vector4( vector.X + value, vector.Y + value, vector.Z + value, vector.W + value ); + } + + /// + /// Adds a value to all coordinates of the specified vector. + /// + /// + /// Vector to add the specified value to. + /// Value to add to all coordinates of the vector. + /// + /// Returns new vector with all coordinates increased by the specified value. + /// + public static Vector4 Add( Vector4 vector, float value ) + { + return vector + value; + } + + /// + /// Subtracts corresponding coordinates of two vectors. + /// + /// + /// The vector to subtract from. + /// The vector to subtract from the first vector. + /// + /// Returns a vector which coordinates are equal to difference of corresponding + /// coordinates of the two specified vectors. + /// + public static Vector4 operator -( Vector4 vector1, Vector4 vector2 ) + { + return new Vector4( vector1.X - vector2.X, vector1.Y - vector2.Y, + vector1.Z - vector2.Z, vector1.W - vector2.W ); + } + + /// + /// Subtracts corresponding coordinates of two vectors. + /// + /// + /// The vector to subtract from. + /// The vector to subtract from the first vector. + /// + /// Returns a vector which coordinates are equal to difference of corresponding + /// coordinates of the two specified vectors. + /// + public static Vector4 Subtract( Vector4 vector1, Vector4 vector2 ) + { + return vector1 - vector2; + } + + /// + /// Subtracts a value from all coordinates of the specified vector. + /// + /// + /// Vector to subtract the specified value from. + /// Value to subtract from all coordinates of the vector. + /// + /// Returns new vector with all coordinates decreased by the specified value. + /// + public static Vector4 operator -( Vector4 vector, float value ) + { + return new Vector4( vector.X - value, vector.Y - value, vector.Z - value, vector.W - value ); + } + + /// + /// Subtracts a value from all coordinates of the specified vector. + /// + /// + /// Vector to subtract the specified value from. + /// Value to subtract from all coordinates of the vector. + /// + /// Returns new vector with all coordinates decreased by the specified value. + /// + public static Vector4 Subtract( Vector4 vector, float value ) + { + return vector - value; + } + + /// + /// Multiplies corresponding coordinates of two vectors. + /// + /// + /// The first vector to multiply. + /// The second vector to multiply. + /// + /// Returns a vector which coordinates are equal to multiplication of corresponding + /// coordinates of the two specified vectors. + /// + public static Vector4 operator *( Vector4 vector1, Vector4 vector2 ) + { + return new Vector4( vector1.X * vector2.X, vector1.Y * vector2.Y, + vector1.Z * vector2.Z, vector1.W * vector2.W ); + } + + /// + /// Multiplies corresponding coordinates of two vectors. + /// + /// + /// The first vector to multiply. + /// The second vector to multiply. + /// + /// Returns a vector which coordinates are equal to multiplication of corresponding + /// coordinates of the two specified vectors. + /// + public static Vector4 Multiply( Vector4 vector1, Vector4 vector2 ) + { + return vector1 * vector2; + } + + /// + /// Multiplies coordinates of the specified vector by the specified factor. + /// + /// + /// Vector to multiply coordinates of. + /// Factor to multiple coordinates of the specified vector by. + /// + /// Returns new vector with all coordinates multiplied by the specified factor. + /// + public static Vector4 operator *( Vector4 vector, float factor ) + { + return new Vector4( vector.X * factor, vector.Y * factor, vector.Z * factor, vector.W * factor ); + } + + /// + /// Multiplies coordinates of the specified vector by the specified factor. + /// + /// + /// Vector to multiply coordinates of. + /// Factor to multiple coordinates of the specified vector by. + /// + /// Returns new vector with all coordinates multiplied by the specified factor. + /// + public static Vector4 Multiply( Vector4 vector, float factor ) + { + return vector * factor; + } + + /// + /// Divides corresponding coordinates of two vectors. + /// + /// + /// The first vector to divide. + /// The second vector to devide. + /// + /// Returns a vector which coordinates are equal to coordinates of the first vector divided by + /// corresponding coordinates of the second vector. + /// + public static Vector4 operator /( Vector4 vector1, Vector4 vector2 ) + { + return new Vector4( vector1.X / vector2.X, vector1.Y / vector2.Y, + vector1.Z / vector2.Z, vector1.W / vector2.W ); + } + + /// + /// Divides corresponding coordinates of two vectors. + /// + /// + /// The first vector to divide. + /// The second vector to devide. + /// + /// Returns a vector which coordinates are equal to coordinates of the first vector divided by + /// corresponding coordinates of the second vector. + /// + public static Vector4 Divide( Vector4 vector1, Vector4 vector2 ) + { + return vector1 / vector2; + } + + /// + /// Divides coordinates of the specified vector by the specified factor. + /// + /// + /// Vector to divide coordinates of. + /// Factor to divide coordinates of the specified vector by. + /// + /// Returns new vector with all coordinates divided by the specified factor. + /// + public static Vector4 operator /( Vector4 vector, float factor ) + { + return new Vector4( vector.X / factor, vector.Y / factor, vector.Z / factor, vector.W / factor ); + } + + /// + /// Divides coordinates of the specified vector by the specified factor. + /// + /// + /// Vector to divide coordinates of. + /// Factor to divide coordinates of the specified vector by. + /// + /// Returns new vector with all coordinates divided by the specified factor. + /// + public static Vector4 Divide( Vector4 vector, float factor ) + { + return vector / factor; + } + + /// + /// Tests whether two specified vectors are equal. + /// + /// + /// The left-hand vector. + /// The right-hand vector. + /// + /// Returns if the two vectors are equal or otherwise. + /// + public static bool operator ==( Vector4 vector1, Vector4 vector2 ) + { + return ( ( vector1.X == vector2.X ) && ( vector1.Y == vector2.Y ) && + ( vector1.Z == vector2.Z ) && ( vector1.W == vector2.W ) ); + } + + /// + /// Tests whether two specified vectors are not equal. + /// + /// + /// The left-hand vector. + /// The right-hand vector. + /// + /// Returns if the two vectors are not equal or otherwise. + /// + public static bool operator !=( Vector4 vector1, Vector4 vector2 ) + { + return ( ( vector1.X != vector2.X ) || ( vector1.Y != vector2.Y ) || + ( vector1.Z != vector2.Z ) || ( vector1.W != vector2.W ) ); + } + + /// + /// Tests whether the vector equals to the specified one. + /// + /// + /// The vector to test equality with. + /// + /// Returns if the two vectors are equal or otherwise. + /// + public bool Equals( Vector4 vector ) + { + return ( ( vector.X == X ) && ( vector.Y == Y ) && ( vector.Z == Z ) && ( vector.W == W ) ); + } + + /// + /// Tests whether the vector equals to the specified object. + /// + /// + /// The object to test equality with. + /// + /// Returns if the vector equals to the specified object or otherwise. + /// + public override bool Equals( Object obj ) + { + if ( obj is Vector4 ) + { + return Equals( (Vector4) obj ); + } + return false; + } + + /// + /// Returns the hashcode for this instance. + /// + /// + /// A 32-bit signed integer hash code. + /// + public override int GetHashCode( ) + { + return X.GetHashCode( ) + Y.GetHashCode( ) + Z.GetHashCode( ) + W.GetHashCode( ); + } + + /// + /// Normalizes the vector by dividing it’s all coordinates with the vector's norm. + /// + /// + /// Returns the value of vectors’ norm before normalization. + /// + public float Normalize( ) + { + float norm = (float) System.Math.Sqrt( X * X + Y * Y + Z * Z + W * W ); + float invNorm = 1.0f / norm; + + X *= invNorm; + Y *= invNorm; + Z *= invNorm; + W *= invNorm; + + return norm; + } + + /// + /// Inverse the vector. + /// + /// + /// Returns a vector with all coordinates equal to 1.0 divided by the value of corresponding coordinate + /// in this vector (or equal to 0.0 if this vector has corresponding coordinate also set to 0.0). + /// + public Vector4 Inverse( ) + { + return new Vector4( + ( X == 0 ) ? 0 : 1.0f / X, + ( Y == 0 ) ? 0 : 1.0f / Y, + ( Z == 0 ) ? 0 : 1.0f / Z, + ( W == 0 ) ? 0 : 1.0f / W ); + } + + /// + /// Calculate absolute values of the vector. + /// + /// + /// Returns a vector with all coordinates equal to absolute values of this vector's coordinates. + /// + public Vector4 Abs( ) + { + return new Vector4( System.Math.Abs( X ), System.Math.Abs( Y ), System.Math.Abs( Z ), System.Math.Abs( W ) ); + } + + /// + /// Calculates dot product of two vectors. + /// + /// + /// First vector to use for dot product calculation. + /// Second vector to use for dot product calculation. + /// + /// Returns dot product of the two specified vectors. + /// + public static float Dot( Vector4 vector1, Vector4 vector2 ) + { + return vector1.X * vector2.X + vector1.Y * vector2.Y + + vector1.Z * vector2.Z + vector1.W * vector2.W; + } + + /// + /// Converts the vector to a 3D vector. + /// + /// + /// Returns 3D vector which has X/Y/Z coordinates equal to X/Y/Z coordinates + /// of this vector divided by . + /// + public Vector3 ToVector3( ) + { + return new Vector3( X / W, Y / W, Z / W ); + } + } +} diff --git a/Sources/Accord.Math/Accord.Math.csproj b/Sources/Accord.Math/Accord.Math.csproj index ecff88ab2..aa2eee841 100644 --- a/Sources/Accord.Math/Accord.Math.csproj +++ b/Sources/Accord.Math/Accord.Math.csproj @@ -36,48 +36,83 @@ False True DEBUG;TRACE - ..\..\Debug\ + $(SolutionDir)..\Debug\ - ..\..\Release\net35 + $(SolutionDir)..\Release\net35 TRACE;CODE_ANALYSIS;NET35 v3.5 true - ..\..\Release\net35\Accord.Math.XML - ..\..\Release\net35\Accord.Math.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net35\Accord.Math.XML + $(SolutionDir)..\Release\net35\Accord.Math.dll.CodeAnalysisLog.xml - ..\..\Release\net40 + $(SolutionDir)..\Release\net40 TRACE;CODE_ANALYSIS;NET40 v4.0 - ..\..\Release\net40\Accord.Math.XML - ..\..\Release\net40\Accord.Math.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net40\Accord.Math.XML + $(SolutionDir)..\Release\net40\Accord.Math.dll.CodeAnalysisLog.xml - ..\..\Release\net45 + $(SolutionDir)..\Release\net45 TRACE;CODE_ANALYSIS;NET45 v4.5 - ..\..\Release\net45\Accord.Math.XML - ..\..\Release\net45\Accord.Math.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net45\Accord.Math.XML + $(SolutionDir)..\Release\net45\Accord.Math.dll.CodeAnalysisLog.xml - - ..\..\Externals\AForge.NET\AForge.dll - False - - - ..\..\Externals\AForge.NET\AForge.Math.dll - False - + Properties\VersionInfo.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -241,11 +276,11 @@ TextTemplatingFileGenerator - -.\JaggedLuDecomposition.cs -.\JaggedLuDecomposition.txt -.\JaggedLuDecompositionD.cs -.\JaggedLuDecompositionF.cs + +.\JaggedLuDecomposition.cs +.\JaggedLuDecomposition.txt +.\JaggedLuDecompositionD.cs +.\JaggedLuDecompositionF.cs JaggedLuDecomposition.txt @@ -253,10 +288,10 @@ TextTemplatingFileGenerator EigenvalueDecomposition.txt - -.\EigenvalueDecomposition.cs -.\EigenvalueDecomposition.txt -.\EigenvalueDecompositionF.cs + +.\EigenvalueDecomposition.cs +.\EigenvalueDecomposition.txt +.\EigenvalueDecompositionF.cs @@ -286,10 +321,10 @@ TextTemplatingFileGenerator - -.\JaggedSingularValueDecomposition.cs -.\JaggedSingularValueDecomposition.txt -.\JaggedSingularValueDecompositionF.cs + +.\JaggedSingularValueDecomposition.cs +.\JaggedSingularValueDecomposition.txt +.\JaggedSingularValueDecompositionF.cs JaggedSingularValueDecomposition.txt @@ -316,10 +351,10 @@ TextTemplatingFileGenerator SingularValueDecomposition.txt - -.\SingularValueDecomposition.cs -.\SingularValueDecomposition.txt -.\SingularValueDecompositionF.cs + +.\SingularValueDecomposition.cs +.\SingularValueDecomposition.txt +.\SingularValueDecompositionF.cs @@ -394,11 +429,11 @@ LuDecomposition.txt TextTemplatingFileGenerator - -.\LuDecomposition.cs -.\LuDecompositionBase1.cs -.\LuDecompositionD.cs -.\LuDecompositionF.cs + +.\LuDecomposition.cs +.\LuDecompositionBase1.cs +.\LuDecompositionD.cs +.\LuDecompositionF.cs diff --git a/Sources/Accord.Math/Comparers/Accord.Math.Comparers.cd b/Sources/Accord.Math/Comparers/Accord.Math.Comparers.cd index 0519ecba6..8b393c2bc 100644 --- a/Sources/Accord.Math/Comparers/Accord.Math.Comparers.cd +++ b/Sources/Accord.Math/Comparers/Accord.Math.Comparers.cd @@ -1 +1,68 @@ - \ No newline at end of file + + + + + + + + + AAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAABAAAAAAAA= + Comparers\StableComparer.cs + + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + Comparers\ArrayComparer`1.cs + + + + + + AAAAAAAAAAAAAAAAgAAAAAAAAAAAAIAAAAAAAAAAAAA= + Comparers\ArrayComparer`1.cs + + + + + + + AAAAAAAAAAAAAAAAgAAAAAAAAAAAAIAAAABBAAAAAAA= + Comparers\CustomComparer`1.cs + + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + Comparers\ElementComparer.cs + + + + + + AAAAAAAAAAAAAAAAgAAAAAAAAAAAAIAAAAFAAAAAAAA= + Comparers\ElementComparer.cs + + + + + + + AAAAEAAAAAAAIAAAACAAAAAAAAAAAAAAAABAAAAAAAA= + Comparers\GeneralComparer.cs + + + + + + + AAAAAAAAACAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAA= + Comparers\GeneralComparer.cs + + + + \ No newline at end of file diff --git a/Sources/Accord.Math/Comparers/GeneralComparer.cs b/Sources/Accord.Math/Comparers/GeneralComparer.cs index 793ef85ab..93760b00a 100644 --- a/Sources/Accord.Math/Comparers/GeneralComparer.cs +++ b/Sources/Accord.Math/Comparers/GeneralComparer.cs @@ -1,151 +1,213 @@ -// Accord Math Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Math.Comparers -{ - using System.Collections.Generic; - using System; - - /// - /// Directions for the General Comparer. - /// - /// - public enum ComparerDirection - { - /// - /// Sorting will be performed in ascending order. - /// - /// - Ascending = +1, - - /// - /// Sorting will be performed in descending order. - /// - /// - Descending = -1 - }; - - /// - /// General comparer which supports multiple - /// directions and comparison of absolute values. - /// - /// - /// - /// - /// // Assume we have values to sort - /// double[] values = { 0, -5, 3, 1, 8 }; - /// - /// // We can create an ad-hoc sorting rule considering only absolute values - /// Array.Sort(values, new GeneralComparer(ComparerDirection.Ascending, Math.Abs)); - /// - /// // Result will be { 0, 1, 3, 5, 8 }. - /// - /// - /// - /// - /// - /// - /// - /// - public class GeneralComparer : IComparer, IComparer - { - Func map; - private int direction = 1; - - /// - /// Gets or sets the sorting direction - /// used by this comparer. - /// - /// - public ComparerDirection Direction - { - get { return (ComparerDirection)direction; } - set { direction = (int)value; } - } - - /// - /// Constructs a new General Comparer. - /// - /// - /// The direction to compare. - /// - public GeneralComparer(ComparerDirection direction) - : this(direction, false) { } - - /// - /// Constructs a new General Comparer. - /// - /// - /// The direction to compare. - /// True to compare absolute values, false otherwise. Default is false. - /// - public GeneralComparer(ComparerDirection direction, bool useAbsoluteValues) - { - if (useAbsoluteValues) - this.map = Math.Abs; - else this.map = (a) => a; - - this.direction = (int)direction; - } - - /// - /// Constructs a new General Comparer. - /// - /// - /// The direction to compare. - /// The mapping function which will be applied to - /// each vector element prior to any comparisons. - /// - public GeneralComparer(ComparerDirection direction, Func map) - { - this.map = map; - this.direction = (int)direction; - } - - /// - /// Compares two objects and returns a value indicating whether one is less than, - /// equal to, or greater than the other. - /// - /// - /// The first object to compare. - /// The second object to compare. - /// - public int Compare(double x, double y) - { - return direction * (map(x).CompareTo(map(y))); - } - - /// - /// Compares two objects and returns a value indicating whether one is less than, - /// equal to, or greater than the other. - /// - /// - /// The first object to compare. - /// The second object to compare. - /// - public int Compare(int x, int y) - { - return direction * (map(x).CompareTo(map(y))); - } - - } -} +// Accord Math Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Math.Comparers +{ + using System.Collections.Generic; + using System; + + /// + /// Directions for the General Comparer. + /// + /// + public enum ComparerDirection + { + /// + /// Sorting will be performed in ascending order. + /// + /// + Ascending = +1, + + /// + /// Sorting will be performed in descending order. + /// + /// + Descending = -1 + }; + + /// + /// General comparer which supports multiple + /// directions and comparison of absolute values. + /// + /// + /// + /// + /// // Assume we have values to sort + /// double[] values = { 0, -5, 3, 1, 8 }; + /// + /// // We can create an ad-hoc sorting rule considering only absolute values + /// Array.Sort(values, new GeneralComparer(ComparerDirection.Ascending, Math.Abs)); + /// + /// // Result will be { 0, 1, 3, 5, 8 }. + /// + /// + /// + /// + /// + /// + /// + /// + public class GeneralComparer : IComparer, IComparer + { + Func map; + private int direction = 1; + + /// + /// Gets or sets the sorting direction + /// used by this comparer. + /// + /// + public ComparerDirection Direction + { + get { return (ComparerDirection)direction; } + set { direction = (int)value; } + } + + /// + /// Constructs a new General Comparer. + /// + /// + /// The direction to compare. + /// + public GeneralComparer(ComparerDirection direction) + : this(direction, false) { } + + /// + /// Constructs a new General Comparer. + /// + /// + /// The direction to compare. + /// True to compare absolute values, false otherwise. Default is false. + /// + public GeneralComparer(ComparerDirection direction, bool useAbsoluteValues) + { + if (useAbsoluteValues) + this.map = Math.Abs; + else this.map = (a) => a; + + this.direction = (int)direction; + } + + /// + /// Constructs a new General Comparer. + /// + /// + /// The direction to compare. + /// The mapping function which will be applied to + /// each vector element prior to any comparisons. + /// + public GeneralComparer(ComparerDirection direction, Func map) + { + this.map = map; + this.direction = (int)direction; + } + + /// + /// Compares two objects and returns a value indicating whether one is less than, + /// equal to, or greater than the other. + /// + /// + /// The first object to compare. + /// The second object to compare. + /// + public int Compare(double x, double y) + { + return direction * (map(x).CompareTo(map(y))); + } + + /// + /// Compares two objects and returns a value indicating whether one is less than, + /// equal to, or greater than the other. + /// + /// + /// The first object to compare. + /// The second object to compare. + /// + public int Compare(int x, int y) + { + return direction * (map(x).CompareTo(map(y))); + } + + } + + /// + /// General comparer which supports multiple sorting directions. + /// + /// + /// + /// + /// // Assume we have values to sort + /// double[] values = { 0, -5, 3, 1, 8 }; + /// + /// // We can create an ad-hoc sorting rule + /// Array.Sort(values, new GeneralComparer<double>(ComparerDirection.Descending)); + /// + /// // Result will be { 8, 5, 3, 1, 0 }. + /// + /// + /// + /// + /// + /// + /// + /// + public class GeneralComparer : IComparer where T : IComparable + { + private int direction = 1; + + /// + /// Gets or sets the sorting direction + /// used by this comparer. + /// + /// + public ComparerDirection Direction + { + get { return (ComparerDirection)direction; } + set { direction = (int)value; } + } + + /// + /// Constructs a new General Comparer. + /// + /// + /// The direction to compare. + /// + public GeneralComparer(ComparerDirection direction) + { + this.direction = (int)direction; + } + + /// + /// Compares two objects and returns a value indicating whether one is less than, + /// equal to, or greater than the other. + /// + /// + /// The first object to compare. + /// The second object to compare. + /// + public int Compare(T x, T y) + { + return direction * x.CompareTo(y); + } + + } +} diff --git a/Sources/Accord.Math/Convergence/RelativeParameterConvergence.cs b/Sources/Accord.Math/Convergence/RelativeParameterConvergence.cs index f4a978959..c7197ccc2 100644 --- a/Sources/Accord.Math/Convergence/RelativeParameterConvergence.cs +++ b/Sources/Accord.Math/Convergence/RelativeParameterConvergence.cs @@ -192,7 +192,7 @@ public bool HasDiverged public bool HasConverged { get - { + { if (NewValues == null && OldValues == null) return true; if (OldValues == null) @@ -209,7 +209,10 @@ public bool HasConverged if (tolerance > 0) { // Stopping criteria is likelihood convergence - maxChange = Math.Abs(OldValues[0] - NewValues[0]) / Math.Abs(OldValues[0]); + maxChange = Math.Abs(OldValues[0] - NewValues[0]) / Math.Abs(OldValues[0]); + + if (Double.IsNaN(maxChange)) + maxChange = 0; for (int i = 1; i < OldValues.Length; i++) { @@ -217,8 +220,10 @@ public bool HasConverged if (delta > maxChange) maxChange = delta; - } - + } + + if (Double.IsNaN(maxChange)) + return true; if (maxChange <= tolerance) return true; @@ -252,13 +257,6 @@ public void Clear() oldValues = null; } - - /// - /// Gets or sets the watched value after the iteration. This - /// method is implemented explicitly to avoid breaking too much - /// existing applications. - /// - /// double[] IConvergence.NewValue { // TODO: Remove this explicit implementation. diff --git a/Sources/Accord.Math/Decompositions/SingularValueDecomposition.cs b/Sources/Accord.Math/Decompositions/SingularValueDecomposition.cs index 8624c6621..e547c1ec9 100644 --- a/Sources/Accord.Math/Decompositions/SingularValueDecomposition.cs +++ b/Sources/Accord.Math/Decompositions/SingularValueDecomposition.cs @@ -342,7 +342,7 @@ public SingularValueDecomposition(Double[,] value, /// will be destroyed in the process, resulting in less /// memory comsumption. /// - public unsafe SingularValueDecomposition(Double[,] value, + public SingularValueDecomposition(Double[,] value, bool computeLeftSingularVectors, bool computeRightSingularVectors, bool autoTranspose, bool inPlace) { if (value == null) @@ -405,548 +405,551 @@ public unsafe SingularValueDecomposition(Double[,] value, bool wantu = computeLeftSingularVectors; bool wantv = computeRightSingularVectors; - fixed (Double* U = u) - fixed (Double* V = v) - fixed (Double* A = a) + unsafe { - - // Will store ordered sequence of indices after sorting. - si = new int[ni]; for (int i = 0; i < ni; i++) si[i] = i; - - - // Reduce A to bidiagonal form, storing the diagonal elements in s and the super-diagonal elements in e. - int nct = System.Math.Min(m - 1, n); - int nrt = System.Math.Max(0, System.Math.Min(n - 2, m)); - int mrc = System.Math.Max(nct, nrt); - - for (int k = 0; k < mrc; k++) + fixed (Double* U = u) + fixed (Double* V = v) + fixed (Double* A = a) { - if (k < nct) - { - // Compute the transformation for the k-th column and place the k-th diagonal in s[k]. - // Compute 2-norm of k-th column without under/overflow. - s[k] = 0; - for (int i = k; i < m; i++) - s[k] = Accord.Math.Tools.Hypotenuse(s[k], a[i, k]); - if (s[k] != 0) - { - if (a[k, k] < 0) - s[k] = -s[k]; - - for (int i = k; i < m; i++) - a[i, k] /= s[k]; + // Will store ordered sequence of indices after sorting. + si = new int[ni]; for (int i = 0; i < ni; i++) si[i] = i; - a[k, k] += 1; - } - s[k] = -s[k]; - } + // Reduce A to bidiagonal form, storing the diagonal elements in s and the super-diagonal elements in e. + int nct = System.Math.Min(m - 1, n); + int nrt = System.Math.Max(0, System.Math.Min(n - 2, m)); + int mrc = System.Math.Max(nct, nrt); - for (int j = k + 1; j < n; j++) + for (int k = 0; k < mrc; k++) { - Double* ptr_ak = A + k * n + k; // A[k,k] - Double* ptr_aj = A + k * n + j; // A[k,j] - - if ((k < nct) & (s[k] != 0)) + if (k < nct) { - // Apply the transformation. - Double t = 0; - Double* ak = ptr_ak; - Double* aj = ptr_aj; - + // Compute the transformation for the k-th column and place the k-th diagonal in s[k]. + // Compute 2-norm of k-th column without under/overflow. + s[k] = 0; for (int i = k; i < m; i++) + s[k] = Accord.Math.Tools.Hypotenuse(s[k], a[i, k]); + + if (s[k] != 0) { - t += (*ak) * (*aj); - ak += n; aj += n; - } + if (a[k, k] < 0) + s[k] = -s[k]; - t = -t / *ptr_ak; - ak = ptr_ak; - aj = ptr_aj; + for (int i = k; i < m; i++) + a[i, k] /= s[k]; - for (int i = k; i < m; i++) - { - *aj += t * (*ak); - ak += n; aj += n; + a[k, k] += 1; } - } - // Place the k-th row of A into e for the subsequent calculation of the row transformation. - e[j] = *ptr_aj; - } + s[k] = -s[k]; + } + for (int j = k + 1; j < n; j++) + { + Double* ptr_ak = A + k * n + k; // A[k,k] + Double* ptr_aj = A + k * n + j; // A[k,j] - if (wantu & (k < nct)) - { - // Place the transformation in U for subsequent back - // multiplication. - for (int i = k; i < m; i++) - u[i, k] = a[i, k]; - } + if ((k < nct) & (s[k] != 0)) + { + // Apply the transformation. + Double t = 0; + Double* ak = ptr_ak; + Double* aj = ptr_aj; - if (k < nrt) - { - // Compute the k-th row transformation and place the k-th super-diagonal in e[k]. - // Compute 2-norm without under/overflow. - e[k] = 0; - for (int i = k + 1; i < n; i++) - e[k] = Accord.Math.Tools.Hypotenuse(e[k], e[i]); + for (int i = k; i < m; i++) + { + t += (*ak) * (*aj); + ak += n; aj += n; + } - if (e[k] != 0) - { - if (e[k + 1] < 0) - e[k] = -e[k]; + t = -t / *ptr_ak; + ak = ptr_ak; + aj = ptr_aj; - for (int i = k + 1; i < n; i++) - e[i] /= e[k]; + for (int i = k; i < m; i++) + { + *aj += t * (*ak); + ak += n; aj += n; + } + } - e[k + 1] += 1; + // Place the k-th row of A into e for the subsequent calculation of the row transformation. + e[j] = *ptr_aj; } - e[k] = -e[k]; - if ((k + 1 < m) & (e[k] != 0)) - { - // Apply the transformation. - for (int i = k + 1; i < m; i++) - work[i] = 0; - - int k1 = k + 1; - for (int i = k1; i < m; i++) - { - Double* ai = A + (i * n) + k1; - for (int j = k1; j < n; j++, ai++) - work[i] += e[j] * (*ai); - } - for (int j = k1; j < n; j++) - { - Double t = -e[j] / e[k1]; - Double* aj = A + (k1 * n) + j; - for (int i = k1; i < m; i++, aj += n) - *aj += t * work[i]; - } + if (wantu & (k < nct)) + { + // Place the transformation in U for subsequent back + // multiplication. + for (int i = k; i < m; i++) + u[i, k] = a[i, k]; } - if (wantv) + if (k < nrt) { - // Place the transformation in V for subsequent back multiplication. + // Compute the k-th row transformation and place the k-th super-diagonal in e[k]. + // Compute 2-norm without under/overflow. + e[k] = 0; for (int i = k + 1; i < n; i++) - v[i, k] = e[i]; - } - } - } + e[k] = Accord.Math.Tools.Hypotenuse(e[k], e[i]); - // Set up the final bidiagonal matrix or order p. - int p = System.Math.Min(n, m + 1); - if (nct < n) s[nct] = a[nct, nct]; - if (m < p) s[p - 1] = 0; - if (nrt + 1 < p) e[nrt] = a[nrt, p - 1]; - e[p - 1] = 0; + if (e[k] != 0) + { + if (e[k + 1] < 0) + e[k] = -e[k]; - // If required, generate U. - if (wantu) - { - for (int j = nct; j < nu; j++) - { - for (int i = 0; i < m; i++) - u[i, j] = 0; - u[j, j] = 1; - } + for (int i = k + 1; i < n; i++) + e[i] /= e[k]; - for (int k = nct - 1; k >= 0; k--) - { - if (s[k] != 0) - { - Double* ptr_uk = U + k * nu + k; // u[k,k] + e[k + 1] += 1; + } - Double* uk, uj; - for (int j = k + 1; j < nu; j++) + e[k] = -e[k]; + if ((k + 1 < m) & (e[k] != 0)) { - Double* ptr_uj = U + k * nu + j; // u[k,j] + // Apply the transformation. + for (int i = k + 1; i < m; i++) + work[i] = 0; - Double t = 0; - uk = ptr_uk; - uj = ptr_uj; - - for (int i = k; i < m; i++) + int k1 = k + 1; + for (int i = k1; i < m; i++) { - t += *uk * *uj; - uk += nu; uj += nu; + Double* ai = A + (i * n) + k1; + for (int j = k1; j < n; j++, ai++) + work[i] += e[j] * (*ai); } - t = -t / *ptr_uk; - - uk = ptr_uk; uj = ptr_uj; - for (int i = k; i < m; i++) + for (int j = k1; j < n; j++) { - *uj += t * (*uk); - uk += nu; uj += nu; + Double t = -e[j] / e[k1]; + Double* aj = A + (k1 * n) + j; + for (int i = k1; i < m; i++, aj += n) + *aj += t * work[i]; } } - uk = ptr_uk; - for (int i = k; i < m; i++) + if (wantv) { - *uk = -(*uk); - uk += nu; + // Place the transformation in V for subsequent back multiplication. + for (int i = k + 1; i < n; i++) + v[i, k] = e[i]; } - - u[k, k] = 1 + u[k, k]; - for (int i = 0; i < k - 1; i++) - u[i, k] = 0; } - else + } + + // Set up the final bidiagonal matrix or order p. + int p = System.Math.Min(n, m + 1); + if (nct < n) s[nct] = a[nct, nct]; + if (m < p) s[p - 1] = 0; + if (nrt + 1 < p) e[nrt] = a[nrt, p - 1]; + e[p - 1] = 0; + + // If required, generate U. + if (wantu) + { + for (int j = nct; j < nu; j++) { for (int i = 0; i < m; i++) - u[i, k] = 0; - u[k, k] = 1; + u[i, j] = 0; + u[j, j] = 1; } - } - } - // If required, generate V. - if (wantv) - { - for (int k = n - 1; k >= 0; k--) - { - if ((k < nrt) & (e[k] != 0)) + for (int k = nct - 1; k >= 0; k--) { - // TODO: The following is a pseudo correction to make SVD - // work on matrices with n > m (less rows than columns). + if (s[k] != 0) + { + Double* ptr_uk = U + k * nu + k; // u[k,k] - // For the proper correction, compute the decomposition of the - // transpose of A and swap the left and right eigenvectors + Double* uk, uj; + for (int j = k + 1; j < nu; j++) + { + Double* ptr_uj = U + k * nu + j; // u[k,j] - // Original line: - // for (int j = k + 1; j < nu; j++) - // Pseudo correction: - // for (int j = k + 1; j < n; j++) + Double t = 0; + uk = ptr_uk; + uj = ptr_uj; - for (int j = k + 1; j < n; j++) // pseudo-correction - { - Double* ptr_vk = V + (k + 1) * n + k; // v[k + 1, k] - Double* ptr_vj = V + (k + 1) * n + j; // v[k + 1, j] + for (int i = k; i < m; i++) + { + t += *uk * *uj; + uk += nu; uj += nu; + } - Double t = 0; - Double* vk = ptr_vk; - Double* vj = ptr_vj; + t = -t / *ptr_uk; - for (int i = k + 1; i < n; i++) - { - t += *vk * *vj; - vk += n; vj += n; + uk = ptr_uk; uj = ptr_uj; + for (int i = k; i < m; i++) + { + *uj += t * (*uk); + uk += nu; uj += nu; + } } - t = -t / *ptr_vk; - - vk = ptr_vk; vj = ptr_vj; - for (int i = k + 1; i < n; i++) + uk = ptr_uk; + for (int i = k; i < m; i++) { - *vj += t * (*vk); - vk += n; vj += n; + *uk = -(*uk); + uk += nu; } + + u[k, k] = 1 + u[k, k]; + for (int i = 0; i < k - 1; i++) + u[i, k] = 0; + } + else + { + for (int i = 0; i < m; i++) + u[i, k] = 0; + u[k, k] = 1; } } - - for (int i = 0; i < n; i++) - v[i, k] = 0; - v[k, k] = 1; } - } - // Main iteration loop for the singular values. - int pp = p - 1; - int iter = 0; - while (p > 0) - { - int k, kase; + // If required, generate V. + if (wantv) + { + for (int k = n - 1; k >= 0; k--) + { + if ((k < nrt) & (e[k] != 0)) + { + // TODO: The following is a pseudo correction to make SVD + // work on matrices with n > m (less rows than columns). + + // For the proper correction, compute the decomposition of the + // transpose of A and swap the left and right eigenvectors - // Here is where a test for too many iterations would go. + // Original line: + // for (int j = k + 1; j < nu; j++) + // Pseudo correction: + // for (int j = k + 1; j < n; j++) - // This section of the program inspects for - // negligible elements in the s and e arrays. On - // completion the variables kase and k are set as follows. + for (int j = k + 1; j < n; j++) // pseudo-correction + { + Double* ptr_vk = V + (k + 1) * n + k; // v[k + 1, k] + Double* ptr_vj = V + (k + 1) * n + j; // v[k + 1, j] - // kase = 1 if s(p) and e[k-1] are negligible and k

= -1; k--) - { - if (k == -1) - break; + for (int i = k + 1; i < n; i++) + { + t += *vk * *vj; + vk += n; vj += n; + } - var alpha = tiny + eps * (System.Math.Abs(s[k]) + System.Math.Abs(s[k + 1])); + t = -t / *ptr_vk; - if (System.Math.Abs(e[k]) <= alpha || Double.IsNaN(e[k])) - { - e[k] = 0; - break; + vk = ptr_vk; vj = ptr_vj; + for (int i = k + 1; i < n; i++) + { + *vj += t * (*vk); + vk += n; vj += n; + } + } + } + + for (int i = 0; i < n; i++) + v[i, k] = 0; + v[k, k] = 1; } } - if (k == p - 2) + // Main iteration loop for the singular values. + int pp = p - 1; + int iter = 0; + while (p > 0) { - kase = 4; - } - else - { - int ks; - for (ks = p - 1; ks >= k; ks--) + int k, kase; + + // Here is where a test for too many iterations would go. + + // This section of the program inspects for + // negligible elements in the s and e arrays. On + // completion the variables kase and k are set as follows. + + // kase = 1 if s(p) and e[k-1] are negligible and k

= -1; k--) { - if (ks == k) + if (k == -1) break; - Double t = (ks != p ? System.Math.Abs(e[ks]) : 0) + - (ks != k + 1 ? System.Math.Abs(e[ks - 1]) : 0); - if (System.Math.Abs(s[ks]) <= tiny + eps * t) + var alpha = tiny + eps * (System.Math.Abs(s[k]) + System.Math.Abs(s[k + 1])); + + if (System.Math.Abs(e[k]) <= alpha || Double.IsNaN(e[k])) { - s[ks] = 0; + e[k] = 0; break; } } - if (ks == k) - kase = 3; - else if (ks == p - 1) - kase = 1; - else + if (k == p - 2) { - kase = 2; - k = ks; + kase = 4; } - } + else + { + int ks; + for (ks = p - 1; ks >= k; ks--) + { + if (ks == k) + break; - k++; + Double t = (ks != p ? System.Math.Abs(e[ks]) : 0) + + (ks != k + 1 ? System.Math.Abs(e[ks - 1]) : 0); + if (System.Math.Abs(s[ks]) <= tiny + eps * t) + { + s[ks] = 0; + break; + } + } - // Perform the task indicated by kase. - switch (kase) - { - // Deflate negligible s(p). - case 1: + if (ks == k) + kase = 3; + else if (ks == p - 1) + kase = 1; + else { - Double f = e[p - 2]; - e[p - 2] = 0; - for (int j = p - 2; j >= k; j--) + kase = 2; + k = ks; + } + } + + k++; + + // Perform the task indicated by kase. + switch (kase) + { + // Deflate negligible s(p). + case 1: { - Double t = Accord.Math.Tools.Hypotenuse(s[j], f); - Double cs = s[j] / t; - Double sn = f / t; - s[j] = t; - if (j != k) + Double f = e[p - 2]; + e[p - 2] = 0; + for (int j = p - 2; j >= k; j--) { - f = -sn * e[j - 1]; - e[j - 1] = cs * e[j - 1]; - } + Double t = Accord.Math.Tools.Hypotenuse(s[j], f); + Double cs = s[j] / t; + Double sn = f / t; + s[j] = t; + if (j != k) + { + f = -sn * e[j - 1]; + e[j - 1] = cs * e[j - 1]; + } - if (wantv) - { - for (int i = 0; i < n; i++) + if (wantv) { - t = cs * v[i, j] + sn * v[i, p - 1]; - v[i, p - 1] = -sn * v[i, j] + cs * v[i, p - 1]; - v[i, j] = t; + for (int i = 0; i < n; i++) + { + t = cs * v[i, j] + sn * v[i, p - 1]; + v[i, p - 1] = -sn * v[i, j] + cs * v[i, p - 1]; + v[i, j] = t; + } } } } - } - break; + break; - // Split at negligible s(k). - case 2: - { - Double f = e[k - 1]; - e[k - 1] = 0; - for (int j = k; j < p; j++) + // Split at negligible s(k). + case 2: { - Double t = Accord.Math.Tools.Hypotenuse(s[j], f); - Double cs = s[j] / t; - Double sn = f / t; - s[j] = t; - f = -sn * e[j]; - e[j] = cs * e[j]; - - if (wantu) + Double f = e[k - 1]; + e[k - 1] = 0; + for (int j = k; j < p; j++) { - for (int i = 0; i < m; i++) + Double t = Accord.Math.Tools.Hypotenuse(s[j], f); + Double cs = s[j] / t; + Double sn = f / t; + s[j] = t; + f = -sn * e[j]; + e[j] = cs * e[j]; + + if (wantu) { - t = cs * u[i, j] + sn * u[i, k - 1]; - u[i, k - 1] = -sn * u[i, j] + cs * u[i, k - 1]; - u[i, j] = t; + for (int i = 0; i < m; i++) + { + t = cs * u[i, j] + sn * u[i, k - 1]; + u[i, k - 1] = -sn * u[i, j] + cs * u[i, k - 1]; + u[i, j] = t; + } } } } - } - break; + break; - // Perform one qr step. - case 3: - { - // Calculate the shift. - Double scale = System.Math.Max(System.Math.Max(System.Math.Max(System.Math.Max(System.Math.Abs(s[p - 1]), System.Math.Abs(s[p - 2])), System.Math.Abs(e[p - 2])), System.Math.Abs(s[k])), System.Math.Abs(e[k])); - Double sp = s[p - 1] / scale; - Double spm1 = s[p - 2] / scale; - Double epm1 = e[p - 2] / scale; - Double sk = s[k] / scale; - Double ek = e[k] / scale; - Double b = ((spm1 + sp) * (spm1 - sp) + epm1 * epm1) / 2; - Double c = (sp * epm1) * (sp * epm1); - double shift = 0; - - if ((b != 0) | (c != 0)) + // Perform one qr step. + case 3: { - if (b < 0) - shift = -System.Math.Sqrt(b * b + c); - else - shift = System.Math.Sqrt(b * b + c); + // Calculate the shift. + Double scale = System.Math.Max(System.Math.Max(System.Math.Max(System.Math.Max(System.Math.Abs(s[p - 1]), System.Math.Abs(s[p - 2])), System.Math.Abs(e[p - 2])), System.Math.Abs(s[k])), System.Math.Abs(e[k])); + Double sp = s[p - 1] / scale; + Double spm1 = s[p - 2] / scale; + Double epm1 = e[p - 2] / scale; + Double sk = s[k] / scale; + Double ek = e[k] / scale; + Double b = ((spm1 + sp) * (spm1 - sp) + epm1 * epm1) / 2; + Double c = (sp * epm1) * (sp * epm1); + double shift = 0; + + if ((b != 0) | (c != 0)) + { + if (b < 0) + shift = -System.Math.Sqrt(b * b + c); + else + shift = System.Math.Sqrt(b * b + c); - shift = c / (b + shift); - } + shift = c / (b + shift); + } - Double f = (sk + sp) * (sk - sp) + (Double)shift; - Double g = sk * ek; + Double f = (sk + sp) * (sk - sp) + (Double)shift; + Double g = sk * ek; - // Chase zeros. - for (int j = k; j < p - 1; j++) - { - Double t = Accord.Math.Tools.Hypotenuse(f, g); - Double cs = f / t; - Double sn = g / t; - if (j != k) e[j - 1] = t; - f = cs * s[j] + sn * e[j]; - e[j] = cs * e[j] - sn * s[j]; - g = sn * s[j + 1]; - s[j + 1] = cs * s[j + 1]; - - if (wantv) + // Chase zeros. + for (int j = k; j < p - 1; j++) { - unsafe + Double t = Accord.Math.Tools.Hypotenuse(f, g); + Double cs = f / t; + Double sn = g / t; + if (j != k) e[j - 1] = t; + f = cs * s[j] + sn * e[j]; + e[j] = cs * e[j] - sn * s[j]; + g = sn * s[j + 1]; + s[j + 1] = cs * s[j + 1]; + + if (wantv) { - fixed (Double* ptr_vj = &v[0, j]) + unsafe { - Double* vj = ptr_vj; - Double* vj1 = ptr_vj + 1; - - for (int i = 0; i < n; i++) + fixed (Double* ptr_vj = &v[0, j]) { - /*t = cs * v[i, j] + sn * v[i, j + 1]; - v[i, j + 1] = -sn * v[i, j] + cs * v[i, j + 1]; - v[i, j] = t;*/ + Double* vj = ptr_vj; + Double* vj1 = ptr_vj + 1; + + for (int i = 0; i < n; i++) + { + /*t = cs * v[i, j] + sn * v[i, j + 1]; + v[i, j + 1] = -sn * v[i, j] + cs * v[i, j + 1]; + v[i, j] = t;*/ - Double vij = *vj; - Double vij1 = *vj1; + Double vij = *vj; + Double vij1 = *vj1; - t = cs * vij + sn * vij1; - *vj1 = -sn * vij + cs * vij1; - *vj = t; + t = cs * vij + sn * vij1; + *vj1 = -sn * vij + cs * vij1; + *vj = t; - vj += n; vj1 += n; + vj += n; vj1 += n; + } } } } - } - t = Accord.Math.Tools.Hypotenuse(f, g); - cs = f / t; - sn = g / t; - s[j] = t; - f = cs * e[j] + sn * s[j + 1]; - s[j + 1] = -sn * e[j] + cs * s[j + 1]; - g = sn * e[j + 1]; - e[j + 1] = cs * e[j + 1]; + t = Accord.Math.Tools.Hypotenuse(f, g); + cs = f / t; + sn = g / t; + s[j] = t; + f = cs * e[j] + sn * s[j + 1]; + s[j + 1] = -sn * e[j] + cs * s[j + 1]; + g = sn * e[j + 1]; + e[j + 1] = cs * e[j + 1]; - if (wantu && (j < m - 1)) - { - fixed (Double* ptr_uj = &u[0, j]) + if (wantu && (j < m - 1)) { - Double* uj = ptr_uj; - Double* uj1 = ptr_uj + 1; - - for (int i = 0; i < m; i++) + fixed (Double* ptr_uj = &u[0, j]) { - /* t = cs * u[i, j] + sn * u[i, j + 1]; - u[i, j + 1] = -sn * u[i, j] + cs * u[i, j + 1]; - u[i, j] = t;*/ + Double* uj = ptr_uj; + Double* uj1 = ptr_uj + 1; + + for (int i = 0; i < m; i++) + { + /* t = cs * u[i, j] + sn * u[i, j + 1]; + u[i, j + 1] = -sn * u[i, j] + cs * u[i, j + 1]; + u[i, j] = t;*/ - Double uij = *uj; - Double uij1 = *uj1; + Double uij = *uj; + Double uij1 = *uj1; - t = cs * uij + sn * uij1; - *uj1 = -sn * uij + cs * uij1; - *uj = t; + t = cs * uij + sn * uij1; + *uj1 = -sn * uij + cs * uij1; + *uj = t; - uj += nu; uj1 += nu; + uj += nu; uj1 += nu; + } } } + } + e[p - 2] = f; + iter = iter + 1; } + break; - e[p - 2] = f; - iter = iter + 1; - } - break; - - // Convergence. - case 4: - { - // Make the singular values positive. - if (s[k] <= 0) + // Convergence. + case 4: { - s[k] = (s[k] < 0 ? -s[k] : 0); - if (wantv) + // Make the singular values positive. + if (s[k] <= 0) { - for (int i = 0; i <= pp; i++) - v[i, k] = -v[i, k]; + s[k] = (s[k] < 0 ? -s[k] : 0); + if (wantv) + { + for (int i = 0; i <= pp; i++) + v[i, k] = -v[i, k]; + } } - } - // Order the singular values. - while (k < pp) - { - if (s[k] >= s[k + 1]) - break; + // Order the singular values. + while (k < pp) + { + if (s[k] >= s[k + 1]) + break; - Double t = s[k]; - s[k] = s[k + 1]; - s[k + 1] = t; + Double t = s[k]; + s[k] = s[k + 1]; + s[k + 1] = t; - int ti = si[k]; - si[k] = si[k + 1]; - si[k + 1] = ti; + int ti = si[k]; + si[k] = si[k + 1]; + si[k + 1] = ti; - if (wantv && (k < n - 1)) - { - for (int i = 0; i < n; i++) + if (wantv && (k < n - 1)) { - t = v[i, k + 1]; - v[i, k + 1] = v[i, k]; - v[i, k] = t; + for (int i = 0; i < n; i++) + { + t = v[i, k + 1]; + v[i, k + 1] = v[i, k]; + v[i, k] = t; + } } - } - if (wantu && (k < m - 1)) - { - for (int i = 0; i < m; i++) + if (wantu && (k < m - 1)) { - t = u[i, k + 1]; - u[i, k + 1] = u[i, k]; - u[i, k] = t; + for (int i = 0; i < m; i++) + { + t = u[i, k + 1]; + u[i, k + 1] = u[i, k]; + u[i, k] = t; + } } + + k++; } - k++; + iter = 0; + p--; } - - iter = 0; - p--; - } - break; + break; + } } - } + } } // If we are violating JAMA's assumption about diff --git a/Sources/Accord.Math/Decompositions/SingularValueDecomposition.tt b/Sources/Accord.Math/Decompositions/SingularValueDecomposition.tt index 60e480128..e736367fe 100644 --- a/Sources/Accord.Math/Decompositions/SingularValueDecomposition.tt +++ b/Sources/Accord.Math/Decompositions/SingularValueDecomposition.tt @@ -360,7 +360,7 @@ namespace Accord.Math.Decompositions /// will be destroyed in the process, resulting in less /// memory comsumption. /// - public unsafe SingularValueDecomposition<#=Suffix#>(<#=T#>[,] value, + public SingularValueDecomposition<#=Suffix#>(<#=T#>[,] value, bool computeLeftSingularVectors, bool computeRightSingularVectors, bool autoTranspose, bool inPlace) { if (value == null) @@ -423,549 +423,552 @@ namespace Accord.Math.Decompositions bool wantu = computeLeftSingularVectors; bool wantv = computeRightSingularVectors; - fixed (<#=T#>* U = u) - fixed (<#=T#>* V = v) - fixed (<#=T#>* A = a) - { - - // Will store ordered sequence of indices after sorting. - si = new int[ni]; for (int i = 0; i < ni; i++) si[i] = i; - - - // Reduce A to bidiagonal form, storing the diagonal elements in s and the super-diagonal elements in e. - int nct = System.Math.Min(m - 1, n); - int nrt = System.Math.Max(0, System.Math.Min(n - 2, m)); - int mrc = System.Math.Max(nct, nrt); - - for (int k = 0; k < mrc; k++) - { - if (k < nct) - { - // Compute the transformation for the k-th column and place the k-th diagonal in s[k]. - // Compute 2-norm of k-th column without under/overflow. - s[k] = 0; - for (int i = k; i < m; i++) - s[k] = Accord.Math.Tools.Hypotenuse(s[k], a[i, k]); - - if (s[k] != 0) - { - if (a[k, k] < 0) - s[k] = -s[k]; - - for (int i = k; i < m; i++) - a[i, k] /= s[k]; - - a[k, k] += 1; - } - - s[k] = -s[k]; - } - - for (int j = k + 1; j < n; j++) - { - <#=T#>* ptr_ak = A + k * n + k; // A[k,k] - <#=T#>* ptr_aj = A + k * n + j; // A[k,j] - - if ((k < nct) & (s[k] != 0)) - { - // Apply the transformation. - <#=T#> t = 0; - <#=T#>* ak = ptr_ak; - <#=T#>* aj = ptr_aj; - - for (int i = k; i < m; i++) - { - t += (*ak) * (*aj); - ak += n; aj += n; - } - - t = -t / *ptr_ak; - ak = ptr_ak; - aj = ptr_aj; - - for (int i = k; i < m; i++) - { - *aj += t * (*ak); - ak += n; aj += n; - } - } - - // Place the k-th row of A into e for the subsequent calculation of the row transformation. - e[j] = *ptr_aj; - } - - - if (wantu & (k < nct)) - { - // Place the transformation in U for subsequent back - // multiplication. - for (int i = k; i < m; i++) - u[i, k] = a[i, k]; - } - - if (k < nrt) - { - // Compute the k-th row transformation and place the k-th super-diagonal in e[k]. - // Compute 2-norm without under/overflow. - e[k] = 0; - for (int i = k + 1; i < n; i++) - e[k] = Accord.Math.Tools.Hypotenuse(e[k], e[i]); - - if (e[k] != 0) - { - if (e[k + 1] < 0) - e[k] = -e[k]; - - for (int i = k + 1; i < n; i++) - e[i] /= e[k]; - - e[k + 1] += 1; - } - - e[k] = -e[k]; - if ((k + 1 < m) & (e[k] != 0)) - { - // Apply the transformation. - for (int i = k + 1; i < m; i++) - work[i] = 0; - - int k1 = k + 1; - for (int i = k1; i < m; i++) - { - <#=T#>* ai = A + (i * n) + k1; - for (int j = k1; j < n; j++, ai++) - work[i] += e[j] * (*ai); - } - - for (int j = k1; j < n; j++) - { - <#=T#> t = -e[j] / e[k1]; - <#=T#>* aj = A + (k1 * n) + j; - for (int i = k1; i < m; i++, aj += n) - *aj += t * work[i]; - } - } - - if (wantv) - { - // Place the transformation in V for subsequent back multiplication. - for (int i = k + 1; i < n; i++) - v[i, k] = e[i]; - } - } - } - - // Set up the final bidiagonal matrix or order p. - int p = System.Math.Min(n, m + 1); - if (nct < n) s[nct] = a[nct, nct]; - if (m < p) s[p - 1] = 0; - if (nrt + 1 < p) e[nrt] = a[nrt, p - 1]; - e[p - 1] = 0; - - // If required, generate U. - if (wantu) - { - for (int j = nct; j < nu; j++) - { - for (int i = 0; i < m; i++) - u[i, j] = 0; - u[j, j] = 1; - } - - for (int k = nct - 1; k >= 0; k--) - { - if (s[k] != 0) - { - <#=T#>* ptr_uk = U + k * nu + k; // u[k,k] - - <#=T#>* uk, uj; - for (int j = k + 1; j < nu; j++) - { - <#=T#>* ptr_uj = U + k * nu + j; // u[k,j] - - <#=T#> t = 0; - uk = ptr_uk; - uj = ptr_uj; - - for (int i = k; i < m; i++) - { - t += *uk * *uj; - uk += nu; uj += nu; - } - - t = -t / *ptr_uk; - - uk = ptr_uk; uj = ptr_uj; - for (int i = k; i < m; i++) - { - *uj += t * (*uk); - uk += nu; uj += nu; - } - } - - uk = ptr_uk; - for (int i = k; i < m; i++) - { - *uk = -(*uk); - uk += nu; - } - - u[k, k] = 1 + u[k, k]; - for (int i = 0; i < k - 1; i++) - u[i, k] = 0; - } - else - { - for (int i = 0; i < m; i++) - u[i, k] = 0; - u[k, k] = 1; - } - } - } - - // If required, generate V. - if (wantv) - { - for (int k = n - 1; k >= 0; k--) - { - if ((k < nrt) & (e[k] != 0)) - { - // TODO: The following is a pseudo correction to make SVD - // work on matrices with n > m (less rows than columns). - - // For the proper correction, compute the decomposition of the - // transpose of A and swap the left and right eigenvectors - - // Original line: - // for (int j = k + 1; j < nu; j++) - // Pseudo correction: - // for (int j = k + 1; j < n; j++) - - for (int j = k + 1; j < n; j++) // pseudo-correction - { - <#=T#>* ptr_vk = V + (k + 1) * n + k; // v[k + 1, k] - <#=T#>* ptr_vj = V + (k + 1) * n + j; // v[k + 1, j] - - <#=T#> t = 0; - <#=T#>* vk = ptr_vk; - <#=T#>* vj = ptr_vj; - - for (int i = k + 1; i < n; i++) - { - t += *vk * *vj; - vk += n; vj += n; - } - - t = -t / *ptr_vk; - - vk = ptr_vk; vj = ptr_vj; - for (int i = k + 1; i < n; i++) - { - *vj += t * (*vk); - vk += n; vj += n; - } - } - } - - for (int i = 0; i < n; i++) - v[i, k] = 0; - v[k, k] = 1; - } - } - - // Main iteration loop for the singular values. - int pp = p - 1; - int iter = 0; - while (p > 0) - { - int k, kase; - - // Here is where a test for too many iterations would go. - - // This section of the program inspects for - // negligible elements in the s and e arrays. On - // completion the variables kase and k are set as follows. - - // kase = 1 if s(p) and e[k-1] are negligible and k

= -1; k--) - { - if (k == -1) - break; - - var alpha = tiny + eps * (System.Math.Abs(s[k]) + System.Math.Abs(s[k + 1])); - - if (System.Math.Abs(e[k]) <= alpha || <#=T#>.IsNaN(e[k])) - { - e[k] = 0; - break; - } - } - - if (k == p - 2) - { - kase = 4; - } - else - { - int ks; - for (ks = p - 1; ks >= k; ks--) - { - if (ks == k) - break; - - <#=T#> t = (ks != p ? System.Math.Abs(e[ks]) : 0) + - (ks != k + 1 ? System.Math.Abs(e[ks - 1]) : 0); - if (System.Math.Abs(s[ks]) <= tiny + eps * t) - { - s[ks] = 0; - break; - } - } - - if (ks == k) - kase = 3; - else if (ks == p - 1) - kase = 1; - else - { - kase = 2; - k = ks; - } - } - - k++; - - // Perform the task indicated by kase. - switch (kase) - { - // Deflate negligible s(p). - case 1: - { - <#=T#> f = e[p - 2]; - e[p - 2] = 0; - for (int j = p - 2; j >= k; j--) - { - <#=T#> t = Accord.Math.Tools.Hypotenuse(s[j], f); - <#=T#> cs = s[j] / t; - <#=T#> sn = f / t; - s[j] = t; - if (j != k) - { - f = -sn * e[j - 1]; - e[j - 1] = cs * e[j - 1]; - } - - if (wantv) - { - for (int i = 0; i < n; i++) - { - t = cs * v[i, j] + sn * v[i, p - 1]; - v[i, p - 1] = -sn * v[i, j] + cs * v[i, p - 1]; - v[i, j] = t; - } - } - } - } - break; - - // Split at negligible s(k). - case 2: - { - <#=T#> f = e[k - 1]; - e[k - 1] = 0; - for (int j = k; j < p; j++) - { - <#=T#> t = Accord.Math.Tools.Hypotenuse(s[j], f); - <#=T#> cs = s[j] / t; - <#=T#> sn = f / t; - s[j] = t; - f = -sn * e[j]; - e[j] = cs * e[j]; - - if (wantu) - { - for (int i = 0; i < m; i++) - { - t = cs * u[i, j] + sn * u[i, k - 1]; - u[i, k - 1] = -sn * u[i, j] + cs * u[i, k - 1]; - u[i, j] = t; - } - } - } - } - break; - - // Perform one qr step. - case 3: - { - // Calculate the shift. - <#=T#> scale = System.Math.Max(System.Math.Max(System.Math.Max(System.Math.Max(System.Math.Abs(s[p - 1]), System.Math.Abs(s[p - 2])), System.Math.Abs(e[p - 2])), System.Math.Abs(s[k])), System.Math.Abs(e[k])); - <#=T#> sp = s[p - 1] / scale; - <#=T#> spm1 = s[p - 2] / scale; - <#=T#> epm1 = e[p - 2] / scale; - <#=T#> sk = s[k] / scale; - <#=T#> ek = e[k] / scale; - <#=T#> b = ((spm1 + sp) * (spm1 - sp) + epm1 * epm1) / 2; - <#=T#> c = (sp * epm1) * (sp * epm1); - double shift = 0; - - if ((b != 0) | (c != 0)) - { - if (b < 0) - shift = -System.Math.Sqrt(b * b + c); - else - shift = System.Math.Sqrt(b * b + c); - - shift = c / (b + shift); - } - - <#=T#> f = (sk + sp) * (sk - sp) + (<#=T#>)shift; - <#=T#> g = sk * ek; - - // Chase zeros. - for (int j = k; j < p - 1; j++) - { - <#=T#> t = Accord.Math.Tools.Hypotenuse(f, g); - <#=T#> cs = f / t; - <#=T#> sn = g / t; - if (j != k) e[j - 1] = t; - f = cs * s[j] + sn * e[j]; - e[j] = cs * e[j] - sn * s[j]; - g = sn * s[j + 1]; - s[j + 1] = cs * s[j + 1]; - - if (wantv) - { - unsafe - { - fixed (<#=T#>* ptr_vj = &v[0, j]) - { - <#=T#>* vj = ptr_vj; - <#=T#>* vj1 = ptr_vj + 1; - - for (int i = 0; i < n; i++) - { - /*t = cs * v[i, j] + sn * v[i, j + 1]; - v[i, j + 1] = -sn * v[i, j] + cs * v[i, j + 1]; - v[i, j] = t;*/ - - <#=T#> vij = *vj; - <#=T#> vij1 = *vj1; - - t = cs * vij + sn * vij1; - *vj1 = -sn * vij + cs * vij1; - *vj = t; - - vj += n; vj1 += n; - } - } - } - } - - t = Accord.Math.Tools.Hypotenuse(f, g); - cs = f / t; - sn = g / t; - s[j] = t; - f = cs * e[j] + sn * s[j + 1]; - s[j + 1] = -sn * e[j] + cs * s[j + 1]; - g = sn * e[j + 1]; - e[j + 1] = cs * e[j + 1]; - - if (wantu && (j < m - 1)) - { - fixed (<#=T#>* ptr_uj = &u[0, j]) - { - <#=T#>* uj = ptr_uj; - <#=T#>* uj1 = ptr_uj + 1; - - for (int i = 0; i < m; i++) - { - /* t = cs * u[i, j] + sn * u[i, j + 1]; - u[i, j + 1] = -sn * u[i, j] + cs * u[i, j + 1]; - u[i, j] = t;*/ - - <#=T#> uij = *uj; - <#=T#> uij1 = *uj1; - - t = cs * uij + sn * uij1; - *uj1 = -sn * uij + cs * uij1; - *uj = t; - - uj += nu; uj1 += nu; - } - } - } - - } - - e[p - 2] = f; - iter = iter + 1; - } - break; - - // Convergence. - case 4: - { - // Make the singular values positive. - if (s[k] <= 0) - { - s[k] = (s[k] < 0 ? -s[k] : 0); - if (wantv) - { - for (int i = 0; i <= pp; i++) - v[i, k] = -v[i, k]; - } - } - - // Order the singular values. - while (k < pp) - { - if (s[k] >= s[k + 1]) - break; - - <#=T#> t = s[k]; - s[k] = s[k + 1]; - s[k + 1] = t; - - int ti = si[k]; - si[k] = si[k + 1]; - si[k + 1] = ti; - - if (wantv && (k < n - 1)) - { - for (int i = 0; i < n; i++) - { - t = v[i, k + 1]; - v[i, k + 1] = v[i, k]; - v[i, k] = t; - } - } - - if (wantu && (k < m - 1)) - { - for (int i = 0; i < m; i++) - { - t = u[i, k + 1]; - u[i, k + 1] = u[i, k]; - u[i, k] = t; - } - } - - k++; - } - - iter = 0; - p--; - } - break; - } - } - } + unsafe + { + fixed (<#=T#>* U = u) + fixed (<#=T#>* V = v) + fixed (<#=T#>* A = a) + { + + // Will store ordered sequence of indices after sorting. + si = new int[ni]; for (int i = 0; i < ni; i++) si[i] = i; + + + // Reduce A to bidiagonal form, storing the diagonal elements in s and the super-diagonal elements in e. + int nct = System.Math.Min(m - 1, n); + int nrt = System.Math.Max(0, System.Math.Min(n - 2, m)); + int mrc = System.Math.Max(nct, nrt); + + for (int k = 0; k < mrc; k++) + { + if (k < nct) + { + // Compute the transformation for the k-th column and place the k-th diagonal in s[k]. + // Compute 2-norm of k-th column without under/overflow. + s[k] = 0; + for (int i = k; i < m; i++) + s[k] = Accord.Math.Tools.Hypotenuse(s[k], a[i, k]); + + if (s[k] != 0) + { + if (a[k, k] < 0) + s[k] = -s[k]; + + for (int i = k; i < m; i++) + a[i, k] /= s[k]; + + a[k, k] += 1; + } + + s[k] = -s[k]; + } + + for (int j = k + 1; j < n; j++) + { + <#=T#>* ptr_ak = A + k * n + k; // A[k,k] + <#=T#>* ptr_aj = A + k * n + j; // A[k,j] + + if ((k < nct) & (s[k] != 0)) + { + // Apply the transformation. + <#=T#> t = 0; + <#=T#>* ak = ptr_ak; + <#=T#>* aj = ptr_aj; + + for (int i = k; i < m; i++) + { + t += (*ak) * (*aj); + ak += n; aj += n; + } + + t = -t / *ptr_ak; + ak = ptr_ak; + aj = ptr_aj; + + for (int i = k; i < m; i++) + { + *aj += t * (*ak); + ak += n; aj += n; + } + } + + // Place the k-th row of A into e for the subsequent calculation of the row transformation. + e[j] = *ptr_aj; + } + + + if (wantu & (k < nct)) + { + // Place the transformation in U for subsequent back + // multiplication. + for (int i = k; i < m; i++) + u[i, k] = a[i, k]; + } + + if (k < nrt) + { + // Compute the k-th row transformation and place the k-th super-diagonal in e[k]. + // Compute 2-norm without under/overflow. + e[k] = 0; + for (int i = k + 1; i < n; i++) + e[k] = Accord.Math.Tools.Hypotenuse(e[k], e[i]); + + if (e[k] != 0) + { + if (e[k + 1] < 0) + e[k] = -e[k]; + + for (int i = k + 1; i < n; i++) + e[i] /= e[k]; + + e[k + 1] += 1; + } + + e[k] = -e[k]; + if ((k + 1 < m) & (e[k] != 0)) + { + // Apply the transformation. + for (int i = k + 1; i < m; i++) + work[i] = 0; + + int k1 = k + 1; + for (int i = k1; i < m; i++) + { + <#=T#>* ai = A + (i * n) + k1; + for (int j = k1; j < n; j++, ai++) + work[i] += e[j] * (*ai); + } + + for (int j = k1; j < n; j++) + { + <#=T#> t = -e[j] / e[k1]; + <#=T#>* aj = A + (k1 * n) + j; + for (int i = k1; i < m; i++, aj += n) + *aj += t * work[i]; + } + } + + if (wantv) + { + // Place the transformation in V for subsequent back multiplication. + for (int i = k + 1; i < n; i++) + v[i, k] = e[i]; + } + } + } + + // Set up the final bidiagonal matrix or order p. + int p = System.Math.Min(n, m + 1); + if (nct < n) s[nct] = a[nct, nct]; + if (m < p) s[p - 1] = 0; + if (nrt + 1 < p) e[nrt] = a[nrt, p - 1]; + e[p - 1] = 0; + + // If required, generate U. + if (wantu) + { + for (int j = nct; j < nu; j++) + { + for (int i = 0; i < m; i++) + u[i, j] = 0; + u[j, j] = 1; + } + + for (int k = nct - 1; k >= 0; k--) + { + if (s[k] != 0) + { + <#=T#>* ptr_uk = U + k * nu + k; // u[k,k] + + <#=T#>* uk, uj; + for (int j = k + 1; j < nu; j++) + { + <#=T#>* ptr_uj = U + k * nu + j; // u[k,j] + + <#=T#> t = 0; + uk = ptr_uk; + uj = ptr_uj; + + for (int i = k; i < m; i++) + { + t += *uk * *uj; + uk += nu; uj += nu; + } + + t = -t / *ptr_uk; + + uk = ptr_uk; uj = ptr_uj; + for (int i = k; i < m; i++) + { + *uj += t * (*uk); + uk += nu; uj += nu; + } + } + + uk = ptr_uk; + for (int i = k; i < m; i++) + { + *uk = -(*uk); + uk += nu; + } + + u[k, k] = 1 + u[k, k]; + for (int i = 0; i < k - 1; i++) + u[i, k] = 0; + } + else + { + for (int i = 0; i < m; i++) + u[i, k] = 0; + u[k, k] = 1; + } + } + } + + // If required, generate V. + if (wantv) + { + for (int k = n - 1; k >= 0; k--) + { + if ((k < nrt) & (e[k] != 0)) + { + // TODO: The following is a pseudo correction to make SVD + // work on matrices with n > m (less rows than columns). + + // For the proper correction, compute the decomposition of the + // transpose of A and swap the left and right eigenvectors + + // Original line: + // for (int j = k + 1; j < nu; j++) + // Pseudo correction: + // for (int j = k + 1; j < n; j++) + + for (int j = k + 1; j < n; j++) // pseudo-correction + { + <#=T#>* ptr_vk = V + (k + 1) * n + k; // v[k + 1, k] + <#=T#>* ptr_vj = V + (k + 1) * n + j; // v[k + 1, j] + + <#=T#> t = 0; + <#=T#>* vk = ptr_vk; + <#=T#>* vj = ptr_vj; + + for (int i = k + 1; i < n; i++) + { + t += *vk * *vj; + vk += n; vj += n; + } + + t = -t / *ptr_vk; + + vk = ptr_vk; vj = ptr_vj; + for (int i = k + 1; i < n; i++) + { + *vj += t * (*vk); + vk += n; vj += n; + } + } + } + + for (int i = 0; i < n; i++) + v[i, k] = 0; + v[k, k] = 1; + } + } + + // Main iteration loop for the singular values. + int pp = p - 1; + int iter = 0; + while (p > 0) + { + int k, kase; + + // Here is where a test for too many iterations would go. + + // This section of the program inspects for + // negligible elements in the s and e arrays. On + // completion the variables kase and k are set as follows. + + // kase = 1 if s(p) and e[k-1] are negligible and k

= -1; k--) + { + if (k == -1) + break; + + var alpha = tiny + eps * (System.Math.Abs(s[k]) + System.Math.Abs(s[k + 1])); + + if (System.Math.Abs(e[k]) <= alpha || <#=T#>.IsNaN(e[k])) + { + e[k] = 0; + break; + } + } + + if (k == p - 2) + { + kase = 4; + } + else + { + int ks; + for (ks = p - 1; ks >= k; ks--) + { + if (ks == k) + break; + + <#=T#> t = (ks != p ? System.Math.Abs(e[ks]) : 0) + + (ks != k + 1 ? System.Math.Abs(e[ks - 1]) : 0); + if (System.Math.Abs(s[ks]) <= tiny + eps * t) + { + s[ks] = 0; + break; + } + } + + if (ks == k) + kase = 3; + else if (ks == p - 1) + kase = 1; + else + { + kase = 2; + k = ks; + } + } + + k++; + + // Perform the task indicated by kase. + switch (kase) + { + // Deflate negligible s(p). + case 1: + { + <#=T#> f = e[p - 2]; + e[p - 2] = 0; + for (int j = p - 2; j >= k; j--) + { + <#=T#> t = Accord.Math.Tools.Hypotenuse(s[j], f); + <#=T#> cs = s[j] / t; + <#=T#> sn = f / t; + s[j] = t; + if (j != k) + { + f = -sn * e[j - 1]; + e[j - 1] = cs * e[j - 1]; + } + + if (wantv) + { + for (int i = 0; i < n; i++) + { + t = cs * v[i, j] + sn * v[i, p - 1]; + v[i, p - 1] = -sn * v[i, j] + cs * v[i, p - 1]; + v[i, j] = t; + } + } + } + } + break; + + // Split at negligible s(k). + case 2: + { + <#=T#> f = e[k - 1]; + e[k - 1] = 0; + for (int j = k; j < p; j++) + { + <#=T#> t = Accord.Math.Tools.Hypotenuse(s[j], f); + <#=T#> cs = s[j] / t; + <#=T#> sn = f / t; + s[j] = t; + f = -sn * e[j]; + e[j] = cs * e[j]; + + if (wantu) + { + for (int i = 0; i < m; i++) + { + t = cs * u[i, j] + sn * u[i, k - 1]; + u[i, k - 1] = -sn * u[i, j] + cs * u[i, k - 1]; + u[i, j] = t; + } + } + } + } + break; + + // Perform one qr step. + case 3: + { + // Calculate the shift. + <#=T#> scale = System.Math.Max(System.Math.Max(System.Math.Max(System.Math.Max(System.Math.Abs(s[p - 1]), System.Math.Abs(s[p - 2])), System.Math.Abs(e[p - 2])), System.Math.Abs(s[k])), System.Math.Abs(e[k])); + <#=T#> sp = s[p - 1] / scale; + <#=T#> spm1 = s[p - 2] / scale; + <#=T#> epm1 = e[p - 2] / scale; + <#=T#> sk = s[k] / scale; + <#=T#> ek = e[k] / scale; + <#=T#> b = ((spm1 + sp) * (spm1 - sp) + epm1 * epm1) / 2; + <#=T#> c = (sp * epm1) * (sp * epm1); + double shift = 0; + + if ((b != 0) | (c != 0)) + { + if (b < 0) + shift = -System.Math.Sqrt(b * b + c); + else + shift = System.Math.Sqrt(b * b + c); + + shift = c / (b + shift); + } + + <#=T#> f = (sk + sp) * (sk - sp) + (<#=T#>)shift; + <#=T#> g = sk * ek; + + // Chase zeros. + for (int j = k; j < p - 1; j++) + { + <#=T#> t = Accord.Math.Tools.Hypotenuse(f, g); + <#=T#> cs = f / t; + <#=T#> sn = g / t; + if (j != k) e[j - 1] = t; + f = cs * s[j] + sn * e[j]; + e[j] = cs * e[j] - sn * s[j]; + g = sn * s[j + 1]; + s[j + 1] = cs * s[j + 1]; + + if (wantv) + { + unsafe + { + fixed (<#=T#>* ptr_vj = &v[0, j]) + { + <#=T#>* vj = ptr_vj; + <#=T#>* vj1 = ptr_vj + 1; + + for (int i = 0; i < n; i++) + { + /*t = cs * v[i, j] + sn * v[i, j + 1]; + v[i, j + 1] = -sn * v[i, j] + cs * v[i, j + 1]; + v[i, j] = t;*/ + + <#=T#> vij = *vj; + <#=T#> vij1 = *vj1; + + t = cs * vij + sn * vij1; + *vj1 = -sn * vij + cs * vij1; + *vj = t; + + vj += n; vj1 += n; + } + } + } + } + + t = Accord.Math.Tools.Hypotenuse(f, g); + cs = f / t; + sn = g / t; + s[j] = t; + f = cs * e[j] + sn * s[j + 1]; + s[j + 1] = -sn * e[j] + cs * s[j + 1]; + g = sn * e[j + 1]; + e[j + 1] = cs * e[j + 1]; + + if (wantu && (j < m - 1)) + { + fixed (<#=T#>* ptr_uj = &u[0, j]) + { + <#=T#>* uj = ptr_uj; + <#=T#>* uj1 = ptr_uj + 1; + + for (int i = 0; i < m; i++) + { + /* t = cs * u[i, j] + sn * u[i, j + 1]; + u[i, j + 1] = -sn * u[i, j] + cs * u[i, j + 1]; + u[i, j] = t;*/ + + <#=T#> uij = *uj; + <#=T#> uij1 = *uj1; + + t = cs * uij + sn * uij1; + *uj1 = -sn * uij + cs * uij1; + *uj = t; + + uj += nu; uj1 += nu; + } + } + } + + } + + e[p - 2] = f; + iter = iter + 1; + } + break; + + // Convergence. + case 4: + { + // Make the singular values positive. + if (s[k] <= 0) + { + s[k] = (s[k] < 0 ? -s[k] : 0); + if (wantv) + { + for (int i = 0; i <= pp; i++) + v[i, k] = -v[i, k]; + } + } + + // Order the singular values. + while (k < pp) + { + if (s[k] >= s[k + 1]) + break; + + <#=T#> t = s[k]; + s[k] = s[k + 1]; + s[k + 1] = t; + + int ti = si[k]; + si[k] = si[k + 1]; + si[k + 1] = ti; + + if (wantv && (k < n - 1)) + { + for (int i = 0; i < n; i++) + { + t = v[i, k + 1]; + v[i, k + 1] = v[i, k]; + v[i, k] = t; + } + } + + if (wantu && (k < m - 1)) + { + for (int i = 0; i < m; i++) + { + t = u[i, k + 1]; + u[i, k + 1] = u[i, k]; + u[i, k] = t; + } + } + + k++; + } + + iter = 0; + p--; + } + break; + } + } + } + } // If we are violating JAMA's assumption about // the input dimension, we need to swap u and v. diff --git a/Sources/Accord.Math/Decompositions/SingularValueDecompositionF.cs b/Sources/Accord.Math/Decompositions/SingularValueDecompositionF.cs index 2d0ce77c9..4680b243a 100644 --- a/Sources/Accord.Math/Decompositions/SingularValueDecompositionF.cs +++ b/Sources/Accord.Math/Decompositions/SingularValueDecompositionF.cs @@ -342,7 +342,7 @@ public SingularValueDecompositionF(Single[,] value, /// will be destroyed in the process, resulting in less /// memory comsumption. /// - public unsafe SingularValueDecompositionF(Single[,] value, + public SingularValueDecompositionF(Single[,] value, bool computeLeftSingularVectors, bool computeRightSingularVectors, bool autoTranspose, bool inPlace) { if (value == null) @@ -405,548 +405,551 @@ public unsafe SingularValueDecompositionF(Single[,] value, bool wantu = computeLeftSingularVectors; bool wantv = computeRightSingularVectors; - fixed (Single* U = u) - fixed (Single* V = v) - fixed (Single* A = a) + unsafe { - - // Will store ordered sequence of indices after sorting. - si = new int[ni]; for (int i = 0; i < ni; i++) si[i] = i; - - - // Reduce A to bidiagonal form, storing the diagonal elements in s and the super-diagonal elements in e. - int nct = System.Math.Min(m - 1, n); - int nrt = System.Math.Max(0, System.Math.Min(n - 2, m)); - int mrc = System.Math.Max(nct, nrt); - - for (int k = 0; k < mrc; k++) + fixed (Single* U = u) + fixed (Single* V = v) + fixed (Single* A = a) { - if (k < nct) - { - // Compute the transformation for the k-th column and place the k-th diagonal in s[k]. - // Compute 2-norm of k-th column without under/overflow. - s[k] = 0; - for (int i = k; i < m; i++) - s[k] = Accord.Math.Tools.Hypotenuse(s[k], a[i, k]); - if (s[k] != 0) - { - if (a[k, k] < 0) - s[k] = -s[k]; - - for (int i = k; i < m; i++) - a[i, k] /= s[k]; + // Will store ordered sequence of indices after sorting. + si = new int[ni]; for (int i = 0; i < ni; i++) si[i] = i; - a[k, k] += 1; - } - s[k] = -s[k]; - } + // Reduce A to bidiagonal form, storing the diagonal elements in s and the super-diagonal elements in e. + int nct = System.Math.Min(m - 1, n); + int nrt = System.Math.Max(0, System.Math.Min(n - 2, m)); + int mrc = System.Math.Max(nct, nrt); - for (int j = k + 1; j < n; j++) + for (int k = 0; k < mrc; k++) { - Single* ptr_ak = A + k * n + k; // A[k,k] - Single* ptr_aj = A + k * n + j; // A[k,j] - - if ((k < nct) & (s[k] != 0)) + if (k < nct) { - // Apply the transformation. - Single t = 0; - Single* ak = ptr_ak; - Single* aj = ptr_aj; - + // Compute the transformation for the k-th column and place the k-th diagonal in s[k]. + // Compute 2-norm of k-th column without under/overflow. + s[k] = 0; for (int i = k; i < m; i++) + s[k] = Accord.Math.Tools.Hypotenuse(s[k], a[i, k]); + + if (s[k] != 0) { - t += (*ak) * (*aj); - ak += n; aj += n; - } + if (a[k, k] < 0) + s[k] = -s[k]; - t = -t / *ptr_ak; - ak = ptr_ak; - aj = ptr_aj; + for (int i = k; i < m; i++) + a[i, k] /= s[k]; - for (int i = k; i < m; i++) - { - *aj += t * (*ak); - ak += n; aj += n; + a[k, k] += 1; } - } - // Place the k-th row of A into e for the subsequent calculation of the row transformation. - e[j] = *ptr_aj; - } + s[k] = -s[k]; + } + for (int j = k + 1; j < n; j++) + { + Single* ptr_ak = A + k * n + k; // A[k,k] + Single* ptr_aj = A + k * n + j; // A[k,j] - if (wantu & (k < nct)) - { - // Place the transformation in U for subsequent back - // multiplication. - for (int i = k; i < m; i++) - u[i, k] = a[i, k]; - } + if ((k < nct) & (s[k] != 0)) + { + // Apply the transformation. + Single t = 0; + Single* ak = ptr_ak; + Single* aj = ptr_aj; - if (k < nrt) - { - // Compute the k-th row transformation and place the k-th super-diagonal in e[k]. - // Compute 2-norm without under/overflow. - e[k] = 0; - for (int i = k + 1; i < n; i++) - e[k] = Accord.Math.Tools.Hypotenuse(e[k], e[i]); + for (int i = k; i < m; i++) + { + t += (*ak) * (*aj); + ak += n; aj += n; + } - if (e[k] != 0) - { - if (e[k + 1] < 0) - e[k] = -e[k]; + t = -t / *ptr_ak; + ak = ptr_ak; + aj = ptr_aj; - for (int i = k + 1; i < n; i++) - e[i] /= e[k]; + for (int i = k; i < m; i++) + { + *aj += t * (*ak); + ak += n; aj += n; + } + } - e[k + 1] += 1; + // Place the k-th row of A into e for the subsequent calculation of the row transformation. + e[j] = *ptr_aj; } - e[k] = -e[k]; - if ((k + 1 < m) & (e[k] != 0)) - { - // Apply the transformation. - for (int i = k + 1; i < m; i++) - work[i] = 0; - - int k1 = k + 1; - for (int i = k1; i < m; i++) - { - Single* ai = A + (i * n) + k1; - for (int j = k1; j < n; j++, ai++) - work[i] += e[j] * (*ai); - } - for (int j = k1; j < n; j++) - { - Single t = -e[j] / e[k1]; - Single* aj = A + (k1 * n) + j; - for (int i = k1; i < m; i++, aj += n) - *aj += t * work[i]; - } + if (wantu & (k < nct)) + { + // Place the transformation in U for subsequent back + // multiplication. + for (int i = k; i < m; i++) + u[i, k] = a[i, k]; } - if (wantv) + if (k < nrt) { - // Place the transformation in V for subsequent back multiplication. + // Compute the k-th row transformation and place the k-th super-diagonal in e[k]. + // Compute 2-norm without under/overflow. + e[k] = 0; for (int i = k + 1; i < n; i++) - v[i, k] = e[i]; - } - } - } + e[k] = Accord.Math.Tools.Hypotenuse(e[k], e[i]); - // Set up the final bidiagonal matrix or order p. - int p = System.Math.Min(n, m + 1); - if (nct < n) s[nct] = a[nct, nct]; - if (m < p) s[p - 1] = 0; - if (nrt + 1 < p) e[nrt] = a[nrt, p - 1]; - e[p - 1] = 0; + if (e[k] != 0) + { + if (e[k + 1] < 0) + e[k] = -e[k]; - // If required, generate U. - if (wantu) - { - for (int j = nct; j < nu; j++) - { - for (int i = 0; i < m; i++) - u[i, j] = 0; - u[j, j] = 1; - } + for (int i = k + 1; i < n; i++) + e[i] /= e[k]; - for (int k = nct - 1; k >= 0; k--) - { - if (s[k] != 0) - { - Single* ptr_uk = U + k * nu + k; // u[k,k] + e[k + 1] += 1; + } - Single* uk, uj; - for (int j = k + 1; j < nu; j++) + e[k] = -e[k]; + if ((k + 1 < m) & (e[k] != 0)) { - Single* ptr_uj = U + k * nu + j; // u[k,j] + // Apply the transformation. + for (int i = k + 1; i < m; i++) + work[i] = 0; - Single t = 0; - uk = ptr_uk; - uj = ptr_uj; - - for (int i = k; i < m; i++) + int k1 = k + 1; + for (int i = k1; i < m; i++) { - t += *uk * *uj; - uk += nu; uj += nu; + Single* ai = A + (i * n) + k1; + for (int j = k1; j < n; j++, ai++) + work[i] += e[j] * (*ai); } - t = -t / *ptr_uk; - - uk = ptr_uk; uj = ptr_uj; - for (int i = k; i < m; i++) + for (int j = k1; j < n; j++) { - *uj += t * (*uk); - uk += nu; uj += nu; + Single t = -e[j] / e[k1]; + Single* aj = A + (k1 * n) + j; + for (int i = k1; i < m; i++, aj += n) + *aj += t * work[i]; } } - uk = ptr_uk; - for (int i = k; i < m; i++) + if (wantv) { - *uk = -(*uk); - uk += nu; + // Place the transformation in V for subsequent back multiplication. + for (int i = k + 1; i < n; i++) + v[i, k] = e[i]; } - - u[k, k] = 1 + u[k, k]; - for (int i = 0; i < k - 1; i++) - u[i, k] = 0; } - else + } + + // Set up the final bidiagonal matrix or order p. + int p = System.Math.Min(n, m + 1); + if (nct < n) s[nct] = a[nct, nct]; + if (m < p) s[p - 1] = 0; + if (nrt + 1 < p) e[nrt] = a[nrt, p - 1]; + e[p - 1] = 0; + + // If required, generate U. + if (wantu) + { + for (int j = nct; j < nu; j++) { for (int i = 0; i < m; i++) - u[i, k] = 0; - u[k, k] = 1; + u[i, j] = 0; + u[j, j] = 1; } - } - } - // If required, generate V. - if (wantv) - { - for (int k = n - 1; k >= 0; k--) - { - if ((k < nrt) & (e[k] != 0)) + for (int k = nct - 1; k >= 0; k--) { - // TODO: The following is a pseudo correction to make SVD - // work on matrices with n > m (less rows than columns). + if (s[k] != 0) + { + Single* ptr_uk = U + k * nu + k; // u[k,k] - // For the proper correction, compute the decomposition of the - // transpose of A and swap the left and right eigenvectors + Single* uk, uj; + for (int j = k + 1; j < nu; j++) + { + Single* ptr_uj = U + k * nu + j; // u[k,j] - // Original line: - // for (int j = k + 1; j < nu; j++) - // Pseudo correction: - // for (int j = k + 1; j < n; j++) + Single t = 0; + uk = ptr_uk; + uj = ptr_uj; - for (int j = k + 1; j < n; j++) // pseudo-correction - { - Single* ptr_vk = V + (k + 1) * n + k; // v[k + 1, k] - Single* ptr_vj = V + (k + 1) * n + j; // v[k + 1, j] + for (int i = k; i < m; i++) + { + t += *uk * *uj; + uk += nu; uj += nu; + } - Single t = 0; - Single* vk = ptr_vk; - Single* vj = ptr_vj; + t = -t / *ptr_uk; - for (int i = k + 1; i < n; i++) - { - t += *vk * *vj; - vk += n; vj += n; + uk = ptr_uk; uj = ptr_uj; + for (int i = k; i < m; i++) + { + *uj += t * (*uk); + uk += nu; uj += nu; + } } - t = -t / *ptr_vk; - - vk = ptr_vk; vj = ptr_vj; - for (int i = k + 1; i < n; i++) + uk = ptr_uk; + for (int i = k; i < m; i++) { - *vj += t * (*vk); - vk += n; vj += n; + *uk = -(*uk); + uk += nu; } + + u[k, k] = 1 + u[k, k]; + for (int i = 0; i < k - 1; i++) + u[i, k] = 0; + } + else + { + for (int i = 0; i < m; i++) + u[i, k] = 0; + u[k, k] = 1; } } - - for (int i = 0; i < n; i++) - v[i, k] = 0; - v[k, k] = 1; } - } - // Main iteration loop for the singular values. - int pp = p - 1; - int iter = 0; - while (p > 0) - { - int k, kase; + // If required, generate V. + if (wantv) + { + for (int k = n - 1; k >= 0; k--) + { + if ((k < nrt) & (e[k] != 0)) + { + // TODO: The following is a pseudo correction to make SVD + // work on matrices with n > m (less rows than columns). + + // For the proper correction, compute the decomposition of the + // transpose of A and swap the left and right eigenvectors - // Here is where a test for too many iterations would go. + // Original line: + // for (int j = k + 1; j < nu; j++) + // Pseudo correction: + // for (int j = k + 1; j < n; j++) - // This section of the program inspects for - // negligible elements in the s and e arrays. On - // completion the variables kase and k are set as follows. + for (int j = k + 1; j < n; j++) // pseudo-correction + { + Single* ptr_vk = V + (k + 1) * n + k; // v[k + 1, k] + Single* ptr_vj = V + (k + 1) * n + j; // v[k + 1, j] - // kase = 1 if s(p) and e[k-1] are negligible and k

= -1; k--) - { - if (k == -1) - break; + for (int i = k + 1; i < n; i++) + { + t += *vk * *vj; + vk += n; vj += n; + } - var alpha = tiny + eps * (System.Math.Abs(s[k]) + System.Math.Abs(s[k + 1])); + t = -t / *ptr_vk; - if (System.Math.Abs(e[k]) <= alpha || Single.IsNaN(e[k])) - { - e[k] = 0; - break; + vk = ptr_vk; vj = ptr_vj; + for (int i = k + 1; i < n; i++) + { + *vj += t * (*vk); + vk += n; vj += n; + } + } + } + + for (int i = 0; i < n; i++) + v[i, k] = 0; + v[k, k] = 1; } } - if (k == p - 2) + // Main iteration loop for the singular values. + int pp = p - 1; + int iter = 0; + while (p > 0) { - kase = 4; - } - else - { - int ks; - for (ks = p - 1; ks >= k; ks--) + int k, kase; + + // Here is where a test for too many iterations would go. + + // This section of the program inspects for + // negligible elements in the s and e arrays. On + // completion the variables kase and k are set as follows. + + // kase = 1 if s(p) and e[k-1] are negligible and k

= -1; k--) { - if (ks == k) + if (k == -1) break; - Single t = (ks != p ? System.Math.Abs(e[ks]) : 0) + - (ks != k + 1 ? System.Math.Abs(e[ks - 1]) : 0); - if (System.Math.Abs(s[ks]) <= tiny + eps * t) + var alpha = tiny + eps * (System.Math.Abs(s[k]) + System.Math.Abs(s[k + 1])); + + if (System.Math.Abs(e[k]) <= alpha || Single.IsNaN(e[k])) { - s[ks] = 0; + e[k] = 0; break; } } - if (ks == k) - kase = 3; - else if (ks == p - 1) - kase = 1; - else + if (k == p - 2) { - kase = 2; - k = ks; + kase = 4; } - } + else + { + int ks; + for (ks = p - 1; ks >= k; ks--) + { + if (ks == k) + break; - k++; + Single t = (ks != p ? System.Math.Abs(e[ks]) : 0) + + (ks != k + 1 ? System.Math.Abs(e[ks - 1]) : 0); + if (System.Math.Abs(s[ks]) <= tiny + eps * t) + { + s[ks] = 0; + break; + } + } - // Perform the task indicated by kase. - switch (kase) - { - // Deflate negligible s(p). - case 1: + if (ks == k) + kase = 3; + else if (ks == p - 1) + kase = 1; + else { - Single f = e[p - 2]; - e[p - 2] = 0; - for (int j = p - 2; j >= k; j--) + kase = 2; + k = ks; + } + } + + k++; + + // Perform the task indicated by kase. + switch (kase) + { + // Deflate negligible s(p). + case 1: { - Single t = Accord.Math.Tools.Hypotenuse(s[j], f); - Single cs = s[j] / t; - Single sn = f / t; - s[j] = t; - if (j != k) + Single f = e[p - 2]; + e[p - 2] = 0; + for (int j = p - 2; j >= k; j--) { - f = -sn * e[j - 1]; - e[j - 1] = cs * e[j - 1]; - } + Single t = Accord.Math.Tools.Hypotenuse(s[j], f); + Single cs = s[j] / t; + Single sn = f / t; + s[j] = t; + if (j != k) + { + f = -sn * e[j - 1]; + e[j - 1] = cs * e[j - 1]; + } - if (wantv) - { - for (int i = 0; i < n; i++) + if (wantv) { - t = cs * v[i, j] + sn * v[i, p - 1]; - v[i, p - 1] = -sn * v[i, j] + cs * v[i, p - 1]; - v[i, j] = t; + for (int i = 0; i < n; i++) + { + t = cs * v[i, j] + sn * v[i, p - 1]; + v[i, p - 1] = -sn * v[i, j] + cs * v[i, p - 1]; + v[i, j] = t; + } } } } - } - break; + break; - // Split at negligible s(k). - case 2: - { - Single f = e[k - 1]; - e[k - 1] = 0; - for (int j = k; j < p; j++) + // Split at negligible s(k). + case 2: { - Single t = Accord.Math.Tools.Hypotenuse(s[j], f); - Single cs = s[j] / t; - Single sn = f / t; - s[j] = t; - f = -sn * e[j]; - e[j] = cs * e[j]; - - if (wantu) + Single f = e[k - 1]; + e[k - 1] = 0; + for (int j = k; j < p; j++) { - for (int i = 0; i < m; i++) + Single t = Accord.Math.Tools.Hypotenuse(s[j], f); + Single cs = s[j] / t; + Single sn = f / t; + s[j] = t; + f = -sn * e[j]; + e[j] = cs * e[j]; + + if (wantu) { - t = cs * u[i, j] + sn * u[i, k - 1]; - u[i, k - 1] = -sn * u[i, j] + cs * u[i, k - 1]; - u[i, j] = t; + for (int i = 0; i < m; i++) + { + t = cs * u[i, j] + sn * u[i, k - 1]; + u[i, k - 1] = -sn * u[i, j] + cs * u[i, k - 1]; + u[i, j] = t; + } } } } - } - break; + break; - // Perform one qr step. - case 3: - { - // Calculate the shift. - Single scale = System.Math.Max(System.Math.Max(System.Math.Max(System.Math.Max(System.Math.Abs(s[p - 1]), System.Math.Abs(s[p - 2])), System.Math.Abs(e[p - 2])), System.Math.Abs(s[k])), System.Math.Abs(e[k])); - Single sp = s[p - 1] / scale; - Single spm1 = s[p - 2] / scale; - Single epm1 = e[p - 2] / scale; - Single sk = s[k] / scale; - Single ek = e[k] / scale; - Single b = ((spm1 + sp) * (spm1 - sp) + epm1 * epm1) / 2; - Single c = (sp * epm1) * (sp * epm1); - double shift = 0; - - if ((b != 0) | (c != 0)) + // Perform one qr step. + case 3: { - if (b < 0) - shift = -System.Math.Sqrt(b * b + c); - else - shift = System.Math.Sqrt(b * b + c); + // Calculate the shift. + Single scale = System.Math.Max(System.Math.Max(System.Math.Max(System.Math.Max(System.Math.Abs(s[p - 1]), System.Math.Abs(s[p - 2])), System.Math.Abs(e[p - 2])), System.Math.Abs(s[k])), System.Math.Abs(e[k])); + Single sp = s[p - 1] / scale; + Single spm1 = s[p - 2] / scale; + Single epm1 = e[p - 2] / scale; + Single sk = s[k] / scale; + Single ek = e[k] / scale; + Single b = ((spm1 + sp) * (spm1 - sp) + epm1 * epm1) / 2; + Single c = (sp * epm1) * (sp * epm1); + double shift = 0; + + if ((b != 0) | (c != 0)) + { + if (b < 0) + shift = -System.Math.Sqrt(b * b + c); + else + shift = System.Math.Sqrt(b * b + c); - shift = c / (b + shift); - } + shift = c / (b + shift); + } - Single f = (sk + sp) * (sk - sp) + (Single)shift; - Single g = sk * ek; + Single f = (sk + sp) * (sk - sp) + (Single)shift; + Single g = sk * ek; - // Chase zeros. - for (int j = k; j < p - 1; j++) - { - Single t = Accord.Math.Tools.Hypotenuse(f, g); - Single cs = f / t; - Single sn = g / t; - if (j != k) e[j - 1] = t; - f = cs * s[j] + sn * e[j]; - e[j] = cs * e[j] - sn * s[j]; - g = sn * s[j + 1]; - s[j + 1] = cs * s[j + 1]; - - if (wantv) + // Chase zeros. + for (int j = k; j < p - 1; j++) { - unsafe + Single t = Accord.Math.Tools.Hypotenuse(f, g); + Single cs = f / t; + Single sn = g / t; + if (j != k) e[j - 1] = t; + f = cs * s[j] + sn * e[j]; + e[j] = cs * e[j] - sn * s[j]; + g = sn * s[j + 1]; + s[j + 1] = cs * s[j + 1]; + + if (wantv) { - fixed (Single* ptr_vj = &v[0, j]) + unsafe { - Single* vj = ptr_vj; - Single* vj1 = ptr_vj + 1; - - for (int i = 0; i < n; i++) + fixed (Single* ptr_vj = &v[0, j]) { - /*t = cs * v[i, j] + sn * v[i, j + 1]; - v[i, j + 1] = -sn * v[i, j] + cs * v[i, j + 1]; - v[i, j] = t;*/ + Single* vj = ptr_vj; + Single* vj1 = ptr_vj + 1; + + for (int i = 0; i < n; i++) + { + /*t = cs * v[i, j] + sn * v[i, j + 1]; + v[i, j + 1] = -sn * v[i, j] + cs * v[i, j + 1]; + v[i, j] = t;*/ - Single vij = *vj; - Single vij1 = *vj1; + Single vij = *vj; + Single vij1 = *vj1; - t = cs * vij + sn * vij1; - *vj1 = -sn * vij + cs * vij1; - *vj = t; + t = cs * vij + sn * vij1; + *vj1 = -sn * vij + cs * vij1; + *vj = t; - vj += n; vj1 += n; + vj += n; vj1 += n; + } } } } - } - t = Accord.Math.Tools.Hypotenuse(f, g); - cs = f / t; - sn = g / t; - s[j] = t; - f = cs * e[j] + sn * s[j + 1]; - s[j + 1] = -sn * e[j] + cs * s[j + 1]; - g = sn * e[j + 1]; - e[j + 1] = cs * e[j + 1]; + t = Accord.Math.Tools.Hypotenuse(f, g); + cs = f / t; + sn = g / t; + s[j] = t; + f = cs * e[j] + sn * s[j + 1]; + s[j + 1] = -sn * e[j] + cs * s[j + 1]; + g = sn * e[j + 1]; + e[j + 1] = cs * e[j + 1]; - if (wantu && (j < m - 1)) - { - fixed (Single* ptr_uj = &u[0, j]) + if (wantu && (j < m - 1)) { - Single* uj = ptr_uj; - Single* uj1 = ptr_uj + 1; - - for (int i = 0; i < m; i++) + fixed (Single* ptr_uj = &u[0, j]) { - /* t = cs * u[i, j] + sn * u[i, j + 1]; - u[i, j + 1] = -sn * u[i, j] + cs * u[i, j + 1]; - u[i, j] = t;*/ + Single* uj = ptr_uj; + Single* uj1 = ptr_uj + 1; + + for (int i = 0; i < m; i++) + { + /* t = cs * u[i, j] + sn * u[i, j + 1]; + u[i, j + 1] = -sn * u[i, j] + cs * u[i, j + 1]; + u[i, j] = t;*/ - Single uij = *uj; - Single uij1 = *uj1; + Single uij = *uj; + Single uij1 = *uj1; - t = cs * uij + sn * uij1; - *uj1 = -sn * uij + cs * uij1; - *uj = t; + t = cs * uij + sn * uij1; + *uj1 = -sn * uij + cs * uij1; + *uj = t; - uj += nu; uj1 += nu; + uj += nu; uj1 += nu; + } } } + } + e[p - 2] = f; + iter = iter + 1; } + break; - e[p - 2] = f; - iter = iter + 1; - } - break; - - // Convergence. - case 4: - { - // Make the singular values positive. - if (s[k] <= 0) + // Convergence. + case 4: { - s[k] = (s[k] < 0 ? -s[k] : 0); - if (wantv) + // Make the singular values positive. + if (s[k] <= 0) { - for (int i = 0; i <= pp; i++) - v[i, k] = -v[i, k]; + s[k] = (s[k] < 0 ? -s[k] : 0); + if (wantv) + { + for (int i = 0; i <= pp; i++) + v[i, k] = -v[i, k]; + } } - } - // Order the singular values. - while (k < pp) - { - if (s[k] >= s[k + 1]) - break; + // Order the singular values. + while (k < pp) + { + if (s[k] >= s[k + 1]) + break; - Single t = s[k]; - s[k] = s[k + 1]; - s[k + 1] = t; + Single t = s[k]; + s[k] = s[k + 1]; + s[k + 1] = t; - int ti = si[k]; - si[k] = si[k + 1]; - si[k + 1] = ti; + int ti = si[k]; + si[k] = si[k + 1]; + si[k + 1] = ti; - if (wantv && (k < n - 1)) - { - for (int i = 0; i < n; i++) + if (wantv && (k < n - 1)) { - t = v[i, k + 1]; - v[i, k + 1] = v[i, k]; - v[i, k] = t; + for (int i = 0; i < n; i++) + { + t = v[i, k + 1]; + v[i, k + 1] = v[i, k]; + v[i, k] = t; + } } - } - if (wantu && (k < m - 1)) - { - for (int i = 0; i < m; i++) + if (wantu && (k < m - 1)) { - t = u[i, k + 1]; - u[i, k + 1] = u[i, k]; - u[i, k] = t; + for (int i = 0; i < m; i++) + { + t = u[i, k + 1]; + u[i, k + 1] = u[i, k]; + u[i, k] = t; + } } + + k++; } - k++; + iter = 0; + p--; } - - iter = 0; - p--; - } - break; + break; + } } - } + } } // If we are violating JAMA's assumption about diff --git a/Sources/Accord.Math/Functions/Gabor.cs b/Sources/Accord.Math/Functions/Gabor.cs index fcaf999e0..5d2c04599 100644 --- a/Sources/Accord.Math/Functions/Gabor.cs +++ b/Sources/Accord.Math/Functions/Gabor.cs @@ -1,239 +1,243 @@ -// Accord Math Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © Diego Catalano, 2013 -// diego.catalano at live.com -// -// Copyright © César Souza, 2009-2015 -// 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.Math -{ - using System; - using AForge.Math; - - ///

- /// Gabor kernel types. - /// - /// - public enum GaborKernelKind - { - - /// - /// Creates kernel based on the real part of the Gabor function. - /// - /// - Real, - - /// - /// Creates a kernel based on the imaginary part of the Gabor function. - /// - /// - Imaginary, - - /// - /// Creates a kernel based on the Magnitude of the Gabor function. - /// - /// - Magnitude, - - /// - /// Creates a kernel based on the Squared Magnitude of the Gabor function. - /// - /// - SquaredMagnitude - }; - - /// - /// Gabor functions. - /// - /// - /// - /// This class has been contributed by Diego Catalano, author of the Catalano - /// Framework, a native port of AForge.NET and Accord.NET for Java and Android. - /// - /// - public static class Gabor - { - - /// - /// 1-D Gabor function. - /// - /// - public static double Function1D(double x, double mean, double amplitude, - double position, double width, double phase, double frequency) - { - double a = (x - position) * (x - position); - double b = (2 * width) * (2 * width); - - double envelope = mean + amplitude * Math.Exp(-a / b); - double carry = Math.Cos(2 * Math.PI * frequency * (x - position) + phase); - - return envelope * carry; - } - - /// - /// 2-D Gabor function. - /// - /// - public static Complex Function2D(int x, int y, double lambda, double theta, - double psi, double sigma, double gamma) - { - double X = +x * Math.Cos(theta) + y * Math.Sin(theta); - double Y = -x * Math.Sin(theta) + y * Math.Cos(theta); - - double envelope = Math.Exp(-((X * X + gamma * gamma * Y * Y) / (2 * sigma * sigma))); - double real = Math.Cos(2 * Math.PI * (X / lambda) + psi); - double imaginary = Math.Sin(2 * Math.PI * (X / lambda) + psi); - - return new Complex(envelope * real, envelope * imaginary); - } - - /// - /// Real part of the 2-D Gabor function. - /// - /// - public static double RealFunction2D(int x, int y, double lambda, double theta, - double psi, double sigma, double gamma) - { - double X = +x * Math.Cos(theta) + y * Math.Sin(theta); - double Y = -x * Math.Sin(theta) + y * Math.Cos(theta); - - double envelope = Math.Exp(-((X * X + gamma * gamma * Y * Y) / (2 * sigma * sigma))); - double carrier = Math.Cos(2 * Math.PI * (X / lambda) + psi); - - return envelope * carrier; - } - - /// - /// Imaginary part of the 2-D Gabor function. - /// - /// - public static double ImaginaryFunction2D(int x, int y, double lambda, double theta, - double psi, double sigma, double gamma) - { - double X = +x * Math.Cos(theta) + y * Math.Sin(theta); - double Y = -x * Math.Sin(theta) + y * Math.Cos(theta); - - double envelope = Math.Exp(-((X * X + gamma * gamma * Y * Y) / (2 * sigma * sigma))); - double carrier = Math.Sin(2 * Math.PI * (X / lambda) + psi); - - return envelope * carrier; - } - - /// - /// Computes the 2-D Gabor kernel. - /// - /// - public static double[,] Kernel2D(double lambda, double theta, double psi, - double sigma, double gamma) - { - return Kernel2D(3, lambda, theta, psi, sigma, gamma, false, GaborKernelKind.Real); - } - - /// - /// Computes the 2-D Gabor kernel. - /// - /// - public static double[,] Kernel2D(double lambda, double theta, double psi, - double sigma, double gamma, bool normalized) - { - return Kernel2D(3, lambda, theta, psi, sigma, gamma, normalized, GaborKernelKind.Imaginary); - } - - /// - /// Computes the 2-D Gabor kernel. - /// - /// - public static double[,] Kernel2D(int size, double lambda, double theta, double psi, - double sigma, double gamma, bool normalized) - { - return Kernel2D(size, lambda, theta, psi, sigma, - gamma, normalized, GaborKernelKind.Imaginary); - } - - - /// - /// Computes the 2-D Gabor kernel. - /// - /// - public static double[,] Kernel2D(int size, double lambda, double theta, - double psi, double sigma, double gamma, bool normalized, GaborKernelKind function) - { - double sigmaX = sigma; - double sigmaY = sigma / gamma; - - double a = Math.Max( - Math.Abs(size * sigmaX * Math.Cos(theta)), - Math.Abs(size * sigmaY * Math.Sin(theta))); - int xMax = (int)Math.Ceiling(Math.Max(1, a)); - - double b = Math.Max( - Math.Abs(size * sigmaX * Math.Sin(theta)), - Math.Abs(size * sigmaY * Math.Cos(theta))); - int yMax = (int)Math.Ceiling(Math.Max(1, b)); - - int[] xValues = Matrix.Vector(-xMax, xMax, increment: 1); - int[] yValues = Matrix.Vector(-yMax, yMax, increment: 1); - - System.Diagnostics.Debug.Assert(xValues.Length == (2 * xMax + 1)); - System.Diagnostics.Debug.Assert(yValues.Length == (2 * yMax + 1)); - - double[,] kernel = new double[xValues.Length, yValues.Length]; - - double sum = 0; - - switch (function) - { - case GaborKernelKind.Real: - for (int i = 0; i < xValues.Length; i++) - for (int j = 0; j < yValues.Length; j++) - sum += kernel[i, j] = Gabor.RealFunction2D( - xValues[i], yValues[j], lambda, theta, psi, sigma, gamma); - break; - - case GaborKernelKind.Imaginary: - for (int i = 0; i < xValues.Length; i++) - for (int j = 0; j < yValues.Length; j++) - sum += kernel[i, j] = Gabor.ImaginaryFunction2D( - xValues[i], yValues[j], lambda, theta, psi, sigma, gamma); - break; - - case GaborKernelKind.Magnitude: - for (int i = 0; i < xValues.Length; i++) - for (int j = 0; j < yValues.Length; j++) - sum += kernel[i, j] = Gabor.Function2D( - xValues[i], yValues[j], lambda, theta, psi, sigma, gamma).Magnitude; - break; - - case GaborKernelKind.SquaredMagnitude: - for (int i = 0; i < xValues.Length; i++) - for (int j = 0; j < yValues.Length; j++) - sum += kernel[i, j] = Gabor.Function2D( - xValues[i], yValues[j], lambda, theta, psi, sigma, gamma).SquaredMagnitude; - break; - } - - if (normalized) - kernel.Divide(sum, inPlace: true); - - return kernel; - } - } -} +// Accord Math Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © Diego Catalano, 2013 +// diego.catalano at live.com +// +// Copyright © César Souza, 2009-2015 +// 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.Math +{ + using System; + using AForge.Math; + using System.Numerics; + + /// + /// Gabor kernel types. + /// + /// + public enum GaborKernelKind + { + + /// + /// Creates kernel based on the real part of the Gabor function. + /// + /// + Real, + + /// + /// Creates a kernel based on the imaginary part of the Gabor function. + /// + /// + Imaginary, + + /// + /// Creates a kernel based on the Magnitude of the Gabor function. + /// + /// + Magnitude, + + /// + /// Creates a kernel based on the Squared Magnitude of the Gabor function. + /// + /// + SquaredMagnitude + }; + + /// + /// Gabor functions. + /// + /// + /// + /// This class has been contributed by Diego Catalano, author of the Catalano + /// Framework, a native port of AForge.NET and Accord.NET for Java and Android. + /// + /// + public static class Gabor + { + + /// + /// 1-D Gabor function. + /// + /// + public static double Function1D(double x, double mean, double amplitude, + double position, double width, double phase, double frequency) + { + double a = (x - position) * (x - position); + double b = (2 * width) * (2 * width); + + double envelope = mean + amplitude * Math.Exp(-a / b); + double carry = Math.Cos(2 * Math.PI * frequency * (x - position) + phase); + + return envelope * carry; + } + + /// + /// 2-D Gabor function. + /// + /// + public static Complex Function2D(int x, int y, double lambda, double theta, + double psi, double sigma, double gamma) + { + double X = +x * Math.Cos(theta) + y * Math.Sin(theta); + double Y = -x * Math.Sin(theta) + y * Math.Cos(theta); + + double envelope = Math.Exp(-((X * X + gamma * gamma * Y * Y) / (2 * sigma * sigma))); + double real = Math.Cos(2 * Math.PI * (X / lambda) + psi); + double imaginary = Math.Sin(2 * Math.PI * (X / lambda) + psi); + + return new Complex(envelope * real, envelope * imaginary); + } + + /// + /// Real part of the 2-D Gabor function. + /// + /// + public static double RealFunction2D(int x, int y, double lambda, double theta, + double psi, double sigma, double gamma) + { + double X = +x * Math.Cos(theta) + y * Math.Sin(theta); + double Y = -x * Math.Sin(theta) + y * Math.Cos(theta); + + double envelope = Math.Exp(-((X * X + gamma * gamma * Y * Y) / (2 * sigma * sigma))); + double carrier = Math.Cos(2 * Math.PI * (X / lambda) + psi); + + return envelope * carrier; + } + + /// + /// Imaginary part of the 2-D Gabor function. + /// + /// + public static double ImaginaryFunction2D(int x, int y, double lambda, double theta, + double psi, double sigma, double gamma) + { + double X = +x * Math.Cos(theta) + y * Math.Sin(theta); + double Y = -x * Math.Sin(theta) + y * Math.Cos(theta); + + double envelope = Math.Exp(-((X * X + gamma * gamma * Y * Y) / (2 * sigma * sigma))); + double carrier = Math.Sin(2 * Math.PI * (X / lambda) + psi); + + return envelope * carrier; + } + + /// + /// Computes the 2-D Gabor kernel. + /// + /// + public static double[,] Kernel2D(double lambda, double theta, double psi, + double sigma, double gamma) + { + return Kernel2D(3, lambda, theta, psi, sigma, gamma, false, GaborKernelKind.Real); + } + + /// + /// Computes the 2-D Gabor kernel. + /// + /// + public static double[,] Kernel2D(double lambda, double theta, double psi, + double sigma, double gamma, bool normalized) + { + return Kernel2D(3, lambda, theta, psi, sigma, gamma, normalized, GaborKernelKind.Imaginary); + } + + /// + /// Computes the 2-D Gabor kernel. + /// + /// + public static double[,] Kernel2D(int size, double lambda, double theta, double psi, + double sigma, double gamma, bool normalized) + { + return Kernel2D(size, lambda, theta, psi, sigma, + gamma, normalized, GaborKernelKind.Imaginary); + } + + + /// + /// Computes the 2-D Gabor kernel. + /// + /// + public static double[,] Kernel2D(int size, double lambda, double theta, + double psi, double sigma, double gamma, bool normalized, GaborKernelKind function) + { + double sigmaX = sigma; + double sigmaY = sigma / gamma; + + double a = Math.Max( + Math.Abs(size * sigmaX * Math.Cos(theta)), + Math.Abs(size * sigmaY * Math.Sin(theta))); + int xMax = (int)Math.Ceiling(Math.Max(1, a)); + + double b = Math.Max( + Math.Abs(size * sigmaX * Math.Sin(theta)), + Math.Abs(size * sigmaY * Math.Cos(theta))); + int yMax = (int)Math.Ceiling(Math.Max(1, b)); + + int[] xValues = Matrix.Vector(-xMax, xMax, increment: 1); + int[] yValues = Matrix.Vector(-yMax, yMax, increment: 1); + + System.Diagnostics.Debug.Assert(xValues.Length == (2 * xMax + 1)); + System.Diagnostics.Debug.Assert(yValues.Length == (2 * yMax + 1)); + + double[,] kernel = new double[xValues.Length, yValues.Length]; + + double sum = 0; + + switch (function) + { + case GaborKernelKind.Real: + for (int i = 0; i < xValues.Length; i++) + for (int j = 0; j < yValues.Length; j++) + sum += kernel[i, j] = Gabor.RealFunction2D( + xValues[i], yValues[j], lambda, theta, psi, sigma, gamma); + break; + + case GaborKernelKind.Imaginary: + for (int i = 0; i < xValues.Length; i++) + for (int j = 0; j < yValues.Length; j++) + sum += kernel[i, j] = Gabor.ImaginaryFunction2D( + xValues[i], yValues[j], lambda, theta, psi, sigma, gamma); + break; + + case GaborKernelKind.Magnitude: + for (int i = 0; i < xValues.Length; i++) + for (int j = 0; j < yValues.Length; j++) + sum += kernel[i, j] = Gabor.Function2D( + xValues[i], yValues[j], lambda, theta, psi, sigma, gamma).Magnitude; + break; + + case GaborKernelKind.SquaredMagnitude: + for (int i = 0; i < xValues.Length; i++) + for (int j = 0; j < yValues.Length; j++) + { + double v = Gabor.Function2D( + xValues[i], yValues[j], lambda, theta, psi, sigma, gamma).Magnitude; + sum += kernel[i, j] = v * v; + } + break; + } + + if (normalized) + kernel.Divide(sum, inPlace: true); + + return kernel; + } + } +} diff --git a/Sources/Accord.Math/Geometry/DiscreteCurveEvolution.cs b/Sources/Accord.Math/Geometry/DiscreteCurveEvolution.cs index ce08dd048..cee947d6f 100644 --- a/Sources/Accord.Math/Geometry/DiscreteCurveEvolution.cs +++ b/Sources/Accord.Math/Geometry/DiscreteCurveEvolution.cs @@ -39,7 +39,8 @@ namespace Accord.Math.Geometry using Accord.Math; using AForge; using AForge.Math; - using AForge.Math.Geometry; + using AForge.Math.Geometry; + using System.Numerics; /// /// Discrete Curve Evolution. @@ -146,7 +147,7 @@ public List OptimizeShape(List shape) var newShape = new List(complex.Count); for (int i = 0; i < complex.Count; i++) - newShape.Add(new IntPoint((int)complex[i].Re, (int)complex[i].Im)); + newShape.Add(new IntPoint((int)complex[i].Real, (int)complex[i].Imaginary)); return newShape; } diff --git a/Sources/Accord.Math/Indices.cs b/Sources/Accord.Math/Indices.cs index 4d551041d..033fd6754 100644 --- a/Sources/Accord.Math/Indices.cs +++ b/Sources/Accord.Math/Indices.cs @@ -339,8 +339,6 @@ public static T[] Range(int from, int to) return vector; } - - static T cast(this object value) { return (T)Convert.ChangeType(value, typeof(T)); diff --git a/Sources/Accord.Math/Matrix/Matrix.Algebra.cs b/Sources/Accord.Math/Matrix/Matrix.Algebra.cs index 0a3d05367..95703dcac 100644 --- a/Sources/Accord.Math/Matrix/Matrix.Algebra.cs +++ b/Sources/Accord.Math/Matrix/Matrix.Algebra.cs @@ -349,7 +349,7 @@ public static double[][] Multiply(this float[][] a, double[][] b) /// The matrix R to store the product R = A*B /// of the given matrices A and B. /// - public static unsafe void Multiply(this double[,] a, double[,] b, double[,] result) + public static void Multiply(this double[,] a, double[,] b, double[,] result) { // TODO: enable argument checking // if (a.GetLength(1) != b.GetLength(0)) @@ -359,22 +359,24 @@ public static unsafe void Multiply(this double[,] a, double[,] b, double[,] resu int m = result.GetLength(0); //a.GetLength(0); int p = result.GetLength(1); //b.GetLength(1); - - fixed (double* ptrA = a) + unsafe { - double[] Bcolj = new double[n]; - for (int j = 0; j < p; j++) + fixed (double* ptrA = a) { - for (int k = 0; k < Bcolj.Length; k++) - Bcolj[k] = b[k, j]; - - double* Arowi = ptrA; - for (int i = 0; i < m; i++) + double[] Bcolj = new double[n]; + for (int j = 0; j < p; j++) { - double s = 0; for (int k = 0; k < Bcolj.Length; k++) - s += *(Arowi++) * Bcolj[k]; - result[i, j] = s; + Bcolj[k] = b[k, j]; + + double* Arowi = ptrA; + for (int i = 0; i < m; i++) + { + double s = 0; + for (int k = 0; k < Bcolj.Length; k++) + s += *(Arowi++) * Bcolj[k]; + result[i, j] = s; + } } } } @@ -430,7 +432,7 @@ public static void Multiply(this double[][] a, double[][] b, double[][] result) /// The matrix R to store the product R = A*B /// of the given matrices A and B. /// - public static unsafe void Multiply(this double[,] a, double[,] b, double[][] result) + public static void Multiply(this double[,] a, double[,] b, double[][] result) { // TODO: enable argument checking // if (a.GetLength(1) != b.GetLength(0)) @@ -440,22 +442,24 @@ public static unsafe void Multiply(this double[,] a, double[,] b, double[][] res int m = a.GetLength(0); int p = b.GetLength(1); - - fixed (double* ptrA = a) + unsafe { - double[] Bcolj = new double[n]; - for (int j = 0; j < p; j++) + fixed (double* ptrA = a) { - for (int k = 0; k < Bcolj.Length; k++) - Bcolj[k] = b[k, j]; - - double* Arowi = ptrA; - for (int i = 0; i < m; i++) + double[] Bcolj = new double[n]; + for (int j = 0; j < p; j++) { - double s = 0; for (int k = 0; k < Bcolj.Length; k++) - s += *(Arowi++) * Bcolj[k]; - result[i][j] = s; + Bcolj[k] = b[k, j]; + + double* Arowi = ptrA; + for (int i = 0; i < m; i++) + { + double s = 0; + for (int k = 0; k < Bcolj.Length; k++) + s += *(Arowi++) * Bcolj[k]; + result[i][j] = s; + } } } } @@ -551,27 +555,30 @@ public static void Multiply(this float[][] a, double[][] b, double[][] result) /// The matrix R to store the product R = A*B /// of the given matrices A and B. /// - public static unsafe void Multiply(this float[,] a, float[,] b, float[,] result) + public static void Multiply(this float[,] a, float[,] b, float[,] result) { int acols = a.GetLength(1); int arows = a.GetLength(0); int bcols = b.GetLength(1); - fixed (float* ptrA = a) + unsafe { - float[] Bcolj = new float[acols]; - for (int j = 0; j < bcols; j++) + fixed (float* ptrA = a) { - for (int k = 0; k < acols; k++) - Bcolj[k] = b[k, j]; - - float* Arowi = ptrA; - for (int i = 0; i < arows; i++) + float[] Bcolj = new float[acols]; + for (int j = 0; j < bcols; j++) { - float s = 0; for (int k = 0; k < acols; k++) - s += *(Arowi++) * Bcolj[k]; - result[i, j] = s; + Bcolj[k] = b[k, j]; + + float* Arowi = ptrA; + for (int i = 0; i < arows; i++) + { + float s = 0; + for (int k = 0; k < acols; k++) + s += *(Arowi++) * Bcolj[k]; + result[i, j] = s; + } } } } @@ -618,29 +625,32 @@ public static unsafe void Multiply(this float[,] a, float[,] b, float[,] result) /// The matrix R to store the product R = A*B' /// of the given matrices A and B. /// - public static unsafe void MultiplyByTranspose(this double[,] a, double[,] b, double[,] result) + public static void MultiplyByTranspose(this double[,] a, double[,] b, double[,] result) { int n = a.GetLength(1); int m = a.GetLength(0); int p = b.GetLength(0); - fixed (double* ptrA = a) - fixed (double* ptrB = b) - fixed (double* ptrR = result) + unsafe { - double* rc = ptrR; - - for (int i = 0; i < m; i++) + fixed (double* ptrA = a) + fixed (double* ptrB = b) + fixed (double* ptrR = result) { - double* bColj = ptrB; - for (int j = 0; j < p; j++) + double* rc = ptrR; + + for (int i = 0; i < m; i++) { - double* aColi = ptrA + n * i; + double* bColj = ptrB; + for (int j = 0; j < p; j++) + { + double* aColi = ptrA + n * i; - double s = 0; - for (int k = 0; k < n; k++) - s += *(aColi++) * *(bColj++); - *(rc++) = s; + double s = 0; + for (int k = 0; k < n; k++) + s += *(aColi++) * *(bColj++); + *(rc++) = s; + } } } } @@ -656,29 +666,32 @@ public static unsafe void MultiplyByTranspose(this double[,] a, double[,] b, dou /// The matrix R to store the product R = A*B' /// of the given matrices A and B. /// - public static unsafe void MultiplyByTranspose(this float[,] a, float[,] b, float[,] result) + public static void MultiplyByTranspose(this float[,] a, float[,] b, float[,] result) { int n = a.GetLength(1); int m = a.GetLength(0); int p = b.GetLength(0); - fixed (float* ptrA = a) - fixed (float* ptrB = b) - fixed (float* ptrR = result) + unsafe { - float* rc = ptrR; - - for (int i = 0; i < m; i++) + fixed (float* ptrA = a) + fixed (float* ptrB = b) + fixed (float* ptrR = result) { - float* bColj = ptrB; - for (int j = 0; j < p; j++) + float* rc = ptrR; + + for (int i = 0; i < m; i++) { - float* aColi = ptrA + n * i; + float* bColj = ptrB; + for (int j = 0; j < p; j++) + { + float* aColi = ptrA + n * i; - float s = 0; - for (int k = 0; k < n; k++) - s += *(aColi++) * *(bColj++); - *(rc++) = s; + float s = 0; + for (int k = 0; k < n; k++) + s += *(aColi++) * *(bColj++); + *(rc++) = s; + } } } } @@ -731,7 +744,7 @@ public static double[][] TransposeAndMultiply(this double[][] a, double[][] b) /// The matrix R to store the product R = A'*B /// of the given matrices A and B. /// - public static unsafe void TransposeAndMultiply(this double[,] a, double[,] b, double[,] result) + public static void TransposeAndMultiply(this double[,] a, double[,] b, double[,] result) { if (a == null) throw new ArgumentNullException("a"); if (b == null) throw new ArgumentNullException("b"); @@ -770,7 +783,7 @@ public static unsafe void TransposeAndMultiply(this double[,] a, double[,] b, do /// The matrix R to store the product R = A'*B /// of the given matrices A and B. /// - public static unsafe void TransposeAndMultiply(this double[][] a, double[][] b, double[][] result) + public static void TransposeAndMultiply(this double[][] a, double[][] b, double[][] result) { if (a == null) throw new ArgumentNullException("a"); if (b == null) throw new ArgumentNullException("b"); @@ -825,7 +838,7 @@ public static double[] TransposeAndMultiply(this double[,] a, double[] b) /// The vector r to store the product r = A'*b /// of the given matrix A and vector b. /// - public static unsafe void TransposeAndMultiply(this double[,] a, double[] b, double[] result) + public static void TransposeAndMultiply(this double[,] a, double[] b, double[] result) { if (a == null) throw new ArgumentNullException("a"); if (b == null) throw new ArgumentNullException("b"); @@ -866,7 +879,7 @@ public static unsafe void TransposeAndMultiply(this double[,] a, double[] b, dou /// The matrix R to store the product R = A*B /// of the given matrices A and B. /// - public static unsafe void TransposeAndMultiplyByDiagonal(this double[,] a, double[] b, double[,] result) + public static void TransposeAndMultiplyByDiagonal(this double[,] a, double[] b, double[,] result) { if (a.GetLength(0) != b.Length) throw new ArgumentException("Matrix dimensions must match."); @@ -939,7 +952,7 @@ public static float[][] MultiplyByDiagonal(this float[][] a, float[] b) /// The matrix R to store the product R = A*B /// of the given matrices A and B. /// - public static unsafe void MultiplyByDiagonal(this double[,] a, double[] b, double[,] result) + public static void MultiplyByDiagonal(this double[,] a, double[] b, double[,] result) { if (a.GetLength(1) != b.Length) throw new ArgumentException("Matrix dimensions must match."); @@ -947,13 +960,16 @@ public static unsafe void MultiplyByDiagonal(this double[,] a, double[] b, doubl int rows = a.GetLength(0); - fixed (double* ptrA = a, ptrR = result) + unsafe { - double* A = ptrA; - double* R = ptrR; - for (int i = 0; i < rows; i++) - for (int j = 0; j < b.Length; j++) - *R++ = *A++ * b[j]; + fixed (double* ptrA = a, ptrR = result) + { + double* A = ptrA; + double* R = ptrR; + for (int i = 0; i < rows; i++) + for (int j = 0; j < b.Length; j++) + *R++ = *A++ * b[j]; + } } } @@ -966,7 +982,7 @@ public static unsafe void MultiplyByDiagonal(this double[,] a, double[] b, doubl /// The matrix R to store the product R = A*B /// of the given matrices A and B. /// - public static unsafe void MultiplyByDiagonal(this double[][] a, double[] b, double[][] result) + public static void MultiplyByDiagonal(this double[][] a, double[] b, double[][] result) { int rows = a.Length; @@ -984,7 +1000,7 @@ public static unsafe void MultiplyByDiagonal(this double[][] a, double[] b, doub /// The matrix R to store the product R = A*B /// of the given matrices A and B. /// - public static unsafe void MultiplyByDiagonal(this float[][] a, float[] b, float[][] result) + public static void MultiplyByDiagonal(this float[][] a, float[] b, float[][] result) { int rows = a.Length; @@ -1017,7 +1033,7 @@ public static unsafe void MultiplyByDiagonal(this float[][] a, float[] b, float[ /// The matrix R to store the product R = A*B /// of the given matrices A and B. /// - public static unsafe void MultiplyByDiagonal(this float[,] a, float[] b, float[,] result) + public static void MultiplyByDiagonal(this float[,] a, float[] b, float[,] result) { if (a.GetLength(1) != b.Length) throw new ArgumentException("Matrix dimensions must match."); @@ -1025,13 +1041,16 @@ public static unsafe void MultiplyByDiagonal(this float[,] a, float[] b, float[, int rows = a.GetLength(0); - fixed (float* ptrA = a, ptrR = result) + unsafe { - float* A = ptrA; - float* R = ptrR; - for (int i = 0; i < rows; i++) - for (int j = 0; j < b.Length; j++) - *R++ = *A++ * b[j]; + fixed (float* ptrA = a, ptrR = result) + { + float* A = ptrA; + float* R = ptrR; + for (int i = 0; i < rows; i++) + for (int j = 0; j < b.Length; j++) + *R++ = *A++ * b[j]; + } } } @@ -1059,7 +1078,7 @@ public static unsafe void MultiplyByDiagonal(this float[,] a, float[] b, float[, /// The matrix R to store the product R = A*B /// of the given matrices A and B. /// - public static unsafe void DivideByDiagonal(this double[,] a, double[] b, double[,] result) + public static void DivideByDiagonal(this double[,] a, double[] b, double[,] result) { if (a.GetLength(1) != b.Length) throw new ArgumentException("Matrix dimensions must match."); @@ -1067,13 +1086,16 @@ public static unsafe void DivideByDiagonal(this double[,] a, double[] b, double[ int rows = a.GetLength(0); - fixed (double* ptrA = a, ptrR = result) + unsafe { - double* A = ptrA; - double* R = ptrR; - for (int i = 0; i < rows; i++) - for (int j = 0; j < b.Length; j++) - *R++ = *A++ / b[j]; + fixed (double* ptrA = a, ptrR = result) + { + double* A = ptrA; + double* R = ptrR; + for (int i = 0; i < rows; i++) + for (int j = 0; j < b.Length; j++) + *R++ = *A++ / b[j]; + } } } @@ -1310,15 +1332,18 @@ public static float[] Multiply(this float[,] matrix, float[] columnVector) /// The matrix R to store the product R=A*x /// of the multiplication of the given matrix A and scalar x. /// - public unsafe static void Multiply(this double[,] matrix, double x, double[,] result) + public static void Multiply(this double[,] matrix, double x, double[,] result) { int length = matrix.Length; - fixed (double* ptrA = matrix, ptrR = result) + unsafe { - double* pa = ptrA, pr = ptrR; - for (int i = 0; i < length; i++, pa++, pr++) - *pr = *pa * x; + fixed (double* ptrA = matrix, ptrR = result) + { + double* pa = ptrA, pr = ptrR; + for (int i = 0; i < length; i++, pa++, pr++) + *pr = *pa * x; + } } } @@ -1331,15 +1356,18 @@ public unsafe static void Multiply(this double[,] matrix, double x, double[,] re /// The matrix R to store the product R=A*x /// of the multiplication of the given matrix A and scalar x. /// - public unsafe static void Multiply(this float[,] matrix, float x, float[,] result) + public static void Multiply(this float[,] matrix, float x, float[,] result) { int length = matrix.Length; - fixed (float* ptrA = matrix, ptrR = result) + unsafe { - float* pa = ptrA, pr = ptrR; - for (int i = 0; i < length; i++, pa++, pr++) - *pr = *pa * x; + fixed (float* ptrA = matrix, ptrR = result) + { + float* pa = ptrA, pr = ptrR; + for (int i = 0; i < length; i++, pa++, pr++) + *pr = *pa * x; + } } } @@ -1912,7 +1940,7 @@ public static T[][] CartesianProduct(this T[] sequence1, T[] sequence2) /// /// The Kronecker product of the two matrices. /// - public unsafe static double[,] KroneckerProduct(this double[,] a, double[,] b) + public static double[,] KroneckerProduct(this double[,] a, double[,] b) { if (a == null) throw new ArgumentNullException("a"); if (b == null) throw new ArgumentNullException("b"); @@ -1930,22 +1958,25 @@ public static T[][] CartesianProduct(this T[] sequence1, T[] sequence2) double[,] result = new double[crows, ccols]; - fixed (double* ptrR = result, ptrA = a, ptrB = b) + unsafe { - double* A = ptrA, Ri = ptrR; - - for (int i = 0; i < arows; Ri += block, i++) + fixed (double* ptrR = result, ptrA = a, ptrB = b) { - double* Rj = Ri; + double* A = ptrA, Ri = ptrR; - for (int j = 0; j < acols; j++, Rj += bcols, A++) + for (int i = 0; i < arows; Ri += block, i++) { - double* R = Rj, B = ptrB; + double* Rj = Ri; - for (int k = 0; k < brows; k++, R += ccols) + for (int j = 0; j < acols; j++, Rj += bcols, A++) { - for (int l = 0; l < bcols; l++, B++) - *(R + l) = (*A) * (*B); + double* R = Rj, B = ptrB; + + for (int k = 0; k < brows; k++, R += ccols) + { + for (int l = 0; l < bcols; l++, B++) + *(R + l) = (*A) * (*B); + } } } } @@ -2019,7 +2050,7 @@ public static double[] KroneckerProduct(this double[] a, double[] b) /// /// The sum of the given matrices. /// - public unsafe static double[,] Add(this double[,] a, double[,] b) + public static double[,] Add(this double[,] a, double[,] b) { if (a.GetLength(0) != b.GetLength(0) || a.GetLength(1) != b.GetLength(1)) throw new ArgumentException("Matrix dimensions must match", "b"); @@ -2030,11 +2061,14 @@ public static double[] KroneckerProduct(this double[] a, double[] b) double[,] r = new double[rows, cols]; - fixed (double* ptrA = a, ptrB = b, ptrR = r) + unsafe { - double* pa = ptrA, pb = ptrB, pr = ptrR; - for (int i = 0; i < length; i++, pa++, pb++, pr++) - *pr = *pa + *pb; + fixed (double* ptrA = a, ptrB = b, ptrR = r) + { + double* pa = ptrA, pb = ptrB, pr = ptrR; + for (int i = 0; i < length; i++, pa++, pb++, pr++) + *pr = *pa + *pb; + } } return r; @@ -2340,7 +2374,7 @@ public static double[] Add(this double[] a, double b) /// /// The subtraction of the given matrices. /// - public unsafe static double[,] Subtract(this double[,] a, double[,] b, bool inPlace = false) + public static double[,] Subtract(this double[,] a, double[,] b, bool inPlace = false) { if (a == null) throw new ArgumentNullException("a"); if (b == null) throw new ArgumentNullException("b"); @@ -2354,11 +2388,14 @@ public static double[] Add(this double[] a, double b) double[,] r = inPlace ? a : new double[rows, cols]; - fixed (double* ptrA = a, ptrB = b, ptrR = r) + unsafe { - double* pa = ptrA, pb = ptrB, pr = ptrR; - for (int i = 0; i < length; i++, pa++, pb++, pr++) - *pr = *pa - *pb; + fixed (double* ptrA = a, ptrB = b, ptrR = r) + { + double* pa = ptrA, pb = ptrB, pr = ptrR; + for (int i = 0; i < length; i++, pa++, pb++, pr++) + *pr = *pa - *pb; + } } return r; } @@ -2559,10 +2596,27 @@ public static int[] Subtract(this int[] vector, int x, bool inPlace = false) /// /// The subtraction of the given vector elements from the given scalar. /// - public static double[] Subtract(this double x, double[] vector) + public static double[] Subtract(this int x, double[] vector) { double[] r = new double[vector.Length]; + for (int i = 0; i < vector.Length; i++) + r[i] = vector[i] - x; + return r; + } + + /// + /// Subtracts a scalar from a vector. + /// + /// + /// A vector. + /// A scalar. + /// + /// The subtraction of the given vector elements from the given scalar. + /// + public static double[] Subtract(this double x, double[] vector) + { + double[] r = new double[vector.Length]; for (int i = 0; i < vector.Length; i++) r[i] = vector[i] - x; diff --git a/Sources/Accord.Math/Matrix/Matrix.Common.cs b/Sources/Accord.Math/Matrix/Matrix.Common.cs index e4cb119e1..1f7093e96 100644 --- a/Sources/Accord.Math/Matrix/Matrix.Common.cs +++ b/Sources/Accord.Math/Matrix/Matrix.Common.cs @@ -1146,23 +1146,26 @@ public static double Trace(this double[,] matrix) /// Gets the trace of a matrix product. /// /// - public static unsafe double Trace(double[,] matrixA, double[,] matrixB) + public static double Trace(double[,] matrixA, double[,] matrixB) { if (matrixA.Length != matrixB.Length) throw new DimensionMismatchException("matrixB", "Matrices must have the same length."); int length = matrixA.Length; - fixed (double* ptrA = matrixA) - fixed (double* ptrB = matrixB) + unsafe { - double* a = ptrA; - double* b = ptrB; + fixed (double* ptrA = matrixA) + fixed (double* ptrB = matrixB) + { + double* a = ptrA; + double* b = ptrB; - double trace = 0.0; - for (int i = 0; i < length; i++) - trace += (*a++) * (*b++); - return trace; + double trace = 0.0; + for (int i = 0; i < length; i++) + trace += (*a++) * (*b++); + return trace; + } } } diff --git a/Sources/Accord.Math/Matrix/Matrix.Complex.cs b/Sources/Accord.Math/Matrix/Matrix.Complex.cs index 023c36425..11d6f5caf 100644 --- a/Sources/Accord.Math/Matrix/Matrix.Complex.cs +++ b/Sources/Accord.Math/Matrix/Matrix.Complex.cs @@ -1,418 +1,392 @@ -// Accord Math Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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 -// - -// #define USE_SYSTEM_NUMERICS_COMPLEX - -namespace Accord.Math -{ - using AForge; - using System; - using System.Runtime.CompilerServices; - -#if USE_SYSTEM_NUMERICS_COMPLEX - using Complex = System.Numerics.Complex; -#else - using Complex = AForge.Math.Complex; -#endif - - /// - /// Static class ComplexExtensions. Defines a set of extension methods - /// that operates mainly on multidimensional arrays and vectors of - /// AForge.NET's data type. - /// - /// - public static class ComplexMatrix - { - - /// - /// Computes the absolute value of an array of complex numbers. - /// - /// - public static Complex[] Abs(this Complex[] x) - { - if (x == null) throw new ArgumentNullException("x"); - - Complex[] r = new Complex[x.Length]; - for (int i = 0; i < x.Length; i++) - r[i] = new Complex(x[i].Magnitude, 0); - return r; - } - - /// - /// Computes the sum of an array of complex numbers. - /// - /// - public static Complex Sum(this Complex[] x) - { - if (x == null) throw new ArgumentNullException("x"); - - Complex r = Complex.Zero; - for (int i = 0; i < x.Length; i++) - r += x[i]; - return r; - } - - /// - /// Elementwise multiplication of two complex vectors. - /// - /// - public static Complex[] Multiply(this Complex[] a, Complex[] b) - { - if (a == null) throw new ArgumentNullException("a"); - if (b == null) throw new ArgumentNullException("b"); - - Complex[] r = new Complex[a.Length]; - for (int i = 0; i < a.Length; i++) - { - r[i] = Complex.Multiply(a[i], b[i]); - } - return r; - } - - /// - /// Gets the magnitude of every complex number in an array. - /// - /// - public static double[] Magnitude(this Complex[] c) - { - if (c == null) throw new ArgumentNullException("c"); - - double[] magnitudes = new double[c.Length]; - for (int i = 0; i < c.Length; i++) - magnitudes[i] = c[i].Magnitude; - - return magnitudes; - } - - /// - /// Gets the magnitude of every complex number in a matrix. - /// - /// - public static double[,] Magnitude(this Complex[,] c) - { - if (c == null) throw new ArgumentNullException("c"); - - int rows = c.GetLength(0); - int cols = c.GetLength(1); - - double[,] magnitudes = new double[rows, cols]; - for (int i = 0; i < rows; i++) - for (int j = 0; j < cols; j++) - magnitudes[i, j] = c[i, j].Magnitude; - - return magnitudes; - } - - /// - /// Gets the phase of every complex number in an array. - /// - /// - public static double[] Phase(this Complex[] c) - { - if (c == null) throw new ArgumentNullException("c"); - - double[] phases = new double[c.Length]; - for (int i = 0; i < c.Length; i++) - phases[i] = c[i].Phase; - - return phases; - } - - /// - /// Returns the real vector part of the complex vector c. - /// - /// - /// A vector of complex numbers. - /// - /// A vector of scalars with the real part of the complex numbers. - /// - public static double[] Re(this Complex[] c) - { - if (c == null) throw new ArgumentNullException("c"); - - double[] re = new double[c.Length]; - for (int i = 0; i < c.Length; i++) - re[i] = c[i].Re(); - - return re; - } - - /// - /// Returns the real matrix part of the complex matrix c. - /// - /// - /// A matrix of complex numbers. - /// - /// A matrix of scalars with the real part of the complex numbers. - /// - public static double[,] Re(this Complex[,] c) - { - if (c == null) - throw new ArgumentNullException("c"); - - int rows = c.GetLength(0); - int cols = c.GetLength(1); - - var re = new double[rows, cols]; - for (int i = 0; i < rows; i++) - for (int j = 0; i < cols; j++) - re[i, j] = c[i, j].Re(); - - return re; - } - - /// - /// Returns the imaginary vector part of the complex vector c. - /// - /// - /// A vector of complex numbers. - /// - /// A vector of scalars with the imaginary part of the complex numbers. - /// - public static double[] Im(this Complex[] c) - { - if (c == null) - throw new ArgumentNullException("c"); - - double[] im = new double[c.Length]; - for (int i = 0; i < c.Length; i++) - im[i] = c[i].Im(); - - return im; - } - - /// - /// Returns the imaginary matrix part of the complex matrix c. - /// - /// A matrix of complex numbers. - /// A matrix of scalars with the imaginary part of the complex numbers. - public static double[,] Im(this Complex[,] c) - { - if (c == null) - throw new ArgumentNullException("c"); - - int rows = c.GetLength(0); - int cols = c.GetLength(1); - - var im = new double[rows, cols]; - for (int i = 0; i < rows; i++) - for (int j = 0; i < cols; j++) - im[i, j] = c[i, j].Im(); - - return im; - } - - /// - /// Converts a complex number to a matrix of scalar values - /// in which the first column contains the real values and - /// the second column contains the imaginary values. - /// - /// An array of complex numbers. - public static double[,] ToArray(this Complex[] c) - { - if (c == null) - throw new ArgumentNullException("c"); - - double[,] arr = new double[c.Length, 2]; - for (int i = 0; i < c.GetLength(0); i++) - { - arr[i, 0] = c[i].Re(); - arr[i, 1] = c[i].Im(); - } - - return arr; - } - - /// - /// Converts a vector of real numbers to complex numbers. - /// - /// - /// The real numbers to be converted. - /// - /// - /// A vector of complex number with the given - /// real numbers as their real components. - /// - /// - public static Complex[] ToComplex(this double[] real) - { - if (real == null) - throw new ArgumentNullException("real"); - - Complex[] arr = new Complex[real.Length]; - for (int i = 0; i < arr.Length; i++) - arr[i] = new Complex(real[i], 0); - - return arr; - } - - /// - /// Combines a vector of real and a vector of - /// imaginary numbers to form complex numbers. - /// - /// - /// The real part of the complex numbers. - /// The imaginary part of the complex numbers - /// - /// - /// A vector of complex number with the given - /// real numbers as their real components and - /// imaginary numbers as their imaginary parts. - /// - /// - public static Complex[] ToComplex(this double[] real, double[] imag) - { - if (real == null) - throw new ArgumentNullException("real"); - - if (imag == null) - throw new ArgumentNullException("imag"); - - if (real.Length != imag.Length) - throw new DimensionMismatchException("imag"); - - Complex[] arr = new Complex[real.Length]; - for (int i = 0; i < arr.Length; i++) - arr[i] = new Complex(real[i], imag[i]); - - return arr; - } - - /// - /// Gets the range of the magnitude values in a complex number vector. - /// - /// - /// A complex number vector. - /// The range of magnitude values in the complex vector. - /// - public static DoubleRange Range(this Complex[] array) - { - if (array == null) - throw new ArgumentNullException("array"); - - double min = array[0].SquaredMagnitude(); - double max = array[0].SquaredMagnitude(); - - for (int i = 1; i < array.Length; i++) - { - double sqMagnitude = array[i].SquaredMagnitude(); - - if (min > sqMagnitude) - min = sqMagnitude; - if (max < sqMagnitude) - max = sqMagnitude; - } - - return new DoubleRange( - System.Math.Sqrt(min), - System.Math.Sqrt(max)); - } - - /// - /// Compares two matrices for equality, considering an acceptance threshold. - /// - public static bool IsEqual(this Complex[][] objA, Complex[][] objB, double threshold) - { - if (objA == null && objB == null) return true; - if (objA == null) throw new ArgumentNullException("objA"); - if (objB == null) throw new ArgumentNullException("objB"); - - for (int i = 0; i < objA.Length; i++) - { - for (int j = 0; j < objA[i].Length; j++) - { - double xr = objA[i][j].Re(), yr = objB[i][j].Re(); - double xi = objA[i][j].Im(), yi = objB[i][j].Im(); - - if (Math.Abs(xr - yr) > threshold || (Double.IsNaN(xr) ^ Double.IsNaN(yr))) - return false; - - if (Math.Abs(xi - yi) > threshold || (Double.IsNaN(xr) ^ Double.IsNaN(yr))) - return false; - } - } - return true; - } - - /// - /// Compares two vectors for equality, considering an acceptance threshold. - /// - public static bool IsEqual(this Complex[] objA, Complex[] objB, double threshold) - { - if (objA == null && objB == null) return true; - if (objA == null) throw new ArgumentNullException("objA"); - if (objB == null) throw new ArgumentNullException("objB"); - - for (int i = 0; i < objA.Length; i++) - { - double xr = objA[i].Re(), yr = objB[i].Re(); - double xi = objA[i].Im(), yi = objB[i].Im(); - - if (Math.Abs(xr - yr) > threshold || (Double.IsNaN(xr) ^ Double.IsNaN(yr))) - return false; - - if (Math.Abs(xi - yi) > threshold || (Double.IsNaN(xi) ^ Double.IsNaN(yi))) - return false; - } - return true; - } - - - -#if NET45 - [MethodImpl(MethodImplOptions.AggressiveInlining)] -#endif - internal static double Re(this Complex c) - { -#if USE_SYSTEM_NUMERICS_COMPLEX - return c.Real; -#else - return c.Re; -#endif - } - -#if NET45 - [MethodImpl(MethodImplOptions.AggressiveInlining)] -#endif - internal static double Im(this Complex c) - { -#if USE_SYSTEM_NUMERICS_COMPLEX - return c.Imaginary; -#else - return c.Im; -#endif - } - -#if NET45 - [MethodImpl(MethodImplOptions.AggressiveInlining)] -#endif - internal static double SquaredMagnitude(this Complex c) - { -#if USE_SYSTEM_NUMERICS_COMPLEX - return c.Magnitude * c.Magnitude; -#else - return c.SquaredMagnitude; -#endif - } - - } -} +// Accord Math Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Math +{ + using AForge; + using System; + using System.Numerics; + using System.Runtime.CompilerServices; + + /// + /// Static class ComplexExtensions. Defines a set of extension methods + /// that operates mainly on multidimensional arrays and vectors of + /// AForge.NET's data type. + /// + /// + public static class ComplexMatrix + { + + /// + /// Computes the absolute value of an array of complex numbers. + /// + /// + public static Complex[] Abs(this Complex[] x) + { + if (x == null) + throw new ArgumentNullException("x"); + + Complex[] r = new Complex[x.Length]; + for (int i = 0; i < x.Length; i++) + r[i] = new Complex(x[i].Magnitude, 0); + return r; + } + + /// + /// Computes the sum of an array of complex numbers. + /// + /// + public static Complex Sum(this Complex[] x) + { + if (x == null) throw new ArgumentNullException("x"); + + Complex r = Complex.Zero; + for (int i = 0; i < x.Length; i++) + r += x[i]; + return r; + } + + /// + /// Elementwise multiplication of two complex vectors. + /// + /// + public static Complex[] Multiply(this Complex[] a, Complex[] b) + { + if (a == null) throw new ArgumentNullException("a"); + if (b == null) throw new ArgumentNullException("b"); + + Complex[] r = new Complex[a.Length]; + for (int i = 0; i < a.Length; i++) + { + r[i] = Complex.Multiply(a[i], b[i]); + } + return r; + } + + /// + /// Gets the magnitude of every complex number in an array. + /// + /// + public static double[] Magnitude(this Complex[] c) + { + if (c == null) + throw new ArgumentNullException("c"); + + double[] magnitudes = new double[c.Length]; + for (int i = 0; i < c.Length; i++) + magnitudes[i] = c[i].Magnitude; + + return magnitudes; + } + + /// + /// Gets the magnitude of every complex number in a matrix. + /// + /// + public static double[,] Magnitude(this Complex[,] c) + { + if (c == null) throw new ArgumentNullException("c"); + + int rows = c.GetLength(0); + int cols = c.GetLength(1); + + double[,] magnitudes = new double[rows, cols]; + for (int i = 0; i < rows; i++) + for (int j = 0; j < cols; j++) + magnitudes[i, j] = c[i, j].Magnitude; + + return magnitudes; + } + + /// + /// Gets the phase of every complex number in an array. + /// + /// + public static double[] Phase(this Complex[] c) + { + if (c == null) throw new ArgumentNullException("c"); + + double[] phases = new double[c.Length]; + for (int i = 0; i < c.Length; i++) + phases[i] = c[i].Phase; + + return phases; + } + + /// + /// Returns the real vector part of the complex vector c. + /// + /// + /// A vector of complex numbers. + /// + /// A vector of scalars with the real part of the complex numbers. + /// + public static double[] Re(this Complex[] c) + { + if (c == null) throw new ArgumentNullException("c"); + + double[] re = new double[c.Length]; + for (int i = 0; i < c.Length; i++) + re[i] = c[i].Real; + + return re; + } + + /// + /// Returns the real matrix part of the complex matrix c. + /// + /// + /// A matrix of complex numbers. + /// + /// A matrix of scalars with the real part of the complex numbers. + /// + public static double[,] Re(this Complex[,] c) + { + if (c == null) + throw new ArgumentNullException("c"); + + int rows = c.GetLength(0); + int cols = c.GetLength(1); + + var re = new double[rows, cols]; + for (int i = 0; i < rows; i++) + for (int j = 0; i < cols; j++) + re[i, j] = c[i, j].Real; + + return re; + } + + /// + /// Returns the imaginary vector part of the complex vector c. + /// + /// + /// A vector of complex numbers. + /// + /// A vector of scalars with the imaginary part of the complex numbers. + /// + // TODO: Rename to Imaginary + public static double[] Im(this Complex[] c) + { + if (c == null) + throw new ArgumentNullException("c"); + + double[] im = new double[c.Length]; + for (int i = 0; i < c.Length; i++) + im[i] = c[i].Imaginary; + + return im; + } + + /// + /// Returns the imaginary matrix part of the complex matrix c. + /// + /// A matrix of complex numbers. + /// A matrix of scalars with the imaginary part of the complex numbers. + public static double[,] Im(this Complex[,] c) + { + if (c == null) + throw new ArgumentNullException("c"); + + int rows = c.GetLength(0); + int cols = c.GetLength(1); + + var im = new double[rows, cols]; + for (int i = 0; i < rows; i++) + for (int j = 0; i < cols; j++) + im[i, j] = c[i, j].Imaginary; + + return im; + } + + /// + /// Converts a complex number to a matrix of scalar values + /// in which the first column contains the real values and + /// the second column contains the imaginary values. + /// + /// An array of complex numbers. + public static double[,] ToArray(this Complex[] c) + { + if (c == null) + throw new ArgumentNullException("c"); + + double[,] arr = new double[c.Length, 2]; + for (int i = 0; i < c.GetLength(0); i++) + { + arr[i, 0] = c[i].Real; + arr[i, 1] = c[i].Imaginary; + } + + return arr; + } + + /// + /// Converts a vector of real numbers to complex numbers. + /// + /// + /// The real numbers to be converted. + /// + /// + /// A vector of complex number with the given + /// real numbers as their real components. + /// + /// + public static Complex[] ToComplex(this double[] real) + { + if (real == null) + throw new ArgumentNullException("real"); + + Complex[] arr = new Complex[real.Length]; + for (int i = 0; i < arr.Length; i++) + arr[i] = new Complex(real[i], 0); + + return arr; + } + + /// + /// Combines a vector of real and a vector of + /// imaginary numbers to form complex numbers. + /// + /// + /// The real part of the complex numbers. + /// The imaginary part of the complex numbers + /// + /// + /// A vector of complex number with the given + /// real numbers as their real components and + /// imaginary numbers as their imaginary parts. + /// + /// + public static Complex[] ToComplex(this double[] real, double[] imag) + { + if (real == null) + throw new ArgumentNullException("real"); + + if (imag == null) + throw new ArgumentNullException("imag"); + + if (real.Length != imag.Length) + throw new DimensionMismatchException("imag"); + + Complex[] arr = new Complex[real.Length]; + for (int i = 0; i < arr.Length; i++) + arr[i] = new Complex(real[i], imag[i]); + + return arr; + } + + /// + /// Gets the range of the magnitude values in a complex number vector. + /// + /// + /// A complex number vector. + /// The range of magnitude values in the complex vector. + /// + public static DoubleRange Range(this Complex[] array) + { + if (array == null) + throw new ArgumentNullException("array"); + + double min = array[0].Magnitude; + double max = array[0].Magnitude; + + for (int i = 1; i < array.Length; i++) + { + double value = array[i].Magnitude; + + if (min > value) + min = value; + if (max < value) + max = value; + } + + return new DoubleRange( + System.Math.Sqrt(min), + System.Math.Sqrt(max)); + } + + /// + /// Compares two matrices for equality, considering an acceptance threshold. + /// + public static bool IsEqual(this Complex[][] objA, Complex[][] objB, double threshold) + { + if (objA == null && objB == null) return true; + if (objA == null) throw new ArgumentNullException("objA"); + if (objB == null) throw new ArgumentNullException("objB"); + + for (int i = 0; i < objA.Length; i++) + { + for (int j = 0; j < objA[i].Length; j++) + { + double xr = objA[i][j].Real; + double yr = objB[i][j].Real; + double xi = objA[i][j].Imaginary; + double yi = objB[i][j].Imaginary; + + if (Math.Abs(xr - yr) > threshold || (Double.IsNaN(xr) ^ Double.IsNaN(yr))) + return false; + + if (Math.Abs(xi - yi) > threshold || (Double.IsNaN(xr) ^ Double.IsNaN(yr))) + return false; + } + } + return true; + } + + /// + /// Compares two vectors for equality, considering an acceptance threshold. + /// + public static bool IsEqual(this Complex[] objA, Complex[] objB, double threshold) + { + if (objA == null && objB == null) return true; + if (objA == null) throw new ArgumentNullException("objA"); + if (objB == null) throw new ArgumentNullException("objB"); + + for (int i = 0; i < objA.Length; i++) + { + double xr = objA[i].Real; + double yr = objB[i].Real; + double xi = objA[i].Imaginary; + double yi = objB[i].Imaginary; + + if (Math.Abs(xr - yr) > threshold || (Double.IsNaN(xr) ^ Double.IsNaN(yr))) + return false; + + if (Math.Abs(xi - yi) > threshold || (Double.IsNaN(xi) ^ Double.IsNaN(yi))) + return false; + } + return true; + } + + /// + /// Gets the squared magnitude of a complex number. + /// + /// +#if NET45 + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + public static double SquaredMagnitude(this Complex value) + { + return value.Magnitude * value.Magnitude; + } + + } +} diff --git a/Sources/Accord.Math/Matrix/Matrix.Construction.cs b/Sources/Accord.Math/Matrix/Matrix.Construction.cs index 25e10b02c..5a59b5e5d 100644 --- a/Sources/Accord.Math/Matrix/Matrix.Construction.cs +++ b/Sources/Accord.Math/Matrix/Matrix.Construction.cs @@ -663,7 +663,7 @@ public static int[] GetDimensions(this Array array) int[] vector = new int[array.Rank]; for (int i = 0; i < vector.Length; i++) - vector[i] = array.GetUpperBound(i); + vector[i] = array.GetUpperBound(i) + 1; return vector; } @@ -1286,7 +1286,7 @@ public static T[] Expand(T[] vector, int[] count) #region Split /// /// Splits a given vector into a smaller vectors of the given size. - /// This operation can be reverted using . + /// This operation can be reverted using . /// /// /// The vector to be splitted. @@ -1309,7 +1309,7 @@ public static T[][] Split(this T[] vector, int size) /// /// Merges a series of vectors into a single vector. This - /// operation can be reverted using . + /// operation can be reverted using . /// /// /// The vectors to be merged. @@ -1329,6 +1329,30 @@ public static T[] Merge(this T[][] vectors, int size) return r; } + + /// + /// Merges a series of vectors into a single vector. This + /// operation can be reverted using . + /// + /// + /// The vectors to be merged. + /// + /// A single array containing the given vectors. + /// + public static T[] Merge(this T[][] vectors) + { + int size = 0; + for (int i = 0; i < vectors.Length; i++) + size += vectors[i].Length; + T[] r = new T[size]; + + int c = 0; + for (int i = 0; i < vectors.Length; i++) + for (int j = 0; j < vectors[i].Length; j++, c++) + r[c] = vectors[i][j]; + + return r; + } #endregion /// diff --git a/Sources/Accord.Math/Matrix/Matrix.Conversions.cs b/Sources/Accord.Math/Matrix/Matrix.Conversions.cs index fb63d4325..627f5d310 100644 --- a/Sources/Accord.Math/Matrix/Matrix.Conversions.cs +++ b/Sources/Accord.Math/Matrix/Matrix.Conversions.cs @@ -23,6 +23,8 @@ namespace Accord.Math { using System; + using System.Collections; + using System.Collections.Generic; using System.Data; using System.Globalization; using System.Linq; @@ -170,7 +172,7 @@ public static T[][] ToArray(this T[,] matrix, bool transpose) /// array. /// /// - public unsafe static double[,] ToDouble(this float[,] matrix) + public static double[,] ToDouble(this float[,] matrix) { int rows = matrix.GetLength(0); int cols = matrix.GetLength(1); @@ -178,14 +180,17 @@ public static T[][] ToArray(this T[,] matrix, bool transpose) double[,] result = new double[rows, cols]; - fixed (float* srcPtr = matrix) - fixed (double* dstPtr = result) + unsafe { - float* src = srcPtr; - double* dst = dstPtr; + fixed (float* srcPtr = matrix) + fixed (double* dstPtr = result) + { + float* src = srcPtr; + double* dst = dstPtr; - for (int i = 0; i < length; i++, src++, dst++) - *dst = (double)*src; + for (int i = 0; i < length; i++, src++, dst++) + *dst = (double)*src; + } } return result; @@ -196,7 +201,7 @@ public static T[][] ToArray(this T[,] matrix, bool transpose) /// precision floating point multidimensional array. ///
/// - public unsafe static double[,] ToDouble(this byte[,] matrix) + public static double[,] ToDouble(this byte[,] matrix) { int rows = matrix.GetLength(0); int cols = matrix.GetLength(1); @@ -204,14 +209,17 @@ public static T[][] ToArray(this T[,] matrix, bool transpose) double[,] result = new double[rows, cols]; - fixed (byte* srcPtr = matrix) - fixed (double* dstPtr = result) + unsafe { - byte* src = srcPtr; - double* dst = dstPtr; + fixed (byte* srcPtr = matrix) + fixed (double* dstPtr = result) + { + byte* src = srcPtr; + double* dst = dstPtr; - for (int i = 0; i < length; i++, src++, dst++) - *dst = (double)*src; + for (int i = 0; i < length; i++, src++, dst++) + *dst = (double)*src; + } } return result; @@ -223,7 +231,7 @@ public static T[][] ToArray(this T[,] matrix, bool transpose) /// array. /// /// - public unsafe static double[,] ToDouble(this int[,] matrix) + public static double[,] ToDouble(this int[,] matrix) { int rows = matrix.GetLength(0); int cols = matrix.GetLength(1); @@ -231,14 +239,17 @@ public static T[][] ToArray(this T[,] matrix, bool transpose) double[,] result = new double[rows, cols]; - fixed (int* srcPtr = matrix) - fixed (double* dstPtr = result) + unsafe { - int* src = srcPtr; - double* dst = dstPtr; + fixed (int* srcPtr = matrix) + fixed (double* dstPtr = result) + { + int* src = srcPtr; + double* dst = dstPtr; - for (int i = 0; i < length; i++, src++, dst++) - *dst = (double)*src; + for (int i = 0; i < length; i++, src++, dst++) + *dst = (double)*src; + } } return result; @@ -250,7 +261,7 @@ public static T[][] ToArray(this T[,] matrix, bool transpose) /// array. /// /// - public unsafe static float[,] ToSingle(this double[,] matrix) + public static float[,] ToSingle(this double[,] matrix) { int rows = matrix.GetLength(0); int cols = matrix.GetLength(1); @@ -258,14 +269,17 @@ public static T[][] ToArray(this T[,] matrix, bool transpose) float[,] result = new float[rows, cols]; - fixed (double* srcPtr = matrix) - fixed (float* dstPtr = result) + unsafe { - double* src = srcPtr; - float* dst = dstPtr; + fixed (double* srcPtr = matrix) + fixed (float* dstPtr = result) + { + double* src = srcPtr; + float* dst = dstPtr; - for (int i = 0; i < length; i++, src++, dst++) - *dst = (float)*src; + for (int i = 0; i < length; i++, src++, dst++) + *dst = (float)*src; + } } return result; @@ -276,7 +290,7 @@ public static T[][] ToArray(this T[,] matrix, bool transpose) /// /// The matrix to be truncated. /// - public unsafe static int[,] ToInt32(this double[,] matrix) + public static int[,] ToInt32(this double[,] matrix) { int rows = matrix.GetLength(0); int cols = matrix.GetLength(1); @@ -284,14 +298,17 @@ public static T[][] ToArray(this T[,] matrix, bool transpose) int[,] result = new int[rows, cols]; - fixed (double* srcPtr = matrix) - fixed (int* dstPtr = result) + unsafe { - double* src = srcPtr; - int* dst = dstPtr; + fixed (double* srcPtr = matrix) + fixed (int* dstPtr = result) + { + double* src = srcPtr; + int* dst = dstPtr; - for (int i = 0; i < length; i++, src++, dst++) - *dst = (int)*src; + for (int i = 0; i < length; i++, src++, dst++) + *dst = (int)*src; + } } return result; @@ -586,9 +603,104 @@ public static TOutput[][] Convert(this TInput[][] matrix, Conve return result; } - #endregion + /// + /// Converts an object into another type, irrespective of whether + /// the conversion can be done at compile time or not. This can be + /// used to convert generic types to numeric types during runtime. + /// + /// + /// The destination type. + /// + /// The value to be converted. + /// + /// The result of the conversion. + /// + public static T To(this object value) + { + return (T)System.Convert.ChangeType(value, typeof(T)); + } + /// + /// Converts the values of a vector using the given converter expression. + /// + /// The type of the output. + /// The vector or array to be converted. + /// + public static TOutput To(this Array array) + where TOutput : class, ICloneable, IList, ICollection, IEnumerable +#if !NET35 + , IStructuralComparable, IStructuralEquatable +#endif + { + var typeInput = array.GetType(); + var typeOutput = typeof(TOutput); + + var inputElementType = typeInput.GetElementType(); + var outputElementType = typeOutput.GetElementType(); + + if (inputElementType.IsSubclassOf(typeof(Array))) + { + // Jagged array + throw new NotImplementedException(); + } + else + { + // Multidimensional array + var dimensions = array.GetDimensions(); + var result = Array.CreateInstance(outputElementType, dimensions); + + foreach (var idx in GetIndices(array)) + { + object inputValue = array.GetValue(idx); + object outputValue = null; + + if (outputElementType.IsEnum) + outputValue = Enum.ToObject(outputElementType, (int)System.Convert.ChangeType(inputValue, typeof(int))); + else + outputValue = System.Convert.ChangeType(inputValue, outputElementType); + + result.SetValue(outputValue, idx); + } + + return result as TOutput; + } + } + + #endregion + + /// + /// Creates a vector containing every index that can be used to + /// address a given , in order. + /// + /// + /// The array whose indices will be returned. + /// + /// + /// An enumerable object that can be used to iterate over all + /// positions of the given System.Array. + /// + /// + /// + /// + /// double[,] a = + /// { + /// { 5.3, 2.3 }, + /// { 4.2, 9.2 } + /// }; + /// + /// foreach (int[] idx in a.GetIndices()) + /// { + /// // Get the current element + /// double e = (double)a.GetValue(idx); + /// } + /// + /// + /// + public static IEnumerable GetIndices(this Array array) + { + return Accord.Math.Indices.From(array); + } @@ -765,7 +877,7 @@ public static DataTable ToTable(this double[,] matrix, params string[] columnNam /// public static DataTable ToTable(this double[][] matrix) { - int cols = matrix.GetLength(1); + int cols = matrix[0].Length; String[] columnNames = new String[cols]; for (int i = 0; i < columnNames.Length; i++) diff --git a/Sources/Accord.Math/Matrix/Matrix.Parsing.cs b/Sources/Accord.Math/Matrix/Matrix.Parsing.cs index d012059bb..46b5604af 100644 --- a/Sources/Accord.Math/Matrix/Matrix.Parsing.cs +++ b/Sources/Accord.Math/Matrix/Matrix.Parsing.cs @@ -43,7 +43,7 @@ public static partial class Matrix /// for more details. /// /// - public static string ToString(this double[,] matrix) + public static string ToString(this T[,] matrix) { return ToString(matrix, DefaultMatrixFormatProvider.CurrentCulture); } @@ -77,7 +77,7 @@ public static string ToString(this double[,] matrix) /// /// /// - public static string ToString(this double[,] matrix, bool multiline, IMatrixFormatProvider provider) + public static string ToString(this T[,] matrix, bool multiline, IMatrixFormatProvider provider) { if (multiline) { @@ -113,7 +113,7 @@ public static string ToString(this double[,] matrix, bool multiline, IMatrixForm /// /// /// - public static string ToString(this double[,] matrix, IMatrixFormatProvider provider) + public static string ToString(this T[,] matrix, IMatrixFormatProvider provider) { return ToString(matrix, null, provider); } @@ -144,7 +144,7 @@ public static string ToString(this double[,] matrix, IMatrixFormatProvider provi /// /// /// - public static string ToString(this double[,] matrix, string format, IMatrixFormatProvider provider) + public static string ToString(this T[,] matrix, string format, IMatrixFormatProvider provider) { return MatrixFormatter.Format(format, matrix, provider); } @@ -171,7 +171,7 @@ public static string ToString(this double[,] matrix, string format, IMatrixForma /// /// /// - public static string ToString(this double[,] matrix, string format) + public static string ToString(this T[,] matrix, string format) { return MatrixFormatter.Format(format, matrix, DefaultMatrixFormatProvider.CurrentCulture); } @@ -194,7 +194,7 @@ public static string ToString(this double[,] matrix, string format) /// /// /// - public static string ToString(this double[][] matrix) + public static string ToString(this T[][] matrix) { return ToString(matrix, DefaultMatrixFormatProvider.CurrentCulture); } @@ -222,7 +222,7 @@ public static string ToString(this double[][] matrix) /// /// /// - public static string ToString(this double[][] matrix, IMatrixFormatProvider provider) + public static string ToString(this T[][] matrix, IMatrixFormatProvider provider) { return ToString(matrix, null, provider); } @@ -252,7 +252,7 @@ public static string ToString(this double[][] matrix, IMatrixFormatProvider prov /// for more details. /// /// - public static string ToString(this double[][] matrix, string format, IMatrixFormatProvider provider) + public static string ToString(this T[][] matrix, string format, IMatrixFormatProvider provider) { return MatrixFormatter.Format(format, matrix, provider); } @@ -278,7 +278,7 @@ public static string ToString(this double[][] matrix, string format, IMatrixForm /// for more details. /// /// - public static string ToString(this double[][] matrix, string format) + public static string ToString(this T[][] matrix, string format) { return MatrixFormatter.Format(format, matrix, DefaultMatrixFormatProvider.CurrentCulture); } @@ -299,7 +299,7 @@ public static string ToString(this double[][] matrix, string format) /// for examples and more details. /// /// - public static string ToString(this double[] array) + public static string ToString(this T[] array) { return ToString(array, DefaultArrayFormatProvider.CurrentCulture); } @@ -326,7 +326,7 @@ public static string ToString(this double[] array) /// for examples and more details. /// /// - public static string ToString(this double[] array, IMatrixFormatProvider provider) + public static string ToString(this T[] array, IMatrixFormatProvider provider) { return ToString(array, null, provider); } @@ -357,7 +357,7 @@ public static string ToString(this double[] array, IMatrixFormatProvider provide /// for examples and more details. /// /// - public static string ToString(this double[] matrix, string format, IMatrixFormatProvider provider) + public static string ToString(this T[] matrix, string format, IMatrixFormatProvider provider) { return MatrixFormatter.Format(format, matrix, provider); } @@ -382,7 +382,7 @@ public static string ToString(this double[] matrix, string format, IMatrixFormat /// for examples and more details. /// /// - public static string ToString(this double[] array, string format) + public static string ToString(this T[] array, string format) { return MatrixFormatter.Format(format, array, DefaultArrayFormatProvider.CurrentCulture); } diff --git a/Sources/Accord.Math/Matrix/Matrix.Selection.cs b/Sources/Accord.Math/Matrix/Matrix.Selection.cs index fc4140ae9..25b104c14 100644 --- a/Sources/Accord.Math/Matrix/Matrix.Selection.cs +++ b/Sources/Accord.Math/Matrix/Matrix.Selection.cs @@ -182,6 +182,17 @@ public static T[][] GetRows(this T[][] m, params int[] index) return m; } + /// + /// Stores a column vector into the given column position of the matrix. + /// + public static T[][] SetColumn(this T[][] m, int index, T[] column) + { + for (int i = 0; i < column.Length; i++) + m[i][index] = column[i]; + + return m; + } + /// /// Gets a row vector from a matrix. /// @@ -205,6 +216,17 @@ public static T[] GetRow(this T[,] m, int index) return m; } + + /// + /// Stores a row vector into the given row position of the matrix. + /// + public static T[][] SetRow(this T[][] m, int index, T[] row) + { + for (int i = 0; i < row.Length; i++) + m[index][i] = row[i]; + + return m; + } #endregion @@ -1566,13 +1588,33 @@ public static T[] Distinct(this T[] values, Func pro public static TValue[,] Sort(TKey[] keys, TValue[,] values, IComparer comparer) { int[] indices = new int[keys.Length]; - for (int i = 0; i < keys.Length; i++) indices[i] = i; + for (int i = 0; i < keys.Length; i++) + indices[i] = i; Array.Sort(keys, indices, comparer); return values.Submatrix(0, values.GetLength(0) - 1, indices); } + /// + /// Sorts the columns of a matrix by sorting keys. + /// + /// + /// The key value for each column. + /// The matrix to be sorted. + /// The comparer to use. + /// + public static TValue[][] Sort(TKey[] keys, TValue[][] values, IComparer comparer) + { + int[] indices = new int[keys.Length]; + for (int i = 0; i < keys.Length; i++) + indices[i] = i; + + Array.Sort(keys, indices, comparer); + + return values.Submatrix(0, values.Length - 1, indices); + } + /// /// Retrieves the top count values of an array. /// diff --git a/Sources/Accord.Math/Optimization/Constrained/Cobyla.cs b/Sources/Accord.Math/Optimization/Constrained/Cobyla.cs index 52fc3f1e1..689da9ea2 100644 --- a/Sources/Accord.Math/Optimization/Constrained/Cobyla.cs +++ b/Sources/Accord.Math/Optimization/Constrained/Cobyla.cs @@ -54,7 +54,13 @@ public enum CobylaStatus /// Size of rounding error is becoming damaging, terminating prematurely. /// /// - DivergingRoundingErrors + DivergingRoundingErrors, + + /// + /// The posed constraints cannot be fulfilled. + /// + /// + NoPossibleSolution } @@ -148,12 +154,12 @@ public class Cobyla : BaseOptimizationMethod, IOptimizationMethod, int iterations; NonlinearConstraint[] constraints; - /* - /// - /// Occurs when progress is made during the optimization. - /// - /// - public event EventHandler Progress; + /* + /// + /// Occurs when progress is made during the optimization. + /// + /// + public event EventHandler Progress; */ /// @@ -914,6 +920,14 @@ private CobylaStatus cobyla() maxfun = iterations; + if (status == CobylaStatus.Success) + { + // Check if all constraints have been fulfilled + for (int i = 0; i < constraints.Length; i++) + if (constraints[i].IsViolated(x)) + status = CobylaStatus.NoPossibleSolution; + } + return status; } diff --git a/Sources/Accord.Math/Optimization/Constrained/Constraints/LinearConstraint.cs b/Sources/Accord.Math/Optimization/Constrained/Constraints/LinearConstraint.cs index 4487839d0..b38701f63 100644 --- a/Sources/Accord.Math/Optimization/Constrained/Constraints/LinearConstraint.cs +++ b/Sources/Accord.Math/Optimization/Constrained/Constraints/LinearConstraint.cs @@ -1,638 +1,652 @@ -// Accord Math Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Math.Optimization +// Accord Math Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Math.Optimization { using System; using System.Collections.Generic; using System.Globalization; using System.Linq.Expressions; - using System.Text.RegularExpressions; - - /// - /// Constraint type. - /// - /// - public enum ConstraintType - { - /// - /// Equality constraint. - /// - /// - EqualTo = 0, - - /// - /// Inequality constraint specifying a greater than or equal to relationship. - /// - /// - GreaterThanOrEqualTo, - - /// - /// Inequality constraint specifying a lesser than or equal to relationship. - /// - /// - LesserThanOrEqualTo, - } - - /// - /// Constraint with only linear terms. - /// - /// - public class LinearConstraint : IConstraint - { - private int[] indices; - private double[] scalars; - - /// - /// Gets the number of variables in the constraint. - /// - /// - public int NumberOfVariables { get; private set; } - - /// - /// Gets the index of the variables (in respective to the - /// object function index) of the variables participating - /// in this constraint. - /// - /// - public int[] VariablesAtIndices - { - get { return indices; } - set - { - if (value == null) - throw new ArgumentNullException("value"); - - if (value.Length != NumberOfVariables) - throw new DimensionMismatchException("value"); - - this.indices = value; - } - } - - /// - /// Gets the scalar coefficients combining the - /// variables specified by the constraints. - /// - public double[] CombinedAs - { - get { return scalars; } - set - { - if (value == null) - throw new ArgumentNullException("value"); - - if (value.Length != NumberOfVariables) - throw new DimensionMismatchException("value"); - - this.scalars = value; - } - } - - /// - /// Gets the type of the constraint. - /// - /// - public ConstraintType ShouldBe { get; set; } - - /// - /// Gets the value to be compared to the combined values - /// of the variables. - /// - /// - public double Value { get; set; } - - /// - /// Gets the violation tolerance for the constraint. Equality - /// constraints should set this to a small positive value. - /// - /// - public double Tolerance { get; set; } - - /// - /// Constructs a new linear constraint. - /// - /// - /// The number of variables in the constraint. - /// - public LinearConstraint(int numberOfVariables) - { - this.NumberOfVariables = numberOfVariables; - this.indices = Matrix.Indices(0, numberOfVariables); - this.scalars = Matrix.Vector(numberOfVariables, 1.0); - this.ShouldBe = ConstraintType.GreaterThanOrEqualTo; - - this.Function = compute; - this.Gradient = gradient; - } - - /// - /// Constructs a new linear constraint. - /// - /// - /// The scalar coefficients specifying - /// how variables should be combined in the constraint. - /// - public LinearConstraint(params double[] coefficients) - { - this.NumberOfVariables = coefficients.Length; - this.indices = Matrix.Indices(0, coefficients.Length); - this.CombinedAs = coefficients; - this.ShouldBe = ConstraintType.GreaterThanOrEqualTo; - - this.Function = compute; - this.Gradient = gradient; - } - - /// - /// Constructs a new linear constraint. - /// - /// - /// The objective function to which - /// this constraint refers to. - /// A - /// specifying this constraint, such as "ax + b = c". - /// The culture information specifying how - /// numbers written in the should - /// be parsed. Default is CultureInfo.InvariantCulture. - /// - public LinearConstraint(IObjectiveFunction function, string constraint, CultureInfo format) - { - parseString(function, constraint, format); - - this.Function = compute; - this.Gradient = gradient; - } - - /// - /// Constructs a new linear constraint. - /// - /// - /// The objective function to which - /// this constraint refers to. - /// A - /// specifying this constraint, such as "ax + b = c". - /// - public LinearConstraint(IObjectiveFunction function, string constraint) - : this(function, constraint, CultureInfo.InvariantCulture) - { - } - - /// - /// Constructs a new linear constraint. - /// - /// - /// The objective function to which this - /// constraint refers to. - /// A specifying - /// this constraint in the form of a lambda expression. - /// - public LinearConstraint(IObjectiveFunction function, Expression> constraint) - { - parseExpression(function, constraint); - - this.Function = compute; - this.Gradient = gradient; - } - - /// - /// Gets how much the constraint is being violated. - /// - /// - /// The function point. - /// - /// - /// How much the constraint is being violated at the given point. Positive - /// value means the constraint is not being violated with the returned slack, - /// while a negative value means the constraint is being violated by the returned - /// amount. - /// - /// - public double GetViolation(double[] input) - { - double fx = 0; - - for (int i = 0; i < indices.Length; i++) - { - double x = input[indices[i]]; - double a = CombinedAs[i]; - - fx += x * a; - } - - switch (ShouldBe) - { - case ConstraintType.EqualTo: - return Math.Abs(fx - Value); - - case ConstraintType.GreaterThanOrEqualTo: - return fx - Value; - - case ConstraintType.LesserThanOrEqualTo: - return Value - fx; - } - - throw new NotSupportedException(); - } - - /// - /// Attempts to create a - /// from a representation. - /// - /// - /// The string containing the constraint in textual form. - /// The objective function to which this constraint refers to. - /// The resulting constraint, if it could be parsed. - /// - /// true if the function could be parsed - /// from the string, false otherwise. - /// - public static bool TryParse(string str, - IObjectiveFunction function, out LinearConstraint constraint) - { - return TryParse(str, CultureInfo.InvariantCulture, function, out constraint); - } - - /// - /// Attempts to create a - /// from a representation. - /// - /// - /// The string containing the constraint in textual form. - /// The objective function to which this constraint refers to. - /// The resulting constraint, if it could be parsed. - /// The culture information specifying how - /// numbers written in the should - /// be parsed. Default is CultureInfo.InvariantCulture. - /// - /// true if the function could be parsed - /// from the string, false otherwise. - /// - public static bool TryParse(string str, CultureInfo culture, - IObjectiveFunction function, out LinearConstraint constraint) - { - // TODO: implement this method without the try-catch block. - - try - { - constraint = new LinearConstraint(function, str, culture); - } - catch (FormatException) - { - constraint = null; - return false; - } - - return true; - } - - private double compute(double[] input) - { - double sum = 0; - - for (int i = 0; i < indices.Length; i++) - { - double x = input[indices[i]]; - double a = CombinedAs[i]; - - sum += x * a; - } - - return sum; - } - - private double[] gradient(double[] x) - { - return CombinedAs; - } - - - private void parseString(IObjectiveFunction function, string constraint, CultureInfo culture) - { - if (String.IsNullOrEmpty(constraint)) - throw new FormatException("Constraint is empty."); - - string f = constraint.Replace("*", String.Empty).Replace(" ", String.Empty); - - if (f[0] != '-' || f[0] != '+') - f = f.Insert(0, "+"); - - ConstraintType type; - - string lhs, rhs; - - if (f.Contains(">=")) - type = ConstraintType.GreaterThanOrEqualTo; - else if (f.Contains("<=")) - type = ConstraintType.LesserThanOrEqualTo; - else if (f.Contains("=")) - type = ConstraintType.EqualTo; - else - throw new FormatException("Invalid constraint type."); - - - - var terms = new Dictionary(); - - string separator = culture.NumberFormat.NumberDecimalSeparator; - - Regex r = new Regex(@"[\-\+][\s]*(\d*\" + separator + @"{0,1}\d+)?[\s]*([a-zA-Z])*"); - Regex number = new Regex(@"\d*\" + separator + @"{0,1}\d+"); - Regex symbol = new Regex(@"[a-zA-Z]"); - Regex comp = new Regex(@"(>=|<=|=)"); - - - var sides = comp.Split(f); - lhs = sides[0]; - rhs = sides[2]; - - double value = Double.Parse(rhs, culture); - - MatchCollection matches = r.Matches(lhs, 0); - - foreach (Match m in matches) - { - string term = m.Value; - - double scalar = (term[0] == '-') ? -1 : 1; - - // Extract value - MatchCollection coeff = number.Matches(term); - - foreach (Match c in coeff) - scalar *= Double.Parse(c.Value, culture); - - // Extract symbols - MatchCollection symbols = symbol.Matches(term); - - if (symbols.Count == 1) - { - terms.Add(symbols[0].Value, scalar); - } - else - { - if (coeff.Count == 1) - value -= scalar; - else if (term != "+") - throw new FormatException("Unexpected expression."); - } - } - - List indices = new List(); - List scalars = new List(); - - foreach (var term in terms) - { - indices.Add(function.Variables[term.Key]); - scalars.Add(term.Value); - } - - NumberOfVariables = indices.Count; - VariablesAtIndices = indices.ToArray(); - CombinedAs = scalars.ToArray(); - ShouldBe = type; - Value = value; - } - - private void parseExpression(IObjectiveFunction function, Expression> constraint) - { - ConstraintType type; - - switch (constraint.Body.NodeType) - { - case ExpressionType.Equal: - type = ConstraintType.EqualTo; break; - - case ExpressionType.LessThanOrEqual: - type = ConstraintType.LesserThanOrEqualTo; break; - - case ExpressionType.GreaterThanOrEqual: - type = ConstraintType.GreaterThanOrEqualTo; break; - - default: - throw new FormatException("Unexpected expression."); - } - - BinaryExpression b = constraint.Body as BinaryExpression; - var terms = new Dictionary(); - double value = 0; - parse(terms, b.Left, ref value); - - ConstantExpression c = b.Right as ConstantExpression; - value = (double)c.Value - value; - - List indices = new List(); - List scalars = new List(); - - foreach (var term in terms) - { - indices.Add(function.Variables[term.Key]); - scalars.Add(term.Value); - } - - NumberOfVariables = indices.Count; - VariablesAtIndices = indices.ToArray(); - CombinedAs = scalars.ToArray(); - ShouldBe = type; - Value = value; - } - - private static string parse(Dictionary terms, Expression expr, ref double value) - { - if (expr == null) - return null; - - BinaryExpression eb = expr as BinaryExpression; - MemberExpression em = expr as MemberExpression; - UnaryExpression eu = expr as UnaryExpression; - - if (em != null) // member expression - { - string term = em.Member.Name; - terms[term] = 1; - return term; - } - else if (eb != null) // binary expression - { - if (expr.NodeType == ExpressionType.Multiply) - { - // This could be either a constant times and expression or a quadratic member - ConstantExpression a = eb.Left as ConstantExpression ?? eb.Right as ConstantExpression; - MemberExpression m = eb.Left as MemberExpression ?? eb.Right as MemberExpression; - UnaryExpression u = eb.Left as UnaryExpression ?? eb.Right as UnaryExpression; - - if (a != null) - { - // This is a constant times an expression - double scalar = (double)a.Value; - - string term = parse(terms, (Expression)m ?? (Expression)u, ref value); - terms[term] = scalar; - - return term; - } - else throw new FormatException("Unexpected expression."); - } - else if (expr.NodeType == ExpressionType.Add) - { - // This could be an expression + term, a term + expression or an expression + expression - BinaryExpression lb = eb.Left as BinaryExpression; - MemberExpression lm = eb.Left as MemberExpression; - UnaryExpression lu = eb.Left as UnaryExpression; - ConstantExpression lc = eb.Left as ConstantExpression; - - BinaryExpression rb = eb.Right as BinaryExpression; - MemberExpression rm = eb.Right as MemberExpression; - ConstantExpression rc = eb.Right as ConstantExpression; - - if (lb != null) - { - parse(terms, lb, ref value); - } - else if (lm != null) - { - terms[lm.Member.Name] = 1; - } - else if (lu != null) - { - parse(terms, lu, ref value); - } - else if (lc != null) - { - value += (double)lc.Value; - } - else throw new FormatException("Unexpected expression."); - - if (rb != null) - { - parse(terms, rb, ref value); - } - else if (rm != null) - { - terms[rm.Member.Name] = 1; - } - else if (rc != null) - { - value += (double)rc.Value; - } - else throw new FormatException("Unexpected expression."); - } - else if (expr.NodeType == ExpressionType.Subtract) - { - // This could be an expression - term, a term - expression or an expression - expression - BinaryExpression lb = eb.Left as BinaryExpression; - MemberExpression lm = eb.Left as MemberExpression; - UnaryExpression lu = eb.Left as UnaryExpression; - - BinaryExpression rb = eb.Right as BinaryExpression; - MemberExpression rm = eb.Right as MemberExpression; - ConstantExpression rc = eb.Right as ConstantExpression; - - if (lb != null) - parse(terms, lb, ref value); - else if (lm != null) - terms[lm.Member.Name] = 1; - else if (lu != null) - parse(terms, lu, ref value); - else throw new FormatException("Unexpected expression."); - - if (rb != null) - { - var term = parse(terms, rb, ref value); - terms[term] = -terms[term]; - } - else if (rm != null) - { - terms[rm.Member.Name] = -1; - } - else if (rc != null) - { - value -= (double)rc.Value; - } - else throw new FormatException("Unexpected expression."); - } - } - else if (eu != null) // unary expression - { - if (expr.NodeType == ExpressionType.UnaryPlus) - { - BinaryExpression lb = eu.Operand as BinaryExpression; - MemberExpression lm = eu.Operand as MemberExpression; - ConstantExpression lc = eu.Operand as ConstantExpression; - - if (lm != null) - { - terms[lm.Member.Name] = 1; - } - else if (lb != null) - { - parse(terms, lb, ref value); - } - else if (lc != null) - { - value += (double)lc.Value; - } - else throw new FormatException("Unexpected expression."); - } - else if (expr.NodeType == ExpressionType.Negate) - { - BinaryExpression lb = eu.Operand as BinaryExpression; - MemberExpression lm = eu.Operand as MemberExpression; - ConstantExpression lc = eu.Operand as ConstantExpression; - - if (lm != null) - { - terms[lm.Member.Name] = -1; - } - else if (lb != null) - { - var term = parse(terms, lb, ref value); - terms[term] = -terms[term]; - } - else if (lc != null) - { - value -= (double)lc.Value; - } - else throw new FormatException("Unexpected expression."); - } - else throw new FormatException("Unexpected expression."); - } - else throw new FormatException("Unexpected expression."); - - return null; - } - - - /// - /// Gets the left hand side of the constraint equation. - /// - /// - public Func Function { get; private set; } - - /// - /// Gets the gradient of the left hand side of the constraint equation. - /// - /// - public Func Gradient { get; private set; } - - } -} + using System.Text.RegularExpressions; + + /// + /// Constraint type. + /// + /// + public enum ConstraintType + { + /// + /// Equality constraint. + /// + /// + EqualTo = 0, + + /// + /// Inequality constraint specifying a greater than or equal to relationship. + /// + /// + GreaterThanOrEqualTo, + + /// + /// Inequality constraint specifying a lesser than or equal to relationship. + /// + /// + LesserThanOrEqualTo, + } + + /// + /// Constraint with only linear terms. + /// + /// + public class LinearConstraint : IConstraint + { + private int[] indices; + private double[] scalars; + + /// + /// Gets the number of variables in the constraint. + /// + /// + public int NumberOfVariables { get; private set; } + + /// + /// Gets the index of the variables (in respective to the + /// object function index) of the variables participating + /// in this constraint. + /// + /// + public int[] VariablesAtIndices + { + get { return indices; } + set + { + if (value == null) + throw new ArgumentNullException("value"); + + if (value.Length != NumberOfVariables) + throw new DimensionMismatchException("value"); + + this.indices = value; + } + } + + /// + /// Gets the scalar coefficients combining the + /// variables specified by the constraints. + /// + public double[] CombinedAs + { + get { return scalars; } + set + { + if (value == null) + throw new ArgumentNullException("value"); + + if (value.Length != NumberOfVariables) + throw new DimensionMismatchException("value"); + + this.scalars = value; + } + } + + /// + /// Gets the type of the constraint. + /// + /// + public ConstraintType ShouldBe { get; set; } + + /// + /// Gets the value to be compared to the combined values + /// of the variables. + /// + /// + public double Value { get; set; } + + /// + /// Gets the violation tolerance for the constraint. Equality + /// constraints should set this to a small positive value. + /// + /// + public double Tolerance { get; set; } + + /// + /// Constructs a new linear constraint. + /// + /// + /// The number of variables in the constraint. + /// + public LinearConstraint(int numberOfVariables) + { + this.NumberOfVariables = numberOfVariables; + this.indices = Matrix.Indices(0, numberOfVariables); + this.scalars = Matrix.Vector(numberOfVariables, 1.0); + this.ShouldBe = ConstraintType.GreaterThanOrEqualTo; + + this.Function = compute; + this.Gradient = gradient; + } + + /// + /// Constructs a new linear constraint. + /// + /// + /// The scalar coefficients specifying + /// how variables should be combined in the constraint. + /// + public LinearConstraint(params double[] coefficients) + { + this.NumberOfVariables = coefficients.Length; + this.indices = Matrix.Indices(0, coefficients.Length); + this.CombinedAs = coefficients; + this.ShouldBe = ConstraintType.GreaterThanOrEqualTo; + + this.Function = compute; + this.Gradient = gradient; + } + + /// + /// Constructs a new linear constraint. + /// + /// + /// The objective function to which + /// this constraint refers to. + /// A + /// specifying this constraint, such as "ax + b = c". + /// The culture information specifying how + /// numbers written in the should + /// be parsed. Default is CultureInfo.InvariantCulture. + /// + public LinearConstraint(IObjectiveFunction function, string constraint, CultureInfo format) + { + parseString(function, constraint, format); + + this.Function = compute; + this.Gradient = gradient; + } + + /// + /// Constructs a new linear constraint. + /// + /// + /// The objective function to which + /// this constraint refers to. + /// A + /// specifying this constraint, such as "ax + b = c". + /// + public LinearConstraint(IObjectiveFunction function, string constraint) + : this(function, constraint, CultureInfo.InvariantCulture) + { + } + + /// + /// Constructs a new linear constraint. + /// + /// + /// The objective function to which this + /// constraint refers to. + /// A specifying + /// this constraint in the form of a lambda expression. + /// + public LinearConstraint(IObjectiveFunction function, Expression> constraint) + { + parseExpression(function, constraint); + + this.Function = compute; + this.Gradient = gradient; + } + + /// + /// Gets how much the constraint is being violated. + /// + /// + /// The function point. + /// + /// + /// How much the constraint is being violated at the given point. Positive + /// value means the constraint is not being violated with the returned slack, + /// while a negative value means the constraint is being violated by the returned + /// amount. + /// + /// + public double GetViolation(double[] input) + { + double fx = 0; + + for (int i = 0; i < indices.Length; i++) + { + double x = input[indices[i]]; + double a = CombinedAs[i]; + + fx += x * a; + } + + switch (ShouldBe) + { + case ConstraintType.EqualTo: + return Math.Abs(fx - Value); + + case ConstraintType.GreaterThanOrEqualTo: + return fx - Value; + + case ConstraintType.LesserThanOrEqualTo: + return Value - fx; + } + + throw new NotSupportedException(); + } + + /// + /// Gets whether this constraint is being violated + /// (within the current tolerance threshold). + /// + /// + /// The function point. + /// + /// True if the constraint is being violated, false otherwise. + /// + public bool IsViolated(double[] input) + { + return GetViolation(input) < -Tolerance; + } + + /// + /// Attempts to create a + /// from a representation. + /// + /// + /// The string containing the constraint in textual form. + /// The objective function to which this constraint refers to. + /// The resulting constraint, if it could be parsed. + /// + /// true if the function could be parsed + /// from the string, false otherwise. + /// + public static bool TryParse(string str, + IObjectiveFunction function, out LinearConstraint constraint) + { + return TryParse(str, CultureInfo.InvariantCulture, function, out constraint); + } + + /// + /// Attempts to create a + /// from a representation. + /// + /// + /// The string containing the constraint in textual form. + /// The objective function to which this constraint refers to. + /// The resulting constraint, if it could be parsed. + /// The culture information specifying how + /// numbers written in the should + /// be parsed. Default is CultureInfo.InvariantCulture. + /// + /// true if the function could be parsed + /// from the string, false otherwise. + /// + public static bool TryParse(string str, CultureInfo culture, + IObjectiveFunction function, out LinearConstraint constraint) + { + // TODO: implement this method without the try-catch block. + + try + { + constraint = new LinearConstraint(function, str, culture); + } + catch (FormatException) + { + constraint = null; + return false; + } + + return true; + } + + private double compute(double[] input) + { + double sum = 0; + + for (int i = 0; i < indices.Length; i++) + { + double x = input[indices[i]]; + double a = CombinedAs[i]; + + sum += x * a; + } + + return sum; + } + + private double[] gradient(double[] x) + { + return CombinedAs; + } + + + private void parseString(IObjectiveFunction function, string constraint, CultureInfo culture) + { + if (String.IsNullOrEmpty(constraint)) + throw new FormatException("Constraint is empty."); + + string f = constraint.Replace("*", String.Empty).Replace(" ", String.Empty); + + if (f[0] != '-' || f[0] != '+') + f = f.Insert(0, "+"); + + ConstraintType type; + + string lhs, rhs; + + if (f.Contains(">=")) + type = ConstraintType.GreaterThanOrEqualTo; + else if (f.Contains("<=")) + type = ConstraintType.LesserThanOrEqualTo; + else if (f.Contains("=")) + type = ConstraintType.EqualTo; + else + throw new FormatException("Invalid constraint type."); + + + + var terms = new Dictionary(); + + string separator = culture.NumberFormat.NumberDecimalSeparator; + + Regex r = new Regex(@"[\-\+][\s]*(\d*\" + separator + @"{0,1}\d+)?[\s]*([a-zA-Z])*"); + Regex number = new Regex(@"\d*\" + separator + @"{0,1}\d+"); + Regex symbol = new Regex(@"[a-zA-Z]"); + Regex comp = new Regex(@"(>=|<=|=)"); + + + var sides = comp.Split(f); + lhs = sides[0]; + rhs = sides[2]; + + double value = Double.Parse(rhs, culture); + + MatchCollection matches = r.Matches(lhs, 0); + + foreach (Match m in matches) + { + string term = m.Value; + + double scalar = (term[0] == '-') ? -1 : 1; + + // Extract value + MatchCollection coeff = number.Matches(term); + + foreach (Match c in coeff) + scalar *= Double.Parse(c.Value, culture); + + // Extract symbols + MatchCollection symbols = symbol.Matches(term); + + if (symbols.Count == 1) + { + terms.Add(symbols[0].Value, scalar); + } + else + { + if (coeff.Count == 1) + value -= scalar; + else if (term != "+") + throw new FormatException("Unexpected expression."); + } + } + + List indices = new List(); + List scalars = new List(); + + foreach (var term in terms) + { + indices.Add(function.Variables[term.Key]); + scalars.Add(term.Value); + } + + NumberOfVariables = indices.Count; + VariablesAtIndices = indices.ToArray(); + CombinedAs = scalars.ToArray(); + ShouldBe = type; + Value = value; + } + + private void parseExpression(IObjectiveFunction function, Expression> constraint) + { + ConstraintType type; + + switch (constraint.Body.NodeType) + { + case ExpressionType.Equal: + type = ConstraintType.EqualTo; break; + + case ExpressionType.LessThanOrEqual: + type = ConstraintType.LesserThanOrEqualTo; break; + + case ExpressionType.GreaterThanOrEqual: + type = ConstraintType.GreaterThanOrEqualTo; break; + + default: + throw new FormatException("Unexpected expression."); + } + + BinaryExpression b = constraint.Body as BinaryExpression; + var terms = new Dictionary(); + double value = 0; + parse(terms, b.Left, ref value); + + ConstantExpression c = b.Right as ConstantExpression; + value = (double)c.Value - value; + + List indices = new List(); + List scalars = new List(); + + foreach (var term in terms) + { + indices.Add(function.Variables[term.Key]); + scalars.Add(term.Value); + } + + NumberOfVariables = indices.Count; + VariablesAtIndices = indices.ToArray(); + CombinedAs = scalars.ToArray(); + ShouldBe = type; + Value = value; + } + + private static string parse(Dictionary terms, Expression expr, ref double value) + { + if (expr == null) + return null; + + BinaryExpression eb = expr as BinaryExpression; + MemberExpression em = expr as MemberExpression; + UnaryExpression eu = expr as UnaryExpression; + + if (em != null) // member expression + { + string term = em.Member.Name; + terms[term] = 1; + return term; + } + else if (eb != null) // binary expression + { + if (expr.NodeType == ExpressionType.Multiply) + { + // This could be either a constant times and expression or a quadratic member + ConstantExpression a = eb.Left as ConstantExpression ?? eb.Right as ConstantExpression; + MemberExpression m = eb.Left as MemberExpression ?? eb.Right as MemberExpression; + UnaryExpression u = eb.Left as UnaryExpression ?? eb.Right as UnaryExpression; + + if (a != null) + { + // This is a constant times an expression + double scalar = (double)a.Value; + + string term = parse(terms, (Expression)m ?? (Expression)u, ref value); + terms[term] = scalar; + + return term; + } + else throw new FormatException("Unexpected expression."); + } + else if (expr.NodeType == ExpressionType.Add) + { + // This could be an expression + term, a term + expression or an expression + expression + BinaryExpression lb = eb.Left as BinaryExpression; + MemberExpression lm = eb.Left as MemberExpression; + UnaryExpression lu = eb.Left as UnaryExpression; + ConstantExpression lc = eb.Left as ConstantExpression; + + BinaryExpression rb = eb.Right as BinaryExpression; + MemberExpression rm = eb.Right as MemberExpression; + ConstantExpression rc = eb.Right as ConstantExpression; + + if (lb != null) + { + parse(terms, lb, ref value); + } + else if (lm != null) + { + terms[lm.Member.Name] = 1; + } + else if (lu != null) + { + parse(terms, lu, ref value); + } + else if (lc != null) + { + value += (double)lc.Value; + } + else throw new FormatException("Unexpected expression."); + + if (rb != null) + { + parse(terms, rb, ref value); + } + else if (rm != null) + { + terms[rm.Member.Name] = 1; + } + else if (rc != null) + { + value += (double)rc.Value; + } + else throw new FormatException("Unexpected expression."); + } + else if (expr.NodeType == ExpressionType.Subtract) + { + // This could be an expression - term, a term - expression or an expression - expression + BinaryExpression lb = eb.Left as BinaryExpression; + MemberExpression lm = eb.Left as MemberExpression; + UnaryExpression lu = eb.Left as UnaryExpression; + + BinaryExpression rb = eb.Right as BinaryExpression; + MemberExpression rm = eb.Right as MemberExpression; + ConstantExpression rc = eb.Right as ConstantExpression; + + if (lb != null) + parse(terms, lb, ref value); + else if (lm != null) + terms[lm.Member.Name] = 1; + else if (lu != null) + parse(terms, lu, ref value); + else throw new FormatException("Unexpected expression."); + + if (rb != null) + { + var term = parse(terms, rb, ref value); + terms[term] = -terms[term]; + } + else if (rm != null) + { + terms[rm.Member.Name] = -1; + } + else if (rc != null) + { + value -= (double)rc.Value; + } + else throw new FormatException("Unexpected expression."); + } + } + else if (eu != null) // unary expression + { + if (expr.NodeType == ExpressionType.UnaryPlus) + { + BinaryExpression lb = eu.Operand as BinaryExpression; + MemberExpression lm = eu.Operand as MemberExpression; + ConstantExpression lc = eu.Operand as ConstantExpression; + + if (lm != null) + { + terms[lm.Member.Name] = 1; + } + else if (lb != null) + { + parse(terms, lb, ref value); + } + else if (lc != null) + { + value += (double)lc.Value; + } + else throw new FormatException("Unexpected expression."); + } + else if (expr.NodeType == ExpressionType.Negate) + { + BinaryExpression lb = eu.Operand as BinaryExpression; + MemberExpression lm = eu.Operand as MemberExpression; + ConstantExpression lc = eu.Operand as ConstantExpression; + + if (lm != null) + { + terms[lm.Member.Name] = -1; + } + else if (lb != null) + { + var term = parse(terms, lb, ref value); + terms[term] = -terms[term]; + } + else if (lc != null) + { + value -= (double)lc.Value; + } + else throw new FormatException("Unexpected expression."); + } + else throw new FormatException("Unexpected expression."); + } + else throw new FormatException("Unexpected expression."); + + return null; + } + + + /// + /// Gets the left hand side of the constraint equation. + /// + /// + public Func Function { get; private set; } + + /// + /// Gets the gradient of the left hand side of the constraint equation. + /// + /// + public Func Gradient { get; private set; } + + } +} diff --git a/Sources/Accord.Math/Optimization/Constrained/Constraints/NonlinearConstraint.cs b/Sources/Accord.Math/Optimization/Constrained/Constraints/NonlinearConstraint.cs index fa2dcaca0..5e8622767 100644 --- a/Sources/Accord.Math/Optimization/Constrained/Constraints/NonlinearConstraint.cs +++ b/Sources/Accord.Math/Optimization/Constrained/Constraints/NonlinearConstraint.cs @@ -1,443 +1,504 @@ -// Accord Math Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Math.Optimization -{ - using System; - using System.Collections.Generic; - using System.Linq; - using System.Linq.Expressions; - using System.Text.RegularExpressions; - using System.Text; - using System.Collections.ObjectModel; - - /// - /// Constraint with only linear terms. - /// - /// - public class NonlinearConstraint : IConstraint - { - - /// - /// Gets the number of variables in the constraint. - /// - /// - public int NumberOfVariables { get; private set; } - - /// - /// Gets the left hand side of - /// the constraint equation. - /// - /// - public Func Function { get; private set; } - - /// - /// Gets the gradient of the left hand - /// side of the constraint equation. - /// - /// - public Func Gradient { get; private set; } - - /// - /// Gets how much the constraint is being violated. - /// - /// - /// The function point. - /// - /// - /// How much the constraint is being violated at the given point. Positive - /// value means the constraint is not being violated with the returned slack, - /// while a negative value means the constraint is being violated by the returned - /// amount. - /// - /// - public double GetViolation(double[] input) - { - double fx = Function(input); - - switch (ShouldBe) - { - case ConstraintType.EqualTo: - return Math.Abs(fx - Value); - - case ConstraintType.GreaterThanOrEqualTo: - return fx - Value; - - case ConstraintType.LesserThanOrEqualTo: - return Value - fx; - } - - throw new NotSupportedException(); - } - - /// - /// Gets the type of the constraint. - /// - /// - public ConstraintType ShouldBe { get; private set; } - - /// - /// Gets the value in the right hand - /// side of the constraint equation. - /// - /// - public double Value { get; private set; } - - /// - /// Gets the violation tolerance for the constraint. Equality - /// constraints should set this to a small positive value. - /// - /// - public double Tolerance { get; set; } - -#if !NET35 - /// - /// Constructs a new nonlinear constraint. - /// - /// - /// The objective function to which this constraint refers. - /// A lambda expression defining the left hand side of the constraint equation. - /// A lambda expression defining the gradient of the - /// left hand side of the constraint equation. - /// How the left hand side of the constraint - /// should be compared to the given . - /// The right hand side of the constraint equation. - /// The tolerance for violations of the constraint. Equality - /// constraints should set this to a small positive value. Default is 0. - /// - public NonlinearConstraint(IObjectiveFunction objective, - Expression> function, ConstraintType shouldBe, double value, - Expression> gradient = null, double withinTolerance = 0.0) - { - this.NumberOfVariables = objective.NumberOfVariables; - this.ShouldBe = shouldBe; - - // Generate lambda functions - var func = ExpressionParser.Replace(function, objective.Variables); - this.Function = func.Compile(); - this.Value = value; - this.Tolerance = withinTolerance; - - if (gradient != null) - { - var grad = ExpressionParser.Replace(gradient, objective.Variables); - this.Gradient = grad.Compile(); - - int n = NumberOfVariables; - double[] probe = new double[n]; - double[] g = Gradient(probe); - - if (g.Length != n) - { - throw new DimensionMismatchException("gradient", - "The length of the gradient vector must match the number of variables in the objective function."); - } - } - } -#endif - - /// - /// Constructs a new nonlinear constraint. - /// - /// - /// The objective function to which this constraint refers. - /// A lambda expression defining the left hand side of the - /// constraint equation. - /// How the left hand side of the constraint should be - /// compared to the given . - /// The right hand side of the constraint equation. - /// - public NonlinearConstraint(IObjectiveFunction objective, - Func function, ConstraintType shouldBe, double value) - { - int n = objective.NumberOfVariables; - - this.Create(objective.NumberOfVariables, function, shouldBe, value, null, 0.0); - } - - /// - /// Constructs a new nonlinear constraint. - /// - /// - /// The objective function to which this constraint refers. - /// A lambda expression defining the left hand side of the - /// constraint equation. - /// A lambda expression defining the gradient of the - /// left hand side of the constraint equation. - /// How the left hand side of the constraint should be - /// compared to the given . - /// The right hand side of the constraint equation. - /// - public NonlinearConstraint(IObjectiveFunction objective, - Func function, ConstraintType shouldBe, double value, - Func gradient) - { - int n = objective.NumberOfVariables; - - this.Create(objective.NumberOfVariables, function, shouldBe, value, gradient, 0.0); - } - - /// - /// Constructs a new nonlinear constraint. - /// - /// - /// The number of variables in the constraint. - /// A lambda expression defining the left hand side of the constraint equation. - /// How the left hand side of the constraint should be compared to - /// the given . Default is . - /// The right hand side of the constraint equation. - /// - public NonlinearConstraint(int numberOfVariables, - Func function, ConstraintType shouldBe, double value) - { - this.Create(numberOfVariables, function, shouldBe, value, null, 0.0); - } - - /// - /// Constructs a new nonlinear constraint. - /// - /// - /// The objective function to which this constraint refers. - /// A boolean lambda expression expression the constraint. Please - /// see examples for details. - /// - /// - /// - /// - /// - public NonlinearConstraint(IObjectiveFunction objective, Expression> constraint) - { - int n = objective.NumberOfVariables; - - Func function; - ConstraintType shouldBe; - double value; - - parse(constraint, out function, out shouldBe, out value); - - this.Create(objective.NumberOfVariables, function, shouldBe, value, null, 0.0); - } - - /// - /// Constructs a new nonlinear constraint. - /// - /// - /// The number of variables in the constraint. - /// A boolean lambda expression expression the constraint. Please - /// see examples for details. - /// - /// - /// - /// - /// - public NonlinearConstraint(int numberOfVariables, Expression> constraint) - { - Func function; - ConstraintType shouldBe; - double value; - - parse(constraint, out function, out shouldBe, out value); - - this.Create(numberOfVariables, function, shouldBe, value, null, 0.0); - } - - - - - private static void parse(Expression> constraint, - out Func function, out ConstraintType shouldBe, out double value) - { - var expression = constraint.Body as BinaryExpression; - - var comparisonType = expression.NodeType; - - switch (comparisonType) - { - case ExpressionType.LessThanOrEqual: - shouldBe = ConstraintType.LesserThanOrEqualTo; - break; - - case ExpressionType.GreaterThanOrEqual: - shouldBe = ConstraintType.GreaterThanOrEqualTo; - break; - - case ExpressionType.Equal: - shouldBe = ConstraintType.EqualTo; - break; - - default: - throw new NotSupportedException(comparisonType + " is not supported."); - } - - var left = expression.Left; - var right = expression.Right as ConstantExpression; - - var functionExpression = Expression.Lambda(left, constraint.Parameters.ToArray()); - - function = functionExpression.Compile() as Func; - - value = (Double)right.Value; - } - - /// - /// Constructs a new nonlinear constraint. - /// - /// - /// The objective function to which this constraint refers. - /// A lambda expression defining the left hand side of the constraint equation. - /// - public NonlinearConstraint(IObjectiveFunction objective, Func function) - { - int n = objective.NumberOfVariables; - - this.Create(objective.NumberOfVariables, function, ConstraintType.GreaterThanOrEqualTo, 0.0, null, 0.0); - } - - /// - /// Constructs a new nonlinear constraint. - /// - /// - /// The objective function to which this constraint refers. - /// A lambda expression defining the left hand side of the - /// constraint equation. - /// A lambda expression defining the gradient of the - /// left hand side of the constraint equation. - /// - public NonlinearConstraint(IObjectiveFunction objective, - Func function, - Func gradient) - { - int n = objective.NumberOfVariables; - - this.Create(objective.NumberOfVariables, function, - ConstraintType.GreaterThanOrEqualTo, 0.0, gradient, 0.0); - } - - /// - /// Constructs a new nonlinear constraint. - /// - /// - /// The number of variables in the constraint. - /// A lambda expression defining the left hand side of the - /// constraint equation. - /// A lambda expression defining the gradient of the - /// left hand side of the constraint equation. - /// - public NonlinearConstraint(int numberOfVariables, - Func function, - Func gradient) - { - this.Create(numberOfVariables, function, - ConstraintType.GreaterThanOrEqualTo, 0.0, gradient, 0.0); - } - - /// - /// Constructs a new nonlinear constraint. - /// - /// - /// The number of variables in the constraint. - /// A lambda expression defining the left hand side of the - /// constraint equation. - /// - public NonlinearConstraint(int numberOfVariables, Func function) - { - this.Create(numberOfVariables, function, ConstraintType.GreaterThanOrEqualTo, 0.0, null, 0.0); - } - - /// - /// Constructs a new nonlinear constraint. - /// - /// - /// The objective function to which this constraint refers. - /// A lambda expression defining the left hand side of the constraint equation. - /// A lambda expression defining the gradient of the - /// left hand side of the constraint equation. - /// How the left hand side of the constraint should be compared to the given . - /// The right hand side of the constraint equation. - /// The tolerance for violations of the constraint. Equality - /// constraints should set this to a small positive value. Default is 0. - /// - public NonlinearConstraint(IObjectiveFunction objective, - Func function, ConstraintType shouldBe, double value, - Func gradient, double withinTolerance = 0.0) - { - this.Create(objective.NumberOfVariables, function, shouldBe, value, gradient, withinTolerance); - } - - - /// - /// Constructs a new nonlinear constraint. - /// - /// - /// The number of variables in the constraint. - /// A lambda expression defining the left hand side of the constraint equation. - /// A lambda expression defining the gradient of the - /// left hand side of the constraint equation. - /// How the left hand side of the constraint should be compared to the given . - /// The right hand side of the constraint equation. - /// The tolerance for violations of the constraint. Equality - /// constraints should set this to a small positive value. Default is 0. - /// - public NonlinearConstraint(int numberOfVariables, - Func function, ConstraintType shouldBe, double value, - Func gradient, double withinTolerance = 0.0) - { - this.Create(numberOfVariables, function, shouldBe, value, gradient, withinTolerance); - } - - /// - /// Creates an empty nonlinear constraint. - /// - /// - protected NonlinearConstraint() - { - } - - /// - /// Creates a nonlinear constraint. - /// - /// - protected void Create(int numberOfVariables, - Func function, ConstraintType shouldBe, double value, - Func gradient, double tolerance) - { - - if (gradient != null) - { - double[] probe = new double[numberOfVariables]; - double[] g = gradient(probe); - - if (g.Length != numberOfVariables) - throw new DimensionMismatchException("gradient", - "The length of the gradient vector must match the number of variables in the objective function."); - } - - this.NumberOfVariables = numberOfVariables; - this.ShouldBe = shouldBe; - this.Value = value; - this.Tolerance = tolerance; - - this.Function = function; - this.Gradient = gradient; - } - } -} +// Accord Math Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Math.Optimization +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Linq.Expressions; + using System.Text.RegularExpressions; + using System.Text; + using System.Collections.ObjectModel; + + /// + /// Constraint with only linear terms. + /// + /// + public class NonlinearConstraint : IConstraint, IFormattable + { + + private const double DEFAULT_TOL = 1e-8; + + /// + /// Gets the number of variables in the constraint. + /// + /// + public int NumberOfVariables { get; private set; } + + /// + /// Gets the left hand side of + /// the constraint equation. + /// + /// + public Func Function { get; private set; } + + /// + /// Gets the gradient of the left hand + /// side of the constraint equation. + /// + /// + public Func Gradient { get; private set; } + + /// + /// Gets how much the constraint is being violated. + /// + /// + /// The function point. + /// + /// + /// How much the constraint is being violated at the given point. Positive + /// value means the constraint is not being violated with the returned slack, + /// while a negative value means the constraint is being violated by the returned + /// amount. + /// + /// + public double GetViolation(double[] input) + { + double fx = Function(input); + + switch (ShouldBe) + { + case ConstraintType.EqualTo: + return Math.Abs(fx - Value); + + case ConstraintType.GreaterThanOrEqualTo: + return fx - Value; + + case ConstraintType.LesserThanOrEqualTo: + return Value - fx; + } + + throw new NotSupportedException(); + } + + /// + /// Gets whether this constraint is being violated + /// (within the current tolerance threshold). + /// + /// + /// The function point. + /// + /// True if the constraint is being violated, false otherwise. + /// + public bool IsViolated(double[] input) + { + return GetViolation(input) < -Tolerance; + } + + /// + /// Gets the type of the constraint. + /// + /// + public ConstraintType ShouldBe { get; private set; } + + /// + /// Gets the value in the right hand side of + /// the constraint equation. Default is 0. + /// + /// + public double Value { get; private set; } + + /// + /// Gets the violation tolerance for the constraint. Equality + /// constraints should set this to a small positive value. + /// Default is 1e-8. + /// + /// + public double Tolerance { get; set; } + +#if !NET35 + /// + /// Constructs a new nonlinear constraint. + /// + /// + /// The objective function to which this constraint refers. + /// A lambda expression defining the left hand side of the constraint equation. + /// A lambda expression defining the gradient of the + /// left hand side of the constraint equation. + /// How the left hand side of the constraint + /// should be compared to the given . + /// The right hand side of the constraint equation. + /// The tolerance for violations of the constraint. Equality + /// constraints should set this to a small positive value. Default is 1e-8. + /// + public NonlinearConstraint(IObjectiveFunction objective, + Expression> function, ConstraintType shouldBe, double value, + Expression> gradient = null, double withinTolerance = DEFAULT_TOL) + { + this.NumberOfVariables = objective.NumberOfVariables; + this.ShouldBe = shouldBe; + + // Generate lambda functions + var func = ExpressionParser.Replace(function, objective.Variables); + this.Function = func.Compile(); + this.Value = value; + this.Tolerance = withinTolerance; + + if (gradient != null) + { + var grad = ExpressionParser.Replace(gradient, objective.Variables); + this.Gradient = grad.Compile(); + + int n = NumberOfVariables; + double[] probe = new double[n]; + double[] g = Gradient(probe); + + if (g.Length != n) + { + throw new DimensionMismatchException("gradient", + "The length of the gradient vector must match the number of variables in the objective function."); + } + } + } +#endif + + /// + /// Constructs a new nonlinear constraint. + /// + /// + /// The objective function to which this constraint refers. + /// A lambda expression defining the left hand side of the + /// constraint equation. + /// How the left hand side of the constraint should be + /// compared to the given . + /// The right hand side of the constraint equation. Default is 0. + /// + public NonlinearConstraint(IObjectiveFunction objective, + Func function, ConstraintType shouldBe, double value) + { + int n = objective.NumberOfVariables; + + this.Create(objective.NumberOfVariables, function, shouldBe, value, null, DEFAULT_TOL); + } + + /// + /// Constructs a new nonlinear constraint. + /// + /// + /// The objective function to which this constraint refers. + /// A lambda expression defining the left hand side of the + /// constraint equation. + /// A lambda expression defining the gradient of the + /// left hand side of the constraint equation. + /// How the left hand side of the constraint should be + /// compared to the given . + /// The right hand side of the constraint equation. Default is 0. + /// + public NonlinearConstraint(IObjectiveFunction objective, + Func function, ConstraintType shouldBe, double value, + Func gradient) + { + int n = objective.NumberOfVariables; + + this.Create(objective.NumberOfVariables, function, shouldBe, value, gradient, DEFAULT_TOL); + } + + /// + /// Constructs a new nonlinear constraint. + /// + /// + /// The number of variables in the constraint. + /// A lambda expression defining the left hand side of the constraint equation. + /// How the left hand side of the constraint should be compared to + /// the given . Default is . + /// The right hand side of the constraint equation. Default is 0. + /// + public NonlinearConstraint(int numberOfVariables, + Func function, ConstraintType shouldBe, double value) + { + this.Create(numberOfVariables, function, shouldBe, value, null, DEFAULT_TOL); + } + + /// + /// Constructs a new nonlinear constraint. + /// + /// + /// The objective function to which this constraint refers. + /// A boolean lambda expression expressing the constraint. Please + /// see examples for details. + /// + public NonlinearConstraint(IObjectiveFunction objective, + Expression> constraint) + { + int n = objective.NumberOfVariables; + + Func function; + ConstraintType shouldBe; + double value; + + parse(constraint, out function, out shouldBe, out value); + + this.Create(objective.NumberOfVariables, function, shouldBe, value, null, DEFAULT_TOL); + } + + /// + /// Constructs a new nonlinear constraint. + /// + /// + /// The number of variables in the constraint. + /// A boolean lambda expression expressing the constraint. Please + /// see examples for details. + /// + public NonlinearConstraint(int numberOfVariables, Expression> constraint) + { + Func function; + ConstraintType shouldBe; + double value; + + parse(constraint, out function, out shouldBe, out value); + + this.Create(numberOfVariables, function, shouldBe, value, null, DEFAULT_TOL); + } + + /// + /// Constructs a new nonlinear constraint. + /// + /// + /// The objective function to which this constraint refers. + /// A lambda expression defining the left hand side of the constraint. + /// + public NonlinearConstraint(IObjectiveFunction objective, Func function) + { + int n = objective.NumberOfVariables; + + this.Create(objective.NumberOfVariables, function, ConstraintType.GreaterThanOrEqualTo, 0.0, null, DEFAULT_TOL); + } + + /// + /// Constructs a new nonlinear constraint. + /// + /// + /// The objective function to which this constraint refers. + /// A lambda expression defining the left hand side of the + /// constraint equation. + /// A lambda expression defining the gradient of the + /// left hand side of the constraint equation.. + /// + public NonlinearConstraint(IObjectiveFunction objective, + Func function, + Func gradient) + { + int n = objective.NumberOfVariables; + + this.Create(objective.NumberOfVariables, function, + ConstraintType.GreaterThanOrEqualTo, 0.0, gradient, DEFAULT_TOL); + } + + /// + /// Constructs a new nonlinear constraint. + /// + /// + /// The number of variables in the constraint. + /// A lambda expression defining the left hand side of the + /// constraint equation. + /// A lambda expression defining the gradient of the + /// left hand side of the constraint equation. + /// How the left hand side of the constraint should be + /// compared to the given . + /// The right hand side of the constraint equation. Default is 0. + /// The tolerance for violations of the constraint. Equality + /// constraints should set this to a small positive value. Default is 1e-8. + /// + public NonlinearConstraint(int numberOfVariables, + Func function, + Func gradient, + ConstraintType shouldBe = ConstraintType.GreaterThanOrEqualTo, + double value = 0, double withinTolerance = DEFAULT_TOL) + { + this.Create(numberOfVariables, function, + shouldBe, value, gradient, withinTolerance); + } + + /// + /// Constructs a new nonlinear constraint. + /// + /// + /// The number of variables in the constraint. + /// A lambda expression defining the left hand side of the + /// constraint equation. + /// + public NonlinearConstraint(int numberOfVariables, Func function) + { + this.Create(numberOfVariables, function, ConstraintType.GreaterThanOrEqualTo, 0.0, null, DEFAULT_TOL); + } + + /// + /// Constructs a new nonlinear constraint. + /// + /// + /// The objective function to which this constraint refers. + /// A lambda expression defining the left hand side of the constraint equation. + /// A lambda expression defining the gradient of the + /// left hand side of the constraint equation. + /// How the left hand side of the constraint should be compared to the given . + /// The right hand side of the constraint equation. Default is 0. + /// The tolerance for violations of the constraint. Equality + /// constraints should set this to a small positive value. Default is 1e-8. + /// + public NonlinearConstraint(IObjectiveFunction objective, + Func function, ConstraintType shouldBe, double value, + Func gradient, double withinTolerance = DEFAULT_TOL) + { + this.Create(objective.NumberOfVariables, function, shouldBe, value, gradient, withinTolerance); + } + + + /// + /// Constructs a new nonlinear constraint. + /// + /// + /// The number of variables in the constraint. + /// A lambda expression defining the left hand side of the constraint equation. + /// A lambda expression defining the gradient of the + /// left hand side of the constraint equation. + /// How the left hand side of the constraint should be compared to the given . + /// The right hand side of the constraint equation. Default is 0. + /// The tolerance for violations of the constraint. Equality + /// constraints should set this to a small positive value. Default is 1e-8. + /// + public NonlinearConstraint(int numberOfVariables, + Func function, ConstraintType shouldBe, double value, + Func gradient, double withinTolerance = DEFAULT_TOL) + { + this.Create(numberOfVariables, function, shouldBe, value, gradient, withinTolerance); + } + + /// + /// Creates an empty nonlinear constraint. + /// + /// + protected NonlinearConstraint() + { + } + + /// + /// Creates a nonlinear constraint. + /// + /// + protected void Create(int numberOfVariables, + Func function, ConstraintType shouldBe, double value, + Func gradient, double tolerance) + { + + if (gradient != null) + { + double[] probe = new double[numberOfVariables]; + double[] g = gradient(probe); + + if (g.Length != numberOfVariables) + throw new DimensionMismatchException("gradient", + "The length of the gradient vector must match the number of variables in the objective function."); + } + + this.NumberOfVariables = numberOfVariables; + this.ShouldBe = shouldBe; + this.Value = value; + this.Tolerance = tolerance; + + this.Function = function; + this.Gradient = gradient; + } + + + + private static void parse(Expression> constraint, + out Func function, out ConstraintType shouldBe, out double value) + { + var expression = constraint.Body as BinaryExpression; + + var comparisonType = expression.NodeType; + + switch (comparisonType) + { + case ExpressionType.LessThanOrEqual: + shouldBe = ConstraintType.LesserThanOrEqualTo; + break; + + case ExpressionType.GreaterThanOrEqual: + shouldBe = ConstraintType.GreaterThanOrEqualTo; + break; + + case ExpressionType.Equal: + shouldBe = ConstraintType.EqualTo; + break; + + default: + throw new NotSupportedException(comparisonType + " is not supported."); + } + + var left = expression.Left; + var right = expression.Right as ConstantExpression; + + var functionExpression = Expression.Lambda(left, constraint.Parameters.ToArray()); + + function = functionExpression.Compile() as Func; + + value = (Double)right.Value; + } + + + /// + /// Returns a that represents this instance. + /// + /// + /// + /// A that represents this instance. + /// + /// + public override string ToString() + { + return ToString("G", System.Globalization.CultureInfo.CurrentCulture); + } + + /// + /// Returns a that represents this instance. + /// + /// + /// The format. + /// The format provider. + /// + /// + /// A that represents this instance. + /// + /// + public string ToString(string format, IFormatProvider formatProvider) + { + string v = Value.ToString(format, formatProvider); + string t = Tolerance.ToString(format, formatProvider); + + switch (ShouldBe) + { + case ConstraintType.EqualTo: + return String.Format(formatProvider, "g(x) == {0} (± {1})", v, t); + + case ConstraintType.GreaterThanOrEqualTo: + return String.Format(formatProvider, "g(x) >= {0} (± {1})", v, t); + + case ConstraintType.LesserThanOrEqualTo: + return String.Format("g(x) <= {0} (± {1})", v, t); + } + + return "g(x)"; + } + } +} diff --git a/Sources/Accord.Math/Tools.cs b/Sources/Accord.Math/Tools.cs index 9b56dc4a5..49740b11d 100644 --- a/Sources/Accord.Math/Tools.cs +++ b/Sources/Accord.Math/Tools.cs @@ -600,14 +600,17 @@ public static double TruncatedPower(double value, double degree) /// Fast inverse floating-point square root. /// /// - public unsafe static float InvSqrt(float f) - { - float xhalf = 0.5f * f; - Int32 i = *(Int32*)&f; - i = 0x5f375a86 - (i >> 1); - f = *(float*)&i; - f = f * (1.5f - xhalf * f * f); - return f; + public static float InvSqrt(float f) + { + unsafe + { + float xhalf = 0.5f * f; + Int32 i = *(Int32*)&f; + i = 0x5f375a86 - (i >> 1); + f = *(float*)&i; + f = f * (1.5f - xhalf * f * f); + return f; + } } diff --git a/Sources/Accord.Math/Transforms/FourierTransform2.cs b/Sources/Accord.Math/Transforms/FourierTransform2.cs index 9fc28bb38..093d3968b 100644 --- a/Sources/Accord.Math/Transforms/FourierTransform2.cs +++ b/Sources/Accord.Math/Transforms/FourierTransform2.cs @@ -48,17 +48,12 @@ // namespace Accord.Math.Transforms -{ - using AForge.Math; - using System; +{ + using AForge.Math; + using System; + using System.Numerics; using System.Runtime.CompilerServices; - // #if NET35 - using Complex = AForge.Math.Complex; - // #else - // using Complex = System.Numerics.Complex; - // #endif - /// /// Fourier Transform (for arbitrary size matrices). /// @@ -95,8 +90,8 @@ public static void DFT(Complex[] data, FourierTransform.Direction direction) // sum source elements for (int j = 0; j < n; j++) { - double re = data[j].Re(); - double im = data[j].Im(); + double re = data[j].Real; + double im = data[j].Imaginary; double cosw = Math.Cos(phim * j); double sinw = Math.Sin(phim * j); @@ -184,7 +179,7 @@ public static void FFT(Complex[] data, FourierTransform.Direction direction) if (direction == FourierTransform.Direction.Backward) { for (int i = 0; i < data.Length; i++) - data[i] = new Complex(data[i].Im(), data[i].Re()); + data[i] = new Complex(data[i].Imaginary, data[i].Real); } if ((n & (n - 1)) == 0) @@ -202,8 +197,8 @@ public static void FFT(Complex[] data, FourierTransform.Direction direction) { for (int i = 0; i < data.Length; i++) { - double im = data[i].Im(); - double re = data[i].Re(); + double im = data[i].Imaginary; + double re = data[i].Real; data[i] = new Complex(im / n, re / n); } } @@ -317,7 +312,7 @@ private static void IDFT(Complex[] data) return; for (int i = 0; i < data.Length; i++) - data[i] = new Complex(data[i].Im(), data[i].Re()); + data[i] = new Complex(data[i].Imaginary, data[i].Real); if ((n & (n - 1)) == 0) { @@ -332,8 +327,8 @@ private static void IDFT(Complex[] data) for (int i = 0; i < data.Length; i++) { - double im = data[i].Im(); - double re = data[i].Re(); + double im = data[i].Imaginary; + double re = data[i].Real; data[i] = new Complex(im, re); } } @@ -476,14 +471,14 @@ private static void TransformRadix2(Complex[] complex) for (int j = i, k = 0; j < i + halfsize; j++, k += tablestep) { int h = j + halfsize; - double re = complex[h].Re(); - double im = complex[h].Im(); + double re = complex[h].Real; + double im = complex[h].Imaginary; double tpre = +re * cosTable[k] + im * sinTable[k]; double tpim = -re * sinTable[k] + im * cosTable[k]; - double rej = complex[j].Re(); - double imj = complex[j].Im(); + double rej = complex[j].Real; + double imj = complex[j].Imaginary; complex[h] = new Complex(rej - tpre, imj - tpim); complex[j] = new Complex(rej + tpre, imj + tpim); @@ -573,8 +568,8 @@ private static void TransformBluestein(Complex[] data) for (int i = 0; i < data.Length; i++) { - double re = data[i].Re(); - double im = data[i].Im(); + double re = data[i].Real; + double im = data[i].Imaginary; areal[i] = +re * cosTable[i] + im * sinTable[i]; aimag[i] = -re * sinTable[i] + im * cosTable[i]; @@ -628,10 +623,10 @@ public static void Convolve(Complex[] x, Complex[] y, Complex[] result) for (int i = 0; i < x.Length; i++) { - double xreal = x[i].Re(); - double ximag = x[i].Im(); - double yreal = y[i].Re(); - double yimag = y[i].Im(); + double xreal = x[i].Real; + double ximag = x[i].Imaginary; + double yreal = y[i].Real; + double yimag = y[i].Imaginary; double re = xreal * yreal - ximag * yimag; double im = ximag * yreal + xreal * yimag; diff --git a/Sources/Accord.Math/Transforms/HilbertTransform.cs b/Sources/Accord.Math/Transforms/HilbertTransform.cs index 1de8bc05f..cd09056b4 100644 --- a/Sources/Accord.Math/Transforms/HilbertTransform.cs +++ b/Sources/Accord.Math/Transforms/HilbertTransform.cs @@ -1,175 +1,172 @@ -// Accord Math Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Math -{ - using System; - using AForge.Math; - - /// - /// Discrete Hilbert Transformation. - /// - /// - /// - /// - /// The discrete Hilbert transform is a transformation operating on the time - /// domain. It performs a 90 degree phase shift, shifting positive frequencies - /// by +90 degrees and negative frequencies by -90 degrees. It is useful to - /// create analytic representation of signals. - /// - /// - /// The Hilbert transform can be implemented efficiently by using the Fast - /// Fourier Transform. After transforming a signal from the time-domain to - /// the frequency domain, one can zero its negative frequency components and - /// revert the signal back to obtain the phase shifting. - /// - /// - /// By applying the Hilbert transform to a signal twice, the negative of - /// the original signal is recovered. - /// - /// - /// References: - /// - /// - /// Marple, S.L., "Computing the discrete-time analytic signal via FFT," IEEE - /// Transactions on Signal Processing, Vol. 47, No.9 (September 1999). Available on: - /// http://classes.engr.oregonstate.edu/eecs/winter2009/ece464/AnalyticSignal_Sept1999_SPTrans.pdf - /// - /// J. F. Culling, Online, cross-indexed dictionary of DSP terms. Available on: - /// http://www.cardiff.ac.uk/psych/home2/CullingJ/frames_dict.html - /// - /// - /// - /// - public static class HilbertTransform - { - /// - /// Performs the Fast Hilbert Transform over a double[] array. - /// - /// - public static void FHT(double[] data, FourierTransform.Direction direction) - { - int N = data.Length; - - - // Forward operation - if (direction == FourierTransform.Direction.Forward) - { - // Copy the input to a complex array which can be processed - // in the complex domain by the FFT - Complex[] cdata = new Complex[N]; - for (int i = 0; i < N; i++) - cdata[i].Re = data[i]; - - // Perform FFT - FourierTransform.FFT(cdata, FourierTransform.Direction.Forward); - - //double positive frequencies - for (int i = 1; i < (N/2); i++) - { - cdata[i].Re *= 2.0; - cdata[i].Im *= 2.0; - } - - // zero out negative frequencies - // (leaving out the dc component) - for (int i = (N/2)+1; i < N; i++) - { - cdata[i].Re = 0.0; - cdata[i].Im = 0.0; - } - - // Reverse the FFT - FourierTransform.FFT(cdata, FourierTransform.Direction.Backward); - - // Convert back to our initial double array - for (int i = 0; i < N; i++) - data[i] = cdata[i].Im; - } - - else // Backward operation - { - // The inverse Hilbert can be calculated by - // negating the transform and reapplying the - // transformation. - // - // H^–1{h(t)} = –H{h(t)} - - FHT(data, FourierTransform.Direction.Forward); - - for (int i = 0; i < data.Length; i++) - data[i] = -data[i]; - } - } - - - /// - /// Performs the Fast Hilbert Transform over a complex[] array. - /// - /// - public static void FHT(Complex[] data, FourierTransform.Direction direction) - { - int N = data.Length; - - // Forward operation - if (direction == FourierTransform.Direction.Forward) - { - // Makes a copy of the data so we don't lose the - // original information to build our final signal - Complex[] shift = (Complex[])data.Clone(); - - // Perform FFT - FourierTransform.FFT(shift, FourierTransform.Direction.Backward); - - //double positive frequencies - for (int i = 1; i < (N/2); i++) - { - shift[i].Re *= 2.0; - shift[i].Im *= 2.0; - } - // zero out negative frequencies - // (leaving out the dc component) - for (int i = (N/2)+1; i < N; i++) - { - shift[i].Re = 0.0; - shift[i].Im = 0.0; - } - - // Reverse the FFT - FourierTransform.FFT(shift, FourierTransform.Direction.Forward); - - // Put the Hilbert transform in the Imaginary part - // of the input signal, creating a Analytic Signal - for (int i = 0; i < N; i++) - data[i].Im = shift[i].Im; - } - - else // Backward operation - { - // Just discard the imaginary part - for (int i = 0; i < data.Length; i++) - data[i].Im = 0.0; - } - } - - } -} +// Accord Math Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Math +{ + using System; + using AForge.Math; + using System.Numerics; + + /// + /// Discrete Hilbert Transformation. + /// + /// + /// + /// + /// The discrete Hilbert transform is a transformation operating on the time + /// domain. It performs a 90 degree phase shift, shifting positive frequencies + /// by +90 degrees and negative frequencies by -90 degrees. It is useful to + /// create analytic representation of signals. + /// + /// + /// The Hilbert transform can be implemented efficiently by using the Fast + /// Fourier Transform. After transforming a signal from the time-domain to + /// the frequency domain, one can zero its negative frequency components and + /// revert the signal back to obtain the phase shifting. + /// + /// + /// By applying the Hilbert transform to a signal twice, the negative of + /// the original signal is recovered. + /// + /// + /// References: + /// + /// + /// Marple, S.L., "Computing the discrete-time analytic signal via FFT," IEEE + /// Transactions on Signal Processing, Vol. 47, No.9 (September 1999). Available on: + /// http://classes.engr.oregonstate.edu/eecs/winter2009/ece464/AnalyticSignal_Sept1999_SPTrans.pdf + /// + /// J. F. Culling, Online, cross-indexed dictionary of DSP terms. Available on: + /// http://www.cardiff.ac.uk/psych/home2/CullingJ/frames_dict.html + /// + /// + /// + /// + public static class HilbertTransform + { + /// + /// Performs the Fast Hilbert Transform over a double[] array. + /// + /// + public static void FHT(double[] data, FourierTransform.Direction direction) + { + int N = data.Length; + + + // Forward operation + if (direction == FourierTransform.Direction.Forward) + { + // Copy the input to a complex array which can be processed + // in the complex domain by the FFT + Complex[] cdata = new Complex[N]; + for (int i = 0; i < N; i++) + cdata[i] = new Complex(data[i], 0.0); + + // Perform FFT + FourierTransform.FFT(cdata, FourierTransform.Direction.Forward); + + //double positive frequencies + for (int i = 1; i < (N / 2); i++) + { + cdata[i] *= 2.0; + } + + // zero out negative frequencies + // (leaving out the dc component) + for (int i = (N / 2) + 1; i < N; i++) + { + cdata[i] = Complex.Zero; + } + + // Reverse the FFT + FourierTransform.FFT(cdata, FourierTransform.Direction.Backward); + + // Convert back to our initial double array + for (int i = 0; i < N; i++) + data[i] = cdata[i].Imaginary; + } + + else // Backward operation + { + // The inverse Hilbert can be calculated by + // negating the transform and reapplying the + // transformation. + // + // H^–1{h(t)} = –H{h(t)} + + FHT(data, FourierTransform.Direction.Forward); + + for (int i = 0; i < data.Length; i++) + data[i] = -data[i]; + } + } + + + /// + /// Performs the Fast Hilbert Transform over a complex[] array. + /// + /// + public static void FHT(Complex[] data, FourierTransform.Direction direction) + { + int N = data.Length; + + // Forward operation + if (direction == FourierTransform.Direction.Forward) + { + // Makes a copy of the data so we don't lose the + // original information to build our final signal + Complex[] shift = (Complex[])data.Clone(); + + // Perform FFT + FourierTransform.FFT(shift, FourierTransform.Direction.Backward); + + //double positive frequencies + for (int i = 1; i < (N / 2); i++) + { + shift[i] *= 2.0; + } + // zero out negative frequencies + // (leaving out the dc component) + for (int i = (N / 2) + 1; i < N; i++) + { + shift[i] = Complex.Zero; + } + + // Reverse the FFT + FourierTransform.FFT(shift, FourierTransform.Direction.Forward); + + // Put the Hilbert transform in the Imaginary part + // of the input signal, creating a Analytic Signal + for (int i = 0; i < N; i++) + data[i] = new Complex(data[i].Real, shift[i].Imaginary); + } + + else // Backward operation + { + // Just discard the imaginary part + for (int i = 0; i < data.Length; i++) + data[i] = new Complex(data[i].Real, 0.0); + } + } + + } +} diff --git a/Sources/Accord.Math/Vector/Vector.cs b/Sources/Accord.Math/Vector/Vector.cs index 6abfef361..007eaf2cd 100644 --- a/Sources/Accord.Math/Vector/Vector.cs +++ b/Sources/Accord.Math/Vector/Vector.cs @@ -113,20 +113,28 @@ public static void Sort(this T[] values, bool stable = false) /// Sorts the elements of an entire one-dimensional array using the given comparison. /// /// - public static void Sort(this T[] values, out int[] order, bool stable = false) + public static void Sort(this T[] values, out int[] order, bool stable = false, ComparerDirection direction = ComparerDirection.Ascending) where T : IComparable { if (!stable) { order = Matrix.Indices(values.Length); - Array.Sort(values, order); + if (direction == ComparerDirection.Ascending) + Array.Sort(values, order); + else + Array.Sort(values, order, new GeneralComparer(direction)); + return; } var keys = new KeyValuePair[values.Length]; for (var i = 0; i < values.Length; i++) keys[i] = new KeyValuePair(i, values[i]); - Array.Sort(keys, values, new StableComparer((a, b) => a.CompareTo(b))); + + if (direction == ComparerDirection.Ascending) + Array.Sort(keys, values, new StableComparer((a, b) => a.CompareTo(b))); + else + Array.Sort(keys, values, new StableComparer((a, b) => -a.CompareTo(b))); order = new int[values.Length]; for (int i = 0; i < keys.Length; i++) diff --git a/Sources/Accord.NET.LGPL.sln b/Sources/Accord.NET.LGPL.sln index 3545525c6..49e27883e 100644 --- a/Sources/Accord.NET.LGPL.sln +++ b/Sources/Accord.NET.LGPL.sln @@ -14,15 +14,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ..\Contributors.txt = ..\Contributors.txt ..\Copyright.txt = ..\Copyright.txt ..\License.txt = ..\License.txt + ..\README.txt = ..\README.txt ..\Release notes.txt = ..\Release notes.txt EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Controls.Audio", "Accord.Controls.Audio\Accord.Controls.Audio.csproj", "{E0B826AC-2A51-41EC-9F09-561CA14A82BB}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.DirectSound", "Accord.DirectSound\Accord.DirectSound.csproj", "{456DB2E8-745A-4F87-A2BD-C43CF8677770}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Audio.Formats", "Accord.Audio.Formats\Accord.Audio.Formats.csproj", "{EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Audio", "Accord.Audio\Accord.Audio.csproj", "{E7B65F08-82F1-438F-847A-2AAC2BEC9AC0}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Audition", "Accord.Audition\Accord.Audition.csproj", "{CDBEFB1A-10BC-49EC-9833-D2CF6D4F6131}" @@ -61,16 +58,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Tests.Audio", "..\Un EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Controls.Vision", "Accord.Controls.Vision\Accord.Controls.Vision.csproj", "{6158E759-FE2B-4308-BA29-11C9E4A07812}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs", "Docs", "{3364C282-6629-4FC0-B7D3-E488576D7115}" -EndProject -Project("{7CF6DF6D-3B04-46F8-A40B-537D21BCA0B4}") = "Accord.Documentation", "Accord.Docs\Accord.Documentation\Accord.Documentation.shfbproj", "{048ACC63-3B91-4E14-B5A3-38E7898426FE}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Setup", "Setup", "{98CCD2AC-1853-4413-A2C7-B7283715B0FE}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Setup", "..\Setup\Accord.Setup.csproj", "{F00F5E2D-D181-4FCC-8F2E-FDCB90F4721B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Namespaces", "Accord.Docs\Namespaces\Accord.Namespaces.csproj", "{4ED2AB06-991F-44FF-AC01-53394B222AF7}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Accord.Tests.Math.Cpp", "..\Unit Tests\Accord.Tests.Math.Cpp\Accord.Tests.Math.Cpp.vcxproj", "{161BD953-537D-4325-8A00-22475FC9088E}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.IO", "Accord.IO\Accord.IO.csproj", "{63184EBD-6B28-4066-AAEE-5B99431E31F4}" @@ -81,6 +72,24 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Accord.Tests.MachineLearnin EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Tests.Core", "..\Unit Tests\Accord.Tests.Core\Accord.Tests.Core.csproj", "{3B1456C2-1591-4E8C-B71C-C0F25C8EA88E}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Tests.Controls", "..\Unit Tests\Accord.Tests.Controls\Accord.Tests.Controls.csproj", "{C021C74F-C774-483B-8BEE-CB5021CFC6F3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Audio.DirectSound", "Accord.Audio.DirectSound\Accord.Audio.DirectSound.csproj", "{456DB2E8-745A-4F87-A2BD-C43CF8677770}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Fuzzy", "Accord.Fuzzy\Accord.Fuzzy.csproj", "{B631038F-E12C-4D0D-8B25-FF7F62FE62D1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Genetic", "Accord.Genetic\Accord.Genetic.csproj", "{2EFAA327-1789-4438-B9F5-E83ACAE12DB2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Video.DirectShow", "Accord.Video.DirectShow\Accord.Video.DirectShow.csproj", "{26CD2CE7-FF63-4669-83B0-7D9C8F3408EE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Video", "Accord.Video\Accord.Video.csproj", "{809725DC-6502-4732-A51C-DEB7FEA12975}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Video.Kinect", "Accord.Video.Kinect\Accord.Video.Kinect.csproj", "{9DA8E727-4038-4E6B-90BD-853730FDFA49}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Video.VFW", "Accord.Video.VFW\Accord.Video.VFW.csproj", "{22E852C0-17FF-4106-9DF6-41EABB8C0613}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Video.Ximea", "Accord.Video.Ximea\Accord.Video.Ximea.csproj", "{AEDD6CFB-747B-4077-9288-9CD2A86090F1}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -97,22 +106,6 @@ Global {E0B826AC-2A51-41EC-9F09-561CA14A82BB}.NET40|Any CPU.Build.0 = NET40|Any CPU {E0B826AC-2A51-41EC-9F09-561CA14A82BB}.NET45|Any CPU.ActiveCfg = NET45|Any CPU {E0B826AC-2A51-41EC-9F09-561CA14A82BB}.NET45|Any CPU.Build.0 = NET45|Any CPU - {456DB2E8-745A-4F87-A2BD-C43CF8677770}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {456DB2E8-745A-4F87-A2BD-C43CF8677770}.Debug|Any CPU.Build.0 = Debug|Any CPU - {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET35|Any CPU.ActiveCfg = NET35|Any CPU - {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET35|Any CPU.Build.0 = NET35|Any CPU - {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET40|Any CPU.ActiveCfg = NET40|Any CPU - {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET40|Any CPU.Build.0 = NET40|Any CPU - {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET45|Any CPU.ActiveCfg = NET45|Any CPU - {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET45|Any CPU.Build.0 = NET45|Any CPU - {EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF}.NET35|Any CPU.ActiveCfg = NET35|Any CPU - {EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF}.NET35|Any CPU.Build.0 = NET35|Any CPU - {EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF}.NET40|Any CPU.ActiveCfg = NET40|Any CPU - {EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF}.NET40|Any CPU.Build.0 = NET40|Any CPU - {EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF}.NET45|Any CPU.ActiveCfg = NET45|Any CPU - {EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF}.NET45|Any CPU.Build.0 = NET45|Any CPU {E7B65F08-82F1-438F-847A-2AAC2BEC9AC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E7B65F08-82F1-438F-847A-2AAC2BEC9AC0}.Debug|Any CPU.Build.0 = Debug|Any CPU {E7B65F08-82F1-438F-847A-2AAC2BEC9AC0}.NET35|Any CPU.ActiveCfg = NET35|Any CPU @@ -265,10 +258,6 @@ Global {6158E759-FE2B-4308-BA29-11C9E4A07812}.NET40|Any CPU.Build.0 = NET40|Any CPU {6158E759-FE2B-4308-BA29-11C9E4A07812}.NET45|Any CPU.ActiveCfg = NET45|Any CPU {6158E759-FE2B-4308-BA29-11C9E4A07812}.NET45|Any CPU.Build.0 = NET45|Any CPU - {048ACC63-3B91-4E14-B5A3-38E7898426FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {048ACC63-3B91-4E14-B5A3-38E7898426FE}.NET35|Any CPU.ActiveCfg = Release|Any CPU - {048ACC63-3B91-4E14-B5A3-38E7898426FE}.NET40|Any CPU.ActiveCfg = Release|Any CPU - {048ACC63-3B91-4E14-B5A3-38E7898426FE}.NET45|Any CPU.ActiveCfg = Release|Any CPU {F00F5E2D-D181-4FCC-8F2E-FDCB90F4721B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F00F5E2D-D181-4FCC-8F2E-FDCB90F4721B}.Debug|Any CPU.Build.0 = Debug|Any CPU {F00F5E2D-D181-4FCC-8F2E-FDCB90F4721B}.NET35|Any CPU.ActiveCfg = Debug|Any CPU @@ -276,14 +265,6 @@ Global {F00F5E2D-D181-4FCC-8F2E-FDCB90F4721B}.NET40|Any CPU.ActiveCfg = Debug|Any CPU {F00F5E2D-D181-4FCC-8F2E-FDCB90F4721B}.NET40|Any CPU.Build.0 = Debug|Any CPU {F00F5E2D-D181-4FCC-8F2E-FDCB90F4721B}.NET45|Any CPU.ActiveCfg = Debug|Any CPU - {4ED2AB06-991F-44FF-AC01-53394B222AF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4ED2AB06-991F-44FF-AC01-53394B222AF7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4ED2AB06-991F-44FF-AC01-53394B222AF7}.NET35|Any CPU.ActiveCfg = Debug|Any CPU - {4ED2AB06-991F-44FF-AC01-53394B222AF7}.NET35|Any CPU.Build.0 = Debug|Any CPU - {4ED2AB06-991F-44FF-AC01-53394B222AF7}.NET40|Any CPU.ActiveCfg = Debug|Any CPU - {4ED2AB06-991F-44FF-AC01-53394B222AF7}.NET40|Any CPU.Build.0 = Debug|Any CPU - {4ED2AB06-991F-44FF-AC01-53394B222AF7}.NET45|Any CPU.ActiveCfg = NET45|Any CPU - {4ED2AB06-991F-44FF-AC01-53394B222AF7}.NET45|Any CPU.Build.0 = NET45|Any CPU {161BD953-537D-4325-8A00-22475FC9088E}.Debug|Any CPU.ActiveCfg = Debug|Win32 {161BD953-537D-4325-8A00-22475FC9088E}.Debug|Any CPU.Build.0 = Debug|Win32 {161BD953-537D-4325-8A00-22475FC9088E}.NET35|Any CPU.ActiveCfg = Debug|Win32 @@ -309,12 +290,12 @@ Global {2562C6B4-088E-48AC-B408-15BC99AE6760}.NET45|Any CPU.Build.0 = NET45|Any CPU {A6775B59-6919-4D7C-A960-7E875F0BD81A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A6775B59-6919-4D7C-A960-7E875F0BD81A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A6775B59-6919-4D7C-A960-7E875F0BD81A}.NET35|Any CPU.ActiveCfg = Release|Any CPU - {A6775B59-6919-4D7C-A960-7E875F0BD81A}.NET35|Any CPU.Build.0 = Release|Any CPU - {A6775B59-6919-4D7C-A960-7E875F0BD81A}.NET40|Any CPU.ActiveCfg = Release|Any CPU - {A6775B59-6919-4D7C-A960-7E875F0BD81A}.NET40|Any CPU.Build.0 = Release|Any CPU - {A6775B59-6919-4D7C-A960-7E875F0BD81A}.NET45|Any CPU.ActiveCfg = Release|Any CPU - {A6775B59-6919-4D7C-A960-7E875F0BD81A}.NET45|Any CPU.Build.0 = Release|Any CPU + {A6775B59-6919-4D7C-A960-7E875F0BD81A}.NET35|Any CPU.ActiveCfg = Debug|Any CPU + {A6775B59-6919-4D7C-A960-7E875F0BD81A}.NET35|Any CPU.Build.0 = Debug|Any CPU + {A6775B59-6919-4D7C-A960-7E875F0BD81A}.NET40|Any CPU.ActiveCfg = Debug|Any CPU + {A6775B59-6919-4D7C-A960-7E875F0BD81A}.NET40|Any CPU.Build.0 = Debug|Any CPU + {A6775B59-6919-4D7C-A960-7E875F0BD81A}.NET45|Any CPU.ActiveCfg = Debug|Any CPU + {A6775B59-6919-4D7C-A960-7E875F0BD81A}.NET45|Any CPU.Build.0 = Debug|Any CPU {3B1456C2-1591-4E8C-B71C-C0F25C8EA88E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3B1456C2-1591-4E8C-B71C-C0F25C8EA88E}.Debug|Any CPU.Build.0 = Debug|Any CPU {3B1456C2-1591-4E8C-B71C-C0F25C8EA88E}.NET35|Any CPU.ActiveCfg = NET35|Any CPU @@ -323,6 +304,78 @@ Global {3B1456C2-1591-4E8C-B71C-C0F25C8EA88E}.NET40|Any CPU.Build.0 = NET40|Any CPU {3B1456C2-1591-4E8C-B71C-C0F25C8EA88E}.NET45|Any CPU.ActiveCfg = NET45|Any CPU {3B1456C2-1591-4E8C-B71C-C0F25C8EA88E}.NET45|Any CPU.Build.0 = NET45|Any CPU + {C021C74F-C774-483B-8BEE-CB5021CFC6F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C021C74F-C774-483B-8BEE-CB5021CFC6F3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C021C74F-C774-483B-8BEE-CB5021CFC6F3}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {C021C74F-C774-483B-8BEE-CB5021CFC6F3}.NET35|Any CPU.Build.0 = NET35|Any CPU + {C021C74F-C774-483B-8BEE-CB5021CFC6F3}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {C021C74F-C774-483B-8BEE-CB5021CFC6F3}.NET40|Any CPU.Build.0 = NET40|Any CPU + {C021C74F-C774-483B-8BEE-CB5021CFC6F3}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {C021C74F-C774-483B-8BEE-CB5021CFC6F3}.NET45|Any CPU.Build.0 = NET45|Any CPU + {456DB2E8-745A-4F87-A2BD-C43CF8677770}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {456DB2E8-745A-4F87-A2BD-C43CF8677770}.Debug|Any CPU.Build.0 = Debug|Any CPU + {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET35|Any CPU.Build.0 = NET35|Any CPU + {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET40|Any CPU.Build.0 = NET40|Any CPU + {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET45|Any CPU.Build.0 = NET45|Any CPU + {B631038F-E12C-4D0D-8B25-FF7F62FE62D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B631038F-E12C-4D0D-8B25-FF7F62FE62D1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B631038F-E12C-4D0D-8B25-FF7F62FE62D1}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {B631038F-E12C-4D0D-8B25-FF7F62FE62D1}.NET35|Any CPU.Build.0 = NET35|Any CPU + {B631038F-E12C-4D0D-8B25-FF7F62FE62D1}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {B631038F-E12C-4D0D-8B25-FF7F62FE62D1}.NET40|Any CPU.Build.0 = NET40|Any CPU + {B631038F-E12C-4D0D-8B25-FF7F62FE62D1}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {B631038F-E12C-4D0D-8B25-FF7F62FE62D1}.NET45|Any CPU.Build.0 = NET45|Any CPU + {2EFAA327-1789-4438-B9F5-E83ACAE12DB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2EFAA327-1789-4438-B9F5-E83ACAE12DB2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2EFAA327-1789-4438-B9F5-E83ACAE12DB2}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {2EFAA327-1789-4438-B9F5-E83ACAE12DB2}.NET35|Any CPU.Build.0 = NET35|Any CPU + {2EFAA327-1789-4438-B9F5-E83ACAE12DB2}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {2EFAA327-1789-4438-B9F5-E83ACAE12DB2}.NET40|Any CPU.Build.0 = NET40|Any CPU + {2EFAA327-1789-4438-B9F5-E83ACAE12DB2}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {2EFAA327-1789-4438-B9F5-E83ACAE12DB2}.NET45|Any CPU.Build.0 = NET45|Any CPU + {26CD2CE7-FF63-4669-83B0-7D9C8F3408EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {26CD2CE7-FF63-4669-83B0-7D9C8F3408EE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {26CD2CE7-FF63-4669-83B0-7D9C8F3408EE}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {26CD2CE7-FF63-4669-83B0-7D9C8F3408EE}.NET35|Any CPU.Build.0 = NET35|Any CPU + {26CD2CE7-FF63-4669-83B0-7D9C8F3408EE}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {26CD2CE7-FF63-4669-83B0-7D9C8F3408EE}.NET40|Any CPU.Build.0 = NET40|Any CPU + {26CD2CE7-FF63-4669-83B0-7D9C8F3408EE}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {26CD2CE7-FF63-4669-83B0-7D9C8F3408EE}.NET45|Any CPU.Build.0 = NET45|Any CPU + {809725DC-6502-4732-A51C-DEB7FEA12975}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {809725DC-6502-4732-A51C-DEB7FEA12975}.Debug|Any CPU.Build.0 = Debug|Any CPU + {809725DC-6502-4732-A51C-DEB7FEA12975}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {809725DC-6502-4732-A51C-DEB7FEA12975}.NET35|Any CPU.Build.0 = NET35|Any CPU + {809725DC-6502-4732-A51C-DEB7FEA12975}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {809725DC-6502-4732-A51C-DEB7FEA12975}.NET40|Any CPU.Build.0 = NET40|Any CPU + {809725DC-6502-4732-A51C-DEB7FEA12975}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {809725DC-6502-4732-A51C-DEB7FEA12975}.NET45|Any CPU.Build.0 = NET45|Any CPU + {9DA8E727-4038-4E6B-90BD-853730FDFA49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9DA8E727-4038-4E6B-90BD-853730FDFA49}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9DA8E727-4038-4E6B-90BD-853730FDFA49}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {9DA8E727-4038-4E6B-90BD-853730FDFA49}.NET35|Any CPU.Build.0 = NET35|Any CPU + {9DA8E727-4038-4E6B-90BD-853730FDFA49}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {9DA8E727-4038-4E6B-90BD-853730FDFA49}.NET40|Any CPU.Build.0 = NET40|Any CPU + {9DA8E727-4038-4E6B-90BD-853730FDFA49}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {9DA8E727-4038-4E6B-90BD-853730FDFA49}.NET45|Any CPU.Build.0 = NET45|Any CPU + {22E852C0-17FF-4106-9DF6-41EABB8C0613}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {22E852C0-17FF-4106-9DF6-41EABB8C0613}.Debug|Any CPU.Build.0 = Debug|Any CPU + {22E852C0-17FF-4106-9DF6-41EABB8C0613}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {22E852C0-17FF-4106-9DF6-41EABB8C0613}.NET35|Any CPU.Build.0 = NET35|Any CPU + {22E852C0-17FF-4106-9DF6-41EABB8C0613}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {22E852C0-17FF-4106-9DF6-41EABB8C0613}.NET40|Any CPU.Build.0 = NET40|Any CPU + {22E852C0-17FF-4106-9DF6-41EABB8C0613}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {22E852C0-17FF-4106-9DF6-41EABB8C0613}.NET45|Any CPU.Build.0 = NET45|Any CPU + {AEDD6CFB-747B-4077-9288-9CD2A86090F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AEDD6CFB-747B-4077-9288-9CD2A86090F1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AEDD6CFB-747B-4077-9288-9CD2A86090F1}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {AEDD6CFB-747B-4077-9288-9CD2A86090F1}.NET35|Any CPU.Build.0 = NET35|Any CPU + {AEDD6CFB-747B-4077-9288-9CD2A86090F1}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {AEDD6CFB-747B-4077-9288-9CD2A86090F1}.NET40|Any CPU.Build.0 = NET40|Any CPU + {AEDD6CFB-747B-4077-9288-9CD2A86090F1}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {AEDD6CFB-747B-4077-9288-9CD2A86090F1}.NET45|Any CPU.Build.0 = NET45|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -335,13 +388,12 @@ Global {16A563A2-2D02-4B9E-B3F8-F36DD72F4477} = {D059B679-8B38-44FE-BEC6-8DFF9271CE59} {8046613E-799A-460C-985A-444C0327B49C} = {D059B679-8B38-44FE-BEC6-8DFF9271CE59} {19385AE1-57CA-4082-AD33-62480D02C1D9} = {D059B679-8B38-44FE-BEC6-8DFF9271CE59} - {048ACC63-3B91-4E14-B5A3-38E7898426FE} = {3364C282-6629-4FC0-B7D3-E488576D7115} {F00F5E2D-D181-4FCC-8F2E-FDCB90F4721B} = {98CCD2AC-1853-4413-A2C7-B7283715B0FE} - {4ED2AB06-991F-44FF-AC01-53394B222AF7} = {3364C282-6629-4FC0-B7D3-E488576D7115} {161BD953-537D-4325-8A00-22475FC9088E} = {D059B679-8B38-44FE-BEC6-8DFF9271CE59} {2562C6B4-088E-48AC-B408-15BC99AE6760} = {D059B679-8B38-44FE-BEC6-8DFF9271CE59} {A6775B59-6919-4D7C-A960-7E875F0BD81A} = {D059B679-8B38-44FE-BEC6-8DFF9271CE59} {3B1456C2-1591-4E8C-B71C-C0F25C8EA88E} = {D059B679-8B38-44FE-BEC6-8DFF9271CE59} + {C021C74F-C774-483B-8BEE-CB5021CFC6F3} = {D059B679-8B38-44FE-BEC6-8DFF9271CE59} EndGlobalSection GlobalSection(TestCaseManagementSettings) = postSolution CategoryFile = Accord.NET.vsmdi diff --git a/Sources/Accord.NET.Mono.sln b/Sources/Accord.NET.Mono.sln index 93759189c..d863c4a94 100644 --- a/Sources/Accord.NET.Mono.sln +++ b/Sources/Accord.NET.Mono.sln @@ -3,6 +3,8 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 VisualStudioVersion = 12.0.31101.0 MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Unit Tests", "Unit Tests", "{D059B679-8B38-44FE-BEC6-8DFF9271CE59}" +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{51B993EE-FE3F-44B0-8FA1-C0EEBF2670C8}" ProjectSection(SolutionItems) = preProject Accord.NET.ruleset = Accord.NET.ruleset @@ -18,10 +20,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Controls.Audio", "Accord.Controls.Audio\Accord.Controls.Audio.csproj", "{E0B826AC-2A51-41EC-9F09-561CA14A82BB}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.DirectSound", "Accord.DirectSound\Accord.DirectSound.csproj", "{456DB2E8-745A-4F87-A2BD-C43CF8677770}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Audio.Formats", "Accord.Audio.Formats\Accord.Audio.Formats.csproj", "{EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Audio", "Accord.Audio\Accord.Audio.csproj", "{E7B65F08-82F1-438F-847A-2AAC2BEC9AC0}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Audition", "Accord.Audition\Accord.Audition.csproj", "{CDBEFB1A-10BC-49EC-9833-D2CF6D4F6131}" @@ -32,18 +30,30 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Statistics", "Accord EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Neuro", "Accord.Neuro\Accord.Neuro.csproj", "{179F3045-8757-4F4B-9508-F48327BA11E3}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Tests.Statistics", "..\Unit Tests\Accord.Tests.Statistics\Accord.Tests.Statistics.csproj", "{49679C95-28CE-4D35-8F38-3D67A511A3C1}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Controls", "Accord.Controls.Statistics\Accord.Controls.csproj", "{0AB27A20-925C-4556-9FA4-6E2C109E448E}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Imaging", "Accord.Imaging\Accord.Imaging.csproj", "{4959A83D-F78F-439E-80A5-41583ECEAAC6}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.MachineLearning", "Accord.MachineLearning\Accord.MachineLearning.csproj", "{7AB4BBCC-6222-423D-9FF9-BA9CB7C09199}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Tests.MachineLearning", "..\Unit Tests\Accord.Tests.MachineLearning\Accord.Tests.MachineLearning.csproj", "{987E989A-E48B-428F-A392-0E7EEC9BCECD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Tests.Neuro", "..\Unit Tests\Accord.Tests.Neuro\Accord.Tests.Neuro.csproj", "{AB8B83D8-F7B4-4C21-AEB4-B0C5D2217DEF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Tests.Imaging", "..\Unit Tests\Accord.Tests.Imaging\Accord.Tests.Imaging.csproj", "{16A563A2-2D02-4B9E-B3F8-F36DD72F4477}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Controls.Imaging", "Accord.Controls.Imaging\Accord.Controls.Imaging.csproj", "{E1089999-EAED-4E55-AC47-B6A196DF84FC}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Vision", "Accord.Vision\Accord.Vision.csproj", "{C70A159D-74A4-405F-9A7F-C17ACF451CCA}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Tests.Vision", "..\Unit Tests\Accord.Tests.Vision\Accord.Tests.Vision.csproj", "{8046613E-799A-460C-985A-444C0327B49C}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Core", "Accord.Core\Accord.Core.csproj", "{A177A90C-8207-466A-AF70-F2B8452A42AC}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Tests.Audio", "..\Unit Tests\Accord.Tests.Audio\Accord.Tests.Audio.csproj", "{19385AE1-57CA-4082-AD33-62480D02C1D9}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Controls.Vision", "Accord.Controls.Vision\Accord.Controls.Vision.csproj", "{6158E759-FE2B-4308-BA29-11C9E4A07812}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.MachineLearning (GPL)", "Extras\Accord.MachineLearning.GPL\Accord.MachineLearning (GPL).csproj", "{6DD1A48C-D7A8-4B39-9C06-5A71FEEC70B9}" @@ -54,6 +64,34 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Non-LGPL", "Non-LGPL", "{54 EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.IO", "Accord.IO\Accord.IO.csproj", "{63184EBD-6B28-4066-AAEE-5B99431E31F4}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Tests.IO", "..\Unit Tests\Accord.Tests.IO\Accord.Tests.IO.csproj", "{2562C6B4-088E-48AC-B408-15BC99AE6760}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Tests.Core", "..\Unit Tests\Accord.Tests.Core\Accord.Tests.Core.csproj", "{3B1456C2-1591-4E8C-B71C-C0F25C8EA88E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Tests.Math (Noncommercial)", "Extras\Accord.Tests.Math.Noncommercial\Accord.Tests.Math (Noncommercial).csproj", "{4C525826-D64B-4D2D-8BB3-33AF46649B05}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Tests.MachineLearning (GPL)", "Extras\Accord.Tests.MachineLearning.GPL\Accord.Tests.MachineLearning (GPL).csproj", "{944A7FDE-890A-45CE-A958-AAE6553E2E24}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Tests.Controls", "..\Unit Tests\Accord.Tests.Controls\Accord.Tests.Controls.csproj", "{C021C74F-C774-483B-8BEE-CB5021CFC6F3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Audio.DirectSound", "Accord.Audio.DirectSound\Accord.Audio.DirectSound.csproj", "{456DB2E8-745A-4F87-A2BD-C43CF8677770}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Fuzzy", "Accord.Fuzzy\Accord.Fuzzy.csproj", "{B631038F-E12C-4D0D-8B25-FF7F62FE62D1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Genetic", "Accord.Genetic\Accord.Genetic.csproj", "{2EFAA327-1789-4438-B9F5-E83ACAE12DB2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Video.DirectShow", "Accord.Video.DirectShow\Accord.Video.DirectShow.csproj", "{26CD2CE7-FF63-4669-83B0-7D9C8F3408EE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Video", "Accord.Video\Accord.Video.csproj", "{809725DC-6502-4732-A51C-DEB7FEA12975}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Video.Kinect", "Accord.Video.Kinect\Accord.Video.Kinect.csproj", "{9DA8E727-4038-4E6B-90BD-853730FDFA49}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Video.VFW", "Accord.Video.VFW\Accord.Video.VFW.csproj", "{22E852C0-17FF-4106-9DF6-41EABB8C0613}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Video.Ximea", "Accord.Video.Ximea\Accord.Video.Ximea.csproj", "{AEDD6CFB-747B-4077-9288-9CD2A86090F1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Tests.Math", "..\Unit Tests\Accord.Tests.Math\Accord.Tests.Math.csproj", "{F454DBD6-2AB9-461D-9624-2249B921B6E6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -70,22 +108,6 @@ Global {E0B826AC-2A51-41EC-9F09-561CA14A82BB}.NET40|Any CPU.Build.0 = NET40|Any CPU {E0B826AC-2A51-41EC-9F09-561CA14A82BB}.NET45|Any CPU.ActiveCfg = NET45|Any CPU {E0B826AC-2A51-41EC-9F09-561CA14A82BB}.NET45|Any CPU.Build.0 = NET45|Any CPU - {456DB2E8-745A-4F87-A2BD-C43CF8677770}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {456DB2E8-745A-4F87-A2BD-C43CF8677770}.Debug|Any CPU.Build.0 = Debug|Any CPU - {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET35|Any CPU.ActiveCfg = NET35|Any CPU - {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET35|Any CPU.Build.0 = NET35|Any CPU - {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET40|Any CPU.ActiveCfg = NET40|Any CPU - {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET40|Any CPU.Build.0 = NET40|Any CPU - {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET45|Any CPU.ActiveCfg = NET45|Any CPU - {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET45|Any CPU.Build.0 = NET45|Any CPU - {EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF}.NET35|Any CPU.ActiveCfg = NET35|Any CPU - {EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF}.NET35|Any CPU.Build.0 = NET35|Any CPU - {EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF}.NET40|Any CPU.ActiveCfg = NET40|Any CPU - {EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF}.NET40|Any CPU.Build.0 = NET40|Any CPU - {EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF}.NET45|Any CPU.ActiveCfg = NET45|Any CPU - {EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF}.NET45|Any CPU.Build.0 = NET45|Any CPU {E7B65F08-82F1-438F-847A-2AAC2BEC9AC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E7B65F08-82F1-438F-847A-2AAC2BEC9AC0}.Debug|Any CPU.Build.0 = Debug|Any CPU {E7B65F08-82F1-438F-847A-2AAC2BEC9AC0}.NET35|Any CPU.ActiveCfg = NET35|Any CPU @@ -126,6 +148,14 @@ Global {179F3045-8757-4F4B-9508-F48327BA11E3}.NET40|Any CPU.Build.0 = NET40|Any CPU {179F3045-8757-4F4B-9508-F48327BA11E3}.NET45|Any CPU.ActiveCfg = NET45|Any CPU {179F3045-8757-4F4B-9508-F48327BA11E3}.NET45|Any CPU.Build.0 = NET45|Any CPU + {49679C95-28CE-4D35-8F38-3D67A511A3C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {49679C95-28CE-4D35-8F38-3D67A511A3C1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {49679C95-28CE-4D35-8F38-3D67A511A3C1}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {49679C95-28CE-4D35-8F38-3D67A511A3C1}.NET35|Any CPU.Build.0 = NET35|Any CPU + {49679C95-28CE-4D35-8F38-3D67A511A3C1}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {49679C95-28CE-4D35-8F38-3D67A511A3C1}.NET40|Any CPU.Build.0 = NET40|Any CPU + {49679C95-28CE-4D35-8F38-3D67A511A3C1}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {49679C95-28CE-4D35-8F38-3D67A511A3C1}.NET45|Any CPU.Build.0 = NET45|Any CPU {0AB27A20-925C-4556-9FA4-6E2C109E448E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0AB27A20-925C-4556-9FA4-6E2C109E448E}.Debug|Any CPU.Build.0 = Debug|Any CPU {0AB27A20-925C-4556-9FA4-6E2C109E448E}.NET35|Any CPU.ActiveCfg = NET35|Any CPU @@ -150,6 +180,30 @@ Global {7AB4BBCC-6222-423D-9FF9-BA9CB7C09199}.NET40|Any CPU.Build.0 = NET40|Any CPU {7AB4BBCC-6222-423D-9FF9-BA9CB7C09199}.NET45|Any CPU.ActiveCfg = NET45|Any CPU {7AB4BBCC-6222-423D-9FF9-BA9CB7C09199}.NET45|Any CPU.Build.0 = NET45|Any CPU + {987E989A-E48B-428F-A392-0E7EEC9BCECD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {987E989A-E48B-428F-A392-0E7EEC9BCECD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {987E989A-E48B-428F-A392-0E7EEC9BCECD}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {987E989A-E48B-428F-A392-0E7EEC9BCECD}.NET35|Any CPU.Build.0 = NET35|Any CPU + {987E989A-E48B-428F-A392-0E7EEC9BCECD}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {987E989A-E48B-428F-A392-0E7EEC9BCECD}.NET40|Any CPU.Build.0 = NET40|Any CPU + {987E989A-E48B-428F-A392-0E7EEC9BCECD}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {987E989A-E48B-428F-A392-0E7EEC9BCECD}.NET45|Any CPU.Build.0 = NET45|Any CPU + {AB8B83D8-F7B4-4C21-AEB4-B0C5D2217DEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AB8B83D8-F7B4-4C21-AEB4-B0C5D2217DEF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AB8B83D8-F7B4-4C21-AEB4-B0C5D2217DEF}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {AB8B83D8-F7B4-4C21-AEB4-B0C5D2217DEF}.NET35|Any CPU.Build.0 = NET35|Any CPU + {AB8B83D8-F7B4-4C21-AEB4-B0C5D2217DEF}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {AB8B83D8-F7B4-4C21-AEB4-B0C5D2217DEF}.NET40|Any CPU.Build.0 = NET40|Any CPU + {AB8B83D8-F7B4-4C21-AEB4-B0C5D2217DEF}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {AB8B83D8-F7B4-4C21-AEB4-B0C5D2217DEF}.NET45|Any CPU.Build.0 = NET45|Any CPU + {16A563A2-2D02-4B9E-B3F8-F36DD72F4477}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {16A563A2-2D02-4B9E-B3F8-F36DD72F4477}.Debug|Any CPU.Build.0 = Debug|Any CPU + {16A563A2-2D02-4B9E-B3F8-F36DD72F4477}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {16A563A2-2D02-4B9E-B3F8-F36DD72F4477}.NET35|Any CPU.Build.0 = NET35|Any CPU + {16A563A2-2D02-4B9E-B3F8-F36DD72F4477}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {16A563A2-2D02-4B9E-B3F8-F36DD72F4477}.NET40|Any CPU.Build.0 = NET40|Any CPU + {16A563A2-2D02-4B9E-B3F8-F36DD72F4477}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {16A563A2-2D02-4B9E-B3F8-F36DD72F4477}.NET45|Any CPU.Build.0 = NET45|Any CPU {E1089999-EAED-4E55-AC47-B6A196DF84FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E1089999-EAED-4E55-AC47-B6A196DF84FC}.Debug|Any CPU.Build.0 = Debug|Any CPU {E1089999-EAED-4E55-AC47-B6A196DF84FC}.NET35|Any CPU.ActiveCfg = NET35|Any CPU @@ -166,6 +220,14 @@ Global {C70A159D-74A4-405F-9A7F-C17ACF451CCA}.NET40|Any CPU.Build.0 = NET40|Any CPU {C70A159D-74A4-405F-9A7F-C17ACF451CCA}.NET45|Any CPU.ActiveCfg = NET45|Any CPU {C70A159D-74A4-405F-9A7F-C17ACF451CCA}.NET45|Any CPU.Build.0 = NET45|Any CPU + {8046613E-799A-460C-985A-444C0327B49C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8046613E-799A-460C-985A-444C0327B49C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8046613E-799A-460C-985A-444C0327B49C}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {8046613E-799A-460C-985A-444C0327B49C}.NET35|Any CPU.Build.0 = NET35|Any CPU + {8046613E-799A-460C-985A-444C0327B49C}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {8046613E-799A-460C-985A-444C0327B49C}.NET40|Any CPU.Build.0 = NET40|Any CPU + {8046613E-799A-460C-985A-444C0327B49C}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {8046613E-799A-460C-985A-444C0327B49C}.NET45|Any CPU.Build.0 = NET45|Any CPU {A177A90C-8207-466A-AF70-F2B8452A42AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A177A90C-8207-466A-AF70-F2B8452A42AC}.Debug|Any CPU.Build.0 = Debug|Any CPU {A177A90C-8207-466A-AF70-F2B8452A42AC}.NET35|Any CPU.ActiveCfg = NET35|Any CPU @@ -174,6 +236,14 @@ Global {A177A90C-8207-466A-AF70-F2B8452A42AC}.NET40|Any CPU.Build.0 = NET40|Any CPU {A177A90C-8207-466A-AF70-F2B8452A42AC}.NET45|Any CPU.ActiveCfg = NET45|Any CPU {A177A90C-8207-466A-AF70-F2B8452A42AC}.NET45|Any CPU.Build.0 = NET45|Any CPU + {19385AE1-57CA-4082-AD33-62480D02C1D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {19385AE1-57CA-4082-AD33-62480D02C1D9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {19385AE1-57CA-4082-AD33-62480D02C1D9}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {19385AE1-57CA-4082-AD33-62480D02C1D9}.NET35|Any CPU.Build.0 = NET35|Any CPU + {19385AE1-57CA-4082-AD33-62480D02C1D9}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {19385AE1-57CA-4082-AD33-62480D02C1D9}.NET40|Any CPU.Build.0 = NET40|Any CPU + {19385AE1-57CA-4082-AD33-62480D02C1D9}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {19385AE1-57CA-4082-AD33-62480D02C1D9}.NET45|Any CPU.Build.0 = NET45|Any CPU {6158E759-FE2B-4308-BA29-11C9E4A07812}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6158E759-FE2B-4308-BA29-11C9E4A07812}.Debug|Any CPU.Build.0 = Debug|Any CPU {6158E759-FE2B-4308-BA29-11C9E4A07812}.NET35|Any CPU.ActiveCfg = NET35|Any CPU @@ -206,13 +276,137 @@ Global {63184EBD-6B28-4066-AAEE-5B99431E31F4}.NET40|Any CPU.Build.0 = NET40|Any CPU {63184EBD-6B28-4066-AAEE-5B99431E31F4}.NET45|Any CPU.ActiveCfg = NET45|Any CPU {63184EBD-6B28-4066-AAEE-5B99431E31F4}.NET45|Any CPU.Build.0 = NET45|Any CPU + {2562C6B4-088E-48AC-B408-15BC99AE6760}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2562C6B4-088E-48AC-B408-15BC99AE6760}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2562C6B4-088E-48AC-B408-15BC99AE6760}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {2562C6B4-088E-48AC-B408-15BC99AE6760}.NET35|Any CPU.Build.0 = NET35|Any CPU + {2562C6B4-088E-48AC-B408-15BC99AE6760}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {2562C6B4-088E-48AC-B408-15BC99AE6760}.NET40|Any CPU.Build.0 = NET40|Any CPU + {2562C6B4-088E-48AC-B408-15BC99AE6760}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {2562C6B4-088E-48AC-B408-15BC99AE6760}.NET45|Any CPU.Build.0 = NET45|Any CPU + {3B1456C2-1591-4E8C-B71C-C0F25C8EA88E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3B1456C2-1591-4E8C-B71C-C0F25C8EA88E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3B1456C2-1591-4E8C-B71C-C0F25C8EA88E}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {3B1456C2-1591-4E8C-B71C-C0F25C8EA88E}.NET35|Any CPU.Build.0 = NET35|Any CPU + {3B1456C2-1591-4E8C-B71C-C0F25C8EA88E}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {3B1456C2-1591-4E8C-B71C-C0F25C8EA88E}.NET40|Any CPU.Build.0 = NET40|Any CPU + {3B1456C2-1591-4E8C-B71C-C0F25C8EA88E}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {3B1456C2-1591-4E8C-B71C-C0F25C8EA88E}.NET45|Any CPU.Build.0 = NET45|Any CPU + {4C525826-D64B-4D2D-8BB3-33AF46649B05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4C525826-D64B-4D2D-8BB3-33AF46649B05}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4C525826-D64B-4D2D-8BB3-33AF46649B05}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {4C525826-D64B-4D2D-8BB3-33AF46649B05}.NET35|Any CPU.Build.0 = NET35|Any CPU + {4C525826-D64B-4D2D-8BB3-33AF46649B05}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {4C525826-D64B-4D2D-8BB3-33AF46649B05}.NET40|Any CPU.Build.0 = NET40|Any CPU + {4C525826-D64B-4D2D-8BB3-33AF46649B05}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {4C525826-D64B-4D2D-8BB3-33AF46649B05}.NET45|Any CPU.Build.0 = NET45|Any CPU + {944A7FDE-890A-45CE-A958-AAE6553E2E24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {944A7FDE-890A-45CE-A958-AAE6553E2E24}.Debug|Any CPU.Build.0 = Debug|Any CPU + {944A7FDE-890A-45CE-A958-AAE6553E2E24}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {944A7FDE-890A-45CE-A958-AAE6553E2E24}.NET35|Any CPU.Build.0 = NET35|Any CPU + {944A7FDE-890A-45CE-A958-AAE6553E2E24}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {944A7FDE-890A-45CE-A958-AAE6553E2E24}.NET40|Any CPU.Build.0 = NET40|Any CPU + {944A7FDE-890A-45CE-A958-AAE6553E2E24}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {944A7FDE-890A-45CE-A958-AAE6553E2E24}.NET45|Any CPU.Build.0 = NET45|Any CPU + {C021C74F-C774-483B-8BEE-CB5021CFC6F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C021C74F-C774-483B-8BEE-CB5021CFC6F3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C021C74F-C774-483B-8BEE-CB5021CFC6F3}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {C021C74F-C774-483B-8BEE-CB5021CFC6F3}.NET35|Any CPU.Build.0 = NET35|Any CPU + {C021C74F-C774-483B-8BEE-CB5021CFC6F3}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {C021C74F-C774-483B-8BEE-CB5021CFC6F3}.NET40|Any CPU.Build.0 = NET40|Any CPU + {C021C74F-C774-483B-8BEE-CB5021CFC6F3}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {C021C74F-C774-483B-8BEE-CB5021CFC6F3}.NET45|Any CPU.Build.0 = NET45|Any CPU + {456DB2E8-745A-4F87-A2BD-C43CF8677770}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {456DB2E8-745A-4F87-A2BD-C43CF8677770}.Debug|Any CPU.Build.0 = Debug|Any CPU + {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET35|Any CPU.Build.0 = NET35|Any CPU + {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET40|Any CPU.Build.0 = NET40|Any CPU + {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET45|Any CPU.Build.0 = NET45|Any CPU + {B631038F-E12C-4D0D-8B25-FF7F62FE62D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B631038F-E12C-4D0D-8B25-FF7F62FE62D1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B631038F-E12C-4D0D-8B25-FF7F62FE62D1}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {B631038F-E12C-4D0D-8B25-FF7F62FE62D1}.NET35|Any CPU.Build.0 = NET35|Any CPU + {B631038F-E12C-4D0D-8B25-FF7F62FE62D1}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {B631038F-E12C-4D0D-8B25-FF7F62FE62D1}.NET40|Any CPU.Build.0 = NET40|Any CPU + {B631038F-E12C-4D0D-8B25-FF7F62FE62D1}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {B631038F-E12C-4D0D-8B25-FF7F62FE62D1}.NET45|Any CPU.Build.0 = NET45|Any CPU + {2EFAA327-1789-4438-B9F5-E83ACAE12DB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2EFAA327-1789-4438-B9F5-E83ACAE12DB2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2EFAA327-1789-4438-B9F5-E83ACAE12DB2}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {2EFAA327-1789-4438-B9F5-E83ACAE12DB2}.NET35|Any CPU.Build.0 = NET35|Any CPU + {2EFAA327-1789-4438-B9F5-E83ACAE12DB2}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {2EFAA327-1789-4438-B9F5-E83ACAE12DB2}.NET40|Any CPU.Build.0 = NET40|Any CPU + {2EFAA327-1789-4438-B9F5-E83ACAE12DB2}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {2EFAA327-1789-4438-B9F5-E83ACAE12DB2}.NET45|Any CPU.Build.0 = NET45|Any CPU + {26CD2CE7-FF63-4669-83B0-7D9C8F3408EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {26CD2CE7-FF63-4669-83B0-7D9C8F3408EE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {26CD2CE7-FF63-4669-83B0-7D9C8F3408EE}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {26CD2CE7-FF63-4669-83B0-7D9C8F3408EE}.NET35|Any CPU.Build.0 = NET35|Any CPU + {26CD2CE7-FF63-4669-83B0-7D9C8F3408EE}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {26CD2CE7-FF63-4669-83B0-7D9C8F3408EE}.NET40|Any CPU.Build.0 = NET40|Any CPU + {26CD2CE7-FF63-4669-83B0-7D9C8F3408EE}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {26CD2CE7-FF63-4669-83B0-7D9C8F3408EE}.NET45|Any CPU.Build.0 = NET45|Any CPU + {809725DC-6502-4732-A51C-DEB7FEA12975}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {809725DC-6502-4732-A51C-DEB7FEA12975}.Debug|Any CPU.Build.0 = Debug|Any CPU + {809725DC-6502-4732-A51C-DEB7FEA12975}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {809725DC-6502-4732-A51C-DEB7FEA12975}.NET35|Any CPU.Build.0 = NET35|Any CPU + {809725DC-6502-4732-A51C-DEB7FEA12975}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {809725DC-6502-4732-A51C-DEB7FEA12975}.NET40|Any CPU.Build.0 = NET40|Any CPU + {809725DC-6502-4732-A51C-DEB7FEA12975}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {809725DC-6502-4732-A51C-DEB7FEA12975}.NET45|Any CPU.Build.0 = NET45|Any CPU + {9DA8E727-4038-4E6B-90BD-853730FDFA49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9DA8E727-4038-4E6B-90BD-853730FDFA49}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9DA8E727-4038-4E6B-90BD-853730FDFA49}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {9DA8E727-4038-4E6B-90BD-853730FDFA49}.NET35|Any CPU.Build.0 = NET35|Any CPU + {9DA8E727-4038-4E6B-90BD-853730FDFA49}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {9DA8E727-4038-4E6B-90BD-853730FDFA49}.NET40|Any CPU.Build.0 = NET40|Any CPU + {9DA8E727-4038-4E6B-90BD-853730FDFA49}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {9DA8E727-4038-4E6B-90BD-853730FDFA49}.NET45|Any CPU.Build.0 = NET45|Any CPU + {22E852C0-17FF-4106-9DF6-41EABB8C0613}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {22E852C0-17FF-4106-9DF6-41EABB8C0613}.Debug|Any CPU.Build.0 = Debug|Any CPU + {22E852C0-17FF-4106-9DF6-41EABB8C0613}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {22E852C0-17FF-4106-9DF6-41EABB8C0613}.NET35|Any CPU.Build.0 = NET35|Any CPU + {22E852C0-17FF-4106-9DF6-41EABB8C0613}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {22E852C0-17FF-4106-9DF6-41EABB8C0613}.NET40|Any CPU.Build.0 = NET40|Any CPU + {22E852C0-17FF-4106-9DF6-41EABB8C0613}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {22E852C0-17FF-4106-9DF6-41EABB8C0613}.NET45|Any CPU.Build.0 = NET45|Any CPU + {AEDD6CFB-747B-4077-9288-9CD2A86090F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AEDD6CFB-747B-4077-9288-9CD2A86090F1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AEDD6CFB-747B-4077-9288-9CD2A86090F1}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {AEDD6CFB-747B-4077-9288-9CD2A86090F1}.NET35|Any CPU.Build.0 = NET35|Any CPU + {AEDD6CFB-747B-4077-9288-9CD2A86090F1}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {AEDD6CFB-747B-4077-9288-9CD2A86090F1}.NET40|Any CPU.Build.0 = NET40|Any CPU + {AEDD6CFB-747B-4077-9288-9CD2A86090F1}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {AEDD6CFB-747B-4077-9288-9CD2A86090F1}.NET45|Any CPU.Build.0 = NET45|Any CPU + {F454DBD6-2AB9-461D-9624-2249B921B6E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F454DBD6-2AB9-461D-9624-2249B921B6E6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F454DBD6-2AB9-461D-9624-2249B921B6E6}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {F454DBD6-2AB9-461D-9624-2249B921B6E6}.NET35|Any CPU.Build.0 = NET35|Any CPU + {F454DBD6-2AB9-461D-9624-2249B921B6E6}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {F454DBD6-2AB9-461D-9624-2249B921B6E6}.NET40|Any CPU.Build.0 = NET40|Any CPU + {F454DBD6-2AB9-461D-9624-2249B921B6E6}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {F454DBD6-2AB9-461D-9624-2249B921B6E6}.NET45|Any CPU.Build.0 = NET45|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution + {49679C95-28CE-4D35-8F38-3D67A511A3C1} = {D059B679-8B38-44FE-BEC6-8DFF9271CE59} + {987E989A-E48B-428F-A392-0E7EEC9BCECD} = {D059B679-8B38-44FE-BEC6-8DFF9271CE59} + {AB8B83D8-F7B4-4C21-AEB4-B0C5D2217DEF} = {D059B679-8B38-44FE-BEC6-8DFF9271CE59} + {16A563A2-2D02-4B9E-B3F8-F36DD72F4477} = {D059B679-8B38-44FE-BEC6-8DFF9271CE59} + {8046613E-799A-460C-985A-444C0327B49C} = {D059B679-8B38-44FE-BEC6-8DFF9271CE59} + {19385AE1-57CA-4082-AD33-62480D02C1D9} = {D059B679-8B38-44FE-BEC6-8DFF9271CE59} {6DD1A48C-D7A8-4B39-9C06-5A71FEEC70B9} = {54EB52AC-52D0-4046-BDB6-276A5C7ED0F4} {1A83AF16-1AC8-45E3-9E7E-FA7248C7CBCB} = {54EB52AC-52D0-4046-BDB6-276A5C7ED0F4} + {2562C6B4-088E-48AC-B408-15BC99AE6760} = {D059B679-8B38-44FE-BEC6-8DFF9271CE59} + {3B1456C2-1591-4E8C-B71C-C0F25C8EA88E} = {D059B679-8B38-44FE-BEC6-8DFF9271CE59} + {4C525826-D64B-4D2D-8BB3-33AF46649B05} = {54EB52AC-52D0-4046-BDB6-276A5C7ED0F4} + {944A7FDE-890A-45CE-A958-AAE6553E2E24} = {54EB52AC-52D0-4046-BDB6-276A5C7ED0F4} + {C021C74F-C774-483B-8BEE-CB5021CFC6F3} = {D059B679-8B38-44FE-BEC6-8DFF9271CE59} + {F454DBD6-2AB9-461D-9624-2249B921B6E6} = {D059B679-8B38-44FE-BEC6-8DFF9271CE59} EndGlobalSection GlobalSection(TestCaseManagementSettings) = postSolution CategoryFile = Accord.NET.vsmdi diff --git a/Sources/Accord.NET.sln b/Sources/Accord.NET.sln index 6bbd594aa..ad65d8207 100644 --- a/Sources/Accord.NET.sln +++ b/Sources/Accord.NET.sln @@ -20,10 +20,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Controls.Audio", "Accord.Controls.Audio\Accord.Controls.Audio.csproj", "{E0B826AC-2A51-41EC-9F09-561CA14A82BB}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.DirectSound", "Accord.DirectSound\Accord.DirectSound.csproj", "{456DB2E8-745A-4F87-A2BD-C43CF8677770}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Audio.Formats", "Accord.Audio.Formats\Accord.Audio.Formats.csproj", "{EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Audio", "Accord.Audio\Accord.Audio.csproj", "{E7B65F08-82F1-438F-847A-2AAC2BEC9AC0}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Audition", "Accord.Audition\Accord.Audition.csproj", "{CDBEFB1A-10BC-49EC-9833-D2CF6D4F6131}" @@ -94,6 +90,28 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Tests.MachineLearnin EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Tests.Controls", "..\Unit Tests\Accord.Tests.Controls\Accord.Tests.Controls.csproj", "{C021C74F-C774-483B-8BEE-CB5021CFC6F3}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Audio.DirectSound", "Accord.Audio.DirectSound\Accord.Audio.DirectSound.csproj", "{456DB2E8-745A-4F87-A2BD-C43CF8677770}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Fuzzy", "Accord.Fuzzy\Accord.Fuzzy.csproj", "{B631038F-E12C-4D0D-8B25-FF7F62FE62D1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Genetic", "Accord.Genetic\Accord.Genetic.csproj", "{2EFAA327-1789-4438-B9F5-E83ACAE12DB2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Video.DirectShow", "Accord.Video.DirectShow\Accord.Video.DirectShow.csproj", "{26CD2CE7-FF63-4669-83B0-7D9C8F3408EE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Video", "Accord.Video\Accord.Video.csproj", "{809725DC-6502-4732-A51C-DEB7FEA12975}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Video.Kinect", "Accord.Video.Kinect\Accord.Video.Kinect.csproj", "{9DA8E727-4038-4E6B-90BD-853730FDFA49}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Video.VFW", "Accord.Video.VFW\Accord.Video.VFW.csproj", "{22E852C0-17FF-4106-9DF6-41EABB8C0613}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Video.Ximea", "Accord.Video.Ximea\Accord.Video.Ximea.csproj", "{AEDD6CFB-747B-4077-9288-9CD2A86090F1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Accord.Video.FFMPEG (GPL)", "Extras\Accord.Video.FFMPEG.GPL\Video.FFMPEG.vcxproj", "{FF31DD24-127D-4EB1-929C-F5738147E886}" +EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Accord.Tests.Math.FSharp", "..\Unit Tests\Accord.Tests.Math.FSharp\Accord.Tests.Math.FSharp.fsproj", "{79173770-18B0-4703-9E74-15F945B9EFDC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accord.Tests.Math.Interop", "..\Unit Tests\Accord.Tests.Math.Interop\Accord.Tests.Math.Interop.csproj", "{F5820249-C973-4EF3-91B3-4B46F2961816}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -110,22 +128,6 @@ Global {E0B826AC-2A51-41EC-9F09-561CA14A82BB}.NET40|Any CPU.Build.0 = NET40|Any CPU {E0B826AC-2A51-41EC-9F09-561CA14A82BB}.NET45|Any CPU.ActiveCfg = NET45|Any CPU {E0B826AC-2A51-41EC-9F09-561CA14A82BB}.NET45|Any CPU.Build.0 = NET45|Any CPU - {456DB2E8-745A-4F87-A2BD-C43CF8677770}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {456DB2E8-745A-4F87-A2BD-C43CF8677770}.Debug|Any CPU.Build.0 = Debug|Any CPU - {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET35|Any CPU.ActiveCfg = NET35|Any CPU - {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET35|Any CPU.Build.0 = NET35|Any CPU - {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET40|Any CPU.ActiveCfg = NET40|Any CPU - {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET40|Any CPU.Build.0 = NET40|Any CPU - {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET45|Any CPU.ActiveCfg = NET45|Any CPU - {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET45|Any CPU.Build.0 = NET45|Any CPU - {EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF}.NET35|Any CPU.ActiveCfg = NET35|Any CPU - {EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF}.NET35|Any CPU.Build.0 = NET35|Any CPU - {EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF}.NET40|Any CPU.ActiveCfg = NET40|Any CPU - {EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF}.NET40|Any CPU.Build.0 = NET40|Any CPU - {EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF}.NET45|Any CPU.ActiveCfg = NET45|Any CPU - {EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF}.NET45|Any CPU.Build.0 = NET45|Any CPU {E7B65F08-82F1-438F-847A-2AAC2BEC9AC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E7B65F08-82F1-438F-847A-2AAC2BEC9AC0}.Debug|Any CPU.Build.0 = Debug|Any CPU {E7B65F08-82F1-438F-847A-2AAC2BEC9AC0}.NET35|Any CPU.ActiveCfg = NET35|Any CPU @@ -291,14 +293,10 @@ Global {6DD1A48C-D7A8-4B39-9C06-5A71FEEC70B9}.NET45|Any CPU.ActiveCfg = NET45|Any CPU {6DD1A48C-D7A8-4B39-9C06-5A71FEEC70B9}.NET45|Any CPU.Build.0 = NET45|Any CPU {F00F5E2D-D181-4FCC-8F2E-FDCB90F4721B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F00F5E2D-D181-4FCC-8F2E-FDCB90F4721B}.Debug|Any CPU.Build.0 = Debug|Any CPU {F00F5E2D-D181-4FCC-8F2E-FDCB90F4721B}.NET35|Any CPU.ActiveCfg = Debug|Any CPU - {F00F5E2D-D181-4FCC-8F2E-FDCB90F4721B}.NET35|Any CPU.Build.0 = Debug|Any CPU {F00F5E2D-D181-4FCC-8F2E-FDCB90F4721B}.NET40|Any CPU.ActiveCfg = Debug|Any CPU - {F00F5E2D-D181-4FCC-8F2E-FDCB90F4721B}.NET40|Any CPU.Build.0 = Debug|Any CPU {F00F5E2D-D181-4FCC-8F2E-FDCB90F4721B}.NET45|Any CPU.ActiveCfg = Debug|Any CPU {4ED2AB06-991F-44FF-AC01-53394B222AF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4ED2AB06-991F-44FF-AC01-53394B222AF7}.Debug|Any CPU.Build.0 = Debug|Any CPU {4ED2AB06-991F-44FF-AC01-53394B222AF7}.NET35|Any CPU.ActiveCfg = Debug|Any CPU {4ED2AB06-991F-44FF-AC01-53394B222AF7}.NET35|Any CPU.Build.0 = Debug|Any CPU {4ED2AB06-991F-44FF-AC01-53394B222AF7}.NET40|Any CPU.ActiveCfg = NET40|Any CPU @@ -308,6 +306,7 @@ Global {161BD953-537D-4325-8A00-22475FC9088E}.Debug|Any CPU.ActiveCfg = Debug|Win32 {161BD953-537D-4325-8A00-22475FC9088E}.Debug|Any CPU.Build.0 = Debug|Win32 {161BD953-537D-4325-8A00-22475FC9088E}.NET35|Any CPU.ActiveCfg = Debug|Win32 + {161BD953-537D-4325-8A00-22475FC9088E}.NET35|Any CPU.Build.0 = Debug|Win32 {161BD953-537D-4325-8A00-22475FC9088E}.NET40|Any CPU.ActiveCfg = Debug|Win32 {161BD953-537D-4325-8A00-22475FC9088E}.NET40|Any CPU.Build.0 = Debug|Win32 {161BD953-537D-4325-8A00-22475FC9088E}.NET45|Any CPU.ActiveCfg = Debug|Win32 @@ -338,12 +337,12 @@ Global {2562C6B4-088E-48AC-B408-15BC99AE6760}.NET45|Any CPU.Build.0 = NET45|Any CPU {A6775B59-6919-4D7C-A960-7E875F0BD81A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A6775B59-6919-4D7C-A960-7E875F0BD81A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A6775B59-6919-4D7C-A960-7E875F0BD81A}.NET35|Any CPU.ActiveCfg = Release|Any CPU - {A6775B59-6919-4D7C-A960-7E875F0BD81A}.NET35|Any CPU.Build.0 = Release|Any CPU - {A6775B59-6919-4D7C-A960-7E875F0BD81A}.NET40|Any CPU.ActiveCfg = Release|Any CPU - {A6775B59-6919-4D7C-A960-7E875F0BD81A}.NET40|Any CPU.Build.0 = Release|Any CPU - {A6775B59-6919-4D7C-A960-7E875F0BD81A}.NET45|Any CPU.ActiveCfg = Release|Any CPU - {A6775B59-6919-4D7C-A960-7E875F0BD81A}.NET45|Any CPU.Build.0 = Release|Any CPU + {A6775B59-6919-4D7C-A960-7E875F0BD81A}.NET35|Any CPU.ActiveCfg = Debug|Any CPU + {A6775B59-6919-4D7C-A960-7E875F0BD81A}.NET35|Any CPU.Build.0 = Debug|Any CPU + {A6775B59-6919-4D7C-A960-7E875F0BD81A}.NET40|Any CPU.ActiveCfg = Debug|Any CPU + {A6775B59-6919-4D7C-A960-7E875F0BD81A}.NET40|Any CPU.Build.0 = Debug|Any CPU + {A6775B59-6919-4D7C-A960-7E875F0BD81A}.NET45|Any CPU.ActiveCfg = Debug|Any CPU + {A6775B59-6919-4D7C-A960-7E875F0BD81A}.NET45|Any CPU.Build.0 = Debug|Any CPU {3B1456C2-1591-4E8C-B71C-C0F25C8EA88E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3B1456C2-1591-4E8C-B71C-C0F25C8EA88E}.Debug|Any CPU.Build.0 = Debug|Any CPU {3B1456C2-1591-4E8C-B71C-C0F25C8EA88E}.NET35|Any CPU.ActiveCfg = NET35|Any CPU @@ -376,6 +375,94 @@ Global {C021C74F-C774-483B-8BEE-CB5021CFC6F3}.NET40|Any CPU.Build.0 = NET40|Any CPU {C021C74F-C774-483B-8BEE-CB5021CFC6F3}.NET45|Any CPU.ActiveCfg = NET45|Any CPU {C021C74F-C774-483B-8BEE-CB5021CFC6F3}.NET45|Any CPU.Build.0 = NET45|Any CPU + {456DB2E8-745A-4F87-A2BD-C43CF8677770}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {456DB2E8-745A-4F87-A2BD-C43CF8677770}.Debug|Any CPU.Build.0 = Debug|Any CPU + {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET35|Any CPU.Build.0 = NET35|Any CPU + {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET40|Any CPU.Build.0 = NET40|Any CPU + {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {456DB2E8-745A-4F87-A2BD-C43CF8677770}.NET45|Any CPU.Build.0 = NET45|Any CPU + {B631038F-E12C-4D0D-8B25-FF7F62FE62D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B631038F-E12C-4D0D-8B25-FF7F62FE62D1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B631038F-E12C-4D0D-8B25-FF7F62FE62D1}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {B631038F-E12C-4D0D-8B25-FF7F62FE62D1}.NET35|Any CPU.Build.0 = NET35|Any CPU + {B631038F-E12C-4D0D-8B25-FF7F62FE62D1}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {B631038F-E12C-4D0D-8B25-FF7F62FE62D1}.NET40|Any CPU.Build.0 = NET40|Any CPU + {B631038F-E12C-4D0D-8B25-FF7F62FE62D1}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {B631038F-E12C-4D0D-8B25-FF7F62FE62D1}.NET45|Any CPU.Build.0 = NET45|Any CPU + {2EFAA327-1789-4438-B9F5-E83ACAE12DB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2EFAA327-1789-4438-B9F5-E83ACAE12DB2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2EFAA327-1789-4438-B9F5-E83ACAE12DB2}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {2EFAA327-1789-4438-B9F5-E83ACAE12DB2}.NET35|Any CPU.Build.0 = NET35|Any CPU + {2EFAA327-1789-4438-B9F5-E83ACAE12DB2}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {2EFAA327-1789-4438-B9F5-E83ACAE12DB2}.NET40|Any CPU.Build.0 = NET40|Any CPU + {2EFAA327-1789-4438-B9F5-E83ACAE12DB2}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {2EFAA327-1789-4438-B9F5-E83ACAE12DB2}.NET45|Any CPU.Build.0 = NET45|Any CPU + {26CD2CE7-FF63-4669-83B0-7D9C8F3408EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {26CD2CE7-FF63-4669-83B0-7D9C8F3408EE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {26CD2CE7-FF63-4669-83B0-7D9C8F3408EE}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {26CD2CE7-FF63-4669-83B0-7D9C8F3408EE}.NET35|Any CPU.Build.0 = NET35|Any CPU + {26CD2CE7-FF63-4669-83B0-7D9C8F3408EE}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {26CD2CE7-FF63-4669-83B0-7D9C8F3408EE}.NET40|Any CPU.Build.0 = NET40|Any CPU + {26CD2CE7-FF63-4669-83B0-7D9C8F3408EE}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {26CD2CE7-FF63-4669-83B0-7D9C8F3408EE}.NET45|Any CPU.Build.0 = NET45|Any CPU + {809725DC-6502-4732-A51C-DEB7FEA12975}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {809725DC-6502-4732-A51C-DEB7FEA12975}.Debug|Any CPU.Build.0 = Debug|Any CPU + {809725DC-6502-4732-A51C-DEB7FEA12975}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {809725DC-6502-4732-A51C-DEB7FEA12975}.NET35|Any CPU.Build.0 = NET35|Any CPU + {809725DC-6502-4732-A51C-DEB7FEA12975}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {809725DC-6502-4732-A51C-DEB7FEA12975}.NET40|Any CPU.Build.0 = NET40|Any CPU + {809725DC-6502-4732-A51C-DEB7FEA12975}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {809725DC-6502-4732-A51C-DEB7FEA12975}.NET45|Any CPU.Build.0 = NET45|Any CPU + {9DA8E727-4038-4E6B-90BD-853730FDFA49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9DA8E727-4038-4E6B-90BD-853730FDFA49}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9DA8E727-4038-4E6B-90BD-853730FDFA49}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {9DA8E727-4038-4E6B-90BD-853730FDFA49}.NET35|Any CPU.Build.0 = NET35|Any CPU + {9DA8E727-4038-4E6B-90BD-853730FDFA49}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {9DA8E727-4038-4E6B-90BD-853730FDFA49}.NET40|Any CPU.Build.0 = NET40|Any CPU + {9DA8E727-4038-4E6B-90BD-853730FDFA49}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {9DA8E727-4038-4E6B-90BD-853730FDFA49}.NET45|Any CPU.Build.0 = NET45|Any CPU + {22E852C0-17FF-4106-9DF6-41EABB8C0613}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {22E852C0-17FF-4106-9DF6-41EABB8C0613}.Debug|Any CPU.Build.0 = Debug|Any CPU + {22E852C0-17FF-4106-9DF6-41EABB8C0613}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {22E852C0-17FF-4106-9DF6-41EABB8C0613}.NET35|Any CPU.Build.0 = NET35|Any CPU + {22E852C0-17FF-4106-9DF6-41EABB8C0613}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {22E852C0-17FF-4106-9DF6-41EABB8C0613}.NET40|Any CPU.Build.0 = NET40|Any CPU + {22E852C0-17FF-4106-9DF6-41EABB8C0613}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {22E852C0-17FF-4106-9DF6-41EABB8C0613}.NET45|Any CPU.Build.0 = NET45|Any CPU + {AEDD6CFB-747B-4077-9288-9CD2A86090F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AEDD6CFB-747B-4077-9288-9CD2A86090F1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AEDD6CFB-747B-4077-9288-9CD2A86090F1}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {AEDD6CFB-747B-4077-9288-9CD2A86090F1}.NET35|Any CPU.Build.0 = NET35|Any CPU + {AEDD6CFB-747B-4077-9288-9CD2A86090F1}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {AEDD6CFB-747B-4077-9288-9CD2A86090F1}.NET40|Any CPU.Build.0 = NET40|Any CPU + {AEDD6CFB-747B-4077-9288-9CD2A86090F1}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {AEDD6CFB-747B-4077-9288-9CD2A86090F1}.NET45|Any CPU.Build.0 = NET45|Any CPU + {FF31DD24-127D-4EB1-929C-F5738147E886}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {FF31DD24-127D-4EB1-929C-F5738147E886}.Debug|Any CPU.Build.0 = Debug|Win32 + {FF31DD24-127D-4EB1-929C-F5738147E886}.NET35|Any CPU.ActiveCfg = NET35|Win32 + {FF31DD24-127D-4EB1-929C-F5738147E886}.NET35|Any CPU.Build.0 = NET35|Win32 + {FF31DD24-127D-4EB1-929C-F5738147E886}.NET40|Any CPU.ActiveCfg = NET40|Win32 + {FF31DD24-127D-4EB1-929C-F5738147E886}.NET40|Any CPU.Build.0 = NET40|Win32 + {FF31DD24-127D-4EB1-929C-F5738147E886}.NET45|Any CPU.ActiveCfg = NET45|Win32 + {FF31DD24-127D-4EB1-929C-F5738147E886}.NET45|Any CPU.Build.0 = NET45|Win32 + {79173770-18B0-4703-9E74-15F945B9EFDC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {79173770-18B0-4703-9E74-15F945B9EFDC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {79173770-18B0-4703-9E74-15F945B9EFDC}.NET35|Any CPU.ActiveCfg = Debug|Any CPU + {79173770-18B0-4703-9E74-15F945B9EFDC}.NET35|Any CPU.Build.0 = Debug|Any CPU + {79173770-18B0-4703-9E74-15F945B9EFDC}.NET40|Any CPU.ActiveCfg = Debug|Any CPU + {79173770-18B0-4703-9E74-15F945B9EFDC}.NET40|Any CPU.Build.0 = Debug|Any CPU + {79173770-18B0-4703-9E74-15F945B9EFDC}.NET45|Any CPU.ActiveCfg = Debug|Any CPU + {79173770-18B0-4703-9E74-15F945B9EFDC}.NET45|Any CPU.Build.0 = Debug|Any CPU + {F5820249-C973-4EF3-91B3-4B46F2961816}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F5820249-C973-4EF3-91B3-4B46F2961816}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F5820249-C973-4EF3-91B3-4B46F2961816}.NET35|Any CPU.ActiveCfg = NET35|Any CPU + {F5820249-C973-4EF3-91B3-4B46F2961816}.NET35|Any CPU.Build.0 = NET35|Any CPU + {F5820249-C973-4EF3-91B3-4B46F2961816}.NET40|Any CPU.ActiveCfg = NET40|Any CPU + {F5820249-C973-4EF3-91B3-4B46F2961816}.NET40|Any CPU.Build.0 = NET40|Any CPU + {F5820249-C973-4EF3-91B3-4B46F2961816}.NET45|Any CPU.ActiveCfg = NET45|Any CPU + {F5820249-C973-4EF3-91B3-4B46F2961816}.NET45|Any CPU.Build.0 = NET45|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -400,6 +487,9 @@ Global {4C525826-D64B-4D2D-8BB3-33AF46649B05} = {54EB52AC-52D0-4046-BDB6-276A5C7ED0F4} {944A7FDE-890A-45CE-A958-AAE6553E2E24} = {54EB52AC-52D0-4046-BDB6-276A5C7ED0F4} {C021C74F-C774-483B-8BEE-CB5021CFC6F3} = {D059B679-8B38-44FE-BEC6-8DFF9271CE59} + {FF31DD24-127D-4EB1-929C-F5738147E886} = {54EB52AC-52D0-4046-BDB6-276A5C7ED0F4} + {79173770-18B0-4703-9E74-15F945B9EFDC} = {D059B679-8B38-44FE-BEC6-8DFF9271CE59} + {F5820249-C973-4EF3-91B3-4B46F2961816} = {D059B679-8B38-44FE-BEC6-8DFF9271CE59} EndGlobalSection GlobalSection(TestCaseManagementSettings) = postSolution CategoryFile = Accord.NET.vsmdi diff --git a/Sources/Accord.Neuro/AForge/Activation Functions/BipolarSigmoidFunction.cs b/Sources/Accord.Neuro/AForge/Activation Functions/BipolarSigmoidFunction.cs new file mode 100644 index 0000000000..58d913bc5 --- /dev/null +++ b/Sources/Accord.Neuro/AForge/Activation Functions/BipolarSigmoidFunction.cs @@ -0,0 +1,144 @@ +// AForge Neural Net Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2012 +// contacts@aforgenet.com +// + +namespace AForge.Neuro +{ + using System; + + /// + /// Bipolar sigmoid activation function. + /// + /// + /// The class represents bipolar sigmoid activation function with + /// the next expression: + /// + /// 2 + /// f(x) = ------------------ - 1 + /// 1 + exp(-alpha * x) + /// + /// 2 * alpha * exp(-alpha * x ) + /// f'(x) = -------------------------------- = alpha * (1 - f(x)^2) / 2 + /// (1 + exp(-alpha * x))^2 + /// + /// + /// + /// Output range of the function: [-1, 1]. + /// + /// Functions graph: + /// + /// + /// + [Serializable] + public class BipolarSigmoidFunction : IActivationFunction, ICloneable + { + // sigmoid's alpha value + private double alpha = 2; + + /// + /// Sigmoid's alpha value. + /// + /// + /// The value determines steepness of the function. Increasing value of + /// this property changes sigmoid to look more like a threshold function. Decreasing + /// value of this property makes sigmoid to be very smooth (slowly growing from its + /// minimum value to its maximum value). + /// + /// Default value is set to 2. + /// + /// + public double Alpha + { + get { return alpha; } + set { alpha = value; } + } + + /// + /// Initializes a new instance of the class. + /// + public BipolarSigmoidFunction( ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Sigmoid's alpha value. + /// + public BipolarSigmoidFunction( double alpha ) + { + this.alpha = alpha; + } + + /// + /// Calculates function value. + /// + /// + /// Function input value. + /// + /// Function output value, f(x). + /// + /// The method calculates function value at point . + /// + public double Function( double x ) + { + return ( ( 2 / ( 1 + Math.Exp( -alpha * x ) ) ) - 1 ); + } + + /// + /// Calculates function derivative. + /// + /// + /// Function input value. + /// + /// Function derivative, f'(x). + /// + /// The method calculates function derivative at point . + /// + public double Derivative( double x ) + { + double y = Function( x ); + + return ( alpha * ( 1 - y * y ) / 2 ); + } + + /// + /// Calculates function derivative. + /// + /// + /// Function output value - the value, which was obtained + /// with the help of method. + /// + /// Function derivative, f'(x). + /// + /// The method calculates the same derivative value as the + /// method, but it takes not the input x value + /// itself, but the function value, which was calculated previously with + /// the help of method. + /// + /// Some applications require as function value, as derivative value, + /// so they can save the amount of calculations using this method to calculate derivative. + /// + /// + public double Derivative2( double y ) + { + return ( alpha * ( 1 - y * y ) / 2 ); + } + + /// + /// Creates a new object that is a copy of the current instance. + /// + /// + /// + /// A new object that is a copy of this instance. + /// + /// + public object Clone( ) + { + return new BipolarSigmoidFunction( alpha ); + } + } +} diff --git a/Sources/Accord.Neuro/AForge/Activation Functions/IActivationFunction.cs b/Sources/Accord.Neuro/AForge/Activation Functions/IActivationFunction.cs new file mode 100644 index 0000000000..c64ee862e --- /dev/null +++ b/Sources/Accord.Neuro/AForge/Activation Functions/IActivationFunction.cs @@ -0,0 +1,67 @@ +// AForge Neural Net Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2005-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Neuro +{ + using System; + + /// + /// Activation function interface. + /// + /// + /// All activation functions, which are supposed to be used with + /// neurons, which calculate their output as a function of weighted sum of + /// their inputs, should implement this interfaces. + /// + /// + public interface IActivationFunction + { + /// + /// Calculates function value. + /// + /// + /// Function input value. + /// + /// Function output value, f(x). + /// + /// The method calculates function value at point . + /// + double Function( double x ); + + /// + /// Calculates function derivative. + /// + /// + /// Function input value. + /// + /// Function derivative, f'(x). + /// + /// The method calculates function derivative at point . + /// + double Derivative( double x ); + + /// + /// Calculates function derivative. + /// + /// + /// Function output value - the value, which was obtained + /// with the help of method. + /// + /// Function derivative, f'(x). + /// + /// The method calculates the same derivative value as the + /// method, but it takes not the input x value + /// itself, but the function value, which was calculated previously with + /// the help of method. + /// + /// Some applications require as function value, as derivative value, + /// so they can save the amount of calculations using this method to calculate derivative. + /// + /// + double Derivative2( double y ); + } +} diff --git a/Sources/Accord.Neuro/AForge/Activation Functions/SigmoidFunction.cs b/Sources/Accord.Neuro/AForge/Activation Functions/SigmoidFunction.cs new file mode 100644 index 0000000000..80a624360 --- /dev/null +++ b/Sources/Accord.Neuro/AForge/Activation Functions/SigmoidFunction.cs @@ -0,0 +1,145 @@ +// AForge Neural Net Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2012 +// contacts@aforgenet.com +// + +namespace AForge.Neuro +{ + using System; + + /// + /// Sigmoid activation function. + /// + /// + /// The class represents sigmoid activation function with + /// the next expression: + /// + /// 1 + /// f(x) = ------------------ + /// 1 + exp(-alpha * x) + /// + /// alpha * exp(-alpha * x ) + /// f'(x) = ---------------------------- = alpha * f(x) * (1 - f(x)) + /// (1 + exp(-alpha * x))^2 + /// + /// + /// + /// Output range of the function: [0, 1]. + /// + /// Functions graph: + /// + /// + /// + [Serializable] + public class SigmoidFunction : IActivationFunction, ICloneable + { + // sigmoid's alpha value + private double alpha = 2; + + /// + /// Sigmoid's alpha value. + /// + /// + /// The value determines steepness of the function. Increasing value of + /// this property changes sigmoid to look more like a threshold function. Decreasing + /// value of this property makes sigmoid to be very smooth (slowly growing from its + /// minimum value to its maximum value). + /// + /// Default value is set to 2. + /// + /// + public double Alpha + { + get { return alpha; } + set { alpha = value; } + } + + /// + /// Initializes a new instance of the class. + /// + public SigmoidFunction( ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Sigmoid's alpha value. + /// + public SigmoidFunction( double alpha ) + { + this.alpha = alpha; + } + + + /// + /// Calculates function value. + /// + /// + /// Function input value. + /// + /// Function output value, f(x). + /// + /// The method calculates function value at point . + /// + public double Function( double x ) + { + return ( 1 / ( 1 + Math.Exp( -alpha * x ) ) ); + } + + /// + /// Calculates function derivative. + /// + /// + /// Function input value. + /// + /// Function derivative, f'(x). + /// + /// The method calculates function derivative at point . + /// + public double Derivative( double x ) + { + double y = Function( x ); + + return ( alpha * y * ( 1 - y ) ); + } + + /// + /// Calculates function derivative. + /// + /// + /// Function output value - the value, which was obtained + /// with the help of method. + /// + /// Function derivative, f'(x). + /// + /// The method calculates the same derivative value as the + /// method, but it takes not the input x value + /// itself, but the function value, which was calculated previously with + /// the help of method. + /// + /// Some applications require as function value, as derivative value, + /// so they can save the amount of calculations using this method to calculate derivative. + /// + /// + public double Derivative2( double y ) + { + return ( alpha * y * ( 1 - y ) ); + } + + /// + /// Creates a new object that is a copy of the current instance. + /// + /// + /// + /// A new object that is a copy of this instance. + /// + /// + public object Clone( ) + { + return new SigmoidFunction( alpha ); + } + } +} diff --git a/Sources/Accord.Neuro/AForge/Activation Functions/ThresholdFunction.cs b/Sources/Accord.Neuro/AForge/Activation Functions/ThresholdFunction.cs new file mode 100644 index 0000000000..3aaaa9e71 --- /dev/null +++ b/Sources/Accord.Neuro/AForge/Activation Functions/ThresholdFunction.cs @@ -0,0 +1,98 @@ +// AForge Neural Net Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2012 +// contacts@aforgenet.com +// + +namespace AForge.Neuro +{ + using System; + + /// + /// Threshold activation function. + /// + /// + /// The class represents threshold activation function with + /// the next expression: + /// + /// f(x) = 1, if x >= 0, otherwise 0 + /// + /// + /// + /// Output range of the function: [0, 1]. + /// + /// Functions graph: + /// + /// + /// + [Serializable] + public class ThresholdFunction : IActivationFunction, ICloneable + { + /// + /// Initializes a new instance of the class. + /// + public ThresholdFunction( ) { } + + /// + /// Calculates function value. + /// + /// + /// Function input value. + /// + /// Function output value, f(x). + /// + /// The method calculates function value at point . + /// + public double Function( double x ) + { + return ( x >= 0 ) ? 1 : 0; + } + + /// + /// Calculates function derivative (not supported). + /// + /// + /// Input value. + /// + /// Always returns 0. + /// + /// The method is not supported, because it is not possible to + /// calculate derivative of the function. + /// + public double Derivative( double x ) + { + return 0; + } + + /// + /// Calculates function derivative (not supported). + /// + /// + /// Input value. + /// + /// Always returns 0. + /// + /// The method is not supported, because it is not possible to + /// calculate derivative of the function. + /// + public double Derivative2( double y ) + { + return 0; + } + + /// + /// Creates a new object that is a copy of the current instance. + /// + /// + /// + /// A new object that is a copy of this instance. + /// + /// + public object Clone( ) + { + return new ThresholdFunction( ); + } + } +} diff --git a/Sources/Accord.Neuro/AForge/Images/sigmoid.bmp b/Sources/Accord.Neuro/AForge/Images/sigmoid.bmp new file mode 100644 index 0000000000..930daf05c Binary files /dev/null and b/Sources/Accord.Neuro/AForge/Images/sigmoid.bmp differ diff --git a/Sources/Accord.Neuro/AForge/Images/sigmoid_bipolar.bmp b/Sources/Accord.Neuro/AForge/Images/sigmoid_bipolar.bmp new file mode 100644 index 0000000000..9f5dfe1c1 Binary files /dev/null and b/Sources/Accord.Neuro/AForge/Images/sigmoid_bipolar.bmp differ diff --git a/Sources/Accord.Neuro/AForge/Images/threshold.bmp b/Sources/Accord.Neuro/AForge/Images/threshold.bmp new file mode 100644 index 0000000000..5da4e66cb Binary files /dev/null and b/Sources/Accord.Neuro/AForge/Images/threshold.bmp differ diff --git a/Sources/Accord.Neuro/AForge/Layers/ActivationLayer.cs b/Sources/Accord.Neuro/AForge/Layers/ActivationLayer.cs new file mode 100644 index 0000000000..f93135ca3 --- /dev/null +++ b/Sources/Accord.Neuro/AForge/Layers/ActivationLayer.cs @@ -0,0 +1,60 @@ +// AForge Neural Net Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2012 +// contacts@aforgenet.com +// + +namespace AForge.Neuro +{ + using System; + + /// + /// Activation layer. + /// + /// + /// Activation layer is a layer of activation neurons. + /// The layer is usually used in multi-layer neural networks. + /// + [Serializable] + public class ActivationLayer : Layer + { + + /// + /// Initializes a new instance of the class. + /// + /// + /// Layer's neurons count. + /// Layer's inputs count. + /// Activation function of neurons of the layer. + /// + /// The new layer is randomized (see + /// method) after it is created. + /// + public ActivationLayer( int neuronsCount, int inputsCount, IActivationFunction function ) + : base( neuronsCount, inputsCount ) + { + // create each neuron + for ( int i = 0; i < neurons.Length; i++ ) + neurons[i] = new ActivationNeuron( inputsCount, function ); + } + + /// + /// Set new activation function for all neurons of the layer. + /// + /// + /// Activation function to set. + /// + /// The methods sets new activation function for each neuron by setting + /// their property. + /// + public void SetActivationFunction( IActivationFunction function ) + { + for ( int i = 0; i < neurons.Length; i++ ) + { + ( (ActivationNeuron) neurons[i] ).ActivationFunction = function; + } + } + } +} diff --git a/Sources/Accord.Neuro/AForge/Layers/DistanceLayer.cs b/Sources/Accord.Neuro/AForge/Layers/DistanceLayer.cs new file mode 100644 index 0000000000..2cfb96662 --- /dev/null +++ b/Sources/Accord.Neuro/AForge/Layers/DistanceLayer.cs @@ -0,0 +1,43 @@ +// AForge Neural Net Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2012 +// contacts@aforgenet.com +// + +namespace AForge.Neuro +{ + using System; + + /// + /// Distance layer. + /// + /// + /// Distance layer is a layer of distance neurons. + /// The layer is usually a single layer of such networks as Kohonen Self + /// Organizing Map, Elastic Net, Hamming Memory Net. + /// + [Serializable] + public class DistanceLayer : Layer + { + + /// + /// Initializes a new instance of the class. + /// + /// + /// Layer's neurons count. + /// Layer's inputs count. + /// + /// The new layet is randomized (see + /// method) after it is created. + /// + public DistanceLayer( int neuronsCount, int inputsCount ) + : base( neuronsCount, inputsCount ) + { + // create each neuron + for ( int i = 0; i < neuronsCount; i++ ) + neurons[i] = new DistanceNeuron( inputsCount ); + } + } +} diff --git a/Sources/Accord.Neuro/AForge/Layers/Layer.cs b/Sources/Accord.Neuro/AForge/Layers/Layer.cs new file mode 100644 index 0000000000..6cb6ca6ee --- /dev/null +++ b/Sources/Accord.Neuro/AForge/Layers/Layer.cs @@ -0,0 +1,143 @@ +// AForge Neural Net Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2012 +// contacts@aforgenet.com +// + +namespace AForge.Neuro +{ + using System; + + /// + /// Base neural layer class. + /// + /// + /// This is a base neural layer class, which represents + /// collection of neurons. + /// + [Serializable] + public abstract class Layer + { + /// + /// Layer's inputs count. + /// + protected int inputsCount = 0; + + /// + /// Layer's neurons count. + /// + protected int neuronsCount = 0; + + /// + /// Layer's neurons. + /// + protected Neuron[] neurons; + + /// + /// Layer's output vector. + /// + protected double[] output; + + /// + /// Layer's inputs count. + /// + public int InputsCount + { + get { return inputsCount; } + } + + /// + /// Layer's neurons. + /// + /// + public Neuron[] Neurons + { + get { return neurons; } + } + + /// + /// Layer's output vector. + /// + /// + /// The calculation way of layer's output vector is determined by neurons, + /// which comprise the layer. + /// + /// The property is not initialized (equals to ) until + /// method is called. + /// + /// + public double[] Output + { + get { return output; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Layer's neurons count. + /// Layer's inputs count. + /// + /// Protected contructor, which initializes , + /// and members. + /// + protected Layer( int neuronsCount, int inputsCount ) + { + this.inputsCount = Math.Max( 1, inputsCount ); + this.neuronsCount = Math.Max( 1, neuronsCount ); + // create collection of neurons + neurons = new Neuron[this.neuronsCount]; + } + + /// + /// Compute output vector of the layer. + /// + /// + /// Input vector. + /// + /// Returns layer's output vector. + /// + /// The actual layer's output vector is determined by neurons, + /// which comprise the layer - consists of output values of layer's neurons. + /// The output vector is also stored in property. + /// + /// The method may be called safely from multiple threads to compute layer's + /// output value for the specified input values. However, the value of + /// property in multi-threaded environment is not predictable, + /// since it may hold layer's output computed from any of the caller threads. Multi-threaded + /// access to the method is useful in those cases when it is required to improve performance + /// by utilizing several threads and the computation is based on the immediate return value + /// of the method, but not on layer's output property. + /// + /// + public virtual double[] Compute( double[] input ) + { + // local variable to avoid mutlithread conflicts + double[] output = new double[neuronsCount]; + + // compute each neuron + for ( int i = 0; i < neurons.Length; i++ ) + output[i] = neurons[i].Compute( input ); + + // assign output property as well (works correctly for single threaded usage) + this.output = output; + + return output; + } + + /// + /// Randomize neurons of the layer. + /// + /// + /// Randomizes layer's neurons by calling method + /// of each neuron. + /// + public virtual void Randomize( ) + { + foreach ( Neuron neuron in neurons ) + neuron.Randomize( ); + } + } +} diff --git a/Sources/Accord.Neuro/AForge/Learning/BackPropagationLearning.cs b/Sources/Accord.Neuro/AForge/Learning/BackPropagationLearning.cs new file mode 100644 index 0000000000..0cf613741 --- /dev/null +++ b/Sources/Accord.Neuro/AForge/Learning/BackPropagationLearning.cs @@ -0,0 +1,375 @@ +// AForge Neural Net Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2012 +// contacts@aforgenet.com +// +// Copyright Cezary Wagner, 2008 +// changes optimizing algorithm performance +// Cezary.Wagner@gmail.com +// + +namespace AForge.Neuro.Learning +{ + using System; + + /// + /// Back propagation learning algorithm. + /// + /// + /// The class implements back propagation learning algorithm, + /// which is widely used for training multi-layer neural networks with + /// continuous activation functions. + /// + /// Sample usage (training network to calculate XOR function): + /// + /// // initialize input and output values + /// double[][] input = new double[4][] { + /// new double[] {0, 0}, new double[] {0, 1}, + /// new double[] {1, 0}, new double[] {1, 1} + /// }; + /// double[][] output = new double[4][] { + /// new double[] {0}, new double[] {1}, + /// new double[] {1}, new double[] {0} + /// }; + /// // create neural network + /// ActivationNetwork network = new ActivationNetwork( + /// SigmoidFunction( 2 ), + /// 2, // two inputs in the network + /// 2, // two neurons in the first layer + /// 1 ); // one neuron in the second layer + /// // create teacher + /// BackPropagationLearning teacher = new BackPropagationLearning( network ); + /// // loop + /// while ( !needToStop ) + /// { + /// // run epoch of learning procedure + /// double error = teacher.RunEpoch( input, output ); + /// // check error value to see if we need to stop + /// // ... + /// } + /// + /// + /// + /// + /// + public class BackPropagationLearning : ISupervisedLearning + { + // network to teach + private ActivationNetwork network; + // learning rate + private double learningRate = 0.1; + // momentum + private double momentum = 0.0; + + // neuron's errors + private double[][] neuronErrors = null; + // weight's updates + private double[][][] weightsUpdates = null; + // threshold's updates + private double[][] thresholdsUpdates = null; + + /// + /// Learning rate, [0, 1]. + /// + /// + /// The value determines speed of learning. + /// + /// Default value equals to 0.1. + /// + /// + public double LearningRate + { + get { return learningRate; } + set + { + learningRate = Math.Max(0.0, Math.Min(1.0, value)); + } + } + + /// + /// Momentum, [0, 1]. + /// + /// + /// The value determines the portion of previous weight's update + /// to use on current iteration. Weight's update values are calculated on + /// each iteration depending on neuron's error. The momentum specifies the amount + /// of update to use from previous iteration and the amount of update + /// to use from current iteration. If the value is equal to 0.1, for example, + /// then 0.1 portion of previous update and 0.9 portion of current update are used + /// to update weight's value. + /// + /// Default value equals to 0.0. + /// + /// + public double Momentum + { + get { return momentum; } + set + { + momentum = Math.Max(0.0, Math.Min(1.0, value)); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Network to teach. + /// + public BackPropagationLearning(ActivationNetwork network) + { + this.network = network; + + // create error and deltas arrays + neuronErrors = new double[network.Layers.Length][]; + weightsUpdates = new double[network.Layers.Length][][]; + thresholdsUpdates = new double[network.Layers.Length][]; + + // initialize errors and deltas arrays for each layer + for (int i = 0; i < network.Layers.Length; i++) + { + Layer layer = network.Layers[i]; + + neuronErrors[i] = new double[layer.Neurons.Length]; + weightsUpdates[i] = new double[layer.Neurons.Length][]; + thresholdsUpdates[i] = new double[layer.Neurons.Length]; + + // for each neuron + for (int j = 0; j < weightsUpdates[i].Length; j++) + { + weightsUpdates[i][j] = new double[layer.InputsCount]; + } + } + } + + /// + /// Runs learning iteration. + /// + /// + /// Input vector. + /// Desired output vector. + /// + /// Returns squared error (difference between current network's output and + /// desired output) divided by 2. + /// + /// Runs one learning iteration and updates neuron's + /// weights. + /// + public double Run(double[] input, double[] output) + { + // compute the network's output + network.Compute(input); + + // calculate network error + double error = CalculateError(output); + + // calculate weights updates + CalculateUpdates(input); + + // update the network + UpdateNetwork(); + + return error; + } + + /// + /// Runs learning epoch. + /// + /// + /// Array of input vectors. + /// Array of output vectors. + /// + /// Returns summary learning error for the epoch. See + /// method for details about learning error calculation. + /// + /// The method runs one learning epoch, by calling method + /// for each vector provided in the array. + /// + public double RunEpoch(double[][] input, double[][] output) + { + double error = 0.0; + + // run learning procedure for all samples + for (int i = 0; i < input.Length; i++) + { + error += Run(input[i], output[i]); + } + + // return summary error + return error; + } + + + /// + /// Calculates error values for all neurons of the network. + /// + /// + /// Desired output vector. + /// + /// Returns summary squared error of the last layer divided by 2. + /// + private double CalculateError(double[] desiredOutput) + { + // current and the next layers + Layer layer, layerNext; + // current and the next errors arrays + double[] errors, errorsNext; + // error values + double error = 0, e, sum; + // neuron's output value + double output; + // layers count + int layersCount = network.Layers.Length; + + // assume, that all neurons of the network have the same activation function + IActivationFunction function = (network.Layers[0].Neurons[0] as ActivationNeuron).ActivationFunction; + + // calculate error values for the last layer first + layer = network.Layers[layersCount - 1]; + errors = neuronErrors[layersCount - 1]; + + for (int i = 0; i < layer.Neurons.Length; i++) + { + output = layer.Neurons[i].Output; + // error of the neuron + e = desiredOutput[i] - output; + // error multiplied with activation function's derivative + errors[i] = e * function.Derivative2(output); + // squre the error and sum it + error += (e * e); + } + + // calculate error values for other layers + for (int j = layersCount - 2; j >= 0; j--) + { + layer = network.Layers[j]; + layerNext = network.Layers[j + 1]; + errors = neuronErrors[j]; + errorsNext = neuronErrors[j + 1]; + + // for all neurons of the layer + for (int i = 0; i < layer.Neurons.Length; i++) + { + sum = 0.0; + // for all neurons of the next layer + for (int k = 0; k < layerNext.Neurons.Length; k++) + { + sum += errorsNext[k] * layerNext.Neurons[k].Weights[i]; + } + errors[i] = sum * function.Derivative2(layer.Neurons[i].Output); + } + } + + // return squared error of the last layer divided by 2 + return error / 2.0; + } + + /// + /// Calculate weights updates. + /// + /// + /// Network's input vector. + /// + private void CalculateUpdates(double[] input) + { + // 1 - calculate updates for the first layer + Layer layer = network.Layers[0]; + double[] errors = neuronErrors[0]; + double[][] layerWeightsUpdates = weightsUpdates[0]; + double[] layerThresholdUpdates = thresholdsUpdates[0]; + + // cache for frequently used values + double cachedMomentum = learningRate * momentum; + double cached1mMomentum = learningRate * (1 - momentum); + double cachedError; + + // for each neuron of the layer + for (int i = 0; i < layer.Neurons.Length; i++) + { + cachedError = errors[i] * cached1mMomentum; + double[] neuronWeightUpdates = layerWeightsUpdates[i]; + + // for each weight of the neuron + for (int j = 0; j < neuronWeightUpdates.Length; j++) + { + // calculate weight update + neuronWeightUpdates[j] = cachedMomentum * neuronWeightUpdates[j] + cachedError * input[j]; + } + + // calculate threshold update + layerThresholdUpdates[i] = cachedMomentum * layerThresholdUpdates[i] + cachedError; + } + + // 2 - for all other layers + for (int k = 1; k < network.Layers.Length; k++) + { + Layer layerPrev = network.Layers[k - 1]; + layer = network.Layers[k]; + errors = neuronErrors[k]; + layerWeightsUpdates = weightsUpdates[k]; + layerThresholdUpdates = thresholdsUpdates[k]; + + // for each neuron of the layer + for (int i = 0; i < layer.Neurons.Length; i++) + { + cachedError = errors[i] * cached1mMomentum; + double[] neuronWeightUpdates = layerWeightsUpdates[i]; + + // for each synapse of the neuron + for (int j = 0; j < neuronWeightUpdates.Length; j++) + { + // calculate weight update + neuronWeightUpdates[j] = cachedMomentum * neuronWeightUpdates[j] + cachedError * layerPrev.Neurons[j].Output; + } + + // calculate threshold update + layerThresholdUpdates[i] = cachedMomentum * layerThresholdUpdates[i] + cachedError; + } + } + } + + /// + /// Update network's weights. + /// + /// + private void UpdateNetwork() + { + // current neuron + ActivationNeuron neuron; + // current layer + Layer layer; + // layer's weights updates + double[][] layerWeightsUpdates; + // layer's thresholds updates + double[] layerThresholdUpdates; + // neuron's weights updates + double[] neuronWeightUpdates; + + // for each layer of the network + for (int i = 0; i < network.Layers.Length; i++) + { + layer = network.Layers[i]; + layerWeightsUpdates = weightsUpdates[i]; + layerThresholdUpdates = thresholdsUpdates[i]; + + // for each neuron of the layer + for (int j = 0; j < layer.Neurons.Length; j++) + { + neuron = layer.Neurons[j] as ActivationNeuron; + neuronWeightUpdates = layerWeightsUpdates[j]; + + // for each weight of the neuron + for (int k = 0; k < neuron.Weights.Length; k++) + { + // update weight + neuron.Weights[k] += neuronWeightUpdates[k]; + } + // update treshold + neuron.Threshold += layerThresholdUpdates[j]; + } + } + } + } +} diff --git a/Sources/Accord.Neuro/AForge/Learning/DeltaRuleLearning.cs b/Sources/Accord.Neuro/AForge/Learning/DeltaRuleLearning.cs new file mode 100644 index 0000000000..51b793771 --- /dev/null +++ b/Sources/Accord.Neuro/AForge/Learning/DeltaRuleLearning.cs @@ -0,0 +1,149 @@ +// AForge Neural Net Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2012 +// contacts@aforgenet.com +// + +namespace AForge.Neuro.Learning +{ + using System; + + /// + /// Delta rule learning algorithm. + /// + /// + /// This learning algorithm is used to train one layer neural + /// network of Activation Neurons + /// with continuous activation function, see + /// for example. + /// + /// See information about delta rule + /// learning algorithm. + /// + /// + public class DeltaRuleLearning : ISupervisedLearning + { + // network to teach + private ActivationNetwork network; + // learning rate + private double learningRate = 0.1; + + /// + /// Learning rate, [0, 1]. + /// + /// + /// The value determines speed of learning. + /// + /// Default value equals to 0.1. + /// + /// + public double LearningRate + { + get { return learningRate; } + set + { + learningRate = Math.Max( 0.0, Math.Min( 1.0, value ) ); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Network to teach. + /// + /// Invalid nuaral network. It should have one layer only. + /// + public DeltaRuleLearning( ActivationNetwork network ) + { + // check layers count + if ( network.Layers.Length != 1 ) + { + throw new ArgumentException( "Invalid nuaral network. It should have one layer only." ); + } + + this.network = network; + } + + /// + /// Runs learning iteration. + /// + /// + /// Input vector. + /// Desired output vector. + /// + /// Returns squared error (difference between current network's output and + /// desired output) divided by 2. + /// + /// Runs one learning iteration and updates neuron's + /// weights. + /// + public double Run( double[] input, double[] output ) + { + // compute output of network + double[] networkOutput = network.Compute( input ); + + // get the only layer of the network + Layer layer = network.Layers[0]; + // get activation function of the layer + IActivationFunction activationFunction = ( layer.Neurons[0] as ActivationNeuron ).ActivationFunction; + + // summary network absolute error + double error = 0.0; + + // update weights of each neuron + for ( int j = 0; j < layer.Neurons.Length; j++ ) + { + // get neuron of the layer + ActivationNeuron neuron = layer.Neurons[j] as ActivationNeuron; + // calculate neuron's error + double e = output[j] - networkOutput[j]; + // get activation function's derivative + double functionDerivative = activationFunction.Derivative2( networkOutput[j] ); + + // update weights + for ( int i = 0; i < neuron.Weights.Length; i++ ) + { + neuron.Weights[i] += learningRate * e * functionDerivative * input[i]; + } + + // update threshold value + neuron.Threshold += learningRate * e * functionDerivative; + + // sum error + error += ( e * e ); + } + + return error / 2; + } + + /// + /// Runs learning epoch. + /// + /// + /// Array of input vectors. + /// Array of output vectors. + /// + /// Returns summary learning error for the epoch. See + /// method for details about learning error calculation. + /// + /// The method runs one learning epoch, by calling method + /// for each vector provided in the array. + /// + public double RunEpoch( double[][] input, double[][] output ) + { + double error = 0.0; + + // run learning procedure for all samples + for ( int i = 0, n = input.Length; i < n; i++ ) + { + error += Run( input[i], output[i] ); + } + + // return summary error + return error; + } + } +} diff --git a/Sources/Accord.Neuro/AForge/Learning/ElasticNetworkLearning.cs b/Sources/Accord.Neuro/AForge/Learning/ElasticNetworkLearning.cs new file mode 100644 index 0000000000..f90a36631 --- /dev/null +++ b/Sources/Accord.Neuro/AForge/Learning/ElasticNetworkLearning.cs @@ -0,0 +1,180 @@ +// AForge Neural Net Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2012 +// contacts@aforgenet.com +// + +namespace AForge.Neuro.Learning +{ + using System; + + /// + /// Elastic network learning algorithm. + /// + /// + /// This class implements elastic network's learning algorithm and + /// allows to train Distance Networks. + /// + /// + public class ElasticNetworkLearning : IUnsupervisedLearning + { + // neural network to train + private DistanceNetwork network; + + // array of distances between neurons + private double[] distance; + + // learning rate + private double learningRate = 0.1; + // learning radius + private double learningRadius = 0.5; + + // squared learning radius multiplied by 2 (precalculated value to speed up computations) + private double squaredRadius2 = 2 * 0.5 * 0.5; + + /// + /// Learning rate, [0, 1]. + /// + /// + /// Determines speed of learning. + /// + /// Default value equals to 0.1. + /// + /// + public double LearningRate + { + get { return learningRate; } + set + { + learningRate = Math.Max( 0.0, Math.Min( 1.0, value ) ); + } + } + + /// + /// Learning radius, [0, 1]. + /// + /// + /// Determines the amount of neurons to be updated around + /// winner neuron. Neurons, which are in the circle of specified radius, + /// are updated during the learning procedure. Neurons, which are closer + /// to the winner neuron, get more update. + /// + /// Default value equals to 0.5. + /// + /// + public double LearningRadius + { + get { return learningRadius; } + set + { + learningRadius = Math.Max( 0, Math.Min( 1.0, value ) ); + squaredRadius2 = 2 * learningRadius * learningRadius; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Neural network to train. + /// + public ElasticNetworkLearning( DistanceNetwork network ) + { + this.network = network; + + // precalculate distances array + int neurons = network.Layers[0].Neurons.Length; + double deltaAlpha = Math.PI * 2.0 / neurons; + double alpha = deltaAlpha; + + distance = new double[neurons]; + distance[0] = 0.0; + + // calculate all distance values + for ( int i = 1; i < neurons; i++ ) + { + double dx = 0.5 * Math.Cos( alpha ) - 0.5; + double dy = 0.5 * Math.Sin( alpha ); + + distance[i] = dx * dx + dy * dy; + + alpha += deltaAlpha; + } + } + + /// + /// Runs learning iteration. + /// + /// + /// Input vector. + /// + /// Returns learning error - summary absolute difference between neurons' + /// weights and appropriate inputs. The difference is measured according to the neurons + /// distance to the winner neuron. + /// + /// The method runs one learning iterations - finds winner neuron (the neuron + /// which has weights with values closest to the specified input vector) and updates its weight + /// (as well as weights of neighbor neurons) in the way to decrease difference with the specified + /// input vector. + /// + public double Run( double[] input ) + { + double error = 0.0; + + // compute the network + network.Compute( input ); + int winner = network.GetWinner( ); + + // get layer of the network + Layer layer = network.Layers[0]; + + // walk through all neurons of the layer + for ( int j = 0; j < layer.Neurons.Length; j++ ) + { + Neuron neuron = layer.Neurons[j]; + + // update factor + double factor = Math.Exp( -distance[Math.Abs( j - winner )] / squaredRadius2 ); + + // update weights of the neuron + for ( int i = 0; i < neuron.Weights.Length; i++ ) + { + // calculate the error + double e = ( input[i] - neuron.Weights[i] ) * factor; + error += Math.Abs( e ); + // update weight + neuron.Weights[i] += e * learningRate; + } + } + return error; + } + + /// + /// Runs learning epoch. + /// + /// + /// Array of input vectors. + /// + /// Returns summary learning error for the epoch. See + /// method for details about learning error calculation. + /// + /// The method runs one learning epoch, by calling method + /// for each vector provided in the array. + /// + public double RunEpoch( double[][] input ) + { + double error = 0.0; + + // walk through all training samples + foreach ( double[] sample in input ) + { + error += Run( sample ); + } + + // return summary error + return error; + } + } +} diff --git a/Sources/Accord.Neuro/AForge/Learning/EvolutionaryFitness.cs b/Sources/Accord.Neuro/AForge/Learning/EvolutionaryFitness.cs new file mode 100644 index 0000000000..8ed7627db --- /dev/null +++ b/Sources/Accord.Neuro/AForge/Learning/EvolutionaryFitness.cs @@ -0,0 +1,121 @@ +// AForge Neural Net Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2012 +// contacts@aforgenet.com +// +// Copyright © Cezary Wagner, 2008 +// Initial implementation of evolutionary learning algorithm +// Cezary.Wagner@gmail.com +// + +namespace AForge.Neuro.Learning +{ + using System; + using System.Diagnostics; + using AForge.Genetic; + + /// + /// Fitness function used for chromosomes representing collection of neural network's weights. + /// + /// + internal class EvolutionaryFitness : IFitnessFunction + { + // neural network for which fitness will be calculated + private ActivationNetwork network; + + // input data samples for neural network + private double[][] input; + + // output data samples for neural network (desired output) + private double[][] output; + + /// + /// Initializes a new instance of the class. + /// + /// + /// Neural network for which fitness will be calculated. + /// Input data samples for neural network. + /// Output data sampels for neural network (desired output). + /// + /// Length of inputs and outputs arrays must be equal and greater than 0. + /// Length of each input vector must be equal to neural network's inputs count. + /// + public EvolutionaryFitness( ActivationNetwork network, double[][] input, double[][] output ) + { + if ( ( input.Length == 0 ) || ( input.Length != output.Length ) ) + { + throw new ArgumentException( "Length of inputs and outputs arrays must be equal and greater than 0." ); + } + + if ( network.InputsCount != input[0].Length ) + { + throw new ArgumentException( "Length of each input vector must be equal to neural network's inputs count." ); + } + + this.network = network; + this.input = input; + this.output = output; + } + + /// + /// Evaluates chromosome. + /// + /// + /// Chromosome to evaluate. + /// + /// Returns chromosome's fitness value. + /// + /// The method calculates fitness value of the specified + /// chromosome. + /// + public double Evaluate( IChromosome chromosome ) + { + DoubleArrayChromosome daChromosome = (DoubleArrayChromosome) chromosome; + double[] chromosomeGenes = daChromosome.Value; + // total number of weight in neural network + int totalNumberOfWeights = 0; + + // asign new weights and thresholds to network from the given chromosome + for ( int i = 0, layersCount = network.Layers.Length; i < layersCount; i++ ) + { + Layer layer = network.Layers[i]; + + for ( int j = 0; j < layer.Neurons.Length; j++ ) + { + ActivationNeuron neuron = layer.Neurons[j] as ActivationNeuron; + + for ( int k = 0; k < neuron.Weights.Length; k++ ) + { + neuron.Weights[k] = chromosomeGenes[totalNumberOfWeights++]; + } + neuron.Threshold = chromosomeGenes[totalNumberOfWeights++]; + } + } + + // post check if all values are processed and lenght of chromosome + // is equal to network size + Debug.Assert( totalNumberOfWeights == daChromosome.Length ); + + double totalError = 0; + + for ( int i = 0, inputVectorsAmount = input.Length; i < inputVectorsAmount; i++ ) + { + double[] computedOutput = network.Compute( input[i] ); + + for ( int j = 0, outputLength = output[0].Length; j < outputLength; j++ ) + { + double error = output[i][j] - computedOutput[j]; + totalError += error * error; + } + } + + if ( totalError > 0 ) + return 1.0 / totalError; + + // zero error means the best fitness + return double.MaxValue; + } + } +} diff --git a/Sources/Accord.Neuro/AForge/Learning/EvolutionaryLearning.cs b/Sources/Accord.Neuro/AForge/Learning/EvolutionaryLearning.cs new file mode 100644 index 0000000000..0ca1fa2ee --- /dev/null +++ b/Sources/Accord.Neuro/AForge/Learning/EvolutionaryLearning.cs @@ -0,0 +1,303 @@ +// AForge Neural Net Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2007-2012 +// contacts@aforgenet.com +// + +namespace AForge.Neuro.Learning +{ + using System; + using System.Diagnostics; + using AForge.Genetic; + using AForge.Math.Random; + + /// + /// Neural networks' evolutionary learning algorithm, which is based on Genetic Algorithms. + /// + /// + /// The class implements supervised neural network's learning algorithm, + /// which is based on Genetic Algorithms. For the given neural network, it create a population + /// of chromosomes, which represent neural network's + /// weights. Then, during the learning process, the genetic population evolves and weights, which + /// are represented by the best chromosome, are set to the source neural network. + /// + /// See class for additional information about genetic population + /// and evolutionary based search. + /// + /// Sample usage (training network to calculate XOR function): + /// + /// // initialize input and output values + /// double[][] input = new double[4][] { + /// new double[] {-1, 1}, new double[] {-1, 1}, + /// new double[] { 1, -1}, new double[] { 1, 1} + /// }; + /// double[][] output = new double[4][] { + /// new double[] {-1}, new double[] { 1}, + /// new double[] { 1}, new double[] {-1} + /// }; + /// // create neural network + /// ActivationNetwork network = new ActivationNetwork( + /// BipolarSigmoidFunction( 2 ), + /// 2, // two inputs in the network + /// 2, // two neurons in the first layer + /// 1 ); // one neuron in the second layer + /// // create teacher + /// EvolutionaryLearning teacher = new EvolutionaryLearning( network, + /// 100 ); // number of chromosomes in genetic population + /// // loop + /// while ( !needToStop ) + /// { + /// // run epoch of learning procedure + /// double error = teacher.RunEpoch( input, output ); + /// // check error value to see if we need to stop + /// // ... + /// } + /// + /// + /// + /// + /// + /// + public class EvolutionaryLearning : ISupervisedLearning + { + // designed network for training which have to matach inputs and outputs + private ActivationNetwork network; + // number of weight in the network to train + private int numberOfNetworksWeights; + + // genetic population + private Population population; + // size of population + private int populationSize; + + // generator for newly generated neurons + private IRandomNumberGenerator chromosomeGenerator; + // mutation generators + private IRandomNumberGenerator mutationMultiplierGenerator; + private IRandomNumberGenerator mutationAdditionGenerator; + + // selection method for chromosomes in population + private ISelectionMethod selectionMethod; + + // crossover probability in genetic population + private double crossOverRate; + // mutation probability in genetic population + private double mutationRate; + // probability to add newly generated chromosome to population + private double randomSelectionRate; + + /// + /// Initializes a new instance of the class. + /// + /// + /// Activation network to be trained. + /// Size of genetic population. + /// Random numbers generator used for initialization of genetic + /// population representing neural network's weights and thresholds (see ). + /// Random numbers generator used to generate random + /// factors for multiplication of network's weights and thresholds during genetic mutation + /// (ses .) + /// Random numbers generator used to generate random + /// values added to neural network's weights and thresholds during genetic mutation + /// (see ). + /// Method of selection best chromosomes in genetic population. + /// Crossover rate in genetic population (see + /// ). + /// Mutation rate in genetic population (see + /// ). + /// Rate of injection of random chromosomes during selection + /// in genetic population (see ). + /// + public EvolutionaryLearning( ActivationNetwork activationNetwork, int populationSize, + IRandomNumberGenerator chromosomeGenerator, + IRandomNumberGenerator mutationMultiplierGenerator, + IRandomNumberGenerator mutationAdditionGenerator, + ISelectionMethod selectionMethod, + double crossOverRate, double mutationRate, double randomSelectionRate ) + { + // Check of assumptions during debugging only + Debug.Assert( activationNetwork != null ); + Debug.Assert( populationSize > 0 ); + Debug.Assert( chromosomeGenerator != null ); + Debug.Assert( mutationMultiplierGenerator != null ); + Debug.Assert( mutationAdditionGenerator != null ); + Debug.Assert( selectionMethod != null ); + Debug.Assert( crossOverRate >= 0.0 && crossOverRate <= 1.0 ); + Debug.Assert( mutationRate >= 0.0 && crossOverRate <= 1.0 ); + Debug.Assert( randomSelectionRate >= 0.0 && randomSelectionRate <= 1.0 ); + + // networks's parameters + this.network = activationNetwork; + this.numberOfNetworksWeights = CalculateNetworkSize( activationNetwork ); + + // population parameters + this.populationSize = populationSize; + this.chromosomeGenerator = chromosomeGenerator; + this.mutationMultiplierGenerator = mutationMultiplierGenerator; + this.mutationAdditionGenerator = mutationAdditionGenerator; + this.selectionMethod = selectionMethod; + this.crossOverRate = crossOverRate; + this.mutationRate = mutationRate; + this.randomSelectionRate = randomSelectionRate; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Activation network to be trained. + /// Size of genetic population. + /// + /// This version of constructor is used to create genetic population + /// for searching optimal neural network's weight using default set of parameters, which are: + /// + /// Selection method - elite; + /// Crossover rate - 0.75; + /// Mutation rate - 0.25; + /// Rate of injection of random chromosomes during selection - 0.20; + /// Random numbers generator for initializing new chromosome - + /// UniformGenerator( new Range( -1, 1 ) ); + /// Random numbers generator used during mutation for genes' multiplication - + /// ExponentialGenerator( 1 ); + /// Random numbers generator used during mutation for adding random value to genes - + /// UniformGenerator( new Range( -0.5f, 0.5f ) ). + /// + /// + /// In order to have full control over the above default parameters, it is possible to + /// used extended version of constructor, which allows to specify all of the parameters. + /// + /// + public EvolutionaryLearning( ActivationNetwork activationNetwork, int populationSize ) + { + // Check of assumptions during debugging only + Debug.Assert( activationNetwork != null ); + Debug.Assert( populationSize > 0 ); + + // networks's parameters + this.network = activationNetwork; + this.numberOfNetworksWeights = CalculateNetworkSize( activationNetwork ); + + // population parameters + this.populationSize = populationSize; + this.chromosomeGenerator = new UniformGenerator( new Range( -1, 1 ) ); + this.mutationMultiplierGenerator = new ExponentialGenerator( 1 ); + this.mutationAdditionGenerator = new UniformGenerator( new Range( -0.5f, 0.5f ) ); + this.selectionMethod = new EliteSelection( ); + this.crossOverRate = 0.75; + this.mutationRate = 0.25; + this.randomSelectionRate = 0.2; + } + + // Create and initialize genetic population + private int CalculateNetworkSize( ActivationNetwork activationNetwork ) + { + // caclculate total amount of weight in neural network + int networkSize = 0; + + for ( int i = 0; i < network.Layers.Length; i++ ) + { + Layer layer = network.Layers[i]; + + for ( int j = 0; j < layer.Neurons.Length; j++ ) + { + // sum all weights and threshold + networkSize += layer.Neurons[j].Weights.Length + 1; + } + } + + return networkSize; + } + + /// + /// Runs learning iteration. + /// + /// + /// Input vector. + /// Desired output vector. + /// + /// Returns learning error. + /// + /// The method is not implemented, since evolutionary learning algorithm is global + /// and requires all inputs/outputs in order to run its one epoch. Use + /// method instead. + /// + /// The method is not implemented by design. + /// + public double Run( double[] input, double[] output ) + { + throw new NotImplementedException( "The method is not implemented by design." ); + } + + /// + /// Runs learning epoch. + /// + /// + /// Array of input vectors. + /// Array of output vectors. + /// + /// Returns summary squared learning error for the entire epoch. + /// + /// While running the neural network's learning process, it is required to + /// pass the same and values for each + /// epoch. On the very first run of the method it will initialize evolutionary fitness + /// function with the given input/output. So, changing input/output in middle of the learning + /// process, will break it. + /// + public double RunEpoch( double[][] input, double[][] output ) + { + Debug.Assert( input.Length > 0 ); + Debug.Assert( output.Length > 0 ); + Debug.Assert( input.Length == output.Length ); + Debug.Assert( network.InputsCount == input.Length ); + + // check if it is a first run and create population if so + if ( population == null ) + { + // sample chromosome + DoubleArrayChromosome chromosomeExample = new DoubleArrayChromosome( + chromosomeGenerator, mutationMultiplierGenerator, mutationAdditionGenerator, + numberOfNetworksWeights ); + + // create population ... + population = new Population( populationSize, chromosomeExample, + new EvolutionaryFitness( network, input, output ), selectionMethod ); + // ... and configure it + population.CrossoverRate = crossOverRate; + population.MutationRate = mutationRate; + population.RandomSelectionPortion = randomSelectionRate; + } + + // run genetic epoch + population.RunEpoch( ); + + // get best chromosome of the population + DoubleArrayChromosome chromosome = (DoubleArrayChromosome) population.BestChromosome; + double[] chromosomeGenes = chromosome.Value; + + // put best chromosome's value into neural network's weights + int v = 0; + + for ( int i = 0; i < network.Layers.Length; i++ ) + { + Layer layer = network.Layers[i]; + + for ( int j = 0; j < layer.Neurons.Length; j++ ) + { + ActivationNeuron neuron = layer.Neurons[j] as ActivationNeuron; + + for ( int k = 0; k < neuron.Weights.Length; k++ ) + { + neuron.Weights[k] = chromosomeGenes[v++]; + } + neuron.Threshold = chromosomeGenes[v++]; + } + } + + Debug.Assert( v == numberOfNetworksWeights ); + + return 1.0 / chromosome.Fitness; + } + } +} diff --git a/Sources/Accord.Neuro/AForge/Learning/ISupervisedLearning.cs b/Sources/Accord.Neuro/AForge/Learning/ISupervisedLearning.cs new file mode 100644 index 0000000000..f0394ee89 --- /dev/null +++ b/Sources/Accord.Neuro/AForge/Learning/ISupervisedLearning.cs @@ -0,0 +1,48 @@ +// AForge Neural Net Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2012 +// contacts@aforgenet.com +// + +namespace AForge.Neuro.Learning +{ + using System; + + /// + /// Supervised learning interface. + /// + /// + /// The interface describes methods, which should be implemented + /// by all supervised learning algorithms. Supervised learning is such + /// type of learning algorithms, where system's desired output is known on + /// the learning stage. So, given sample input values and desired outputs, + /// system should adopt its internals to produce correct (or close to correct) + /// result after the learning step is complete. + /// + public interface ISupervisedLearning + { + /// + /// Runs learning iteration. + /// + /// + /// Input vector. + /// Desired output vector. + /// + /// Returns learning error. + /// + double Run( double[] input, double[] output ); + + /// + /// Runs learning epoch. + /// + /// + /// Array of input vectors. + /// Array of output vectors. + /// + /// Returns sum of learning errors. + /// + double RunEpoch( double[][] input, double[][] output ); + } +} diff --git a/Sources/Accord.Neuro/AForge/Learning/IUnsupervisedLearning.cs b/Sources/Accord.Neuro/AForge/Learning/IUnsupervisedLearning.cs new file mode 100644 index 0000000000..54e7462c9 --- /dev/null +++ b/Sources/Accord.Neuro/AForge/Learning/IUnsupervisedLearning.cs @@ -0,0 +1,46 @@ +// AForge Neural Net Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2012 +// contacts@aforgenet.com +// + +namespace AForge.Neuro.Learning +{ + using System; + + /// + /// Unsupervised learning interface. + /// + /// + /// The interface describes methods, which should be implemented + /// by all unsupervised learning algorithms. Unsupervised learning is such + /// type of learning algorithms, where system's desired output is not known on + /// the learning stage. Given sample input values, it is expected, that + /// system will organize itself in the way to find similarities betweed provided + /// samples. + /// + public interface IUnsupervisedLearning + { + /// + /// Runs learning iteration. + /// + /// + /// Input vector. + /// + /// Returns learning error. + /// + double Run( double[] input ); + + /// + /// Runs learning epoch. + /// + /// + /// Array of input vectors. + /// + /// Returns sum of learning errors. + /// + double RunEpoch( double[][] input ); + } +} diff --git a/Sources/Accord.Neuro/AForge/Learning/PerceptronLearning.cs b/Sources/Accord.Neuro/AForge/Learning/PerceptronLearning.cs new file mode 100644 index 0000000000..6ce9e2db7 --- /dev/null +++ b/Sources/Accord.Neuro/AForge/Learning/PerceptronLearning.cs @@ -0,0 +1,148 @@ +// AForge Neural Net Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2012 +// contacts@aforgenet.com +// + +namespace AForge.Neuro.Learning +{ + using System; + + /// + /// Perceptron learning algorithm. + /// + /// + /// This learning algorithm is used to train one layer neural + /// network of Activation Neurons + /// with the Threshold + /// activation function. + /// + /// See information about Perceptron + /// and its learning algorithm. + /// + /// + public class PerceptronLearning : ISupervisedLearning + { + // network to teach + private ActivationNetwork network; + // learning rate + private double learningRate = 0.1; + + /// + /// Learning rate, [0, 1]. + /// + /// + /// The value determines speed of learning. + /// + /// Default value equals to 0.1. + /// + /// + public double LearningRate + { + get { return learningRate; } + set + { + learningRate = Math.Max( 0.0, Math.Min( 1.0, value ) ); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Network to teach. + /// + /// Invalid nuaral network. It should have one layer only. + /// + public PerceptronLearning( ActivationNetwork network ) + { + // check layers count + if ( network.Layers.Length != 1 ) + { + throw new ArgumentException( "Invalid nuaral network. It should have one layer only." ); + } + + this.network = network; + } + + /// + /// Runs learning iteration. + /// + /// + /// Input vector. + /// Desired output vector. + /// + /// Returns absolute error - difference between current network's output and + /// desired output. + /// + /// Runs one learning iteration and updates neuron's + /// weights in the case if neuron's output is not equal to the + /// desired output. + /// + public double Run( double[] input, double[] output ) + { + // compute output of network + double[] networkOutput = network.Compute( input ); + + // get the only layer of the network + Layer layer = network.Layers[0]; + + // summary network absolute error + double error = 0.0; + + // check output of each neuron and update weights + for ( int j = 0; j < layer.Neurons.Length; j++ ) + { + double e = output[j] - networkOutput[j]; + + if ( e != 0 ) + { + ActivationNeuron perceptron = layer.Neurons[j] as ActivationNeuron; + + // update weights + for ( int i = 0; i < perceptron.Weights.Length; i++ ) + { + perceptron.Weights[i] += learningRate * e * input[i]; + } + + // update threshold value + perceptron.Threshold += learningRate * e; + + // make error to be absolute + error += Math.Abs( e ); + } + } + + return error; + } + + /// + /// Runs learning epoch. + /// + /// + /// Array of input vectors. + /// Array of output vectors. + /// + /// Returns summary learning error for the epoch. See + /// method for details about learning error calculation. + /// + /// The method runs one learning epoch, by calling method + /// for each vector provided in the array. + /// + public double RunEpoch( double[][] input, double[][] output ) + { + double error = 0.0; + + // run learning procedure for all samples + for ( int i = 0, n = input.Length; i < n; i++ ) + { + error += Run( input[i], output[i] ); + } + + // return summary error + return error; + } + } +} diff --git a/Sources/Accord.Neuro/AForge/Learning/ResilientBackPropagationLearning.cs b/Sources/Accord.Neuro/AForge/Learning/ResilientBackPropagationLearning.cs new file mode 100644 index 0000000000..074761fca --- /dev/null +++ b/Sources/Accord.Neuro/AForge/Learning/ResilientBackPropagationLearning.cs @@ -0,0 +1,483 @@ +// AForge Neural Net Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © César Souza, 2009-2012 +// cesarsouza at gmail.com +// +// Copyright © AForge.NET, 2005-2012 +// contacts@aforgenet.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 AForge.Neuro.Learning +{ + using System; + + /// + /// Resilient Backpropagation learning algorithm. + /// + /// + /// This class implements the resilient backpropagation (RProp) + /// learning algorithm. The RProp learning algorithm is one of the fastest learning + /// algorithms for feed-forward learning networks which use only first-order + /// information. + /// + /// Sample usage (training network to calculate XOR function): + /// + /// // initialize input and output values + /// double[][] input = new double[4][] { + /// new double[] {0, 0}, new double[] {0, 1}, + /// new double[] {1, 0}, new double[] {1, 1} + /// }; + /// double[][] output = new double[4][] { + /// new double[] {0}, new double[] {1}, + /// new double[] {1}, new double[] {0} + /// }; + /// // create neural network + /// ActivationNetwork network = new ActivationNetwork( + /// SigmoidFunction( 2 ), + /// 2, // two inputs in the network + /// 2, // two neurons in the first layer + /// 1 ); // one neuron in the second layer + /// // create teacher + /// ResilientBackpropagationLearning teacher = new ResilientBackpropagationLearning( network ); + /// // loop + /// while ( !needToStop ) + /// { + /// // run epoch of learning procedure + /// double error = teacher.RunEpoch( input, output ); + /// // check error value to see if we need to stop + /// // ... + /// } + /// + /// + /// + public class ResilientBackpropagationLearning : ISupervisedLearning + { + private ActivationNetwork network; + + private double learningRate = 0.0125; + private double deltaMax = 50.0; + private double deltaMin = 1e-6; + + private const double etaMinus = 0.5; + private double etaPlus = 1.2; + + private double[][] neuronErrors = null; + + // update values, also known as deltas + private double[][][] weightsUpdates = null; + private double[][] thresholdsUpdates = null; + + // current and previous gradient values + private double[][][] weightsDerivatives = null; + private double[][] thresholdsDerivatives = null; + + private double[][][] weightsPreviousDerivatives = null; + private double[][] thresholdsPreviousDerivatives = null; + + + /// + /// Learning rate. + /// + /// + /// The value determines speed of learning. + /// + /// Default value equals to 0.0125. + /// + /// + public double LearningRate + { + get { return learningRate; } + set + { + learningRate = value; + ResetUpdates(learningRate); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Network to teach. + /// + public ResilientBackpropagationLearning(ActivationNetwork network) + { + this.network = network; + + int layersCount = network.Layers.Length; + + neuronErrors = new double[layersCount][]; + + weightsDerivatives = new double[layersCount][][]; + thresholdsDerivatives = new double[layersCount][]; + + weightsPreviousDerivatives = new double[layersCount][][]; + thresholdsPreviousDerivatives = new double[layersCount][]; + + weightsUpdates = new double[layersCount][][]; + thresholdsUpdates = new double[layersCount][]; + + // initialize errors, derivatives and steps + for (int i = 0; i < network.Layers.Length; i++) + { + Layer layer = network.Layers[i]; + int neuronsCount = layer.Neurons.Length; + + neuronErrors[i] = new double[neuronsCount]; + + weightsDerivatives[i] = new double[neuronsCount][]; + weightsPreviousDerivatives[i] = new double[neuronsCount][]; + weightsUpdates[i] = new double[neuronsCount][]; + + thresholdsDerivatives[i] = new double[neuronsCount]; + thresholdsPreviousDerivatives[i] = new double[neuronsCount]; + thresholdsUpdates[i] = new double[neuronsCount]; + + // for each neuron + for (int j = 0; j < layer.Neurons.Length; j++) + { + weightsDerivatives[i][j] = new double[layer.InputsCount]; + weightsPreviousDerivatives[i][j] = new double[layer.InputsCount]; + weightsUpdates[i][j] = new double[layer.InputsCount]; + } + } + + // intialize steps + ResetUpdates(learningRate); + } + + /// + /// Runs learning iteration. + /// + /// + /// Input vector. + /// Desired output vector. + /// + /// Returns squared error (difference between current network's output and + /// desired output) divided by 2. + /// + /// Runs one learning iteration and updates neuron's + /// weights. + /// + public double Run(double[] input, double[] output) + { + // zero gradient + ResetGradient(); + + // compute the network's output + network.Compute(input); + + // calculate network error + double error = CalculateError(output); + + // calculate weights updates + CalculateGradient(input); + + // update the network + UpdateNetwork(); + + // return summary error + return error; + } + + /// + /// Runs learning epoch. + /// + /// + /// Array of input vectors. + /// Array of output vectors. + /// + /// Returns summary learning error for the epoch. See + /// method for details about learning error calculation. + /// + /// The method runs one learning epoch, by calling method + /// for each vector provided in the array. + /// + public double RunEpoch(double[][] input, double[][] output) + { + // zero gradient + ResetGradient(); + + double error = 0.0; + + // run learning procedure for all samples + for (int i = 0; i < input.Length; i++) + { + // compute the network's output + network.Compute(input[i]); + + // calculate network error + error += CalculateError(output[i]); + + // calculate weights updates + CalculateGradient(input[i]); + } + + // update the network + UpdateNetwork(); + + // return summary error + return error; + } + + /// + /// Resets current weight and threshold derivatives. + /// + /// + private void ResetGradient() + { + for (int i = 0; i < weightsDerivatives.Length; i++) + { + for (int j = 0; j < weightsDerivatives[i].Length; j++) + { + Array.Clear(weightsDerivatives[i][j], 0, weightsDerivatives[i][j].Length); + } + } + + for (int i = 0; i < thresholdsDerivatives.Length; i++) + { + Array.Clear(thresholdsDerivatives[i], 0, thresholdsDerivatives[i].Length); + } + } + + /// + /// Resets the current update steps using the given learning rate. + /// + /// + private void ResetUpdates(double rate) + { + for (int i = 0; i < weightsUpdates.Length; i++) + { + for (int j = 0; j < weightsUpdates[i].Length; j++) + { + for (int k = 0; k < weightsUpdates[i][j].Length; k++) + { + weightsUpdates[i][j][k] = rate; + } + } + } + + for (int i = 0; i < thresholdsUpdates.Length; i++) + { + for (int j = 0; j < thresholdsUpdates[i].Length; j++) + { + thresholdsUpdates[i][j] = rate; + } + } + } + + /// + /// Update network's weights. + /// + /// + private void UpdateNetwork() + { + double[][] layerWeightsUpdates; + double[] layerThresholdUpdates; + double[] neuronWeightUpdates; + + double[][] layerWeightsDerivatives; + double[] layerThresholdDerivatives; + double[] neuronWeightDerivatives; + + double[][] layerPreviousWeightsDerivatives; + double[] layerPreviousThresholdDerivatives; + double[] neuronPreviousWeightDerivatives; + + // for each layer of the network + for (int i = 0; i < network.Layers.Length; i++) + { + ActivationLayer layer = network.Layers[i] as ActivationLayer; + + layerWeightsUpdates = weightsUpdates[i]; + layerThresholdUpdates = thresholdsUpdates[i]; + + layerWeightsDerivatives = weightsDerivatives[i]; + layerThresholdDerivatives = thresholdsDerivatives[i]; + + layerPreviousWeightsDerivatives = weightsPreviousDerivatives[i]; + layerPreviousThresholdDerivatives = thresholdsPreviousDerivatives[i]; + + // for each neuron of the layer + for (int j = 0; j < layer.Neurons.Length; j++) + { + ActivationNeuron neuron = layer.Neurons[j] as ActivationNeuron; + + neuronWeightUpdates = layerWeightsUpdates[j]; + neuronWeightDerivatives = layerWeightsDerivatives[j]; + neuronPreviousWeightDerivatives = layerPreviousWeightsDerivatives[j]; + + double S = 0; + + // for each weight of the neuron + for (int k = 0; k < neuron.InputsCount; k++) + { + S = neuronPreviousWeightDerivatives[k] * neuronWeightDerivatives[k]; + + if (S > 0) + { + neuronWeightUpdates[k] = Math.Min(neuronWeightUpdates[k] * etaPlus, deltaMax); + neuron.Weights[k] -= Math.Sign(neuronWeightDerivatives[k]) * neuronWeightUpdates[k]; + neuronPreviousWeightDerivatives[k] = neuronWeightDerivatives[k]; + } + else if (S < 0) + { + neuronWeightUpdates[k] = Math.Max(neuronWeightUpdates[k] * etaMinus, deltaMin); + neuronPreviousWeightDerivatives[k] = 0; + } + else + { + neuron.Weights[k] -= Math.Sign(neuronWeightDerivatives[k]) * neuronWeightUpdates[k]; + neuronPreviousWeightDerivatives[k] = neuronWeightDerivatives[k]; + } + } + + // update treshold + S = layerPreviousThresholdDerivatives[j] * layerThresholdDerivatives[j]; + + if (S > 0) + { + layerThresholdUpdates[j] = Math.Min(layerThresholdUpdates[j] * etaPlus, deltaMax); + neuron.Threshold -= Math.Sign(layerThresholdDerivatives[j]) * layerThresholdUpdates[j]; + layerPreviousThresholdDerivatives[j] = layerThresholdDerivatives[j]; + } + else if (S < 0) + { + layerThresholdUpdates[j] = Math.Max(layerThresholdUpdates[j] * etaMinus, deltaMin); + layerThresholdDerivatives[j] = 0; + } + else + { + neuron.Threshold -= Math.Sign(layerThresholdDerivatives[j]) * layerThresholdUpdates[j]; + layerPreviousThresholdDerivatives[j] = layerThresholdDerivatives[j]; + } + } + } + } + + /// + /// Calculates error values for all neurons of the network. + /// + /// + /// Desired output vector. + /// + /// Returns summary squared error of the last layer divided by 2. + /// + private double CalculateError(double[] desiredOutput) + { + double error = 0; + int layersCount = network.Layers.Length; + + // assume, that all neurons of the network have the same activation function + IActivationFunction function = (network.Layers[0].Neurons[0] as ActivationNeuron).ActivationFunction; + + // calculate error values for the last layer first + ActivationLayer layer = network.Layers[layersCount - 1] as ActivationLayer; + double[] layerDerivatives = neuronErrors[layersCount - 1]; + + for (int i = 0; i < layer.Neurons.Length; i++) + { + double output = layer.Neurons[i].Output; + + double e = output - desiredOutput[i]; + layerDerivatives[i] = e * function.Derivative2(output); + error += (e * e); + } + + // calculate error values for other layers + for (int j = layersCount - 2; j >= 0; j--) + { + layer = network.Layers[j] as ActivationLayer; + layerDerivatives = neuronErrors[j]; + + ActivationLayer layerNext = network.Layers[j + 1] as ActivationLayer; + double[] nextDerivatives = neuronErrors[j + 1]; + + // for all neurons of the layer + for (int i = 0, n = layer.Neurons.Length; i < n; i++) + { + double sum = 0.0; + + for (int k = 0; k < layerNext.Neurons.Length; k++) + { + sum += nextDerivatives[k] * layerNext.Neurons[k].Weights[i]; + } + + layerDerivatives[i] = sum * function.Derivative2(layer.Neurons[i].Output); + } + } + + // return squared error of the last layer divided by 2 + return error / 2.0; + } + + /// + /// Calculate weights updates + /// + /// + /// Network's input vector. + /// + private void CalculateGradient(double[] input) + { + // 1. calculate updates for the first layer + ActivationLayer layer = network.Layers[0] as ActivationLayer; + double[] weightErrors = neuronErrors[0]; + double[][] layerWeightsDerivatives = weightsDerivatives[0]; + double[] layerThresholdDerivatives = thresholdsDerivatives[0]; + + // So, for each neuron of the first layer: + for (int i = 0; i < layer.Neurons.Length; i++) + { + ActivationNeuron neuron = layer.Neurons[i] as ActivationNeuron; + double[] neuronWeightDerivatives = layerWeightsDerivatives[i]; + + // for each weight of the neuron: + for (int j = 0; j < neuron.InputsCount; j++) + { + neuronWeightDerivatives[j] += weightErrors[i] * input[j]; + } + layerThresholdDerivatives[i] += weightErrors[i]; + } + + // 2. for all other layers + for (int k = 1; k < network.Layers.Length; k++) + { + layer = network.Layers[k] as ActivationLayer; + weightErrors = neuronErrors[k]; + layerWeightsDerivatives = weightsDerivatives[k]; + layerThresholdDerivatives = thresholdsDerivatives[k]; + + ActivationLayer layerPrev = network.Layers[k - 1] as ActivationLayer; + + // for each neuron of the layer + for (int i = 0; i < layer.Neurons.Length; i++) + { + double[] neuronWeightDerivatives = layerWeightsDerivatives[i]; + + // for each weight of the neuron + for (int j = 0; j < layerPrev.Neurons.Length; j++) + { + neuronWeightDerivatives[j] += weightErrors[i] * layerPrev.Neurons[j].Output; + } + layerThresholdDerivatives[i] += weightErrors[i]; + } + } + } + } +} \ No newline at end of file diff --git a/Sources/Accord.Neuro/AForge/Learning/SOMLearning.cs b/Sources/Accord.Neuro/AForge/Learning/SOMLearning.cs new file mode 100644 index 0000000000..6098d2b0b --- /dev/null +++ b/Sources/Accord.Neuro/AForge/Learning/SOMLearning.cs @@ -0,0 +1,275 @@ +// AForge Neural Net Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2012 +// contacts@aforgenet.com +// + +namespace AForge.Neuro.Learning +{ + using System; + + /// + /// Kohonen Self Organizing Map (SOM) learning algorithm. + /// + /// + /// This class implements Kohonen's SOM learning algorithm and + /// is widely used in clusterization tasks. The class allows to train + /// Distance Networks. + /// + /// Sample usage (clustering RGB colors): + /// + /// // set range for randomization neurons' weights + /// Neuron.RandRange = new Range( 0, 255 ); + /// // create network + /// DistanceNetwork network = new DistanceNetwork( + /// 3, // thress inputs in the network + /// 100 * 100 ); // 10000 neurons + /// // create learning algorithm + /// SOMLearning trainer = new SOMLearning( network ); + /// // network's input + /// double[] input = new double[3]; + /// // loop + /// while ( !needToStop ) + /// { + /// input[0] = rand.Next( 256 ); + /// input[1] = rand.Next( 256 ); + /// input[2] = rand.Next( 256 ); + /// + /// trainer.Run( input ); + /// + /// // ... + /// // update learning rate and radius continuously, + /// // so networks may come steady state + /// } + /// + /// + /// + public class SOMLearning : IUnsupervisedLearning + { + // neural network to train + private DistanceNetwork network; + // network's dimension + private int width; + private int height; + + // learning rate + private double learningRate = 0.1; + // learning radius + private double learningRadius = 7; + + // squared learning radius multiplied by 2 (precalculated value to speed up computations) + private double squaredRadius2 = 2 * 7 * 7; + + /// + /// Learning rate, [0, 1]. + /// + /// + /// Determines speed of learning. + /// + /// Default value equals to 0.1. + /// + /// + public double LearningRate + { + get { return learningRate; } + set + { + learningRate = Math.Max(0.0, Math.Min(1.0, value)); + } + } + + /// + /// Learning radius. + /// + /// + /// Determines the amount of neurons to be updated around + /// winner neuron. Neurons, which are in the circle of specified radius, + /// are updated during the learning procedure. Neurons, which are closer + /// to the winner neuron, get more update. + /// + /// In the case if learning rate is set to 0, then only winner + /// neuron's weights are updated. + /// + /// Default value equals to 7. + /// + /// + public double LearningRadius + { + get { return learningRadius; } + set + { + learningRadius = Math.Max(0, value); + squaredRadius2 = 2 * learningRadius * learningRadius; + } + } + + /// + /// Gets the neural network's height. + /// + /// + public int Height { get { return height; } } + + /// + /// Gets the neural network's width. + /// + /// + public int Width { get { return width; } } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Neural network to train. + /// + /// This constructor supposes that a square network will be passed for training - + /// it should be possible to get square root of network's neurons amount. + /// + /// Invalid network size - square network is expected. + /// + public SOMLearning(DistanceNetwork network) + { + // network's dimension was not specified, let's try to guess + int neuronsCount = network.Layers[0].Neurons.Length; + int width = (int)Math.Sqrt(neuronsCount); + + if (width * width != neuronsCount) + { + throw new ArgumentException("Invalid network size."); + } + + // ok, we got it + this.network = network; + this.width = width; + this.height = width; + } + + + /// + /// Initializes a new instance of the class. + /// + /// + /// Neural network to train. + /// Neural network's width. + /// Neural network's height. + /// + /// The constructor allows to pass network of arbitrary rectangular shape. + /// The amount of neurons in the network should be equal to width * height. + /// + /// + /// Invalid network size - network size does not correspond + /// to specified width and height. + /// + public SOMLearning(DistanceNetwork network, int width, int height) + { + // check network size + if (network.Layers[0].Neurons.Length != width * height) + { + throw new ArgumentException("Invalid network size."); + } + + this.network = network; + this.width = width; + this.height = height; + } + + /// + /// Runs learning iteration. + /// + /// + /// Input vector. + /// + /// Returns learning error - summary absolute difference between neurons' weights + /// and appropriate inputs. The difference is measured according to the neurons + /// distance to the winner neuron. + /// + /// The method runs one learning iterations - finds winner neuron (the neuron + /// which has weights with values closest to the specified input vector) and updates its weight + /// (as well as weights of neighbor neurons) in the way to decrease difference with the specified + /// input vector. + /// + public double Run(double[] input) + { + double error = 0.0; + + // compute the network + network.Compute(input); + int winner = network.GetWinner(); + + // get layer of the network + Layer layer = network.Layers[0]; + + // check learning radius + if (learningRadius == 0) + { + Neuron neuron = layer.Neurons[winner]; + + // update weight of the winner only + for (int i = 0; i < neuron.Weights.Length; i++) + { + // calculate the error + double e = input[i] - neuron.Weights[i]; + error += Math.Abs(e); + // update weights + neuron.Weights[i] += e * learningRate; + } + } + else + { + // winner's X and Y + int wx = winner % width; + int wy = winner / width; + + // walk through all neurons of the layer + for (int j = 0; j < layer.Neurons.Length; j++) + { + Neuron neuron = layer.Neurons[j]; + + int dx = (j % width) - wx; + int dy = (j / width) - wy; + + // update factor ( Gaussian based ) + double factor = Math.Exp(-(double)(dx * dx + dy * dy) / squaredRadius2); + + // update weight of the neuron + for (int i = 0; i < neuron.Weights.Length; i++) + { + // calculate the error + double e = (input[i] - neuron.Weights[i]) * factor; + error += Math.Abs(e); + // update weight + neuron.Weights[i] += e * learningRate; + } + } + } + return error; + } + + /// + /// Runs learning epoch. + /// + /// + /// Array of input vectors. + /// + /// Returns summary learning error for the epoch. See + /// method for details about learning error calculation. + /// + /// The method runs one learning epoch, by calling method + /// for each vector provided in the array. + /// + public double RunEpoch(double[][] input) + { + double error = 0.0; + + // walk through all training samples + foreach (double[] sample in input) + { + error += Run(sample); + } + + // return summary error + return error; + } + } +} diff --git a/Sources/Accord.Neuro/AForge/Networks/ActivationNetwork.cs b/Sources/Accord.Neuro/AForge/Networks/ActivationNetwork.cs new file mode 100644 index 0000000000..52ec9f3e4 --- /dev/null +++ b/Sources/Accord.Neuro/AForge/Networks/ActivationNetwork.cs @@ -0,0 +1,83 @@ +// AForge Neural Net Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2012 +// contacts@aforgenet.com +// + +namespace AForge.Neuro +{ + using System; + + /// + /// Activation network. + /// + /// + /// Activation network is a base for multi-layer neural network + /// with activation functions. It consists of activation + /// layers. + /// + /// Sample usage: + /// + /// // create activation network + /// ActivationNetwork network = new ActivationNetwork( + /// new SigmoidFunction( ), // sigmoid activation function + /// 3, // 3 inputs + /// 4, 1 ); // 2 layers: + /// // 4 neurons in the firs layer + /// // 1 neuron in the second layer + /// + /// + /// + [Serializable] + public class ActivationNetwork : Network + { + + + /// + /// Initializes a new instance of the class. + /// + /// + /// Activation function of neurons of the network. + /// Network's inputs count. + /// Array, which specifies the amount of neurons in + /// each layer of the neural network. + /// + /// The new network is randomized (see + /// method) after it is created. + /// + public ActivationNetwork( IActivationFunction function, int inputsCount, params int[] neuronsCount ) + : base( inputsCount, neuronsCount.Length ) + { + // create each layer + for ( int i = 0; i < layers.Length; i++ ) + { + layers[i] = new ActivationLayer( + // neurons count in the layer + neuronsCount[i], + // inputs count of the layer + ( i == 0 ) ? inputsCount : neuronsCount[i - 1], + // activation function of the layer + function ); + } + } + + /// + /// Set new activation function for all neurons of the network. + /// + /// + /// Activation function to set. + /// + /// The method sets new activation function for all neurons by calling + /// method for each layer of the network. + /// + public void SetActivationFunction( IActivationFunction function ) + { + for ( int i = 0; i < layers.Length; i++ ) + { + ( (ActivationLayer) layers[i] ).SetActivationFunction( function ); + } + } + } +} diff --git a/Sources/Accord.Neuro/AForge/Networks/DistanceNetwork.cs b/Sources/Accord.Neuro/AForge/Networks/DistanceNetwork.cs new file mode 100644 index 0000000000..f8c75baae --- /dev/null +++ b/Sources/Accord.Neuro/AForge/Networks/DistanceNetwork.cs @@ -0,0 +1,71 @@ +// AForge Neural Net Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2012 +// contacts@aforgenet.com +// + +namespace AForge.Neuro +{ + using System; + + /// + /// Distance network. + /// + /// + /// Distance network is a neural network of only one distance + /// layer. The network is a base for such neural networks as SOM, Elastic net, etc. + /// + /// + [Serializable] + public class DistanceNetwork : Network + { + + + /// + /// Initializes a new instance of the class. + /// + /// + /// Network's inputs count. + /// Network's neurons count. + /// + /// The new network is randomized (see + /// method) after it is created. + /// + public DistanceNetwork( int inputsCount, int neuronsCount ) + : base( inputsCount, 1 ) + { + // create layer + layers[0] = new DistanceLayer( neuronsCount, inputsCount ); + } + + /// + /// Get winner neuron. + /// + /// + /// Index of the winner neuron. + /// + /// The method returns index of the neuron, which weights have + /// the minimum distance from network's input. + /// + public int GetWinner( ) + { + // find the MIN value + double min = output[0]; + int minIndex = 0; + + for ( int i = 1; i < output.Length; i++ ) + { + if ( output[i] < min ) + { + // found new MIN value + min = output[i]; + minIndex = i; + } + } + + return minIndex; + } + } +} diff --git a/Sources/Accord.Neuro/AForge/Networks/Network.cs b/Sources/Accord.Neuro/AForge/Networks/Network.cs new file mode 100644 index 0000000000..1a0a3b94d --- /dev/null +++ b/Sources/Accord.Neuro/AForge/Networks/Network.cs @@ -0,0 +1,216 @@ +// AForge Neural Net Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2012 +// contacts@aforgenet.com +// + +namespace AForge.Neuro +{ + using System; + using System.IO; + using System.Runtime.Serialization; + using System.Runtime.Serialization.Formatters.Binary; + + /// + /// Base neural network class. + /// + /// + /// This is a base neural netwok class, which represents + /// collection of neuron's layers. + /// + [Serializable] + public abstract class Network + { + /// + /// Network's inputs count. + /// + protected int inputsCount; + + /// + /// Network's layers count. + /// + protected int layersCount; + + /// + /// Network's layers. + /// + protected Layer[] layers; + + /// + /// Network's output vector. + /// + protected double[] output; + + /// + /// Network's inputs count. + /// + public int InputsCount + { + get { return inputsCount; } + } + + /// + /// Network's layers. + /// + public Layer[] Layers + { + get { return layers; } + } + + /// + /// Network's output vector. + /// + /// + /// The calculation way of network's output vector is determined by + /// layers, which comprise the network. + /// + /// The property is not initialized (equals to ) until + /// method is called. + /// + /// + public double[] Output + { + get { return output; } + } + + + + /// + /// Initializes a new instance of the class. + /// + /// + /// Network's inputs count. + /// Network's layers count. + /// + /// Protected constructor, which initializes , + /// and members. + /// + protected Network( int inputsCount, int layersCount ) + { + this.inputsCount = Math.Max( 1, inputsCount ); + this.layersCount = Math.Max( 1, layersCount ); + // create collection of layers + this.layers = new Layer[this.layersCount]; + } + + /// + /// Compute output vector of the network. + /// + /// + /// Input vector. + /// + /// Returns network's output vector. + /// + /// The actual network's output vecor is determined by layers, + /// which comprise the layer - represents an output vector of the last layer + /// of the network. The output vector is also stored in property. + /// + /// The method may be called safely from multiple threads to compute network's + /// output value for the specified input values. However, the value of + /// property in multi-threaded environment is not predictable, + /// since it may hold network's output computed from any of the caller threads. Multi-threaded + /// access to the method is useful in those cases when it is required to improve performance + /// by utilizing several threads and the computation is based on the immediate return value + /// of the method, but not on network's output property. + /// + /// + public virtual double[] Compute( double[] input ) + { + // local variable to avoid mutlithread conflicts + double[] output = input; + + // compute each layer + for ( int i = 0; i < layers.Length; i++ ) + { + output = layers[i].Compute( output ); + } + + // assign output property as well (works correctly for single threaded usage) + this.output = output; + + return output; + } + + /// + /// Randomize layers of the network. + /// + /// + /// Randomizes network's layers by calling method + /// of each layer. + /// + public virtual void Randomize( ) + { + foreach ( Layer layer in layers ) + { + layer.Randomize( ); + } + } + + /// + /// Save network to specified file. + /// + /// + /// File name to save network into. + /// + /// The neural network is saved using .NET serialization (binary formatter is used). + /// + public void Save( string fileName ) + { + FileStream stream = new FileStream( fileName, FileMode.Create, FileAccess.Write, FileShare.None ); + Save( stream ); + stream.Close( ); + } + + /// + /// Save network to specified file. + /// + /// + /// Stream to save network into. + /// + /// The neural network is saved using .NET serialization (binary formatter is used). + /// + public void Save( Stream stream ) + { + IFormatter formatter = new BinaryFormatter( ); + formatter.Serialize( stream, this ); + } + + /// + /// Load network from specified file. + /// + /// + /// File name to load network from. + /// + /// Returns instance of class with all properties initialized from file. + /// + /// Neural network is loaded from file using .NET serialization (binary formater is used). + /// + public static Network Load( string fileName ) + { + FileStream stream = new FileStream( fileName, FileMode.Open, FileAccess.Read, FileShare.Read ); + Network network = Load( stream ); + stream.Close( ); + + return network; + } + + /// + /// Load network from specified file. + /// + /// + /// Stream to load network from. + /// + /// Returns instance of class with all properties initialized from file. + /// + /// Neural network is loaded from file using .NET serialization (binary formater is used). + /// + public static Network Load( Stream stream ) + { + IFormatter formatter = new BinaryFormatter( ); + Network network = (Network) formatter.Deserialize( stream ); + return network; + } + } +} diff --git a/Sources/Accord.Neuro/AForge/Neurons/ActivationNeuron.cs b/Sources/Accord.Neuro/AForge/Neurons/ActivationNeuron.cs new file mode 100644 index 0000000000..3e319e9d8 --- /dev/null +++ b/Sources/Accord.Neuro/AForge/Neurons/ActivationNeuron.cs @@ -0,0 +1,144 @@ +// AForge Neural Net Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2012 +// contacts@aforgenet.com +// + +namespace AForge.Neuro +{ + using System; + + /// + /// Activation neuron. + /// + /// + /// Activation neuron computes weighted sum of its inputs, adds + /// threshold value and then applies activation function. + /// The neuron isusually used in multi-layer neural networks. + /// + /// + /// + [Serializable] + public class ActivationNeuron : Neuron + { + /// + /// Threshold value. + /// + /// + /// The value is added to inputs weighted sum before it is passed to activation + /// function. + /// + protected double threshold = 0.0; + + /// + /// Activation function. + /// + /// + /// The function is applied to inputs weighted sum plus + /// threshold value. + /// + protected IActivationFunction function = null; + + /// + /// Threshold value. + /// + /// + /// The value is added to inputs weighted sum before it is passed to activation + /// function. + /// + public double Threshold + { + get { return threshold; } + set { threshold = value; } + } + + /// + /// Neuron's activation function. + /// + /// + public IActivationFunction ActivationFunction + { + get { return function; } + set { function = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Neuron's inputs count. + /// Neuron's activation function. + /// + public ActivationNeuron( int inputs, IActivationFunction function ) + : base( inputs ) + { + this.function = function; + } + + /// + /// Randomize neuron. + /// + /// + /// Calls base class Randomize method + /// to randomize neuron's weights and then randomizes threshold's value. + /// + public override void Randomize( ) + { + // randomize weights + base.Randomize( ); + // randomize threshold + threshold = rand.NextDouble( ) * ( randRange.Length ) + randRange.Min; + } + + /// + /// Computes output value of neuron. + /// + /// + /// Input vector. + /// + /// Returns neuron's output value. + /// + /// The output value of activation neuron is equal to value + /// of nueron's activation function, which parameter is weighted sum + /// of its inputs plus threshold value. The output value is also stored + /// in Output property. + /// + /// The method may be called safely from multiple threads to compute neuron's + /// output value for the specified input values. However, the value of + /// property in multi-threaded environment is not predictable, + /// since it may hold neuron's output computed from any of the caller threads. Multi-threaded + /// access to the method is useful in those cases when it is required to improve performance + /// by utilizing several threads and the computation is based on the immediate return value + /// of the method, but not on neuron's output property. + /// + /// + /// Wrong length of the input vector, which is not + /// equal to the expected value. + /// + public override double Compute( double[] input ) + { + // check for corrent input vector + if ( input.Length != inputsCount ) + throw new ArgumentException( "Wrong length of the input vector." ); + + // initial sum value + double sum = 0.0; + + // compute weighted sum of inputs + for ( int i = 0; i < weights.Length; i++ ) + { + sum += weights[i] * input[i]; + } + sum += threshold; + + // local variable to avoid mutlithreaded conflicts + double output = function.Function( sum ); + // assign output property as well (works correctly for single threaded usage) + this.output = output; + + return output; + } + } +} diff --git a/Sources/Accord.Neuro/AForge/Neurons/DistanceNeuron.cs b/Sources/Accord.Neuro/AForge/Neurons/DistanceNeuron.cs new file mode 100644 index 0000000000..73c5720b8 --- /dev/null +++ b/Sources/Accord.Neuro/AForge/Neurons/DistanceNeuron.cs @@ -0,0 +1,79 @@ +// AForge Neural Net Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2012 +// contacts@aforgenet.com +// + +namespace AForge.Neuro +{ + using System; + + /// + /// Distance neuron. + /// + /// + /// Distance neuron computes its output as distance between + /// its weights and inputs - sum of absolute differences between weights' + /// values and corresponding inputs' values. The neuron is usually used in Kohonen + /// Self Organizing Map. + /// + [Serializable] + public class DistanceNeuron : Neuron + { + /// + /// Initializes a new instance of the class. + /// + /// + /// Neuron's inputs count. + /// + public DistanceNeuron( int inputs ) : base( inputs ) { } + + /// + /// Computes output value of neuron. + /// + /// + /// Input vector. + /// + /// Returns neuron's output value. + /// + /// The output value of distance neuron is equal to the distance + /// between its weights and inputs - sum of absolute differences. + /// The output value is also stored in Output + /// property. + /// + /// The method may be called safely from multiple threads to compute neuron's + /// output value for the specified input values. However, the value of + /// property in multi-threaded environment is not predictable, + /// since it may hold neuron's output computed from any of the caller threads. Multi-threaded + /// access to the method is useful in those cases when it is required to improve performance + /// by utilizing several threads and the computation is based on the immediate return value + /// of the method, but not on neuron's output property. + /// + /// + /// Wrong length of the input vector, which is not + /// equal to the expected value. + /// + public override double Compute( double[] input ) + { + // check for corrent input vector + if ( input.Length != inputsCount ) + throw new ArgumentException( "Wrong length of the input vector." ); + + // difference value + double dif = 0.0; + + // compute distance between inputs and weights + for ( int i = 0; i < inputsCount; i++ ) + { + dif += Math.Abs( weights[i] - input[i] ); + } + + // assign output property as well (works correctly for single threaded usage) + this.output = dif; + + return dif; + } + } +} diff --git a/Sources/Accord.Neuro/AForge/Neurons/Neuron.cs b/Sources/Accord.Neuro/AForge/Neurons/Neuron.cs new file mode 100644 index 0000000000..b75738796 --- /dev/null +++ b/Sources/Accord.Neuro/AForge/Neurons/Neuron.cs @@ -0,0 +1,162 @@ +// AForge Neural Net Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2012 +// contacts@aforgenet.com +// + +namespace AForge.Neuro +{ + using System; + using AForge; + + /// + /// Base neuron class. + /// + /// + /// This is a base neuron class, which encapsulates such + /// common properties, like neuron's input, output and weights. + /// + [Serializable] + public abstract class Neuron + { + /// + /// Neuron's inputs count. + /// + protected int inputsCount = 0; + + /// + /// Neuron's weights. + /// + protected double[] weights = null; + + /// + /// Neuron's output value. + /// + protected double output = 0; + + /// + /// Random number generator. + /// + /// + /// The generator is used for neuron's weights randomization. + /// + protected static ThreadSafeRandom rand = new ThreadSafeRandom(); + + /// + /// Random generator range. + /// + /// + /// Sets the range of random generator. Affects initial values of neuron's weight. + /// Default value is [0, 1]. + /// + protected static Range randRange = new Range(0.0f, 1.0f); + + /// + /// Random number generator. + /// + /// + /// The property allows to initialize random generator with a custom seed. The generator is + /// used for neuron's weights randomization. + /// + public static ThreadSafeRandom RandGenerator + { + get { return rand; } + set + { + if (value != null) + rand = value; + } + } + + /// + /// Random generator range. + /// + /// + /// Sets the range of random generator. Affects initial values of neuron's weight. + /// Default value is [0, 1]. + /// + public static Range RandRange + { + get { return randRange; } + set { randRange = value; } + } + + /// + /// Neuron's inputs count. + /// + public int InputsCount + { + get { return inputsCount; } + } + + /// + /// Neuron's output value. + /// + /// + /// The calculation way of neuron's output value is determined by inherited class. + /// + public double Output + { + get { return output; } + } + + + /// + /// Neuron's weights. + /// + public double[] Weights + { + get { return weights; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Neuron's inputs count. + /// + /// The new neuron will be randomized (see method) + /// after it is created. + /// + protected Neuron(int inputs) + { + // allocate weights + inputsCount = Math.Max(1, inputs); + weights = new double[inputsCount]; + + // randomize the neuron + Randomize(); + } + + /// + /// Randomize neuron. + /// + /// + /// Initialize neuron's weights with random values within the range specified + /// by . + /// + public virtual void Randomize() + { + double d = randRange.Length; + + // randomize weights + for (int i = 0; i < inputsCount; i++) + weights[i] = rand.NextDouble() * d + randRange.Min; + } + + /// + /// Computes output value of neuron. + /// + /// + /// Input vector. + /// + /// Returns neuron's output value. + /// + /// The actual neuron's output value is determined by inherited class. + /// The output value is also stored in property. + /// + public abstract double Compute(double[] input); + } +} diff --git a/Sources/Accord.Neuro/Accord.Neuro.csproj b/Sources/Accord.Neuro/Accord.Neuro.csproj index d22391a93..5eba37d6b 100644 --- a/Sources/Accord.Neuro/Accord.Neuro.csproj +++ b/Sources/Accord.Neuro/Accord.Neuro.csproj @@ -36,50 +36,36 @@ False True DEBUG;TRACE - ..\..\Debug\ + $(SolutionDir)..\Debug\ - ..\..\Release\net35 + $(SolutionDir)..\Release\net35 TRACE;CODE_ANALYSIS;NET35 v3.5 true - ..\..\Release\net35\Accord.Neuro.XML - ..\..\Release\net35\Accord.Neuro.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net35\Accord.Neuro.XML + $(SolutionDir)..\Release\net35\Accord.Neuro.dll.CodeAnalysisLog.xml - ..\..\Release\net40 + $(SolutionDir)..\Release\net40 TRACE;CODE_ANALYSIS;NET40 v4.0 - ..\..\Release\net40\Accord.Neuro.XML - ..\..\Release\net40\Accord.Neuro.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net40\Accord.Neuro.XML + $(SolutionDir)..\Release\net40\Accord.Neuro.dll.CodeAnalysisLog.xml - ..\..\Release\net45 + $(SolutionDir)..\Release\net45 TRACE;CODE_ANALYSIS;NET45 v4.5 - ..\..\Release\net45\Accord.Neuro.XML - ..\..\Release\net45\Accord.Neuro.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net45\Accord.Neuro.XML + $(SolutionDir)..\Release\net45\Accord.Neuro.dll.CodeAnalysisLog.xml - - False - ..\..\Externals\AForge.NET\AForge.dll - False - - - False - ..\..\Externals\AForge.NET\AForge.Math.dll - False - - - False - ..\..\Externals\AForge.NET\AForge.Neuro.dll - False - 3.5 + @@ -91,6 +77,29 @@ + + + + + + + + + + + + + + + + + + + + + + + @@ -115,6 +124,10 @@ {A177A90C-8207-466A-AF70-F2B8452A42AC} Accord.Core + + {2efaa327-1789-4438-b9f5-e83acae12db2} + Accord.Genetic + {F718E9A8-DB62-4785-8C49-4333A60D256A} Accord.Math @@ -149,13 +162,17 @@ true - + + + + + - - \ No newline at end of file + diff --git a/Sources/Accord.Neuro/Learning/ContrastiveDivergenceLearning.cs b/Sources/Accord.Neuro/Learning/ContrastiveDivergenceLearning.cs index 14fd8d64c..f07330520 100644 --- a/Sources/Accord.Neuro/Learning/ContrastiveDivergenceLearning.cs +++ b/Sources/Accord.Neuro/Learning/ContrastiveDivergenceLearning.cs @@ -325,6 +325,108 @@ private double ComputeGradient(double[][] input) #endif return errors; + } + + /// + /// Computes the reconstruction error of the current layer. + /// + /// + /// Array of input vectors. + /// + /// + /// Returns sum of learning errors. + /// + /// + public double ComputeError(double[][] input) + { + double errors = 0; + + +#if NET35 + var partial = storage.Value.Clear(); + for (int i = 0; i < input.Length; i++) + { + int observationIndex = i; +#else + Object lockObj = new Object(); + + // For each training instance + Parallel.For(0, input.Length, + +#if DEBUG + new ParallelOptions() { MaxDegreeOfParallelism = 1 }, +#endif + + // Initialize + () => storage.Value.Clear(), + + // Map + (observationIndex, loopState, partial) => +#endif + { + var observation = input[observationIndex]; + + var probability = partial.OriginalProbability; + var activations = partial.OriginalActivations; + var reconstruction = partial.ReconstructedInput; + + + // 1. Compute a forward pass. The network is being + // driven by data, so we will gather activations + for (int j = 0; j < hidden.Neurons.Length; j++) + { + probability[j] = hidden.Neurons[j].Compute(observation); // output probabilities + activations[j] = hidden.Neurons[j].Generate(probability[j]); // state activations + } + + // 2. Reconstruct inputs from previous outputs + for (int j = 0; j < visible.Neurons.Length; j++) + reconstruction[j] = visible.Neurons[j].Compute(activations); + + if (steps > 1) + { + // Perform Gibbs sampling + double[] current = probability; + for (int k = 0; k < steps - 1; k++) + { + for (int j = 0; j < probability.Length; j++) + probability[j] = hidden.Neurons[j].Compute(current); + for (int j = 0; j < reconstruction.Length; j++) + reconstruction[j] = visible.Neurons[j].Compute(probability); + current = reconstruction; + } + } + + // Compute current error + for (int j = 0; j < observation.Length; j++) + { + double e = observation[j] - reconstruction[j]; + partial.ErrorSumOfSquares += e * e; + } + +#if !NET35 + return partial; // Report partial solution + }, + + // Reduce + (partial) => + { + lock (lockObj) + { + errors += partial.ErrorSumOfSquares; + } + }); +#else + } + } + + weightsGradient = partial.WeightGradient; + hiddenBiasGradient = partial.HiddenBiasGradient; + visibleBiasGradient = partial.VisibleBiasGradient; + errors = partial.ErrorSumOfSquares; +#endif + + return errors; } private void CalculateUpdates(double[][] input) diff --git a/Sources/Accord.Neuro/Learning/DeepBeliefNetworkLearning.cs b/Sources/Accord.Neuro/Learning/DeepBeliefNetworkLearning.cs index bb0fc051e..e55cdfd5b 100644 --- a/Sources/Accord.Neuro/Learning/DeepBeliefNetworkLearning.cs +++ b/Sources/Accord.Neuro/Learning/DeepBeliefNetworkLearning.cs @@ -1,271 +1,271 @@ -// Accord Neural Net Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Neuro.Learning -{ - using System; - using System.Collections.Generic; - using Accord.Neuro.Layers; - using Accord.Neuro.Networks; - using AForge.Neuro.Learning; - - /// - /// Delegate used to configure and create layer-specific learning algorithms. - /// - /// - /// The hidden layer being trained. - /// The visible layer being trained. - /// The layer-pair index in the deep network. - /// - /// - /// The function should return an instance of the algorithm - /// which should be used to train the pair of layers. - /// - /// - public delegate IUnsupervisedLearning RestrictedBoltzmannNetworkLearningConfigurationFunction( - StochasticLayer hiddenLayer, StochasticLayer visibleLayer, int index); - - /// - /// Deep Belief Network learning algorithm. - /// - /// - public class DeepBeliefNetworkLearning : IUnsupervisedLearning - { - - private DeepBeliefNetwork network; - private RestrictedBoltzmannNetworkLearningConfigurationFunction configure; - - private int layerIndex = 0; - - private IUnsupervisedLearning[] algorithms; - - /// - /// Gets or sets the configuration function used - /// to specify and create the learning algorithms - /// for each of the layers of the deep network. - /// - /// - public RestrictedBoltzmannNetworkLearningConfigurationFunction Algorithm - { - get { return configure; } - set - { - configure = value; - createAlgorithms(); - } - } - - private void createAlgorithms() - { - algorithms = new IUnsupervisedLearning[network.Machines.Count]; - for (int i = 0; i < network.Machines.Count; i++) - { - StochasticLayer hidden = network.Machines[i].Hidden; - StochasticLayer visible = network.Machines[i].Visible; - algorithms[i] = configure(hidden, visible, i); - } - } - - /// - /// Gets or sets the current layer index being - /// trained by the deep learning algorithm. - /// - /// - public int LayerIndex - { - get { return layerIndex; } - set - { - if (layerIndex < 0 || layerIndex >= network.Machines.Count) - throw new ArgumentOutOfRangeException("value"); - - layerIndex = value; - } - } - - /// - /// Creates a new algorithm. - /// - /// - /// The network to be trained. - /// - public DeepBeliefNetworkLearning(DeepBeliefNetwork network) - { - this.network = network; - } - - /// - /// Gets the learning data needed to train the currently - /// selected layer. The return of this function should then be passed to - /// to actually run a learning epoch. - /// - /// - /// The batch of input data. - /// - /// The learning data for the current layer. - /// - public double[][] GetLayerInput(double[][] input) - { - return GetLayerInput(new[] { input })[0]; - } - - /// - /// Gets the learning data needed to train the currently - /// selected layer. The return of this function should then be passed to - /// to actually run a learning epoch. - /// - /// - /// The mini-batches of input data. - /// - /// The learning data for the current layer. - /// - public double[][][] GetLayerInput(double[][][] batches) - { - if (layerIndex == 0) - return batches; - - var outputBatches = new double[batches.Length][][]; - - for (int j = 0; j < batches.Length; j++) - { - int batchSize = batches[j].Length; - - double[][] inputs = batches[j]; - double[][] outputs = new double[batchSize][]; - - for (int i = 0; i < inputs.Length; i++) +// Accord Neural Net Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Neuro.Learning +{ + using System; + using System.Collections.Generic; + using Accord.Neuro.Layers; + using Accord.Neuro.Networks; + using AForge.Neuro.Learning; + + /// + /// Delegate used to configure and create layer-specific learning algorithms. + /// + /// + /// The hidden layer being trained. + /// The visible layer being trained. + /// The layer-pair index in the deep network. + /// + /// + /// The function should return an instance of the algorithm + /// which should be used to train the pair of layers. + /// + /// + public delegate IUnsupervisedLearning RestrictedBoltzmannNetworkLearningConfigurationFunction( + StochasticLayer hiddenLayer, StochasticLayer visibleLayer, int index); + + /// + /// Deep Belief Network learning algorithm. + /// + /// + public class DeepBeliefNetworkLearning : IUnsupervisedLearning + { + + private DeepBeliefNetwork network; + private RestrictedBoltzmannNetworkLearningConfigurationFunction configure; + + private int layerIndex = 0; + + private IUnsupervisedLearning[] algorithms; + + /// + /// Gets or sets the configuration function used + /// to specify and create the learning algorithms + /// for each of the layers of the deep network. + /// + /// + public RestrictedBoltzmannNetworkLearningConfigurationFunction Algorithm + { + get { return configure; } + set + { + configure = value; + createAlgorithms(); + } + } + + private void createAlgorithms() + { + algorithms = new IUnsupervisedLearning[network.Machines.Count]; + for (int i = 0; i < network.Machines.Count; i++) + { + StochasticLayer hidden = network.Machines[i].Hidden; + StochasticLayer visible = network.Machines[i].Visible; + algorithms[i] = configure(hidden, visible, i); + } + } + + /// + /// Gets or sets the current layer index being + /// trained by the deep learning algorithm. + /// + /// + public int LayerIndex + { + get { return layerIndex; } + set + { + if (layerIndex < 0 || layerIndex >= network.Machines.Count) + throw new ArgumentOutOfRangeException("value"); + + layerIndex = value; + } + } + + /// + /// Creates a new algorithm. + /// + /// + /// The network to be trained. + /// + public DeepBeliefNetworkLearning(DeepBeliefNetwork network) + { + this.network = network; + } + + /// + /// Gets the learning data needed to train the currently + /// selected layer. The return of this function should then be passed to + /// to actually run a learning epoch. + /// + /// + /// The batch of input data. + /// + /// The learning data for the current layer. + /// + public double[][] GetLayerInput(double[][] input) + { + return GetLayerInput(new[] { input })[0]; + } + + /// + /// Gets the learning data needed to train the currently + /// selected layer. The return of this function should then be passed to + /// to actually run a learning epoch. + /// + /// + /// The mini-batches of input data. + /// + /// The learning data for the current layer. + /// + public double[][][] GetLayerInput(double[][][] batches) + { + if (layerIndex == 0) + return batches; + + var outputBatches = new double[batches.Length][][]; + + for (int j = 0; j < batches.Length; j++) + { + int batchSize = batches[j].Length; + + double[][] inputs = batches[j]; + double[][] outputs = new double[batchSize][]; + + for (int i = 0; i < inputs.Length; i++) { - network.Compute(inputs[i]); // double[] responses = - outputs[i] = network.Machines[layerIndex - 1].Hidden.Output; - } - - outputBatches[j] = outputs; - } - - return outputBatches; - } - - /// - /// Gets the unsupervised - /// learning algorithm allocated for the given layer. - /// - /// - /// The index of the layer to get the algorithm for. - /// - public IUnsupervisedLearning GetLayerAlgorithm(int layerIndex) - { - return algorithms[layerIndex]; - } - - /// - /// Runs a single learning iteration. - /// - /// - /// A single input vector. - /// - /// - /// Returns the learning error after the iteration. - /// - /// - public double Run(double[] input) - { - // Get layer learning algorithm - var teacher = algorithms[layerIndex]; - - // Learn the layer using data - return teacher.Run(input); - } - - /// - /// Runs a single batch epoch - /// of the learning algorithm. - /// - /// - /// Array of input vectors. - /// - /// - /// Returns sum of learning errors. - /// - /// - public double RunEpoch(double[][] input) - { - // Get layer learning algorithm - var teacher = algorithms[layerIndex]; - - // Learn the layer using data - return teacher.RunEpoch(input); - } - - /// - /// Runs a single learning epoch using - /// multiple mini-batches to improve speed. - /// - /// - /// Array of input batches. - /// - /// - /// Returns sum of learning errors. - /// - /// - public double RunEpoch(double[][][] batches) - { - // Get layer learning algorithm - var teacher = algorithms[layerIndex]; - - // Learn the layer using data - double error = 0; - for (int i = 0; i < batches.Length; i++) - error += teacher.RunEpoch(batches[i]); - - return error; - } - - /// - /// Computes the reconstruction error for - /// a given set of input values. - /// - /// - /// The input values. - /// - /// The squared reconstruction error. - /// - public double ComputeError(double[][] inputs) - { - double error = 0; - for (int i = 0; i < inputs.Length; i++) - { - double[] output = network.Compute(inputs[i]); - double[] reconstruct = network.Reconstruct(output); - - for (int j = 0; j < inputs[i].Length; j++) - { - double e = reconstruct[j] - inputs[i][j]; - error += e * e; - } - } - return error; - } - - - - } -} + network.Compute(inputs[i]); // double[] responses = + outputs[i] = network.Machines[layerIndex - 1].Hidden.Output; + } + + outputBatches[j] = outputs; + } + + return outputBatches; + } + + /// + /// Gets the unsupervised + /// learning algorithm allocated for the given layer. + /// + /// + /// The index of the layer to get the algorithm for. + /// + public IUnsupervisedLearning GetLayerAlgorithm(int layerIndex) + { + return algorithms[layerIndex]; + } + + /// + /// Runs a single learning iteration. + /// + /// + /// A single input vector. + /// + /// + /// Returns the learning error after the iteration. + /// + /// + public double Run(double[] input) + { + // Get layer learning algorithm + var teacher = algorithms[layerIndex]; + + // Learn the layer using data + return teacher.Run(input); + } + + /// + /// Runs a single batch epoch + /// of the learning algorithm. + /// + /// + /// Array of input vectors. + /// + /// + /// Returns sum of learning errors. + /// + /// + public double RunEpoch(double[][] input) + { + // Get layer learning algorithm + var teacher = algorithms[layerIndex]; + + // Learn the layer using data + return teacher.RunEpoch(input); + } + + /// + /// Runs a single learning epoch using + /// multiple mini-batches to improve speed. + /// + /// + /// Array of input batches. + /// + /// + /// Returns sum of learning errors. + /// + /// + public double RunEpoch(double[][][] batches) + { + // Get layer learning algorithm + var teacher = algorithms[layerIndex]; + + // Learn the layer using data + double error = 0; + for (int i = 0; i < batches.Length; i++) + error += teacher.RunEpoch(batches[i]); + + return error; + } + + /// + /// Computes the reconstruction error for + /// a given set of input values. + /// + /// + /// The input values. + /// + /// The squared reconstruction error. + /// + public double ComputeError(double[][] inputs) + { + double error = 0; + for (int i = 0; i < inputs.Length; i++) + { + double[] output = network.Compute(inputs[i]); + double[] reconstruct = network.Reconstruct(output); + + for (int j = 0; j < inputs[i].Length; j++) + { + double e = reconstruct[j] - inputs[i][j]; + error += e * e; + } + } + return error; + } + + + + } +} diff --git a/Sources/Accord.Neuro/Learning/DeepNeuralNetworkLearning.cs b/Sources/Accord.Neuro/Learning/DeepNeuralNetworkLearning.cs index 48d513815..eca7a7f52 100644 --- a/Sources/Accord.Neuro/Learning/DeepNeuralNetworkLearning.cs +++ b/Sources/Accord.Neuro/Learning/DeepNeuralNetworkLearning.cs @@ -1,297 +1,297 @@ -// Accord Neural Net Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Neuro.Learning -{ - using System; - using System.Collections.Generic; - using Accord.Neuro.Layers; - using Accord.Neuro.Networks; - using AForge.Neuro.Learning; - using AForge.Neuro; - - /// - /// Delegate used to configure and create layer-specific learning algorithms. - /// - /// - /// The network layer being trained. - /// The index of the layer in the deep network. - /// - /// - /// The function should return an instance of the algorithm - /// which should be used to train the network. - /// - /// - public delegate ISupervisedLearning ActivationNetworkLearningConfigurationFunction( - ActivationNetwork network, int index); - - /// - /// Deep Neural Network learning algorithm. - /// - /// - public class DeepNeuralNetworkLearning : ISupervisedLearning - { - - private DeepBeliefNetwork network; - private ActivationNetworkLearningConfigurationFunction configure; - - private int layerIndex = 0; - private int layerCount = 1; - - private ISupervisedLearning algorithm; - - /// - /// Gets or sets the configuration function used - /// to specify and create the learning algorithms - /// for each of the layers of the deep network. - /// - /// - public ActivationNetworkLearningConfigurationFunction Algorithm - { - get { return configure; } - set - { - configure = value; - algorithm = null; - } - } - - private void createAlgorithms() - { - if (layerCount == 1) - { - algorithm = configure(network.Machines[layerIndex], layerIndex); - } - else - { - var machines = new RestrictedBoltzmannMachine[layerCount]; - for (int i = 0; i < machines.Length; i++) - machines[i] = network.Machines[i + layerIndex]; - int inputsCount = machines[0].InputsCount; - - algorithm = configure(new DeepBeliefNetwork(inputsCount, machines), layerIndex); - } - } - - /// - /// Gets or sets the current layer index being - /// trained by the deep learning algorithm. - /// - /// - public int LayerIndex - { - get { return layerIndex; } - set - { - if (value < 0 || value >= network.Machines.Count) - throw new ArgumentOutOfRangeException("value"); - - layerIndex = value; - algorithm = null; - } - } - - /// - /// Gets or sets the number of layers, starting at - /// to be trained by the deep learning algorithm. - /// - /// - public int LayerCount - { - get { return layerCount; } - set - { - if (value <= 0) - throw new ArgumentOutOfRangeException("value"); - - layerCount = value; - algorithm = null; - } - } - - /// - /// Creates a new algorithm. - /// - /// - /// The network to be trained. - /// - public DeepNeuralNetworkLearning(DeepBeliefNetwork network) - { - this.network = network; - } - - /// - /// Gets the learning data needed to train the currently - /// selected layer. The return of this function should then be passed to - /// to actually run a learning epoch. - /// - /// - /// The batch of input data. - /// - /// The learning data for the current layer. - /// - public double[][] GetLayerInput(double[][] input) - { - return GetLayerInput(new[] { input })[0]; - } - - /// - /// Gets the learning data needed to train the currently - /// selected layer. The return of this function should then be passed to - /// to actually run a learning epoch. - /// - /// - /// The mini-batches of input data. - /// - /// The learning data for the current layer. - /// - public double[][][] GetLayerInput(double[][][] batches) - { - if (layerIndex == 0) - return batches; - - var outputBatches = new double[batches.Length][][]; - - for (int j = 0; j < batches.Length; j++) - { - int batchSize = batches[j].Length; - - double[][] inputs = batches[j]; - double[][] outputs = new double[batchSize][]; - - for (int i = 0; i < inputs.Length; i++) +// Accord Neural Net Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Neuro.Learning +{ + using System; + using System.Collections.Generic; + using Accord.Neuro.Layers; + using Accord.Neuro.Networks; + using AForge.Neuro.Learning; + using AForge.Neuro; + + /// + /// Delegate used to configure and create layer-specific learning algorithms. + /// + /// + /// The network layer being trained. + /// The index of the layer in the deep network. + /// + /// + /// The function should return an instance of the algorithm + /// which should be used to train the network. + /// + /// + public delegate ISupervisedLearning ActivationNetworkLearningConfigurationFunction( + ActivationNetwork network, int index); + + /// + /// Deep Neural Network learning algorithm. + /// + /// + public class DeepNeuralNetworkLearning : ISupervisedLearning + { + + private DeepBeliefNetwork network; + private ActivationNetworkLearningConfigurationFunction configure; + + private int layerIndex = 0; + private int layerCount = 1; + + private ISupervisedLearning algorithm; + + /// + /// Gets or sets the configuration function used + /// to specify and create the learning algorithms + /// for each of the layers of the deep network. + /// + /// + public ActivationNetworkLearningConfigurationFunction Algorithm + { + get { return configure; } + set + { + configure = value; + algorithm = null; + } + } + + private void createAlgorithms() + { + if (layerCount == 1) + { + algorithm = configure(network.Machines[layerIndex], layerIndex); + } + else + { + var machines = new RestrictedBoltzmannMachine[layerCount]; + for (int i = 0; i < machines.Length; i++) + machines[i] = network.Machines[i + layerIndex]; + int inputsCount = machines[0].InputsCount; + + algorithm = configure(new DeepBeliefNetwork(inputsCount, machines), layerIndex); + } + } + + /// + /// Gets or sets the current layer index being + /// trained by the deep learning algorithm. + /// + /// + public int LayerIndex + { + get { return layerIndex; } + set + { + if (value < 0 || value >= network.Machines.Count) + throw new ArgumentOutOfRangeException("value"); + + layerIndex = value; + algorithm = null; + } + } + + /// + /// Gets or sets the number of layers, starting at + /// to be trained by the deep learning algorithm. + /// + /// + public int LayerCount + { + get { return layerCount; } + set + { + if (value <= 0) + throw new ArgumentOutOfRangeException("value"); + + layerCount = value; + algorithm = null; + } + } + + /// + /// Creates a new algorithm. + /// + /// + /// The network to be trained. + /// + public DeepNeuralNetworkLearning(DeepBeliefNetwork network) + { + this.network = network; + } + + /// + /// Gets the learning data needed to train the currently + /// selected layer. The return of this function should then be passed to + /// to actually run a learning epoch. + /// + /// + /// The batch of input data. + /// + /// The learning data for the current layer. + /// + public double[][] GetLayerInput(double[][] input) + { + return GetLayerInput(new[] { input })[0]; + } + + /// + /// Gets the learning data needed to train the currently + /// selected layer. The return of this function should then be passed to + /// to actually run a learning epoch. + /// + /// + /// The mini-batches of input data. + /// + /// The learning data for the current layer. + /// + public double[][][] GetLayerInput(double[][][] batches) + { + if (layerIndex == 0) + return batches; + + var outputBatches = new double[batches.Length][][]; + + for (int j = 0; j < batches.Length; j++) + { + int batchSize = batches[j].Length; + + double[][] inputs = batches[j]; + double[][] outputs = new double[batchSize][]; + + for (int i = 0; i < inputs.Length; i++) { - network.Compute(inputs[i]); // double[] responses = - outputs[i] = network.Machines[layerIndex - 1].Hidden.Output; - } - - outputBatches[j] = outputs; - } - - return outputBatches; - } - - - /// - /// Runs a single learning iteration. - /// - /// - /// A single input vector. - /// The corresponding output vector. - /// - /// - /// Returns the learning error after the iteration. - /// - /// - public double Run(double[] input, double[] output) - { - if (algorithm == null) - createAlgorithms(); - - // Get layer learning algorithm - var teacher = algorithm; - - // Learn the layer using data - return teacher.Run(input, output); - } - - /// - /// Runs a single batch epoch - /// of the learning algorithm. - /// - /// - /// Array of input vectors. - /// Array of corresponding output vectors. - /// - /// - /// Returns sum of learning errors. - /// - /// - public double RunEpoch(double[][] input, double[][] output) - { - if (algorithm == null) - createAlgorithms(); - - // Get layer learning algorithm - var teacher = algorithm; - - // Learn the layer using data - return teacher.RunEpoch(input, output); - } - - /// - /// Runs a single learning epoch using - /// multiple mini-batches to improve speed. - /// - /// - /// Array of input batches. - /// Array of corresponding output batches. - /// - /// - /// Returns sum of learning errors. - /// - /// - public double RunEpoch(double[][][] inputBatches, double[][][] outputBatches) - { - if (algorithm == null) - createAlgorithms(); - - // Get layer learning algorithm - var teacher = algorithm; - - // Learn the layer using data - double error = 0; - for (int i = 0; i < inputBatches.Length; i++) - error += teacher.RunEpoch(inputBatches[i], outputBatches[i]); - - return error; - } - - /// - /// Computes the reconstruction error for - /// a given set of input values. - /// - /// - /// The input values. - /// The corresponding output values. - /// - /// The squared reconstruction error. - /// - public double ComputeError(double[][] inputs, double[][] outputs) - { - double error = 0; - for (int i = 0; i < inputs.Length; i++) - { - double[] output = network.Compute(inputs[i]); - - for (int j = 0; j < inputs[i].Length; j++) - { - double e = output[j] - outputs[i][j]; - error += e * e; - } - } - return error; - } - - - } -} + network.Compute(inputs[i]); // double[] responses = + outputs[i] = network.Machines[layerIndex - 1].Hidden.Output; + } + + outputBatches[j] = outputs; + } + + return outputBatches; + } + + + /// + /// Runs a single learning iteration. + /// + /// + /// A single input vector. + /// The corresponding output vector. + /// + /// + /// Returns the learning error after the iteration. + /// + /// + public double Run(double[] input, double[] output) + { + if (algorithm == null) + createAlgorithms(); + + // Get layer learning algorithm + var teacher = algorithm; + + // Learn the layer using data + return teacher.Run(input, output); + } + + /// + /// Runs a single batch epoch + /// of the learning algorithm. + /// + /// + /// Array of input vectors. + /// Array of corresponding output vectors. + /// + /// + /// Returns sum of learning errors. + /// + /// + public double RunEpoch(double[][] input, double[][] output) + { + if (algorithm == null) + createAlgorithms(); + + // Get layer learning algorithm + var teacher = algorithm; + + // Learn the layer using data + return teacher.RunEpoch(input, output); + } + + /// + /// Runs a single learning epoch using + /// multiple mini-batches to improve speed. + /// + /// + /// Array of input batches. + /// Array of corresponding output batches. + /// + /// + /// Returns sum of learning errors. + /// + /// + public double RunEpoch(double[][][] inputBatches, double[][][] outputBatches) + { + if (algorithm == null) + createAlgorithms(); + + // Get layer learning algorithm + var teacher = algorithm; + + // Learn the layer using data + double error = 0; + for (int i = 0; i < inputBatches.Length; i++) + error += teacher.RunEpoch(inputBatches[i], outputBatches[i]); + + return error; + } + + /// + /// Computes the reconstruction error for + /// a given set of input values. + /// + /// + /// The input values. + /// The corresponding output values. + /// + /// The squared reconstruction error. + /// + public double ComputeError(double[][] inputs, double[][] outputs) + { + double error = 0; + for (int i = 0; i < inputs.Length; i++) + { + double[] output = network.Compute(inputs[i]); + + for (int j = 0; j < inputs[i].Length; j++) + { + double e = output[j] - outputs[i][j]; + error += e * e; + } + } + return error; + } + + + } +} diff --git a/Sources/Accord.Neuro/Learning/LevenbergMarquardtLearning.cs b/Sources/Accord.Neuro/Learning/LevenbergMarquardtLearning.cs index e9289073d..8f73fae82 100644 --- a/Sources/Accord.Neuro/Learning/LevenbergMarquardtLearning.cs +++ b/Sources/Accord.Neuro/Learning/LevenbergMarquardtLearning.cs @@ -386,6 +386,15 @@ public float[][] Hessian get { return hessian; } } + /// + /// Gets the Jacobian matrix created in the last iteration. + /// + /// + public float[][] Jacobian + { + get { return jacobian; } + } + /// /// Gets the gradient vector computed in the last iteration. /// diff --git a/Sources/Accord.Statistics/Accord.Statistics.cd b/Sources/Accord.Statistics/Accord.Statistics.cd index 91b1374db..93bb2a3e5 100644 --- a/Sources/Accord.Statistics/Accord.Statistics.cd +++ b/Sources/Accord.Statistics/Accord.Statistics.cd @@ -1,336 +1,336 @@ - - - - - - AQDBAkAIBYABhAgAAIADAAIwlCAABgFEgAAAgCAoFCQ= - Tools.cs - - - - - - - - - - - - - AEIgwAAgYQQACEAASAEDAAAgACAAEAAACAAgAARAABA= - Visualizations\Histogram.cs - - - - - - - - - - - - - - - AAAAAAAAAAAACAAAAAAgAEAAAAAAAAAAAAAgAAARAAA= - Visualizations\HistogramBin.cs - - - - - - AAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= - Filters\FilterSequence.cs - - - - - - - CAIAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAA= - Filters\Base\BaseFilter.cs - - - - - - - - - AAAAAAAAABAAAAAACAAACAAAAAAAAAAgAAAAAAgAAAA= - Filters\Base\BaseFilter.cs - - - - - - - - - - AAAAAAAAAAAgAAAEAABAAAAAAAAAAAAAAAAAAAAAAAA= - Filters\Base\BaseFilter.cs - - - - - - - - AAAAAAAABQAAAAAAAAAACAQABAAAAAAEgAAACABBCAA= - Moving\MovingCircularStatistics.cs - - - - - - - - - ACAAAAAAAAAAABAAAAAAAAQBBAAEACAEgAAACABACAQ= - Moving\MovingNormalStatistics.cs - - - - - - - - - AAAAAAAAAAAAAACABAAAAAAABAQAAAAUgAAAABBACAA= - Running\RunningNormalStatistics.cs - - - - - - - AAAAAAAAAAAAIAAAAAAACAAAAAAAAAAAAAAEAAAACAA= - Filters\Codification.cs - - - - - - - AAAAAAAAAAAAIAAAAAAACAAAAAAAAAAAAAAAAAAAAAA= - Filters\Discretization.cs - - - - - - - AAAAAAAAAAAAIAAAAAAACAAAAAAAAAAAAAAAAAAACAA= - Filters\LinearScaling.cs - - - - - - - AAAAEAAAABAAIAAAAAAACAAAAAAAAAAAAAAAQAAAAAA= - Filters\Normalization.cs - - - - - - - ACAAAAAAAAAAIAAAAAAAKAAAAAAAAAAAAAAgBAAAAAA= - Filters\PrincipalComponentProjection.cs - - - - - - - AAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAA= - Filters\Projection.cs - - - - - - - AIAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAA= - Filters\Selection.cs - - - - - - - AAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAA= - Filters\Branching.cs - - - - - - AAAAAAAAAAAAIAAAAAAACAAAAAAAAAAAAAAAAAAAAAA= - Filters\Elimination.cs - - - - - - - AAAQEAAAQAAAAAAIAAAACAAAAAAAEAABAAAAAQCAAAA= - Filters\Grouping.cs - - - - - - AAAAAAAAABAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAA= - Filters\Identification.cs - - - - - - - AAAAAAAAAAAAIAAAAAAACAAAAAAAAAAAAAAAAAAAAAA= - Filters\Imputation.cs - - - - - - - AAAAAAAAABAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA= - Filters\Randomization.cs - - - - - - - AAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAA= - Filters\Stratification.cs - - - - - - - - AAAAAAAAAABEAAAAAAQAAAAAAAABACAAAAAgAABICAA= - Running\Markov\RunningMarkovClassifier.cs - - - - - - - - - AAAAAAAAAABEAAAAAAQAAAAAAAABACAAAAAgAABICAA= - Running\Markov\RunningMarkovClassifier`1.cs - - - - - - - - - AAAAAAAAAAAEAAEAAAKAACAAAAIAAAAAAAkIAAJACAA= - Running\Markov\RunningMarkovStatistics.cs - - - - - - - - - AAAAAAAAAAAEAAEAAAKAACAAAAIAAAAAAAkIAAJACAA= - Running\Markov\RunningMarkovStatistics`1.cs - - - - - - - AAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= - Filters\Base\IFilter.cs - - - - - - AAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= - Filters\Base\IAutoConfigurableFilter.cs - - - - - - AAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAACAAAAAA= - Moving\IMovingStatistics.cs - - - - - - AAAAAAAAAAAAAAAAAAAAAAAABAAAAAAEgAAAAAAAAAA= - Running\IRunningStatistics.cs - - - - - - AAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= - Filters\Base\IAutoConfigurableColumn.cs - - - - - - AAAAAAAAAAAAAAEAAACAACAAAAIAAAAAAAEAAABAAAA= - Running\Markov\IRunningMarkovStatistics.cs - - - - - - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABACAA= - Running\IRunning`1.cs - - - + + + + + + AQDBAkAIBYYRhAgAAIADAAI4lCgABgFEgAggoCAoFCQ= + Measures\Measures.Matrix.cs + + + + + + + + + + + + + AEIgwAAgYQQACEAASAEDAAAgACAAEAAACAAgAARAABA= + Visualizations\Histogram.cs + + + + + + + + + + + + + + + AAAAAAAAAAAACAAAAAAgAEAAAAAAAAAAAAAgAAARAAA= + Visualizations\HistogramBin.cs + + + + + + AAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + Filters\FilterSequence.cs + + + + + + + CAIAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + Filters\Base\BaseFilter.cs + + + + + + + + + AAAAAAAAABAAAAAACAAACAAAAAAAAAAgAAAAAAgAAAA= + Filters\Base\BaseFilter.cs + + + + + + + + + + AAAAAAAAAAAgAAAEAABAAAAAAAAAAAAAAAAAAAAAAAA= + Filters\Base\BaseFilter.cs + + + + + + + + AAAAAAAABQAAAAAAAAAACAQABAAAAAAEgAAACABBCAA= + Moving\MovingCircularStatistics.cs + + + + + + + + + ACAAAAAAAAAAABAAAAAAAAQBBAAEACAEgAAACABACAQ= + Moving\MovingNormalStatistics.cs + + + + + + + + + AAAAAAAAAAAAAACABAAAAAAABAQAAAAUgAAAABBACAA= + Running\RunningNormalStatistics.cs + + + + + + + AAAAAAAAAAQAIAAAAAAACAAAAAAAAAAAAAAEAAAACAA= + Filters\Codification.cs + + + + + + + AAAAAAAAAAAAIAAAAAAACAAAAAAAAAAAAAAAAAAAAAA= + Filters\Discretization.cs + + + + + + + AAAAAAAAAAAAIAAAAAAACAAAAAAAAAAAAAAAAAAACAA= + Filters\LinearScaling.cs + + + + + + + AAAAEAAAABAAIAAAAAAACAAAAAAAAAAAAAAAQAAAAAA= + Filters\Normalization.cs + + + + + + + ACAAAAAAAAAAIAAAAAAAKAAAAAAAAAAAAAAgBAAAAAA= + Filters\PrincipalComponentProjection.cs + + + + + + + AAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAA= + Filters\Projection.cs + + + + + + + AIAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAA= + Filters\Selection.cs + + + + + + + AAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAA= + Filters\Branching.cs + + + + + + AAAAAAAAAAAAIAAAAAAACAAAAAAAAAAAAAAAAAAAAAA= + Filters\Elimination.cs + + + + + + + AAAQEAAAQAAAAAAIAAAACAAAAAAAEAABAAAAAQCAAAA= + Filters\Grouping.cs + + + + + + AAAAAAAAABAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAA= + Filters\Identification.cs + + + + + + + AAAAAAAAAAAAIAAAAAAACAAAAAAAAAAAAAAAAAAAAAA= + Filters\Imputation.cs + + + + + + + AAAAAAAAABAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA= + Filters\Randomization.cs + + + + + + + AAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAA= + Filters\Stratification.cs + + + + + + + + AAAAAAAAAABEAAAAAAQAAAAAAAABACAAAAAgAABICAA= + Running\Markov\RunningMarkovClassifier.cs + + + + + + + + + AAAAAAAAAABEAAAAAAQAAAAAAAABACAAAAAgAABICAA= + Running\Markov\RunningMarkovClassifier`1.cs + + + + + + + + + AAAAAAAAAAAEAAEAAAKAACAAAAIAAAAAAAkIAAJACAA= + Running\Markov\RunningMarkovStatistics.cs + + + + + + + + + AAAAAAAAAAAEAAEAAAKAACAAAAIAAAAAAAkIAAJACAA= + Running\Markov\RunningMarkovStatistics`1.cs + + + + + + + AAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + Filters\Base\IFilter.cs + + + + + + AAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + Filters\Base\IAutoConfigurableFilter.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAACAAAAAA= + Moving\IMovingStatistics.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAAABAAAAAAEgAAAAAAAAAA= + Running\IRunningStatistics.cs + + + + + + AAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + Filters\Base\IAutoConfigurableColumn.cs + + + + + + AAAAAAAAAAAAAAEAAACAACAAAAIAAAAAAAEAAABAAAA= + Running\Markov\IRunningMarkovStatistics.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABACAA= + Running\IRunning`1.cs + + + \ No newline at end of file diff --git a/Sources/Accord.Statistics/Accord.Statistics.csproj b/Sources/Accord.Statistics/Accord.Statistics.csproj index f8486b8df..4fbea9bdf 100644 --- a/Sources/Accord.Statistics/Accord.Statistics.csproj +++ b/Sources/Accord.Statistics/Accord.Statistics.csproj @@ -36,48 +36,39 @@ False True DEBUG;TRACE - ..\..\Debug\ + $(SolutionDir)..\Debug\ - ..\..\Release\net35 + $(SolutionDir)..\Release\net35 TRACE;CODE_ANALYSIS;NET35 v3.5 true - ..\..\Release\net35\Accord.Statistics.XML - ..\..\Release\net35\Accord.Statistics.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net35\Accord.Statistics.XML + $(SolutionDir)..\Release\net35\Accord.Statistics.dll.CodeAnalysisLog.xml - ..\..\Release\net40 + $(SolutionDir)..\Release\net40 TRACE;CODE_ANALYSIS;NET40 v4.0 - ..\..\Release\net40\Accord.Statistics.XML - ..\..\Release\net40\Accord.Statistics.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net40\Accord.Statistics.XML + $(SolutionDir)..\Release\net40\Accord.Statistics.dll.CodeAnalysisLog.xml - ..\..\Release\net45 + $(SolutionDir)..\Release\net45 TRACE;CODE_ANALYSIS;NET45 v4.5 - ..\..\Release\net45\Accord.Statistics.XML - ..\..\Release\net45\Accord.Statistics.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net45\Accord.Statistics.XML + $(SolutionDir)..\Release\net45\Accord.Statistics.dll.CodeAnalysisLog.xml - - ..\..\Externals\AForge.NET\AForge.dll - False - False - - - ..\..\Externals\AForge.NET\AForge.Math.dll - False - False - 3.5 + @@ -262,8 +253,10 @@ + + @@ -411,7 +404,7 @@ - + Code diff --git a/Sources/Accord.Statistics/Analysis/Performance/ConfusionMatrix.cs b/Sources/Accord.Statistics/Analysis/Performance/ConfusionMatrix.cs index 40478b766..99decb010 100644 --- a/Sources/Accord.Statistics/Analysis/Performance/ConfusionMatrix.cs +++ b/Sources/Accord.Statistics/Analysis/Performance/ConfusionMatrix.cs @@ -95,7 +95,7 @@ public ConfusionMatrix( this.truePositives = truePositives; this.trueNegatives = trueNegatives; this.falsePositives = falsePositives; - this.falseNegatives = falseNegatives; + this.falseNegatives = falseNegatives; } /// diff --git a/Sources/Accord.Statistics/Analysis/ProportionalHazardsAnalysis.cs b/Sources/Accord.Statistics/Analysis/ProportionalHazardsAnalysis.cs index 151715237..7b623d1f1 100644 --- a/Sources/Accord.Statistics/Analysis/ProportionalHazardsAnalysis.cs +++ b/Sources/Accord.Statistics/Analysis/ProportionalHazardsAnalysis.cs @@ -1,822 +1,828 @@ -// Accord Statistics Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Statistics.Analysis -{ - using Accord.Math; - using Accord.Statistics.Models.Regression; - using Accord.Statistics.Models.Regression.Fitting; - using Accord.Statistics.Testing; - using AForge; - using System; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using System.ComponentModel; - - /// - /// Cox's Proportional Hazards Survival Analysis. - /// - /// - /// - /// - /// Proportional hazards models are a class of survival models in statistics. Survival models - /// relate the time that passes before some event occurs to one or more covariates that may be - /// associated with that quantity. In a proportional hazards model, the unique effect of a unit - /// increase in a covariate is multiplicative with respect to the hazard rate. - /// - /// - /// For example, taking a drug may halve one's hazard rate for a stroke occurring, or, changing - /// the material from which a manufactured component is constructed may double its hazard rate - /// for failure. Other types of survival models such as accelerated failure time models do not - /// exhibit proportional hazards. These models could describe a situation such as a drug that - /// reduces a subject's immediate risk of having a stroke, but where there is no reduction in - /// the hazard rate after one year for subjects who do not have a stroke in the first year of - /// analysis. - /// - /// - /// This class uses the to extract more detailed - /// information about a given problem, such as confidence intervals, hypothesis tests - /// and performance measures. - /// - /// - /// This class can also be bound to standard controls such as the - /// DataGridView - /// by setting their DataSource property to the analysis' property. - /// - /// - /// - /// - /// // Consider the following example data, adapted from John C. Pezzullo's - /// // example for his great Cox's proportional hazards model example in - /// // JavaScript (http://www.sph.emory.edu/~cdckms/CoxPH/prophaz2.html). - /// - /// // In this data, we have three columns. The first column denotes the - /// // input variables for the problem. The second column, the survival - /// // times. And the last one is the output of the experiment (if the - /// // subject has died [1] or has survived [0]). - /// - /// double[,] example = - /// { - /// // input time censor - /// { 50, 1, 0 }, - /// { 70, 2, 1 }, - /// { 45, 3, 0 }, - /// { 35, 5, 0 }, - /// { 62, 7, 1 }, - /// { 50, 11, 0 }, - /// { 45, 4, 0 }, - /// { 57, 6, 0 }, - /// { 32, 8, 0 }, - /// { 57, 9, 1 }, - /// { 60, 10, 1 }, - /// }; - /// - /// // First we will extract the input, times and outputs - /// double[,] inputs = example.GetColumns(0); - /// double[] times = example.GetColumn(1); - /// int[] output = example.GetColumn(2).ToInt32(); - /// - /// // Now we can proceed and create the analysis - /// var cox = new ProportionalHazardsAnalysis(inputs, times, output); - /// - /// cox.Compute(); // compute the analysis - /// - /// // Now we can show an analysis summary - /// DataGridBox.Show(cox.Coefficients); - /// - /// - /// - /// The resulting table is shown below. - /// - /// - /// - /// // We can also investigate all parameters individually. For - /// // example the coefficients values will be available at - /// - /// double[] coef = cox.CoefficientValues; - /// double[] stde = cox.StandardErrors; - /// - /// // We can also obtain the hazards ratios - /// double[] ratios = cox.HazardRatios; - /// - /// // And other information such as the partial - /// // likelihood, the deviance and also make - /// // hypothesis tests on the parameters - /// - /// double partial = cox.LogLikelihood; - /// double deviance = cox.Deviance; - /// - /// // Chi-Square for whole model - /// ChiSquareTest chi = cox.ChiSquare; - /// - /// // Wald tests for individual parameters - /// WaldTest wald = cox.Coefficients[0].Wald; - /// - /// - /// // Finally, we can also use the model to predict - /// // scores for new observations (without considering time) - /// - /// double y1 = cox.Regression.Compute(new double[] { 63 }); - /// double y2 = cox.Regression.Compute(new double[] { 32 }); - /// - /// // Those scores can be interpreted by comparing then - /// // to 1. If they are greater than one, the odds are - /// // the patient will not survive. If the value is less - /// // than one, the patient is likely to survive. - /// - /// // The first value, y1, gives approximately 86.138, - /// // while the second value, y2, gives about 0.00072. - /// - /// - /// // We can also consider instant estimates for a given time: - /// double p1 = cox.Regression.Compute(new double[] { 63 }, 2); - /// double p2 = cox.Regression.Compute(new double[] { 63 }, 10); - /// - /// // Here, p1 is the score after 2 time instants, with a - /// // value of 0.0656. The second value, p2, is the time - /// // after 10 time instants, with a value of 6.2907. - /// - /// - /// - [Serializable] - public class ProportionalHazardsAnalysis : IRegressionAnalysis - { - private ProportionalHazards regression; - - private int inputCount; - private double[] coefficients; - private double[] standardErrors; - private double[] hazardRatios; - - private WaldTest[] waldTests; - private ChiSquareTest[] ratioTests; - - private DoubleRange[] confidences; - - private double deviance; - private double logLikelihood; - private ChiSquareTest chiSquare; - - private double[][] inputData; - private double[] timeData; - private int[] censorData; - - private string[] inputNames; - private string timeName; - private string censorName; - - private double[,] source; - private double[] result; - - private HazardCoefficientCollection coefficientCollection; - - private int iterations = 50; - private double tolerance = 1e-5; - - private bool innerComputed = false; - - - //--------------------------------------------- - - - #region Constructors - - /// - /// Constructs a new Cox's Proportional Hazards Analysis. - /// - /// - /// The input data for the analysis. - /// The output data for the analysis. - /// The right-censoring indicative values. - /// - public ProportionalHazardsAnalysis(double[,] inputs, double[] times, int[] censor) - { - // Initial argument checking - if (inputs == null) throw new ArgumentNullException("inputs"); - if (times == null) throw new ArgumentNullException("times"); - - if (inputs.GetLength(0) != times.Length) - throw new ArgumentException("The number of rows in the input array must match the number of given outputs."); - - initialize(inputs.ToArray(), times, censor); - - // Start regression using the Null Model - this.regression = new ProportionalHazards(inputCount); - } - - /// - /// Constructs a new Cox's Proportional Hazards Analysis. - /// - /// - /// The input data for the analysis. - /// The output data for the analysis. - /// The right-censoring indicative values. - /// - public ProportionalHazardsAnalysis(double[][] inputs, double[] times, int[] censor) - { - // Initial argument checking - if (inputs == null) throw new ArgumentNullException("inputs"); - if (times == null) throw new ArgumentNullException("times"); - - if (inputs.Length != times.Length) - throw new ArgumentException("The number of rows in the input array must match the number of given outputs."); - - initialize(inputs, times, censor); - - // Start regression using the Null Model - this.regression = new ProportionalHazards(inputCount); - } - - /// - /// Constructs a new Cox's Proportional Hazards Analysis. - /// - /// - /// The input data for the analysis. - /// The output, binary data for the analysis. - /// The right-censoring indicative values. - /// The names of the input variables. - /// The name of the time variable. - /// The name of the event indication variable. - /// - public ProportionalHazardsAnalysis(double[][] inputs, double[] times, int[] censor, - String[] inputNames, String timeName, String censorName) - : this(inputs, times, censor) - { - this.inputNames = inputNames; - this.timeName = timeName; - this.censorName = censorName; - } - - private void initialize(double[][] inputs, double[] outputs, int[] censor) - { - this.inputCount = inputs[0].Length; - int coefficientCount = inputCount; - - // Store data sets - this.inputData = inputs; - this.timeData = outputs; - this.censorData = censor; - - - // Create additional structures - this.coefficients = new double[coefficientCount]; - this.waldTests = new WaldTest[coefficientCount]; - this.standardErrors = new double[coefficientCount]; - this.hazardRatios = new double[coefficientCount]; - this.confidences = new DoubleRange[coefficientCount]; - this.ratioTests = new ChiSquareTest[coefficientCount]; - - this.timeName = "Time"; - this.censorName = "Outcome"; - this.inputNames = new string[inputCount]; - for (int i = 0; i < inputNames.Length; i++) - inputNames[i] = "Input " + i; - - // Create object-oriented structure to represent the analysis - var logCoefs = new List(coefficientCount); - for (int i = 0; i < coefficientCount; i++) - logCoefs.Add(new HazardCoefficient(this, i)); - this.coefficientCollection = new HazardCoefficientCollection(logCoefs); - - this.source = inputs.ToMatrix(); - } - - #endregion - - - //--------------------------------------------- - - - #region Public Properties - - /// - /// Gets or sets the maximum number of iterations to be - /// performed by the regression algorithm. Default is 50. - /// - /// - public int Iterations - { - get { return iterations; } - set { iterations = value; } - } - - /// - /// Gets or sets the difference between two iterations of the regression - /// algorithm when the algorithm should stop. The difference is calculated - /// based on the largest absolute parameter change of the regression. Default - /// is 1e-5. - /// - /// - public double Tolerance - { - get { return tolerance; } - set { tolerance = value; } - } - - /// - /// Source data used in the analysis. - /// - /// - public double[,] Source - { - get { return source; } - } - - /// - /// Gets the time passed until the event - /// occurred or until the observation was - /// censored. - /// - /// - public double[] TimeToEvent - { - get { return timeData; } - } - - /// - /// Gets whether the event of - /// interest happened or not. - /// - /// - public int[] Events - { - get { return censorData; } - } - - /// - /// Gets the dependent variable value - /// for each of the source input points. - /// - /// - public double[] Outputs - { - get { return censorData.ToDouble(); } - } - - /// - /// Gets the resulting probabilities obtained - /// by the logistic regression model. - /// - /// - public double[] Result - { - get { return result; } - } - - - /// - /// Gets the Proportional Hazards model created - /// and evaluated by this analysis. - /// - /// - public ProportionalHazards Regression - { - get { return regression; } - } - - /// - /// Gets the collection of coefficients of the model. - /// - /// - public ReadOnlyCollection Coefficients - { - get { return coefficientCollection; } - } - - /// - /// Gets the Log-Likelihood for the model. - /// - /// - public double LogLikelihood - { - get { return this.logLikelihood; } - } - - /// - /// Gets the Chi-Square (Likelihood Ratio) Test for the model. - /// - /// - public ChiSquareTest ChiSquare - { - get { return this.chiSquare; } - } - - /// - /// Gets the Deviance of the model. - /// - /// - public double Deviance - { - get { return deviance; } - } - - /// - /// Gets the name of the input variables for the model. - /// - /// - public String[] InputNames - { - get { return inputNames; } - } - - /// - /// Gets the name of the output variable for the model. - /// - /// - public String TimeName - { - get { return timeName; } - } - - /// - /// Gets the name of event occurrence variable in the model. - /// - /// - public String EventName - { - get { return censorName; } - } - - /// - /// Gets the Hazard Ratio for each coefficient - /// found during the proportional hazards. - /// - /// - public double[] HazardRatios - { - get { return this.hazardRatios; } - } - - /// - /// Gets the Standard Error for each coefficient - /// found during the proportional hazards. - /// - /// - public double[] StandardErrors - { - get { return this.standardErrors; } - } - - /// - /// Gets the Wald Tests for each coefficient. - /// - /// - public WaldTest[] WaldTests - { - get { return this.waldTests; } - } - - /// - /// Gets the Likelihood-Ratio Tests for each coefficient. - /// - /// - public ChiSquareTest[] LikelihoodRatioTests - { - get - { - if (innerComputed == false) - computeInner(); - - return this.ratioTests; - } - } - - /// - /// Gets the value of each coefficient. - /// - /// - public double[] CoefficientValues - { - get { return this.coefficients; } - } - - /// - /// Gets the 95% Confidence Intervals (C.I.) - /// for each coefficient found in the regression. - /// - /// - public DoubleRange[] Confidences - { - get { return this.confidences; } - } - - #endregion - - - //--------------------------------------------- - - - #region Public Methods - - /// - /// Gets the Log-Likelihood Ratio between this model and another model. - /// - /// - /// Another proportional hazards model. - /// - /// The Likelihood-Ratio between the two models. - /// - public double GetLikelihoodRatio(ProportionalHazards model) - { - return regression.GetLogLikelihoodRatio(inputData, timeData, censorData, model); - } - - /// - /// Computes the Proportional Hazards Analysis for an already computed regression. - /// - /// - public void Compute(ProportionalHazards regression) - { - this.regression = regression; - - computeInformation(); - - innerComputed = false; - } - - /// - /// Computes the Proportional Hazards Analysis. - /// - /// - /// - /// True if the model converged, false otherwise. - /// - /// - public bool Compute() - { - return compute(); - } - - /// - /// Computes the Proportional Hazards Analysis. - /// - /// - /// - /// The difference between two iterations of the regression algorithm - /// when the algorithm should stop. If not specified, the value of - /// 1e-4 will be used. The difference is calculated based on the largest - /// absolute parameter change of the regression. - /// - /// - /// - /// The maximum number of iterations to be performed by the regression - /// algorithm. - /// - /// - /// - /// True if the model converged, false otherwise. - /// - /// - [Obsolete("Please set up the Iterations and Tolerance properties and call Compute() instead.")] - public bool Compute(double limit = 1e-4, int maxIterations = 50) - { - this.iterations = maxIterations; - this.tolerance = limit; - - return compute(); - } - - #endregion - - - - private bool compute() - { - ProportionalHazardsNewtonRaphson learning = - new ProportionalHazardsNewtonRaphson(regression); - - Array.Clear(regression.Coefficients, 0, regression.Coefficients.Length); - - - learning.Iterations = Iterations; - learning.Tolerance = Tolerance; - - learning.Run(inputData, timeData, censorData); - - // Check if the full model has converged - bool converged = learning.CurrentIteration < Iterations; - - - computeInformation(); - - innerComputed = false; - - // Returns true if the full model has converged, false otherwise. - return converged; - } - - private void computeInner() - { - if (inputCount <= 2) - return; - - // Perform likelihood-ratio tests against diminished nested models - ProportionalHazards innerModel = new ProportionalHazards(inputCount - 1); - ProportionalHazardsNewtonRaphson learning = new ProportionalHazardsNewtonRaphson(innerModel); - - for (int i = 0; i < inputCount; i++) - { - // Create a diminished inner model without the current variable - double[][] data = inputData.RemoveColumn(i); - - System.Diagnostics.Trace.Assert(data[0].Length > 0); - - Array.Clear(innerModel.Coefficients, 0, inputCount - 1); - - learning.Iterations = Iterations; - learning.Tolerance = Tolerance; - - learning.Run(data, timeData, censorData); - - - double ratio = 2.0 * (logLikelihood - innerModel.GetPartialLogLikelihood(data, timeData, censorData)); - ratioTests[i] = new ChiSquareTest(ratio, 1); - } - - innerComputed = true; - } - - private void computeInformation() - { - // Store model information - this.result = regression.Compute(inputData, timeData); - this.deviance = regression.GetDeviance(inputData, timeData, censorData); - this.logLikelihood = regression.GetPartialLogLikelihood(inputData, timeData, censorData); - this.chiSquare = regression.ChiSquare(inputData, timeData, censorData); - - // Store coefficient information - for (int i = 0; i < regression.Coefficients.Length; i++) - { - this.standardErrors[i] = regression.StandardErrors[i]; - - this.waldTests[i] = regression.GetWaldTest(i); - this.coefficients[i] = regression.Coefficients[i]; - this.confidences[i] = regression.GetConfidenceInterval(i); - this.hazardRatios[i] = regression.GetHazardRatio(i); - } - } - - /// - /// Computes the analysis using given source data and parameters. - /// - /// - void IAnalysis.Compute() - { - Compute(); - } - - } - - - #region Support Classes - - /// - /// Represents a Proportional Hazards Coefficient found in the Cox's Hazards model, - /// allowing it to be bound to controls like the DataGridView. This class cannot - /// be instantiated outside the . - /// - /// - [Serializable] - public class HazardCoefficient - { - private ProportionalHazardsAnalysis analysis; - private int index; - - - internal HazardCoefficient(ProportionalHazardsAnalysis analysis, int index) - { - this.analysis = analysis; - this.index = index; - } - - /// - /// Gets the name for the current coefficient. - /// - /// - public string Name - { - get - { - if (analysis.InputNames.Length == 0) - return String.Empty; - - return analysis.InputNames[index]; - } - } - - /// - /// Gets the Odds ratio for the current coefficient. - /// - /// - [DisplayName("Hazard ratio")] - public double HazardRatio - { - get { return analysis.HazardRatios[index]; } - } - - /// - /// Gets the Standard Error for the current coefficient. - /// - /// - [DisplayName("Std. Error")] - public double StandardError - { - get { return analysis.StandardErrors[index]; } - } - - /// - /// Gets the 95% confidence interval (C.I.) for the current coefficient. - /// - /// - [Browsable(false)] - public DoubleRange Confidence - { - get { return analysis.Confidences[index]; } - } - - /// - /// Gets the upper limit for the 95% confidence interval. - /// - /// - [DisplayName("Upper confidence limit")] - public double ConfidenceUpper - { - get { return Confidence.Max; } - } - - /// - /// Gets the lower limit for the 95% confidence interval. - /// - /// - [DisplayName("Lower confidence limit")] - public double ConfidenceLower - { - get { return Confidence.Min; } - } - - /// - /// Gets the coefficient value. - /// - /// - [DisplayName("Value")] - public double Value - { - get { return analysis.CoefficientValues[index]; } - } - - /// - /// Gets the Wald's test performed for this coefficient. - /// - /// - [DisplayName("Wald p-value")] - public WaldTest Wald - { - get { return analysis.WaldTests[index]; } - } - - /// - /// Gets the Likelihood-Ratio test performed for this coefficient. - /// - /// - [DisplayName("Likelihood-Ratio p-value")] - public ChiSquareTest LikelihoodRatio - { - get { return analysis.LikelihoodRatioTests[index]; } - } - - - } - - /// - /// Represents a collection of Hazard Coefficients found in the - /// . This class cannot be instantiated. - /// - /// - [Serializable] - public class HazardCoefficientCollection : ReadOnlyCollection - { - internal HazardCoefficientCollection(IList coefficients) - : base(coefficients) { } - } - #endregion - -} +// Accord Statistics Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Statistics.Analysis +{ + using Accord.Math; + using Accord.Statistics.Distributions.Univariate; + using Accord.Statistics.Models.Regression; + using Accord.Statistics.Models.Regression.Fitting; + using Accord.Statistics.Testing; + using AForge; + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.ComponentModel; + + /// + /// Cox's Proportional Hazards Survival Analysis. + /// + /// + /// + /// + /// Proportional hazards models are a class of survival models in statistics. Survival models + /// relate the time that passes before some event occurs to one or more covariates that may be + /// associated with that quantity. In a proportional hazards model, the unique effect of a unit + /// increase in a covariate is multiplicative with respect to the hazard rate. + /// + /// + /// For example, taking a drug may halve one's hazard rate for a stroke occurring, or, changing + /// the material from which a manufactured component is constructed may double its hazard rate + /// for failure. Other types of survival models such as accelerated failure time models do not + /// exhibit proportional hazards. These models could describe a situation such as a drug that + /// reduces a subject's immediate risk of having a stroke, but where there is no reduction in + /// the hazard rate after one year for subjects who do not have a stroke in the first year of + /// analysis. + /// + /// + /// This class uses the to extract more detailed + /// information about a given problem, such as confidence intervals, hypothesis tests + /// and performance measures. + /// + /// + /// This class can also be bound to standard controls such as the + /// DataGridView + /// by setting their DataSource property to the analysis' property. + /// + /// + /// + /// + /// // Consider the following example data, adapted from John C. Pezzullo's + /// // example for his great Cox's proportional hazards model example in + /// // JavaScript (http://www.sph.emory.edu/~cdckms/CoxPH/prophaz2.html). + /// + /// // In this data, we have three columns. The first column denotes the + /// // input variables for the problem. The second column, the survival + /// // times. And the last one is the output of the experiment (if the + /// // subject has died [1] or has survived [0]). + /// + /// double[,] example = + /// { + /// // input time censor + /// { 50, 1, 0 }, + /// { 70, 2, 1 }, + /// { 45, 3, 0 }, + /// { 35, 5, 0 }, + /// { 62, 7, 1 }, + /// { 50, 11, 0 }, + /// { 45, 4, 0 }, + /// { 57, 6, 0 }, + /// { 32, 8, 0 }, + /// { 57, 9, 1 }, + /// { 60, 10, 1 }, + /// }; + /// + /// // First we will extract the input, times and outputs + /// double[,] inputs = example.GetColumns(0); + /// double[] times = example.GetColumn(1); + /// int[] output = example.GetColumn(2).ToInt32(); + /// + /// // Now we can proceed and create the analysis + /// var cox = new ProportionalHazardsAnalysis(inputs, times, output); + /// + /// cox.Compute(); // compute the analysis + /// + /// // Now we can show an analysis summary + /// DataGridBox.Show(cox.Coefficients); + /// + /// + /// + /// The resulting table is shown below. + /// + /// + /// + /// // We can also investigate all parameters individually. For + /// // example the coefficients values will be available at + /// + /// double[] coef = cox.CoefficientValues; + /// double[] stde = cox.StandardErrors; + /// + /// // We can also obtain the hazards ratios + /// double[] ratios = cox.HazardRatios; + /// + /// // And other information such as the partial + /// // likelihood, the deviance and also make + /// // hypothesis tests on the parameters + /// + /// double partial = cox.LogLikelihood; + /// double deviance = cox.Deviance; + /// + /// // Chi-Square for whole model + /// ChiSquareTest chi = cox.ChiSquare; + /// + /// // Wald tests for individual parameters + /// WaldTest wald = cox.Coefficients[0].Wald; + /// + /// + /// // Finally, we can also use the model to predict + /// // scores for new observations (without considering time) + /// + /// double y1 = cox.Regression.Compute(new double[] { 63 }); + /// double y2 = cox.Regression.Compute(new double[] { 32 }); + /// + /// // Those scores can be interpreted by comparing then + /// // to 1. If they are greater than one, the odds are + /// // the patient will not survive. If the value is less + /// // than one, the patient is likely to survive. + /// + /// // The first value, y1, gives approximately 86.138, + /// // while the second value, y2, gives about 0.00072. + /// + /// + /// // We can also consider instant estimates for a given time: + /// double p1 = cox.Regression.Compute(new double[] { 63 }, 2); + /// double p2 = cox.Regression.Compute(new double[] { 63 }, 10); + /// + /// // Here, p1 is the score after 2 time instants, with a + /// // value of 0.0656. The second value, p2, is the time + /// // after 10 time instants, with a value of 6.2907. + /// + /// + /// + [Serializable] + public class ProportionalHazardsAnalysis : IRegressionAnalysis + { + private ProportionalHazards regression; + + private int inputCount; + private double[] coefficients; + private double[] standardErrors; + private double[] hazardRatios; + + private WaldTest[] waldTests; + private ChiSquareTest[] ratioTests; + + private DoubleRange[] confidences; + + private double deviance; + private double logLikelihood; + private ChiSquareTest chiSquare; + + private double[][] inputData; + private double[] timeData; + private SurvivalOutcome[] censorData; + + private string[] inputNames; + private string timeName; + private string censorName; + + private double[,] source; + private double[] result; + + private HazardCoefficientCollection coefficientCollection; + + private int iterations = 50; + private double tolerance = 1e-5; + + private bool innerComputed = false; + + + //--------------------------------------------- + + + #region Constructors + + /// + /// Constructs a new Cox's Proportional Hazards Analysis. + /// + /// + /// The input data for the analysis. + /// The output data for the analysis. + /// The right-censoring indicative values. + /// + public ProportionalHazardsAnalysis(double[,] inputs, double[] times, SurvivalOutcome[] censor) + { + // Initial argument checking + if (inputs == null) + throw new ArgumentNullException("inputs"); + + if (times == null) + throw new ArgumentNullException("times"); + + if (inputs.GetLength(0) != times.Length) + throw new ArgumentException("The number of rows in the input array must match the number of given outputs."); + + initialize(inputs.ToArray(), times, censor); + + // Start regression using the Null Model + this.regression = new ProportionalHazards(inputCount); + } + + /// + /// Constructs a new Cox's Proportional Hazards Analysis. + /// + /// + /// The input data for the analysis. + /// The output data for the analysis. + /// The right-censoring indicative values. + /// + public ProportionalHazardsAnalysis(double[][] inputs, double[] times, SurvivalOutcome[] censor) + { + // Initial argument checking + if (inputs == null) + throw new ArgumentNullException("inputs"); + + if (times == null) + throw new ArgumentNullException("times"); + + if (inputs.Length != times.Length) + throw new ArgumentException("The number of rows in the input array must match the number of given outputs."); + + initialize(inputs, times, censor); + + // Start regression using the Null Model + this.regression = new ProportionalHazards(inputCount); + } + + /// + /// Constructs a new Cox's Proportional Hazards Analysis. + /// + /// + /// The input data for the analysis. + /// The output, binary data for the analysis. + /// The right-censoring indicative values. + /// The names of the input variables. + /// The name of the time variable. + /// The name of the event indication variable. + /// + public ProportionalHazardsAnalysis(double[][] inputs, double[] times, SurvivalOutcome[] censor, + String[] inputNames, String timeName, String censorName) + : this(inputs, times, censor) + { + this.inputNames = inputNames; + this.timeName = timeName; + this.censorName = censorName; + } + + private void initialize(double[][] inputs, double[] outputs, SurvivalOutcome[] censor) + { + this.inputCount = inputs[0].Length; + int coefficientCount = inputCount; + + // Store data sets + this.inputData = inputs; + this.timeData = outputs; + this.censorData = censor; + + + // Create additional structures + this.coefficients = new double[coefficientCount]; + this.waldTests = new WaldTest[coefficientCount]; + this.standardErrors = new double[coefficientCount]; + this.hazardRatios = new double[coefficientCount]; + this.confidences = new DoubleRange[coefficientCount]; + this.ratioTests = new ChiSquareTest[coefficientCount]; + + this.timeName = "Time"; + this.censorName = "Outcome"; + this.inputNames = new string[inputCount]; + for (int i = 0; i < inputNames.Length; i++) + inputNames[i] = "Input " + i; + + // Create object-oriented structure to represent the analysis + var logCoefs = new List(coefficientCount); + for (int i = 0; i < coefficientCount; i++) + logCoefs.Add(new HazardCoefficient(this, i)); + this.coefficientCollection = new HazardCoefficientCollection(logCoefs); + + this.source = inputs.ToMatrix(); + } + + #endregion + + + //--------------------------------------------- + + + #region Public Properties + + /// + /// Gets or sets the maximum number of iterations to be + /// performed by the regression algorithm. Default is 50. + /// + /// + public int Iterations + { + get { return iterations; } + set { iterations = value; } + } + + /// + /// Gets or sets the difference between two iterations of the regression + /// algorithm when the algorithm should stop. The difference is calculated + /// based on the largest absolute parameter change of the regression. Default + /// is 1e-5. + /// + /// + public double Tolerance + { + get { return tolerance; } + set { tolerance = value; } + } + + /// + /// Source data used in the analysis. + /// + /// + public double[,] Source + { + get { return source; } + } + + /// + /// Gets the time passed until the event + /// occurred or until the observation was + /// censored. + /// + /// + public double[] TimeToEvent + { + get { return timeData; } + } + + /// + /// Gets whether the event of + /// interest happened or not. + /// + /// + public SurvivalOutcome[] Events + { + get { return censorData; } + } + + /// + /// Gets the dependent variable value + /// for each of the source input points. + /// + /// + public double[] Outputs + { + get { return censorData.To(); } + } + + /// + /// Gets the resulting probabilities obtained + /// by the logistic regression model. + /// + /// + public double[] Result + { + get { return result; } + } + + + /// + /// Gets the Proportional Hazards model created + /// and evaluated by this analysis. + /// + /// + public ProportionalHazards Regression + { + get { return regression; } + } + + /// + /// Gets the collection of coefficients of the model. + /// + /// + public ReadOnlyCollection Coefficients + { + get { return coefficientCollection; } + } + + /// + /// Gets the Log-Likelihood for the model. + /// + /// + public double LogLikelihood + { + get { return this.logLikelihood; } + } + + /// + /// Gets the Chi-Square (Likelihood Ratio) Test for the model. + /// + /// + public ChiSquareTest ChiSquare + { + get { return this.chiSquare; } + } + + /// + /// Gets the Deviance of the model. + /// + /// + public double Deviance + { + get { return deviance; } + } + + /// + /// Gets the name of the input variables for the model. + /// + /// + public String[] InputNames + { + get { return inputNames; } + } + + /// + /// Gets the name of the output variable for the model. + /// + /// + public String TimeName + { + get { return timeName; } + } + + /// + /// Gets the name of event occurrence variable in the model. + /// + /// + public String EventName + { + get { return censorName; } + } + + /// + /// Gets the Hazard Ratio for each coefficient + /// found during the proportional hazards. + /// + /// + public double[] HazardRatios + { + get { return this.hazardRatios; } + } + + /// + /// Gets the Standard Error for each coefficient + /// found during the proportional hazards. + /// + /// + public double[] StandardErrors + { + get { return this.standardErrors; } + } + + /// + /// Gets the Wald Tests for each coefficient. + /// + /// + public WaldTest[] WaldTests + { + get { return this.waldTests; } + } + + /// + /// Gets the Likelihood-Ratio Tests for each coefficient. + /// + /// + public ChiSquareTest[] LikelihoodRatioTests + { + get + { + if (innerComputed == false) + computeInner(); + + return this.ratioTests; + } + } + + /// + /// Gets the value of each coefficient. + /// + /// + public double[] CoefficientValues + { + get { return this.coefficients; } + } + + /// + /// Gets the 95% Confidence Intervals (C.I.) + /// for each coefficient found in the regression. + /// + /// + public DoubleRange[] Confidences + { + get { return this.confidences; } + } + + #endregion + + + //--------------------------------------------- + + + #region Public Methods + + /// + /// Gets the Log-Likelihood Ratio between this model and another model. + /// + /// + /// Another proportional hazards model. + /// + /// The Likelihood-Ratio between the two models. + /// + public double GetLikelihoodRatio(ProportionalHazards model) + { + return regression.GetLogLikelihoodRatio(inputData, timeData, censorData, model); + } + + /// + /// Computes the Proportional Hazards Analysis for an already computed regression. + /// + /// + public void Compute(ProportionalHazards regression) + { + this.regression = regression; + + computeInformation(); + + innerComputed = false; + } + + /// + /// Computes the Proportional Hazards Analysis. + /// + /// + /// + /// True if the model converged, false otherwise. + /// + /// + public bool Compute() + { + return compute(); + } + + /// + /// Computes the Proportional Hazards Analysis. + /// + /// + /// + /// The difference between two iterations of the regression algorithm + /// when the algorithm should stop. If not specified, the value of + /// 1e-4 will be used. The difference is calculated based on the largest + /// absolute parameter change of the regression. + /// + /// + /// + /// The maximum number of iterations to be performed by the regression + /// algorithm. + /// + /// + /// + /// True if the model converged, false otherwise. + /// + /// + [Obsolete("Please set up the Iterations and Tolerance properties and call Compute() instead.")] + public bool Compute(double limit = 1e-4, int maxIterations = 50) + { + this.iterations = maxIterations; + this.tolerance = limit; + + return compute(); + } + + #endregion + + + + private bool compute() + { + var learning = new ProportionalHazardsNewtonRaphson(regression); + + Array.Clear(regression.Coefficients, 0, regression.Coefficients.Length); + + + learning.Iterations = Iterations; + learning.Tolerance = Tolerance; + + learning.Run(inputData, timeData, censorData); + + // Check if the full model has converged + bool converged = learning.CurrentIteration < Iterations; + + + computeInformation(); + + innerComputed = false; + + // Returns true if the full model has converged, false otherwise. + return converged; + } + + private void computeInner() + { + if (inputCount <= 2) + return; + + // Perform likelihood-ratio tests against diminished nested models + ProportionalHazards innerModel = new ProportionalHazards(inputCount - 1); + ProportionalHazardsNewtonRaphson learning = new ProportionalHazardsNewtonRaphson(innerModel); + + for (int i = 0; i < inputCount; i++) + { + // Create a diminished inner model without the current variable + double[][] data = inputData.RemoveColumn(i); + + System.Diagnostics.Trace.Assert(data[0].Length > 0); + + Array.Clear(innerModel.Coefficients, 0, inputCount - 1); + + learning.Iterations = Iterations; + learning.Tolerance = Tolerance; + + learning.Run(data, timeData, censorData); + + + double ratio = 2.0 * (logLikelihood - innerModel.GetPartialLogLikelihood(data, timeData, censorData)); + ratioTests[i] = new ChiSquareTest(ratio, 1); + } + + innerComputed = true; + } + + private void computeInformation() + { + // Store model information + this.result = regression.Compute(inputData, timeData); + this.deviance = regression.GetDeviance(inputData, timeData, censorData); + this.logLikelihood = regression.GetPartialLogLikelihood(inputData, timeData, censorData); + this.chiSquare = regression.ChiSquare(inputData, timeData, censorData); + + // Store coefficient information + for (int i = 0; i < regression.Coefficients.Length; i++) + { + this.standardErrors[i] = regression.StandardErrors[i]; + + this.waldTests[i] = regression.GetWaldTest(i); + this.coefficients[i] = regression.Coefficients[i]; + this.confidences[i] = regression.GetConfidenceInterval(i); + this.hazardRatios[i] = regression.GetHazardRatio(i); + } + } + + /// + /// Computes the analysis using given source data and parameters. + /// + /// + void IAnalysis.Compute() + { + Compute(); + } + + } + + + #region Support Classes + + /// + /// Represents a Proportional Hazards Coefficient found in the Cox's Hazards model, + /// allowing it to be bound to controls like the DataGridView. This class cannot + /// be instantiated outside the . + /// + /// + [Serializable] + public class HazardCoefficient + { + private ProportionalHazardsAnalysis analysis; + private int index; + + + internal HazardCoefficient(ProportionalHazardsAnalysis analysis, int index) + { + this.analysis = analysis; + this.index = index; + } + + /// + /// Gets the name for the current coefficient. + /// + /// + public string Name + { + get + { + if (analysis.InputNames.Length == 0) + return String.Empty; + + return analysis.InputNames[index]; + } + } + + /// + /// Gets the Odds ratio for the current coefficient. + /// + /// + [DisplayName("Hazard ratio")] + public double HazardRatio + { + get { return analysis.HazardRatios[index]; } + } + + /// + /// Gets the Standard Error for the current coefficient. + /// + /// + [DisplayName("Std. Error")] + public double StandardError + { + get { return analysis.StandardErrors[index]; } + } + + /// + /// Gets the 95% confidence interval (C.I.) for the current coefficient. + /// + /// + [Browsable(false)] + public DoubleRange Confidence + { + get { return analysis.Confidences[index]; } + } + + /// + /// Gets the upper limit for the 95% confidence interval. + /// + /// + [DisplayName("Upper confidence limit")] + public double ConfidenceUpper + { + get { return Confidence.Max; } + } + + /// + /// Gets the lower limit for the 95% confidence interval. + /// + /// + [DisplayName("Lower confidence limit")] + public double ConfidenceLower + { + get { return Confidence.Min; } + } + + /// + /// Gets the coefficient value. + /// + /// + [DisplayName("Value")] + public double Value + { + get { return analysis.CoefficientValues[index]; } + } + + /// + /// Gets the Wald's test performed for this coefficient. + /// + /// + [DisplayName("Wald p-value")] + public WaldTest Wald + { + get { return analysis.WaldTests[index]; } + } + + /// + /// Gets the Likelihood-Ratio test performed for this coefficient. + /// + /// + [DisplayName("Likelihood-Ratio p-value")] + public ChiSquareTest LikelihoodRatio + { + get { return analysis.LikelihoodRatioTests[index]; } + } + + + } + + /// + /// Represents a collection of Hazard Coefficients found in the + /// . This class cannot be instantiated. + /// + /// + [Serializable] + public class HazardCoefficientCollection : ReadOnlyCollection + { + internal HazardCoefficientCollection(IList coefficients) + : base(coefficients) { } + } + #endregion + +} diff --git a/Sources/Accord.Statistics/Circular.cs b/Sources/Accord.Statistics/Circular.cs index 3ae689ead..5436f6e25 100644 --- a/Sources/Accord.Statistics/Circular.cs +++ b/Sources/Accord.Statistics/Circular.cs @@ -59,6 +59,7 @@ namespace Accord.Statistics using Accord.Math; using Accord.Statistics.Distributions.Univariate; using AForge.Math; + using System.Numerics; /// /// Set of statistics functions operating over a circular space. diff --git a/Sources/Accord.Statistics/Distributions/Fitting/SurvivalOptions.cs b/Sources/Accord.Statistics/Distributions/Fitting/SurvivalOptions.cs index c7490a1b5..083f9d5a5 100644 --- a/Sources/Accord.Statistics/Distributions/Fitting/SurvivalOptions.cs +++ b/Sources/Accord.Statistics/Distributions/Fitting/SurvivalOptions.cs @@ -1,77 +1,143 @@ -// Accord Statistics Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Statistics.Distributions.Fitting -{ - using Accord.Statistics.Distributions.Univariate; - - /// - /// Options for Survival distributions. - /// - /// - public class SurvivalOptions : IFittingOptions - { - - /// - /// Gets or sets the values for - /// the right-censoring variable. - /// - /// - public int[] Censor { get; set; } - - /// - /// Initializes a new instance of the class. - /// - /// - public SurvivalOptions() - { - } - } - - /// - /// Options for Empirical Hazard distributions. - /// - /// - public class EmpiricalHazardOptions : SurvivalOptions - { - /// - /// Gets or sets the outputs of the hazards model. - /// - /// - public double[] Output { get; set; } - - /// - /// Gets or sets the estimator to be used. - /// - /// - public HazardEstimator Estimator { get; set; } - - /// - /// Initializes a new instance of the class. - /// - /// - public EmpiricalHazardOptions() - { - Estimator = HazardEstimator.BreslowNelsonAalen; - } - } -} +// Accord Statistics Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Statistics.Distributions.Fitting +{ + using Accord.Statistics.Distributions.Univariate; + using Accord.Math; + + /// + /// Options for Survival distributions. + /// + /// + public class SurvivalOptions : IFittingOptions + { + /// + /// Default survival estimation method. Returns . + /// + /// + public const SurvivalEstimator DefaultSurvival = SurvivalEstimator.FlemingHarrington; + + /// + /// Gets or sets the values for + /// the right-censoring variable. + /// + /// + public SurvivalOutcome[] Outcome { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// + public SurvivalOptions() + { + } + + } + + /// + /// Options for Empirical Hazard distributions. + /// + /// + public class EmpiricalHazardOptions : SurvivalOptions + { + /// + /// Default hazard estimator. Returns . + /// + /// + public const HazardEstimator DefaultEstimator = HazardEstimator.BreslowNelsonAalen; + + /// + /// Default tie handling method. Returns . + /// + /// + public const HazardTiesMethod DefaultTies = HazardTiesMethod.Efron; + + + /// + /// Gets or sets the estimator to be used. Default is . + /// + /// + public HazardEstimator Estimator { get; set; } + + /// + /// Gets or sets the tie handling method to be used. Default is . + /// + /// + public HazardTiesMethod Ties { get; set; } + + + /// + /// Initializes a new instance of the class. + /// + /// + public EmpiricalHazardOptions() + { + Estimator = DefaultEstimator; + Ties = DefaultTies; + } + + /// + /// Initializes a new instance of the class. + /// + /// + public EmpiricalHazardOptions(HazardEstimator estimator, SurvivalOutcome[] output) + { + Estimator = estimator; + Outcome = output; + Ties = DefaultTies; + } + + /// + /// Initializes a new instance of the class. + /// + /// + public EmpiricalHazardOptions(HazardEstimator estimator, int[] output) + { + Estimator = estimator; + Outcome = output.To(); + Ties = HazardTiesMethod.Breslow; + } + + /// + /// Initializes a new instance of the class. + /// + /// + public EmpiricalHazardOptions(HazardEstimator estimator, HazardTiesMethod ties, SurvivalOutcome[] outcome) + { + Estimator = estimator; + Outcome = outcome; + Ties = ties; + } + + /// + /// Initializes a new instance of the class. + /// + /// + public EmpiricalHazardOptions(HazardEstimator estimator, HazardTiesMethod ties, int[] output) + { + Estimator = estimator; + Outcome = output.To(); + Ties = ties; + } + } +} diff --git a/Sources/Accord.Statistics/Distributions/Multivariate/Continuous/MultivariateEmpiricalDistribution.cs b/Sources/Accord.Statistics/Distributions/Multivariate/Continuous/MultivariateEmpiricalDistribution.cs index 25abd4559..8c6ed7c0f 100644 --- a/Sources/Accord.Statistics/Distributions/Multivariate/Continuous/MultivariateEmpiricalDistribution.cs +++ b/Sources/Accord.Statistics/Distributions/Multivariate/Continuous/MultivariateEmpiricalDistribution.cs @@ -490,7 +490,7 @@ public override double[] Variance /// probability that a given value x will occur. /// /// - public override double ProbabilityDensityFunction(double[] x) + public override double ProbabilityDensityFunction(params double[] x) { // http://www.buch-kromann.dk/tine/nonpar/Nonparametric_Density_Estimation_multidim.pdf // http://sfb649.wiwi.hu-berlin.de/fedc_homepage/xplore/ebooks/html/spm/spmhtmlnode18.html diff --git a/Sources/Accord.Statistics/Distributions/Multivariate/Independent`1.cs b/Sources/Accord.Statistics/Distributions/Multivariate/Independent`1.cs index 3f81e37ea..9beece051 100644 --- a/Sources/Accord.Statistics/Distributions/Multivariate/Independent`1.cs +++ b/Sources/Accord.Statistics/Distributions/Multivariate/Independent`1.cs @@ -1,407 +1,433 @@ -// Accord Statistics Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Statistics.Distributions.Multivariate -{ - using System; - using Accord.Math; - using Accord.Statistics.Distributions.Fitting; - - /// - /// Joint distribution assuming independence between vector components. - /// - /// - /// The type of the underlying distributions. - /// - /// - /// - /// In probability and statistics, given at least two random variables X, - /// Y, ..., that are defined on a probability space, the joint probability - /// distribution for X, Y, ... is a probability distribution that - /// gives the probability that each of X, Y, ... falls in any particular range or - /// discrete set of values specified for that variable. In the case of only two - /// random variables, this is called a bivariate distribution, but the concept - /// generalizes to any number of random variables, giving a multivariate distribution. - /// - /// - /// - /// References: - /// - /// - /// Wikipedia, The Free Encyclopedia. Beta distribution. - /// Available from: http://en.wikipedia.org/wiki/Joint_probability_distribution - /// - /// - /// - /// - /// - /// The following example shows how to declare and initialize an Independent Joint - /// Gaussian Distribution using known means and variances for each component. - /// - /// - /// // Declare two normal distributions - /// NormalDistribution pa = new NormalDistribution(4.2, 1); // p(a) - /// NormalDistribution pb = new NormalDistribution(7.0, 2); // p(b) - /// - /// // Now, create a joint distribution combining these two: - /// var joint = new Independent<NormalDistribution>(pa, pb); - /// - /// // This distribution assumes the distributions of the two components are independent, - /// // i.e. if we have 2D input vectors on the form {a, b}, then p({a,b}) = p(a) * p(b). - /// - /// // Lets check a simple example. Consider a 2D input vector x = { 4.2, 7.0 } as - /// // - /// double[] x = new double[] { 4.2, 7.0 }; - /// - /// // Those two should be completely equivalent: - /// double p1 = joint.ProbabilityDensityFunction(x); - /// double p2 = pa.ProbabilityDensityFunction(x[0]) * pb.ProbabilityDensityFunction(x[1]); - /// - /// bool equal = p1 == p2; // at this point, equal should be true. - /// - /// - /// - /// The following example shows how to fit a distribution (estimate - /// its parameters) from a given dataset. - /// - /// - /// // Let's consider an input dataset of 2D vectors. We would - /// // like to estimate an Independent<NormalDistribution> - /// // which best models this data. - /// - /// double[][] data = - /// { - /// // x, y - /// new double[] { 1, 8 }, - /// new double[] { 2, 6 }, - /// new double[] { 5, 7 }, - /// new double[] { 3, 9 }, - /// }; - /// - /// // We start by declaring some initial guesses for the - /// // distributions of each random variable (x, and y): - /// // - /// var distX = new NormalDistribution(0, 1); - /// var distY = new NormalDistribution(0, 1); - /// - /// // Next, we declare our initial guess Independent distribution - /// var joint = new Independent<NormalDistribution>(distX, distY); - /// - /// // We can now fit the distribution to our data, - /// // producing an estimate of its parameters: - /// // - /// joint.Fit(data); - /// - /// // At this point, we have estimated our distribution. - /// - /// double[] mean = joint.Mean; // should be { 2.75, 7.50 } - /// double[] var = joint.Variance; // should be { 2.917, 1.667 } - /// - /// // | 2.917, 0.000 | - /// double[,] cov = joint.Covariance; // Cov = | | - /// // | 0.000, 1.667 | - /// - /// // The covariance matrix is diagonal, as it would be expected - /// // if is assumed there are no interactions between components. - /// - /// - /// - [Serializable] - public class Independent : MultivariateContinuousDistribution - where TDistribution : IUnivariateDistribution - { - - private TDistribution[] components; - - private double[] mean; - private double[] variance; - private double[,] covariance; - - /// - /// Initializes a new instance of the class. - /// - /// - /// The components. - /// - public Independent(params TDistribution[] components) - : base(components.Length) - { - this.components = components; - } - - /// - /// Gets the component distributions of the joint. - /// - /// - public TDistribution[] Components - { - get { return components; } - } - - /// - /// Gets the mean for this distribution. - /// - /// - /// A vector containing the mean values for the distribution. - /// - public override double[] Mean - { - get - { - if (mean == null) - { - mean = new double[components.Length]; - for (int i = 0; i < components.Length; i++) - mean[i] = components[i].Mean; - } - return mean; - } - } - - /// - /// Gets the variance for this distribution. - /// - /// - /// A vector containing the variance values for the distribution. - /// - public override double[] Variance - { - get - { - if (variance == null) - { - variance = new double[components.Length]; - for (int i = 0; i < components.Length; i++) - variance[i] = components[i].Variance; - } - return variance; - } - } - - /// - /// Gets the variance-covariance matrix for this distribution. - /// - /// - /// A matrix containing the covariance values for the distribution. - /// - /// - /// For an independent distribution, this matrix will always be diagonal. - /// - /// - public override double[,] Covariance - { - get - { - if (covariance == null) - covariance = Matrix.Diagonal(Variance); - return covariance; - } - } - - /// - /// Gets the probability density function (pdf) for - /// this distribution evaluated at point x. - /// - /// - /// A single point in the distribution range. For a - /// univariate distribution, this should be a single - /// double value. For a multivariate distribution, - /// this should be a double array. - /// - /// - /// The probability of x occurring - /// in the current distribution. - /// - /// - /// - /// The Probability Density Function (PDF) describes the - /// probability that a given value x will occur. - /// - /// - public override double DistributionFunction(params double[] x) - { - double p = 1; - for (int i = 0; i < components.Length; i++) - p *= components[i].DistributionFunction(x[i]); - - return p; - } - - /// - /// Gets the probability density function (pdf) for - /// this distribution evaluated at point x. - /// - /// - /// A single point in the distribution range. For a - /// univariate distribution, this should be a single - /// double value. For a multivariate distribution, - /// this should be a double array. - /// - /// - /// The probability of x occurring - /// in the current distribution. - /// - /// - /// - /// The Probability Density Function (PDF) describes the - /// probability that a given value x will occur. - /// - /// - public override double ProbabilityDensityFunction(params double[] x) - { - return Math.Exp(LogProbabilityDensityFunction(x)); - } - - /// - /// Gets the log-probability density function (pdf) - /// for this distribution evaluated at point x. - /// - /// - /// A single point in the distribution range. For a - /// univariate distribution, this should be a single - /// double value. For a multivariate distribution, - /// this should be a double array. - /// - /// - /// The logarithm of the probability of x - /// occurring in the current distribution. - /// - /// - public override double LogProbabilityDensityFunction(params double[] x) - { - double p = 0; - for (int i = 0; i < components.Length; i++) - p += components[i].LogProbabilityFunction(x[i]); - - return p; - } - - /// - /// Fits the underlying distribution to a given set of observations. - /// - /// - /// The array of observations to fit the model against. The array - /// elements can be either of type double (for univariate data) or - /// type double[] (for multivariate data). - /// The weight vector containing the weight for each of the samples. - /// Optional arguments which may be used during fitting, such - /// as regularization constants and additional parameters. - /// - /// - /// Although both double[] and double[][] arrays are supported, - /// providing a double[] for a multivariate distribution or a - /// double[][] for a univariate distribution may have a negative - /// impact in performance. - /// - /// - /// - /// For an example on how to fit an independent joint distribution, please - /// take a look at the examples section for . - /// - /// - public override void Fit(double[][] observations, double[] weights, IFittingOptions options) - { - IndependentOptions independentOptions = options as IndependentOptions; - if (options != null && independentOptions == null) - throw new ArgumentException("The specified options' type is invalid.", "options"); - - Fit(observations, weights, independentOptions); - } - - /// - /// Fits the underlying distribution to a given set of observations. - /// - /// - /// The array of observations to fit the model against. The array - /// elements can be either of type double (for univariate data) or - /// type double[] (for multivariate data). - /// The weight vector containing the weight for each of the samples. - /// Optional arguments which may be used during fitting, such - /// as regularization constants and additional parameters. - /// - /// - /// For an example on how to fit an independent joint distribution, please - /// take a look at the examples section for . - /// - /// - public void Fit(double[][] observations, double[] weights, IndependentOptions options) - { - observations = observations.Transpose(); - - if (options != null) - { - if (options.InnerOptions != null) - { - for (int i = 0; i < components.Length; i++) - components[i].Fit(observations[i], weights, options.InnerOptions[i]); - } - else - { - for (int i = 0; i < components.Length; i++) - components[i].Fit(observations[i], weights, options.InnerOption); - } - } - else - { - for (int i = 0; i < components.Length; i++) - components[i].Fit(observations[i], weights, null); - } - - mean = null; - variance = null; - covariance = null; - } - - /// - /// Creates a new object that is a copy of the current instance. - /// - /// - /// - /// A new object that is a copy of this instance. - /// - /// - public override object Clone() - { - TDistribution[] clone = new TDistribution[components.Length]; - for (int i = 0; i < clone.Length; i++) - clone[i] = (TDistribution)components[i].Clone(); - - return new Independent(clone); - } - - /// - /// Returns a that represents this instance. - /// - /// - /// The format. - /// The format provider. - /// - /// - /// A that represents this instance. - /// - /// - public override string ToString(string format, IFormatProvider formatProvider) - { - return String.Format(formatProvider, "Independent(X)"); - } - } -} +// Accord Statistics Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Statistics.Distributions.Multivariate +{ + using System; + using Accord.Math; + using Accord.Statistics.Distributions.Fitting; + using System.Text; + + /// + /// Joint distribution assuming independence between vector components. + /// + /// + /// The type of the underlying distributions. + /// + /// + /// + /// In probability and statistics, given at least two random variables X, + /// Y, ..., that are defined on a probability space, the joint probability + /// distribution for X, Y, ... is a probability distribution that + /// gives the probability that each of X, Y, ... falls in any particular range or + /// discrete set of values specified for that variable. In the case of only two + /// random variables, this is called a bivariate distribution, but the concept + /// generalizes to any number of random variables, giving a multivariate distribution. + /// + /// + /// + /// References: + /// + /// + /// Wikipedia, The Free Encyclopedia. Beta distribution. + /// Available from: http://en.wikipedia.org/wiki/Joint_probability_distribution + /// + /// + /// + /// + /// + /// The following example shows how to declare and initialize an Independent Joint + /// Gaussian Distribution using known means and variances for each component. + /// + /// + /// // Declare two normal distributions + /// NormalDistribution pa = new NormalDistribution(4.2, 1); // p(a) + /// NormalDistribution pb = new NormalDistribution(7.0, 2); // p(b) + /// + /// // Now, create a joint distribution combining these two: + /// var joint = new Independent<NormalDistribution>(pa, pb); + /// + /// // This distribution assumes the distributions of the two components are independent, + /// // i.e. if we have 2D input vectors on the form {a, b}, then p({a,b}) = p(a) * p(b). + /// + /// // Lets check a simple example. Consider a 2D input vector x = { 4.2, 7.0 } as + /// // + /// double[] x = new double[] { 4.2, 7.0 }; + /// + /// // Those two should be completely equivalent: + /// double p1 = joint.ProbabilityDensityFunction(x); + /// double p2 = pa.ProbabilityDensityFunction(x[0]) * pb.ProbabilityDensityFunction(x[1]); + /// + /// bool equal = p1 == p2; // at this point, equal should be true. + /// + /// + /// + /// The following example shows how to fit a distribution (estimate + /// its parameters) from a given dataset. + /// + /// + /// // Let's consider an input dataset of 2D vectors. We would + /// // like to estimate an Independent<NormalDistribution> + /// // which best models this data. + /// + /// double[][] data = + /// { + /// // x, y + /// new double[] { 1, 8 }, + /// new double[] { 2, 6 }, + /// new double[] { 5, 7 }, + /// new double[] { 3, 9 }, + /// }; + /// + /// // We start by declaring some initial guesses for the + /// // distributions of each random variable (x, and y): + /// // + /// var distX = new NormalDistribution(0, 1); + /// var distY = new NormalDistribution(0, 1); + /// + /// // Next, we declare our initial guess Independent distribution + /// var joint = new Independent<NormalDistribution>(distX, distY); + /// + /// // We can now fit the distribution to our data, + /// // producing an estimate of its parameters: + /// // + /// joint.Fit(data); + /// + /// // At this point, we have estimated our distribution. + /// + /// double[] mean = joint.Mean; // should be { 2.75, 7.50 } + /// double[] var = joint.Variance; // should be { 2.917, 1.667 } + /// + /// // | 2.917, 0.000 | + /// double[,] cov = joint.Covariance; // Cov = | | + /// // | 0.000, 1.667 | + /// + /// // The covariance matrix is diagonal, as it would be expected + /// // if is assumed there are no interactions between components. + /// + /// + /// + [Serializable] + public class Independent : MultivariateContinuousDistribution + where TDistribution : IUnivariateDistribution + { + + private TDistribution[] components; + + private double[] mean; + private double[] variance; + private double[,] covariance; + + /// + /// Initializes a new instance of the class. + /// + /// + /// The components. + /// + public Independent(params TDistribution[] components) + : base(components.Length) + { + this.components = components; + } + + /// + /// Gets the component distributions of the joint. + /// + /// + public TDistribution[] Components + { + get { return components; } + } + + /// + /// Gets the mean for this distribution. + /// + /// + /// A vector containing the mean values for the distribution. + /// + public override double[] Mean + { + get + { + if (mean == null) + { + mean = new double[components.Length]; + for (int i = 0; i < components.Length; i++) + mean[i] = components[i].Mean; + } + return mean; + } + } + + /// + /// Gets the variance for this distribution. + /// + /// + /// A vector containing the variance values for the distribution. + /// + public override double[] Variance + { + get + { + if (variance == null) + { + variance = new double[components.Length]; + for (int i = 0; i < components.Length; i++) + variance[i] = components[i].Variance; + } + return variance; + } + } + + /// + /// Gets the variance-covariance matrix for this distribution. + /// + /// + /// A matrix containing the covariance values for the distribution. + /// + /// + /// For an independent distribution, this matrix will always be diagonal. + /// + /// + public override double[,] Covariance + { + get + { + if (covariance == null) + covariance = Matrix.Diagonal(Variance); + return covariance; + } + } + + /// + /// Gets the probability density function (pdf) for + /// this distribution evaluated at point x. + /// + /// + /// A single point in the distribution range. For a + /// univariate distribution, this should be a single + /// double value. For a multivariate distribution, + /// this should be a double array. + /// + /// + /// The probability of x occurring + /// in the current distribution. + /// + /// + /// + /// The Probability Density Function (PDF) describes the + /// probability that a given value x will occur. + /// + /// + public override double DistributionFunction(params double[] x) + { + double p = 1; + for (int i = 0; i < components.Length; i++) + p *= components[i].DistributionFunction(x[i]); + + return p; + } + + /// + /// Gets the probability density function (pdf) for + /// this distribution evaluated at point x. + /// + /// + /// A single point in the distribution range. For a + /// univariate distribution, this should be a single + /// double value. For a multivariate distribution, + /// this should be a double array. + /// + /// + /// The probability of x occurring + /// in the current distribution. + /// + /// + /// + /// The Probability Density Function (PDF) describes the + /// probability that a given value x will occur. + /// + /// + public override double ProbabilityDensityFunction(params double[] x) + { + return Math.Exp(LogProbabilityDensityFunction(x)); + } + + /// + /// Gets the log-probability density function (pdf) + /// for this distribution evaluated at point x. + /// + /// + /// A single point in the distribution range. For a + /// univariate distribution, this should be a single + /// double value. For a multivariate distribution, + /// this should be a double array. + /// + /// + /// The logarithm of the probability of x + /// occurring in the current distribution. + /// + /// + public override double LogProbabilityDensityFunction(params double[] x) + { + double p = 0; + for (int i = 0; i < components.Length; i++) + p += components[i].LogProbabilityFunction(x[i]); + + return p; + } + + /// + /// Fits the underlying distribution to a given set of observations. + /// + /// + /// The array of observations to fit the model against. The array + /// elements can be either of type double (for univariate data) or + /// type double[] (for multivariate data). + /// The weight vector containing the weight for each of the samples. + /// Optional arguments which may be used during fitting, such + /// as regularization constants and additional parameters. + /// + /// + /// Although both double[] and double[][] arrays are supported, + /// providing a double[] for a multivariate distribution or a + /// double[][] for a univariate distribution may have a negative + /// impact in performance. + /// + /// + /// + /// For an example on how to fit an independent joint distribution, please + /// take a look at the examples section for . + /// + /// + public override void Fit(double[][] observations, double[] weights, IFittingOptions options) + { + IndependentOptions independentOptions = options as IndependentOptions; + if (options != null && independentOptions == null) + throw new ArgumentException("The specified options' type is invalid.", "options"); + + Fit(observations, weights, independentOptions); + } + + /// + /// Fits the underlying distribution to a given set of observations. + /// + /// + /// The array of observations to fit the model against. The array + /// elements can be either of type double (for univariate data) or + /// type double[] (for multivariate data). + /// The weight vector containing the weight for each of the samples. + /// Optional arguments which may be used during fitting, such + /// as regularization constants and additional parameters. + /// + /// + /// For an example on how to fit an independent joint distribution, please + /// take a look at the examples section for . + /// + /// + public void Fit(double[][] observations, double[] weights, IndependentOptions options) + { + observations = observations.Transpose(); + + if (options != null) + { + if (options.InnerOptions != null) + { + for (int i = 0; i < components.Length; i++) + components[i].Fit(observations[i], weights, options.InnerOptions[i]); + } + else + { + for (int i = 0; i < components.Length; i++) + components[i].Fit(observations[i], weights, options.InnerOption); + } + } + else + { + for (int i = 0; i < components.Length; i++) + components[i].Fit(observations[i], weights, null); + } + + mean = null; + variance = null; + covariance = null; + } + + /// + /// Creates a new object that is a copy of the current instance. + /// + /// + /// + /// A new object that is a copy of this instance. + /// + /// + public override object Clone() + { + TDistribution[] clone = new TDistribution[components.Length]; + for (int i = 0; i < clone.Length; i++) + clone[i] = (TDistribution)components[i].Clone(); + + return new Independent(clone); + } + + /// + /// Returns a that represents this instance. + /// + /// + /// + /// A that represents this instance. + /// + /// + public override string ToString(string format, IFormatProvider formatProvider) + { + StringBuilder sb = new StringBuilder(); + sb.Append("Independent("); + for (int i = 0; i < components.Length; i++) + { + sb.Append("x" + i); + + if (i < components.Length - 1) + sb.Append(", "); + } + + sb.Append("; "); + + for (int i = 0; i < components.Length; i++) + { + var fmt = components[i] as IFormattable; + + String componentText = fmt + .ToString(format, formatProvider) + .Replace("(x", "(x" + i); + + sb.AppendFormat(componentText); + + if (i < components.Length - 1) + sb.Append(" + "); + } + sb.Append(")"); + + return sb.ToString(); + } + + } +} diff --git a/Sources/Accord.Statistics/Distributions/Multivariate/MultivariateMixture`1.cs b/Sources/Accord.Statistics/Distributions/Multivariate/MultivariateMixture`1.cs index c379aa13d..fd2fe2a6b 100644 --- a/Sources/Accord.Statistics/Distributions/Multivariate/MultivariateMixture`1.cs +++ b/Sources/Accord.Statistics/Distributions/Multivariate/MultivariateMixture`1.cs @@ -647,10 +647,9 @@ public override string ToString(string format, IFormatProvider formatProvider) for (int i = 0; i < coefficients.Length; i++) { - sb.AppendFormat("{0}*", - coefficients[0].ToString(format, formatProvider)); + sb.AppendFormat("{0}*", coefficients[i].ToString(format, formatProvider)); - var fmt = components[1] as IFormattable; + var fmt = components[i] as IFormattable; if (fmt != null) sb.AppendFormat(fmt.ToString(format, formatProvider)); diff --git a/Sources/Accord.Statistics/Distributions/Univariate/Base/IUnivariateDistribution.cs b/Sources/Accord.Statistics/Distributions/Univariate/Base/IUnivariateDistribution.cs index 44ec8516c..8f9f56b7f 100644 --- a/Sources/Accord.Statistics/Distributions/Univariate/Base/IUnivariateDistribution.cs +++ b/Sources/Accord.Statistics/Distributions/Univariate/Base/IUnivariateDistribution.cs @@ -1,139 +1,139 @@ -// Accord Statistics Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Statistics.Distributions -{ - using System; - using Accord.Statistics.Distributions.Fitting; - using Accord.Statistics.Distributions.Univariate; - using AForge; - - /// - /// Common interface for univariate probability distributions. - /// - /// - /// - /// - /// This interface is implemented by both univariate - /// Discrete Distributions and Continuous - /// Distributions. - /// - /// - /// For Multivariate distributions, see . - /// - /// - /// - /// - /// - /// - /// - public interface IUnivariateDistribution : IDistribution - { - - /// - /// Gets the mean value for the distribution. - /// - /// - /// The distribution's mean. - /// - double Mean { get; } - - /// - /// Gets the variance value for the distribution. - /// - /// - /// The distribution's variance. - /// - double Variance { get; } - - /// - /// Gets the median value for the distribution. - /// - /// - /// The distribution's median. - /// - double Median { get; } - - /// - /// Gets the mode value for the distribution. - /// - /// - /// The distribution's mode. - /// - double Mode { get; } - - /// - /// Gets entropy of the distribution. - /// - /// - /// The distribution's entropy. - /// - double Entropy { get; } - - /// - /// Gets the support interval for this distribution. - /// - /// - /// A containing - /// the support interval for this distribution. - /// - DoubleRange Support { get; } - - /// - /// Gets the Quartiles for this distribution. - /// - /// - /// A object containing the first quartile - /// (Q1) as its minimum value, and the third quartile (Q2) as the maximum. - /// - DoubleRange Quartiles { get; } - - /// - /// Gets the distribution range within a given percentile. - /// - /// - /// - /// If 0.25 is passed as the argument, - /// this function returns the same as the function. - /// - /// - /// - /// The percentile at which the distribution ranges will be returned. - /// - /// A object containing the minimum value - /// for the distribution value, and the third quartile (Q2) as the maximum. - /// - DoubleRange GetRange(double percentile); - - /// - /// Gets the cumulative distribution function (cdf) for - /// this distribution evaluated at point x. - /// - /// - /// - /// The Cumulative Distribution Function (CDF) describes the cumulative - /// probability that a given value or any value smaller than it will occur. - /// - /// +// Accord Statistics Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Statistics.Distributions +{ + using System; + using Accord.Statistics.Distributions.Fitting; + using Accord.Statistics.Distributions.Univariate; + using AForge; + + /// + /// Common interface for univariate probability distributions. + /// + /// + /// + /// + /// This interface is implemented by both univariate + /// Discrete Distributions and Continuous + /// Distributions. + /// + /// + /// For Multivariate distributions, see . + /// + /// + /// + /// + /// + /// + /// + public interface IUnivariateDistribution : IDistribution + { + + /// + /// Gets the mean value for the distribution. + /// + /// + /// The distribution's mean. + /// + double Mean { get; } + + /// + /// Gets the variance value for the distribution. + /// + /// + /// The distribution's variance. + /// + double Variance { get; } + + /// + /// Gets the median value for the distribution. + /// + /// + /// The distribution's median. + /// + double Median { get; } + + /// + /// Gets the mode value for the distribution. + /// + /// + /// The distribution's mode. + /// + double Mode { get; } + + /// + /// Gets entropy of the distribution. + /// + /// + /// The distribution's entropy. + /// + double Entropy { get; } + + /// + /// Gets the support interval for this distribution. + /// + /// + /// A containing + /// the support interval for this distribution. + /// + DoubleRange Support { get; } + + /// + /// Gets the Quartiles for this distribution. + /// + /// + /// A object containing the first quartile + /// (Q1) as its minimum value, and the third quartile (Q2) as the maximum. + /// + DoubleRange Quartiles { get; } + + /// + /// Gets the distribution range within a given percentile. + /// + /// + /// + /// If 0.25 is passed as the argument, + /// this function returns the same as the function. + /// + /// + /// + /// The percentile at which the distribution ranges will be returned. + /// + /// A object containing the minimum value + /// for the distribution value, and the third quartile (Q2) as the maximum. + /// + DoubleRange GetRange(double percentile); + + /// + /// Gets the cumulative distribution function (cdf) for + /// this distribution evaluated at point x. + /// + /// + /// + /// The Cumulative Distribution Function (CDF) describes the cumulative + /// probability that a given value or any value smaller than it will occur. + /// + /// double DistributionFunction(double x); /// @@ -150,253 +150,253 @@ public interface IUnivariateDistribution : IDistribution /// probability that a given value or any value smaller than it will occur. /// /// - double DistributionFunction(double a, double b); - - /// - /// Gets the probability density function (pdf) for - /// this distribution evaluated at point x. - /// - /// - /// - /// A single point in the distribution range. For a - /// univariate distribution, this should be a single - /// double value. For a multivariate distribution, - /// this should be a double array. - /// - /// - /// The Probability Density Function (PDF) describes the - /// probability that a given value x will occur. - /// - /// - /// - /// The probability of x occurring - /// in the current distribution. - /// - double ProbabilityFunction(double x); - - /// - /// Gets the log-probability density function (pdf) - /// for this distribution evaluated at point x. - /// - /// - /// - /// A single point in the distribution range. For a - /// univariate distribution, this should be a single - /// double value. For a multivariate distribution, - /// this should be a double array. - /// - /// The logarithm of the probability of x - /// occurring in the current distribution. - /// - double LogProbabilityFunction(double x); - - /// - /// Gets the inverse of the cumulative distribution function (icdf) for - /// this distribution evaluated at probability p. This function - /// is also known as the Quantile function. - /// - /// - /// - /// The Inverse Cumulative Distribution Function (ICDF) specifies, for - /// a given probability, the value which the random variable will be at, - /// or below, with that probability. - /// - /// - /// A probability value between 0 and 1. - /// - /// A sample which could original the given probability - /// value when applied in the . - /// - double InverseDistributionFunction(double p); - - /// - /// Gets the complementary cumulative distribution function - /// (ccdf) for this distribution evaluated at point x. - /// This function is also known as the Survival function. - /// - /// - /// - /// A single point in the distribution range. - /// - /// - /// The Complementary Cumulative Distribution Function (CCDF) is - /// the complement of the Cumulative Distribution Function, or 1 - /// minus the CDF. - /// - /// - double ComplementaryDistributionFunction(double x); - - /// - /// Gets the hazard function, also known as the failure rate or - /// the conditional failure density function for this distribution - /// evaluated at point x. - /// - /// - /// - /// The hazard function is the ratio of the probability - /// density function f(x) to the survival function, S(x). - /// - /// - /// - /// A single point in the distribution range. - /// - /// - /// The conditional failure density function h(x) - /// evaluated at x in the current distribution. - /// - double HazardFunction(double x); - - /// - /// Gets the cumulative hazard function for this - /// distribution evaluated at point x. - /// - /// - /// - /// A single point in the distribution range. - /// - /// - /// The cumulative hazard function H(x) - /// evaluated at x in the current distribution. - /// - double CumulativeHazardFunction(double x); - - /// - /// Gets the first derivative of the - /// inverse distribution function (icdf) for this distribution evaluated - /// at probability p. - /// - /// - /// A probability value between 0 and 1. - /// - double QuantileDensityFunction(double p); - } - - /// - /// Common interface for univariate probability distributions. - /// - /// - /// - /// - /// This interface is implemented by both univariate - /// Discrete Distributions and Continuous - /// Distributions. However, unlike , this interface - /// has a generic parameter that allows to define the type of the distribution values (i.e. - /// ). - /// - /// - /// For Multivariate distributions, see . - /// - /// - /// - /// - /// - /// - /// - public interface IUnivariateDistribution - : IDistribution, IDistribution - { - - /// - /// Gets the mean value for the distribution. - /// - /// - /// The distribution's mean. - /// - double Mean { get; } - - /// - /// Gets the variance value for the distribution. - /// - /// - /// The distribution's variance. - /// - double Variance { get; } - - /// - /// Gets the median value for the distribution. - /// - /// - /// The distribution's median. - /// - double Median { get; } - - /// - /// Gets the mode value for the distribution. - /// - /// - /// The distribution's mode. - /// - double Mode { get; } - - /// - /// Gets entropy of the distribution. - /// - /// - /// The distribution's entropy. - /// - double Entropy { get; } - - /// - /// Gets the support interval for this distribution. - /// - /// - /// A containing - /// the support interval for this distribution. - /// - DoubleRange Support { get; } - - /// - /// Gets the inverse of the cumulative distribution function (icdf) for - /// this distribution evaluated at probability p. This function - /// is also known as the Quantile function. - /// - /// - /// - /// The Inverse Cumulative Distribution Function (ICDF) specifies, for - /// a given probability, the value which the random variable will be at, - /// or below, with that probability. - /// - /// - /// A probability value between 0 and 1. - /// - /// A sample which could original the given probability - /// value when applied in the . - /// - TObservation InverseDistributionFunction(double p); - - /// - /// Gets the hazard function, also known as the failure rate or - /// the conditional failure density function for this distribution - /// evaluated at point x. - /// - /// - /// - /// The hazard function is the ratio of the probability - /// density function f(x) to the survival function, S(x). - /// - /// - /// - /// A single point in the distribution range. - /// - /// - /// The conditional failure density function h(x) - /// evaluated at x in the current distribution. - /// - double HazardFunction(TObservation x); - - /// - /// Gets the cumulative hazard function for this - /// distribution evaluated at point x. - /// - /// - /// - /// A single point in the distribution range. - /// - /// - /// The cumulative hazard function H(x) - /// evaluated at x in the current distribution. - /// - double CumulativeHazardFunction(TObservation x); - - } -} + double DistributionFunction(double a, double b); + + /// + /// Gets the probability density function (pdf) for + /// this distribution evaluated at point x. + /// + /// + /// + /// A single point in the distribution range. For a + /// univariate distribution, this should be a single + /// double value. For a multivariate distribution, + /// this should be a double array. + /// + /// + /// The Probability Density Function (PDF) describes the + /// probability that a given value x will occur. + /// + /// + /// + /// The probability of x occurring + /// in the current distribution. + /// + double ProbabilityFunction(double x); + + /// + /// Gets the log-probability density function (pdf) + /// for this distribution evaluated at point x. + /// + /// + /// + /// A single point in the distribution range. For a + /// univariate distribution, this should be a single + /// double value. For a multivariate distribution, + /// this should be a double array. + /// + /// The logarithm of the probability of x + /// occurring in the current distribution. + /// + double LogProbabilityFunction(double x); + + /// + /// Gets the inverse of the cumulative distribution function (icdf) for + /// this distribution evaluated at probability p. This function + /// is also known as the Quantile function. + /// + /// + /// + /// The Inverse Cumulative Distribution Function (ICDF) specifies, for + /// a given probability, the value which the random variable will be at, + /// or below, with that probability. + /// + /// + /// A probability value between 0 and 1. + /// + /// A sample which could original the given probability + /// value when applied in the . + /// + double InverseDistributionFunction(double p); + + /// + /// Gets the complementary cumulative distribution function + /// (ccdf) for this distribution evaluated at point x. + /// This function is also known as the Survival function. + /// + /// + /// + /// A single point in the distribution range. + /// + /// + /// The Complementary Cumulative Distribution Function (CCDF) is + /// the complement of the Cumulative Distribution Function, or 1 + /// minus the CDF. + /// + /// + double ComplementaryDistributionFunction(double x); + + /// + /// Gets the hazard function, also known as the failure rate or + /// the conditional failure density function for this distribution + /// evaluated at point x. + /// + /// + /// + /// The hazard function is the ratio of the probability + /// density function f(x) to the survival function, S(x). + /// + /// + /// + /// A single point in the distribution range. + /// + /// + /// The conditional failure density function h(x) + /// evaluated at x in the current distribution. + /// + double HazardFunction(double x); + + /// + /// Gets the cumulative hazard function for this + /// distribution evaluated at point x. + /// + /// + /// + /// A single point in the distribution range. + /// + /// + /// The cumulative hazard function H(x) + /// evaluated at x in the current distribution. + /// + double CumulativeHazardFunction(double x); + + /// + /// Gets the first derivative of the + /// inverse distribution function (icdf) for this distribution evaluated + /// at probability p. + /// + /// + /// A probability value between 0 and 1. + /// + double QuantileDensityFunction(double p); + } + + /// + /// Common interface for univariate probability distributions. + /// + /// + /// + /// + /// This interface is implemented by both univariate + /// Discrete Distributions and Continuous + /// Distributions. However, unlike , this interface + /// has a generic parameter that allows to define the type of the distribution values (i.e. + /// ). + /// + /// + /// For Multivariate distributions, see . + /// + /// + /// + /// + /// + /// + /// + public interface IUnivariateDistribution + : IDistribution, IDistribution + { + + /// + /// Gets the mean value for the distribution. + /// + /// + /// The distribution's mean. + /// + double Mean { get; } + + /// + /// Gets the variance value for the distribution. + /// + /// + /// The distribution's variance. + /// + double Variance { get; } + + /// + /// Gets the median value for the distribution. + /// + /// + /// The distribution's median. + /// + double Median { get; } + + /// + /// Gets the mode value for the distribution. + /// + /// + /// The distribution's mode. + /// + double Mode { get; } + + /// + /// Gets entropy of the distribution. + /// + /// + /// The distribution's entropy. + /// + double Entropy { get; } + + /// + /// Gets the support interval for this distribution. + /// + /// + /// A containing + /// the support interval for this distribution. + /// + DoubleRange Support { get; } + + /// + /// Gets the inverse of the cumulative distribution function (icdf) for + /// this distribution evaluated at probability p. This function + /// is also known as the Quantile function. + /// + /// + /// + /// The Inverse Cumulative Distribution Function (ICDF) specifies, for + /// a given probability, the value which the random variable will be at, + /// or below, with that probability. + /// + /// + /// A probability value between 0 and 1. + /// + /// A sample which could original the given probability + /// value when applied in the . + /// + TObservation InverseDistributionFunction(double p); + + /// + /// Gets the hazard function, also known as the failure rate or + /// the conditional failure density function for this distribution + /// evaluated at point x. + /// + /// + /// + /// The hazard function is the ratio of the probability + /// density function f(x) to the survival function, S(x). + /// + /// + /// + /// A single point in the distribution range. + /// + /// + /// The conditional failure density function h(x) + /// evaluated at x in the current distribution. + /// + double HazardFunction(TObservation x); + + /// + /// Gets the cumulative hazard function for this + /// distribution evaluated at point x. + /// + /// + /// + /// A single point in the distribution range. + /// + /// + /// The cumulative hazard function H(x) + /// evaluated at x in the current distribution. + /// + double CumulativeHazardFunction(TObservation x); + + } +} diff --git a/Sources/Accord.Statistics/Distributions/Univariate/Base/UnivariateContinuousDistribution.cs b/Sources/Accord.Statistics/Distributions/Univariate/Base/UnivariateContinuousDistribution.cs index 98a63b2df..17b79a37e 100644 --- a/Sources/Accord.Statistics/Distributions/Univariate/Base/UnivariateContinuousDistribution.cs +++ b/Sources/Accord.Statistics/Distributions/Univariate/Base/UnivariateContinuousDistribution.cs @@ -819,7 +819,12 @@ public virtual double LogProbabilityDensityFunction(double x) /// public virtual double HazardFunction(double x) { - return ProbabilityDensityFunction(x) / ComplementaryDistributionFunction(x); + double f = ProbabilityDensityFunction(x); + if (f == 0) + return 0; + + double s = ComplementaryDistributionFunction(x); + return f / s; } /// diff --git a/Sources/Accord.Statistics/Distributions/Univariate/Continuous/BetaDistribution.cs b/Sources/Accord.Statistics/Distributions/Univariate/Continuous/BetaDistribution.cs index 13a139182..652496bda 100644 --- a/Sources/Accord.Statistics/Distributions/Univariate/Continuous/BetaDistribution.cs +++ b/Sources/Accord.Statistics/Distributions/Univariate/Continuous/BetaDistribution.cs @@ -861,10 +861,46 @@ public static double[] Random(double alpha, double beta, int samples) /// public static double Random(double alpha, double beta) { - double x = GammaDistribution.Random(alpha, 1); - double y = GammaDistribution.Random(beta, 1); + double r; - return x / (x + y); + if (alpha < 1) + { + double d = alpha + 1.0 - 1.0 / 3.0; + double c = 1.0 / Math.Sqrt(9 * d); + + double U = Accord.Math.Tools.Random.Next(); + r = Gamma.Random(d, c) * Math.Pow(U, 1.0 / alpha); + } + else + { + double d = alpha - 1.0 / 3.0; + double c = 1.0 / Math.Sqrt(9 * d); + + r = Gamma.Random(d, c); + } + + if (beta < 1) + { + double d = beta + 1.0 - 1.0 / 3.0; + double c = 1.0 / Math.Sqrt(9 * d); + + double U = Accord.Math.Tools.Random.Next(); + + double x = r; + double y = Gamma.Random(d, c) * Math.Pow(U, 1.0 / beta); + r = x / (x + y); + } + else + { + double d = beta - 1.0 / 3.0; + double c = 1.0 / Math.Sqrt(9 * d); + + double x = r; + double y = Gamma.Random(d, c); + r = x / (x + y); + } + + return r; } #endregion diff --git a/Sources/Accord.Statistics/Distributions/Univariate/Continuous/BetaPrimeDistribution.cs b/Sources/Accord.Statistics/Distributions/Univariate/Continuous/BetaPrimeDistribution.cs index 41381a413..3fef03741 100644 --- a/Sources/Accord.Statistics/Distributions/Univariate/Continuous/BetaPrimeDistribution.cs +++ b/Sources/Accord.Statistics/Distributions/Univariate/Continuous/BetaPrimeDistribution.cs @@ -1,125 +1,125 @@ -// Accord Statistics Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © Ashley Messer, 2014 -// glyphard 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.Statistics.Distributions.Univariate.Continuous -{ - using System; - using Accord.Math; - using AForge; - - /// - /// Beta prime distribution. - /// - /// - /// - /// - /// In probability theory and statistics, the beta prime distribution (also known as inverted - /// beta distribution or beta distribution of the second kind) is an absolutely continuous - /// probability distribution defined for x > 0 with two parameters α and β, having the - /// probability density function: - /// - /// - /// x^(α-1) (1+x)^(-α-β) - /// f(x) = -------------------- - /// B(α,β) - /// - /// - /// - /// where B is the Beta function. While the related beta distribution is - /// the conjugate prior distribution of the parameter of a Bernoulli - /// distribution expressed as a probability, the beta prime distribution is the conjugate prior - /// distribution of the parameter of a Bernoulli distribution expressed in odds. The distribution is - /// a Pearson type VI distribution. - /// - /// - /// References: - /// - /// - /// Wikipedia, The Free Encyclopedia. Beta Prime distribution. Available on: - /// http://en.wikipedia.org/wiki/Beta_prime_distribution - /// - /// - /// - /// - /// - /// The following example shows how to create and test the main characteristics - /// of an Beta prime distribution given its two non-negative shape parameters: - /// - /// - /// // Create a new Beta-Prime distribution with shape (4,2) - /// var betaPrime = new BetaPrimeDistribution(alpha: 4, beta: 2); - /// - /// double mean = betaPrime.Mean; // 4.0 - /// double median = betaPrime.Median; // 2.1866398762435981 - /// double mode = betaPrime.Mode; // 1.0 - /// double var = betaPrime.Variance; // +inf - /// - /// double cdf = betaPrime.DistributionFunction(x: 0.4); // 0.02570357589099781 - /// double pdf = betaPrime.ProbabilityDensityFunction(x: 0.4); // 0.16999719504628183 - /// double lpdf = betaPrime.LogProbabilityDensityFunction(x: 0.4); // -1.7719733417957513 - /// - /// double ccdf = betaPrime.ComplementaryDistributionFunction(x: 0.4); // 0.97429642410900219 - /// double icdf = betaPrime.InverseDistributionFunction(p: cdf); // 0.39999982363709291 - /// - /// double hf = betaPrime.HazardFunction(x: 0.4); // 0.17448200654307533 - /// double chf = betaPrime.CumulativeHazardFunction(x: 0.4); // 0.026039684773113869 - /// - /// string str = betaPrime.ToString(CultureInfo.InvariantCulture); // BetaPrime(x; α = 4, β = 2) - /// - /// - /// - [Serializable] - public class BetaPrimeDistribution : UnivariateContinuousDistribution - { - - // Distribution parameters - double alpha; // shape (α) - double beta; // shape (β) - - /// - /// Constructs a new Beta-Prime distribution with the given - /// two non-negative shape parameters a and b. - /// - /// - /// The distribution's non-negative shape parameter a. - /// The distribution's non-negative shape parameter b. - /// - public BetaPrimeDistribution([Positive] double alpha, [Positive] double beta) - { - if (alpha <= 0) - throw new ArgumentOutOfRangeException("alpha", "The shape parameter alpha must be positive."); - - if (beta < 0) - throw new ArgumentOutOfRangeException("beta", "The shape parameter beta must be positive."); - - - this.alpha = alpha; - this.beta = beta; - } - +// Accord Statistics Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © Ashley Messer, 2014 +// glyphard 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.Statistics.Distributions.Univariate +{ + using System; + using Accord.Math; + using AForge; + + /// + /// Beta prime distribution. + /// + /// + /// + /// + /// In probability theory and statistics, the beta prime distribution (also known as inverted + /// beta distribution or beta distribution of the second kind) is an absolutely continuous + /// probability distribution defined for x > 0 with two parameters α and β, having the + /// probability density function: + /// + /// + /// x^(α-1) (1+x)^(-α-β) + /// f(x) = -------------------- + /// B(α,β) + /// + /// + /// + /// where B is the Beta function. While the related beta distribution is + /// the conjugate prior distribution of the parameter of a Bernoulli + /// distribution expressed as a probability, the beta prime distribution is the conjugate prior + /// distribution of the parameter of a Bernoulli distribution expressed in odds. The distribution is + /// a Pearson type VI distribution. + /// + /// + /// References: + /// + /// + /// Wikipedia, The Free Encyclopedia. Beta Prime distribution. Available on: + /// http://en.wikipedia.org/wiki/Beta_prime_distribution + /// + /// + /// + /// + /// + /// The following example shows how to create and test the main characteristics + /// of an Beta prime distribution given its two non-negative shape parameters: + /// + /// + /// // Create a new Beta-Prime distribution with shape (4,2) + /// var betaPrime = new BetaPrimeDistribution(alpha: 4, beta: 2); + /// + /// double mean = betaPrime.Mean; // 4.0 + /// double median = betaPrime.Median; // 2.1866398762435981 + /// double mode = betaPrime.Mode; // 1.0 + /// double var = betaPrime.Variance; // +inf + /// + /// double cdf = betaPrime.DistributionFunction(x: 0.4); // 0.02570357589099781 + /// double pdf = betaPrime.ProbabilityDensityFunction(x: 0.4); // 0.16999719504628183 + /// double lpdf = betaPrime.LogProbabilityDensityFunction(x: 0.4); // -1.7719733417957513 + /// + /// double ccdf = betaPrime.ComplementaryDistributionFunction(x: 0.4); // 0.97429642410900219 + /// double icdf = betaPrime.InverseDistributionFunction(p: cdf); // 0.39999982363709291 + /// + /// double hf = betaPrime.HazardFunction(x: 0.4); // 0.17448200654307533 + /// double chf = betaPrime.CumulativeHazardFunction(x: 0.4); // 0.026039684773113869 + /// + /// string str = betaPrime.ToString(CultureInfo.InvariantCulture); // BetaPrime(x; α = 4, β = 2) + /// + /// + /// + [Serializable] + public class BetaPrimeDistribution : UnivariateContinuousDistribution + { + + // Distribution parameters + double alpha; // shape (α) + double beta; // shape (β) + + /// + /// Constructs a new Beta-Prime distribution with the given + /// two non-negative shape parameters a and b. + /// + /// + /// The distribution's non-negative shape parameter a. + /// The distribution's non-negative shape parameter b. + /// + public BetaPrimeDistribution([Positive] double alpha, [Positive] double beta) + { + if (alpha <= 0) + throw new ArgumentOutOfRangeException("alpha", "The shape parameter alpha must be positive."); + + if (beta < 0) + throw new ArgumentOutOfRangeException("beta", "The shape parameter beta must be positive."); + + + this.alpha = alpha; + this.beta = beta; + } + /// /// Gets the distribution's non-negative shape parameter a. - /// - /// + /// + /// public double Alpha { get { return alpha; } @@ -128,203 +128,203 @@ public double Alpha /// /// Gets the distribution's non-negative shape parameter b. /// - /// + /// public double Beta { get { return beta; } - } - - /// - /// Gets the mean for this distribution. - /// - /// - /// - /// The distribution's mean value. - /// - /// - public override double Mean - { - get - { - if (beta > 1) - return alpha / (beta - 1); - - return Double.PositiveInfinity; - } - } - - /// - /// Gets the mode for this distribution. - /// - /// - /// - /// The distribution's mode value. - /// - /// - public override double Mode - { - get - { - if (alpha >= 1) - return (alpha - 1) / (beta + 1); - - return 0.0; - } - } - - /// - /// Gets the variance for this distribution. - /// - /// - /// - /// The distribution's variance. - /// - /// - public override double Variance - { - get - { - if (beta > 2.0) - { - double num = alpha * (alpha + beta - 1); - double den = (beta - 2) * Math.Pow(beta - 1, 2); - return num / den; - } - else if (beta > 1.0) - { - return Double.PositiveInfinity; - } - - return double.NaN; - } - } - - /// - /// Not supported. - /// - /// - public override double Entropy - { - get { return double.NaN; } - } - - /// - /// Gets the support interval for this distribution, which - /// for the Beta- Prime distribution ranges from 0 to all - /// positive numbers. - /// - /// - /// - /// A containing - /// the support interval for this distribution. - /// - /// - public override DoubleRange Support - { - get { return new DoubleRange(0, Double.MaxValue); } - } - - /// - /// Gets the cumulative distribution function (cdf) for - /// this distribution evaluated at point x. - /// - /// - /// A single point in the distribution range. - /// - /// - /// The Cumulative Distribution Function (CDF) describes the cumulative - /// probability that a given value or any value smaller than it will occur. - /// - /// - public override double DistributionFunction([Positive] double x) - { - if (x <= 0) + } + + /// + /// Gets the mean for this distribution. + /// + /// + /// + /// The distribution's mean value. + /// + /// + public override double Mean + { + get + { + if (beta > 1) + return alpha / (beta - 1); + + return Double.PositiveInfinity; + } + } + + /// + /// Gets the mode for this distribution. + /// + /// + /// + /// The distribution's mode value. + /// + /// + public override double Mode + { + get + { + if (alpha >= 1) + return (alpha - 1) / (beta + 1); + + return 0.0; + } + } + + /// + /// Gets the variance for this distribution. + /// + /// + /// + /// The distribution's variance. + /// + /// + public override double Variance + { + get + { + if (beta > 2.0) + { + double num = alpha * (alpha + beta - 1); + double den = (beta - 2) * Math.Pow(beta - 1, 2); + return num / den; + } + else if (beta > 1.0) + { + return Double.PositiveInfinity; + } + + return double.NaN; + } + } + + /// + /// Not supported. + /// + /// + public override double Entropy + { + get { return double.NaN; } + } + + /// + /// Gets the support interval for this distribution, which + /// for the Beta- Prime distribution ranges from 0 to all + /// positive numbers. + /// + /// + /// + /// A containing + /// the support interval for this distribution. + /// + /// + public override DoubleRange Support + { + get { return new DoubleRange(0, Double.MaxValue); } + } + + /// + /// Gets the cumulative distribution function (cdf) for + /// this distribution evaluated at point x. + /// + /// + /// A single point in the distribution range. + /// + /// + /// The Cumulative Distribution Function (CDF) describes the cumulative + /// probability that a given value or any value smaller than it will occur. + /// + /// + public override double DistributionFunction([Positive] double x) + { + if (x <= 0) return 0; - return Accord.Math.Beta.Incomplete(alpha, beta, x / (1 + x)); - } - - /// - /// Gets the probability density function (pdf) for - /// this distribution evaluated at point x. - /// - /// - /// A single point in the distribution range. - /// - /// - /// The probability of x occurring - /// in the current distribution. - /// - /// - /// - /// The Probability Density Function (PDF) describes the - /// probability that a given value x will occur. - /// - /// - public override double ProbabilityDensityFunction([Positive] double x) - { - if (x <= 0) - return 0; - - double num = Math.Pow(x, alpha - 1) * Math.Pow(1 + x, -alpha - beta); - double den = Accord.Math.Beta.Function(alpha, beta); - return num / den; - } - - /// - /// Gets the log-probability density function (pdf) for - /// this distribution evaluated at point x. - /// - /// - /// A single point in the distribution range. - /// - /// - /// The logarithm of the probability of x - /// occurring in the current distribution. - /// - /// - /// - /// The Probability Density Function (PDF) describes the - /// probability that a given value x will occur. - /// - /// - public override double LogProbabilityDensityFunction([Positive] double x) - { - if (x <= 0) - return Double.NegativeInfinity; - + return Accord.Math.Beta.Incomplete(alpha, beta, x / (1 + x)); + } + + /// + /// Gets the probability density function (pdf) for + /// this distribution evaluated at point x. + /// + /// + /// A single point in the distribution range. + /// + /// + /// The probability of x occurring + /// in the current distribution. + /// + /// + /// + /// The Probability Density Function (PDF) describes the + /// probability that a given value x will occur. + /// + /// + public override double ProbabilityDensityFunction([Positive] double x) + { + if (x <= 0) + return 0; + + double num = Math.Pow(x, alpha - 1) * Math.Pow(1 + x, -alpha - beta); + double den = Accord.Math.Beta.Function(alpha, beta); + return num / den; + } + + /// + /// Gets the log-probability density function (pdf) for + /// this distribution evaluated at point x. + /// + /// + /// A single point in the distribution range. + /// + /// + /// The logarithm of the probability of x + /// occurring in the current distribution. + /// + /// + /// + /// The Probability Density Function (PDF) describes the + /// probability that a given value x will occur. + /// + /// + public override double LogProbabilityDensityFunction([Positive] double x) + { + if (x <= 0) + return Double.NegativeInfinity; + double num = (alpha - 1) * Math.Log(x) + (-alpha - beta) * Math.Log(1 + x); - double den = Accord.Math.Beta.Log(alpha, beta); - return num - den; - } - - /// - /// Creates a new object that is a copy of the current instance. - /// - /// - /// - /// A new object that is a copy of this instance. - /// - /// - public override object Clone() - { - return new BetaPrimeDistribution(this.alpha, this.beta); - } - - /// - /// Returns a that represents this instance. - /// - /// - /// - /// A that represents this instance. - /// - /// - public override string ToString(string format, IFormatProvider formatProvider) - { - return String.Format(formatProvider, "BetaPrime(x; α = {0}, β = {1})", - alpha.ToString(format, formatProvider), - beta.ToString(format, formatProvider)); - } - - } -} + double den = Accord.Math.Beta.Log(alpha, beta); + return num - den; + } + + /// + /// Creates a new object that is a copy of the current instance. + /// + /// + /// + /// A new object that is a copy of this instance. + /// + /// + public override object Clone() + { + return new BetaPrimeDistribution(this.alpha, this.beta); + } + + /// + /// Returns a that represents this instance. + /// + /// + /// + /// A that represents this instance. + /// + /// + public override string ToString(string format, IFormatProvider formatProvider) + { + return String.Format(formatProvider, "BetaPrime(x; α = {0}, β = {1})", + alpha.ToString(format, formatProvider), + beta.ToString(format, formatProvider)); + } + + } +} diff --git a/Sources/Accord.Statistics/Distributions/Univariate/Continuous/EmpiricalHazardDistribution.cs b/Sources/Accord.Statistics/Distributions/Univariate/Continuous/EmpiricalHazardDistribution.cs index d96c3118f..58c90a037 100644 --- a/Sources/Accord.Statistics/Distributions/Univariate/Continuous/EmpiricalHazardDistribution.cs +++ b/Sources/Accord.Statistics/Distributions/Univariate/Continuous/EmpiricalHazardDistribution.cs @@ -1,564 +1,1077 @@ -// Accord Statistics Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Statistics.Distributions.Univariate -{ - using System; - using Accord.Math; - using Accord.Statistics.Distributions.Fitting; - using AForge; - - /// - /// Estimators for Hazard distribution functions. - /// - /// - public enum HazardEstimator - { - /// - /// Breslow-Nelson-Aalen estimator. - /// - /// - BreslowNelsonAalen, - - /// - /// Kalbfleisch & Prentice estimator. - /// - /// - KalbfleischPrentice - } - - /// - /// Empirical Hazard Distribution. - /// - /// - /// - /// - /// The Empirical Hazard (or Survival) Distribution can be used as an - /// estimative of the true Survival function for a dataset which does - /// not relies on distribution or model assumptions about the data. - /// - /// This class can be instantiated using either hazards values through - /// its constructor and - /// ; or using survival values using - /// . - /// - /// - /// The most direct use for this class is in Survival Analysis, such as when - /// using or creating - /// Cox's Proportional Hazards models. - /// - /// - /// - /// - /// The following example shows how to construct an empirical hazards - /// function from a set of hazard values at the given time instants. - /// - /// - /// // Consider the following observations, occurring at the given time steps - /// double[] times = { 11, 10, 9, 8, 6, 5, 4, 2 }; - /// double[] values = { 0.22, 0.67, 1.00, 0.18, 1.00, 1.00, 1.00, 0.55 }; - /// - /// // Create a new empirical distribution function given the observations and event times - /// EmpiricalHazardDistribution distribution = new EmpiricalHazardDistribution(times, values); - /// - /// // Common measures - /// double mean = distribution.Mean; // 0.93696461879063664 - /// double median = distribution.Median; // 3.9999999151458066 - /// double var = distribution.Variance; // 2.0441627748096289 - /// - /// // Cumulative distribution functions - /// double cdf = distribution.DistributionFunction(x: 4.2); // 0.7877520261732569 - /// double ccdf = distribution.ComplementaryDistributionFunction(x: 4.2); // 0.21224797382674304 - /// double icdf = distribution.InverseDistributionFunction(p: cdf); // 4.3304819115496436 - /// - /// // Probability density functions - /// double pdf = distribution.ProbabilityDensityFunction(x: 4.2); // 0.046694554241883471 - /// double lpdf = distribution.LogProbabilityDensityFunction(x: 4.2); // -3.0641277326297756 - /// - /// // Hazard (failure rate) functions - /// double hf = distribution.HazardFunction(x: 4.2); // 0.22 - /// double chf = distribution.CumulativeHazardFunction(x: 4.2); // 1.55 - /// - /// // String representation - /// string str = distribution.ToString(); // H(x; v, t) - /// - /// - /// - /// - /// - [Serializable] - public class EmpiricalHazardDistribution : UnivariateContinuousDistribution, - IFittableDistribution - { - private double? mean; - private double? variance; - - private double? maxTimes; - - - /// - /// Gets the time steps of the hazard density values. - /// - /// - public double[] Times { get; private set; } - - /// - /// Gets the hazard values at each time step. - /// - /// - public double[] Hazards { get; private set; } - - - /// - /// Initializes a new instance of the class. - /// - /// - public EmpiricalHazardDistribution() - { - this.Times = new double[0]; - this.Hazards = new double[0]; - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// The time steps. - /// The hazard values at the time steps. - /// - public EmpiricalHazardDistribution(double[] time, double[] values) - { - if (time == null) - throw new ArgumentNullException("time"); - - if (values == null) - throw new ArgumentNullException("values"); - - if (time.Length != values.Length) - { - throw new DimensionMismatchException("time", - "The time steps and value vectors must have the same length."); - } - - this.Times = time; - this.Hazards = values; - } - - /// - /// Gets the mean for this distribution. - /// - /// - /// - /// The distribution's mean value. - /// - /// - public override double Mean - { - get - { - if (!mean.HasValue) - { - // http://www.stat.nuk.edu.tw/wongkf_html/survival02.pdf - - double m = 0; - for (int i = 0; i < Times.Length; i++) - m += ComplementaryDistributionFunction(Times[i]); - mean = m; - } - - return mean.Value; - } - } - - /// - /// Gets the variance for this distribution. - /// - /// - /// - /// The distribution's variance. - /// - /// - public override double Variance - { - get - { - if (!variance.HasValue) - { - // http://www.stat.nuk.edu.tw/wongkf_html/survival02.pdf - - double v = 0; - double m = Mean; - - for (int i = 0; i < Times.Length; i++) - v += Times[i] * ComplementaryDistributionFunction(Times[i]); - - this.variance = v - m * m; - } - - return variance.Value; - } - } - - /// - /// This method is not supported. - /// - /// - public override double Mode - { - get { throw new NotSupportedException(); } - } - - /// - /// This method is not supported. - /// - /// - public override double Entropy - { - get { throw new NotSupportedException(); } - } - - /// - /// Gets the support interval for this distribution. - /// - /// - /// - /// A containing - /// the support interval for this distribution. - /// - /// - public override DoubleRange Support - { - get - { - if (!maxTimes.HasValue) - { - maxTimes = 0; - if (Times.Length > 0) - maxTimes = Matrix.Max(Times); - } - - return new DoubleRange(0, maxTimes.Value); - } - } - - /// - /// Gets the cumulative hazard function for this - /// distribution evaluated at point x. - /// - /// - /// A single point in the distribution range. - /// - /// - /// The cumulative hazard function H(x) - /// evaluated at x in the current distribution. - /// - /// - public override double CumulativeHazardFunction(double x) - { - double sum = 0; - - for (int i = 0; i < Times.Length; i++) - { - if (Times[i] <= x) - sum += Hazards[i]; - } - - return sum; - } - - /// - /// Gets the cumulative distribution function (cdf) for - /// this distribution evaluated at point x. - /// - /// - /// A single point in the distribution range. - /// - /// - /// The Cumulative Distribution Function (CDF) describes the cumulative - /// probability that a given value or any value smaller than it will occur. - /// - /// - public override double DistributionFunction(double x) - { - if (!maxTimes.HasValue) - maxTimes = Matrix.Max(Times); - - if (x > maxTimes) - return 1.0; - - // H(x) = -ln(1-F(x)) - // F(x) = 1 - exp(-H(x)) - double chf = CumulativeHazardFunction(x); - double exp = Math.Exp(-chf); - return 1.0 - exp; - } - - - /// - /// Gets the complementary cumulative distribution function - /// (ccdf) for this distribution evaluated at point x. - /// This function is also known as the Survival function. - /// - /// - /// - /// A single point in the distribution range. - /// - /// - /// The Complementary Cumulative Distribution Function (CCDF) is - /// the complement of the Cumulative Distribution Function, or 1 - /// minus the CDF. - /// - /// - public override double ComplementaryDistributionFunction(double x) - { - // H(x) = -ln(1-F(x)) - // 1-F(x) = exp(-H(x)) - return Math.Exp(-CumulativeHazardFunction(x)); - } - - /// - /// Gets the probability density function (pdf) for - /// this distribution evaluated at point x. - /// - /// - /// A single point in the distribution range. - /// - /// - /// The probability of x occurring - /// in the current distribution. - /// - /// - /// - /// In the Empirical Hazard Distribution, the PDF is defined - /// as the product of the hazard function h(x) and survival - /// function CDF(x), as PDF(x) = h(x) * CDF(x). - /// - /// - public override double ProbabilityDensityFunction(double x) - { - // f(x) = h(x)exp(-H(x)) - - // Density function is the product of the hazard and survival functions - return HazardFunction(x) * ComplementaryDistributionFunction(x); - } - - /// - /// Gets the log-probability density function (pdf) for - /// this distribution evaluated at point x. - /// - /// - /// A single point in the distribution range. - /// - /// - /// The logarithm of the probability of x - /// occurring in the current distribution. - /// - /// - public override double LogProbabilityDensityFunction(double x) - { - // f(x) = h(x)exp(-H(x)) - - // Density function is the product of the hazard and survival functions - return Math.Log(HazardFunction(x) * ComplementaryDistributionFunction(x)); - } - - /// - /// Gets the hazard function, also known as the failure rate or - /// the conditional failure density function for this distribution - /// evaluated at point x. - /// - /// - /// A single point in the distribution range. - /// - /// - /// The conditional failure density function h(x) - /// evaluated at x in the current distribution. - /// - /// - public override double HazardFunction(double x) - { - for (int i = 0; i < Times.Length; i++) - if (Times[i] >= x) return Hazards[i]; - return 0; - } - - /// - /// Creates a new object that is a copy of the current instance. - /// - /// - /// - /// A new object that is a copy of this instance. - /// - /// - public override object Clone() - { - return new EmpiricalHazardDistribution( - (double[])Times.Clone(), - (double[])Hazards.Clone()); - } - - /// - /// Creates a new Empirical Hazard Distribution from the hazard values. - /// - /// - /// The time steps. - /// The hazard values at the time steps. - /// - /// A new using the given hazard values. - /// - public static EmpiricalHazardDistribution FromHazardValues(double[] time, double[] hazard) - { - return new EmpiricalHazardDistribution(time, hazard); - } - - /// - /// Creates a new Empirical Hazard Distribution from the survival values. - /// - /// - /// The time steps. - /// The survival values at the time steps. - /// - /// A new using the given survival values. - /// - public static EmpiricalHazardDistribution FromSurvivalValues(double[] time, double[] survival) - { - double[] hazard = new double[survival.Length]; - for (int i = 0; i < hazard.Length; i++) - hazard[i] = 1.0 - survival[i]; - return new EmpiricalHazardDistribution(time, hazard); - } - - /// - /// Fits the underlying distribution to a given set of observations. - /// - /// - /// The array of observations to fit the model against. The array - /// elements can be either of type double (for univariate data) or - /// type double[] (for multivariate data). - /// The weight vector containing the weight for each of the samples. - /// Optional arguments which may be used during fitting, such - /// as regularization constants and additional parameters. - /// - public override void Fit(double[] observations, double[] weights, IFittingOptions options) - { - Fit(observations, weights, options as EmpiricalHazardOptions); - } - - /// - /// Fits the underlying distribution to a given set of observations. - /// - /// - /// The array of observations to fit the model against. The array - /// elements can be either of type double (for univariate data) or - /// type double[] (for multivariate data). - /// The weight vector containing the weight for each of the samples. - /// Optional arguments which may be used during fitting, such - /// as regularization constants and additional parameters. - /// - public void Fit(double[] observations, double[] weights, EmpiricalHazardOptions options) - { - if (options == null) - throw new ArgumentNullException("options", "Options can't be null"); - - if (weights != null) - throw new ArgumentException("Weights are not supported.", "weights"); - - - double[] output = options.Output; - int[] censor = options.Censor; - double[] time = observations; - - double[] values = new double[time.Length]; - - - if (options.Estimator == HazardEstimator.BreslowNelsonAalen) - { - // Compute an estimate of the cumulative Hazard - // function using the Nelson-Aalen estimator - - for (int i = 0; i < values.Length; i++) - { - // Check if we should censor - if (censor[i] == 0) continue; - - double t = time[i]; - - int numberOfTies = 0; - - // Count the number of ties at t = time[i] - for (int j = 0; j < time.Length; j++) - if (time[j] == t) numberOfTies++; - - double sum = 0; - for (int j = 0; j < output.Length && time[j] >= time[i]; j++) - sum += output[j]; - - values[i] = numberOfTies / sum; - } - } - - else if (options.Estimator == HazardEstimator.KalbfleischPrentice) - { - // Compute an estimate of the cumulative Survival - // function using Kalbfleisch & Prentice's estimator - // assuming there are no ties in event times - - for (int i = 0; i < values.Length; i++) - { - values[i] = 1; - - // Check if we should censor - if (censor[i] == 0) continue; - - double num = output[i]; - - double den = 0; - for (int j = 0; j < output.Length && time[j] >= time[i]; j++) - den += output[j]; - - values[i] = 1.0 - Math.Pow(1.0 - num / den, 1.0 / num); - } - } - - this.Times = (double[])time.Clone(); - this.Hazards = values; - this.mean = null; - this.variance = null; - } - - /// - /// Returns a that represents this instance. - /// - /// - /// The format. - /// The format provider. - /// - /// - /// A that represents this instance. - /// - /// - public override string ToString(string format, IFormatProvider formatProvider) - { - return String.Format(formatProvider, "H(x; v, t)"); - } - } -} +// Accord Statistics Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Statistics.Distributions.Univariate +{ + using Accord.Math; + using Accord.Math.Comparers; + using Accord.Statistics.Distributions.Fitting; + using AForge; + using System; + + /// + /// Outcome status for survival methods. A sample can + /// enter the experiment, exit the experiment while still + /// alive or exit the experiment due to failure. + /// + /// + public enum SurvivalOutcome + { + /// + /// Observation started. The observation was left censored before + /// the current time and has now entered the experiment. This is + /// equivalent to R's censoring code -1. + /// + /// + Started = -1, + + /// + /// Failure happened. This is equivalent to R's censoring code 1. + /// + /// + Failed = 1, + + /// + /// The sample was right-censored. This is equivalent to R's censoring code 0. + /// + /// + Censored = 0, + } + + /// + /// Estimators for estimating parameters of Hazard distributions. + /// + /// + public enum HazardEstimator + { + /// + /// Breslow-Nelson-Aalen estimator (default). + /// + /// + BreslowNelsonAalen = 0, + + /// + /// Kaplan-Meier estimator. + /// + /// + KaplanMeier + } + + /// + /// Methods for handling ties in hazard/survival estimation algorithms. + /// + /// + public enum HazardTiesMethod + { + /// + /// Efron's method for ties (default). + /// + /// + Efron = 0, + + /// + /// Breslow's method for ties. + /// + /// + Breslow, + } + + /// + /// Estimators for Survival distribution functions. + /// + /// + public enum SurvivalEstimator + { + /// + /// Fleming-Harrington estimator (default). + /// + /// + FlemingHarrington = 0, + + /// + /// Kaplan-Meier estimator. + /// + /// + KaplanMeier, + } + + /// + /// Empirical Hazard Distribution. + /// + /// + /// + /// + /// The Empirical Hazard (or Survival) Distribution can be used as an + /// estimative of the true Survival function for a dataset which does + /// not relies on distribution or model assumptions about the data. + /// + /// + /// The most direct use for this class is in Survival Analysis, such as when + /// using or creating + /// Cox's Proportional Hazards models. + /// + /// // references + /// http://www.statsdirect.com/help/default.htm#survival_analysis/kaplan_meier.htm + /// + /// + /// + /// + /// The following example shows how to construct an empirical hazards + /// function from a set of hazard values at the given time instants. + /// + /// + /// // Consider the following observations, occurring at the given time steps + /// double[] times = { 11, 10, 9, 8, 6, 5, 4, 2 }; + /// double[] values = { 0.22, 0.67, 1.00, 0.18, 1.00, 1.00, 1.00, 0.55 }; + /// + /// // Create a new empirical distribution function given the observations and event times + /// EmpiricalHazardDistribution distribution = new EmpiricalHazardDistribution(times, values); + /// + /// // Common measures + /// double mean = distribution.Mean; // 2.1994135014183138 + /// double median = distribution.Median; // 3.9999999151458066 + /// double var = distribution.Variance; // 4.2044065839577112 + /// + /// // Cumulative distribution functions + /// double cdf = distribution.DistributionFunction(x: 4.2); // 0.7877520261732569 + /// double ccdf = distribution.ComplementaryDistributionFunction(x: 4.2); // 0.21224797382674304 + /// double icdf = distribution.InverseDistributionFunction(p: cdf); // 4.3304819115496436 + /// + /// // Probability density functions + /// double pdf = distribution.ProbabilityDensityFunction(x: 4.2); // 0.21224797382674304 + /// double lpdf = distribution.LogProbabilityDensityFunction(x: 4.2); // -1.55 + /// + /// // Hazard (failure rate) functions + /// double hf = distribution.HazardFunction(x: 4.2); // 1.0 + /// double chf = distribution.CumulativeHazardFunction(x: 4.2); // 1.55 + /// + /// // String representation + /// string str = distribution.ToString(); // H(x; v, t) + /// + /// + /// + /// + /// + [Serializable] + public class EmpiricalHazardDistribution : UnivariateContinuousDistribution, + IFittableDistribution, + IFittableDistribution + { + private double? mean; + private double? variance; + + private double[] times; + + private double[] hazards; + private double[] survivals; + + private DoubleRange range; + + private SurvivalEstimator estimator; + + + /// + /// Gets the time steps of the hazard density values. + /// + /// + public double[] Times { get { return times; } } + + /// + /// Gets the hazard rate values at each time step. + /// + /// + public double[] Hazards { get { return hazards; } } + + /// + /// Gets the survival values at each time step. + /// + /// + public double[] Survivals { get { return survivals; } } + + /// + /// Gets the survival function estimator being used in this distribution. + /// + /// + public SurvivalEstimator Estimator + { + get { return estimator; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public EmpiricalHazardDistribution() + { + init(null, null, SurvivalOptions.DefaultSurvival); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The time steps. + /// The hazard rates at the time steps. + /// + public EmpiricalHazardDistribution(double[] time, double[] lambdas) + { + init(time, lambdas, SurvivalOptions.DefaultSurvival); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The time steps. + /// The hazard rates at the time steps. + /// The survival function estimator to be used. Default is + /// + /// + public EmpiricalHazardDistribution(double[] times, double[] lambdas, SurvivalEstimator estimator) + { + if (times == null) + throw new ArgumentNullException("time"); + + if (lambdas == null) + throw new ArgumentNullException("values"); + + if (times.Length != lambdas.Length) + { + throw new DimensionMismatchException("time", + "The time steps and value vectors must have the same length."); + } + + init(times, lambdas, estimator); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The survival function estimator to be used. Default is + /// + /// + public EmpiricalHazardDistribution(SurvivalEstimator estimator) + { + init(null, null, estimator); + } + + void init(double[] times, double[] hazards, SurvivalEstimator estimator) + { + if (times == null) + times = new double[0]; + + if (hazards == null) + hazards = new double[0]; + + times = (double[])times.Clone(); + hazards = (double[])hazards.Clone(); + + Array.Sort(times, hazards); + + for (int i = 0; i < times.Length - 1; i++) + { + if (times[i] > times[i + 1]) + throw new Exception(); + } + + if (times.Length > 0) + { + this.range = new DoubleRange(0, times[times.Length - 1]); + + this.survivals = new double[times.Length]; + this.survivals[0] = 1; + for (int i = 1; i < survivals.Length; i++) + survivals[i] = survivals[i - 1] * (1.0 - hazards[i - 1]); + } + + this.times = times; + this.hazards = hazards; + this.estimator = estimator; + + this.mean = null; + this.variance = null; + } + + /// + /// Gets the mean for this distribution. + /// + /// + /// + /// The distribution's mean value. + /// + /// + public override double Mean + { + get + { + if (!mean.HasValue) + { + // http://www.stat.nuk.edu.tw/wongkf_html/survival02.pdf + double m = 0; + foreach (var t in times.Distinct()) + m += t * ProbabilityDensityFunction(t); + mean = m; + } + + return mean.Value; + } + } + + /// + /// Gets the variance for this distribution. + /// + /// + /// + /// The distribution's variance. + /// + /// + public override double Variance + { + get + { + if (!variance.HasValue) + { + // http://www.stat.nuk.edu.tw/wongkf_html/survival02.pdf + + double v = 0; + foreach (var t in times.Distinct()) + v += t * t * ProbabilityDensityFunction(t); + + double m = Mean; + this.variance = v - m * m; + } + + return variance.Value; + } + } + + /// + /// This method is not supported. + /// + /// + public override double Mode + { + get { throw new NotSupportedException(); } + } + + /// + /// This method is not supported. + /// + /// + public override double Entropy + { + get { throw new NotSupportedException(); } + } + + /// + /// Gets the support interval for this distribution. + /// + /// + /// + /// A containing + /// the support interval for this distribution. + /// + /// + public override DoubleRange Support + { + get { return range; } + } + + + + + /// + /// Gets the complementary cumulative distribution function + /// (ccdf) for this distribution evaluated at point x. + /// This function is also known as the Survival function. + /// + /// + /// + /// A single point in the distribution range. + /// + /// + /// The Complementary Cumulative Distribution Function (CCDF) is + /// the complement of the Cumulative Distribution Function, or 1 + /// minus the CDF. In the Empirical Hazard Distribution, this function + /// is computed using the Fleming-Harrington estimator. + /// + /// + public override double ComplementaryDistributionFunction(double x) + { + if (estimator == SurvivalEstimator.KaplanMeier) + { + // Kaplan-Meier estimator + if (x < range.Min) + return 1; + + if (x > range.Max) + return 0; + + for (int i = 0; i < survivals.Length; i++) + { + if (times[i] > x) + return survivals[i]; + } + + return survivals[survivals.Length - 1]; + } + + else // (estimator == SurvivalEstimator.FlemingHarrington) + { + // Use the Fleming-Harrington estimator. In general, this estimator + // will be close to the Kaplan-Meier estimator, but not equal (page 98) + // http://www.amstat.org/chapters/northeasternillinois/pastevents/presentations/summer05_Ibrahim_J.pdf + + // H(x) = -ln(1-F(x)) + // 1-F(x) = exp(-H(x)) + double chf = CumulativeHazardFunction(x); + double s = Math.Exp(-chf); + return s; + } + } + + /// + /// Gets the cumulative hazard function for this + /// distribution evaluated at point x. + /// + /// + /// A single point in the distribution range. + /// + /// + /// The cumulative hazard function H(x) + /// evaluated at x in the current distribution. + /// + /// + public override double CumulativeHazardFunction(double x) + { + if (estimator == SurvivalEstimator.KaplanMeier) + { + // Compute the cumulative hazard function using the Kaplan-Meier estimator (page 98) + // http://www.amstat.org/chapters/northeasternillinois/pastevents/presentations/summer05_Ibrahim_J.pdf + + // This is also known as the method of Peterson (1977): + // Peterson AV Jr.. Expressing the Kaplan-Meier estimator as a function of empirical + // subsurvival functions. Journal of the American Statistical Association 1977;72:854-858. + return -Math.Log(ComplementaryDistributionFunction(x)); + } + else // (estimator == SurvivalEstimator.FlemingHarrington) + { + // Fleming-Harrington estimator + if (x < range.Min || x > range.Max) + return Double.PositiveInfinity; + + double sum = 0; + for (int i = 0; i < times.Length; i++) + { + if (times[i] <= x) + sum += hazards[i]; + } + + return sum; + } + } + + /// + /// Gets the hazard function, also known as the failure rate or + /// the conditional failure density function for this distribution + /// evaluated at point x. + /// + /// + /// A single point in the distribution range. + /// + /// + /// The conditional failure density function h(x) + /// evaluated at x in the current distribution. + /// + /// + public override double HazardFunction(double x) + { + if (x < range.Min || x > range.Max) + return 0; + + double sum = 0; + for (int i = 0; i < times.Length; i++) + { + if (times[i] == x) + sum += hazards[i]; + } + + return sum; + } + + + /// + /// Gets the probability density function (pdf) for + /// this distribution evaluated at point x. + /// + /// + /// A single point in the distribution range. + /// + /// + /// The probability of x occurring in the current distribution. + /// + /// + /// + /// In the Empirical Hazard Distribution, the PDF is defined + /// as the product of the hazard function h(x) and survival + /// function S(x), as PDF(x) = h(x) * S(x). + /// + /// + public override double ProbabilityDensityFunction(double x) + { + return HazardFunction(x) * ComplementaryDistributionFunction(x); + } + + /// + /// Gets the cumulative distribution function (cdf) for + /// this distribution evaluated at point x. + /// + /// + /// A single point in the distribution range. + /// + /// + /// The Cumulative Distribution Function (CDF) describes the cumulative + /// probability that a given value or any value smaller than it will occur. + /// + /// + public override double DistributionFunction(double x) + { + return 1.0 - ComplementaryDistributionFunction(x); + } + + + + /// + /// Creates a new object that is a copy of the current instance. + /// + /// + /// + /// A new object that is a copy of this instance. + /// + /// + public override object Clone() + { + return new EmpiricalHazardDistribution((double[])Times.Clone(), (double[])Hazards.Clone(), estimator); + } + + /// + /// Fits the underlying distribution to a given set of observations. + /// + /// + /// The array of observations to fit the model against. The array + /// elements can be either of type double (for univariate data) or + /// type double[] (for multivariate data). + /// The weight vector containing the weight for each of the samples. + /// Optional arguments which may be used during fitting, such + /// as regularization constants and additional parameters. + /// + public override void Fit(double[] observations, double[] weights, IFittingOptions options) + { + Fit(observations, weights, options as SurvivalOptions); + } + + /// + /// Fits the underlying distribution to a given set of observations. + /// + /// + /// The array of observations to fit the model against. The array + /// elements can be either of type double (for univariate data) or + /// type double[] (for multivariate data). + /// The weight vector containing the weight for each of the samples. + /// Optional arguments which may be used during fitting, such + /// as regularization constants and additional parameters. + /// + public void Fit(double[] observations, double[] weights, EmpiricalHazardOptions options) + { + Fit(observations, weights, options as SurvivalOptions); + } + + /// + /// Fits the underlying distribution to a given set of observations. + /// + /// + /// The array of observations to fit the model against. The array + /// elements can be either of type double (for univariate data) or + /// type double[] (for multivariate data). + /// The weight vector containing the weight for each of the samples. + /// Optional arguments which may be used during fitting, such + /// as regularization constants and additional parameters. + /// + public void Fit(double[] observations, double[] weights, SurvivalOptions options) + { + SurvivalOutcome[] outcome = null; + double[] output = weights; + var estimator = HazardEstimator.BreslowNelsonAalen; + var ties = HazardTiesMethod.Breslow; + + if (options != null) + { + outcome = options.Outcome; + var hazardOps = options as EmpiricalHazardOptions; + if (hazardOps != null) + { + estimator = hazardOps.Estimator; + ties = hazardOps.Ties; + } + } + + if (outcome == null) + outcome = Vector.Create(observations.Length, SurvivalOutcome.Failed); + + if (output == null) + output = Vector.Create(observations.Length, 1.0); + + + + if (estimator == HazardEstimator.KaplanMeier) + { + double[] times = observations.Distinct(); + double[] hazards = new double[times.Length]; + hazards[hazards.Length - 1] = 1; + + Array.Sort(times); + + // Compute an estimate of the hazard function using + // the Kaplan-Meier estimator for the survival function + + double r = observations.Length; + double d = 0; // Number of deaths + double c = 0; // Number of censor + + for (int j = 0; j < times.Length; j++) + { + double t = times[j]; + + // Survivals until time t + r = r - d - c; + d = 0; + c = 0; + + for (int i = 0; i < observations.Length; i++) + { + if (observations[i] == t) + { + if (outcome[i] == SurvivalOutcome.Failed) + d++; // Failure at time t + else + c++; // Censored at time t + } + } + + hazards[j] = d / r; + } + + this.init(times, hazards, this.estimator); + return; + } + else if (estimator == HazardEstimator.BreslowNelsonAalen) + { + double[] survivals = new double[observations.Length]; + + Sort(ref observations, ref outcome, ref output); + + // Compute an estimate of the cumulative Hazard + // function using the Breslow-Nelson-Aalen estimator + + double sum = 0; + double d = 0; + for (int i = 0; i < observations.Length; i++) + { + survivals[i] = 1; + double t = observations[i]; + double v = output[i]; + var o = outcome[i]; + + sum += v; + + if (o == SurvivalOutcome.Censored) + { + d = 0; + continue; + } + + if (i > 0 && t != observations[i - 1]) + d = 0; + + // Count the number of deaths at t + if (o == SurvivalOutcome.Failed) + d++; // Deaths at time t + + if (i < observations.Length - 1 && t == observations[i + 1] && outcome[i + 1] == SurvivalOutcome.Failed) + continue; + + if (ties == HazardTiesMethod.Breslow) + { + survivals[i] = Math.Exp(-d / sum); + } + else + { + if (d == 1) + { + survivals[i] = Math.Pow(1 - v / sum, 1 / v); + } + else + { + survivals[i] = Math.Exp(-d / sum); + } + } + } + + // Transform to hazards + double[] hazards = new double[observations.Length]; + for (int i = 0; i < hazards.Length; i++) + hazards[i] = -Math.Log(survivals[i]); + + Array.Sort(observations, hazards); + + this.init(observations, hazards, this.estimator); + return; + } + + throw new ArgumentException(); + } + + /// + /// Sorts time-censored events considering their time of occurrence and the type of event. + /// Events are first sorted in decreased order of occurrence, and then with failures coming + /// before censoring. + /// + /// + /// The time of occurrence for the event. + /// The outcome at the time of event (failure or censored). + /// + /// The indices of the new sorting. + /// + public static int[] Sort(ref double[] time, ref SurvivalOutcome[] output) + { + double[] keys = new double[time.Length]; + for (int i = 0; i < keys.Length; i++) + keys[i] = time[i] - 1e-5 * (int)output[i]; + + int[] idx; + Vector.Sort(keys, out idx, stable: true, direction: ComparerDirection.Descending); + + time = time.Submatrix(idx); + output = output.Submatrix(idx); + + return idx; + } + + /// + /// Sorts time-censored events considering their time of occurrence and the type of event. + /// Events are first sorted in decreased order of occurrence, and then with failures coming + /// before censoring. + /// + /// + /// The time of occurrence for the event. + /// The outcome at the time of event (failure or censored). + /// The input vector associated with the event. + /// + /// The indices of the new sorting. + /// + public static int[] Sort(ref double[] time, ref SurvivalOutcome[] output, ref double[][] inputs) + { + int[] idx = Sort(ref time, ref output); + inputs = inputs.Submatrix(idx); + return idx; + } + + /// + /// Sorts time-censored events considering their time of occurrence and the type of event. + /// Events are first sorted in decreased order of occurrence, and then with failures coming + /// before censoring. + /// + /// + /// The time of occurrence for the event. + /// The outcome at the time of event (failure or censored). + /// The weights associated with each event. + /// + /// The indices of the new sorting. + /// + public static int[] Sort(ref double[] time, ref SurvivalOutcome[] output, ref double[] weights) + { + int[] idx = Sort(ref time, ref output); + weights = weights.Submatrix(idx); + return idx; + } + + /// + /// Returns a that represents this instance. + /// + /// + /// The format. + /// The format provider. + /// + /// + /// A that represents this instance. + /// + /// + public override string ToString(string format, IFormatProvider formatProvider) + { + return String.Format(formatProvider, "H(x; v, t)"); + } + + /// + /// Estimates an Empirical Hazards distribution considering event times and the outcome of the + /// observed sample at the time of event, plus additional parameters for the hazard estimation. + /// + /// + /// The time of occurrence for the event. + /// The outcome at the time of event (failure or censored). + /// The weights associated with each event. + /// + /// The estimated from the given data. + /// + public static EmpiricalHazardDistribution Estimate(double[] time, SurvivalOutcome[] outcome, double[] weights) + { + return Estimate(time, outcome, weights, + EmpiricalHazardOptions.DefaultSurvival, EmpiricalHazardOptions.DefaultEstimator); + } + + /// + /// Estimates an Empirical Hazards distribution considering event times and the outcome of the + /// observed sample at the time of event, plus additional parameters for the hazard estimation. + /// + /// + /// The time of occurrence for the event. + /// The outcome at the time of event (failure or censored). + /// The weights associated with each event. + /// + /// The estimated from the given data. + /// + public static EmpiricalHazardDistribution Estimate(double[] time, int[] outcome, double[] weights) + { + return Estimate(time, outcome, weights, + EmpiricalHazardOptions.DefaultSurvival, EmpiricalHazardOptions.DefaultEstimator); + } + + /// + /// Estimates an Empirical Hazards distribution considering event times and the outcome of the + /// observed sample at the time of event, plus additional parameters for the hazard estimation. + /// + /// + /// The time of occurrence for the event. + /// The outcome at the time of event (failure or censored). + /// The weights associated with each event. + /// The hazard estimator to use. Default is . + /// The survival estimator to use. Default is . + /// + /// The estimated from the given data. + /// + public static EmpiricalHazardDistribution Estimate(double[] time, SurvivalOutcome[] outcome, double[] weights, + SurvivalEstimator survival, HazardEstimator hazard) + { + return Estimate(time, outcome, weights, survival, hazard, EmpiricalHazardOptions.DefaultTies); + } + + /// + /// Estimates an Empirical Hazards distribution considering event times and the outcome of the + /// observed sample at the time of event, plus additional parameters for the hazard estimation. + /// + /// + /// The time of occurrence for the event. + /// The outcome at the time of event (failure or censored). + /// The weights associated with each event. + /// The hazard estimator to use. Default is . + /// The survival estimator to use. Default is . + /// + /// The estimated from the given data. + /// + public static EmpiricalHazardDistribution Estimate(double[] time, int[] outcome, double[] weights, + SurvivalEstimator survival, HazardEstimator hazard) + { + return Estimate(time, outcome, weights, survival, hazard, EmpiricalHazardOptions.DefaultTies); + } + + /// + /// Estimates an Empirical Hazards distribution considering event times and the outcome of the + /// observed sample at the time of event, plus additional parameters for the hazard estimation. + /// + /// + /// The time of occurrence for the event. + /// The outcome at the time of event (failure or censored). + /// The hazard estimator to use. Default is . + /// The survival estimator to use. Default is . + /// + /// The estimated from the given data. + /// + public static EmpiricalHazardDistribution Estimate(double[] time, SurvivalOutcome[] outcome, + SurvivalEstimator survival, HazardEstimator hazard) + { + return Estimate(time, outcome, null, survival, hazard, EmpiricalHazardOptions.DefaultTies); + } + + /// + /// Estimates an Empirical Hazards distribution considering event times and the outcome of the + /// observed sample at the time of event, plus additional parameters for the hazard estimation. + /// + /// + /// The time of occurrence for the event. + /// The outcome at the time of event (failure or censored). + /// The hazard estimator to use. Default is . + /// The survival estimator to use. Default is . + /// + /// The estimated from the given data. + /// + public static EmpiricalHazardDistribution Estimate(double[] time, int[] outcome, + SurvivalEstimator survival, HazardEstimator hazard) + { + return Estimate(time, outcome, survival, hazard, EmpiricalHazardOptions.DefaultTies); + } + + /// + /// Estimates an Empirical Hazards distribution considering event times and the outcome of the + /// observed sample at the time of event, plus additional parameters for the hazard estimation. + /// + /// + /// The time of occurrence for the event. + /// The outcome at the time of event (failure or censored). + /// The hazard estimator to use. Default is . + /// The survival estimator to use. Default is . + /// The method for handling event ties. Default is . + /// + /// The estimated from the given data. + /// + public static EmpiricalHazardDistribution Estimate(double[] time, int[] outcome, + SurvivalEstimator survival, HazardEstimator hazard, HazardTiesMethod ties) + { + return Estimate(time, outcome.To(), null, survival, hazard, ties); + } + + /// + /// Estimates an Empirical Hazards distribution considering event times and the outcome of the + /// observed sample at the time of event, plus additional parameters for the hazard estimation. + /// + /// + /// The time of occurrence for the event. + /// The outcome at the time of event (failure or censored). + /// The weights associated with each event. + /// The hazard estimator to use. Default is . + /// The survival estimator to use. Default is . + /// The method for handling event ties. Default is . + /// + /// The estimated from the given data. + /// + public static EmpiricalHazardDistribution Estimate(double[] time, int[] outcome, + double[] weights, SurvivalEstimator survival, HazardEstimator hazard, HazardTiesMethod ties) + { + return Estimate(time, outcome.To(), weights, survival, hazard, ties); + } + + /// + /// Estimates an Empirical Hazards distribution considering event times and the outcome of the + /// observed sample at the time of event, plus additional parameters for the hazard estimation. + /// + /// + /// The time of occurrence for the event. + /// The outcome at the time of event (failure or censored). + /// The hazard estimator to use. Default is . + /// The survival estimator to use. Default is . + /// The method for handling event ties. Default is . + /// + /// The estimated from the given data. + /// + public static EmpiricalHazardDistribution Estimate(double[] time, SurvivalOutcome[] outcome, + SurvivalEstimator survival, HazardEstimator hazard, HazardTiesMethod ties) + { + return Estimate(time, outcome, null, survival, hazard, ties); + } + + /// + /// Estimates an Empirical Hazards distribution considering event times and the outcome of the + /// observed sample at the time of event, plus additional parameters for the hazard estimation. + /// + /// + /// The time of occurrence for the event. + /// The outcome at the time of event (failure or censored). + /// The method for handling event ties. Default is . + /// + /// The estimated from the given data. + /// + public static EmpiricalHazardDistribution Estimate(double[] time, SurvivalOutcome[] outcome, HazardTiesMethod ties) + { + return Estimate(time, outcome, null, SurvivalOptions.DefaultSurvival, EmpiricalHazardOptions.DefaultEstimator, ties); + } + + /// + /// Estimates an Empirical Hazards distribution considering event times and the outcome of the + /// observed sample at the time of event, plus additional parameters for the hazard estimation. + /// + /// + /// The time of occurrence for the event. + /// The outcome at the time of event (failure or censored). + /// The method for handling event ties. Default is . + /// + /// The estimated from the given data. + /// + public static EmpiricalHazardDistribution Estimate(double[] time, int[] outcome, HazardTiesMethod ties) + { + return Estimate(time, outcome, null, SurvivalOptions.DefaultSurvival, EmpiricalHazardOptions.DefaultEstimator, ties); + } + + /// + /// Estimates an Empirical Hazards distribution considering event times and the outcome of the + /// observed sample at the time of event, plus additional parameters for the hazard estimation. + /// + /// + /// The time of occurrence for the event. + /// The outcome at the time of event (failure or censored). + /// + /// The estimated from the given data. + /// + public static EmpiricalHazardDistribution Estimate(double[] time, SurvivalOutcome[] outcome) + { + return Estimate(time, outcome, null, SurvivalOptions.DefaultSurvival, + EmpiricalHazardOptions.DefaultEstimator, EmpiricalHazardOptions.DefaultTies); + } + + /// + /// Estimates an Empirical Hazards distribution considering event times and the outcome of the + /// observed sample at the time of event, plus additional parameters for the hazard estimation. + /// + /// + /// The time of occurrence for the event. + /// The outcome at the time of event (failure or censored). + /// The weights associated with each event. + /// The hazard estimator to use. Default is . + /// The survival estimator to use. Default is . + /// The method for handling event ties. Default is . + /// + /// The estimated from the given data. + /// + public static EmpiricalHazardDistribution Estimate(double[] time, SurvivalOutcome[] outcome, + double[] weights, SurvivalEstimator survival, HazardEstimator hazard, HazardTiesMethod ties) + { + var dist = new EmpiricalHazardDistribution(survival); + dist.Fit(time, weights, new EmpiricalHazardOptions + { + Outcome = outcome, + Estimator = hazard, + Ties = ties + }); + + return dist; + } + + } +} diff --git a/Sources/Accord.Statistics/Distributions/Univariate/Continuous/GeneralContinuousDistribution.cs b/Sources/Accord.Statistics/Distributions/Univariate/Continuous/GeneralContinuousDistribution.cs index 449be40d1..b82fab011 100644 --- a/Sources/Accord.Statistics/Distributions/Univariate/Continuous/GeneralContinuousDistribution.cs +++ b/Sources/Accord.Statistics/Distributions/Univariate/Continuous/GeneralContinuousDistribution.cs @@ -1,459 +1,476 @@ -// Accord Statistics Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Statistics.Distributions.Univariate -{ - using System; - using Accord.Math.Differentiation; - using Accord.Math.Integration; - using Accord.Math.Optimization; - using AForge; - - /// - /// General continuous distribution. - /// - /// - /// - /// - /// The general continuous distribution provides the automatic calculation for - /// a variety of distribution functions and measures given only definitions for - /// the Probability Density Function (PDF) or the Cumulative Distribution Function - /// (CDF). Values such as the Expected value, Variance, Entropy and others are - /// computed through numeric integration. - /// - /// - /// - /// - /// // Let's suppose we have a formula that defines a probability distribution - /// // but we dont know much else about it. We don't know the form of its cumulative - /// // distribution function, for example. We would then like to know more about - /// // it, such as the underlying distribution's moments, characteristics, and - /// // properties. - /// - /// // Let's suppose the formula we have is this one: - /// double mu = 5; - /// double sigma = 4.2; - /// - /// Func>double, double> df = x => 1.0 / (sigma * Math.Sqrt(2 * Math.PI)) - /// * Math.Exp(-Math.Pow(x - mu, 2) / (2 * sigma * sigma)); - /// - /// // And for the moment, let's also pretend we don't know it is actually the - /// // p.d.f. of a Gaussian distribution with mean 5 and std. deviation of 4.2. - /// - /// // So, let's create a distribution based _solely_ on the formula we have: - /// var distribution = GeneralContinuousDistribution.FromDensityFunction(df); - /// - /// // Now, we can check everything that we can know about it: - /// - /// double mean = distribution.Mean; // 5 (note that all of those have been - /// double median = distribution.Median; // 5 detected automatically simply from - /// double var = distribution.Variance; // 17.64 the given density formula through - /// double mode = distribution.Mode; // 5 numerical methods) - /// - /// double cdf = distribution.DistributionFunction(x: 1.4); // 0.19568296915377595 - /// double pdf = distribution.ProbabilityDensityFunction(x: 1.4); // 0.065784567984404935 - /// double lpdf = distribution.LogProbabilityDensityFunction(x: 1.4); // -2.7213699972695058 - /// - /// double ccdf = distribution.ComplementaryDistributionFunction(x: 1.4); // 0.80431703084622408 - /// double icdf = distribution.InverseDistributionFunction(p: cdf); // 1.3999999997024655 - /// - /// double hf = distribution.HazardFunction(x: 1.4); // 0.081789351041333558 - /// double chf = distribution.CumulativeHazardFunction(x: 1.4); // 0.21776177055276186 - /// - /// - /// - public class GeneralContinuousDistribution : UnivariateContinuousDistribution - { - - // distribution parameters - private IUnivariateIntegration method; - private Func pdf; - private Func cdf; - private DoubleRange support; - - private double? mean; - private double? variance; - private double? entropy; - private double? mode; - - - /// - /// Creates a new with the given PDF and CDF functions. - /// - /// - /// The distribution's support over the real line. - /// A probability density function. - /// A cumulative distribution function. - /// - public GeneralContinuousDistribution(DoubleRange support, - Func density, Func distribution) - { - if (density == null) - throw new ArgumentNullException("density"); - - if (distribution == null) - throw new ArgumentNullException("distribution"); - - this.method = new InfiniteAdaptiveGaussKronrod(100); - this.pdf = density; - this.cdf = distribution; - this.support = support; - } - - /// - /// Creates a new - /// from an existing - /// continuous distribution. - /// - /// - /// The distribution. - /// - /// A representing the same - /// but whose measures and functions are computed - /// using numerical integration and differentiation. - /// - public static GeneralContinuousDistribution FromDistribution(UnivariateContinuousDistribution distribution) - { - GeneralContinuousDistribution dist = new GeneralContinuousDistribution(); - dist.support = distribution.Support; - dist.pdf = distribution.ProbabilityDensityFunction; - dist.cdf = distribution.DistributionFunction; - return dist; - } - - /// - /// Creates a new - /// using only a probability density function definition. - /// - /// - /// A probability density function. - /// - /// A created from the - /// whose measures and functions are computed using - /// numerical integration and differentiation. - /// - public static GeneralContinuousDistribution FromDensityFunction(Func pdf) - { - var range = new DoubleRange(double.NegativeInfinity, double.PositiveInfinity); - var method = createDefaultIntegrationMethod(); - return FromDensityFunction(range, pdf, method); - } - - /// - /// Creates a new - /// using only a probability density function definition. - /// - /// - /// The distribution's support over the real line. - /// A probability density function. - /// - /// A created from the - /// whose measures and functions are computed using - /// numerical integration and differentiation. - /// - public static GeneralContinuousDistribution FromDensityFunction( - DoubleRange support, Func pdf) - { - var method = createDefaultIntegrationMethod(); - return FromDensityFunction(support, pdf, method); - } - - /// - /// Creates a new - /// using only a cumulative distribution function definition. - /// - /// - /// A cumulative distribution function. - /// - /// A created from the - /// whose measures and functions are computed using - /// numerical integration and differentiation. - /// - public static GeneralContinuousDistribution FromDistributionFunction(Func cdf) - { - var range = new DoubleRange(double.NegativeInfinity, double.PositiveInfinity); - var method = createDefaultIntegrationMethod(); - return FromDistributionFunction(range, cdf, method); - } - - /// - /// Creates a new - /// using only a cumulative distribution function definition. - /// - /// - /// The distribution's support over the real line. - /// A cumulative distribution function. - /// - /// A created from the - /// whose measures and functions are computed using - /// numerical integration and differentiation. - /// - public static GeneralContinuousDistribution FromDistributionFunction( - DoubleRange support, Func cdf) - { - var method = createDefaultIntegrationMethod(); - return FromDistributionFunction(support, cdf, method); - } - - /// - /// Creates a new - /// using only a probability density function definition. - /// - /// - /// The distribution's support over the real line. - /// A probability density function. - /// The integration method to use for numerical computations. - /// - /// A created from the - /// whose measures and functions are computed using - /// numerical integration and differentiation. - /// - public static GeneralContinuousDistribution FromDensityFunction( - DoubleRange support, Func pdf, IUnivariateIntegration method) - { - GeneralContinuousDistribution dist = new GeneralContinuousDistribution(); - dist.support = support; - dist.pdf = pdf; - dist.method = method; - return dist; - } - - /// - /// Creates a new - /// using only a cumulative distribution function definition. - /// - /// - /// The distribution's support over the real line. - /// A cumulative distribution function. - /// The integration method to use for numerical computations. - /// - /// A created from the - /// whose measures and functions are computed using - /// numerical integration and differentiation. - /// - public static GeneralContinuousDistribution FromDistributionFunction( - DoubleRange support, Func cdf, IUnivariateIntegration method) - { - GeneralContinuousDistribution dist = new GeneralContinuousDistribution(); - dist.support = support; - dist.cdf = cdf; - dist.method = method; - return dist; - } - - /// - /// Gets the support interval for this distribution. - /// - /// - /// - /// A containing - /// the support interval for this distribution. - /// - /// - public override DoubleRange Support - { - get { return support; } - } - - - /// - /// Gets the mean for this distribution. - /// - /// - /// The distribution's mean value. - /// - public override double Mean - { - get - { - if (mean == null) - { - method.Function = (x) => - { - double p = ProbabilityDensityFunction(x); - return x * p; - }; - - method.Range = support; - method.Compute(); - mean = method.Area; - } - - return mean.Value; - } - } - - /// - /// Gets the variance for this distribution. - /// - /// - /// The distribution's variance. - /// - public override double Variance - { - get - { - if (variance == null) - { - double u = Mean; - method.Function = (x) => (x * x) * ProbabilityDensityFunction(x); - method.Range = support; - method.Compute(); - variance = method.Area - u * u; - } - - return variance.Value; - } - } - - /// - /// Gets the entropy for this distribution. - /// - /// - /// The distribution's entropy. - /// - public override double Entropy - { - get - { - if (entropy == null) - { - method.Function = (x) => ProbabilityDensityFunction(x) * LogProbabilityDensityFunction(x); - method.Range = support; - method.Compute(); - entropy = method.Area; - } - - return entropy.Value; - } - } - - /// - /// Gets the mode for this distribution. - /// - /// - /// - /// The distribution's mode value. - /// - /// - public override double Mode - { - get - { - if (mode == null) - { - var range = GetRange(0.99); - double lower = range.Min; - double upper = range.Max; - mode = BrentSearch.Maximize(ProbabilityDensityFunction, lower, upper); - } - - return mode.Value; - } - } - - /// - /// Gets the cumulative distribution function (cdf) for - /// this distribution evaluated at point x. - /// - /// - /// A single point in the distribution range. - /// - public override double DistributionFunction(double x) - { - if (cdf != null) - return cdf(x); - - method.Function = pdf; - method.Range = new DoubleRange(Double.NegativeInfinity, x); - method.Compute(); - return method.Area; - } - - /// - /// Gets the probability density function (pdf) for - /// this distribution evaluated at point x. - /// - /// - /// A single point in the distribution range. - /// - /// - /// The probability of x occurring - /// in the current distribution. - /// - /// - public override double ProbabilityDensityFunction(double x) - { - if (pdf != null) - return pdf(x); - - return FiniteDifferences.Derivative(cdf, x, 1, 1e-6); - } - - /// - /// Creates a new object that is a copy of the current instance. - /// - /// - /// - /// A new object that is a copy of this instance. - /// - /// - public override object Clone() - { - GeneralContinuousDistribution c = new GeneralContinuousDistribution(); - - c.pdf = pdf; - c.cdf = cdf; - c.method = (IUnivariateIntegration)method.Clone(); - - return c; - } - - /// - /// Returns a that represents this instance. - /// - /// - /// The format. - /// The format provider. - /// - /// - /// A that represents this instance. - /// - /// - public override string ToString(string format, IFormatProvider formatProvider) - { - return String.Format(formatProvider, "Continuous(x)"); - } - - private GeneralContinuousDistribution() - { - } - - - private static InfiniteAdaptiveGaussKronrod createDefaultIntegrationMethod() - { - var method = new InfiniteAdaptiveGaussKronrod(100); - method.ToleranceRelative = 1e-5; - return method; - } - } -} +// Accord Statistics Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Statistics.Distributions.Univariate +{ + using System; + using Accord.Math.Differentiation; + using Accord.Math.Integration; + using Accord.Math.Optimization; + using AForge; + + /// + /// General continuous distribution. + /// + /// + /// + /// + /// The general continuous distribution provides the automatic calculation for + /// a variety of distribution functions and measures given only definitions for + /// the Probability Density Function (PDF) or the Cumulative Distribution Function + /// (CDF). Values such as the Expected value, Variance, Entropy and others are + /// computed through numeric integration. + /// + /// + /// + /// + /// // Let's suppose we have a formula that defines a probability distribution + /// // but we dont know much else about it. We don't know the form of its cumulative + /// // distribution function, for example. We would then like to know more about + /// // it, such as the underlying distribution's moments, characteristics, and + /// // properties. + /// + /// // Let's suppose the formula we have is this one: + /// double mu = 5; + /// double sigma = 4.2; + /// + /// Func>double, double> df = x => 1.0 / (sigma * Math.Sqrt(2 * Math.PI)) + /// * Math.Exp(-Math.Pow(x - mu, 2) / (2 * sigma * sigma)); + /// + /// // And for the moment, let's also pretend we don't know it is actually the + /// // p.d.f. of a Gaussian distribution with mean 5 and std. deviation of 4.2. + /// + /// // So, let's create a distribution based _solely_ on the formula we have: + /// var distribution = GeneralContinuousDistribution.FromDensityFunction(df); + /// + /// // Now, we can check everything that we can know about it: + /// + /// double mean = distribution.Mean; // 5 (note that all of those have been + /// double median = distribution.Median; // 5 detected automatically simply from + /// double var = distribution.Variance; // 17.64 the given density formula through + /// double mode = distribution.Mode; // 5 numerical methods) + /// + /// double cdf = distribution.DistributionFunction(x: 1.4); // 0.19568296915377595 + /// double pdf = distribution.ProbabilityDensityFunction(x: 1.4); // 0.065784567984404935 + /// double lpdf = distribution.LogProbabilityDensityFunction(x: 1.4); // -2.7213699972695058 + /// + /// double ccdf = distribution.ComplementaryDistributionFunction(x: 1.4); // 0.80431703084622408 + /// double icdf = distribution.InverseDistributionFunction(p: cdf); // 1.3999999997024655 + /// + /// double hf = distribution.HazardFunction(x: 1.4); // 0.081789351041333558 + /// double chf = distribution.CumulativeHazardFunction(x: 1.4); // 0.21776177055276186 + /// + /// + /// + public class GeneralContinuousDistribution : UnivariateContinuousDistribution + { + + // distribution parameters + private IUnivariateIntegration method; + private Func pdf; + private Func cdf; + private DoubleRange support; + + private double? mean; + private double? variance; + private double? entropy; + private double? mode; + + + /// + /// Creates a new with the given PDF and CDF functions. + /// + /// + /// The distribution's support over the real line. + /// A probability density function. + /// A cumulative distribution function. + /// + public GeneralContinuousDistribution(DoubleRange support, + Func density, Func distribution) + { + if (density == null) + throw new ArgumentNullException("density"); + + if (distribution == null) + throw new ArgumentNullException("distribution"); + + this.method = new InfiniteAdaptiveGaussKronrod(100); + this.pdf = density; + this.cdf = distribution; + this.support = support; + } + + /// + /// Creates a new with the given PDF and CDF functions. + /// + /// + /// A distribution whose properties will be numerically estimated. + /// + public GeneralContinuousDistribution(UnivariateContinuousDistribution distribution) + { + if (distribution == null) + throw new ArgumentNullException("distribution"); + + this.method = new InfiniteAdaptiveGaussKronrod(100); + this.pdf = distribution.ProbabilityDensityFunction; + this.cdf = distribution.DistributionFunction; + this.support = distribution.Support; + } + + /// + /// Creates a new + /// from an existing + /// continuous distribution. + /// + /// + /// The distribution. + /// + /// A representing the same + /// but whose measures and functions are computed + /// using numerical integration and differentiation. + /// + public static GeneralContinuousDistribution FromDistribution(UnivariateContinuousDistribution distribution) + { + GeneralContinuousDistribution dist = new GeneralContinuousDistribution(); + dist.support = distribution.Support; + dist.pdf = distribution.ProbabilityDensityFunction; + dist.cdf = distribution.DistributionFunction; + return dist; + } + + /// + /// Creates a new + /// using only a probability density function definition. + /// + /// + /// A probability density function. + /// + /// A created from the + /// whose measures and functions are computed using + /// numerical integration and differentiation. + /// + public static GeneralContinuousDistribution FromDensityFunction(Func pdf) + { + var range = new DoubleRange(double.NegativeInfinity, double.PositiveInfinity); + var method = createDefaultIntegrationMethod(); + return FromDensityFunction(range, pdf, method); + } + + /// + /// Creates a new + /// using only a probability density function definition. + /// + /// + /// The distribution's support over the real line. + /// A probability density function. + /// + /// A created from the + /// whose measures and functions are computed using + /// numerical integration and differentiation. + /// + public static GeneralContinuousDistribution FromDensityFunction( + DoubleRange support, Func pdf) + { + var method = createDefaultIntegrationMethod(); + return FromDensityFunction(support, pdf, method); + } + + /// + /// Creates a new + /// using only a cumulative distribution function definition. + /// + /// + /// A cumulative distribution function. + /// + /// A created from the + /// whose measures and functions are computed using + /// numerical integration and differentiation. + /// + public static GeneralContinuousDistribution FromDistributionFunction(Func cdf) + { + var range = new DoubleRange(double.NegativeInfinity, double.PositiveInfinity); + var method = createDefaultIntegrationMethod(); + return FromDistributionFunction(range, cdf, method); + } + + /// + /// Creates a new + /// using only a cumulative distribution function definition. + /// + /// + /// The distribution's support over the real line. + /// A cumulative distribution function. + /// + /// A created from the + /// whose measures and functions are computed using + /// numerical integration and differentiation. + /// + public static GeneralContinuousDistribution FromDistributionFunction( + DoubleRange support, Func cdf) + { + var method = createDefaultIntegrationMethod(); + return FromDistributionFunction(support, cdf, method); + } + + /// + /// Creates a new + /// using only a probability density function definition. + /// + /// + /// The distribution's support over the real line. + /// A probability density function. + /// The integration method to use for numerical computations. + /// + /// A created from the + /// whose measures and functions are computed using + /// numerical integration and differentiation. + /// + public static GeneralContinuousDistribution FromDensityFunction( + DoubleRange support, Func pdf, IUnivariateIntegration method) + { + GeneralContinuousDistribution dist = new GeneralContinuousDistribution(); + dist.support = support; + dist.pdf = pdf; + dist.method = method; + return dist; + } + + /// + /// Creates a new + /// using only a cumulative distribution function definition. + /// + /// + /// The distribution's support over the real line. + /// A cumulative distribution function. + /// The integration method to use for numerical computations. + /// + /// A created from the + /// whose measures and functions are computed using + /// numerical integration and differentiation. + /// + public static GeneralContinuousDistribution FromDistributionFunction( + DoubleRange support, Func cdf, IUnivariateIntegration method) + { + GeneralContinuousDistribution dist = new GeneralContinuousDistribution(); + dist.support = support; + dist.cdf = cdf; + dist.method = method; + return dist; + } + + /// + /// Gets the support interval for this distribution. + /// + /// + /// + /// A containing + /// the support interval for this distribution. + /// + /// + public override DoubleRange Support + { + get { return support; } + } + + + /// + /// Gets the mean for this distribution. + /// + /// + /// The distribution's mean value. + /// + public override double Mean + { + get + { + if (mean == null) + { + method.Function = (x) => + { + double p = ProbabilityDensityFunction(x); + return x * p; + }; + + method.Range = support; + method.Compute(); + mean = method.Area; + } + + return mean.Value; + } + } + + /// + /// Gets the variance for this distribution. + /// + /// + /// The distribution's variance. + /// + public override double Variance + { + get + { + if (variance == null) + { + double u = Mean; + method.Function = (x) => (x * x) * ProbabilityDensityFunction(x); + method.Range = support; + method.Compute(); + variance = method.Area - u * u; + } + + return variance.Value; + } + } + + /// + /// Gets the entropy for this distribution. + /// + /// + /// The distribution's entropy. + /// + public override double Entropy + { + get + { + if (entropy == null) + { + method.Function = (x) => ProbabilityDensityFunction(x) * LogProbabilityDensityFunction(x); + method.Range = support; + method.Compute(); + entropy = method.Area; + } + + return entropy.Value; + } + } + + /// + /// Gets the mode for this distribution. + /// + /// + /// + /// The distribution's mode value. + /// + /// + public override double Mode + { + get + { + if (mode == null) + { + var range = GetRange(0.99); + double lower = range.Min; + double upper = range.Max; + mode = BrentSearch.Maximize(ProbabilityDensityFunction, lower, upper); + } + + return mode.Value; + } + } + + /// + /// Gets the cumulative distribution function (cdf) for + /// this distribution evaluated at point x. + /// + /// + /// A single point in the distribution range. + /// + public override double DistributionFunction(double x) + { + if (cdf != null) + return cdf(x); + + method.Function = pdf; + method.Range = new DoubleRange(Double.NegativeInfinity, x); + method.Compute(); + return method.Area; + } + + /// + /// Gets the probability density function (pdf) for + /// this distribution evaluated at point x. + /// + /// + /// A single point in the distribution range. + /// + /// + /// The probability of x occurring + /// in the current distribution. + /// + /// + public override double ProbabilityDensityFunction(double x) + { + if (pdf != null) + return pdf(x); + + return FiniteDifferences.Derivative(cdf, x, 1, 1e-6); + } + + /// + /// Creates a new object that is a copy of the current instance. + /// + /// + /// + /// A new object that is a copy of this instance. + /// + /// + public override object Clone() + { + GeneralContinuousDistribution c = new GeneralContinuousDistribution(); + + c.pdf = pdf; + c.cdf = cdf; + c.method = (IUnivariateIntegration)method.Clone(); + + return c; + } + + /// + /// Returns a that represents this instance. + /// + /// + /// The format. + /// The format provider. + /// + /// + /// A that represents this instance. + /// + /// + public override string ToString(string format, IFormatProvider formatProvider) + { + return String.Format(formatProvider, "Continuous(x)"); + } + + private GeneralContinuousDistribution() + { + } + + + private static InfiniteAdaptiveGaussKronrod createDefaultIntegrationMethod() + { + var method = new InfiniteAdaptiveGaussKronrod(100); + method.ToleranceRelative = 1e-5; + return method; + } + } +} diff --git a/Sources/Accord.Statistics/Distributions/Univariate/Continuous/GeneralizedBetaDistribution.cs b/Sources/Accord.Statistics/Distributions/Univariate/Continuous/GeneralizedBetaDistribution.cs index dd740305d..a79fd0cd5 100644 --- a/Sources/Accord.Statistics/Distributions/Univariate/Continuous/GeneralizedBetaDistribution.cs +++ b/Sources/Accord.Statistics/Distributions/Univariate/Continuous/GeneralizedBetaDistribution.cs @@ -982,7 +982,7 @@ private static double GetVariance(double[] observations, int[] weights, double m /// public override double[] Generate(int samples) { - return Random(min, max, alpha, beta, samples); + return Random(alpha, beta, min, max, samples); } /// @@ -993,7 +993,7 @@ public override double[] Generate(int samples) /// public override double Generate() { - return Random(min, max, alpha, beta); + return Random(alpha, beta, min, max); } /// diff --git a/Sources/Accord.Statistics/Distributions/Univariate/Continuous/KumaraswamyDistribution.cs b/Sources/Accord.Statistics/Distributions/Univariate/Continuous/KumaraswamyDistribution.cs index cf472cbca..78671bae1 100644 --- a/Sources/Accord.Statistics/Distributions/Univariate/Continuous/KumaraswamyDistribution.cs +++ b/Sources/Accord.Statistics/Distributions/Univariate/Continuous/KumaraswamyDistribution.cs @@ -1,114 +1,114 @@ -// Accord Statistics Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © Ashley Messer, 2014 -// glyphard 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.Statistics.Distributions.Univariate.Continuous -{ - - using System; - using Accord.Math; - using AForge; - - /// - /// Kumaraswamy distribution. - /// - /// - /// - /// - /// In probability and statistics, the Kumaraswamy's double bounded distribution is a - /// family of continuous probability distributions defined on the interval [0,1] differing - /// in the values of their two non-negative shape parameters, a and b. - /// It is similar to the Beta distribution, but much simpler to use especially in simulation - /// studies due to the simple closed form of both its probability density function and - /// cumulative distribution function. This distribution was originally proposed by Poondi - /// Kumaraswamy for variables that are lower and upper bounded. - /// - /// - /// A good example of the use of the Kumaraswamy distribution is the storage volume of a - /// reservoir of capacity zmax whose upper bound is zmax and lower - /// bound is 0 (Fletcher and Ponnambalam, 1996). - /// - /// - /// - /// References: - /// - /// - /// Wikipedia, The Free Encyclopedia. Kumaraswamy distribution. Available on: - /// http://en.wikipedia.org/wiki/Kumaraswamy_distribution - /// - /// - /// - /// - /// - /// The following example shows how to create and test the main characteristics - /// of an Kumaraswamy distribution given its two non-negative shape parameters: - /// - /// - /// // Create a new Kumaraswamy distribution with shape (4,2) - /// var kumaraswamy = new KumaraswamyDistribution(a: 4, b: 2); - /// - /// double mean = kumaraswamy.Mean; // 0.71111111111111114 - /// double median = kumaraswamy.Median; // 0.73566031573423674 - /// double mode = kumaraswamy.Mode; // 0.80910671157022118 - /// double var = kumaraswamy.Variance; // 0.027654320987654302 - /// - /// double cdf = kumaraswamy.DistributionFunction(x: 0.4); // 0.050544639999999919 - /// double pdf = kumaraswamy.ProbabilityDensityFunction(x: 0.4); // 0.49889280000000014 - /// double lpdf = kumaraswamy.LogProbabilityDensityFunction(x: 0.4); // -0.69536403596913343 - /// - /// double ccdf = kumaraswamy.ComplementaryDistributionFunction(x: 0.4); // 0.94945536000000008 - /// double icdf = kumaraswamy.InverseDistributionFunction(p: cdf); // 0.40000011480618253 - /// - /// double hf = kumaraswamy.HazardFunction(x: 0.4); // 0.52545155993431869 - /// double chf = kumaraswamy.CumulativeHazardFunction(x: 0.4); // 0.051866764053008864 - /// - /// string str = kumaraswamy.ToString(CultureInfo.InvariantCulture); // Kumaraswamy(x; a = 4, b = 2) - /// - /// - /// - [Serializable] - public class KumaraswamyDistribution : UnivariateContinuousDistribution - { - double a; - double b; - - /// - /// Constructs a new Kumaraswamy's double bounded distribution with - /// the given two non-negative shape parameters a and b. - /// - /// - /// The distribution's non-negative shape parameter a. - /// The distribution's non-negative shape parameter b. - /// - public KumaraswamyDistribution([Positive] double a, [Positive] double b) - { - if (a <= 0) - throw new ArgumentOutOfRangeException("a", "The shape parameter a must be positive."); - - if (b < 0) - throw new ArgumentOutOfRangeException("b", "The shape parameter b must be positive."); - - this.a = a; - this.b = b; +// Accord Statistics Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © Ashley Messer, 2014 +// glyphard 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.Statistics.Distributions.Univariate +{ + + using System; + using Accord.Math; + using AForge; + + /// + /// Kumaraswamy distribution. + /// + /// + /// + /// + /// In probability and statistics, the Kumaraswamy's double bounded distribution is a + /// family of continuous probability distributions defined on the interval [0,1] differing + /// in the values of their two non-negative shape parameters, a and b. + /// It is similar to the Beta distribution, but much simpler to use especially in simulation + /// studies due to the simple closed form of both its probability density function and + /// cumulative distribution function. This distribution was originally proposed by Poondi + /// Kumaraswamy for variables that are lower and upper bounded. + /// + /// + /// A good example of the use of the Kumaraswamy distribution is the storage volume of a + /// reservoir of capacity zmax whose upper bound is zmax and lower + /// bound is 0 (Fletcher and Ponnambalam, 1996). + /// + /// + /// + /// References: + /// + /// + /// Wikipedia, The Free Encyclopedia. Kumaraswamy distribution. Available on: + /// http://en.wikipedia.org/wiki/Kumaraswamy_distribution + /// + /// + /// + /// + /// + /// The following example shows how to create and test the main characteristics + /// of an Kumaraswamy distribution given its two non-negative shape parameters: + /// + /// + /// // Create a new Kumaraswamy distribution with shape (4,2) + /// var kumaraswamy = new KumaraswamyDistribution(a: 4, b: 2); + /// + /// double mean = kumaraswamy.Mean; // 0.71111111111111114 + /// double median = kumaraswamy.Median; // 0.73566031573423674 + /// double mode = kumaraswamy.Mode; // 0.80910671157022118 + /// double var = kumaraswamy.Variance; // 0.027654320987654302 + /// + /// double cdf = kumaraswamy.DistributionFunction(x: 0.4); // 0.050544639999999919 + /// double pdf = kumaraswamy.ProbabilityDensityFunction(x: 0.4); // 0.49889280000000014 + /// double lpdf = kumaraswamy.LogProbabilityDensityFunction(x: 0.4); // -0.69536403596913343 + /// + /// double ccdf = kumaraswamy.ComplementaryDistributionFunction(x: 0.4); // 0.94945536000000008 + /// double icdf = kumaraswamy.InverseDistributionFunction(p: cdf); // 0.40000011480618253 + /// + /// double hf = kumaraswamy.HazardFunction(x: 0.4); // 0.52545155993431869 + /// double chf = kumaraswamy.CumulativeHazardFunction(x: 0.4); // 0.051866764053008864 + /// + /// string str = kumaraswamy.ToString(CultureInfo.InvariantCulture); // Kumaraswamy(x; a = 4, b = 2) + /// + /// + /// + [Serializable] + public class KumaraswamyDistribution : UnivariateContinuousDistribution + { + double a; + double b; + + /// + /// Constructs a new Kumaraswamy's double bounded distribution with + /// the given two non-negative shape parameters a and b. + /// + /// + /// The distribution's non-negative shape parameter a. + /// The distribution's non-negative shape parameter b. + /// + public KumaraswamyDistribution([Positive] double a, [Positive] double b) + { + if (a <= 0) + throw new ArgumentOutOfRangeException("a", "The shape parameter a must be positive."); + + if (b < 0) + throw new ArgumentOutOfRangeException("b", "The shape parameter b must be positive."); + + this.a = a; + this.b = b; } /// @@ -120,194 +120,194 @@ public KumaraswamyDistribution([Positive] double a, [Positive] double b) /// /// Gets the distribution's non-negative shape parameter b. /// - /// - public double B { get { return b; } } - - /// - /// Gets the mean for this distribution. - /// - /// - /// - /// The distribution's mean value. - /// - /// - public override double Mean - { - get - { - double num = b * Gamma.Function(1 + (1 / a)) * Gamma.Function(b); - double den = Gamma.Function(1 + (1 / a) + b); - - return num / den; - } - } - - /// - /// Gets the variance for this distribution. - /// - /// - /// - /// The distribution's variance. - /// - /// - public override double Variance - { - get - { - double alpha = momentGeneratingFunction(2, a, b); - double beta = Math.Pow(momentGeneratingFunction(1, a, b), 2); - return alpha - beta; - } - } - - private static double momentGeneratingFunction(int n, double a, double b) - { - return (b * Beta.Function(1.0d + ((double)n) / a, b)); - } - - /// - /// Gets the median for this distribution. - /// - /// - /// - /// The distribution's median value. - /// - /// - public override double Median - { - get - { - return Math.Pow(1 - Math.Pow(2, -1 / b), 1 / a); - } - } - - /// - /// Gets the mode for this distribution. - /// - /// - /// - /// The distribution's mode value. - /// - /// - public override double Mode - { - get - { - - if ((a >= 1) && (b >= 1) && (a != 1 && b != 1)) - { - double num = a - 1; - double den = a * b - 1; - return Math.Pow(num / den, 1 / a); - } - - return Double.NaN; - } - } - - - /// - /// Not supported. - /// - /// - public override double Entropy - { - get { return double.NaN; } - } - - /// - /// Gets the support interval for this distribution. - /// - /// - /// - /// A containing - /// the support interval for this distribution. - /// - /// - public override DoubleRange Support - { - get { return new DoubleRange(0, 1); } - } - - /// - /// Gets the cumulative distribution function (cdf) for - /// this distribution evaluated at point x. - /// - /// - /// A single point in the distribution range. - /// - /// - /// The Cumulative Distribution Function (CDF) describes the cumulative - /// probability that a given value or any value smaller than it will occur. - /// - /// - public override double DistributionFunction(double x) - { - if (x > 1) - return 1; - - if (x < 0) - return 0; - - double xa = Math.Pow(x, a); - return 1 - Math.Pow(1 - xa, b); - } - - /// - /// Gets the probability density function (pdf) for - /// this distribution evaluated at point x. - /// - /// - /// A single point in the distribution range. - /// - /// - /// The probability of x occurring - /// in the current distribution. - /// - /// - /// - /// The Probability Density Function (PDF) describes the - /// probability that a given value x will occur. - /// - /// - public override double ProbabilityDensityFunction(double x) - { - if (x > 1) - return 0; - - if (x < 0) - return 0; - - return a * b * Math.Pow(x, a - 1) * Math.Pow(1 - Math.Pow(x, a), b - 1); - } - - /// - /// Creates a new object that is a copy of the current instance. - /// - /// - /// - /// A new object that is a copy of this instance. - /// - /// - public override object Clone() - { - return new KumaraswamyDistribution(this.a, this.b); - } - - /// - /// Returns a that represents this instance. - /// - /// - /// - /// A that represents this instance. - /// - /// - public override string ToString(string format, IFormatProvider formatProvider) - { - return String.Format(formatProvider, "Kumaraswamy(x; a = {0}, b = {1})", - a.ToString(format, formatProvider), - b.ToString(format, formatProvider)); - } - - } -} + /// + public double B { get { return b; } } + + /// + /// Gets the mean for this distribution. + /// + /// + /// + /// The distribution's mean value. + /// + /// + public override double Mean + { + get + { + double num = b * Gamma.Function(1 + (1 / a)) * Gamma.Function(b); + double den = Gamma.Function(1 + (1 / a) + b); + + return num / den; + } + } + + /// + /// Gets the variance for this distribution. + /// + /// + /// + /// The distribution's variance. + /// + /// + public override double Variance + { + get + { + double alpha = momentGeneratingFunction(2, a, b); + double beta = Math.Pow(momentGeneratingFunction(1, a, b), 2); + return alpha - beta; + } + } + + private static double momentGeneratingFunction(int n, double a, double b) + { + return (b * Beta.Function(1.0d + ((double)n) / a, b)); + } + + /// + /// Gets the median for this distribution. + /// + /// + /// + /// The distribution's median value. + /// + /// + public override double Median + { + get + { + return Math.Pow(1 - Math.Pow(2, -1 / b), 1 / a); + } + } + + /// + /// Gets the mode for this distribution. + /// + /// + /// + /// The distribution's mode value. + /// + /// + public override double Mode + { + get + { + + if ((a >= 1) && (b >= 1) && (a != 1 && b != 1)) + { + double num = a - 1; + double den = a * b - 1; + return Math.Pow(num / den, 1 / a); + } + + return Double.NaN; + } + } + + + /// + /// Not supported. + /// + /// + public override double Entropy + { + get { return double.NaN; } + } + + /// + /// Gets the support interval for this distribution. + /// + /// + /// + /// A containing + /// the support interval for this distribution. + /// + /// + public override DoubleRange Support + { + get { return new DoubleRange(0, 1); } + } + + /// + /// Gets the cumulative distribution function (cdf) for + /// this distribution evaluated at point x. + /// + /// + /// A single point in the distribution range. + /// + /// + /// The Cumulative Distribution Function (CDF) describes the cumulative + /// probability that a given value or any value smaller than it will occur. + /// + /// + public override double DistributionFunction(double x) + { + if (x > 1) + return 1; + + if (x < 0) + return 0; + + double xa = Math.Pow(x, a); + return 1 - Math.Pow(1 - xa, b); + } + + /// + /// Gets the probability density function (pdf) for + /// this distribution evaluated at point x. + /// + /// + /// A single point in the distribution range. + /// + /// + /// The probability of x occurring + /// in the current distribution. + /// + /// + /// + /// The Probability Density Function (PDF) describes the + /// probability that a given value x will occur. + /// + /// + public override double ProbabilityDensityFunction(double x) + { + if (x > 1) + return 0; + + if (x < 0) + return 0; + + return a * b * Math.Pow(x, a - 1) * Math.Pow(1 - Math.Pow(x, a), b - 1); + } + + /// + /// Creates a new object that is a copy of the current instance. + /// + /// + /// + /// A new object that is a copy of this instance. + /// + /// + public override object Clone() + { + return new KumaraswamyDistribution(this.a, this.b); + } + + /// + /// Returns a that represents this instance. + /// + /// + /// + /// A that represents this instance. + /// + /// + public override string ToString(string format, IFormatProvider formatProvider) + { + return String.Format(formatProvider, "Kumaraswamy(x; a = {0}, b = {1})", + a.ToString(format, formatProvider), + b.ToString(format, formatProvider)); + } + + } +} diff --git a/Sources/Accord.Statistics/Distributions/Univariate/Continuous/TrapezoidalDistribution.cs b/Sources/Accord.Statistics/Distributions/Univariate/Continuous/TrapezoidalDistribution.cs index 708e13535..f923b7ef2 100644 --- a/Sources/Accord.Statistics/Distributions/Univariate/Continuous/TrapezoidalDistribution.cs +++ b/Sources/Accord.Statistics/Distributions/Univariate/Continuous/TrapezoidalDistribution.cs @@ -1,407 +1,407 @@ -// Accord Statistics Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © Ashley Messer, 2014 -// glyphard 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.Statistics.Distributions.Univariate.Continuous -{ - using System; +// Accord Statistics Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © Ashley Messer, 2014 +// glyphard 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.Statistics.Distributions.Univariate +{ + using System; using AForge; - using System.ComponentModel; - - /// - /// Trapezoidal distribution. - /// - /// - /// - /// - /// Trapezoidal distributions have been used in many areas and studied under varying - /// scopes, such as in the excellent work of (van Dorp and Kotz, 2003), risk analysis - /// (Pouliquen, 1970) and (Powell and Wilson, 1997), fuzzy set theory (Chen and Hwang, - /// 1992), applied phyisics, and biomedical applications (Flehinger and Kimmel, 1987). - /// - /// - /// - /// Trapezoidal distributions are appropriate for modeling events that are comprised - /// by three different stages: one growth stage, where probability grows up until a - /// plateau is reached; a stability stage, where probability stays more or less the same; - /// and a decline stage, where probability decreases until zero (van Dorp and Kotz, 2003). - /// - /// - /// - /// References: - /// - /// - /// J. René van Dorp, Samuel Kotz, Trapezoidal distribution. Available on: - /// http://www.seas.gwu.edu/~dorpjr/Publications/JournalPapers/Metrika2003VanDorp.pdf - /// - /// Powell MR, Wilson JD (1997). Risk Assessment for National Natural Resource - /// Conservation Programs, Discussion Paper 97-49. Resources for the Future, Washington - /// D.C. - /// - /// Chen SJ, Hwang CL (1992). Fuzzy Multiple Attribute Decision-Making: Methods and - /// Applications, Springer-Verlag, Berlin, New York. - /// - /// Flehinger BJ, Kimmel M (1987). The natural history of lung cancer in periodically - /// screened population. Biometrics 1987, 43, 127-144. - /// - /// - /// - /// - /// - /// The following example shows how to create and test the main characteristics - /// of a Trapezoidal distribution given its parameters: - /// - /// - /// // Create a new trapezoidal distribution with linear growth between - /// // 0 and 2, stability between 2 and 8, and decrease between 8 and 10. - /// // - /// // - /// // +-----------+ - /// // /| |\ - /// // / | | \ - /// // / | | \ - /// // -------+---+-----------+---+------- - /// // ... 0 2 4 6 8 10 ... - /// // - /// var trapz = new TrapezoidalDistribution(a: 0, b: 2, c: 8, d: 10, n1: 1, n3: 1); - /// - /// double mean = trapz.Mean; // 2.25 - /// double median = trapz.Median; // 3.0 - /// double mode = trapz.Mode; // 3.1353457616424696 - /// double var = trapz.Variance; // 17.986666666666665 - /// - /// double cdf = trapz.DistributionFunction(x: 1.4); // 0.13999999999999999 - /// double pdf = trapz.ProbabilityDensityFunction(x: 1.4); // 0.10000000000000001 - /// double lpdf = trapz.LogProbabilityDensityFunction(x: 1.4); // -2.3025850929940455 - /// - /// double ccdf = trapz.ComplementaryDistributionFunction(x: 1.4); // 0.85999999999999999 - /// double icdf = trapz.InverseDistributionFunction(p: cdf); // 1.3999999999999997 - /// - /// double hf = trapz.HazardFunction(x: 1.4); // 0.11627906976744187 - /// double chf = trapz.CumulativeHazardFunction(x: 1.4); // 0.15082288973458366 - /// - /// string str = trapz.ToString(CultureInfo.InvariantCulture); // Trapezoidal(x; a=0, b=2, c=8, d=10, n1=1, n3=1, α = 1) - /// - /// - /// - [Serializable] - public class TrapezoidalDistribution : UnivariateContinuousDistribution - { - // distribution parameters - double a; // left bottom boundary - double b; // left top boundary - double c; // right top boundary - double d; // right bottom boundary - double n1; // growth rate - double n3; // decay rate - - double alpha = 1; - - // derived measures - double constant; - - - /// - /// Creates a new trapezoidal distribution. - /// - /// - /// The minimum value a. - /// The beginning of the stability region b. - /// The end of the stability region c. - /// The maximum value d. - /// The growth slope between points and . - /// The growth slope between points and . - /// - public TrapezoidalDistribution( + using System.ComponentModel; + + /// + /// Trapezoidal distribution. + /// + /// + /// + /// + /// Trapezoidal distributions have been used in many areas and studied under varying + /// scopes, such as in the excellent work of (van Dorp and Kotz, 2003), risk analysis + /// (Pouliquen, 1970) and (Powell and Wilson, 1997), fuzzy set theory (Chen and Hwang, + /// 1992), applied phyisics, and biomedical applications (Flehinger and Kimmel, 1987). + /// + /// + /// + /// Trapezoidal distributions are appropriate for modeling events that are comprised + /// by three different stages: one growth stage, where probability grows up until a + /// plateau is reached; a stability stage, where probability stays more or less the same; + /// and a decline stage, where probability decreases until zero (van Dorp and Kotz, 2003). + /// + /// + /// + /// References: + /// + /// + /// J. René van Dorp, Samuel Kotz, Trapezoidal distribution. Available on: + /// http://www.seas.gwu.edu/~dorpjr/Publications/JournalPapers/Metrika2003VanDorp.pdf + /// + /// Powell MR, Wilson JD (1997). Risk Assessment for National Natural Resource + /// Conservation Programs, Discussion Paper 97-49. Resources for the Future, Washington + /// D.C. + /// + /// Chen SJ, Hwang CL (1992). Fuzzy Multiple Attribute Decision-Making: Methods and + /// Applications, Springer-Verlag, Berlin, New York. + /// + /// Flehinger BJ, Kimmel M (1987). The natural history of lung cancer in periodically + /// screened population. Biometrics 1987, 43, 127-144. + /// + /// + /// + /// + /// + /// The following example shows how to create and test the main characteristics + /// of a Trapezoidal distribution given its parameters: + /// + /// + /// // Create a new trapezoidal distribution with linear growth between + /// // 0 and 2, stability between 2 and 8, and decrease between 8 and 10. + /// // + /// // + /// // +-----------+ + /// // /| |\ + /// // / | | \ + /// // / | | \ + /// // -------+---+-----------+---+------- + /// // ... 0 2 4 6 8 10 ... + /// // + /// var trapz = new TrapezoidalDistribution(a: 0, b: 2, c: 8, d: 10, n1: 1, n3: 1); + /// + /// double mean = trapz.Mean; // 2.25 + /// double median = trapz.Median; // 3.0 + /// double mode = trapz.Mode; // 3.1353457616424696 + /// double var = trapz.Variance; // 17.986666666666665 + /// + /// double cdf = trapz.DistributionFunction(x: 1.4); // 0.13999999999999999 + /// double pdf = trapz.ProbabilityDensityFunction(x: 1.4); // 0.10000000000000001 + /// double lpdf = trapz.LogProbabilityDensityFunction(x: 1.4); // -2.3025850929940455 + /// + /// double ccdf = trapz.ComplementaryDistributionFunction(x: 1.4); // 0.85999999999999999 + /// double icdf = trapz.InverseDistributionFunction(p: cdf); // 1.3999999999999997 + /// + /// double hf = trapz.HazardFunction(x: 1.4); // 0.11627906976744187 + /// double chf = trapz.CumulativeHazardFunction(x: 1.4); // 0.15082288973458366 + /// + /// string str = trapz.ToString(CultureInfo.InvariantCulture); // Trapezoidal(x; a=0, b=2, c=8, d=10, n1=1, n3=1, α = 1) + /// + /// + /// + [Serializable] + public class TrapezoidalDistribution : UnivariateContinuousDistribution + { + // distribution parameters + double a; // left bottom boundary + double b; // left top boundary + double c; // right top boundary + double d; // right bottom boundary + double n1; // growth rate + double n3; // decay rate + + double alpha = 1; + + // derived measures + double constant; + + + /// + /// Creates a new trapezoidal distribution. + /// + /// + /// The minimum value a. + /// The beginning of the stability region b. + /// The end of the stability region c. + /// The maximum value d. + /// The growth slope between points and . + /// The growth slope between points and . + /// + public TrapezoidalDistribution( [Real, DefaultValue(0)] double a, [Real, DefaultValue(1)] double b, - [Real, DefaultValue(2)] double c, [Real, DefaultValue(3)] double d, - [Positive] double n1, [Positive] double n3) - { - // boundary validation - if (a > b) - throw new ArgumentOutOfRangeException("b", "Argument b must be higher than a."); - - if (b > c) - throw new ArgumentOutOfRangeException("c", "Argument c must be higher than b."); - - if (d < c) + [Real, DefaultValue(2)] double c, [Real, DefaultValue(3)] double d, + [Positive] double n1, [Positive] double n3) + { + // boundary validation + if (a > b) + throw new ArgumentOutOfRangeException("b", "Argument b must be higher than a."); + + if (b > c) + throw new ArgumentOutOfRangeException("c", "Argument c must be higher than b."); + + if (d < c) throw new ArgumentOutOfRangeException("d", "Argument d must be higher than c."); if (d <= a) - throw new ArgumentOutOfRangeException("d", "The maximum value d must be higher than the minimum value a"); - - if (n1 <= 0) - throw new ArgumentOutOfRangeException("n1", "Slope n1 must be positive."); - - if (n3 <= 0) - throw new ArgumentOutOfRangeException("n3", "Slope n3 must be positive."); - - this.a = a; - this.b = b; - this.c = c; - this.d = d; - this.n1 = n1; - this.n3 = n3; - - double num = 2 * n1 * n3; - double den = 2 * alpha * (b - a) * n3 - + (alpha + 1) * (c - b) * n1 * n3 - + 2 * (d - c) * n1; - - this.constant = num / den; - } - - /// - /// Gets the mean for this distribution. - /// - /// - /// - /// The distribution's mean value. - /// - /// - public override double Mean - { - get - { - double expectationX1 = (a + n1 * b) / (n1 + 1); - double expectationX3 = (n3 * c + d) / (n3 + 1); - - double num = (-2 / 3.0) * (alpha - 1) * (Math.Pow(c, 3) - - Math.Pow(b, 3)) + (alpha * c - b) * (Math.Pow(c, 2) - Math.Pow(b, 2)); - double den = Math.Pow(c - b, 2) * (alpha + 1); - - double expectationX2 = num / den; - - - num = (2 * alpha * (b - a) * n3 * expectationX1) - + (n1 * n3 * (expectationX2)) - + (2 * (d - c) * n1 * expectationX3); - - den = (2 * alpha * (b - a) * n3) - + ((alpha + 1) * (c - b) * n1 * n3) - + (2 * (d - c) * n1); - - return num / den; - } - } - - /// - /// Gets the variance for this distribution. - /// - /// - /// - /// The distribution's variance. - /// - /// - public override double Variance - { - get - { - double expectationX1_2; - double expectationX2_2; - double expectationX3_2; - - { - double num = 2 * a * a + 2 * n1 * a * b + n1 * (n1 + 1) * b * b; - double den = (n1 + 2) + (n1 + 1); - expectationX1_2 = num / den; - } - - { - double num = -0.5 * (alpha - 1) * (Math.Pow(c, 4) - Math.Pow(b, 4)) - + (2 / 3.0) * (alpha * c - b) * (Math.Pow(c, 3) - - Math.Pow(b, 3)); - - double den = Math.Pow(c - b, 2) * (alpha + 1); - expectationX2_2 = num / den; - } - - { - double num = 2 * d * d + 2 * n3 * c * d + n3 * (n3 + 1) * c * c; - double den = (n3 + 2) * (n3 + 1); - expectationX3_2 = num / den; - } - - double x = (2 * alpha * (b - a) * n3) - / (2 * alpha * (b - a) * n3 + (alpha + 1) * (c - b) * n1 * n3 + 2 * (d - c) * n1); - - double y = (n1 * n3) - / (2 * alpha * (b - a) * n3 + (alpha + 1) * (c - b) * n1 * n3 + 2 * (d - c) * n1); - - double z = (2 * (d - c) * n1) - / (2 * alpha * (b - a) * n3 + (alpha + 1) * (c - b) * n1 * n3 + 2 * (d - c) * n1); - - - return x * expectationX1_2 + y * expectationX2_2 + z * expectationX3_2; - } - } - - /// - /// Not supported. - /// - /// - public override double Entropy - { - get { return double.NaN; } - } - - - /// - /// Gets the support interval for this distribution. - /// - /// - /// - /// A containing - /// the support interval for this distribution. - /// - /// - public override DoubleRange Support - { - get { return new DoubleRange(a, d); } - } - - /// - /// Gets the cumulative distribution function (cdf) for - /// this distribution evaluated at point x. - /// - /// - /// A single point in the distribution range. - /// - /// - /// The Cumulative Distribution Function (CDF) describes the cumulative - /// probability that a given value or any value smaller than it will occur. - /// - /// - public override double DistributionFunction(double x) - { - if (x < a) - return 0; - - if (x > d) - return 1; - - if (x < b) - { - double num = 2 * alpha * (b - a) * n3; - double den = 2 * alpha * (b - a) * n3 - + (alpha + 1) * (c - b) * n1 * n3 - + 2 * (d - c) * n1; - - return (num / den) * Math.Pow((x - a) / (b - a), n1); - } - - if (x < c) - { - double num = 2 * alpha * (b - a) * n3 - + 2 * (x - b) * n1 * n3 * (1 + ((alpha - 1) * (2 * c - b - x)) / (2 * (c - b))); - - double den = 2 * alpha * (b - a) * n3 - + (alpha + 1) * (c - b) * n1 * n3 - + 2 * (c - d) * n1; - - return num / den; - } - - if (x < d) - { - double num = 2 * (c - d) * n1; - double den = 2 * alpha * (b - a) * n3 - + (alpha + 1) * (c - b) * n1 * n3 - + 2 * (c - d) * n1; - - return 1 - num / den * Math.Pow((d - x) / (d - c), n3); - } - - return 1; - } - - /// - /// Gets the probability density function (pdf) for - /// this distribution evaluated at point x. - /// - /// - /// A single point in the distribution range. - /// - /// - /// The probability of x occurring - /// in the current distribution. - /// - /// - /// - /// The Probability Density Function (PDF) describes the - /// probability that a given value x will occur. - /// - /// - public override double ProbabilityDensityFunction(double x) - { - if (x < a) - return 0; - - if (x > d) - return 0; - - if (x < b) - return constant * alpha * Math.Pow((x - a) / (b - a), n1 - 1); - - if (x < c) - return constant * (((alpha - 1) * (c - x) / (c - b)) + 1); - - if (x < d) - return constant * Math.Pow((d - x) / (d - c), n3 - 1); - - return 0; - } - - - /// - /// Creates a new object that is a copy of the current instance. - /// - /// - /// - /// A new object that is a copy of this instance. - /// - /// - public override object Clone() - { - return new TrapezoidalDistribution(a, b, c, d, n1, n3); - } - - - /// - /// Returns a that represents this instance. - /// - /// - /// - /// A that represents this instance. - /// - /// - public override string ToString(string format, IFormatProvider formatProvider) - { - return String.Format("Trapezoidal(x; a = {0}, b = {1}, c = {2}, d = {3}, n1 = {4}, n3 = {5}, α = {6})", - a.ToString(format, formatProvider), - b.ToString(format, formatProvider), - c.ToString(format, formatProvider), - d.ToString(format, formatProvider), - n1.ToString(format, formatProvider), - n3.ToString(format, formatProvider), - alpha.ToString(format, formatProvider)); - } - } -} + throw new ArgumentOutOfRangeException("d", "The maximum value d must be higher than the minimum value a"); + + if (n1 <= 0) + throw new ArgumentOutOfRangeException("n1", "Slope n1 must be positive."); + + if (n3 <= 0) + throw new ArgumentOutOfRangeException("n3", "Slope n3 must be positive."); + + this.a = a; + this.b = b; + this.c = c; + this.d = d; + this.n1 = n1; + this.n3 = n3; + + double num = 2 * n1 * n3; + double den = 2 * alpha * (b - a) * n3 + + (alpha + 1) * (c - b) * n1 * n3 + + 2 * (d - c) * n1; + + this.constant = num / den; + } + + /// + /// Gets the mean for this distribution. + /// + /// + /// + /// The distribution's mean value. + /// + /// + public override double Mean + { + get + { + double expectationX1 = (a + n1 * b) / (n1 + 1); + double expectationX3 = (n3 * c + d) / (n3 + 1); + + double num = (-2 / 3.0) * (alpha - 1) * (Math.Pow(c, 3) + - Math.Pow(b, 3)) + (alpha * c - b) * (Math.Pow(c, 2) - Math.Pow(b, 2)); + double den = Math.Pow(c - b, 2) * (alpha + 1); + + double expectationX2 = num / den; + + + num = (2 * alpha * (b - a) * n3 * expectationX1) + + (n1 * n3 * (expectationX2)) + + (2 * (d - c) * n1 * expectationX3); + + den = (2 * alpha * (b - a) * n3) + + ((alpha + 1) * (c - b) * n1 * n3) + + (2 * (d - c) * n1); + + return num / den; + } + } + + /// + /// Gets the variance for this distribution. + /// + /// + /// + /// The distribution's variance. + /// + /// + public override double Variance + { + get + { + double expectationX1_2; + double expectationX2_2; + double expectationX3_2; + + { + double num = 2 * a * a + 2 * n1 * a * b + n1 * (n1 + 1) * b * b; + double den = (n1 + 2) + (n1 + 1); + expectationX1_2 = num / den; + } + + { + double num = -0.5 * (alpha - 1) * (Math.Pow(c, 4) - Math.Pow(b, 4)) + + (2 / 3.0) * (alpha * c - b) * (Math.Pow(c, 3) + - Math.Pow(b, 3)); + + double den = Math.Pow(c - b, 2) * (alpha + 1); + expectationX2_2 = num / den; + } + + { + double num = 2 * d * d + 2 * n3 * c * d + n3 * (n3 + 1) * c * c; + double den = (n3 + 2) * (n3 + 1); + expectationX3_2 = num / den; + } + + double x = (2 * alpha * (b - a) * n3) + / (2 * alpha * (b - a) * n3 + (alpha + 1) * (c - b) * n1 * n3 + 2 * (d - c) * n1); + + double y = (n1 * n3) + / (2 * alpha * (b - a) * n3 + (alpha + 1) * (c - b) * n1 * n3 + 2 * (d - c) * n1); + + double z = (2 * (d - c) * n1) + / (2 * alpha * (b - a) * n3 + (alpha + 1) * (c - b) * n1 * n3 + 2 * (d - c) * n1); + + + return x * expectationX1_2 + y * expectationX2_2 + z * expectationX3_2; + } + } + + /// + /// Not supported. + /// + /// + public override double Entropy + { + get { return double.NaN; } + } + + + /// + /// Gets the support interval for this distribution. + /// + /// + /// + /// A containing + /// the support interval for this distribution. + /// + /// + public override DoubleRange Support + { + get { return new DoubleRange(a, d); } + } + + /// + /// Gets the cumulative distribution function (cdf) for + /// this distribution evaluated at point x. + /// + /// + /// A single point in the distribution range. + /// + /// + /// The Cumulative Distribution Function (CDF) describes the cumulative + /// probability that a given value or any value smaller than it will occur. + /// + /// + public override double DistributionFunction(double x) + { + if (x < a) + return 0; + + if (x > d) + return 1; + + if (x < b) + { + double num = 2 * alpha * (b - a) * n3; + double den = 2 * alpha * (b - a) * n3 + + (alpha + 1) * (c - b) * n1 * n3 + + 2 * (d - c) * n1; + + return (num / den) * Math.Pow((x - a) / (b - a), n1); + } + + if (x < c) + { + double num = 2 * alpha * (b - a) * n3 + + 2 * (x - b) * n1 * n3 * (1 + ((alpha - 1) * (2 * c - b - x)) / (2 * (c - b))); + + double den = 2 * alpha * (b - a) * n3 + + (alpha + 1) * (c - b) * n1 * n3 + + 2 * (c - d) * n1; + + return num / den; + } + + if (x < d) + { + double num = 2 * (c - d) * n1; + double den = 2 * alpha * (b - a) * n3 + + (alpha + 1) * (c - b) * n1 * n3 + + 2 * (c - d) * n1; + + return 1 - num / den * Math.Pow((d - x) / (d - c), n3); + } + + return 1; + } + + /// + /// Gets the probability density function (pdf) for + /// this distribution evaluated at point x. + /// + /// + /// A single point in the distribution range. + /// + /// + /// The probability of x occurring + /// in the current distribution. + /// + /// + /// + /// The Probability Density Function (PDF) describes the + /// probability that a given value x will occur. + /// + /// + public override double ProbabilityDensityFunction(double x) + { + if (x < a) + return 0; + + if (x > d) + return 0; + + if (x < b) + return constant * alpha * Math.Pow((x - a) / (b - a), n1 - 1); + + if (x < c) + return constant * (((alpha - 1) * (c - x) / (c - b)) + 1); + + if (x < d) + return constant * Math.Pow((d - x) / (d - c), n3 - 1); + + return 0; + } + + + /// + /// Creates a new object that is a copy of the current instance. + /// + /// + /// + /// A new object that is a copy of this instance. + /// + /// + public override object Clone() + { + return new TrapezoidalDistribution(a, b, c, d, n1, n3); + } + + + /// + /// Returns a that represents this instance. + /// + /// + /// + /// A that represents this instance. + /// + /// + public override string ToString(string format, IFormatProvider formatProvider) + { + return String.Format("Trapezoidal(x; a = {0}, b = {1}, c = {2}, d = {3}, n1 = {4}, n3 = {5}, α = {6})", + a.ToString(format, formatProvider), + b.ToString(format, formatProvider), + c.ToString(format, formatProvider), + d.ToString(format, formatProvider), + n1.ToString(format, formatProvider), + n3.ToString(format, formatProvider), + alpha.ToString(format, formatProvider)); + } + } +} diff --git a/Sources/Accord.Statistics/Distributions/Univariate/Continuous/UQuadraticDistribution.cs b/Sources/Accord.Statistics/Distributions/Univariate/Continuous/UQuadraticDistribution.cs index 9a7cd9006..29e4419db 100644 --- a/Sources/Accord.Statistics/Distributions/Univariate/Continuous/UQuadraticDistribution.cs +++ b/Sources/Accord.Statistics/Distributions/Univariate/Continuous/UQuadraticDistribution.cs @@ -20,7 +20,7 @@ // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // -namespace Accord.Statistics.Distributions.Univariate.Continuous +namespace Accord.Statistics.Distributions.Univariate { using System; using Accord.Math; diff --git a/Sources/Accord.Statistics/Distributions/Univariate/Continuous/WrappedCauchyDistribution.cs b/Sources/Accord.Statistics/Distributions/Univariate/Continuous/WrappedCauchyDistribution.cs index 4a2cf3893..9c60a5282 100644 --- a/Sources/Accord.Statistics/Distributions/Univariate/Continuous/WrappedCauchyDistribution.cs +++ b/Sources/Accord.Statistics/Distributions/Univariate/Continuous/WrappedCauchyDistribution.cs @@ -25,7 +25,8 @@ namespace Accord.Statistics.Distributions.Univariate using System; using Accord.Statistics.Distributions.Fitting; using AForge; - using AForge.Math; + using AForge.Math; + using System.Numerics; /// /// Wrapped Cauchy Distribution. diff --git a/Sources/Accord.Statistics/Distributions/Univariate/Mixture`1.cs b/Sources/Accord.Statistics/Distributions/Univariate/Mixture`1.cs index 77e70389c..6f059bf03 100644 --- a/Sources/Accord.Statistics/Distributions/Univariate/Mixture`1.cs +++ b/Sources/Accord.Statistics/Distributions/Univariate/Mixture`1.cs @@ -709,10 +709,9 @@ public override string ToString(string format, IFormatProvider formatProvider) for (int i = 0; i < coefficients.Length; i++) { - sb.AppendFormat("{0}*", - coefficients[0].ToString(format, formatProvider)); + sb.AppendFormat("{0}*", coefficients[i].ToString(format, formatProvider)); - var fmt = components[1] as IFormattable; + var fmt = components[i] as IFormattable; if (fmt != null) sb.AppendFormat(fmt.ToString(format, formatProvider)); diff --git a/Sources/Accord.Statistics/Group.cs b/Sources/Accord.Statistics/Group.cs index 7f1255bf3..7473ee909 100644 --- a/Sources/Accord.Statistics/Group.cs +++ b/Sources/Accord.Statistics/Group.cs @@ -179,6 +179,12 @@ public static T[][] Group(T[] values, int[] labels, int groups) /// public static int[][] Expand(int[] data, int[] positives, int[] negatives) { + if (data.Length != positives.Length) + throw new DimensionMismatchException(); + + if (positives.Length != negatives.Length) + throw new DimensionMismatchException(); + List rows = new List(); for (int i = 0; i < data.Length; i++) diff --git a/Sources/Accord.Statistics/Kernels/Linear.cs b/Sources/Accord.Statistics/Kernels/Linear.cs index c34d4bce5..389f2161e 100644 --- a/Sources/Accord.Statistics/Kernels/Linear.cs +++ b/Sources/Accord.Statistics/Kernels/Linear.cs @@ -53,7 +53,7 @@ public Linear() : this(0) { } /// - /// Gets or sets the kernel's intercept term. + /// Gets or sets the kernel's intercept term. Default is 0. /// /// public double Constant @@ -147,7 +147,7 @@ public double ReverseDistance(double[] x, double[] y) } - + /// /// Creates a new object that is a copy of the current instance. /// diff --git a/Sources/Accord.Statistics/Kernels/NormalizedPolynomial.cs b/Sources/Accord.Statistics/Kernels/NormalizedPolynomial.cs new file mode 100644 index 0000000000..f479e7f4c --- /dev/null +++ b/Sources/Accord.Statistics/Kernels/NormalizedPolynomial.cs @@ -0,0 +1,128 @@ +// Accord Statistics Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Statistics.Kernels +{ + using System; + using Accord.Math; + + /// + /// Normalized Polynomial Kernel. This class is equivalent to the + /// Normalized>Polynomial> kernel but has more efficient + /// implementation. + /// + /// + [Serializable] + public sealed class NormalizedPolynomial : KernelBase, IKernel, + IDistance, ICloneable + { + private int degree; + private double constant; + + /// + /// Constructs a new Normalized Polynomial kernel of a given degree. + /// + /// + /// The polynomial degree for this kernel. + /// The polynomial constant for this kernel. Default is 1. + /// + public NormalizedPolynomial(int degree, double constant) + { + this.degree = degree; + this.constant = constant; + } + + /// + /// Constructs a new Normalized Polynomial kernel of a given degree. + /// + /// + /// The polynomial degree for this kernel. + /// + public NormalizedPolynomial(int degree) + : this(degree, 1.0) { } + + /// + /// Gets or sets the kernel's polynomial degree. + /// + /// + public int Degree + { + get { return degree; } + set + { + if (degree <= 0) + throw new ArgumentOutOfRangeException("value", "Degree must be positive."); + + degree = value; + } + } + + /// + /// Gets or sets the kernel's polynomial constant term. + /// + /// + public double Constant + { + get { return constant; } + set { constant = value; } + } + + + /// + /// Normalized polynomial kernel function. + /// + /// + /// Vector x in input space. + /// Vector y in input space. + /// Dot product in feature (kernel) space. + /// + public override double Function(double[] x, double[] y) + { + double sum = constant; + double sumX = constant; + double sumY = constant; + + for (int i = 0; i < x.Length; i++) + { + sum += x[i] * y[i]; + sumX += x[i] * x[i]; + sumY += y[i] * y[i]; + } + + return Math.Pow(sum / (sumX + sumY), degree); + } + + /// + /// Creates a new object that is a copy of the current instance. + /// + /// + /// + /// A new object that is a copy of this instance. + /// + /// + public object Clone() + { + return MemberwiseClone(); + } + + } +} diff --git a/Sources/Accord.Statistics/Kernels/Pearson.cs b/Sources/Accord.Statistics/Kernels/Pearson.cs new file mode 100644 index 0000000000..2d581dda6 --- /dev/null +++ b/Sources/Accord.Statistics/Kernels/Pearson.cs @@ -0,0 +1,138 @@ +// Accord Statistics Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Statistics.Kernels +{ + using System; + + /// + /// Pearson VII universal kernel (PUK). + /// + /// + [Serializable] + public sealed class Pearson : KernelBase, IKernel, IDistance, + ICloneable + { + private double omega; + private double sigma; + + private double constant; + + /// + /// Constructs a new Pearson VII universal kernel. + /// + /// + /// The Pearson's omega parameter w. Default is 1. + /// The Pearson's sigma parameter s. Default is 1. + /// + public Pearson(double omega, double sigma) + { + this.omega = omega; + this.sigma = sigma; + } + + /// + /// Constructs a new Pearson VII universal kernel. + /// + /// + public Pearson() + : this(1, 1) { } + + /// + /// Gets or sets the kernel's parameter omega. Default is 1. + /// + /// + public double Omega + { + get { return omega; } + set + { + omega = value; + double u = 2 * Math.Sqrt(Math.Pow(2, (1 / omega)) - 1) / sigma; + constant = u * u; + } + } + + /// + /// Gets or sets the kernel's parameter sigma. Default is 1. + /// + /// + public double Sigma + { + get { return sigma; } + set + { + sigma = value; + double u = 2 * Math.Sqrt(Math.Pow(2, (1 / omega)) - 1) / sigma; + constant = u * u; + } + } + + /// + /// Pearson Universal kernel function. + /// + /// + /// Vector x in input space. + /// Vector y in input space. + /// + /// Dot product in feature (kernel) space. + /// + public override double Function(double[] x, double[] y) + { + double sum = 0; + for (int i = 0; i < x.Length; i++) + { + double u = x[i] - y[i]; + sum += u; + } + + return 1 / Math.Pow(1 - sum * constant, omega); + } + + /// + /// Pearson Universal function. + /// + /// + /// Distance z in input space. + /// + /// Dot product in feature (kernel) space. + /// + public double Function(double z) + { + return 1 / Math.Pow(1 - z * constant, omega); + } + + /// + /// Creates a new object that is a copy of the current instance. + /// + /// + /// + /// A new object that is a copy of this instance. + /// + /// + public object Clone() + { + return MemberwiseClone(); + } + + } +} diff --git a/Sources/Accord.Statistics/Kernels/Sparse/SparseGaussian.cs b/Sources/Accord.Statistics/Kernels/Sparse/SparseGaussian.cs index 502b74d02..dcbd52b0f 100644 --- a/Sources/Accord.Statistics/Kernels/Sparse/SparseGaussian.cs +++ b/Sources/Accord.Statistics/Kernels/Sparse/SparseGaussian.cs @@ -1,193 +1,205 @@ -// Accord Statistics Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Statistics.Kernels.Sparse -{ - using System; - using AForge; - - /// - /// Sparse Gaussian Kernel. - /// - /// - /// - /// - /// The Gaussian kernel requires tuning for the proper value of σ. Different approaches - /// to this problem includes the use of brute force (i.e. using a grid-search algorithm) - /// or a gradient ascent optimization. - /// - /// - /// References: - /// - /// - /// P. F. Evangelista, M. J. Embrechts, and B. K. Szymanski. Some Properties of the - /// Gaussian Kernel for One Class Learning. Available on: http://www.cs.rpi.edu/~szymansk/papers/icann07.pdf - /// - /// - /// - [Serializable] - public sealed class SparseGaussian : KernelBase, IKernel, IDistance, IReverseDistance - { - private double sigma; - private double gamma; - - - /// - /// Constructs a new Sparse Gaussian Kernel - /// - /// - /// The standard deviation for the Gaussian distribution. - /// - public SparseGaussian(double sigma) - { - this.Sigma = sigma; - } - - /// - /// Gets or sets the sigma value for the kernel. When setting - /// sigma, gamma gets updated accordingly (gamma = 0.5*/sigma^2). - /// - /// - public double Sigma - { - get { return sigma; } - set - { - sigma = value; - gamma = 1.0 / (2.0 * sigma * sigma); - } - } - - /// - /// Gets or sets the gamma value for the kernel. When setting - /// gamma, sigma gets updated accordingly (gamma = 0.5*/sigma^2). - /// - /// - public double Gamma - { - get { return gamma; } - set - { - gamma = value; - sigma = Math.Sqrt(1.0 / (gamma * 2.0)); - } - } - - /// - /// Gaussian Kernel function. - /// - /// - /// Vector x in input space. - /// Vector y in input space. - /// Dot product in feature (kernel) space. - /// - public override double Function(double[] x, double[] y) - { - // Optimization in case x and y are - // exactly the same object reference. - - if (x == y) - return 1.0; - - double norm = SparseLinear.SquaredEuclidean(x, y); - - return Math.Exp(-gamma * norm); - } - - /// - /// Computes the distance in input space - /// between two points given in feature space. - /// - /// - /// Vector x in feature (kernel) space. - /// Vector y in feature (kernel) space. - /// - /// - /// Distance between x and y in input space. - /// - /// - public override double Distance(double[] x, double[] y) - { - if (x == y) - return 0.0; - - double norm = SparseLinear.SquaredEuclidean(x, y); - - return 2 - 2 * Math.Exp(-gamma * norm); - } - - /// - /// Computes the squared distance in input space - /// between two points given in feature space. - /// - /// - /// Vector x in feature (kernel) space. - /// Vector y in feature (kernel) space. - /// - /// - /// Squared distance between x and y in input space. - /// - /// - public double ReverseDistance(double[] x, double[] y) - { - if (x == y) - return 0.0; - - double norm = SparseLinear.SquaredEuclidean(x, y); - - return -(1.0 / gamma) * Math.Log(1.0 - 0.5 * norm); - } - - /// - /// Estimate appropriate values for sigma given a data set. - /// - /// - /// - /// This method uses a simple heuristic to obtain appropriate values - /// for sigma in a radial basis function kernel. The heuristic is shown - /// by Caputo, Sim, Furesjo and Smola, "Appearance-based object - /// recognition using SVMs: which kernel should I use?", 2002. - /// - /// - /// The data set. - /// The number of random samples to analyze. - /// The range of suitable values for sigma. - /// A Gaussian kernel initialized with an appropriate sigma value. - /// - public static SparseGaussian Estimate(double[][] inputs, int samples, out DoubleRange range) - { - if (samples > inputs.Length) - throw new ArgumentOutOfRangeException("samples"); - - double[] distances = Gaussian.Distances(inputs, samples); - - double q1 = Math.Sqrt(distances[(int)Math.Ceiling(0.15 * distances.Length)] / 2.0); - double q9 = Math.Sqrt(distances[(int)Math.Ceiling(0.85 * distances.Length)] / 2.0); - double qm = Math.Sqrt(Accord.Statistics.Tools.Median(distances, alreadySorted: true) / 2.0); - - range = new DoubleRange(q1, q9); - - return new SparseGaussian(sigma: qm); - } - - } -} +// Accord Statistics Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Statistics.Kernels.Sparse +{ + using System; + using AForge; + + /// + /// Sparse Gaussian Kernel. + /// + /// + /// + /// + /// The Gaussian kernel requires tuning for the proper value of σ. Different approaches + /// to this problem includes the use of brute force (i.e. using a grid-search algorithm) + /// or a gradient ascent optimization. + /// + /// + /// For an example on how to create a sparse kernel, please see the page. + /// + /// + /// References: + /// + /// + /// P. F. Evangelista, M. J. Embrechts, and B. K. Szymanski. Some Properties of the + /// Gaussian Kernel for One Class Learning. Available on: http://www.cs.rpi.edu/~szymansk/papers/icann07.pdf + /// + /// + /// + [Serializable] + public sealed class SparseGaussian : KernelBase, IKernel, IDistance, IReverseDistance + { + private double sigma; + private double gamma; + + + /// + /// Constructs a new Sparse Gaussian Kernel + /// + /// + public SparseGaussian() + : this(1) + { + } + + /// + /// Constructs a new Sparse Gaussian Kernel + /// + /// + /// The standard deviation for the Gaussian distribution. Default is 1. + /// + public SparseGaussian(double sigma) + { + this.Sigma = sigma; + } + + /// + /// Gets or sets the sigma value for the kernel. When setting + /// sigma, gamma gets updated accordingly (gamma = 0.5*/sigma^2). + /// + /// + public double Sigma + { + get { return sigma; } + set + { + sigma = value; + gamma = 1.0 / (2.0 * sigma * sigma); + } + } + + /// + /// Gets or sets the gamma value for the kernel. When setting + /// gamma, sigma gets updated accordingly (gamma = 0.5*/sigma^2). + /// + /// + public double Gamma + { + get { return gamma; } + set + { + gamma = value; + sigma = Math.Sqrt(1.0 / (gamma * 2.0)); + } + } + + /// + /// Gaussian Kernel function. + /// + /// + /// Vector x in input space. + /// Vector y in input space. + /// Dot product in feature (kernel) space. + /// + public override double Function(double[] x, double[] y) + { + // Optimization in case x and y are + // exactly the same object reference. + + if (x == y) + return 1.0; + + double norm = SparseLinear.SquaredEuclidean(x, y); + + return Math.Exp(-gamma * norm); + } + + /// + /// Computes the distance in input space + /// between two points given in feature space. + /// + /// + /// Vector x in feature (kernel) space. + /// Vector y in feature (kernel) space. + /// + /// + /// Distance between x and y in input space. + /// + /// + public override double Distance(double[] x, double[] y) + { + if (x == y) + return 0.0; + + double norm = SparseLinear.SquaredEuclidean(x, y); + + return 2 - 2 * Math.Exp(-gamma * norm); + } + + /// + /// Computes the squared distance in input space + /// between two points given in feature space. + /// + /// + /// Vector x in feature (kernel) space. + /// Vector y in feature (kernel) space. + /// + /// + /// Squared distance between x and y in input space. + /// + /// + public double ReverseDistance(double[] x, double[] y) + { + if (x == y) + return 0.0; + + double norm = SparseLinear.SquaredEuclidean(x, y); + + return -(1.0 / gamma) * Math.Log(1.0 - 0.5 * norm); + } + + /// + /// Estimate appropriate values for sigma given a data set. + /// + /// + /// + /// This method uses a simple heuristic to obtain appropriate values + /// for sigma in a radial basis function kernel. The heuristic is shown + /// by Caputo, Sim, Furesjo and Smola, "Appearance-based object + /// recognition using SVMs: which kernel should I use?", 2002. + /// + /// + /// The data set. + /// The number of random samples to analyze. + /// The range of suitable values for sigma. + /// A Gaussian kernel initialized with an appropriate sigma value. + /// + public static SparseGaussian Estimate(double[][] inputs, int samples, out DoubleRange range) + { + if (samples > inputs.Length) + throw new ArgumentOutOfRangeException("samples"); + + double[] distances = Gaussian.Distances(inputs, samples); + + double q1 = Math.Sqrt(distances[(int)Math.Ceiling(0.15 * distances.Length)] / 2.0); + double q9 = Math.Sqrt(distances[(int)Math.Ceiling(0.85 * distances.Length)] / 2.0); + double qm = Math.Sqrt(Accord.Statistics.Tools.Median(distances, alreadySorted: true) / 2.0); + + range = new DoubleRange(q1, q9); + + return new SparseGaussian(sigma: qm); + } + + } +} diff --git a/Sources/Accord.Statistics/Kernels/Sparse/SparseLaplacian.cs b/Sources/Accord.Statistics/Kernels/Sparse/SparseLaplacian.cs index fcfbb2d94..a42752a86 100644 --- a/Sources/Accord.Statistics/Kernels/Sparse/SparseLaplacian.cs +++ b/Sources/Accord.Statistics/Kernels/Sparse/SparseLaplacian.cs @@ -93,45 +93,16 @@ public double Gamma /// Dot product in feature (kernel) space. /// public override double Function(double[] x, double[] y) - { - // Optimization in case x and y are - // exactly the same object reference. - - if (x == y) - return 1.0; - - double norm = 0.0; - - int i = 0, j = 0; - - while (i < x.Length || j < y.Length) - { - double posx = x[i]; - double posy = y[j]; - - if (posx == posy) - { - double d = x[i + 1] - y[j + 1]; - norm += d * d; - i += 2; j += 2; - } - else if (posx < posy) - { - double d = x[j + 1]; - norm += d * d; - i += 2; - } - else if (posx > posy) - { - double d = y[i + 1]; - norm += d * d; - j += 2; - } - } - - norm = Math.Sqrt(norm); - - return Math.Exp(-gamma * norm); + { + // Optimization in case x and y are + // exactly the same object reference. + + if (x == y) + return 1.0; + + double norm = SparseLinear.SquaredEuclidean(x, y); + + return Math.Exp(-gamma * Math.Sqrt(norm)); } /// @@ -145,42 +116,13 @@ public override double Function(double[] x, double[] y) /// Distance between x and y in input space. /// public override double Distance(double[] x, double[] y) - { - if (x == y) - return 0.0; - - double norm = 0.0; - - int i = 0, j = 0; - - while (i < x.Length || j < y.Length) - { - double posx = x[i]; - double posy = y[j]; - - if (posx == posy) - { - double d = x[i + 1] - y[j + 1]; - norm += d * d; - i += 2; j += 2; - } - else if (posx < posy) - { - double d = x[j + 1]; - norm += d * d; - i += 2; - } - else if (posx > posy) - { - double d = y[i + 1]; - norm += d * d; - j += 2; - } - } - - norm = Math.Sqrt(norm); - - return 2 - 2 * Math.Exp(-gamma * norm); + { + if (x == y) + return 0.0; + + double norm = SparseLinear.SquaredEuclidean(x, y); + + return 2 - 2 * Math.Exp(-gamma * Math.Sqrt(norm)); } diff --git a/Sources/Accord.Statistics/Kernels/Sparse/SparseLinear.cs b/Sources/Accord.Statistics/Kernels/Sparse/SparseLinear.cs index 6ce053bfa..269281cba 100644 --- a/Sources/Accord.Statistics/Kernels/Sparse/SparseLinear.cs +++ b/Sources/Accord.Statistics/Kernels/Sparse/SparseLinear.cs @@ -32,6 +32,48 @@ namespace Accord.Statistics.Kernels.Sparse /// The Sparse Linear kernel accepts inputs in the libsvm sparse format. /// /// + /// + /// + /// The following example shows how to teach a kernel support vector machine using + /// the linear sparse kernel to perform the AND classification task using sparse + /// vectors. + /// + /// + /// // Example AND problem + /// double[][] inputs = + /// { + /// new double[] { }, // 0 and 0: 0 (label -1) + /// new double[] { 2,1 }, // 0 and 1: 0 (label -1) + /// new double[] { 1,1 }, // 1 and 0: 0 (label -1) + /// new double[] { 1,1, 2,1 } // 1 and 1: 1 (label +1) + /// }; + /// + /// // Dichotomy SVM outputs should be given as [-1;+1] + /// int[] labels = + /// { + /// // 0, 0, 0, 1 + /// -1, -1, -1, 1 + /// }; + /// + /// // Create a Support Vector Machine for the given inputs + /// // (sparse machines should use 0 as the number of inputs) + /// var machine = new KernelSupportVectorMachine(new SparseLinear(), inputs: 0); + /// + /// // Instantiate a new learning algorithm for SVMs + /// var smo = new SequentialMinimalOptimization(machine, inputs, labels); + /// + /// // Set up the learning algorithm + /// smo.Complexity = 100000.0; + /// + /// // Run + /// double error = smo.Run(); // should be zero + /// + /// double[] predicted = inputs.Apply(machine.Compute).Sign(); + /// + /// // Outputs should be -1, -1, -1, +1 + /// + /// + /// [Serializable] public sealed class SparseLinear : KernelBase, IKernel { @@ -41,7 +83,7 @@ public sealed class SparseLinear : KernelBase, IKernel /// Constructs a new Linear kernel. /// /// - /// A constant intercept term. Default is 1. + /// A constant intercept term. Default is 0. /// public SparseLinear(double constant) { @@ -75,13 +117,10 @@ public double Constant /// public override double Function(double[] x, double[] y) { - if (x == y) - return 1.0; - return Product(x, y) + constant; } - + /// /// Computes the squared distance in feature space @@ -97,7 +136,7 @@ public override double Distance(double[] x, double[] y) if (x == y) return 0; - return SquaredEuclidean(x,y); + return SquaredEuclidean(x, y); } @@ -186,6 +225,12 @@ public static double SquaredEuclidean(double[] x, double[] y) } } + for (; i < x.Length; i += 2) + sum += x[i + 1] * x[i + 1]; + + for (; j < y.Length; j += 2) + sum += y[j + 1] * y[j + 1]; + return sum; } diff --git a/Sources/Accord.Statistics/Kernels/Sparse/SparseSigmoid.cs b/Sources/Accord.Statistics/Kernels/Sparse/SparseSigmoid.cs index 803db353a..b0e6f107f 100644 --- a/Sources/Accord.Statistics/Kernels/Sparse/SparseSigmoid.cs +++ b/Sources/Accord.Statistics/Kernels/Sparse/SparseSigmoid.cs @@ -1,97 +1,104 @@ -// Accord Statistics Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Statistics.Kernels.Sparse -{ - using System; - - /// - /// Sparse Sigmoid Kernel. - /// - /// - /// - /// Sigmoid kernels are not positive definite and therefore do not induce - /// a reproducing kernel Hilbert space. However, they have been successfully - /// used in practice (Schölkopf and Smola, 2002). - /// - /// - [Serializable] - public sealed class SparseSigmoid : KernelBase, IKernel - { - private double gamma; - private double constant; - - /// - /// Constructs a Sparse Sigmoid kernel. - /// - /// - /// Alpha parameter. - /// Constant parameter. - /// - public SparseSigmoid(double alpha, double constant) - { - this.gamma = alpha; - this.constant = constant; - } - - /// - /// Gets or sets the kernel's gamma parameter. - /// - /// - /// - /// In a sigmoid kernel, gamma is a inner product - /// coefficient for the hyperbolic tangent function. - /// - /// - public double Gamma - { - get { return gamma; } - set { gamma = value; } - } - - /// - /// Gets or sets the kernel's constant term. - /// - /// - public double Constant - { - get { return constant; } - set { constant = value; } - } - - /// - /// Sigmoid kernel function. - /// - /// - /// Vector x in input space. - /// Vector y in input space. - /// Dot product in feature (kernel) space. - /// - public override double Function(double[] x, double[] y) - { - double sum = SparseLinear.Product(x,y); - - return System.Math.Tanh(Gamma * sum + Constant); - } - - } -} +// Accord Statistics Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Statistics.Kernels.Sparse +{ + using System; + + /// + /// Sparse Sigmoid Kernel. + /// + /// + /// + /// Sigmoid kernels are not positive definite and therefore do not induce + /// a reproducing kernel Hilbert space. However, they have been successfully + /// used in practice (Schölkopf and Smola, 2002). + /// + /// + [Serializable] + public sealed class SparseSigmoid : KernelBase, IKernel + { + private double gamma; + private double constant; + + /// + /// Constructs a Sparse Sigmoid kernel. + /// + /// + /// Alpha parameter. + /// Constant parameter. + /// + public SparseSigmoid(double alpha, double constant) + { + this.gamma = alpha; + this.constant = constant; + } + + /// + /// Constructs a Sparse Sigmoid kernel. + /// + /// + public SparseSigmoid() + : this(0.01, -Math.E) { } + + /// + /// Gets or sets the kernel's gamma parameter. + /// + /// + /// + /// In a sigmoid kernel, gamma is a inner product + /// coefficient for the hyperbolic tangent function. + /// + /// + public double Gamma + { + get { return gamma; } + set { gamma = value; } + } + + /// + /// Gets or sets the kernel's constant term. + /// + /// + public double Constant + { + get { return constant; } + set { constant = value; } + } + + /// + /// Sigmoid kernel function. + /// + /// + /// Vector x in input space. + /// Vector y in input space. + /// Dot product in feature (kernel) space. + /// + public override double Function(double[] x, double[] y) + { + double sum = SparseLinear.Product(x, y); + + return System.Math.Tanh(Gamma * sum + Constant); + } + + } +} diff --git a/Sources/Accord.Statistics/Models/Accord.Statistics.Models.cd b/Sources/Accord.Statistics/Models/Accord.Statistics.Models.cd index 46a6f4a32..5b6760a40 100644 --- a/Sources/Accord.Statistics/Models/Accord.Statistics.Models.cd +++ b/Sources/Accord.Statistics/Models/Accord.Statistics.Models.cd @@ -1,227 +1,228 @@ - - - - - - - - - - - BEAAAAAAAAAAgAAAIAAAQAAAEEAAEDAAAAAAAAAAAAA= - Models\Regression\Linear\MultivariateLinearRegression.cs - Models\Regression\Linear\MultipleLinearRegression.cs - - - - - - - - - AEAQAAAAAAAAgAAEAAAAAAAQAEAAEDAAAAAAAAAAAAA= - Models\Regression\Linear\PolynomialRegression.cs - - - - - - - - - - - - AEAQAAAAAAAAgAAEAAAAAAAAAAAAEDAAAAAAAgAAAEA= - Models\Regression\Linear\SimpleLinearRegression.cs - - - - - - - - - - - - - - - AEAAAACAAAAAgAAEAAAAQABAEEAAEDAAAAAQAAAAAAA= - Models\Regression\Linear\MultipleLinearRegression.cs - - - - - - - AAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAIAAAAAAAAAA= - Models\Regression\Nonlinear\LogisticRegression.cs - - - - - - - - - - - BEAIAAAAAoAjCAYJBACIAAQAEAEAACAAAAQgABAAAAA= - Analysis\StepwiseLogisticRegressionAnalysis.cs - - - - - - - - - - AQAAgIAAAgAAAAAAAAAAAAAAUEAAAAAARAQABAAAEAA= - Analysis\StepwiseLogisticRegressionAnalysis.cs - - - - - - - - AEAAAAAAAAAAAAAQAAACQIAYEEAAEBAAYAAABEAAABA= - Models\Regression\Nonlinear\MultinomialLogisticRegression.cs - - - - - - - - - AACQABAAAAByQgAAVAIAAAoAkAAIAAAAAYAAAAEAgII= - Models\Survival\Fitting\PartialNewtonRaphson.cs - - - - - - - IEAAAAAAAAAABAAAAAACAIAIEEAAAQAAQAAAhAAAAFA= - Models\Survival\ProportionalHazards.cs - - - - - - - - QASQABAAAABAQgAAQAIAAAgAAAAIAAAAAYAAAAAAgAI= - Models\Regression\Nonlinear\Fitting\IterativeReweightedLeastSquares.cs - - - - - - - - - AECQAhEAAAFQQgAAQAMAAAEACAAAQABAAYAAAMJAgAI= - Models\Regression\Nonlinear\Fitting\LowerBoundNewtonRaphson.cs - - - - - - - - - AAQQAFAAAABAAgAEQAIABAAAAAAAAAAAAYAAAGAAAAI= - Models\Regression\Nonlinear\Fitting\LogisticGradientDescent.cs - - - - - - - AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= - Models\Regression\Linear\ILinearRegression.cs - - - - - - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI= - Models\Survival\Fitting\ISurvivalFitting.cs - - - - - - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI= - Models\Regression\Nonlinear\Fitting\Base\IMultipleRegressionFitting.cs - - - - - - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI= - Models\Regression\Nonlinear\Fitting\Base\IRegressionFitting.cs - - - + + + + + + + + + + + BEAAAAAAAAAAgAAAIAAAQAAAEEAAEDAAAAAAAAAAAAA= + Models\Regression\Linear\MultivariateLinearRegression.cs + Models\Regression\Linear\MultipleLinearRegression.cs + + + + + + + + + AEAQAAAAAAAAgAAEAAAAAAAQAEAAEDAAAAAAAAAAAAA= + Models\Regression\Linear\PolynomialRegression.cs + + + + + + + + + + + + AEAQAAAAAAAAgAAEAAAAAAAAAAAAEDAAAAAAAgAAAEA= + Models\Regression\Linear\SimpleLinearRegression.cs + + + + + + + + + + + + + + + AEAAAACAAAAAgAAEAAAAQABAEEAAEDAAAAAQAAAAAAA= + Models\Regression\Linear\MultipleLinearRegression.cs + + + + + + + AAIAAAAAAAAAAAAAAAAAAAAAAEAAAAAAIAAAAAAAAAA= + Models\Regression\Nonlinear\LogisticRegression.cs + + + + + + + + + + + BEAIAAIAAoAjCAYJBgCIAAYAEAAAACAAAAQgABAAAAA= + Analysis\StepwiseLogisticRegressionAnalysis.cs + + + + + + + + + + AQAAgIAAAgAAAAAAAAAAAAAAUEAAAAAARAQABAAAEAA= + Analysis\StepwiseLogisticRegressionAnalysis.cs + + + + + + + + AEAAAAAAAAAAAAAQAAACQIAYEEAAEBAAYAAABEAAABA= + Models\Regression\Nonlinear\MultinomialLogisticRegression.cs + + + + + + + + + AAiQABAAAAByQgAAVAIAAAoAgIAIAAAAAYAAQAEAgII= + Models\Survival\Fitting\ProportionalHazardsNewtonRaphson.cs + + + + + + + IEQAAAAAAAAABAAAAAACAIAIEEAAAQAAQAAAhAAAAFA= + Models\Survival\ProportionalHazards.cs + + + + + + + + QASQABAIAABAQgAAQAIAAggAAAAIAAAAAYAAAAAAgAI= + Models\Regression\Nonlinear\Fitting\IterativeReweightedLeastSquares.cs + + + + + + + + + AECQAhEAAAFQQgAAQAMAAAEACAAAQABAAYAAAMJAgAI= + Models\Regression\Nonlinear\Fitting\LowerBoundNewtonRaphson.cs + + + + + + + + + AAQQAFAAAABAAgAEQAIABAAAAAAAAAAAAYAAAGAAAAI= + Models\Regression\Nonlinear\Fitting\LogisticGradientDescent.cs + + + + + + + AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + Models\Regression\Linear\ILinearRegression.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI= + Models\Survival\Fitting\ISurvivalFitting.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI= + Models\Regression\Nonlinear\Fitting\Base\IMultipleRegressionFitting.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI= + Models\Regression\Nonlinear\Fitting\Base\IRegressionFitting.cs + + + \ No newline at end of file diff --git a/Sources/Accord.Statistics/Models/Markov/Learning/BaumWelchLearning`1.cs b/Sources/Accord.Statistics/Models/Markov/Learning/BaumWelchLearning`1.cs index 3c07c6764..5529ac1fc 100644 --- a/Sources/Accord.Statistics/Models/Markov/Learning/BaumWelchLearning`1.cs +++ b/Sources/Accord.Statistics/Models/Markov/Learning/BaumWelchLearning`1.cs @@ -205,7 +205,7 @@ namespace Accord.Statistics.Models.Markov.Learning /// new double[] { 9, 8 }, // observation 2 of sequence 2 /// new double[] { 1, 0 }, // observation 3 of sequence 2 /// }, - /// new double[][] // sequence 3 + /// new double[][] // sequence 3 /// { /// new double[] { 1, 3 }, // observation 1 of sequence 3 /// new double[] { 8, 9 }, // observation 2 of sequence 3 diff --git a/Sources/Accord.Statistics/Models/Regression/Nonlinear/Fitting/NonlinearLeastSquares.cs b/Sources/Accord.Statistics/Models/Regression/Nonlinear/Fitting/NonlinearLeastSquares.cs index 6918a6969..4c4775819 100644 --- a/Sources/Accord.Statistics/Models/Regression/Nonlinear/Fitting/NonlinearLeastSquares.cs +++ b/Sources/Accord.Statistics/Models/Regression/Nonlinear/Fitting/NonlinearLeastSquares.cs @@ -29,6 +29,59 @@ namespace Accord.Statistics.Models.Regression.Fitting /// Non-linear Least Squares for optimization. /// /// + /// + /// + /// // Suppose we would like to map the continuous values in the + /// // second column to the integer values in the first column. + /// double[,] data = + /// { + /// { -40, -21142.1111111111 }, + /// { -30, -21330.1111111111 }, + /// { -20, -12036.1111111111 }, + /// { -10, 7255.3888888889 }, + /// { 0, 32474.8888888889 }, + /// { 10, 32474.8888888889 }, + /// { 20, 9060.8888888889 }, + /// { 30, -11628.1111111111 }, + /// { 40, -15129.6111111111 }, + /// }; + /// + /// // Extract inputs and outputs + /// double[][] inputs = data.GetColumn(0).ToArray(); + /// double[] outputs = data.GetColumn(1); + /// + /// // Create a Nonlinear regression using + /// var regression = new NonlinearRegression(3, + /// + /// // Let's assume a quadratic model function: ax² + bx + c + /// function: (w, x) => w[0] * x[0] * x[0] + w[1] * x[0] + w[2], + /// + /// // Derivative in respect to the weights: + /// gradient: (w, x, r) => + /// { + /// r[0] = 2 * w[0]; // w.r.t a: 2a + /// r[1] = w[1]; // w.r.t b: b + /// r[2] = w[2]; // w.r.t c: 0 + /// } + /// ); + /// + /// // Create a non-linear least squares teacher + /// var nls = new NonlinearLeastSquares(regression); + /// + /// // Initialize to some random values + /// regression.Coefficients[0] = 4.2; + /// regression.Coefficients[1] = 0.3; + /// regression.Coefficients[2] = 1; + /// + /// // Run the function estimation algorithm + /// double error; + /// for (int i = 0; i < 100; i++) + /// error = nls.Run(inputs, outputs); + /// + /// // Use the function to compute the input values + /// double[] predict = inputs.Apply(regression.Compute); + /// + /// public class NonlinearLeastSquares : IRegressionFitting { private ILeastSquaresMethod solver; diff --git a/Sources/Accord.Statistics/Models/Survival/Fitting/ISurvivalFitting.cs b/Sources/Accord.Statistics/Models/Survival/Fitting/ISurvivalFitting.cs index 4c3bf7e6e..5132afde4 100644 --- a/Sources/Accord.Statistics/Models/Survival/Fitting/ISurvivalFitting.cs +++ b/Sources/Accord.Statistics/Models/Survival/Fitting/ISurvivalFitting.cs @@ -1,47 +1,61 @@ -// Accord Statistics Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Statistics.Models.Regression.Fitting -{ - - /// - /// Common interface for regression fitting methods. - /// - /// - interface ISurvivalFitting : IRegressionFitting - { - - /// - /// Runs the fitting algorithm. - /// - /// - /// The input training data. - /// The time until the output happened. - /// The indication variables used to signal - /// if the event ocurred or not. - /// - /// The error. - /// - double Run(double[][] inputs, double[] time, int[] censor); - - } -} +// Accord Statistics Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Statistics.Models.Regression.Fitting +{ + using Accord.Statistics.Distributions.Univariate; + + /// + /// Common interface for regression fitting methods. + /// + /// + interface ISurvivalFitting : IRegressionFitting + { + + /// + /// Runs the fitting algorithm. + /// + /// + /// The input training data. + /// The time until the output happened. + /// The indication variables used to signal + /// if the event occurred or if it was censored. + /// + /// The error. + /// + double Run(double[][] inputs, double[] time, SurvivalOutcome[] censor); + + /// + /// Runs the fitting algorithm. + /// + /// + /// The input training data. + /// The time until the output happened. + /// The indication variables used to signal + /// if the event occurred or if it was censored. + /// + /// The error. + /// + double Run(double[][] inputs, double[] time, int[] censor); + + } +} diff --git a/Sources/Accord.Statistics/Models/Survival/Fitting/PartialNewtonRaphson.cs b/Sources/Accord.Statistics/Models/Survival/Fitting/ProportionalHazardsNewtonRaphson.cs similarity index 67% rename from Sources/Accord.Statistics/Models/Survival/Fitting/PartialNewtonRaphson.cs rename to Sources/Accord.Statistics/Models/Survival/Fitting/ProportionalHazardsNewtonRaphson.cs index d2601a17a..fd6c0b36a 100644 --- a/Sources/Accord.Statistics/Models/Survival/Fitting/PartialNewtonRaphson.cs +++ b/Sources/Accord.Statistics/Models/Survival/Fitting/ProportionalHazardsNewtonRaphson.cs @@ -1,443 +1,523 @@ -// Accord Statistics Library -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Statistics.Models.Regression.Fitting -{ - using System; - using Accord.Math; - using Accord.Math.Decompositions; - using Accord.Statistics.Distributions.Univariate; - using Accord.Statistics.Distributions.Fitting; - using Accord.Statistics.Distributions; - using Accord.Math.Comparers; - - /// - /// Newton-Raphson learning updates for Cox's Proportional Hazards models. - /// - /// - public class ProportionalHazardsNewtonRaphson : ISurvivalFitting, IConvergenceLearning - { - - private ProportionalHazards regression; - private int parameterCount; - - private double[,] hessian; - private double[] gradient; - - private double[] partialGradient; - private double[,] partialHessian; - - private bool computeStandardErrors = true; - private bool computeBaselineFunction = true; - private bool normalize = true; - - private ISolverMatrixDecomposition decomposition; - private RelativeParameterConvergence convergence; - - - /// - /// Gets or sets the maximum absolute parameter change detectable - /// after an iteration of the algorithm used to detect convergence. - /// Default is 1e-5. - /// - /// - public double Tolerance - { - get { return convergence.Tolerance; } - set { convergence.Tolerance = value; } - } - - /// - /// Gets or sets the maximum number of iterations - /// performed by the learning algorithm. - /// - /// - public int Iterations - { - get { return convergence.Iterations; } - set { convergence.Iterations = value; } - } - - /// - /// Gets or sets the number of performed iterations. - /// - /// - public int CurrentIteration - { - get { return convergence.CurrentIteration; } - set { convergence.CurrentIteration = value; } - } - - - /// - /// Gets the previous values for the coefficients which were - /// in place before the last learning iteration was performed. - /// - /// - public double[] Previous { get { return convergence.OldValues; } } - - /// - /// Gets the current values for the coefficients. - /// - /// - public double[] Solution { get { return regression.Coefficients; } } - - /// - /// Gets the Hessian matrix computed in - /// the last Newton-Raphson iteration. - /// - /// - public double[,] Hessian { get { return hessian; } } - - /// - /// Gets the Gradient vector computed in - /// the last Newton-Raphson iteration. - /// - /// - public double[] Gradient { get { return gradient; } } - - /// - /// Gets the total number of parameters in the model. - /// - /// - public int Parameters { get { return parameterCount; } } - - - /// - /// Gets or sets a value indicating whether standard - /// errors should be computed at the end of the next - /// iterations. - /// - /// - /// true to compute standard errors; otherwise, false. - /// - /// - public bool ComputeStandardErrors - { - get { return computeStandardErrors; } - set { computeStandardErrors = value; } - } - - /// - /// Gets or sets a value indicating whether an estimate - /// of the baseline hazard function should be computed - /// at the end of the next iterations. - /// - /// - /// true to compute the baseline function; otherwise, false. - /// - /// - public bool ComputeBaselineFunction - { - get { return computeBaselineFunction; } - set { computeBaselineFunction = value; } - } - - /// - /// Gets or sets a value indicating whether the Cox model should - /// be computed using the mean-centered version of the covariates. - /// Default is true. - /// - /// - public bool Normalize - { - get { return normalize; } - set { normalize = value; } - } - - - /// - /// Constructs a new Newton-Raphson learning algorithm - /// for Cox's Proportional Hazards models. - /// - /// - /// The model to estimate. - /// - public ProportionalHazardsNewtonRaphson(ProportionalHazards hazards) - { - this.regression = hazards; - this.parameterCount = hazards.Coefficients.Length; - - this.hessian = new double[parameterCount, parameterCount]; - this.gradient = new double[parameterCount]; - - this.partialHessian = new double[parameterCount, parameterCount]; - this.partialGradient = new double[parameterCount]; - - this.convergence = new RelativeParameterConvergence() - { - Iterations = 0, - Tolerance = 1e-5 - }; - } - - - /// - /// Runs one iteration of the Newton-Raphson update for Cox's hazards learning. - /// - /// - /// The input data. - /// The time-to-event for the training samples. - /// - /// The maximum relative change in the parameters after the iteration. - /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", - "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "1#")] - public double Run(double[][] inputs, double[] time) - { - int[] censor = new int[time.Length]; - for (int i = 0; i < censor.Length; i++) - censor[i] = 1; - - return Run(inputs, time, censor); - } - - /// - /// Runs one iteration of the Newton-Raphson update for Cox's hazards learning. - /// - /// - /// The input data. - /// The output (event) associated with each input vector. - /// The time-to-event for the non-censored training samples. - /// - /// The maximum relative change in the parameters after the iteration. - /// - public double Run(double[][] inputs, double[] time, int[] censor) - { - if (inputs.Length != time.Length || time.Length != censor.Length) - throw new DimensionMismatchException("time", - "The inputs, time and output vector must have the same length."); - - double[] means = new double[parameterCount]; - double[] sdev = new double[parameterCount]; - for (int i = 0; i < sdev.Length; i++) - sdev[i] = 1; - - if (normalize) - { - // Store means as regression centers - means = inputs.Mean(); - for (int i = 0; i < means.Length; i++) - regression.Offsets[i] = means[i]; - - // Convert to unit scores for increased accuracy - sdev = Accord.Statistics.Tools.StandardDeviation(inputs); - inputs = inputs.Subtract(means, 0).ElementwiseDivide(sdev, 0, inPlace: true); - } - - // Sort data by time to accelerate performance - if (!time.IsSorted(ComparerDirection.Descending)) - sort(ref inputs, ref time, ref censor); - - // Compute actual outputs - double[] output = new double[inputs.Length]; - for (int i = 0; i < output.Length; i++) - output[i] = regression.Compute(inputs[i]); - - // Compute ties - int[] ties = new int[inputs.Length]; - for (int i = 0; i < inputs.Length; i++) - for (int j = 0; j < time.Length; j++) - if (time[j] == time[i]) ties[i]++; - - if (parameterCount == 0) - return createBaseline(time, censor, output); - - CurrentIteration = 0; - double smooth = 0.1; - - - do // learning iterations until convergence - { // or maximum number of iterations reached - - CurrentIteration++; - - // Reset Hessian matrix and gradient - Array.Clear(gradient, 0, gradient.Length); - Array.Clear(hessian, 0, hessian.Length); - - // For each observation instance - for (int i = 0; i < inputs.Length; i++) - { - // Check if we should censor - if (censor[i] == 0) continue; - - // Compute partials - double den = 0; - Array.Clear(partialGradient, 0, partialGradient.Length); - Array.Clear(partialHessian, 0, partialHessian.Length); - - for (int j = 0; j < inputs.Length; j++) - { - if (time[j] >= time[i]) - den += output[j]; - } - - for (int j = 0; j < inputs.Length; j++) - { - if (time[j] >= time[i]) - { - // Compute partial gradient - for (int k = 0; k < partialGradient.Length; k++) - partialGradient[k] += inputs[j][k] * output[j] / den; - - // Compute partial Hessian - for (int ii = 0; ii < inputs[j].Length; ii++) - for (int jj = 0; jj < inputs[j].Length; jj++) - partialHessian[ii, jj] += inputs[j][ii] * inputs[j][jj] * output[j] / den; - } - } - - // Compute gradient vector - for (int j = 0; j < gradient.Length; j++) - gradient[j] += inputs[i][j] - partialGradient[j]; - - // Compute Hessian matrix - for (int j = 0; j < partialGradient.Length; j++) - for (int k = 0; k < partialGradient.Length; k++) - hessian[j, k] -= partialHessian[j, k] - partialGradient[j] * partialGradient[k]; - } - - - // Decompose to solve the linear system. Usually the Hessian will - // be invertible and LU will succeed. However, sometimes the Hessian - // may be singular and a Singular Value Decomposition may be needed. - - // The SVD is very stable, but is quite expensive, being on average - // about 10-15 times more expensive than LU decomposition. There are - // other ways to avoid a singular Hessian. For a very interesting - // reading on the subject, please see: - // - // - Jeff Gill & Gary King, "What to Do When Your Hessian Is Not Invertible", - // Sociological Methods & Research, Vol 33, No. 1, August 2004, 54-87. - // Available in: http://gking.harvard.edu/files/help.pdf - // - - // Moreover, the computation of the inverse is optional, as it will - // be used only to compute the standard errors of the regression. - - - // Hessian Matrix is singular, try pseudo-inverse solution - decomposition = new SingularValueDecomposition(hessian); - double[] deltas = decomposition.Solve(gradient); - - - // Update coefficients using the calculated deltas - for (int i = 0; i < regression.Coefficients.Length; i++) - regression.Coefficients[i] -= smooth * deltas[i]; - - smooth += 0.1; - if (smooth > 1) - smooth = 1; - - // Check relative maximum parameter change - convergence.NewValues = regression.Coefficients; - - - if (convergence.HasDiverged) - { - // Restore previous coefficients - for (int i = 0; i < regression.Coefficients.Length; i++) - regression.Coefficients[i] = convergence.OldValues[i]; - } - - - // Recompute current outputs - for (int i = 0; i < output.Length; i++) - { - double sum = 0; - for (int j = 0; j < regression.Coefficients.Length; j++) - sum += regression.Coefficients[j] * inputs[i][j]; - output[i] = Math.Exp(sum); - } - - } while (!convergence.HasConverged); - - - for (int i = 0; i < regression.Coefficients.Length; i++) - regression.Coefficients[i] /= sdev[i]; - - if (computeStandardErrors) - { - // Grab the regression information matrix - double[,] inverse = decomposition.Inverse(); - - // Calculate coefficients' standard errors - double[] standardErrors = regression.StandardErrors; - for (int i = 0; i < standardErrors.Length; i++) - standardErrors[i] = Math.Sqrt(Math.Abs(inverse[i, i])) / sdev[i]; - } - - if (computeBaselineFunction) - createBaseline(time, censor, output); - - return convergence.Delta; - } - - private double createBaseline(double[] time, int[] censor, double[] output) - { - if (regression.BaselineHazard != null) - { - IFittingOptions options = null; - - if (regression.BaselineHazard is IFittableDistribution) - { - // Compute an estimate of the cumulative Hazard - // function using the Nelson-Aalen estimator - options = new EmpiricalHazardOptions() - { - Censor = censor, - Output = output, - Estimator = HazardEstimator.BreslowNelsonAalen - }; - } - else if (regression.BaselineHazard is IFittableDistribution) - { - // Compute an estimate of the cumulative Hazard - // function using the Nelson-Aalen estimator - options = new SurvivalOptions() - { - Censor = censor - }; - } - - regression.BaselineHazard.Fit(time, options); - } - - return 0; - } - - - private static void sort(ref double[][] inputs, ref double[] time, ref int[] output) - { - int[] idx = Matrix.Indices(0, inputs.Length); - - time = (double[])time.Clone(); - Array.Sort(time, idx, new GeneralComparer(ComparerDirection.Descending)); - - inputs = inputs.Submatrix(idx); - output = output.Submatrix(idx); - } - - - } -} +// Accord Statistics Library +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Statistics.Models.Regression.Fitting +{ + using System; + using Accord.Math; + using Accord.Math.Decompositions; + using Accord.Statistics.Distributions.Univariate; + using Accord.Statistics.Distributions.Fitting; + using Accord.Statistics.Distributions; + using Accord.Math.Comparers; + + /// + /// Newton-Raphson learning updates for Cox's Proportional Hazards models. + /// + /// + public class ProportionalHazardsNewtonRaphson : ISurvivalFitting, IConvergenceLearning + { + + private ProportionalHazards regression; + private int parameterCount; + + private double[,] hessian; + private double[] gradient; + + private double[] partialGradient; + private double[,] partialHessian; + + private bool computeStandardErrors = true; + private bool computeBaselineFunction = true; + private bool normalize = true; + + private ISolverMatrixDecomposition decomposition; + private RelativeParameterConvergence convergence; + + + /// + /// Gets or sets the maximum absolute parameter change detectable + /// after an iteration of the algorithm used to detect convergence. + /// Default is 1e-5. + /// + /// + public double Tolerance + { + get { return convergence.Tolerance; } + set { convergence.Tolerance = value; } + } + + /// + /// Gets or sets the maximum number of iterations + /// performed by the learning algorithm. + /// + /// + public int Iterations + { + get { return convergence.Iterations; } + set { convergence.Iterations = value; } + } + + /// + /// Gets or sets the number of performed iterations. + /// + /// + public int CurrentIteration + { + get { return convergence.CurrentIteration; } + set { convergence.CurrentIteration = value; } + } + + /// + /// Gets or sets the hazard estimator that should be used by the + /// proportional hazards learning algorithm. Default is to use + /// . + /// + /// + public HazardEstimator Estimator { get; set; } + + /// + /// Gets or sets the ties handling method to be used by the + /// proportional hazards learning algorithm. Default is to use + /// 's method. + /// + /// + public HazardTiesMethod Ties { get; set; } + + + /// + /// Gets the previous values for the coefficients which were + /// in place before the last learning iteration was performed. + /// + /// + public double[] Previous { get { return convergence.OldValues; } } + + /// + /// Gets the current values for the coefficients. + /// + /// + public double[] Solution { get { return regression.Coefficients; } } + + /// + /// Gets the Hessian matrix computed in + /// the last Newton-Raphson iteration. + /// + /// + public double[,] Hessian { get { return hessian; } } + + /// + /// Gets the Gradient vector computed in + /// the last Newton-Raphson iteration. + /// + /// + public double[] Gradient { get { return gradient; } } + + /// + /// Gets the total number of parameters in the model. + /// + /// + public int Parameters { get { return parameterCount; } } + + + /// + /// Gets or sets a value indicating whether standard + /// errors should be computed at the end of the next + /// iterations. + /// + /// + /// true to compute standard errors; otherwise, false. + /// + /// + public bool ComputeStandardErrors + { + get { return computeStandardErrors; } + set { computeStandardErrors = value; } + } + + /// + /// Gets or sets a value indicating whether an estimate + /// of the baseline hazard function should be computed + /// at the end of the next iterations. + /// + /// + /// true to compute the baseline function; otherwise, false. + /// + /// + public bool ComputeBaselineFunction + { + get { return computeBaselineFunction; } + set { computeBaselineFunction = value; } + } + + /// + /// Gets or sets a value indicating whether the Cox model should + /// be computed using the mean-centered version of the covariates. + /// Default is true. + /// + /// + public bool Normalize + { + get { return normalize; } + set { normalize = value; } + } + + /// + /// Gets or sets the smoothing factor used to avoid numerical + /// problems in the beginning of the training. Default is 0.1. + /// + /// + public double Lambda { get; set; } + + /// + /// Constructs a new Newton-Raphson learning algorithm + /// for Cox's Proportional Hazards models. + /// + /// + /// The model to estimate. + /// + public ProportionalHazardsNewtonRaphson(ProportionalHazards hazards) + { + this.regression = hazards; + this.parameterCount = hazards.Coefficients.Length; + + this.hessian = new double[parameterCount, parameterCount]; + this.gradient = new double[parameterCount]; + + this.partialHessian = new double[parameterCount, parameterCount]; + this.partialGradient = new double[parameterCount]; + + this.convergence = new RelativeParameterConvergence() + { + Iterations = 0, + Tolerance = 1e-5 + }; + + this.Estimator = HazardEstimator.BreslowNelsonAalen; + this.Ties = HazardTiesMethod.Efron; + this.Lambda = 0.1; + } + + + /// + /// Runs the Newton-Raphson update for Cox's hazards learning until convergence. + /// + /// + /// The input data. + /// The time-to-event for the training samples. + /// + /// The maximum relative change in the parameters after the iteration. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", + "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "1#")] + public double Run(double[][] inputs, double[] time) + { + var censor = new SurvivalOutcome[time.Length]; + + System.Diagnostics.Debug.Assert(censor[0] == SurvivalOutcome.Failed); + + return Run(inputs, time, censor); + } + + /// + /// Runs the Newton-Raphson update for Cox's hazards learning until convergence. + /// + /// + /// The input data. + /// The output (event) associated with each input vector. + /// The time-to-event for the non-censored training samples. + /// + /// The maximum relative change in the parameters after the iteration. + /// + public double Run(double[][] inputs, double[] time, int[] censor) + { + return Run(inputs, time, censor.To()); + } + + /// + /// Runs the Newton-Raphson update for Cox's hazards learning until convergence. + /// + /// + /// The input data. + /// The output (event) associated with each input vector. + /// The time-to-event for the non-censored training samples. + /// + /// The maximum relative change in the parameters after the iteration. + /// + public double Run(double[][] inputs, double[] time, SurvivalOutcome[] censor) + { + if (inputs.Length != time.Length || time.Length != censor.Length) + { + throw new DimensionMismatchException("time", + "The inputs, time and output vector must have the same length."); + } + + + // Sort data by time to accelerate performance + EmpiricalHazardDistribution.Sort(ref time, ref censor, ref inputs); + + + double[] means = new double[parameterCount]; + double[] sdev = new double[parameterCount]; + for (int i = 0; i < sdev.Length; i++) + sdev[i] = 1; + + if (normalize) + { + // Store means as regression centers + means = inputs.Mean(); + for (int i = 0; i < means.Length; i++) + regression.Offsets[i] = means[i]; + + // Convert to unit scores for increased accuracy + sdev = Accord.Statistics.Tools.StandardDeviation(inputs); + inputs = inputs.Subtract(means, 0).ElementwiseDivide(sdev, 0, inPlace: true); + + for (int i = 0; i < regression.Coefficients.Length; i++) + regression.Coefficients[i] *= sdev[i]; + } + + + + // Compute actual outputs + double[] output = new double[inputs.Length]; + for (int i = 0; i < output.Length; i++) + { + double sum = 0; + for (int j = 0; j < regression.Coefficients.Length; j++) + sum += regression.Coefficients[j] * inputs[i][j]; + output[i] = Math.Exp(sum); + } + + // Compute ties + int[] ties = new int[inputs.Length]; + for (int i = 0; i < inputs.Length; i++) + for (int j = 0; j < time.Length; j++) + if (time[j] == time[i]) ties[i]++; + + if (parameterCount == 0) + { + createBaseline(time, censor, output); + return regression.GetPartialLogLikelihood(inputs, time, censor); + } + + CurrentIteration = 0; + double smooth = Lambda; + + do + { + // learning iterations until convergence + // or maximum number of iterations reached + + CurrentIteration++; + + // Reset Hessian matrix and gradient + Array.Clear(gradient, 0, gradient.Length); + Array.Clear(hessian, 0, hessian.Length); + + // For each observation instance + for (int i = 0; i < inputs.Length; i++) + { + // Check if we should censor + if (censor[i] == SurvivalOutcome.Censored) + continue; + + // Compute partials + double den = 0; + Array.Clear(partialGradient, 0, partialGradient.Length); + Array.Clear(partialHessian, 0, partialHessian.Length); + + for (int j = 0; j < inputs.Length; j++) + { + if (time[j] >= time[i]) + den += output[j]; + } + + for (int j = 0; j < inputs.Length; j++) + { + if (time[j] >= time[i]) + { + // Compute partial gradient + for (int k = 0; k < partialGradient.Length; k++) + partialGradient[k] += inputs[j][k] * output[j] / den; + + // Compute partial Hessian + for (int ii = 0; ii < inputs[j].Length; ii++) + for (int jj = 0; jj < inputs[j].Length; jj++) + partialHessian[ii, jj] += inputs[j][ii] * inputs[j][jj] * output[j] / den; + } + } + + // Compute gradient vector + for (int j = 0; j < gradient.Length; j++) + gradient[j] += inputs[i][j] - partialGradient[j]; + + // Compute Hessian matrix + for (int j = 0; j < partialGradient.Length; j++) + for (int k = 0; k < partialGradient.Length; k++) + hessian[j, k] -= partialHessian[j, k] - partialGradient[j] * partialGradient[k]; + } + + + // Decompose to solve the linear system. Usually the Hessian will + // be invertible and LU will succeed. However, sometimes the Hessian + // may be singular and a Singular Value Decomposition may be needed. + + // The SVD is very stable, but is quite expensive, being on average + // about 10-15 times more expensive than LU decomposition. There are + // other ways to avoid a singular Hessian. For a very interesting + // reading on the subject, please see: + // + // - Jeff Gill & Gary King, "What to Do When Your Hessian Is Not Invertible", + // Sociological Methods & Research, Vol 33, No. 1, August 2004, 54-87. + // Available in: http://gking.harvard.edu/files/help.pdf + // + + decomposition = new SingularValueDecomposition(hessian); + double[] deltas = decomposition.Solve(gradient); + + if (convergence.Iterations > 0 || convergence.Tolerance > 0) + { + // Update coefficients using the calculated deltas + for (int i = 0; i < regression.Coefficients.Length; i++) + regression.Coefficients[i] -= smooth * deltas[i]; + } + + smooth += Lambda; + if (smooth > 1) + smooth = 1; + + // Check relative maximum parameter change + convergence.NewValues = regression.Coefficients; + + + if (convergence.HasDiverged) + { + // Restore previous coefficients + for (int i = 0; i < regression.Coefficients.Length; i++) + regression.Coefficients[i] = convergence.OldValues[i]; + } + + // Recompute current outputs + for (int i = 0; i < output.Length; i++) + { + double sum = 0; + for (int j = 0; j < regression.Coefficients.Length; j++) + sum += regression.Coefficients[j] * inputs[i][j]; + output[i] = Math.Exp(sum); + } + + } while (!convergence.HasConverged); + + + for (int i = 0; i < regression.Coefficients.Length; i++) + regression.Coefficients[i] /= sdev[i]; + + if (computeStandardErrors) + { + // Grab the regression information matrix + double[,] inverse = decomposition.Inverse(); + + // Calculate coefficients' standard errors + double[] standardErrors = regression.StandardErrors; + for (int i = 0; i < standardErrors.Length; i++) + standardErrors[i] = Math.Sqrt(Math.Abs(inverse[i, i])) / sdev[i]; + } + + if (computeBaselineFunction) + createBaseline(time, censor, output); + + return regression.GetPartialLogLikelihood(inputs, time, censor); + } + + /// + /// Runs the Newton-Raphson update for Cox's hazards learning until convergence. + /// + /// + /// The output (event) associated with each input vector. + /// The time-to-event for the non-censored training samples. + /// + /// The maximum relative change in the parameters after the iteration. + /// + public double Run(double[] time, int[] censor) + { + return Run(time, censor.To()); + } + + /// + /// Runs the Newton-Raphson update for Cox's hazards learning until convergence. + /// + /// + /// The output (event) associated with each input vector. + /// The time-to-event for the non-censored training samples. + /// + /// The maximum relative change in the parameters after the iteration. + /// + public double Run(double[] time, SurvivalOutcome[] censor) + { + if (time.Length != censor.Length) + { + throw new DimensionMismatchException("time", + "The time and output vector must have the same length."); + } + + // Sort data by time to accelerate performance + EmpiricalHazardDistribution.Sort(ref time, ref censor); + + createBaseline(time, censor); + + return regression.GetPartialLogLikelihood(time, censor); + } + + private void createBaseline(double[] time, SurvivalOutcome[] censor, double[] output = null) + { + if (regression.BaselineHazard == null) + return; + + var hazard = regression.BaselineHazard as IFittableDistribution; + if (hazard != null) + { + // Compute an estimate of the cumulative Hazard + // function using the Nelson-Aalen estimator + hazard.Fit(time, output, new EmpiricalHazardOptions() + { + Outcome = censor, + Estimator = Estimator, + Ties = Ties + }); + return; + } + + var survival = regression.BaselineHazard as IFittableDistribution; + if (survival != null) + { + // Compute an estimate of the cumulative Hazard + // function using the Kaplan-Meier estimator + survival.Fit(time, new SurvivalOptions() + { + Outcome = censor, + }); + } + } + + + } +} diff --git a/Sources/Accord.Statistics/Models/Survival/ProportionalHazards.cs b/Sources/Accord.Statistics/Models/Survival/ProportionalHazards.cs index 75d978b5d..71558aa2d 100644 --- a/Sources/Accord.Statistics/Models/Survival/ProportionalHazards.cs +++ b/Sources/Accord.Statistics/Models/Survival/ProportionalHazards.cs @@ -27,6 +27,7 @@ namespace Accord.Statistics.Models.Regression using Accord.Statistics.Distributions.Univariate; using Accord.Statistics.Testing; using AForge; + using Accord.Math; /// /// Cox's Proportional Hazards Model. @@ -151,6 +152,40 @@ public double Compute(double[] input, double time) return h0 * exp; } + /// + /// Computes the model output for the given time. + /// + /// + /// The event time. + /// + /// The probabilities of the event occurring at the given time. + /// + public double Compute(double time) + { + if (BaselineHazard == null) + throw new InvalidOperationException(); + + return BaselineHazard.CumulativeHazardFunction(time); + } + + /// + /// Computes the model's baseline survival function. This method + /// simply calls the + /// of the function. + /// + /// + /// The event time. + /// + /// The baseline survival function at the given time. + /// + public double Survival(double time) + { + if (BaselineHazard == null) + throw new InvalidOperationException(); + + return BaselineHazard.ComplementaryDistributionFunction(time); + } + /// /// Computes the model output for the given input vector. /// @@ -201,7 +236,7 @@ public double GetLogHazardRatio(double[] x, double[] y) /// calculated over the given data sets. /// /// - public double GetDeviance(double[][] inputs, double[] time, int[] output) + public double GetDeviance(double[][] inputs, double[] time, SurvivalOutcome[] output) { return -2.0 * GetPartialLogLikelihood(inputs, time, output); } @@ -220,6 +255,24 @@ public double GetDeviance(double[][] inputs, double[] time, int[] output) /// /// public double GetPartialLogLikelihood(double[][] inputs, double[] time, int[] output) + { + return GetPartialLogLikelihood(inputs, time, output.To()); + } + + /// + /// Gets the Partial Log-Likelihood for the model. + /// + /// + /// A set of input data. + /// The time-to-event before the output occurs. + /// The corresponding output data. + /// + /// + /// The Partial Log-Likelihood (a measure of performance) + /// of the model calculated over the given data set. + /// + /// + public double GetPartialLogLikelihood(double[][] inputs, double[] time, SurvivalOutcome[] output) { double sum1 = 0, sum2 = 0; for (int i = 0; i < inputs.Length; i++) @@ -228,7 +281,7 @@ public double GetPartialLogLikelihood(double[][] inputs, double[] time, int[] ou // Compute the first sum for (int j = 0; j < Coefficients.Length; j++) - sum1 += Coefficients[j] * inputs[i][j]; + sum1 += Coefficients[j] * (inputs[i][j] - Offsets[j]); // Compute the second sum double sum = 0; @@ -238,7 +291,7 @@ public double GetPartialLogLikelihood(double[][] inputs, double[] time, int[] ou { double s = 0; for (int k = 0; k < Coefficients.Length; k++) - s += Coefficients[k] * (inputs[j][k]); + s += Coefficients[k] * (inputs[j][k] - Offsets[k]); sum += Math.Exp(s); } } @@ -248,6 +301,58 @@ public double GetPartialLogLikelihood(double[][] inputs, double[] time, int[] ou return sum1 - sum2; } + /// + /// Gets the Partial Log-Likelihood for the model. + /// + /// + /// The time-to-event before the output occurs. + /// The corresponding output data. + /// + /// + /// The Partial Log-Likelihood (a measure of performance) + /// of the model calculated over the given data set. + /// + /// + public double GetPartialLogLikelihood(double[] time, int[] output) + { + return GetPartialLogLikelihood(time, output.To()); + } + + /// + /// Gets the Partial Log-Likelihood for the model. + /// + /// + /// The time-to-event before the output occurs. + /// The corresponding output data. + /// + /// + /// The Partial Log-Likelihood (a measure of performance) + /// of the model calculated over the given data set. + /// + /// + public double GetPartialLogLikelihood(double[] time, SurvivalOutcome[] output) + { + double sum2 = 0; + for (int i = 0; i < time.Length; i++) + { + if (output[i] == 0) + continue; + + // Compute the second sum + double sum = 0; + for (int j = 0; j < time.Length; j++) + { + if (time[j] >= time[i]) + sum++; + } + + sum2 += Math.Log(sum); + } + + return -sum2; + } + + /// /// Gets the 95% confidence interval for the /// Hazard Ratio for a given coefficient. @@ -308,7 +413,7 @@ public WaldTest GetWaldTest(int index) /// The Log-Likelihood ratio (a measure of performance /// between two models) calculated over the given data sets. /// - public double GetLogLikelihoodRatio(double[][] input, double[] time, int[] output, ProportionalHazards hazards) + public double GetLogLikelihoodRatio(double[][] input, double[] time, SurvivalOutcome[] output, ProportionalHazards hazards) { return 2.0 * (this.GetPartialLogLikelihood(input, time, output) - hazards.GetPartialLogLikelihood(input, time, output)); } @@ -333,7 +438,7 @@ public double GetLogLikelihoodRatio(double[][] input, double[] time, int[] outpu /// simpler model is often called the "model chi-square". /// /// - public ChiSquareTest ChiSquare(double[][] input, double[] time, int[] output) + public ChiSquareTest ChiSquare(double[][] input, double[] time, SurvivalOutcome[] output) { ProportionalHazards regression = new ProportionalHazards(Inputs); diff --git a/Sources/Accord.Video.DirectShow/Accord.Video.DirectShow.cd b/Sources/Accord.Video.DirectShow/Accord.Video.DirectShow.cd new file mode 100644 index 0000000000..bce57c7a9 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Accord.Video.DirectShow.cd @@ -0,0 +1,172 @@ + + + + + + + + + + FileVideoSource.cs + + + + + + AABABQYCQiACEAkAABAAQAQAAAAAAAAJIUAAAIAAAAI= + FileVideoSource.cs + + + + + + + AAAAAAAAAAAAAAQAAAAIAAQAAAAAAAAAAQAAAAAAhAA= + FilterInfo.cs + + + + + + + AAAABAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAA= + FilterInfoCollection.cs + + + + + + + + AAAAAEAAAAAAQAgAAAgAAAAAAAAAAAAAAAAAAAAAAAA= + Uuids.cs + + + + + + + + ABAAAAgAAAAAAAAAgAACAAAAgCAAAIAAACAAAAAAAiA= + VideoCapabilities.cs + + + + + + + + + + VideoCaptureDevice.cs + + + + + + QQBmRIaHAuEKPQkAEhEgQAQGQAACQgDIIYSCAIEBAAI= + VideoCaptureDevice.cs + + + + + + + + + IAAmAgAAJCQBABAAIQiIACACAyAAEAGAACAAoCAAAgA= + VideoCaptureDeviceForm.cs + + + + + + AAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAQEAAAAAAAA= + VideoInput.cs + + + + + + ACAAAAAAAAAAAgAAEDAAAAAAAAAAAAAAAAAAAAIABAA= + CameraControlProperty.cs + + + + + + AAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAACEAAAA= + CameraControlProperty.cs + + + + + + AAQFEIiEQQACAAAAAAAgqAICQABAAAAAIAAACgAAAEA= + PhysicalConnectorType.cs + + + + \ No newline at end of file diff --git a/Sources/Accord.Video.DirectShow/Accord.Video.DirectShow.csproj b/Sources/Accord.Video.DirectShow/Accord.Video.DirectShow.csproj new file mode 100644 index 0000000000..151d3cc19 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Accord.Video.DirectShow.csproj @@ -0,0 +1,178 @@ + + + + {26CD2CE7-FF63-4669-83B0-7D9C8F3408EE} + Accord.Video.DirectShow + Accord.Video.DirectShow + Debug + AnyCPU + AnyCPU + Library + Properties + True + 4 + True + true + Accord.snk + 3.5 + False + true + ..\Accord.NET.ruleset + false + true + 4096 + true + pdbonly + true + + + v4.5 + Full + False + true + False + True + DEBUG;TRACE + $(SolutionDir)..\Debug\ + + + $(SolutionDir)..\Release\net35 + TRACE;CODE_ANALYSIS;NET35 + v3.5 + $(SolutionDir)..\Release\net35\Accord.Video.DirectShow.XML + $(SolutionDir)..\Release\net35\Accord.Video.DirectShow.dll.CodeAnalysisLog.xml + + + $(SolutionDir)..\Release\net40 + TRACE;CODE_ANALYSIS;NET40 + v4.0 + $(SolutionDir)..\Release\net40\Accord.Video.DirectShow.XML + $(SolutionDir)..\Release\net40\Accord.Video.DirectShow.dll.CodeAnalysisLog.xml + + + $(SolutionDir)..\Release\net45 + TRACE;CODE_ANALYSIS;NET45 + v4.5 + $(SolutionDir)..\Release\net45\Accord.Video.DirectShow.XML + $(SolutionDir)..\Release\net45\Accord.Video.DirectShow.dll.CodeAnalysisLog.xml + + + + + + + + + Properties\VersionInfo.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + True + Resources.resx + + + + + + Form + + + VideoCaptureDeviceForm.cs + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 2.0 %28x86%29 + false + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + true + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + VideoCaptureDeviceForm.cs + + + + + + + + + {809725dc-6502-4732-a51c-deb7fea12975} + Accord.Video + + + + + \ No newline at end of file diff --git a/Sources/Accord.Video.DirectShow/Accord.snk b/Sources/Accord.Video.DirectShow/Accord.snk new file mode 100644 index 0000000000..ed97b4edd Binary files /dev/null and b/Sources/Accord.Video.DirectShow/Accord.snk differ diff --git a/Sources/Accord.Video.DirectShow/CameraControlProperty.cs b/Sources/Accord.Video.DirectShow/CameraControlProperty.cs new file mode 100644 index 0000000000..8ab1f6cca --- /dev/null +++ b/Sources/Accord.Video.DirectShow/CameraControlProperty.cs @@ -0,0 +1,67 @@ +// AForge Direct Show Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2009-2013 +// contacts@aforgenet.com +// + +namespace AForge.Video.DirectShow +{ + using System; + + /// + /// The enumeration specifies a setting on a camera. + /// + public enum CameraControlProperty + { + /// + /// Pan control. + /// + Pan = 0, + /// + /// Tilt control. + /// + Tilt, + /// + /// Roll control. + /// + Roll, + /// + /// Zoom control. + /// + Zoom, + /// + /// Exposure control. + /// + Exposure, + /// + /// Iris control. + /// + Iris, + /// + /// Focus control. + /// + Focus + } + + /// + /// The enumeration defines whether a camera setting is controlled manually or automatically. + /// + [Flags] + public enum CameraControlFlags + { + /// + /// No control flag. + /// + None = 0x0, + /// + /// Auto control Flag. + /// + Auto = 0x0001, + /// + /// Manual control Flag. + /// + Manual = 0x0002 + } +} diff --git a/Sources/Accord.Video.DirectShow/FileVideoSource.cs b/Sources/Accord.Video.DirectShow/FileVideoSource.cs new file mode 100644 index 0000000000..d3754674d --- /dev/null +++ b/Sources/Accord.Video.DirectShow/FileVideoSource.cs @@ -0,0 +1,621 @@ +// AForge Direct Show Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2009-2011 +// contacts@aforgenet.com +// + +namespace AForge.Video.DirectShow +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + using System.Threading; + using System.Runtime.InteropServices; + + using AForge.Video; + using AForge.Video.DirectShow.Internals; + + /// + /// Video source for video files. + /// + /// + /// The video source provides access to video files. DirectShow is used to access video + /// files. + /// + /// Sample usage: + /// + /// // create video source + /// FileVideoSource videoSource = new FileVideoSource( fileName ); + /// // set NewFrame event handler + /// videoSource.NewFrame += new NewFrameEventHandler( video_NewFrame ); + /// // start the video source + /// videoSource.Start( ); + /// // ... + /// // signal to stop + /// videoSource.SignalToStop( ); + /// // ... + /// + /// // New frame event handler, which is invoked on each new available video frame + /// private void video_NewFrame( object sender, NewFrameEventArgs eventArgs ) + /// { + /// // get new frame + /// Bitmap bitmap = eventArgs.Frame; + /// // process the frame + /// } + /// + /// + /// + public class FileVideoSource : IVideoSource + { + // video file name + private string fileName; + // received frames count + private int framesReceived; + // recieved byte count + private long bytesReceived; + // prevent freezing + private bool preventFreezing = false; + // reference clock for the graph - when disabled, graph processes frames ASAP + private bool referenceClockEnabled = true; + + private Thread thread = null; + private ManualResetEvent stopEvent = null; + + /// + /// New frame event. + /// + /// + /// Notifies clients about new available frame from video source. + /// + /// Since video source may have multiple clients, each client is responsible for + /// making a copy (cloning) of the passed video frame, because the video source disposes its + /// own original copy after notifying of clients. + /// + /// + public event NewFrameEventHandler NewFrame; + + /// + /// Video source error event. + /// + /// + /// This event is used to notify clients about any type of errors occurred in + /// video source object, for example internal exceptions. + /// + public event VideoSourceErrorEventHandler VideoSourceError; + + /// + /// Video playing finished event. + /// + /// + /// This event is used to notify clients that the video playing has finished. + /// + /// + public event PlayingFinishedEventHandler PlayingFinished; + + /// + /// Video source. + /// + /// + /// Video source is represented by video file name. + /// + public virtual string Source + { + get { return fileName; } + set { fileName = value; } + } + + /// + /// Received frames count. + /// + /// + /// Number of frames the video source provided from the moment of the last + /// access to the property. + /// + /// + public int FramesReceived + { + get + { + int frames = framesReceived; + framesReceived = 0; + return frames; + } + } + + /// + /// Received bytes count. + /// + /// + /// Number of bytes the video source provided from the moment of the last + /// access to the property. + /// + /// + public long BytesReceived + { + get + { + long bytes = bytesReceived; + bytesReceived = 0; + return bytes; + } + } + + /// + /// State of the video source. + /// + /// + /// Current state of video source object - running or not. + /// + public bool IsRunning + { + get + { + if ( thread != null ) + { + // check thread status + if ( thread.Join( 0 ) == false ) + return true; + + // the thread is not running, free resources + Free( ); + } + return false; + } + } + + /// + /// Prevent video freezing after screen saver and workstation lock or not. + /// + /// + /// + /// The value specifies if the class should prevent video freezing during and + /// after screen saver or workstation lock. To prevent freezing the DirectShow graph + /// should not contain Renderer filter, which is added by Render() method + /// of graph. However, in some cases it may be required to call Render() method of graph, since + /// it may add some more filters, which may be required for playing video. So, the property is + /// a trade off - it is possible to prevent video freezing skipping adding renderer filter or + /// it is possible to keep renderer filter, but video may freeze during screen saver. + /// + /// The property may become obsolete in the future when approach to disable freezing + /// and adding all required filters is found. + /// + /// The property should be set before calling method + /// of the class to have effect. + /// + /// Default value of this property is set to false. + /// + /// + /// + public bool PreventFreezing + { + get { return preventFreezing; } + set { preventFreezing = value; } + } + + /// + /// Enables/disables reference clock on the graph. + /// + /// + /// Disabling reference clocks causes DirectShow graph to run as fast as + /// it can process data. When enabled, it will process frames according to presentation + /// time of a video file. + /// + /// The property should be set before calling method + /// of the class to have effect. + /// + /// Default value of this property is set to true. + /// + /// + public bool ReferenceClockEnabled + { + get { return referenceClockEnabled; } + set { referenceClockEnabled = value;} + } + + /// + /// Initializes a new instance of the class. + /// + /// + public FileVideoSource( ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Video file name. + /// + public FileVideoSource( string fileName ) + { + this.fileName = fileName; + } + + /// + /// Start video source. + /// + /// + /// Starts video source and return execution to caller. Video source + /// object creates background thread and notifies about new frames with the + /// help of event. + /// + public void Start( ) + { + if ( !IsRunning ) + { + // check source + if ( ( fileName == null ) || ( fileName == string.Empty ) ) + throw new ArgumentException( "Video source is not specified" ); + + framesReceived = 0; + bytesReceived = 0; + + // create events + stopEvent = new ManualResetEvent( false ); + + // create and start new thread + thread = new Thread( new ThreadStart( WorkerThread ) ); + thread.Name = fileName; // mainly for debugging + thread.Start( ); + } + } + + /// + /// Signal video source to stop its work. + /// + /// + /// Signals video source to stop its background thread, stop to + /// provide new frames and free resources. + /// + public void SignalToStop( ) + { + // stop thread + if ( thread != null ) + { + // signal to stop + stopEvent.Set( ); + } + } + + /// + /// Wait for video source has stopped. + /// + /// + /// Waits for source stopping after it was signalled to stop using + /// method. + /// + public void WaitForStop( ) + { + if ( thread != null ) + { + // wait for thread stop + thread.Join( ); + + Free( ); + } + } + + /// + /// Stop video source. + /// + /// + /// Stops video source aborting its thread. + /// + /// Since the method aborts background thread, its usage is highly not preferred + /// and should be done only if there are no other options. The correct way of stopping camera + /// is signaling it stop and then + /// waiting for background thread's completion. + /// + /// + public void Stop( ) + { + if ( this.IsRunning ) + { + thread.Abort( ); + WaitForStop( ); + } + } + + /// + /// Free resource. + /// + /// + private void Free( ) + { + thread = null; + + // release events + stopEvent.Close( ); + stopEvent = null; + } + + /// + /// Worker thread. + /// + /// + private void WorkerThread( ) + { + ReasonToFinishPlaying reasonToStop = ReasonToFinishPlaying.StoppedByUser; + + // grabber + Grabber grabber = new Grabber( this ); + + // objects + object graphObject = null; + object grabberObject = null; + + // interfaces + IGraphBuilder graph = null; + IBaseFilter sourceBase = null; + IBaseFilter grabberBase = null; + ISampleGrabber sampleGrabber = null; + IMediaControl mediaControl = null; + + IMediaEventEx mediaEvent = null; + + try + { + // get type for filter graph + Type type = Type.GetTypeFromCLSID( Clsid.FilterGraph ); + if ( type == null ) + throw new ApplicationException( "Failed creating filter graph" ); + + // create filter graph + graphObject = Activator.CreateInstance( type ); + graph = (IGraphBuilder) graphObject; + + // create source device's object + graph.AddSourceFilter( fileName, "source", out sourceBase ); + if ( sourceBase == null ) + throw new ApplicationException( "Failed creating source filter" ); + + // get type for sample grabber + type = Type.GetTypeFromCLSID( Clsid.SampleGrabber ); + if ( type == null ) + throw new ApplicationException( "Failed creating sample grabber" ); + + // create sample grabber + grabberObject = Activator.CreateInstance( type ); + sampleGrabber = (ISampleGrabber) grabberObject; + grabberBase = (IBaseFilter) grabberObject; + + // add grabber filters to graph + graph.AddFilter( grabberBase, "grabber" ); + + // set media type + AMMediaType mediaType = new AMMediaType( ); + mediaType.MajorType = MediaType.Video; + mediaType.SubType = MediaSubType.RGB24; + sampleGrabber.SetMediaType( mediaType ); + + // connect pins + int pinToTry = 0; + + IPin inPin = Tools.GetInPin( grabberBase, 0 ); + IPin outPin = null; + + // find output pin acceptable by sample grabber + while ( true ) + { + outPin = Tools.GetOutPin( sourceBase, pinToTry ); + + if ( outPin == null ) + { + Marshal.ReleaseComObject( inPin ); + throw new ApplicationException( "Did not find acceptable output video pin in the given source" ); + } + + if ( graph.Connect( outPin, inPin ) < 0 ) + { + Marshal.ReleaseComObject( outPin ); + outPin = null; + pinToTry++; + } + else + { + break; + } + } + + Marshal.ReleaseComObject( outPin ); + Marshal.ReleaseComObject( inPin ); + + // get media type + if ( sampleGrabber.GetConnectedMediaType( mediaType ) == 0 ) + { + VideoInfoHeader vih = (VideoInfoHeader) Marshal.PtrToStructure( mediaType.FormatPtr, typeof( VideoInfoHeader ) ); + + grabber.Width = vih.BmiHeader.Width; + grabber.Height = vih.BmiHeader.Height; + mediaType.Dispose( ); + } + + // let's do rendering, if we don't need to prevent freezing + if ( !preventFreezing ) + { + // render pin + graph.Render( Tools.GetOutPin( grabberBase, 0 ) ); + + // configure video window + IVideoWindow window = (IVideoWindow) graphObject; + window.put_AutoShow( false ); + window = null; + } + + // configure sample grabber + sampleGrabber.SetBufferSamples( false ); + sampleGrabber.SetOneShot( false ); + sampleGrabber.SetCallback( grabber, 1 ); + + // disable clock, if someone requested it + if ( !referenceClockEnabled ) + { + IMediaFilter mediaFilter = (IMediaFilter) graphObject; + mediaFilter.SetSyncSource( null ); + } + + // get media control + mediaControl = (IMediaControl) graphObject; + + // get media events' interface + mediaEvent = (IMediaEventEx) graphObject; + IntPtr p1, p2; + DsEvCode code; + + // run + mediaControl.Run( ); + + do + { + if ( mediaEvent != null ) + { + if ( mediaEvent.GetEvent( out code, out p1, out p2, 0 ) >= 0 ) + { + mediaEvent.FreeEventParams( code, p1, p2 ); + + if ( code == DsEvCode.Complete ) + { + reasonToStop = ReasonToFinishPlaying.EndOfStreamReached; + break; + } + } + } + } + while ( !stopEvent.WaitOne( 100, false ) ); + + mediaControl.Stop( ); + } + catch ( Exception exception ) + { + // provide information to clients + if ( VideoSourceError != null ) + { + VideoSourceError( this, new VideoSourceErrorEventArgs( exception.Message ) ); + } + } + finally + { + // release all objects + graph = null; + grabberBase = null; + sampleGrabber = null; + mediaControl = null; + mediaEvent = null; + + if ( graphObject != null ) + { + Marshal.ReleaseComObject( graphObject ); + graphObject = null; + } + if ( sourceBase != null ) + { + Marshal.ReleaseComObject( sourceBase ); + sourceBase = null; + } + if ( grabberObject != null ) + { + Marshal.ReleaseComObject( grabberObject ); + grabberObject = null; + } + } + + if ( PlayingFinished != null ) + { + PlayingFinished( this, reasonToStop ); + } + } + + /// + /// Notifies client about new frame. + /// + /// + /// New frame's image. + /// + protected void OnNewFrame( Bitmap image ) + { + framesReceived++; + bytesReceived += image.Width * image.Height * ( Bitmap.GetPixelFormatSize( image.PixelFormat ) >> 3 ); + + if ( ( !stopEvent.WaitOne( 0, false ) ) && ( NewFrame != null ) ) + NewFrame( this, new NewFrameEventArgs( image ) ); + } + + // + // Video grabber + // + private class Grabber : ISampleGrabberCB + { + private FileVideoSource parent; + private int width, height; + + // Width property + public int Width + { + get { return width; } + set { width = value; } + } + // Height property + public int Height + { + get { return height; } + set { height = value; } + } + + // Constructor + public Grabber( FileVideoSource parent ) + { + this.parent = parent; + } + + // Callback to receive samples + public int SampleCB( double sampleTime, IntPtr sample ) + { + return 0; + } + + // Callback method that receives a pointer to the sample buffer + public int BufferCB( double sampleTime, IntPtr buffer, int bufferLen ) + { + if ( parent.NewFrame != null ) + { + // create new image + System.Drawing.Bitmap image = new Bitmap( width, height, PixelFormat.Format24bppRgb ); + + // lock bitmap data + BitmapData imageData = image.LockBits( + new Rectangle( 0, 0, width, height ), + ImageLockMode.ReadWrite, + PixelFormat.Format24bppRgb ); + + // copy image data + int srcStride = imageData.Stride; + int dstStride = imageData.Stride; + + unsafe + { + byte* dst = (byte*) imageData.Scan0.ToPointer( ) + dstStride * ( height - 1 ); + byte* src = (byte*) buffer.ToPointer( ); + + for ( int y = 0; y < height; y++ ) + { + Win32.memcpy( dst, src, srcStride ); + dst -= dstStride; + src += srcStride; + } + } + + // unlock bitmap data + image.UnlockBits( imageData ); + + // notify parent + parent.OnNewFrame( image ); + + // release the image + image.Dispose( ); + } + + return 0; + } + } + } +} diff --git a/Sources/Accord.Video.DirectShow/FilterInfo.cs b/Sources/Accord.Video.DirectShow/FilterInfo.cs new file mode 100644 index 0000000000..c70e9665f --- /dev/null +++ b/Sources/Accord.Video.DirectShow/FilterInfo.cs @@ -0,0 +1,193 @@ +// AForge Direct Show Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Video.DirectShow +{ + using System; + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.ComTypes; + using AForge.Video.DirectShow.Internals; + + /// + /// DirectShow filter information. + /// + /// + public class FilterInfo : IComparable + { + /// + /// Filter name. + /// + public string Name { get; private set; } + + /// + /// Filters's moniker string. + /// + /// + public string MonikerString { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Filters's moniker string. + /// + public FilterInfo( string monikerString ) + { + MonikerString = monikerString; + Name = GetName( monikerString ); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Filter's moniker object. + /// + internal FilterInfo( IMoniker moniker ) + { + MonikerString = GetMonikerString( moniker ); + Name = GetName( moniker ); + } + + /// + /// Compare the object with another instance of this class. + /// + /// + /// Object to compare with. + /// + /// A signed number indicating the relative values of this instance and value. + /// + public int CompareTo( object value ) + { + FilterInfo f = (FilterInfo) value; + + if ( f == null ) + return 1; + + return ( this.Name.CompareTo( f.Name ) ); + } + + /// + /// Create an instance of the filter. + /// + /// + /// Filter's moniker string. + /// + /// Returns filter's object, which implements IBaseFilter interface. + /// + /// The returned filter's object should be released using Marshal.ReleaseComObject(). + /// + public static object CreateFilter( string filterMoniker ) + { + // filter's object + object filterObject = null; + // bind context and moniker objects + IBindCtx bindCtx = null; + IMoniker moniker = null; + + int n = 0; + + // create bind context + if ( Win32.CreateBindCtx( 0, out bindCtx ) == 0 ) + { + // convert moniker`s string to a moniker + if ( Win32.MkParseDisplayName( bindCtx, filterMoniker, ref n, out moniker ) == 0 ) + { + // get device base filter + Guid filterId = typeof( IBaseFilter ).GUID; + moniker.BindToObject( null, null, ref filterId, out filterObject ); + + Marshal.ReleaseComObject( moniker ); + } + Marshal.ReleaseComObject( bindCtx ); + } + return filterObject; + } + + // + // Get moniker string of the moniker + // + private string GetMonikerString( IMoniker moniker ) + { + string str; + moniker.GetDisplayName( null, null, out str ); + return str; + } + + // + // Get filter name represented by the moniker + // + private string GetName( IMoniker moniker ) + { + Object bagObj = null; + IPropertyBag bag = null; + + try + { + Guid bagId = typeof( IPropertyBag ).GUID; + // get property bag of the moniker + moniker.BindToStorage( null, null, ref bagId, out bagObj ); + bag = (IPropertyBag) bagObj; + + // read FriendlyName + object val = ""; + int hr = bag.Read( "FriendlyName", ref val, IntPtr.Zero ); + if ( hr != 0 ) + Marshal.ThrowExceptionForHR( hr ); + + // get it as string + string ret = (string) val; + if ( ( ret == null ) || ( ret.Length < 1 ) ) + throw new ApplicationException( ); + + return ret; + } + catch ( Exception ) + { + return ""; + } + finally + { + // release all COM objects + bag = null; + if ( bagObj != null ) + { + Marshal.ReleaseComObject( bagObj ); + bagObj = null; + } + } + } + + // + // Get filter name represented by the moniker string + // + private string GetName( string monikerString ) + { + IBindCtx bindCtx = null; + IMoniker moniker = null; + String name = ""; + int n = 0; + + // create bind context + if ( Win32.CreateBindCtx( 0, out bindCtx ) == 0 ) + { + // convert moniker`s string to a moniker + if ( Win32.MkParseDisplayName( bindCtx, monikerString, ref n, out moniker ) == 0 ) + { + // get device name + name = GetName( moniker ); + + Marshal.ReleaseComObject( moniker ); + moniker = null; + } + Marshal.ReleaseComObject( bindCtx ); + bindCtx = null; + } + return name; + } + } +} diff --git a/Sources/Accord.Video.DirectShow/FilterInfoCollection.cs b/Sources/Accord.Video.DirectShow/FilterInfoCollection.cs new file mode 100644 index 0000000000..dabd30d56 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/FilterInfoCollection.cs @@ -0,0 +1,138 @@ +// AForge Direct Show Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Video.DirectShow +{ + using System; + using System.Collections; + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.ComTypes; + using AForge.Video.DirectShow.Internals; + + /// + /// Collection of filters' information objects. + /// + /// + /// The class allows to enumerate DirectShow filters of specified category. For + /// a list of categories see . + /// + /// Sample usage: + /// + /// // enumerate video devices + /// videoDevices = new FilterInfoCollection( FilterCategory.VideoInputDevice ); + /// // list devices + /// foreach ( FilterInfo device in videoDevices ) + /// { + /// // ... + /// } + /// + /// + /// + public class FilterInfoCollection : CollectionBase + { + /// + /// Initializes a new instance of the class. + /// + /// + /// Guid of DirectShow filter category. See . + /// + /// Build collection of filters' information objects for the + /// specified filter category. + /// + public FilterInfoCollection( Guid category ) + { + CollectFilters( category ); + } + + /// + /// Get filter information object. + /// + /// + /// Index of filter information object to retrieve. + /// + /// Filter information object. + /// + public FilterInfo this[int index] + { + get + { + return ( (FilterInfo) InnerList[index] ); + } + } + + // Collect filters of specified category + private void CollectFilters( Guid category ) + { + object comObj = null; + ICreateDevEnum enumDev = null; + IEnumMoniker enumMon = null; + IMoniker[] devMon = new IMoniker[1]; + int hr; + + try + { + // Get the system device enumerator + Type srvType = Type.GetTypeFromCLSID( Clsid.SystemDeviceEnum ); + if ( srvType == null ) + throw new ApplicationException( "Failed creating device enumerator" ); + + // create device enumerator + comObj = Activator.CreateInstance( srvType ); + enumDev = (ICreateDevEnum) comObj; + + // Create an enumerator to find filters of specified category + hr = enumDev.CreateClassEnumerator( ref category, out enumMon, 0 ); + if ( hr != 0 ) + throw new ApplicationException( "No devices of the category" ); + + // Collect all filters + IntPtr n = IntPtr.Zero; + while ( true ) + { + // Get next filter + hr = enumMon.Next( 1, devMon, n ); + if ( ( hr != 0 ) || ( devMon[0] == null ) ) + break; + + // Add the filter + FilterInfo filter = new FilterInfo( devMon[0] ); + InnerList.Add( filter ); + + // Release COM object + Marshal.ReleaseComObject( devMon[0] ); + devMon[0] = null; + } + + // Sort the collection + InnerList.Sort( ); + } + catch + { + } + finally + { + // release all COM objects + enumDev = null; + if ( comObj != null ) + { + Marshal.ReleaseComObject( comObj ); + comObj = null; + } + if ( enumMon != null ) + { + Marshal.ReleaseComObject( enumMon ); + enumMon = null; + } + if ( devMon[0] != null ) + { + Marshal.ReleaseComObject( devMon[0] ); + devMon[0] = null; + } + } + } + } +} diff --git a/Sources/Accord.Video.DirectShow/Icons/camera.png b/Sources/Accord.Video.DirectShow/Icons/camera.png new file mode 100644 index 0000000000..d16b2bb00 Binary files /dev/null and b/Sources/Accord.Video.DirectShow/Icons/camera.png differ diff --git a/Sources/Accord.Video.DirectShow/Images/VideoCaptureDeviceForm.png b/Sources/Accord.Video.DirectShow/Images/VideoCaptureDeviceForm.png new file mode 100644 index 0000000000..5de50a2a2 Binary files /dev/null and b/Sources/Accord.Video.DirectShow/Images/VideoCaptureDeviceForm.png differ diff --git a/Sources/Accord.Video.DirectShow/Internals/IAMCameraControl.cs b/Sources/Accord.Video.DirectShow/Internals/IAMCameraControl.cs new file mode 100644 index 0000000000..c207797fd --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/IAMCameraControl.cs @@ -0,0 +1,81 @@ +// AForge Direct Show Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2009-2013 +// contacts@aforgenet.com +// + +namespace AForge.Video.DirectShow.Internals +{ + using System; + using System.Runtime.InteropServices; + + /// + /// The IAMCameraControl interface controls camera settings such as zoom, pan, aperture adjustment, + /// or shutter speed. To obtain this interface, query the filter that controls the camera. + /// + [ComImport, + Guid( "C6E13370-30AC-11d0-A18C-00A0C9118956" ), + InterfaceType( ComInterfaceType.InterfaceIsIUnknown )] + internal interface IAMCameraControl + { + /// + /// Gets the range and default value of a specified camera property. + /// + /// + /// Specifies the property to query. + /// Receives the minimum value of the property. + /// Receives the maximum value of the property. + /// Receives the step size for the property. + /// Receives the default value of the property. + /// Receives a member of the CameraControlFlags enumeration, indicating whether the property is controlled automatically or manually. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetRange( + [In] CameraControlProperty Property, + [Out] out int pMin, + [Out] out int pMax, + [Out] out int pSteppingDelta, + [Out] out int pDefault, + [Out] out CameraControlFlags pCapsFlags + ); + + /// + /// Sets a specified property on the camera. + /// + /// + /// Specifies the property to set. + /// Specifies the new value of the property. + /// Specifies the desired control setting, as a member of the CameraControlFlags enumeration. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Set( + [In] CameraControlProperty Property, + [In] int lValue, + [In] CameraControlFlags Flags + ); + + /// + /// Gets the current setting of a camera property. + /// + /// + /// Specifies the property to retrieve. + /// Receives the value of the property. + /// Receives a member of the CameraControlFlags enumeration. + /// The returned value indicates whether the setting is controlled manually or automatically. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Get( + [In] CameraControlProperty Property, + [Out] out int lValue, + [Out] out CameraControlFlags Flags + ); + } +} diff --git a/Sources/Accord.Video.DirectShow/Internals/IAMCrossbar.cs b/Sources/Accord.Video.DirectShow/Internals/IAMCrossbar.cs new file mode 100644 index 0000000000..b67fc091d --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/IAMCrossbar.cs @@ -0,0 +1,88 @@ +// AForge Direct Show Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2009-2012 +// contacts@aforgenet.com +// + +using System; +using System.Runtime.InteropServices; + +namespace AForge.Video.DirectShow.Internals +{ + /// + /// The IAMCrossbar interface routes signals from an analog or digital source to a video capture filter. + /// + [ComImport, System.Security.SuppressUnmanagedCodeSecurity, + Guid( "C6E13380-30AC-11D0-A18C-00A0C9118956" ), + InterfaceType( ComInterfaceType.InterfaceIsIUnknown )] + internal interface IAMCrossbar + { + /// + /// Retrieves the number of input and output pins on the crossbar filter. + /// + /// + /// Variable that receives the number of output pins. + /// Variable that receives the number of input pins. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int get_PinCounts( [Out] out int outputPinCount, [Out] out int inputPinCount ); + + /// + /// Queries whether a specified input pin can be routed to a specified output pin. + /// + /// + /// Specifies the index of the output pin. + /// Specifies the index of input pin. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int CanRoute( [In] int outputPinIndex, [In] int inputPinIndex ); + + /// + /// Routes an input pin to an output pin. + /// + /// + /// Specifies the index of the output pin. + /// Specifies the index of the input pin. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Route( [In] int outputPinIndex, [In] int inputPinIndex ); + + /// + /// Retrieves the input pin that is currently routed to the specified output pin. + /// + /// + /// Specifies the index of the output pin. + /// Variable that receives the index of the input pin, or -1 if no input pin is routed to this output pin. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int get_IsRoutedTo( [In] int outputPinIndex, [Out] out int inputPinIndex ); + + /// + /// Retrieves information about a specified pin. + /// + /// + /// Specifies the direction of the pin. Use one of the following values. + /// Specifies the index of the pin. + /// Variable that receives the index of the related pin, or –1 if no pin is related to this pin. + /// Variable that receives a member of the PhysicalConnectorType enumeration, indicating the pin's physical type. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int get_CrossbarPinInfo( + [In, MarshalAs( UnmanagedType.Bool )] bool isInputPin, + [In] int pinIndex, + [Out] out int pinIndexRelated, + [Out] out PhysicalConnectorType physicalType ); + } +} diff --git a/Sources/Accord.Video.DirectShow/Internals/IAMStreamConfig.cs b/Sources/Accord.Video.DirectShow/Internals/IAMStreamConfig.cs new file mode 100644 index 0000000000..e72f06e19 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/IAMStreamConfig.cs @@ -0,0 +1,74 @@ +// AForge Direct Show Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Video.DirectShow.Internals +{ + using System; + using System.Runtime.InteropServices; + + /// + /// This interface sets the output format on certain capture and compression filters, + /// for both audio and video. + /// + /// + [ComImport, + Guid( "C6E13340-30AC-11d0-A18C-00A0C9118956" ), + InterfaceType( ComInterfaceType.InterfaceIsIUnknown )] + internal interface IAMStreamConfig + { + /// + /// Set the output format on the pin. + /// + /// + /// Media type to set. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int SetFormat( [In, MarshalAs( UnmanagedType.LPStruct )] AMMediaType mediaType ); + + /// + /// Retrieves the audio or video stream's format. + /// + /// + /// Retrieved media type. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetFormat( [Out, MarshalAs( UnmanagedType.LPStruct )] out AMMediaType mediaType ); + + /// + /// Retrieve the number of format capabilities that this pin supports. + /// + /// + /// Variable that receives the number of format capabilities. + /// Variable that receives the size of the configuration structure in bytes. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetNumberOfCapabilities( out int count, out int size ); + + /// + /// Retrieve a set of format capabilities. + /// + /// + /// Specifies the format capability to retrieve, indexed from zero. + /// Retrieved media type. + /// Byte array, which receives information about capabilities. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetStreamCaps( + [In] int index, + [Out, MarshalAs( UnmanagedType.LPStruct )] out AMMediaType mediaType, + [In, MarshalAs( UnmanagedType.LPStruct )] VideoStreamConfigCaps streamConfigCaps + ); + } +} diff --git a/Sources/Accord.Video.DirectShow/Internals/IAMVideoControl.cs b/Sources/Accord.Video.DirectShow/Internals/IAMVideoControl.cs new file mode 100644 index 0000000000..cb57dfe73 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/IAMVideoControl.cs @@ -0,0 +1,112 @@ +// AForge Direct Show Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2009-2011 +// contacts@aforgenet.com +// + +namespace AForge.Video.DirectShow.Internals +{ + using System; + using System.Runtime.InteropServices; + + /// + /// The interface controls certain video capture operations such as enumerating available + /// frame rates and image orientation. + /// + /// + [ComImport, + Guid( "6A2E0670-28E4-11D0-A18c-00A0C9118956" ), + InterfaceType( ComInterfaceType.InterfaceIsIUnknown )] + internal interface IAMVideoControl + { + /// + /// Retrieves the capabilities of the underlying hardware. + /// + /// + /// Pin to query capabilities from. + /// Get capabilities of the specified pin. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetCaps( [In] IPin pin, [Out, MarshalAs( UnmanagedType.I4 )] out VideoControlFlags flags ); + + /// + /// Sets the video control mode of operation. + /// + /// + /// The pin to set the video control mode on. + /// Value specifying a combination of the flags to set the video control mode. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int SetMode( [In] IPin pin, [In, MarshalAs( UnmanagedType.I4 )] VideoControlFlags mode ); + + /// + /// Retrieves the video control mode of operation. + /// + /// + /// The pin to retrieve the video control mode from. + /// Gets combination of flags, which specify the video control mode. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetMode( [In] IPin pin, [Out, MarshalAs( UnmanagedType.I4 )] out VideoControlFlags mode ); + + /// + /// The method retrieves the actual frame rate, expressed as a frame duration in 100-nanosecond units. + /// USB (Universal Serial Bus) and IEEE 1394 cameras may provide lower frame rates than requested + /// because of bandwidth availability. This is only available during video streaming. + /// + /// + /// The pin to retrieve the frame rate from. + /// Gets frame rate in frame duration in 100-nanosecond units. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetCurrentActualFrameRate( [In] IPin pin, [Out, MarshalAs( UnmanagedType.I8 )] out long actualFrameRate ); + + /// + /// Retrieves the maximum frame rate currently available based on bus bandwidth usage for connections + /// such as USB and IEEE 1394 camera devices where the maximum frame rate can be limited by bandwidth + /// availability. + /// + /// + /// The pin to retrieve the maximum frame rate from. + /// Index of the format to query for maximum frame rate. This index corresponds + /// to the order in which formats are enumerated by . + /// Frame image size (width and height) in pixels. + /// Gets maximum available frame rate. The frame rate is expressed as frame duration in 100-nanosecond units. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetMaxAvailableFrameRate( [In] IPin pin, [In] int index, + [In] System.Drawing.Size dimensions, + [Out] out long maxAvailableFrameRate ); + + /// + /// Retrieves a list of available frame rates. + /// + /// + /// The pin to retrieve the maximum frame rate from. + /// Index of the format to query for maximum frame rate. This index corresponds + /// to the order in which formats are enumerated by . + /// Frame image size (width and height) in pixels. + /// Number of elements in the list of frame rates. + /// Array of frame rates in 100-nanosecond units. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetFrameRateList( [In] IPin pin, [In] int index, + [In] System.Drawing.Size dimensions, + [Out] out int listSize, + [Out] out IntPtr frameRate ); + } +} diff --git a/Sources/Accord.Video.DirectShow/Internals/IBaseFilter.cs b/Sources/Accord.Video.DirectShow/Internals/IBaseFilter.cs new file mode 100644 index 0000000000..3c03a316f --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/IBaseFilter.cs @@ -0,0 +1,161 @@ +// AForge Direct Show Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2007 +// andrew.kirillov@gmail.com +// + +namespace AForge.Video.DirectShow.Internals +{ + using System; + using System.Runtime.InteropServices; + + /// + /// The IBaseFilter interface provides methods for controlling a filter. + /// All DirectShow filters expose this interface + /// + /// + [ComImport, + Guid( "56A86895-0AD4-11CE-B03A-0020AF0BA770" ), + InterfaceType( ComInterfaceType.InterfaceIsIUnknown )] + internal interface IBaseFilter + { + // --- IPersist Methods + + /// + /// Returns the class identifier (CLSID) for the component object. + /// + /// + /// Points to the location of the CLSID on return. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetClassID( [Out] out Guid ClassID ); + + // --- IMediaFilter Methods + + /// + /// Stops the filter. + /// + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Stop( ); + + /// + /// Pauses the filter. + /// + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Pause( ); + + /// + /// Runs the filter. + /// + /// + /// Reference time corresponding to stream time 0. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Run( long start ); + + /// + /// Retrieves the state of the filter (running, stopped, or paused). + /// + /// + /// Time-out interval, in milliseconds. + /// Pointer to a variable that receives filter's state. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetState( int milliSecsTimeout, [Out] out int filterState ); + + /// + /// Sets the reference clock for the filter or the filter graph. + /// + /// + /// Pointer to the clock's IReferenceClock interface, or NULL. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int SetSyncSource( [In] IntPtr clock ); + + /// + /// Retrieves the current reference clock. + /// + /// + /// Address of a variable that receives a pointer to the clock's IReferenceClock interface. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetSyncSource( [Out] out IntPtr clock ); + + // --- IBaseFilter Methods + + /// + /// Enumerates the pins on this filter. + /// + /// + /// Address of a variable that receives a pointer to the IEnumPins interface. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int EnumPins( [Out] out IEnumPins enumPins ); + + /// + /// Retrieves the pin with the specified identifier. + /// + /// + /// Pointer to a constant wide-character string that identifies the pin. + /// Address of a variable that receives a pointer to the pin's IPin interface. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int FindPin( [In, MarshalAs( UnmanagedType.LPWStr )] string id, [Out] out IPin pin ); + + /// + /// Retrieves information about the filter. + /// + /// + /// Pointer to FilterInfo structure. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int QueryFilterInfo( [Out] out FilterInfo filterInfo ); + + /// + /// Notifies the filter that it has joined or left the filter graph. + /// + /// + /// Pointer to the Filter Graph Manager's IFilterGraph interface, or NULL + /// if the filter is leaving the graph. + /// String that specifies a name for the filter. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int JoinFilterGraph( [In] IFilterGraph graph, [In, MarshalAs( UnmanagedType.LPWStr )] string name ); + + /// + /// Retrieves a string containing vendor information. + /// + /// + /// Receives a string containing the vendor information. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int QueryVendorInfo( [Out, MarshalAs( UnmanagedType.LPWStr )] out string vendorInfo ); + } +} diff --git a/Sources/Accord.Video.DirectShow/Internals/ICaptureGraphBuilder2.cs b/Sources/Accord.Video.DirectShow/Internals/ICaptureGraphBuilder2.cs new file mode 100644 index 0000000000..4ef802a37 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/ICaptureGraphBuilder2.cs @@ -0,0 +1,192 @@ +// AForge Direct Show Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Video.DirectShow.Internals +{ + using System; + using System.Runtime.InteropServices; + + /// + /// This interface builds capture graphs and other custom filter graphs. + /// + /// + [ComImport, + Guid( "93E5A4E0-2D50-11d2-ABFA-00A0C9C6E38D" ), + InterfaceType( ComInterfaceType.InterfaceIsIUnknown )] + internal interface ICaptureGraphBuilder2 + { + /// + /// Specify filter graph for the capture graph builder to use. + /// + /// + /// Filter graph's interface. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int SetFiltergraph( [In] IGraphBuilder graphBuilder ); + + /// + /// Retrieve the filter graph that the builder is using. + /// + /// + /// Filter graph's interface. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetFiltergraph( [Out] out IGraphBuilder graphBuilder ); + + /// + /// Create file writing section of the filter graph. + /// + /// + /// GUID that represents either the media subtype of the output or the + /// class identifier (CLSID) of a multiplexer filter or file writer filter. + /// Output file name. + /// Receives the multiplexer's interface. + /// Receives the file writer's IFileSinkFilter interface. Can be NULL. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int SetOutputFileName( + [In, MarshalAs( UnmanagedType.LPStruct )] Guid type, + [In, MarshalAs( UnmanagedType.LPWStr )] string fileName, + [Out] out IBaseFilter baseFilter, + [Out] out IntPtr fileSinkFilter + ); + + /// + /// Searche the graph for a specified interface, starting from a specified filter. + /// + /// + /// GUID that specifies the search criteria. + /// GUID that specifies the major media type of an output pin, or NULL. + /// interface of the filter. The method begins searching from this filter. + /// Interface identifier (IID) of the interface to locate. + /// Receives found interface. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int FindInterface( + [In, MarshalAs( UnmanagedType.LPStruct )] Guid category, + [In, MarshalAs( UnmanagedType.LPStruct )] Guid type, + [In] IBaseFilter baseFilter, + [In, MarshalAs( UnmanagedType.LPStruct )] Guid interfaceID , + [Out, MarshalAs( UnmanagedType.IUnknown )] out object retInterface + ); + + /// + /// Connect an output pin on a source filter to a rendering filter, optionally through a compression filter. + /// + /// + /// Pin category. + /// Major-type GUID that specifies the media type of the output pin. + /// Starting filter for the connection. + /// Interface of an intermediate filter, such as a compression filter. Can be NULL. + /// Sink filter, such as a renderer or mux filter. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int RenderStream( + [In, MarshalAs( UnmanagedType.LPStruct )] Guid category, + [In, MarshalAs( UnmanagedType.LPStruct )] Guid mediaType, + [In, MarshalAs( UnmanagedType.IUnknown )] object source, + [In] IBaseFilter compressor, + [In] IBaseFilter renderer + ); + + /// + /// Set the start and stop times for one or more streams of captured data. + /// + /// + /// Pin category. + /// Major-type GUID that specifies the media type. + /// interface that specifies which filter to control. + /// Start time. + /// Stop time. + /// Value that is sent as the second parameter of the + /// EC_STREAM_CONTROL_STARTED event notification. + /// Value that is sent as the second parameter of the + /// EC_STREAM_CONTROL_STOPPED event notification. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int ControlStream( + [In, MarshalAs( UnmanagedType.LPStruct )] Guid category, + [In, MarshalAs( UnmanagedType.LPStruct )] Guid mediaType, + [In, MarshalAs( UnmanagedType.Interface )] IBaseFilter filter, + [In] long start, + [In] long stop, + [In] short startCookie, + [In] short stopCookie + ); + + /// + /// Preallocate a capture file to a specified size. + /// + /// + /// File name to create or resize. + /// Size of the file to allocate, in bytes. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int AllocCapFile( + [In, MarshalAs( UnmanagedType.LPWStr )] string fileName, + [In] long size + ); + + /// + /// Copy the valid media data from a capture file. + /// + /// + /// Old file name. + /// New file name. + /// Boolean value that specifies whether pressing the ESC key cancels the copy operation. + /// IAMCopyCaptureFileProgress interface to display progress information, or NULL. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int CopyCaptureFile( + [In, MarshalAs( UnmanagedType.LPWStr )] string oldFileName, + [In, MarshalAs( UnmanagedType.LPWStr )] string newFileName, + [In, MarshalAs( UnmanagedType.Bool )] bool allowEscAbort, + [In] IntPtr callback + ); + + /// + /// + /// + /// + /// Interface on a filter, or to an interface on a pin. + /// Pin direction (input or output). + /// Pin category. + /// Media type. + /// Boolean value that specifies whether the pin must be unconnected. + /// Zero-based index of the pin to retrieve, from the set of matching pins. + /// Interface of the matching pin. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int FindPin( + [In, MarshalAs( UnmanagedType.IUnknown )] object source, + [In] PinDirection pinDirection, + [In, MarshalAs( UnmanagedType.LPStruct )] Guid category, + [In, MarshalAs( UnmanagedType.LPStruct )] Guid mediaType, + [In, MarshalAs( UnmanagedType.Bool )] bool unconnected, + [In] int index, + [Out, MarshalAs( UnmanagedType.Interface )] out IPin pin + ); + } +} diff --git a/Sources/Accord.Video.DirectShow/Internals/ICreateDevEnum.cs b/Sources/Accord.Video.DirectShow/Internals/ICreateDevEnum.cs new file mode 100644 index 0000000000..81e4b59f0 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/ICreateDevEnum.cs @@ -0,0 +1,37 @@ +// AForge Direct Show Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2007 +// andrew.kirillov@gmail.com +// + +namespace AForge.Video.DirectShow.Internals +{ + using System; + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.ComTypes; + + /// + /// The ICreateDevEnum interface creates an enumerator for devices within a particular category, + /// such as video capture devices, audio capture devices, video compressors, and so forth. + /// + /// + [ComImport, + Guid( "29840822-5B84-11D0-BD3B-00A0C911CE86" ), + InterfaceType( ComInterfaceType.InterfaceIsIUnknown )] + internal interface ICreateDevEnum + { + /// + /// Creates a class enumerator for a specified device category. + /// + /// + /// Specifies the class identifier of the device category. + /// Address of a variable that receives an IEnumMoniker interface pointer + /// Bitwise combination of zero or more flags. If zero, the method enumerates every filter in the category. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int CreateClassEnumerator( [In] ref Guid type, [Out] out IEnumMoniker enumMoniker, [In] int flags ); + } +} diff --git a/Sources/Accord.Video.DirectShow/Internals/IEnumFilters.cs b/Sources/Accord.Video.DirectShow/Internals/IEnumFilters.cs new file mode 100644 index 0000000000..a4c8eb936 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/IEnumFilters.cs @@ -0,0 +1,71 @@ +// AForge Direct Show Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2007-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Video.DirectShow.Internals +{ + using System; + using System.Runtime.InteropServices; + + /// + /// This interface is used by applications or other filters to determine + /// what filters exist in the filter graph. + /// + /// + [ComImport, + Guid( "56A86893-0AD4-11CE-B03A-0020AF0BA770" ), + InterfaceType( ComInterfaceType.InterfaceIsIUnknown )] + internal interface IEnumFilters + { + /// + /// Retrieves the specified number of filters in the enumeration sequence. + /// + /// + /// Number of filters to retrieve. + /// Array in which to place interfaces. + /// Actual number of filters placed in the array. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Next( [In] int cFilters, + [Out, MarshalAs( UnmanagedType.LPArray, SizeParamIndex = 0 )] IBaseFilter[] filters, + [Out] out int filtersFetched ); + + /// + /// Skips a specified number of filters in the enumeration sequence. + /// + /// + /// Number of filters to skip. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Skip( [In] int cFilters ); + + /// + /// Resets the enumeration sequence to the beginning. + /// + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Reset( ); + + /// + /// Makes a copy of the enumerator with the same enumeration state. + /// + /// + /// Duplicate of the enumerator. + /// + /// + /// Return's HRESULT error code. + /// + /// + [PreserveSig] + int Clone( [Out] out IEnumFilters enumFilters ); + } +} diff --git a/Sources/Accord.Video.DirectShow/Internals/IEnumPins.cs b/Sources/Accord.Video.DirectShow/Internals/IEnumPins.cs new file mode 100644 index 0000000000..41e1f740d --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/IEnumPins.cs @@ -0,0 +1,68 @@ +// AForge Direct Show Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2007 +// andrew.kirillov@gmail.com +// + +namespace AForge.Video.DirectShow.Internals +{ + using System; + using System.Runtime.InteropServices; + + /// + /// Enumerates pins on a filter. + /// + /// + [ComImport, + Guid( "56A86892-0AD4-11CE-B03A-0020AF0BA770" ), + InterfaceType( ComInterfaceType.InterfaceIsIUnknown )] + internal interface IEnumPins + { + /// + /// Retrieves a specified number of pins. + /// + /// + /// Number of pins to retrieve. + /// Array of size cPins that is filled with IPin pointers. + /// Receives the number of pins retrieved. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Next( [In] int cPins, + [Out, MarshalAs( UnmanagedType.LPArray, SizeParamIndex = 0 )] IPin[] pins, + [Out] out int pinsFetched ); + + /// + /// Skips a specified number of pins in the enumeration sequence. + /// + /// + /// Number of pins to skip. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Skip( [In] int cPins ); + + /// + /// Resets the enumeration sequence to the beginning. + /// + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Reset( ); + + /// + /// Makes a copy of the enumerator with the same enumeration state. + /// + /// + /// Duplicate of the enumerator. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Clone( [Out] out IEnumPins enumPins ); + } +} diff --git a/Sources/Accord.Video.DirectShow/Internals/IFileSourceFilter.cs b/Sources/Accord.Video.DirectShow/Internals/IFileSourceFilter.cs new file mode 100644 index 0000000000..a362e47a1 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/IFileSourceFilter.cs @@ -0,0 +1,48 @@ +// AForge Direct Show Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2007 +// andrew.kirillov@gmail.com +// + +namespace AForge.Video.DirectShow.Internals +{ + using System; + using System.Runtime.InteropServices; + + /// + /// The interface is exposed by source filters to set the file name and media type of the media file that they are to render. + /// + /// + [ComImport, + Guid( "56A868A6-0Ad4-11CE-B03A-0020AF0BA770" ), + InterfaceType( ComInterfaceType.InterfaceIsIUnknown )] + internal interface IFileSourceFilter + { + /// + /// Loads the source filter with the file. + /// + /// + /// The name of the file to open. + /// Media type of the file. This can be null. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Load( [In, MarshalAs( UnmanagedType.LPWStr )] string fileName, + [In, MarshalAs( UnmanagedType.LPStruct )] AMMediaType mediaType ); + + /// + /// Retrieves the current file. + /// + /// + /// Name of media file. + /// Receives media type. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetCurFile([Out, MarshalAs( UnmanagedType.LPWStr )] out string fileName, + [Out, MarshalAs( UnmanagedType.LPStruct )] AMMediaType mediaType ); + } +} diff --git a/Sources/Accord.Video.DirectShow/Internals/IFilterGraph.cs b/Sources/Accord.Video.DirectShow/Internals/IFilterGraph.cs new file mode 100644 index 0000000000..7d21c5f12 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/IFilterGraph.cs @@ -0,0 +1,113 @@ +// AForge Direct Show Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2007 +// andrew.kirillov@gmail.com +// + +namespace AForge.Video.DirectShow.Internals +{ + using System; + using System.Runtime.InteropServices; + + /// + /// The interface provides methods for building a filter graph. An application can use it to add filters to + /// the graph, connect or disconnect filters, remove filters, and perform other basic operations. + /// + /// + [ComImport, + Guid( "56A8689F-0AD4-11CE-B03A-0020AF0BA770" ), + InterfaceType( ComInterfaceType.InterfaceIsIUnknown )] + internal interface IFilterGraph + { + /// + /// Adds a filter to the graph and gives it a name. + /// + /// + /// Filter to add to the graph. + /// Name of the filter. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int AddFilter( [In] IBaseFilter filter, [In, MarshalAs( UnmanagedType.LPWStr )] string name ); + + /// + /// Removes a filter from the graph. + /// + /// + /// Filter to be removed from the graph. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int RemoveFilter( [In] IBaseFilter filter ); + + /// + /// Provides an enumerator for all filters in the graph. + /// + /// + /// Filter enumerator. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int EnumFilters( [Out] out IntPtr enumerator ); + + /// + /// Finds a filter that was added with a specified name. + /// + /// + /// Name of filter to search for. + /// Interface of found filter. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int FindFilterByName( [In, MarshalAs( UnmanagedType.LPWStr )] string name, [Out] out IBaseFilter filter ); + + /// + /// Connects two pins directly (without intervening filters). + /// + /// + /// Output pin. + /// Input pin. + /// Media type to use for the connection. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int ConnectDirect( [In] IPin pinOut, [In] IPin pinIn, [In, MarshalAs( UnmanagedType.LPStruct )] AMMediaType mediaType ); + + /// + /// Breaks the existing pin connection and reconnects it to the same pin. + /// + /// + /// Pin to disconnect and reconnect. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Reconnect( [In] IPin pin ); + + /// + /// Disconnects a specified pin. + /// + /// + /// Pin to disconnect. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Disconnect( [In] IPin pin ); + + /// + /// Sets the reference clock to the default clock. + /// + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int SetDefaultSyncSource( ); + } +} diff --git a/Sources/Accord.Video.DirectShow/Internals/IFilterGraph2.cs b/Sources/Accord.Video.DirectShow/Internals/IFilterGraph2.cs new file mode 100644 index 0000000000..b4dbf4c01 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/IFilterGraph2.cs @@ -0,0 +1,257 @@ +// AForge Direct Show Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Video.DirectShow.Internals +{ + using System; + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.ComTypes; + + /// + /// This interface extends the and + /// interfaces, which contain methods for building filter graphs. + /// + /// + [ComImport, + Guid("36B73882-C2C8-11CF-8B46-00805F6CEF60"), + InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IFilterGraph2 + { + // --- IFilterGraph Methods + + /// + /// Adds a filter to the graph and gives it a name. + /// + /// + /// Filter to add to the graph. + /// Name of the filter. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int AddFilter( [In] IBaseFilter filter, [In, MarshalAs( UnmanagedType.LPWStr )] string name ); + + /// + /// Removes a filter from the graph. + /// + /// + /// Filter to be removed from the graph. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int RemoveFilter( [In] IBaseFilter filter ); + + /// + /// Provides an enumerator for all filters in the graph. + /// + /// + /// Filter enumerator. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int EnumFilters( [Out] out IEnumFilters enumerator ); + + /// + /// Finds a filter that was added with a specified name. + /// + /// + /// Name of filter to search for. + /// Interface of found filter. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int FindFilterByName( [In, MarshalAs( UnmanagedType.LPWStr )] string name, [Out] out IBaseFilter filter ); + + /// + /// Connects two pins directly (without intervening filters). + /// + /// + /// Output pin. + /// Input pin. + /// Media type to use for the connection. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int ConnectDirect( [In] IPin pinOut, [In] IPin pinIn, [In, MarshalAs( UnmanagedType.LPStruct )] AMMediaType mediaType ); + + /// + /// Breaks the existing pin connection and reconnects it to the same pin. + /// + /// + /// Pin to disconnect and reconnect. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Reconnect( [In] IPin pin ); + + /// + /// Disconnects a specified pin. + /// + /// + /// Pin to disconnect. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Disconnect( [In] IPin pin ); + + /// + /// Sets the reference clock to the default clock. + /// + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int SetDefaultSyncSource( ); + + // --- IGraphBuilder methods + + /// + /// Connects two pins. If they will not connect directly, this method connects them with intervening transforms. + /// + /// + /// Output pin. + /// Input pin. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Connect( [In] IPin pinOut, [In] IPin pinIn ); + + /// + /// Adds a chain of filters to a specified output pin to render it. + /// + /// + /// Output pin. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Render( [In] IPin pinOut ); + + /// + /// Builds a filter graph that renders the specified file. + /// + /// + /// Specifies a string that contains file name or device moniker. + /// Reserved. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int RenderFile( + [In, MarshalAs( UnmanagedType.LPWStr )] string file, + [In, MarshalAs( UnmanagedType.LPWStr )] string playList ); + + /// + /// Adds a source filter to the filter graph for a specific file. + /// + /// + /// Specifies the name of the file to load. + /// Specifies a name for the source filter. + /// Variable that receives the interface of the source filter. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int AddSourceFilter( + [In, MarshalAs( UnmanagedType.LPWStr )] string fileName, + [In, MarshalAs( UnmanagedType.LPWStr )] string filterName, + [Out] out IBaseFilter filter ); + + /// + /// Sets the file for logging actions taken when attempting to perform an operation. + /// + /// + /// Handle to the log file. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int SetLogFile( IntPtr hFile ); + + /// + /// Requests that the graph builder return as soon as possible from its current task. + /// + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Abort( ); + + /// + /// Queries whether the current operation should continue. + /// + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int ShouldOperationContinue( ); + + + // --- IFilterGraph2 methods + + /// + /// + /// + /// + /// Moniker interface. + /// Bind context interface. + /// Name for the filter. + /// Receives source filter's IBaseFilter interface. + /// The caller must release the interface. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int AddSourceFilterForMoniker( + [In] IMoniker moniker, + [In] IBindCtx bindContext, + [In, MarshalAs( UnmanagedType.LPWStr )] string filterName, + [Out] out IBaseFilter filter + ); + + /// + /// Breaks the existing pin connection and reconnects it to the same pin, + /// using a specified media type. + /// + /// + /// Pin to disconnect and reconnect. + /// Media type to reconnect with. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int ReconnectEx( + [In] IPin pin, + [In, MarshalAs( UnmanagedType.LPStruct )] AMMediaType mediaType + ); + + /// + /// Render an output pin, with an option to use existing renderers only. + /// + /// + /// Interface of the output pin. + /// Flag that specifies how to render the pin. + /// Reserved. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int RenderEx( + [In] IPin outputPin, + [In] int flags, + [In] IntPtr context + ); + + } +} diff --git a/Sources/Accord.Video.DirectShow/Internals/IGraphBuilder.cs b/Sources/Accord.Video.DirectShow/Internals/IGraphBuilder.cs new file mode 100644 index 0000000000..8f3fc4ee7 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/IGraphBuilder.cs @@ -0,0 +1,198 @@ +// AForge Direct Show Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2007 +// andrew.kirillov@gmail.com +// + +namespace AForge.Video.DirectShow.Internals +{ + using System; + using System.Runtime.InteropServices; + + /// + /// This interface provides methods that enable an application to build a filter graph. + /// + /// + [ComImport, + Guid( "56A868A9-0AD4-11CE-B03A-0020AF0BA770" ), + InterfaceType( ComInterfaceType.InterfaceIsIUnknown )] + internal interface IGraphBuilder + { + // --- IFilterGraph Methods + + /// + /// Adds a filter to the graph and gives it a name. + /// + /// + /// Filter to add to the graph. + /// Name of the filter. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int AddFilter( [In] IBaseFilter filter, [In, MarshalAs( UnmanagedType.LPWStr )] string name ); + + /// + /// Removes a filter from the graph. + /// + /// + /// Filter to be removed from the graph. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int RemoveFilter( [In] IBaseFilter filter ); + + /// + /// Provides an enumerator for all filters in the graph. + /// + /// + /// Filter enumerator. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int EnumFilters( [Out] out IEnumFilters enumerator ); + + /// + /// Finds a filter that was added with a specified name. + /// + /// + /// Name of filter to search for. + /// Interface of found filter. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int FindFilterByName( [In, MarshalAs( UnmanagedType.LPWStr )] string name, [Out] out IBaseFilter filter ); + + /// + /// Connects two pins directly (without intervening filters). + /// + /// + /// Output pin. + /// Input pin. + /// Media type to use for the connection. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int ConnectDirect( [In] IPin pinOut, [In] IPin pinIn, [In, MarshalAs( UnmanagedType.LPStruct )] AMMediaType mediaType ); + + /// + /// Breaks the existing pin connection and reconnects it to the same pin. + /// + /// + /// Pin to disconnect and reconnect. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Reconnect( [In] IPin pin ); + + /// + /// Disconnects a specified pin. + /// + /// + /// Pin to disconnect. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Disconnect( [In] IPin pin ); + + /// + /// Sets the reference clock to the default clock. + /// + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int SetDefaultSyncSource( ); + + // --- IGraphBuilder methods + + /// + /// Connects two pins. If they will not connect directly, this method connects them with intervening transforms. + /// + /// + /// Output pin. + /// Input pin. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Connect( [In] IPin pinOut, [In] IPin pinIn ); + + /// + /// Adds a chain of filters to a specified output pin to render it. + /// + /// + /// Output pin. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Render( [In] IPin pinOut ); + + /// + /// Builds a filter graph that renders the specified file. + /// + /// + /// Specifies a string that contains file name or device moniker. + /// Reserved. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int RenderFile( + [In, MarshalAs( UnmanagedType.LPWStr )] string file, + [In, MarshalAs( UnmanagedType.LPWStr )] string playList); + + /// + /// Adds a source filter to the filter graph for a specific file. + /// + /// + /// Specifies the name of the file to load. + /// Specifies a name for the source filter. + /// Variable that receives the interface of the source filter. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int AddSourceFilter( + [In, MarshalAs( UnmanagedType.LPWStr )] string fileName, + [In, MarshalAs( UnmanagedType.LPWStr )] string filterName, + [Out] out IBaseFilter filter ); + + /// + /// Sets the file for logging actions taken when attempting to perform an operation. + /// + /// + /// Handle to the log file. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int SetLogFile( IntPtr hFile ); + + /// + /// Requests that the graph builder return as soon as possible from its current task. + /// + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Abort( ); + + /// + /// Queries whether the current operation should continue. + /// + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int ShouldOperationContinue( ); + } +} diff --git a/Sources/Accord.Video.DirectShow/Internals/IMediaControl.cs b/Sources/Accord.Video.DirectShow/Internals/IMediaControl.cs new file mode 100644 index 0000000000..c6ba35760 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/IMediaControl.cs @@ -0,0 +1,118 @@ +// AForge Direct Show Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2007 +// andrew.kirillov@gmail.com +// + +namespace AForge.Video.DirectShow.Internals +{ + using System; + using System.Runtime.InteropServices; + + /// + /// The interface provides methods for controlling the flow of data through the filter graph. + /// It includes methods for running, pausing, and stopping the graph. + /// + /// + [ComImport, + Guid( "56A868B1-0AD4-11CE-B03A-0020AF0BA770" ), + InterfaceType( ComInterfaceType.InterfaceIsDual )] + internal interface IMediaControl + { + /// + /// Runs all the filters in the filter graph. + /// + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Run( ); + + /// + /// Pauses all filters in the filter graph. + /// + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Pause( ); + + /// + /// Stops all the filters in the filter graph. + /// + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Stop( ); + + /// + /// Retrieves the state of the filter graph. + /// + /// + /// Duration of the time-out, in milliseconds, or INFINITE to specify an infinite time-out. + /// ariable that receives a member of the FILTER_STATE enumeration. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetState( int timeout, out int filterState ); + + /// + /// Builds a filter graph that renders the specified file. + /// + /// + /// Name of the file to render + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int RenderFile( string fileName ); + + /// + /// Adds a source filter to the filter graph, for a specified file. + /// + /// + /// Name of the file containing the source video. + /// Receives interface of filter information object. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int AddSourceFilter( [In] string fileName, [Out, MarshalAs( UnmanagedType.IDispatch )] out object filterInfo ); + + /// + /// Retrieves a collection of the filters in the filter graph. + /// + /// + /// Receives the IAMCollection interface. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int get_FilterCollection( + [Out, MarshalAs( UnmanagedType.IDispatch )] out object collection ); + + /// + /// Retrieves a collection of all the filters listed in the registry. + /// + /// + /// Receives the IDispatch interface of IAMCollection object. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int get_RegFilterCollection( + [Out, MarshalAs( UnmanagedType.IDispatch )] out object collection ); + + /// + /// Pauses the filter graph, allowing filters to queue data, and then stops the filter graph. + /// + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int StopWhenReady( ); + } +} diff --git a/Sources/Accord.Video.DirectShow/Internals/IMediaEventEx.cs b/Sources/Accord.Video.DirectShow/Internals/IMediaEventEx.cs new file mode 100644 index 0000000000..d01bee8c5 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/IMediaEventEx.cs @@ -0,0 +1,126 @@ +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2009-2011 +// contacts@aforgenet.com +// + +namespace AForge.Video.DirectShow.Internals +{ + using System; + using System.Runtime.InteropServices; + + /// + /// The interface inherits contains methods for retrieving event notifications and for overriding the + /// filter graph's default handling of events. + /// + [ComVisible( true ), ComImport, + Guid( "56a868c0-0ad4-11ce-b03a-0020af0ba770" ), + InterfaceType( ComInterfaceType.InterfaceIsDual )] + internal interface IMediaEventEx + { + /// + /// Retrieves a handle to a manual-reset event that remains signaled while the queue contains event notifications. + /// + /// Pointer to a variable that receives the event handle. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetEventHandle( out IntPtr hEvent ); + + /// + /// Retrieves the next event notification from the event queue. + /// + /// + /// Variable that receives the event code. + /// Pointer to a variable that receives the first event parameter. + /// Pointer to a variable that receives the second event parameter. + /// Time-out interval, in milliseconds. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetEvent( [Out, MarshalAs( UnmanagedType.I4 )] out DsEvCode lEventCode, [Out] out IntPtr lParam1, [Out] out IntPtr lParam2, int msTimeout ); + + /// + /// Waits for the filter graph to render all available data. + /// + /// + /// Time-out interval, in milliseconds. Pass zero to return immediately. + /// Pointer to a variable that receives an event code. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int WaitForCompletion( int msTimeout, [Out] out int pEvCode ); + + /// + /// Cancels the Filter Graph Manager's default handling for a specified event. + /// + /// + /// Event code for which to cancel default handling. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int CancelDefaultHandling( int lEvCode ); + + /// + /// Restores the Filter Graph Manager's default handling for a specified event. + /// + /// Event code for which to restore default handling. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int RestoreDefaultHandling( int lEvCode ); + + /// + /// Frees resources associated with the parameters of an event. + /// + /// Event code. + /// First event parameter. + /// Second event parameter. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int FreeEventParams( [In, MarshalAs( UnmanagedType.I4 )] DsEvCode lEvCode, IntPtr lParam1, IntPtr lParam2 ); + + /// + /// Registers a window to process event notifications. + /// + /// + /// Handle to the window, or to stop receiving event messages. + /// Window message to be passed as the notification. + /// Value to be passed as the lParam parameter for the lMsg message. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int SetNotifyWindow( IntPtr hwnd, int lMsg, IntPtr lInstanceData ); + + /// + /// Enables or disables event notifications. + /// + /// + /// Value indicating whether to enable or disable event notifications. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int SetNotifyFlags( int lNoNotifyFlags ); + + /// + /// Determines whether event notifications are enabled. + /// + /// + /// Variable that receives current notification status. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetNotifyFlags( out int lplNoNotifyFlags ); + } +} diff --git a/Sources/Accord.Video.DirectShow/Internals/IMediaFilter.cs b/Sources/Accord.Video.DirectShow/Internals/IMediaFilter.cs new file mode 100644 index 0000000000..e4ca82ecb --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/IMediaFilter.cs @@ -0,0 +1,102 @@ +// AForge Direct Show Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2010 +// andrew.kirillov@gmail.com +// +// Written by Jeremy Noring +// kidjan@gmail.com +// + +namespace AForge.Video.DirectShow.Internals +{ + using System; + using System.Runtime.InteropServices; + + /// + /// The interface provides methods for controlling the flow of data through the filter graph. + /// It includes methods for running, pausing, and stopping the graph. + /// + /// + [ComImport, System.Security.SuppressUnmanagedCodeSecurity, + Guid( "56a86899-0ad4-11ce-b03a-0020af0ba770" ), + InterfaceType( ComInterfaceType.InterfaceIsIUnknown )] + internal interface IMediaFilter : IPersist + { + #region IPersist Methods + + [PreserveSig] + new int GetClassID( + [Out] out Guid pClassID ); + + #endregion + + /// + /// This method informs the filter to transition to the new state. + /// + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Stop( ); + + /// + /// This method informs the filter to transition to the new state. + /// + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Pause( ); + + /// + /// This method informs the filter to transition to the new (running) state. Passes a time value to synchronize independent streams. + /// + /// + /// Time value of the reference clock. The amount to be added to the IMediaSample time stamp to determine the time at which that sample should be rendered according to the reference clock. That is, it is the reference time at which a sample with a stream time of zero should be rendered. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Run( [In] long tStart ); + + /// + /// This method determines the filter's state. + /// + /// + /// Duration of the time-out, in milliseconds. To block indefinitely, pass INFINITE. + /// Returned state of the filter. States include stopped, paused, running, or intermediate (in the process of changing). + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetState( + [In] int dwMilliSecsTimeout, + [Out] out FilterState filtState ); + + /// + /// This method identifies the reference clock to which the filter should synchronize activity. + /// + /// + /// Pointer to the IReferenceClock interface. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int SetSyncSource( [In] IReferenceClock pClock ); + + /// + /// This method retrieves the current reference clock in use by this filter. + /// + /// + /// Pointer to a reference clock; it will be set to the IReferenceClock interface. + /// + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetSyncSource( [Out] out IReferenceClock pClock ); + } +} + diff --git a/Sources/Accord.Video.DirectShow/Internals/IPersist.cs b/Sources/Accord.Video.DirectShow/Internals/IPersist.cs new file mode 100644 index 0000000000..4bf1d91f9 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/IPersist.cs @@ -0,0 +1,32 @@ +// AForge Direct Show Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2010 +// andrew.kirillov@gmail.com +// +// Written by Jeremy Noring +// kidjan@gmail.com + +namespace AForge.Video.DirectShow.Internals +{ + using System; + using System.Runtime.InteropServices; + + /// + /// Provides the CLSID of an object that can be stored persistently in the system. Allows the object to specify which object + /// handler to use in the client process, as it is used in the default implementation of marshaling. + /// + [ComImport, + Guid("0000010c-0000-0000-C000-000000000046"), + InterfaceType(ComInterfaceType.InterfaceIsDual)] + internal interface IPersist + { + /// + /// Retrieves the class identifier (CLSID) of the object. + /// + /// + /// + [PreserveSig] + int GetClassID([Out] out Guid pClassID); + } +} diff --git a/Sources/Accord.Video.DirectShow/Internals/IPin.cs b/Sources/Accord.Video.DirectShow/Internals/IPin.cs new file mode 100644 index 0000000000..ceed73f26 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/IPin.cs @@ -0,0 +1,191 @@ +// AForge Direct Show Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2007 +// andrew.kirillov@gmail.com +// + +namespace AForge.Video.DirectShow.Internals +{ + using System; + using System.Runtime.InteropServices; + + /// + /// This interface is exposed by all input and output pins of DirectShow filters. + /// + /// + [ComImport, + Guid( "56A86891-0AD4-11CE-B03A-0020AF0BA770" ), + InterfaceType( ComInterfaceType.InterfaceIsIUnknown )] + internal interface IPin + { + /// + /// Connects the pin to another pin. + /// + /// + /// Other pin to connect to. + /// Type to use for the connections (optional). + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Connect( [In] IPin receivePin, [In, MarshalAs( UnmanagedType.LPStruct )] AMMediaType mediaType ); + + /// + /// Makes a connection to this pin and is called by a connecting pin. + /// + /// + /// Connecting pin. + /// Media type of the samples to be streamed. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int ReceiveConnection( [In] IPin receivePin, [In, MarshalAs( UnmanagedType.LPStruct )] AMMediaType mediaType ); + + /// + /// Breaks the current pin connection. + /// + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Disconnect( ); + + /// + /// Returns a pointer to the connecting pin. + /// + /// + /// Receives IPin interface of connected pin (if any). + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int ConnectedTo( [Out] out IPin pin ); + + /// + /// Returns the media type of this pin's connection. + /// + /// + /// Pointer to an structure. If the pin is connected, + /// the media type is returned. Otherwise, the structure is initialized to a default state in which + /// all elements are 0, with the exception of lSampleSize, which is set to 1, and + /// FixedSizeSamples, which is set to true. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int ConnectionMediaType( [Out, MarshalAs( UnmanagedType.LPStruct )] AMMediaType mediaType ); + + /// + /// Retrieves information about this pin (for example, the name, owning filter, and direction). + /// + /// + /// structure that receives the pin information. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int QueryPinInfo( [Out] out PinInfo pinInfo ); + + /// + /// Retrieves the direction for this pin. + /// + /// + /// Receives direction of the pin. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int QueryDirection( out PinDirection pinDirection ); + + /// + /// Retrieves an identifier for the pin. + /// + /// + /// Pin identifier. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int QueryId( [Out, MarshalAs( UnmanagedType.LPWStr )] out string id ); + + /// + /// Queries whether a given media type is acceptable by the pin. + /// + /// + /// structure that specifies the media type. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int QueryAccept( [In, MarshalAs( UnmanagedType.LPStruct )] AMMediaType mediaType ); + + /// + /// Provides an enumerator for this pin's preferred media types. + /// + /// + /// Address of a variable that receives a pointer to the IEnumMediaTypes interface. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int EnumMediaTypes( IntPtr enumerator ); + + /// + /// Provides an array of the pins to which this pin internally connects. + /// + /// + /// Address of an array of IPin pointers. + /// On input, specifies the size of the array. When the method returns, + /// the value is set to the number of pointers returned in the array. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int QueryInternalConnections( IntPtr apPin, [In, Out] ref int nPin ); + + /// + /// Notifies the pin that no additional data is expected. + /// + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int EndOfStream( ); + + /// + /// Begins a flush operation. + /// + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int BeginFlush( ); + + /// + /// Ends a flush operation. + /// + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int EndFlush( ); + + /// + /// Specifies that samples following this call are grouped as a segment with a given start time, stop time, and rate. + /// + /// + /// Start time of the segment, relative to the original source, in 100-nanosecond units. + /// End time of the segment, relative to the original source, in 100-nanosecond units. + /// Rate at which this segment should be processed, as a percentage of the original rate. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int NewSegment( + long start, + long stop, + double rate ); + } +} diff --git a/Sources/Accord.Video.DirectShow/Internals/IPropertyBag.cs b/Sources/Accord.Video.DirectShow/Internals/IPropertyBag.cs new file mode 100644 index 0000000000..faea69d50 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/IPropertyBag.cs @@ -0,0 +1,53 @@ +// AForge Direct Show Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2007 +// andrew.kirillov@gmail.com +// + +namespace AForge.Video.DirectShow.Internals +{ + using System; + using System.Runtime.InteropServices; + + /// + /// The IPropertyBag interface provides an object with a property bag in + /// which the object can persistently save its properties. + /// + /// + [ComImport, + Guid( "55272A00-42CB-11CE-8135-00AA004BB851" ), + InterfaceType( ComInterfaceType.InterfaceIsIUnknown )] + internal interface IPropertyBag + { + /// + /// Read a property from property bag. + /// + /// + /// Property name to read. + /// Property value. + /// Caller's error log. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Read( + [In, MarshalAs( UnmanagedType.LPWStr )] string propertyName, + [In, Out, MarshalAs( UnmanagedType.Struct )] ref object pVar, + [In] IntPtr pErrorLog ); + + /// + /// Write property to property bag. + /// + /// + /// Property name to read. + /// Property value. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Write( + [In, MarshalAs( UnmanagedType.LPWStr )] string propertyName, + [In, MarshalAs( UnmanagedType.Struct )] ref object pVar ); + } +} diff --git a/Sources/Accord.Video.DirectShow/Internals/IReferenceClock.cs b/Sources/Accord.Video.DirectShow/Internals/IReferenceClock.cs new file mode 100644 index 0000000000..cb0328fab --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/IReferenceClock.cs @@ -0,0 +1,87 @@ +// AForge Direct Show Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2010 +// andrew.kirillov@gmail.com +// +// Written by Jeremy Noring +// kidjan@gmail.com +// + +namespace AForge.Video.DirectShow.Internals +{ + using System; + using System.Runtime.InteropServices; + + /// + /// The IReferenceClock interface provides the reference time for the filter graph. + /// + /// Filters that can act as a reference clock can expose this interface. It is also exposed by the System Reference Clock. + /// The filter graph manager uses this interface to synchronize the filter graph. Applications can use this interface to + /// retrieve the current reference time, or to request notification of an elapsed time. + /// + [ComImport, System.Security.SuppressUnmanagedCodeSecurity, + Guid( "56a86897-0ad4-11ce-b03a-0020af0ba770" ), + InterfaceType( ComInterfaceType.InterfaceIsIUnknown )] + internal interface IReferenceClock + { + /// + /// The GetTime method retrieves the current reference time. + /// + /// + /// Pointer to a variable that receives the current time, in 100-nanosecond units. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetTime( [Out] out long pTime ); + + /// + /// The AdviseTime method creates a one-shot advise request. + /// + /// + /// Base reference time, in 100-nanosecond units. See Remarks. + /// Stream offset time, in 100-nanosecond units. See Remarks. + /// Handle to an event, created by the caller. + /// Pointer to a variable that receives an identifier for the advise request. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int AdviseTime( + [In] long baseTime, + [In] long streamTime, + [In] IntPtr hEvent, + [Out] out int pdwAdviseCookie ); + + /// + /// The AdvisePeriodic method creates a periodic advise request. + /// + /// + /// Time of the first notification, in 100-nanosecond units. Must be greater than zero and less than MAX_TIME. + /// Time between notifications, in 100-nanosecond units. Must be greater than zero. + /// Handle to a semaphore, created by the caller. + /// Pointer to a variable that receives an identifier for the advise request. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int AdvisePeriodic( + [In] long startTime, + [In] long periodTime, + [In] IntPtr hSemaphore, + [Out] out int pdwAdviseCookie ); + + /// + /// The Unadvise method removes a pending advise request. + /// + /// + /// Identifier of the request to remove. Use the value returned by IReferenceClock::AdviseTime or IReferenceClock::AdvisePeriodic in the pdwAdviseToken parameter. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int Unadvise( [In] int dwAdviseCookie ); + } +} diff --git a/Sources/Accord.Video.DirectShow/Internals/ISampleGrabber.cs b/Sources/Accord.Video.DirectShow/Internals/ISampleGrabber.cs new file mode 100644 index 0000000000..07854ac69 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/ISampleGrabber.cs @@ -0,0 +1,103 @@ +// AForge Direct Show Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2007 +// andrew.kirillov@gmail.com +// + +namespace AForge.Video.DirectShow.Internals +{ + using System; + using System.Runtime.InteropServices; + + /// + /// The interface is exposed by the Sample Grabber Filter. It enables an application to retrieve + /// individual media samples as they move through the filter graph. + /// + /// + [ComImport, + Guid("6B652FFF-11FE-4FCE-92AD-0266B5D7C78F"), + InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface ISampleGrabber + { + /// + /// Specifies whether the filter should stop the graph after receiving one sample. + /// + /// + /// Boolean value specifying whether the filter should stop the graph after receiving one sample. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int SetOneShot( [In, MarshalAs( UnmanagedType.Bool )] bool oneShot ); + + /// + /// Specifies the media type for the connection on the Sample Grabber's input pin. + /// + /// + /// Specifies the required media type. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int SetMediaType( [In, MarshalAs( UnmanagedType.LPStruct )] AMMediaType mediaType ); + + /// + /// Retrieves the media type for the connection on the Sample Grabber's input pin. + /// + /// + /// structure, which receives media type. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetConnectedMediaType( [Out, MarshalAs( UnmanagedType.LPStruct )] AMMediaType mediaType ); + + /// + /// Specifies whether to copy sample data into a buffer as it goes through the filter. + /// + /// + /// Boolean value specifying whether to buffer sample data. + /// If true, the filter copies sample data into an internal buffer. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int SetBufferSamples( [In, MarshalAs( UnmanagedType.Bool )] bool bufferThem ); + + /// + /// Retrieves a copy of the sample that the filter received most recently. + /// + /// + /// Pointer to the size of the buffer. If pBuffer is NULL, this parameter receives the required size. + /// Pointer to a buffer to receive a copy of the sample, or NULL. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetCurrentBuffer( ref int bufferSize, IntPtr buffer ); + + /// + /// Not currently implemented. + /// + /// + /// + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetCurrentSample( IntPtr sample ); + + /// + /// Specifies a callback method to call on incoming samples. + /// + /// + /// interface containing the callback method, or NULL to cancel the callback. + /// Index specifying the callback method. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int SetCallback( ISampleGrabberCB callback, int whichMethodToCallback ); + } +} diff --git a/Sources/Accord.Video.DirectShow/Internals/ISampleGrabberCB.cs b/Sources/Accord.Video.DirectShow/Internals/ISampleGrabberCB.cs new file mode 100644 index 0000000000..4dc734019 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/ISampleGrabberCB.cs @@ -0,0 +1,47 @@ +// AForge Direct Show Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2007 +// andrew.kirillov@gmail.com +// + +namespace AForge.Video.DirectShow.Internals +{ + using System; + using System.Runtime.InteropServices; + + /// + /// The interface provides callback methods for the method. + /// + /// + [ComImport, + Guid("0579154A-2B53-4994-B0D0-E773148EFF85"), + InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface ISampleGrabberCB + { + /// + /// Callback method that receives a pointer to the media sample. + /// + /// + /// Starting time of the sample, in seconds. + /// Pointer to the sample's IMediaSample interface. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int SampleCB( double sampleTime, IntPtr sample ); + + /// + /// Callback method that receives a pointer to the sample buffer + /// + /// + /// Starting time of the sample, in seconds. + /// Pointer to a buffer that contains the sample data. + /// Length of the buffer pointed to by buffer, in bytes + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int BufferCB( double sampleTime, IntPtr buffer, int bufferLen ); + } +} diff --git a/Sources/Accord.Video.DirectShow/Internals/ISpecifyPropertyPages.cs b/Sources/Accord.Video.DirectShow/Internals/ISpecifyPropertyPages.cs new file mode 100644 index 0000000000..ecb073926 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/ISpecifyPropertyPages.cs @@ -0,0 +1,36 @@ +// AForge Direct Show Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Video.DirectShow.Internals +{ + using System; + using System.Runtime.InteropServices; + + /// + /// The interface indicates that an object supports property pages. + /// + /// + [ComImport, + Guid( "B196B28B-BAB4-101A-B69C-00AA00341D07" ), + InterfaceType( ComInterfaceType.InterfaceIsIUnknown )] + internal interface ISpecifyPropertyPages + { + /// + /// Fills a counted array of GUID values where each GUID specifies the + /// CLSID of each property page that can be displayed in the property + /// sheet for this object. + /// + /// + /// Pointer to a CAUUID structure that must be initialized + /// and filled before returning. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetPages( out CAUUID pPages ); + } +} diff --git a/Sources/Accord.Video.DirectShow/Internals/IVideoWindow.cs b/Sources/Accord.Video.DirectShow/Internals/IVideoWindow.cs new file mode 100644 index 0000000000..25f3bfa11 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/IVideoWindow.cs @@ -0,0 +1,466 @@ +// AForge Direct Show Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2007 +// andrew.kirillov@gmail.com +// + +namespace AForge.Video.DirectShow.Internals +{ + using System; + using System.Runtime.InteropServices; + + /// + /// The interface sets properties on the video window. + /// + /// + [ComImport, + Guid("56A868B4-0AD4-11CE-B03A-0020AF0BA770"), + InterfaceType(ComInterfaceType.InterfaceIsDual)] + internal interface IVideoWindow + { + /// + /// Sets the video window caption. + /// + /// + /// Caption. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int put_Caption( string caption ); + + /// + /// Retrieves the video window caption. + /// + /// + /// Caption. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int get_Caption( [Out] out string caption ); + + /// + /// Sets the window style on the video window. + /// + /// + /// Window style flags. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int put_WindowStyle( int windowStyle ); + + /// + /// Retrieves the window style on the video window. + /// + /// + /// Window style flags. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int get_WindowStyle( out int windowStyle ); + + /// + /// Sets the extended window style on the video window. + /// + /// + /// Window extended style flags. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int put_WindowStyleEx( int windowStyleEx ); + + /// + /// Retrieves the extended window style on the video window. + /// + /// + /// Window extended style flags. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int get_WindowStyleEx( out int windowStyleEx ); + + /// + /// Specifies whether the video renderer automatically shows the video window when it receives video data. + /// + /// + /// Specifies whether the video renderer automatically shows the video window. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int put_AutoShow( [In, MarshalAs( UnmanagedType.Bool )] bool autoShow ); + + /// + /// Queries whether the video renderer automatically shows the video window when it receives video data. + /// + /// + /// REceives window auto show flag. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int get_AutoShow( [Out, MarshalAs( UnmanagedType.Bool )] out bool autoShow ); + + /// + /// Shows, hides, minimizes, or maximizes the video window. + /// + /// + /// Window state. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int put_WindowState( int windowState ); + + /// + /// Queries whether the video window is visible, hidden, minimized, or maximized. + /// + /// + /// Window state. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int get_WindowState( out int windowState ); + + /// + /// Specifies whether the video window realizes its palette in the background. + /// + /// + /// Value that specifies whether the video renderer realizes it palette in the background. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int put_BackgroundPalette( [In, MarshalAs( UnmanagedType.Bool )] bool backgroundPalette ); + + /// + /// Queries whether the video window realizes its palette in the background. + /// + /// + /// Receives state of background palette flag. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int get_BackgroundPalette( [Out, MarshalAs( UnmanagedType.Bool )] out bool backgroundPalette ); + + /// + /// Shows or hides the video window. + /// + /// + /// Value that specifies whether to show or hide the window. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int put_Visible( [In, MarshalAs( UnmanagedType.Bool )] bool visible ); + + /// + /// Queries whether the video window is visible. + /// + /// + /// Visibility flag. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int get_Visible( [Out, MarshalAs( UnmanagedType.Bool )] out bool visible ); + + /// + /// Sets the video window's x-coordinate. + /// + /// + /// Specifies the x-coordinate, in pixels. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int put_Left( int left ); + + /// + /// Retrieves the video window's x-coordinate. + /// + /// + /// x-coordinate, in pixels. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int get_Left( out int left ); + + /// + /// Sets the width of the video window. + /// + /// + /// Specifies the width, in pixels. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int put_Width( int width ); + + /// + /// Retrieves the width of the video window. + /// + /// + /// Width, in pixels. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int get_Width( out int width ); + + /// + /// Sets the video window's y-coordinate. + /// + /// + /// Specifies the y-coordinate, in pixels. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int put_Top( int top ); + + /// + /// Retrieves the video window's y-coordinate. + /// + /// + /// y-coordinate, in pixels. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int get_Top( out int top ); + + /// + /// Sets the height of the video window. + /// + /// + /// Specifies the height, in pixels. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int put_Height( int height ); + + /// + /// Retrieves the height of the video window. + /// + /// + /// Height, in pixels. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int get_Height( out int height ); + + /// + /// Specifies a parent window for the video window + /// + /// + /// Specifies a handle to the parent window. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int put_Owner( IntPtr owner ); + + /// + /// Retrieves the video window's parent window, if any + /// + /// + /// Parent window's handle. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int get_Owner( out IntPtr owner ); + + /// + /// Specifies a window to receive mouse and keyboard messages from the video window. + /// + /// + /// Specifies a handle to the window. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int put_MessageDrain( IntPtr drain ); + + /// + /// Retrieves the window that receives mouse and keyboard messages from the video window, if any. + /// + /// + /// Window's handle. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int get_MessageDrain( out IntPtr drain ); + + /// + /// Retrieves the color that appears around the edges of the destination rectangle. + /// + /// + /// Border's color. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int get_BorderColor( out int color ); + + /// + /// Sets the color that appears around the edges of the destination rectangle. + /// + /// + /// Specifies the border color. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int put_BorderColor( int color ); + + /// + /// Queries whether the video renderer is in full-screen mode. + /// + /// + /// Full-screen mode. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int get_FullScreenMode( + [Out, MarshalAs( UnmanagedType.Bool )] out bool fullScreenMode ); + + /// + /// Enables or disables full-screen mode. + /// + /// + /// Boolean value that specifies whether to enable or disable full-screen mode. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int put_FullScreenMode( [In, MarshalAs( UnmanagedType.Bool )] bool fullScreenMode ); + + /// + /// Places the video window at the top of the Z order. + /// + /// + /// Value that specifies whether to give the window focus. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int SetWindowForeground( int focus ); + + /// + /// Forwards a message to the video window. + /// + /// + /// Handle to the window. + /// Specifies the message. + /// Message parameter. + /// Message parameter. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int NotifyOwnerMessage( IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam ); + + /// + /// Sets the position of the video window + /// + /// + /// Specifies the x-coordinate, in pixels. + /// Specifies the y-coordinate, in pixels. + /// Specifies the width, in pixels. + /// Specifies the height, in pixels. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int SetWindowPosition( int left, int top, int width, int height ); + + /// + /// Retrieves the position of the video window. + /// + /// + /// x-coordinate, in pixels. + /// y-coordinate, in pixels. + /// Width, in pixels. + /// Height, in pixels. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetWindowPosition( out int left, out int top, out int width, out int height ); + + /// + /// Retrieves the minimum ideal size for the video image. + /// + /// + /// Receives the minimum ideal width, in pixels. + /// Receives the minimum ideal height, in pixels. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetMinIdealImageSize( out int width, out int height ); + + /// + /// Retrieves the maximum ideal size for the video image. + /// + /// + /// Receives the maximum ideal width, in pixels. + /// Receives the maximum ideal height, in pixels. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetMaxIdealImageSize( out int width, out int height ); + + /// + /// Retrieves the restored window position. + /// + /// + /// x-coordinate, in pixels. + /// y-coordinate, in pixels. + /// Width, in pixels. + /// Height, in pixels. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int GetRestorePosition( out int left, out int top, out int width, out int height ); + + /// + /// Hides the cursor. + /// + /// + /// Specifies whether to hide or display the cursor. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int HideCursor( [In, MarshalAs( UnmanagedType.Bool )] bool hideCursor ); + + /// + /// Queries whether the cursor is hidden. + /// + /// + /// Specifies if cursor is hidden or not. + /// + /// Return's HRESULT error code. + /// + [PreserveSig] + int IsCursorHidden( [Out, MarshalAs( UnmanagedType.Bool )] out bool hideCursor ); + } +} diff --git a/Sources/Accord.Video.DirectShow/Internals/Structures.cs b/Sources/Accord.Video.DirectShow/Internals/Structures.cs new file mode 100644 index 0000000000..530283c37 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/Structures.cs @@ -0,0 +1,518 @@ +// AForge Direct Show Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2009-2013 +// contacts@aforgenet.com +// + +namespace AForge.Video.DirectShow.Internals +{ + using System; + using System.Runtime.InteropServices; + using System.Drawing; + + // PIN_DIRECTION + + /// + /// This enumeration indicates a pin's direction. + /// + /// + [ComVisible( false )] + internal enum PinDirection + { + /// + /// Input pin. + /// + Input, + + /// + /// Output pin. + /// + Output + } + + // AM_MEDIA_TYPE + + /// + /// The structure describes the format of a media sample. + /// + /// + [ComVisible( false ), + StructLayout( LayoutKind.Sequential )] + internal class AMMediaType : IDisposable + { + /// + /// Globally unique identifier (GUID) that specifies the major type of the media sample. + /// + public Guid MajorType; + + /// + /// GUID that specifies the subtype of the media sample. + /// + public Guid SubType; + + /// + /// If true, samples are of a fixed size. + /// + [MarshalAs( UnmanagedType.Bool )] + public bool FixedSizeSamples = true; + + /// + /// If true, samples are compressed using temporal (interframe) compression. + /// + [MarshalAs( UnmanagedType.Bool )] + public bool TemporalCompression; + + /// + /// Size of the sample in bytes. For compressed data, the value can be zero. + /// + public int SampleSize = 1; + + /// + /// GUID that specifies the structure used for the format block. + /// + public Guid FormatType; + + /// + /// Not used. + /// + public IntPtr unkPtr; + + /// + /// Size of the format block, in bytes. + /// + public int FormatSize; + + /// + /// Pointer to the format block. + /// + public IntPtr FormatPtr; + + /// + /// Destroys the instance of the class. + /// + /// + ~AMMediaType( ) + { + Dispose( false ); + } + + /// + /// Dispose the object. + /// + /// + public void Dispose( ) + { + Dispose( true ); + // remove me from the Finalization queue + GC.SuppressFinalize( this ); + } + + /// + /// Dispose the object + /// + /// + /// Indicates if disposing was initiated manually. + /// + protected virtual void Dispose( bool disposing ) + { + if ( ( FormatSize != 0 ) && ( FormatPtr != IntPtr.Zero ) ) + { + Marshal.FreeCoTaskMem( FormatPtr ); + FormatSize = 0; + } + + if ( unkPtr != IntPtr.Zero ) + { + Marshal.Release( unkPtr ); + unkPtr = IntPtr.Zero; + } + } + } + + + // PIN_INFO + + /// + /// The structure contains information about a pin. + /// + /// + [ComVisible( false ), + StructLayout( LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode )] + internal struct PinInfo + { + /// + /// Owning filter. + /// + public IBaseFilter Filter; + + /// + /// Direction of the pin. + /// + public PinDirection Direction; + + /// + /// Name of the pin. + /// + [MarshalAs( UnmanagedType.ByValTStr, SizeConst = 128 )] + public string Name; + } + + // FILTER_INFO + [ComVisible( false ), + StructLayout( LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode )] + internal struct FilterInfo + { + /// + /// Filter's name. + /// + [MarshalAs( UnmanagedType.ByValTStr, SizeConst = 128 )] + public string Name; + + /// + /// Owning graph. + /// + public IFilterGraph FilterGraph; + } + + // VIDEOINFOHEADER + + /// + /// The structure describes the bitmap and color information for a video image. + /// + /// + [ComVisible( false ), + StructLayout( LayoutKind.Sequential )] + internal struct VideoInfoHeader + { + /// + /// structure that specifies the source video window. + /// + public RECT SrcRect; + + /// + /// structure that specifies the destination video window. + /// + public RECT TargetRect; + + /// + /// Approximate data rate of the video stream, in bits per second. + /// + public int BitRate; + + /// + /// Data error rate, in bit errors per second. + /// + public int BitErrorRate; + + /// + /// The desired average display time of the video frames, in 100-nanosecond units. + /// + public long AverageTimePerFrame; + + /// + /// structure that contains color and dimension information for the video image bitmap. + /// + public BitmapInfoHeader BmiHeader; + } + + // VIDEOINFOHEADER2 + + /// + /// The structure describes the bitmap and color information for a video image (v2). + /// + /// + [ComVisible( false ), + StructLayout( LayoutKind.Sequential )] + internal struct VideoInfoHeader2 + { + /// + /// structure that specifies the source video window. + /// + public RECT SrcRect; + + /// + /// structure that specifies the destination video window. + /// + public RECT TargetRect; + + /// + /// Approximate data rate of the video stream, in bits per second. + /// + public int BitRate; + + /// + /// Data error rate, in bit errors per second. + /// + public int BitErrorRate; + + /// + /// The desired average display time of the video frames, in 100-nanosecond units. + /// + public long AverageTimePerFrame; + + /// + /// Flags that specify how the video is interlaced. + /// + public int InterlaceFlags; + + /// + /// Flag set to indicate that the duplication of the stream should be restricted. + /// + public int CopyProtectFlags; + + /// + /// The X dimension of picture aspect ratio. + /// + public int PictAspectRatioX; + + /// + /// The Y dimension of picture aspect ratio. + /// + public int PictAspectRatioY; + + /// + /// Reserved for future use. + /// + public int Reserved1; + + /// + /// Reserved for future use. + /// + public int Reserved2; + + /// + /// structure that contains color and dimension information for the video image bitmap. + /// + public BitmapInfoHeader BmiHeader; + } + + /// + /// The structure contains information about the dimensions and color format of a device-independent bitmap (DIB). + /// + /// + [ComVisible( false ), + StructLayout( LayoutKind.Sequential, Pack = 2 )] + internal struct BitmapInfoHeader + { + /// + /// Specifies the number of bytes required by the structure. + /// + public int Size; + + /// + /// Specifies the width of the bitmap. + /// + public int Width; + + /// + /// Specifies the height of the bitmap, in pixels. + /// + public int Height; + + /// + /// Specifies the number of planes for the target device. This value must be set to 1. + /// + public short Planes; + + /// + /// Specifies the number of bits per pixel. + /// + public short BitCount; + + /// + /// If the bitmap is compressed, this member is a FOURCC the specifies the compression. + /// + public int Compression; + + /// + /// Specifies the size, in bytes, of the image. + /// + public int ImageSize; + + /// + /// Specifies the horizontal resolution, in pixels per meter, of the target device for the bitmap. + /// + public int XPelsPerMeter; + + /// + /// Specifies the vertical resolution, in pixels per meter, of the target device for the bitmap. + /// + public int YPelsPerMeter; + + /// + /// Specifies the number of color indices in the color table that are actually used by the bitmap. + /// + public int ColorsUsed; + + /// + /// Specifies the number of color indices that are considered important for displaying the bitmap. + /// + public int ColorsImportant; + } + + // RECT + + /// + /// The structure defines the coordinates of the upper-left and lower-right corners of a rectangle. + /// + /// + [ComVisible( false ), + StructLayout( LayoutKind.Sequential )] + internal struct RECT + { + /// + /// Specifies the x-coordinate of the upper-left corner of the rectangle. + /// + public int Left; + + /// + /// Specifies the y-coordinate of the upper-left corner of the rectangle. + /// + public int Top; + + /// + /// Specifies the x-coordinate of the lower-right corner of the rectangle. + /// + public int Right; + + /// + /// Specifies the y-coordinate of the lower-right corner of the rectangle. + /// + public int Bottom; + } + + // CAUUID + + /// + /// The CAUUID structure is a Counted Array of UUID or GUID types. + /// + /// + [ComVisible( false ), + StructLayout( LayoutKind.Sequential )] + internal struct CAUUID + { + /// + /// Size of the array pointed to by pElems. + /// + public int cElems; + + /// + /// Pointer to an array of UUID values, each of which specifies UUID. + /// + public IntPtr pElems; + + /// + /// Performs manual marshaling of pElems to retrieve an array of Guid objects. + /// + /// + /// A managed representation of pElems. + /// + public Guid[] ToGuidArray( ) + { + Guid[] retval = new Guid[cElems]; + + for ( int i = 0; i < cElems; i++ ) + { + IntPtr ptr = new IntPtr( pElems.ToInt64( ) + i * Marshal.SizeOf( typeof( Guid ) ) ); + retval[i] = (Guid) Marshal.PtrToStructure( ptr, typeof( Guid ) ); + } + + return retval; + } + } + + /// + /// Enumeration of DirectShow event codes. + /// + internal enum DsEvCode + { + None, + Complete = 0x01, // EC_COMPLETE + DeviceLost = 0x1F, // EC_DEVICE_LOST + //(...) not yet interested in other events + } + + [Flags, ComVisible( false )] + internal enum AnalogVideoStandard + { + None = 0x00000000, // This is a digital sensor + NTSC_M = 0x00000001, // 75 IRE Setup + NTSC_M_J = 0x00000002, // Japan, 0 IRE Setup + NTSC_433 = 0x00000004, + PAL_B = 0x00000010, + PAL_D = 0x00000020, + PAL_G = 0x00000040, + PAL_H = 0x00000080, + PAL_I = 0x00000100, + PAL_M = 0x00000200, + PAL_N = 0x00000400, + PAL_60 = 0x00000800, + SECAM_B = 0x00001000, + SECAM_D = 0x00002000, + SECAM_G = 0x00004000, + SECAM_H = 0x00008000, + SECAM_K = 0x00010000, + SECAM_K1 = 0x00020000, + SECAM_L = 0x00040000, + SECAM_L1 = 0x00080000, + PAL_N_COMBO = 0x00100000 // Argentina + } + + [Flags, ComVisible( false )] + internal enum VideoControlFlags + { + FlipHorizontal = 0x0001, + FlipVertical = 0x0002, + ExternalTriggerEnable = 0x0004, + Trigger = 0x0008 + } + + [StructLayout( LayoutKind.Sequential ), ComVisible( false )] + internal class VideoStreamConfigCaps // VIDEO_STREAM_CONFIG_CAPS + { + public Guid Guid; + public AnalogVideoStandard VideoStandard; + public Size InputSize; + public Size MinCroppingSize; + public Size MaxCroppingSize; + public int CropGranularityX; + public int CropGranularityY; + public int CropAlignX; + public int CropAlignY; + public Size MinOutputSize; + public Size MaxOutputSize; + public int OutputGranularityX; + public int OutputGranularityY; + public int StretchTapsX; + public int StretchTapsY; + public int ShrinkTapsX; + public int ShrinkTapsY; + public long MinFrameInterval; + public long MaxFrameInterval; + public int MinBitsPerSecond; + public int MaxBitsPerSecond; + } + + /// + /// Specifies a filter's state or the state of the filter graph. + /// + internal enum FilterState + { + /// + /// Stopped. The filter is not processing data. + /// + State_Stopped, + + /// + /// Paused. The filter is processing data, but not rendering it. + /// + State_Paused, + + /// + /// Running. The filter is processing and rendering data. + /// + State_Running + } +} diff --git a/Sources/Accord.Video.DirectShow/Internals/Tools.cs b/Sources/Accord.Video.DirectShow/Internals/Tools.cs new file mode 100644 index 0000000000..0c9cc84a6 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/Tools.cs @@ -0,0 +1,95 @@ +// AForge Direct Show Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2007 +// andrew.kirillov@gmail.com +// + +namespace AForge.Video.DirectShow.Internals +{ + using System; + using System.Runtime.InteropServices; + + /// + /// Some miscellaneous functions. + /// + /// + internal static class Tools + { + /// + /// Get filter's pin. + /// + /// + /// Filter to get pin of. + /// Pin's direction. + /// Pin's number. + /// + /// Returns filter's pin. + /// + public static IPin GetPin( IBaseFilter filter, PinDirection dir, int num ) + { + IPin[] pin = new IPin[1]; + IEnumPins pinsEnum = null; + + // enum filter pins + if ( filter.EnumPins( out pinsEnum ) == 0 ) + { + PinDirection pinDir; + int n; + + try + { + // get next pin + while ( pinsEnum.Next( 1, pin, out n ) == 0 ) + { + // query pin`s direction + pin[0].QueryDirection( out pinDir ); + + if ( pinDir == dir ) + { + if ( num == 0 ) + return pin[0]; + num--; + } + + Marshal.ReleaseComObject( pin[0] ); + pin[0] = null; + } + } + finally + { + Marshal.ReleaseComObject( pinsEnum ); + } + } + return null; + } + + /// + /// Get filter's input pin. + /// + /// + /// Filter to get pin of. + /// Pin's number. + /// + /// Returns filter's pin. + /// + public static IPin GetInPin( IBaseFilter filter, int num ) + { + return GetPin( filter, PinDirection.Input, num ); + } + + /// + /// Get filter's output pin. + /// + /// + /// Filter to get pin of. + /// Pin's number. + /// + /// Returns filter's pin. + /// + public static IPin GetOutPin( IBaseFilter filter, int num ) + { + return GetPin( filter, PinDirection.Output, num ); + } + } +} diff --git a/Sources/Accord.Video.DirectShow/Internals/Uuids.cs b/Sources/Accord.Video.DirectShow/Internals/Uuids.cs new file mode 100644 index 0000000000..8dc187454 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/Uuids.cs @@ -0,0 +1,299 @@ +// AForge Direct Show Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2009-2013 +// contacts@aforgenet.com +// + +namespace AForge.Video.DirectShow.Internals +{ + using System; + using System.Runtime.InteropServices; + + /// + /// DirectShow class IDs. + /// + [ComVisible( false )] + static internal class Clsid + { + /// + /// System device enumerator. + /// + /// + /// Equals to CLSID_SystemDeviceEnum. + /// + public static readonly Guid SystemDeviceEnum = + new Guid( 0x62BE5D10, 0x60EB, 0x11D0, 0xBD, 0x3B, 0x00, 0xA0, 0xC9, 0x11, 0xCE, 0x86 ); + + /// + /// Filter graph. + /// + /// + /// Equals to CLSID_FilterGraph. + /// + public static readonly Guid FilterGraph = + new Guid( 0xE436EBB3, 0x524F, 0x11CE, 0x9F, 0x53, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70 ); + + /// + /// Sample grabber. + /// + /// + /// Equals to CLSID_SampleGrabber. + /// + public static readonly Guid SampleGrabber = + new Guid( 0xC1F400A0, 0x3F08, 0x11D3, 0x9F, 0x0B, 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37 ); + + /// + /// Capture graph builder. + /// + /// + /// Equals to CLSID_CaptureGraphBuilder2. + /// + public static readonly Guid CaptureGraphBuilder2 = + new Guid( 0xBF87B6E1, 0x8C27, 0x11D0, 0xB3, 0xF0, 0x00, 0xAA, 0x00, 0x37, 0x61, 0xC5 ); + + /// + /// Async reader. + /// + /// + /// Equals to CLSID_AsyncReader. + /// + public static readonly Guid AsyncReader = + new Guid( 0xE436EBB5, 0x524F, 0x11CE, 0x9F, 0x53, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70 ); + } + + /// + /// DirectShow format types. + /// + /// + [ComVisible( false )] + static internal class FormatType + { + /// + /// VideoInfo. + /// + /// + /// Equals to FORMAT_VideoInfo. + /// + public static readonly Guid VideoInfo = + new Guid( 0x05589F80, 0xC356, 0x11CE, 0xBF, 0x01, 0x00, 0xAA, 0x00, 0x55, 0x59, 0x5A ); + + /// + /// VideoInfo2. + /// + /// + /// Equals to FORMAT_VideoInfo2. + /// + public static readonly Guid VideoInfo2 = + new Guid( 0xf72A76A0, 0xEB0A, 0x11D0, 0xAC, 0xE4, 0x00, 0x00, 0xC0, 0xCC, 0x16, 0xBA ); + } + + /// + /// DirectShow media types. + /// + /// + [ComVisible( false )] + static internal class MediaType + { + /// + /// Video. + /// + /// + /// Equals to MEDIATYPE_Video. + /// + public static readonly Guid Video = + new Guid( 0x73646976, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 ); + + /// + /// Interleaved. Used by Digital Video (DV). + /// + /// + /// Equals to MEDIATYPE_Interleaved. + /// + public static readonly Guid Interleaved = + new Guid( 0x73766169, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 ); + + /// + /// Audio. + /// + /// + /// Equals to MEDIATYPE_Audio. + /// + public static readonly Guid Audio = + new Guid( 0x73647561, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 ); + + /// + /// Text. + /// + /// + /// Equals to MEDIATYPE_Text. + /// + public static readonly Guid Text = + new Guid( 0x73747874, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 ); + + /// + /// Byte stream with no time stamps. + /// + /// + /// Equals to MEDIATYPE_Stream. + /// + public static readonly Guid Stream = + new Guid( 0xE436EB83, 0x524F, 0x11CE, 0x9F, 0x53, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70 ); + } + + /// + /// DirectShow media subtypes. + /// + /// + [ComVisible( false )] + static internal class MediaSubType + { + /// + /// YUY2 (packed 4:2:2). + /// + /// + /// Equals to MEDIASUBTYPE_YUYV. + /// + public static readonly Guid YUYV = + new Guid( 0x56595559, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 ); + + /// + /// IYUV. + /// + /// + /// Equals to MEDIASUBTYPE_IYUV. + /// + public static readonly Guid IYUV = + new Guid( 0x56555949, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 ); + + /// + /// A DV encoding format. (FOURCC 'DVSD') + /// + /// + /// Equals to MEDIASUBTYPE_DVSD. + /// + public static readonly Guid DVSD = + new Guid( 0x44535644, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 ); + + /// + /// RGB, 1 bit per pixel (bpp), palettized. + /// + /// + /// Equals to MEDIASUBTYPE_RGB1. + /// + public static readonly Guid RGB1 = + new Guid( 0xE436EB78, 0x524F, 0x11CE, 0x9F, 0x53, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70 ); + + /// + /// RGB, 4 bpp, palettized. + /// + /// + /// Equals to MEDIASUBTYPE_RGB4. + /// + public static readonly Guid RGB4 = + new Guid( 0xE436EB79, 0x524F, 0x11CE, 0x9F, 0x53, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70 ); + + /// + /// RGB, 8 bpp. + /// + /// + /// Equals to MEDIASUBTYPE_RGB8. + /// + public static readonly Guid RGB8 = + new Guid( 0xE436EB7A, 0x524F, 0x11CE, 0x9F, 0x53, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70 ); + + /// + /// RGB 565, 16 bpp. + /// + /// + /// Equals to MEDIASUBTYPE_RGB565. + /// + public static readonly Guid RGB565 = + new Guid( 0xE436EB7B, 0x524F, 0x11CE, 0x9F, 0x53, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70 ); + + /// + /// RGB 555, 16 bpp. + /// + /// + /// Equals to MEDIASUBTYPE_RGB555. + /// + public static readonly Guid RGB555 = + new Guid( 0xE436EB7C, 0x524F, 0x11CE, 0x9F, 0x53, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70 ); + + /// + /// RGB, 24 bpp. + /// + /// + /// Equals to MEDIASUBTYPE_RGB24. + /// + public static readonly Guid RGB24 = + new Guid( 0xE436Eb7D, 0x524F, 0x11CE, 0x9F, 0x53, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70 ); + + /// + /// RGB, 32 bpp, no alpha channel. + /// + /// + /// Equals to MEDIASUBTYPE_RGB32. + /// + public static readonly Guid RGB32 = + new Guid( 0xE436EB7E, 0x524F, 0x11CE, 0x9F, 0x53, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70 ); + + /// + /// Data from AVI file. + /// + /// + /// Equals to MEDIASUBTYPE_Avi. + /// + public static readonly Guid Avi = + new Guid( 0xE436EB88, 0x524F, 0x11CE, 0x9F, 0x53, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70 ); + + /// + /// Advanced Streaming Format (ASF). + /// + /// + /// Equals to MEDIASUBTYPE_Asf. + /// + public static readonly Guid Asf = + new Guid( 0x3DB80F90, 0x9412, 0x11D1, 0xAD, 0xED, 0x00, 0x00, 0xF8, 0x75, 0x4B, 0x99 ); + } + + /// + /// DirectShow pin categories. + /// + /// + [ComVisible( false )] + static internal class PinCategory + { + /// + /// Capture pin. + /// + /// + /// Equals to PIN_CATEGORY_CAPTURE. + /// + public static readonly Guid Capture = + new Guid( 0xFB6C4281, 0x0353, 0x11D1, 0x90, 0x5F, 0x00, 0x00, 0xC0, 0xCC, 0x16, 0xBA ); + + /// + /// Still image pin. + /// + /// + /// Equals to PIN_CATEGORY_STILL. + /// + public static readonly Guid StillImage = + new Guid( 0xFB6C428A, 0x0353, 0x11D1, 0x90, 0x5F, 0x00, 0x00, 0xC0, 0xCC, 0x16, 0xBA ); + } + + // Below GUIDs are used by ICaptureGraphBuilder::FindInterface(). + [ComVisible( false )] + static internal class FindDirection + { + /// Equals to LOOK_UPSTREAM_ONLY. + public static readonly Guid UpstreamOnly = + new Guid( 0xAC798BE0, 0x98E3, 0x11D1, 0xB3, 0xF1, 0x00, 0xAA, 0x00, 0x37, 0x61, 0xC5 ); + + /// Equals to LOOK_DOWNSTREAM_ONLY. + public static readonly Guid DownstreamOnly = + new Guid( 0xAC798BE1, 0x98E3, 0x11D1, 0xB3, 0xF1, 0x00, 0xAA, 0x00, 0x37, 0x61, 0xC5 ); + } +} diff --git a/Sources/Accord.Video.DirectShow/Internals/Win32.cs b/Sources/Accord.Video.DirectShow/Internals/Win32.cs new file mode 100644 index 0000000000..73d2e9092 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Internals/Win32.cs @@ -0,0 +1,102 @@ +// AForge Video for Windows Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com +// + +namespace AForge.Video.DirectShow.Internals +{ + using System; + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.ComTypes; + + /// + /// Some Win32 API used internally. + /// + /// + internal static class Win32 + { + /// + /// Supplies a pointer to an implementation of IBindCtx (a bind context object). + /// This object stores information about a particular moniker-binding operation. + /// + /// + /// Reserved for future use; must be zero. + /// Address of IBindCtx* pointer variable that receives the + /// interface pointer to the new bind context object. + /// + /// Returns S_OK on success. + /// + [DllImport( "ole32.dll" )] + public static extern + int CreateBindCtx( int reserved, out IBindCtx ppbc ); + + /// + /// Converts a string into a moniker that identifies the object named by the string. + /// + /// + /// Pointer to the IBindCtx interface on the bind context object to be used in this binding operation. + /// Pointer to a zero-terminated wide character string containing the display name to be parsed. + /// Pointer to the number of characters of szUserName that were consumed. + /// Address of IMoniker* pointer variable that receives the interface pointer + /// to the moniker that was built from szUserName. + /// + /// Returns S_OK on success. + /// + [DllImport( "ole32.dll", CharSet = CharSet.Unicode )] + public static extern + int MkParseDisplayName( IBindCtx pbc, string szUserName, + ref int pchEaten, out IMoniker ppmk ); + + /// + /// Copy a block of memory. + /// + /// + /// Destination pointer. + /// Source pointer. + /// Memory block's length to copy. + /// + /// Return's the value of dst - pointer to destination. + /// + [DllImport( "ntdll.dll", CallingConvention = CallingConvention.Cdecl )] + public static unsafe extern int memcpy( + byte* dst, + byte* src, + int count ); + + /// + /// Invokes a new property frame, that is, a property sheet dialog box. + /// + /// + /// Parent window of property sheet dialog box. + /// Horizontal position for dialog box. + /// Vertical position for dialog box. + /// Dialog box caption. + /// Number of object pointers in ppUnk. + /// Pointer to the objects for property sheet. + /// Number of property pages in lpPageClsID. + /// Array of CLSIDs for each property page. + /// Locale identifier for property sheet locale. + /// Reserved. + /// Reserved. + /// + /// Returns S_OK on success. + /// + [DllImport( "oleaut32.dll" )] + public static extern int OleCreatePropertyFrame( + IntPtr hwndOwner, + int x, + int y, + [MarshalAs( UnmanagedType.LPWStr )] string caption, + int cObjects, + [MarshalAs( UnmanagedType.Interface, ArraySubType = UnmanagedType.IUnknown )] + ref object ppUnk, + int cPages, + IntPtr lpPageClsID, + int lcid, + int dwReserved, + IntPtr lpvReserved ); + } +} diff --git a/Sources/Accord.Video.DirectShow/PhysicalConnectorType.cs b/Sources/Accord.Video.DirectShow/PhysicalConnectorType.cs new file mode 100644 index 0000000000..365a7c3c0 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/PhysicalConnectorType.cs @@ -0,0 +1,123 @@ +// AForge Direct Show Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2009-2012 +// contacts@aforgenet.com +// + +namespace AForge.Video.DirectShow +{ + /// + /// Specifies the physical type of pin (audio or video). + /// + public enum PhysicalConnectorType + { + /// + /// Default value of connection type. Physically it does not exist, but just either to specify that + /// connection type should not be changed (input) or was not determined (output). + /// + Default = 0, + /// + /// Specifies a tuner pin for video. + /// + VideoTuner = 1, + /// + /// Specifies a composite pin for video. + /// + VideoComposite, + /// + /// Specifies an S-Video (Y/C video) pin. + /// + VideoSVideo, + /// + /// Specifies an RGB pin for video. + /// + VideoRGB, + /// + /// Specifies a YRYBY (Y, R–Y, B–Y) pin for video. + /// + VideoYRYBY, + /// + /// Specifies a serial digital pin for video. + /// + VideoSerialDigital, + /// + /// Specifies a parallel digital pin for video. + /// + VideoParallelDigital, + /// + /// Specifies a SCSI (Small Computer System Interface) pin for video. + /// + VideoSCSI, + /// + /// Specifies an AUX (auxiliary) pin for video. + /// + VideoAUX, + /// + /// Specifies an IEEE 1394 pin for video. + /// + Video1394, + /// + /// Specifies a USB (Universal Serial Bus) pin for video. + /// + VideoUSB, + /// + /// Specifies a video decoder pin. + /// + VideoDecoder, + /// + /// Specifies a video encoder pin. + /// + VideoEncoder, + /// + /// Specifies a SCART (Peritel) pin for video. + /// + VideoSCART, + /// + /// Not used. + /// + VideoBlack, + + /// + /// Specifies a tuner pin for audio. + /// + AudioTuner = 4096, + /// + /// Specifies a line pin for audio. + /// + AudioLine, + /// + /// Specifies a microphone pin. + /// + AudioMic, + /// + /// Specifies an AES/EBU (Audio Engineering Society/European Broadcast Union) digital pin for audio. + /// + AudioAESDigital, + /// + /// Specifies an S/PDIF (Sony/Philips Digital Interface Format) digital pin for audio. + /// + AudioSPDIFDigital, + /// + /// Specifies a SCSI pin for audio. + /// + AudioSCSI, + /// + /// Specifies an AUX pin for audio. + /// + AudioAUX, + /// + /// Specifies an IEEE 1394 pin for audio. + /// + Audio1394, + /// + /// Specifies a USB pin for audio. + /// + AudioUSB, + /// + /// Specifies an audio decoder pin. + /// + AudioDecoder + } +} diff --git a/Sources/Accord.Video.DirectShow/Properties/AssemblyInfo.cs b/Sources/Accord.Video.DirectShow/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..47d7db11d --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Properties/AssemblyInfo.cs @@ -0,0 +1,13 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Accord.Video.DirectShow")] +[assembly: AssemblyDescription("Accord.NET - Video DirectShow Interface Library")] +[assembly: AssemblyConfiguration("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. +[assembly: ComVisible(false)] diff --git a/Sources/Accord.Video.DirectShow/Properties/Resources.Designer.cs b/Sources/Accord.Video.DirectShow/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..5618f0d65 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Properties/Resources.Designer.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Accord.Video.DirectShow.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Accord.Video.DirectShow.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap camera { + get { + object obj = ResourceManager.GetObject("camera", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/Sources/Accord.Video.DirectShow/Properties/Resources.resx b/Sources/Accord.Video.DirectShow/Properties/Resources.resx new file mode 100644 index 0000000000..24fdc6b60 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Properties/Resources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Icons\camera.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/Sources/Accord.Video.DirectShow/Uuids.cs b/Sources/Accord.Video.DirectShow/Uuids.cs new file mode 100644 index 0000000000..3256fedce --- /dev/null +++ b/Sources/Accord.Video.DirectShow/Uuids.cs @@ -0,0 +1,55 @@ +// AForge Direct Show Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Video.DirectShow +{ + using System; + using System.Runtime.InteropServices; + + /// + /// DirectShow filter categories. + /// + [ComVisible( false )] + public static class FilterCategory + { + /// + /// Audio input device category. + /// + /// + /// Equals to CLSID_AudioInputDeviceCategory. + /// + public static readonly Guid AudioInputDevice = + new Guid( 0x33D9A762, 0x90C8, 0x11D0, 0xBD, 0x43, 0x00, 0xA0, 0xC9, 0x11, 0xCE, 0x86 ); + + /// + /// Video input device category. + /// + /// + /// Equals to CLSID_VideoInputDeviceCategory. + /// + public static readonly Guid VideoInputDevice = + new Guid( 0x860BB310, 0x5D01, 0x11D0, 0xBD, 0x3B, 0x00, 0xA0, 0xC9, 0x11, 0xCE, 0x86 ); + + /// + /// Video compressor category. + /// + /// + /// Equals to CLSID_VideoCompressorCategory. + /// + public static readonly Guid VideoCompressorCategory = + new Guid( 0x33D9A760, 0x90C8, 0x11D0, 0xBD, 0x43, 0x00, 0xA0, 0xC9, 0x11, 0xCE, 0x86 ); + + /// + /// Audio compressor category + /// + /// + /// Equals to CLSID_AudioCompressorCategory. + /// + public static readonly Guid AudioCompressorCategory = + new Guid( 0x33D9A761, 0x90C8, 0x11D0, 0xBD, 0x43, 0x00, 0xA0, 0xC9, 0x11, 0xCE, 0x86 ); + } +} diff --git a/Sources/Accord.Video.DirectShow/VideoCapabilities.cs b/Sources/Accord.Video.DirectShow/VideoCapabilities.cs new file mode 100644 index 0000000000..a7c8dd413 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/VideoCapabilities.cs @@ -0,0 +1,245 @@ +// AForge Direct Show Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2009-2013 +// contacts@aforgenet.com +// + +namespace AForge.Video.DirectShow +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Runtime.InteropServices; + + using AForge.Video; + using AForge.Video.DirectShow.Internals; + + /// + /// Capabilities of video device such as frame size and frame rate. + /// + public class VideoCapabilities + { + /// + /// Frame size supported by video device. + /// + public readonly Size FrameSize; + + /// + /// Frame rate supported by video device for corresponding frame size. + /// + /// + /// This field is depricated - should not be used. + /// Its value equals to . + /// + /// + [Obsolete( "No longer supported. Use AverageFrameRate instead." )] + public int FrameRate + { + get { return AverageFrameRate; } + } + + /// + /// Average frame rate of video device for corresponding frame size. + /// + public readonly int AverageFrameRate; + + /// + /// Maximum frame rate of video device for corresponding frame size. + /// + public readonly int MaximumFrameRate; + + /// + /// Number of bits per pixel provided by the camera. + /// + public readonly int BitCount; + + internal VideoCapabilities( ) { } + + // Retrieve capabilities of a video device + static internal VideoCapabilities[] FromStreamConfig( IAMStreamConfig videoStreamConfig ) + { + if ( videoStreamConfig == null ) + throw new ArgumentNullException( "videoStreamConfig" ); + + // ensure this device reports capabilities + int count, size; + int hr = videoStreamConfig.GetNumberOfCapabilities( out count, out size ); + + if ( hr != 0 ) + Marshal.ThrowExceptionForHR( hr ); + + if ( count <= 0 ) + throw new NotSupportedException( "This video device does not report capabilities." ); + + if ( size > Marshal.SizeOf( typeof( VideoStreamConfigCaps ) ) ) + throw new NotSupportedException( "Unable to retrieve video device capabilities. This video device requires a larger VideoStreamConfigCaps structure." ); + + // group capabilities with similar parameters + Dictionary videocapsList = new Dictionary( ); + + for ( int i = 0; i < count; i++ ) + { + try + { + VideoCapabilities vc = new VideoCapabilities( videoStreamConfig, i ); + + uint key = ( ( (uint) vc.FrameSize.Height ) << 32 ) | + ( ( (uint) vc.FrameSize.Width ) << 16 ); + + if ( !videocapsList.ContainsKey( key ) ) + { + videocapsList.Add( key, vc ); + } + else + { + if ( vc.BitCount > videocapsList[key].BitCount ) + { + videocapsList[key] = vc; + } + } + } + catch + { + } + } + + VideoCapabilities[] videocaps = new VideoCapabilities[videocapsList.Count]; + videocapsList.Values.CopyTo( videocaps, 0 ); + + return videocaps; + } + + // Retrieve capabilities of a video device + internal VideoCapabilities( IAMStreamConfig videoStreamConfig, int index ) + { + AMMediaType mediaType = null; + VideoStreamConfigCaps caps = new VideoStreamConfigCaps( ); + + try + { + // retrieve capabilities struct at the specified index + int hr = videoStreamConfig.GetStreamCaps( index, out mediaType, caps ); + + if ( hr != 0 ) + Marshal.ThrowExceptionForHR( hr ); + + if ( mediaType.FormatType == FormatType.VideoInfo ) + { + VideoInfoHeader videoInfo = (VideoInfoHeader) Marshal.PtrToStructure( mediaType.FormatPtr, typeof( VideoInfoHeader ) ); + + FrameSize = new Size( videoInfo.BmiHeader.Width, videoInfo.BmiHeader.Height ); + BitCount = videoInfo.BmiHeader.BitCount; + AverageFrameRate = (int) ( 10000000 / videoInfo.AverageTimePerFrame ); + MaximumFrameRate = (int) ( 10000000 / caps.MinFrameInterval ); + } + else if ( mediaType.FormatType == FormatType.VideoInfo2 ) + { + VideoInfoHeader2 videoInfo = (VideoInfoHeader2) Marshal.PtrToStructure( mediaType.FormatPtr, typeof( VideoInfoHeader2 ) ); + + FrameSize = new Size( videoInfo.BmiHeader.Width, videoInfo.BmiHeader.Height ); + BitCount = videoInfo.BmiHeader.BitCount; + AverageFrameRate = (int) ( 10000000 / videoInfo.AverageTimePerFrame ); + MaximumFrameRate = (int) ( 10000000 / caps.MinFrameInterval ); + } + else + { + throw new ApplicationException( "Unsupported format found." ); + } + + // ignore 12 bpp formats for now, since it was noticed they cause issues on Windows 8 + // TODO: proper fix needs to be done so ICaptureGraphBuilder2::RenderStream() does not fail + // on such formats + if ( BitCount <= 12 ) + { + throw new ApplicationException( "Unsupported format found." ); + } + } + finally + { + if ( mediaType != null ) + mediaType.Dispose( ); + } + } + + /// + /// Check if the video capability equals to the specified object. + /// + /// + /// Object to compare with. + /// + /// Returns true if both are equal are equal or false otherwise. + /// + public override bool Equals( object obj ) + { + return Equals( obj as VideoCapabilities ); + } + + /// + /// Check if two video capabilities are equal. + /// + /// + /// Second video capability to compare with. + /// + /// Returns true if both video capabilities are equal or false otherwise. + /// + public bool Equals( VideoCapabilities vc2 ) + { + if ( (object) vc2 == null ) + { + return false; + } + + return ( ( FrameSize == vc2.FrameSize ) && ( BitCount == vc2.BitCount ) ); + } + + /// + /// Get hash code of the object. + /// + /// + /// Returns hash code ot the object + public override int GetHashCode( ) + { + return FrameSize.GetHashCode( ) ^ BitCount; + } + + /// + /// Equality operator. + /// + /// + /// First object to check. + /// Seconds object to check. + /// + /// Return true if both objects are equal or false otherwise. + public static bool operator ==( VideoCapabilities a, VideoCapabilities b ) + { + // if both are null, or both are same instance, return true. + if ( object.ReferenceEquals( a, b ) ) + { + return true; + } + + // if one is null, but not both, return false. + if ( ( (object) a == null ) || ( (object) b == null ) ) + { + return false; + } + + return a.Equals( b ); + } + + /// + /// Inequality operator. + /// + /// + /// First object to check. + /// Seconds object to check. + /// + /// Return true if both objects are not equal or false otherwise. + public static bool operator !=( VideoCapabilities a, VideoCapabilities b ) + { + return !( a == b ); + } + } +} diff --git a/Sources/Accord.Video.DirectShow/VideoCaptureDevice.cs b/Sources/Accord.Video.DirectShow/VideoCaptureDevice.cs new file mode 100644 index 0000000000..d2ba52fee --- /dev/null +++ b/Sources/Accord.Video.DirectShow/VideoCaptureDevice.cs @@ -0,0 +1,1700 @@ +// AForge Direct Show Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2009-2013 +// contacts@aforgenet.com +// + +namespace AForge.Video.DirectShow +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + using System.Threading; + using System.Runtime.InteropServices; + + using AForge.Video; + using AForge.Video.DirectShow.Internals; + + /// + /// Video source for local video capture device (for example USB webcam). + /// + /// + /// This video source class captures video data from local video capture device, + /// like USB web camera (or internal), frame grabber, capture board - anything which + /// supports DirectShow interface. For devices which has a shutter button or + /// support external software triggering, the class also allows to do snapshots. Both + /// video size and snapshot size can be configured. + /// + /// Sample usage: + /// + /// // enumerate video devices + /// videoDevices = new FilterInfoCollection( FilterCategory.VideoInputDevice ); + /// // create video source + /// VideoCaptureDevice videoSource = new VideoCaptureDevice( videoDevices[0].MonikerString ); + /// // set NewFrame event handler + /// videoSource.NewFrame += new NewFrameEventHandler( video_NewFrame ); + /// // start the video source + /// videoSource.Start( ); + /// // ... + /// // signal to stop when you no longer need capturing + /// videoSource.SignalToStop( ); + /// // ... + /// + /// private void video_NewFrame( object sender, NewFrameEventArgs eventArgs ) + /// { + /// // get new frame + /// Bitmap bitmap = eventArgs.Frame; + /// // process the frame + /// } + /// + /// + /// + public class VideoCaptureDevice : IVideoSource + { + // moniker string of video capture device + private string deviceMoniker; + // received frames count + private int framesReceived; + // recieved byte count + private long bytesReceived; + + // video and snapshot resolutions to set + private VideoCapabilities videoResolution = null; + private VideoCapabilities snapshotResolution = null; + + // provide snapshots or not + private bool provideSnapshots = false; + + private Thread thread = null; + private ManualResetEvent stopEvent = null; + + private VideoCapabilities[] videoCapabilities; + private VideoCapabilities[] snapshotCapabilities; + + private bool needToSetVideoInput = false; + private bool needToSimulateTrigger = false; + private bool needToDisplayPropertyPage = false; + private bool needToDisplayCrossBarPropertyPage = false; + private IntPtr parentWindowForPropertyPage = IntPtr.Zero; + + // video capture source object + private object sourceObject = null; + + // time of starting the DirectX graph + private DateTime startTime = new DateTime( ); + + // dummy object to lock for synchronization + private object sync = new object( ); + + // flag specifying if IAMCrossbar interface is supported by the running graph/source object + private bool? isCrossbarAvailable = null; + + private VideoInput[] crossbarVideoInputs = null; + private VideoInput crossbarVideoInput = VideoInput.Default; + + // cache for video/snapshot capabilities and video inputs + private static Dictionary cacheVideoCapabilities = new Dictionary( ); + private static Dictionary cacheSnapshotCapabilities = new Dictionary( ); + private static Dictionary cacheCrossbarVideoInputs = new Dictionary( ); + + /// + /// Current video input of capture card. + /// + /// + /// The property specifies video input to use for video devices like capture cards + /// (those which provide crossbar configuration). List of available video inputs can be obtained + /// from property. + /// + /// To check if the video device supports crossbar configuration, the + /// method can be used. + /// + /// This property can be set as before running video device, as while running it. + /// + /// By default this property is set to , which means video input + /// will not be set when running video device, but currently configured will be used. After video device + /// is started this property will be updated anyway to tell current video input. + /// + /// + public VideoInput CrossbarVideoInput + { + get { return crossbarVideoInput; } + set + { + needToSetVideoInput = true; + crossbarVideoInput = value; + } + } + + /// + /// Available inputs of the video capture card. + /// + /// + /// The property provides list of video inputs for devices like video capture cards. + /// Such devices usually provide several video inputs, which can be selected using crossbar. + /// If video device represented by the object of this class supports crossbar, then this property + /// will list all video inputs. However if it is a regular USB camera, for example, which does not + /// provide crossbar configuration, the property will provide zero length array. + /// + /// Video input to be used can be selected using . See also + /// method, which provides crossbar configuration dialog. + /// + /// It is recomended not to call this property immediately after method, since + /// device may not start yet and provide its information. It is better to call the property + /// before starting device or a bit after (but not immediately after). + /// + /// + public VideoInput[] AvailableCrossbarVideoInputs + { + get + { + if ( crossbarVideoInputs == null ) + { + lock ( cacheCrossbarVideoInputs ) + { + if ( ( !string.IsNullOrEmpty( deviceMoniker ) ) && ( cacheCrossbarVideoInputs.ContainsKey( deviceMoniker ) ) ) + { + crossbarVideoInputs = cacheCrossbarVideoInputs[deviceMoniker]; + } + } + + if ( crossbarVideoInputs == null ) + { + if ( !IsRunning ) + { + // create graph without playing to collect available inputs + WorkerThread( false ); + } + else + { + for ( int i = 0; ( i < 500 ) && ( crossbarVideoInputs == null ); i++ ) + { + Thread.Sleep( 10 ); + } + } + } + } + // don't return null even if capabilities are not provided for some reason + return ( crossbarVideoInputs != null ) ? crossbarVideoInputs : new VideoInput[0]; + } + } + + /// + /// Specifies if snapshots should be provided or not. + /// + /// + /// Some USB cameras/devices may have a shutter button, which may result into snapshot if it + /// is pressed. So the property specifies if the video source will try providing snapshots or not - it will + /// check if the camera supports providing still image snapshots. If camera supports snapshots and the property + /// is set to , then snapshots will be provided through + /// event. + /// + /// Check supported sizes of snapshots using property and set the + /// desired size using property. + /// + /// The property must be set before running the video source to take effect. + /// + /// Default value of the property is set to . + /// + /// + public bool ProvideSnapshots + { + get { return provideSnapshots; } + set { provideSnapshots = value; } + } + + /// + /// New frame event. + /// + /// + /// Notifies clients about new available frame from video source. + /// + /// Since video source may have multiple clients, each client is responsible for + /// making a copy (cloning) of the passed video frame, because the video source disposes its + /// own original copy after notifying of clients. + /// + /// + public event NewFrameEventHandler NewFrame; + + /// + /// Snapshot frame event. + /// + /// + /// Notifies clients about new available snapshot frame - the one which comes when + /// camera's snapshot/shutter button is pressed. + /// + /// See documentation to for additional information. + /// + /// Since video source may have multiple clients, each client is responsible for + /// making a copy (cloning) of the passed snapshot frame, because the video source disposes its + /// own original copy after notifying of clients. + /// + /// + /// + /// + public event NewFrameEventHandler SnapshotFrame; + + /// + /// Video source error event. + /// + /// + /// This event is used to notify clients about any type of errors occurred in + /// video source object, for example internal exceptions. + /// + public event VideoSourceErrorEventHandler VideoSourceError; + + /// + /// Video playing finished event. + /// + /// + /// This event is used to notify clients that the video playing has finished. + /// + /// + public event PlayingFinishedEventHandler PlayingFinished; + + /// + /// Video source. + /// + /// + /// Video source is represented by moniker string of video capture device. + /// + public virtual string Source + { + get { return deviceMoniker; } + set + { + deviceMoniker = value; + + videoCapabilities = null; + snapshotCapabilities = null; + crossbarVideoInputs = null; + isCrossbarAvailable = null; + } + } + + /// + /// Received frames count. + /// + /// + /// Number of frames the video source provided from the moment of the last + /// access to the property. + /// + /// + public int FramesReceived + { + get + { + int frames = framesReceived; + framesReceived = 0; + return frames; + } + } + + /// + /// Received bytes count. + /// + /// + /// Number of bytes the video source provided from the moment of the last + /// access to the property. + /// + /// + public long BytesReceived + { + get + { + long bytes = bytesReceived; + bytesReceived = 0; + return bytes; + } + } + + /// + /// State of the video source. + /// + /// + /// Current state of video source object - running or not. + /// + public bool IsRunning + { + get + { + if ( thread != null ) + { + // check thread status + if ( thread.Join( 0 ) == false ) + return true; + + // the thread is not running, free resources + Free( ); + } + return false; + } + } + + /// + /// Obsolete - no longer in use + /// + /// + /// The property is obsolete. Use property instead. + /// Setting this property does not have any effect. + /// + [Obsolete] + public Size DesiredFrameSize + { + get { return Size.Empty; } + set { } + } + + /// + /// Obsolete - no longer in use + /// + /// + /// The property is obsolete. Use property instead. + /// Setting this property does not have any effect. + /// + [Obsolete] + public Size DesiredSnapshotSize + { + get { return Size.Empty; } + set { } + } + + /// + /// Obsolete - no longer in use. + /// + /// + /// The property is obsolete. Setting this property does not have any effect. + /// + [Obsolete] + public int DesiredFrameRate + { + get { return 0; } + set { } + } + + /// + /// Video resolution to set. + /// + /// + /// The property allows to set one of the video resolutions supported by the camera. + /// Use property to get the list of supported video resolutions. + /// + /// The property must be set before camera is started to make any effect. + /// + /// Default value of the property is set to , which means default video + /// resolution is used. + /// + /// + public VideoCapabilities VideoResolution + { + get { return videoResolution; } + set { videoResolution = value; } + } + + /// + /// Snapshot resolution to set. + /// + /// + /// The property allows to set one of the snapshot resolutions supported by the camera. + /// Use property to get the list of supported snapshot resolutions. + /// + /// The property must be set before camera is started to make any effect. + /// + /// Default value of the property is set to , which means default snapshot + /// resolution is used. + /// + /// + public VideoCapabilities SnapshotResolution + { + get { return snapshotResolution; } + set { snapshotResolution = value; } + } + + /// + /// Video capabilities of the device. + /// + /// + /// The property provides list of device's video capabilities. + /// + /// It is recomended not to call this property immediately after method, since + /// device may not start yet and provide its information. It is better to call the property + /// before starting device or a bit after (but not immediately after). + /// + /// + public VideoCapabilities[] VideoCapabilities + { + get + { + if ( videoCapabilities == null ) + { + lock ( cacheVideoCapabilities ) + { + if ( ( !string.IsNullOrEmpty( deviceMoniker ) ) && ( cacheVideoCapabilities.ContainsKey( deviceMoniker ) ) ) + { + videoCapabilities = cacheVideoCapabilities[deviceMoniker]; + } + } + + if ( videoCapabilities == null ) + { + if ( !IsRunning ) + { + // create graph without playing to get the video/snapshot capabilities only. + // not very clean but it works + WorkerThread( false ); + } + else + { + for ( int i = 0; ( i < 500 ) && ( videoCapabilities == null ); i++ ) + { + Thread.Sleep( 10 ); + } + } + } + } + // don't return null even capabilities are not provided for some reason + return ( videoCapabilities != null ) ? videoCapabilities : new VideoCapabilities[0]; + } + } + + /// + /// Snapshot capabilities of the device. + /// + /// + /// The property provides list of device's snapshot capabilities. + /// + /// If the array has zero length, then it means that this device does not support making + /// snapshots. + /// + /// See documentation to for additional information. + /// + /// It is recomended not to call this property immediately after method, since + /// device may not start yet and provide its information. It is better to call the property + /// before starting device or a bit after (but not immediately after). + /// + /// + /// + /// + public VideoCapabilities[] SnapshotCapabilities + { + get + { + if ( snapshotCapabilities == null ) + { + lock ( cacheSnapshotCapabilities ) + { + if ( ( !string.IsNullOrEmpty( deviceMoniker ) ) && ( cacheSnapshotCapabilities.ContainsKey( deviceMoniker ) ) ) + { + snapshotCapabilities = cacheSnapshotCapabilities[deviceMoniker]; + } + } + + if ( snapshotCapabilities == null ) + { + if ( !IsRunning ) + { + // create graph without playing to get the video/snapshot capabilities only. + // not very clean but it works + WorkerThread( false ); + } + else + { + for ( int i = 0; ( i < 500 ) && ( snapshotCapabilities == null ); i++ ) + { + Thread.Sleep( 10 ); + } + } + } + } + // don't return null even capabilities are not provided for some reason + return ( snapshotCapabilities != null ) ? snapshotCapabilities : new VideoCapabilities[0]; + } + } + + /// + /// Source COM object of camera capture device. + /// + /// + /// The source COM object of camera capture device is exposed for the + /// case when user may need get direct access to the object for making some custom + /// configuration of camera through DirectShow interface, for example. + /// + /// + /// If camera is not running, the property is set to . + /// + /// + public object SourceObject + { + get { return sourceObject; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public VideoCaptureDevice( ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Moniker string of video capture device. + /// + public VideoCaptureDevice( string deviceMoniker ) + { + this.deviceMoniker = deviceMoniker; + } + + /// + /// Start video source. + /// + /// + /// Starts video source and return execution to caller. Video source + /// object creates background thread and notifies about new frames with the + /// help of event. + /// + public void Start( ) + { + if ( !IsRunning ) + { + // check source + if ( string.IsNullOrEmpty( deviceMoniker ) ) + throw new ArgumentException( "Video source is not specified." ); + + framesReceived = 0; + bytesReceived = 0; + isCrossbarAvailable = null; + needToSetVideoInput = true; + + // create events + stopEvent = new ManualResetEvent( false ); + + lock ( sync ) + { + // create and start new thread + thread = new Thread( new ThreadStart( WorkerThread ) ); + thread.Name = deviceMoniker; // mainly for debugging + thread.Start( ); + } + } + } + + /// + /// Signal video source to stop its work. + /// + /// + /// Signals video source to stop its background thread, stop to + /// provide new frames and free resources. + /// + public void SignalToStop( ) + { + // stop thread + if ( thread != null ) + { + // signal to stop + stopEvent.Set( ); + } + } + + /// + /// Wait for video source has stopped. + /// + /// + /// Waits for source stopping after it was signalled to stop using + /// method. + /// + public void WaitForStop( ) + { + if ( thread != null ) + { + // wait for thread stop + thread.Join( ); + + Free( ); + } + } + + /// + /// Stop video source. + /// + /// + /// Stops video source aborting its thread. + /// + /// Since the method aborts background thread, its usage is highly not preferred + /// and should be done only if there are no other options. The correct way of stopping camera + /// is signaling it stop and then + /// waiting for background thread's completion. + /// + /// + public void Stop( ) + { + if ( this.IsRunning ) + { + thread.Abort( ); + WaitForStop( ); + } + } + + /// + /// Free resource. + /// + /// + private void Free( ) + { + thread = null; + + // release events + stopEvent.Close( ); + stopEvent = null; + } + + /// + /// Display property window for the video capture device providing its configuration + /// capabilities. + /// + /// + /// Handle of parent window. + /// + /// If you pass parent window's handle to this method, then the + /// displayed property page will become modal window and none of the controls from the + /// parent window will be accessible. In order to make it modeless it is required + /// to pass as parent window's handle. + /// + /// + /// + /// The video source does not support configuration property page. + /// + public void DisplayPropertyPage( IntPtr parentWindow ) + { + // check source + if ( ( deviceMoniker == null ) || ( deviceMoniker == string.Empty ) ) + throw new ArgumentException( "Video source is not specified." ); + + lock ( sync ) + { + if ( IsRunning ) + { + // pass the request to backgroud thread if video source is running + parentWindowForPropertyPage = parentWindow; + needToDisplayPropertyPage = true; + return; + } + + object tempSourceObject = null; + + // create source device's object + try + { + tempSourceObject = FilterInfo.CreateFilter( deviceMoniker ); + } + catch + { + throw new ApplicationException( "Failed creating device object for moniker." ); + } + + if ( !( tempSourceObject is ISpecifyPropertyPages ) ) + { + throw new NotSupportedException( "The video source does not support configuration property page." ); + } + + DisplayPropertyPage( parentWindow, tempSourceObject ); + + Marshal.ReleaseComObject( tempSourceObject ); + } + } + + /// + /// Display property page of video crossbar (Analog Video Crossbar filter). + /// + /// + /// Handle of parent window. + /// + /// The Analog Video Crossbar filter is modeled after a general switching matrix, + /// with n inputs and m outputs. For example, a video card might have two external connectors: + /// a coaxial connector for TV, and an S-video input. These would be represented as input pins on + /// the filter. The displayed property page allows to configure the crossbar by selecting input + /// of a video card to use. + /// + /// This method can be invoked only when video source is running ( is + /// ). Otherwise it generates exception. + /// + /// Use method to check if running video source provides + /// crossbar configuration. + /// + /// + /// The video source must be running in order to display crossbar property page. + /// Crossbar configuration is not supported by currently running video source. + /// + public void DisplayCrossbarPropertyPage( IntPtr parentWindow ) + { + lock ( sync ) + { + // wait max 5 seconds till the flag gets initialized + for ( int i = 0; ( i < 500 ) && ( !isCrossbarAvailable.HasValue ) && ( IsRunning ); i++ ) + { + Thread.Sleep( 10 ); + } + + if ( ( !IsRunning ) || ( !isCrossbarAvailable.HasValue ) ) + { + throw new ApplicationException( "The video source must be running in order to display crossbar property page." ); + } + + if ( !isCrossbarAvailable.Value ) + { + throw new NotSupportedException( "Crossbar configuration is not supported by currently running video source." ); + } + + // pass the request to background thread if video source is running + parentWindowForPropertyPage = parentWindow; + needToDisplayCrossBarPropertyPage = true; + } + } + + /// + /// Check if running video source provides crossbar for configuration. + /// + /// + /// Returns if crossbar configuration is available or + /// otherwise. + /// + /// The method reports if the video source provides crossbar configuration + /// using . + /// + /// + public bool CheckIfCrossbarAvailable( ) + { + lock ( sync ) + { + if ( !isCrossbarAvailable.HasValue ) + { + if ( !IsRunning ) + { + // create graph without playing to collect available inputs + WorkerThread( false ); + } + else + { + for ( int i = 0; ( i < 500 ) && ( !isCrossbarAvailable.HasValue ); i++ ) + { + Thread.Sleep( 10 ); + } + } + } + + return ( !isCrossbarAvailable.HasValue ) ? false : isCrossbarAvailable.Value; + } + } + + + /// + /// Simulates an external trigger. + /// + /// + /// The method simulates external trigger for video cameras, which support + /// providing still image snapshots. The effect is equivalent as pressing camera's shutter + /// button - a snapshot will be provided through event. + /// + /// The property must be set to + /// to enable receiving snapshots. + /// + /// + public void SimulateTrigger( ) + { + needToSimulateTrigger = true; + } + + /// + /// Sets a specified property on the camera. + /// + /// + /// Specifies the property to set. + /// Specifies the new value of the property. + /// Specifies the desired control setting. + /// + /// Returns true on sucee or false otherwise. + /// + /// Video source is not specified - device moniker is not set. + /// Failed creating device object for moniker. + /// The video source does not support camera control. + /// + public bool SetCameraProperty( CameraControlProperty property, int value, CameraControlFlags controlFlags ) + { + bool ret = true; + + // check if source was set + if ( ( deviceMoniker == null ) || ( string.IsNullOrEmpty( deviceMoniker ) ) ) + { + throw new ArgumentException( "Video source is not specified." ); + } + + lock ( sync ) + { + object tempSourceObject = null; + + // create source device's object + try + { + tempSourceObject = FilterInfo.CreateFilter( deviceMoniker ); + } + catch + { + throw new ApplicationException( "Failed creating device object for moniker." ); + } + + if ( !( tempSourceObject is IAMCameraControl ) ) + { + throw new NotSupportedException( "The video source does not support camera control." ); + } + + IAMCameraControl pCamControl = (IAMCameraControl) tempSourceObject; + int hr = pCamControl.Set( property, value, controlFlags ); + + ret = ( hr >= 0 ); + + Marshal.ReleaseComObject( tempSourceObject ); + } + + return ret; + } + + /// + /// Gets the current setting of a camera property. + /// + /// + /// Specifies the property to retrieve. + /// Receives the value of the property. + /// Receives the value indicating whether the setting is controlled manually or automatically + /// + /// Returns true on sucee or false otherwise. + /// + /// Video source is not specified - device moniker is not set. + /// Failed creating device object for moniker. + /// The video source does not support camera control. + /// + public bool GetCameraProperty( CameraControlProperty property, out int value, out CameraControlFlags controlFlags ) + { + bool ret = true; + + // check if source was set + if ( ( deviceMoniker == null ) || ( string.IsNullOrEmpty( deviceMoniker ) ) ) + { + throw new ArgumentException( "Video source is not specified." ); + } + + lock ( sync ) + { + object tempSourceObject = null; + + // create source device's object + try + { + tempSourceObject = FilterInfo.CreateFilter( deviceMoniker ); + } + catch + { + throw new ApplicationException( "Failed creating device object for moniker." ); + } + + if ( !( tempSourceObject is IAMCameraControl ) ) + { + throw new NotSupportedException( "The video source does not support camera control." ); + } + + IAMCameraControl pCamControl = (IAMCameraControl) tempSourceObject; + int hr = pCamControl.Get( property, out value, out controlFlags ); + + ret = ( hr >= 0 ); + + Marshal.ReleaseComObject( tempSourceObject ); + } + + return ret; + } + + /// + /// Gets the range and default value of a specified camera property. + /// + /// + /// Specifies the property to query. + /// Receives the minimum value of the property. + /// Receives the maximum value of the property. + /// Receives the step size for the property. + /// Receives the default value of the property. + /// Receives a member of the enumeration, indicating whether the property is controlled automatically or manually. + /// + /// Returns true on sucee or false otherwise. + /// + /// Video source is not specified - device moniker is not set. + /// Failed creating device object for moniker. + /// The video source does not support camera control. + /// + public bool GetCameraPropertyRange( CameraControlProperty property, out int minValue, out int maxValue, out int stepSize, out int defaultValue, out CameraControlFlags controlFlags ) + { + bool ret = true; + + // check if source was set + if ( ( deviceMoniker == null ) || ( string.IsNullOrEmpty( deviceMoniker ) ) ) + { + throw new ArgumentException( "Video source is not specified." ); + } + + lock ( sync ) + { + object tempSourceObject = null; + + // create source device's object + try + { + tempSourceObject = FilterInfo.CreateFilter( deviceMoniker ); + } + catch + { + throw new ApplicationException( "Failed creating device object for moniker." ); + } + + if ( !( tempSourceObject is IAMCameraControl ) ) + { + throw new NotSupportedException( "The video source does not support camera control." ); + } + + IAMCameraControl pCamControl = (IAMCameraControl) tempSourceObject; + int hr = pCamControl.GetRange( property, out minValue, out maxValue, out stepSize, out defaultValue, out controlFlags ); + + ret = ( hr >= 0 ); + + Marshal.ReleaseComObject( tempSourceObject ); + } + + return ret; + } + + /// + /// Worker thread. + /// + /// + private void WorkerThread( ) + { + WorkerThread( true ); + } + + private void WorkerThread( bool runGraph ) + { + ReasonToFinishPlaying reasonToStop = ReasonToFinishPlaying.StoppedByUser; + bool isSapshotSupported = false; + + // grabber + Grabber videoGrabber = new Grabber( this, false ); + Grabber snapshotGrabber = new Grabber( this, true ); + + // objects + object captureGraphObject = null; + object graphObject = null; + object videoGrabberObject = null; + object snapshotGrabberObject = null; + object crossbarObject = null; + + // interfaces + ICaptureGraphBuilder2 captureGraph = null; + IFilterGraph2 graph = null; + IBaseFilter sourceBase = null; + IBaseFilter videoGrabberBase = null; + IBaseFilter snapshotGrabberBase = null; + ISampleGrabber videoSampleGrabber = null; + ISampleGrabber snapshotSampleGrabber = null; + IMediaControl mediaControl = null; + IAMVideoControl videoControl = null; + IMediaEventEx mediaEvent = null; + IPin pinStillImage = null; + IAMCrossbar crossbar = null; + + try + { + // get type of capture graph builder + Type type = Type.GetTypeFromCLSID( Clsid.CaptureGraphBuilder2 ); + if ( type == null ) + throw new ApplicationException( "Failed creating capture graph builder" ); + + // create capture graph builder + captureGraphObject = Activator.CreateInstance( type ); + captureGraph = (ICaptureGraphBuilder2) captureGraphObject; + + // get type of filter graph + type = Type.GetTypeFromCLSID( Clsid.FilterGraph ); + if ( type == null ) + throw new ApplicationException( "Failed creating filter graph" ); + + // create filter graph + graphObject = Activator.CreateInstance( type ); + graph = (IFilterGraph2) graphObject; + + // set filter graph to the capture graph builder + captureGraph.SetFiltergraph( (IGraphBuilder) graph ); + + // create source device's object + sourceObject = FilterInfo.CreateFilter( deviceMoniker ); + if ( sourceObject == null ) + throw new ApplicationException( "Failed creating device object for moniker" ); + + // get base filter interface of source device + sourceBase = (IBaseFilter) sourceObject; + + // get video control interface of the device + try + { + videoControl = (IAMVideoControl) sourceObject; + } + catch + { + // some camera drivers may not support IAMVideoControl interface + } + + // get type of sample grabber + type = Type.GetTypeFromCLSID( Clsid.SampleGrabber ); + if ( type == null ) + throw new ApplicationException( "Failed creating sample grabber" ); + + // create sample grabber used for video capture + videoGrabberObject = Activator.CreateInstance( type ); + videoSampleGrabber = (ISampleGrabber) videoGrabberObject; + videoGrabberBase = (IBaseFilter) videoGrabberObject; + // create sample grabber used for snapshot capture + snapshotGrabberObject = Activator.CreateInstance( type ); + snapshotSampleGrabber = (ISampleGrabber) snapshotGrabberObject; + snapshotGrabberBase = (IBaseFilter) snapshotGrabberObject; + + // add source and grabber filters to graph + graph.AddFilter( sourceBase, "source" ); + graph.AddFilter( videoGrabberBase, "grabber_video" ); + graph.AddFilter( snapshotGrabberBase, "grabber_snapshot" ); + + // set media type + AMMediaType mediaType = new AMMediaType( ); + mediaType.MajorType = MediaType.Video; + mediaType.SubType = MediaSubType.RGB24; + + videoSampleGrabber.SetMediaType( mediaType ); + snapshotSampleGrabber.SetMediaType( mediaType ); + + // get crossbar object to to allows configuring pins of capture card + captureGraph.FindInterface( FindDirection.UpstreamOnly, Guid.Empty, sourceBase, typeof( IAMCrossbar ).GUID, out crossbarObject ); + if ( crossbarObject != null ) + { + crossbar = (IAMCrossbar) crossbarObject; + } + isCrossbarAvailable = ( crossbar != null ); + crossbarVideoInputs = ColletCrossbarVideoInputs( crossbar ); + + if ( videoControl != null ) + { + // find Still Image output pin of the vedio device + captureGraph.FindPin( sourceObject, PinDirection.Output, + PinCategory.StillImage, MediaType.Video, false, 0, out pinStillImage ); + // check if it support trigger mode + if ( pinStillImage != null ) + { + VideoControlFlags caps; + videoControl.GetCaps( pinStillImage, out caps ); + isSapshotSupported = ( ( caps & VideoControlFlags.ExternalTriggerEnable ) != 0 ); + } + } + + // configure video sample grabber + videoSampleGrabber.SetBufferSamples( false ); + videoSampleGrabber.SetOneShot( false ); + videoSampleGrabber.SetCallback( videoGrabber, 1 ); + + // configure snapshot sample grabber + snapshotSampleGrabber.SetBufferSamples( true ); + snapshotSampleGrabber.SetOneShot( false ); + snapshotSampleGrabber.SetCallback( snapshotGrabber, 1 ); + + // configure pins + GetPinCapabilitiesAndConfigureSizeAndRate( captureGraph, sourceBase, + PinCategory.Capture, videoResolution, ref videoCapabilities ); + if ( isSapshotSupported ) + { + GetPinCapabilitiesAndConfigureSizeAndRate( captureGraph, sourceBase, + PinCategory.StillImage, snapshotResolution, ref snapshotCapabilities ); + } + else + { + snapshotCapabilities = new VideoCapabilities[0]; + } + + // put video/snapshot capabilities into cache + lock ( cacheVideoCapabilities ) + { + if ( ( videoCapabilities != null ) && ( !cacheVideoCapabilities.ContainsKey( deviceMoniker ) ) ) + { + cacheVideoCapabilities.Add( deviceMoniker, videoCapabilities ); + } + } + lock ( cacheSnapshotCapabilities ) + { + if ( ( snapshotCapabilities != null ) && ( !cacheSnapshotCapabilities.ContainsKey( deviceMoniker ) ) ) + { + cacheSnapshotCapabilities.Add( deviceMoniker, snapshotCapabilities ); + } + } + + if ( runGraph ) + { + // render capture pin + captureGraph.RenderStream( PinCategory.Capture, MediaType.Video, sourceBase, null, videoGrabberBase ); + + if ( videoSampleGrabber.GetConnectedMediaType( mediaType ) == 0 ) + { + VideoInfoHeader vih = (VideoInfoHeader) Marshal.PtrToStructure( mediaType.FormatPtr, typeof( VideoInfoHeader ) ); + + videoGrabber.Width = vih.BmiHeader.Width; + videoGrabber.Height = vih.BmiHeader.Height; + + mediaType.Dispose( ); + } + + if ( ( isSapshotSupported ) && ( provideSnapshots ) ) + { + // render snapshot pin + captureGraph.RenderStream( PinCategory.StillImage, MediaType.Video, sourceBase, null, snapshotGrabberBase ); + + if ( snapshotSampleGrabber.GetConnectedMediaType( mediaType ) == 0 ) + { + VideoInfoHeader vih = (VideoInfoHeader) Marshal.PtrToStructure( mediaType.FormatPtr, typeof( VideoInfoHeader ) ); + + snapshotGrabber.Width = vih.BmiHeader.Width; + snapshotGrabber.Height = vih.BmiHeader.Height; + + mediaType.Dispose( ); + } + } + + // get media control + mediaControl = (IMediaControl) graphObject; + + // get media events' interface + mediaEvent = (IMediaEventEx) graphObject; + IntPtr p1, p2; + DsEvCode code; + + // run + mediaControl.Run( ); + + if ( ( isSapshotSupported ) && ( provideSnapshots ) ) + { + startTime = DateTime.Now; + videoControl.SetMode( pinStillImage, VideoControlFlags.ExternalTriggerEnable ); + } + + do + { + if ( mediaEvent != null ) + { + if ( mediaEvent.GetEvent( out code, out p1, out p2, 0 ) >= 0 ) + { + mediaEvent.FreeEventParams( code, p1, p2 ); + + if ( code == DsEvCode.DeviceLost ) + { + reasonToStop = ReasonToFinishPlaying.DeviceLost; + break; + } + } + } + + if ( needToSetVideoInput ) + { + needToSetVideoInput = false; + // set/check current input type of a video card (frame grabber) + if ( isCrossbarAvailable.Value ) + { + SetCurrentCrossbarInput( crossbar, crossbarVideoInput ); + crossbarVideoInput = GetCurrentCrossbarInput( crossbar ); + } + } + + if ( needToSimulateTrigger ) + { + needToSimulateTrigger = false; + + if ( ( isSapshotSupported ) && ( provideSnapshots ) ) + { + videoControl.SetMode( pinStillImage, VideoControlFlags.Trigger ); + } + } + + if ( needToDisplayPropertyPage ) + { + needToDisplayPropertyPage = false; + DisplayPropertyPage( parentWindowForPropertyPage, sourceObject ); + + if ( crossbar != null ) + { + crossbarVideoInput = GetCurrentCrossbarInput( crossbar ); + } + } + + if ( needToDisplayCrossBarPropertyPage ) + { + needToDisplayCrossBarPropertyPage = false; + + if ( crossbar != null ) + { + DisplayPropertyPage( parentWindowForPropertyPage, crossbar ); + crossbarVideoInput = GetCurrentCrossbarInput( crossbar ); + } + } + } + while ( !stopEvent.WaitOne( 100, false ) ); + + mediaControl.Stop( ); + } + } + catch ( Exception exception ) + { + // provide information to clients + if ( VideoSourceError != null ) + { + VideoSourceError( this, new VideoSourceErrorEventArgs( exception.Message ) ); + } + } + finally + { + // release all objects + captureGraph = null; + graph = null; + sourceBase = null; + mediaControl = null; + videoControl = null; + mediaEvent = null; + pinStillImage = null; + crossbar = null; + + videoGrabberBase = null; + snapshotGrabberBase = null; + videoSampleGrabber = null; + snapshotSampleGrabber = null; + + if ( graphObject != null ) + { + Marshal.ReleaseComObject( graphObject ); + graphObject = null; + } + if ( sourceObject != null ) + { + Marshal.ReleaseComObject( sourceObject ); + sourceObject = null; + } + if ( videoGrabberObject != null ) + { + Marshal.ReleaseComObject( videoGrabberObject ); + videoGrabberObject = null; + } + if ( snapshotGrabberObject != null ) + { + Marshal.ReleaseComObject( snapshotGrabberObject ); + snapshotGrabberObject = null; + } + if ( captureGraphObject != null ) + { + Marshal.ReleaseComObject( captureGraphObject ); + captureGraphObject = null; + } + if ( crossbarObject != null ) + { + Marshal.ReleaseComObject( crossbarObject ); + crossbarObject = null; + } + } + + if ( PlayingFinished != null ) + { + PlayingFinished( this, reasonToStop ); + } + } + + // Set resolution for the specified stream configuration + private void SetResolution( IAMStreamConfig streamConfig, VideoCapabilities resolution ) + { + if ( resolution == null ) + { + return; + } + + // iterate through device's capabilities to find mediaType for desired resolution + int capabilitiesCount = 0, capabilitySize = 0; + AMMediaType newMediaType = null; + VideoStreamConfigCaps caps = new VideoStreamConfigCaps( ); + + streamConfig.GetNumberOfCapabilities( out capabilitiesCount, out capabilitySize ); + + for ( int i = 0; i < capabilitiesCount; i++ ) + { + try + { + VideoCapabilities vc = new VideoCapabilities( streamConfig, i ); + + if ( resolution == vc ) + { + if ( streamConfig.GetStreamCaps( i, out newMediaType, caps ) == 0 ) + { + break; + } + } + } + catch + { + } + } + + // set the new format + if ( newMediaType != null ) + { + streamConfig.SetFormat( newMediaType ); + newMediaType.Dispose( ); + } + } + + // Configure specified pin and collect its capabilities if required + private void GetPinCapabilitiesAndConfigureSizeAndRate( ICaptureGraphBuilder2 graphBuilder, IBaseFilter baseFilter, + Guid pinCategory, VideoCapabilities resolutionToSet, ref VideoCapabilities[] capabilities ) + { + object streamConfigObject; + graphBuilder.FindInterface( pinCategory, MediaType.Video, baseFilter, typeof( IAMStreamConfig ).GUID, out streamConfigObject ); + + if ( streamConfigObject != null ) + { + IAMStreamConfig streamConfig = null; + + try + { + streamConfig = (IAMStreamConfig) streamConfigObject; + } + catch ( InvalidCastException ) + { + } + + if ( streamConfig != null ) + { + if ( capabilities == null ) + { + try + { + // get all video capabilities + capabilities = AForge.Video.DirectShow.VideoCapabilities.FromStreamConfig( streamConfig ); + } + catch + { + } + } + + // check if it is required to change capture settings + if ( resolutionToSet != null ) + { + SetResolution( streamConfig, resolutionToSet ); + } + } + + Marshal.ReleaseComObject( streamConfigObject ); + } + + // if failed resolving capabilities, then just create empty capabilities array, + // so we don't try again + if ( capabilities == null ) + { + capabilities = new VideoCapabilities[0]; + } + } + + // Display property page for the specified object + private void DisplayPropertyPage( IntPtr parentWindow, object sourceObject ) + { + try + { + // retrieve ISpecifyPropertyPages interface of the device + ISpecifyPropertyPages pPropPages = (ISpecifyPropertyPages) sourceObject; + + // get property pages from the property bag + CAUUID caGUID; + pPropPages.GetPages( out caGUID ); + + // get filter info + FilterInfo filterInfo = new FilterInfo( deviceMoniker ); + + // create and display the OlePropertyFrame + Win32.OleCreatePropertyFrame( parentWindow, 0, 0, filterInfo.Name, 1, ref sourceObject, caGUID.cElems, caGUID.pElems, 0, 0, IntPtr.Zero ); + + // release COM objects + Marshal.FreeCoTaskMem( caGUID.pElems ); + } + catch + { + } + } + + // Collect all video inputs of the specified crossbar + private VideoInput[] ColletCrossbarVideoInputs( IAMCrossbar crossbar ) + { + lock ( cacheCrossbarVideoInputs ) + { + if ( cacheCrossbarVideoInputs.ContainsKey( deviceMoniker ) ) + { + return cacheCrossbarVideoInputs[deviceMoniker]; + } + + List videoInputsList = new List( ); + + if ( crossbar != null ) + { + int inPinsCount, outPinsCount; + + // gen number of pins in the crossbar + if ( crossbar.get_PinCounts( out outPinsCount, out inPinsCount ) == 0 ) + { + // collect all video inputs + for ( int i = 0; i < inPinsCount; i++ ) + { + int pinIndexRelated; + PhysicalConnectorType type; + + if ( crossbar.get_CrossbarPinInfo( true, i, out pinIndexRelated, out type ) != 0 ) + continue; + + if ( type < PhysicalConnectorType.AudioTuner ) + { + videoInputsList.Add( new VideoInput( i, type ) ); + } + } + } + } + + VideoInput[] videoInputs = new VideoInput[videoInputsList.Count]; + videoInputsList.CopyTo( videoInputs ); + + cacheCrossbarVideoInputs.Add( deviceMoniker, videoInputs ); + + return videoInputs; + } + } + + // Get type of input connected to video output of the crossbar + private VideoInput GetCurrentCrossbarInput( IAMCrossbar crossbar ) + { + VideoInput videoInput = VideoInput.Default; + + int inPinsCount, outPinsCount; + + // gen number of pins in the crossbar + if ( crossbar.get_PinCounts( out outPinsCount, out inPinsCount ) == 0 ) + { + int videoOutputPinIndex = -1; + int pinIndexRelated; + PhysicalConnectorType type; + + // find index of the video output pin + for ( int i = 0; i < outPinsCount; i++ ) + { + if ( crossbar.get_CrossbarPinInfo( false, i, out pinIndexRelated, out type ) != 0 ) + continue; + + if ( type == PhysicalConnectorType.VideoDecoder ) + { + videoOutputPinIndex = i; + break; + } + } + + if ( videoOutputPinIndex != -1 ) + { + int videoInputPinIndex; + + // get index of the input pin connected to the output + if ( crossbar.get_IsRoutedTo( videoOutputPinIndex, out videoInputPinIndex ) == 0 ) + { + PhysicalConnectorType inputType; + + crossbar.get_CrossbarPinInfo( true, videoInputPinIndex, out pinIndexRelated, out inputType ); + + videoInput = new VideoInput( videoInputPinIndex, inputType ); + } + } + } + + return videoInput; + } + + // Set type of input connected to video output of the crossbar + private void SetCurrentCrossbarInput( IAMCrossbar crossbar, VideoInput videoInput ) + { + if ( videoInput.Type != PhysicalConnectorType.Default ) + { + int inPinsCount, outPinsCount; + + // gen number of pins in the crossbar + if ( crossbar.get_PinCounts( out outPinsCount, out inPinsCount ) == 0 ) + { + int videoOutputPinIndex = -1; + int videoInputPinIndex = -1; + int pinIndexRelated; + PhysicalConnectorType type; + + // find index of the video output pin + for ( int i = 0; i < outPinsCount; i++ ) + { + if ( crossbar.get_CrossbarPinInfo( false, i, out pinIndexRelated, out type ) != 0 ) + continue; + + if ( type == PhysicalConnectorType.VideoDecoder ) + { + videoOutputPinIndex = i; + break; + } + } + + // find index of the required input pin + for ( int i = 0; i < inPinsCount; i++ ) + { + if ( crossbar.get_CrossbarPinInfo( true, i, out pinIndexRelated, out type ) != 0 ) + continue; + + if ( ( type == videoInput.Type ) && ( i == videoInput.Index ) ) + { + videoInputPinIndex = i; + break; + } + } + + // try connecting pins + if ( ( videoInputPinIndex != -1 ) && ( videoOutputPinIndex != -1 ) && + ( crossbar.CanRoute( videoOutputPinIndex, videoInputPinIndex ) == 0 ) ) + { + crossbar.Route( videoOutputPinIndex, videoInputPinIndex ); + } + } + } + } + + /// + /// Notifies clients about new frame. + /// + /// + /// New frame's image. + /// + private void OnNewFrame( Bitmap image ) + { + framesReceived++; + bytesReceived += image.Width * image.Height * ( Bitmap.GetPixelFormatSize( image.PixelFormat ) >> 3 ); + + if ( ( !stopEvent.WaitOne( 0, false ) ) && ( NewFrame != null ) ) + NewFrame( this, new NewFrameEventArgs( image ) ); + } + + /// + /// Notifies clients about new snapshot frame. + /// + /// + /// New snapshot's image. + /// + private void OnSnapshotFrame( Bitmap image ) + { + TimeSpan timeSinceStarted = DateTime.Now - startTime; + + // TODO: need to find better way to ignore the first snapshot, which is sent + // automatically (or better disable it) + if ( timeSinceStarted.TotalSeconds >= 4 ) + { + if ( ( !stopEvent.WaitOne( 0, false ) ) && ( SnapshotFrame != null ) ) + SnapshotFrame( this, new NewFrameEventArgs( image ) ); + } + } + + // + // Video grabber + // + private class Grabber : ISampleGrabberCB + { + private VideoCaptureDevice parent; + private bool snapshotMode; + private int width, height; + + // Width property + public int Width + { + get { return width; } + set { width = value; } + } + // Height property + public int Height + { + get { return height; } + set { height = value; } + } + + // Constructor + public Grabber( VideoCaptureDevice parent, bool snapshotMode ) + { + this.parent = parent; + this.snapshotMode = snapshotMode; + } + + // Callback to receive samples + public int SampleCB( double sampleTime, IntPtr sample ) + { + return 0; + } + + // Callback method that receives a pointer to the sample buffer + public int BufferCB( double sampleTime, IntPtr buffer, int bufferLen ) + { + if ( parent.NewFrame != null ) + { + // create new image + System.Drawing.Bitmap image = new Bitmap( width, height, PixelFormat.Format24bppRgb ); + + // lock bitmap data + BitmapData imageData = image.LockBits( + new Rectangle( 0, 0, width, height ), + ImageLockMode.ReadWrite, + PixelFormat.Format24bppRgb ); + + // copy image data + int srcStride = imageData.Stride; + int dstStride = imageData.Stride; + + unsafe + { + byte* dst = (byte*) imageData.Scan0.ToPointer( ) + dstStride * ( height - 1 ); + byte* src = (byte*) buffer.ToPointer( ); + + for ( int y = 0; y < height; y++ ) + { + Win32.memcpy( dst, src, srcStride ); + dst -= dstStride; + src += srcStride; + } + } + + // unlock bitmap data + image.UnlockBits( imageData ); + + // notify parent + if ( snapshotMode ) + { + parent.OnSnapshotFrame( image ); + } + else + { + parent.OnNewFrame( image ); + } + + // release the image + image.Dispose( ); + } + + return 0; + } + } + } +} diff --git a/Sources/Accord.Video.DirectShow/VideoCaptureDeviceForm.Designer.cs b/Sources/Accord.Video.DirectShow/VideoCaptureDeviceForm.Designer.cs new file mode 100644 index 0000000000..febcdd7cd --- /dev/null +++ b/Sources/Accord.Video.DirectShow/VideoCaptureDeviceForm.Designer.cs @@ -0,0 +1,219 @@ +namespace AForge.Video.DirectShow +{ + partial class VideoCaptureDeviceForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.cancelButton = new System.Windows.Forms.Button(); + this.okButton = new System.Windows.Forms.Button(); + this.devicesCombo = new System.Windows.Forms.ComboBox(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.videoInputsCombo = new System.Windows.Forms.ComboBox(); + this.label3 = new System.Windows.Forms.Label(); + this.snapshotsLabel = new System.Windows.Forms.Label(); + this.snapshotResolutionsCombo = new System.Windows.Forms.ComboBox(); + this.videoResolutionsCombo = new System.Windows.Forms.ComboBox(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.pictureBox = new System.Windows.Forms.PictureBox(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).BeginInit(); + this.SuspendLayout(); + // + // cancelButton + // + this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.cancelButton.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.cancelButton.Location = new System.Drawing.Point(358, 292); + this.cancelButton.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.cancelButton.Name = "cancelButton"; + this.cancelButton.Size = new System.Drawing.Size(112, 35); + this.cancelButton.TabIndex = 11; + this.cancelButton.Text = "Cancel"; + // + // okButton + // + this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK; + this.okButton.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.okButton.Location = new System.Drawing.Point(224, 292); + this.okButton.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.okButton.Name = "okButton"; + this.okButton.Size = new System.Drawing.Size(112, 35); + this.okButton.TabIndex = 10; + this.okButton.Text = "OK"; + this.okButton.Click += new System.EventHandler(this.okButton_Click); + // + // devicesCombo + // + this.devicesCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.devicesCombo.FormattingEnabled = true; + this.devicesCombo.Location = new System.Drawing.Point(150, 62); + this.devicesCombo.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.devicesCombo.Name = "devicesCombo"; + this.devicesCombo.Size = new System.Drawing.Size(486, 28); + this.devicesCombo.TabIndex = 9; + this.devicesCombo.SelectedIndexChanged += new System.EventHandler(this.devicesCombo_SelectedIndexChanged); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.videoInputsCombo); + this.groupBox1.Controls.Add(this.label3); + this.groupBox1.Controls.Add(this.snapshotsLabel); + this.groupBox1.Controls.Add(this.snapshotResolutionsCombo); + this.groupBox1.Controls.Add(this.videoResolutionsCombo); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.pictureBox); + this.groupBox1.Controls.Add(this.devicesCombo); + this.groupBox1.Location = new System.Drawing.Point(15, 15); + this.groupBox1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox1.Size = new System.Drawing.Size(660, 254); + this.groupBox1.TabIndex = 12; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Video capture device settings"; + // + // videoInputsCombo + // + this.videoInputsCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.videoInputsCombo.FormattingEnabled = true; + this.videoInputsCombo.Location = new System.Drawing.Point(150, 200); + this.videoInputsCombo.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.videoInputsCombo.Name = "videoInputsCombo"; + this.videoInputsCombo.Size = new System.Drawing.Size(223, 28); + this.videoInputsCombo.TabIndex = 17; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(150, 177); + this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(93, 20); + this.label3.TabIndex = 16; + this.label3.Text = "Video input:"; + // + // snapshotsLabel + // + this.snapshotsLabel.AutoSize = true; + this.snapshotsLabel.Location = new System.Drawing.Point(412, 108); + this.snapshotsLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.snapshotsLabel.Name = "snapshotsLabel"; + this.snapshotsLabel.Size = new System.Drawing.Size(152, 20); + this.snapshotsLabel.TabIndex = 15; + this.snapshotsLabel.Text = "Snapshot resoluton:"; + // + // snapshotResolutionsCombo + // + this.snapshotResolutionsCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.snapshotResolutionsCombo.FormattingEnabled = true; + this.snapshotResolutionsCombo.Location = new System.Drawing.Point(412, 131); + this.snapshotResolutionsCombo.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.snapshotResolutionsCombo.Name = "snapshotResolutionsCombo"; + this.snapshotResolutionsCombo.Size = new System.Drawing.Size(223, 28); + this.snapshotResolutionsCombo.TabIndex = 14; + // + // videoResolutionsCombo + // + this.videoResolutionsCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.videoResolutionsCombo.FormattingEnabled = true; + this.videoResolutionsCombo.Location = new System.Drawing.Point(150, 131); + this.videoResolutionsCombo.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.videoResolutionsCombo.Name = "videoResolutionsCombo"; + this.videoResolutionsCombo.Size = new System.Drawing.Size(223, 28); + this.videoResolutionsCombo.TabIndex = 13; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(150, 108); + this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(124, 20); + this.label2.TabIndex = 12; + this.label2.Text = "Video resoluton:"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(150, 38); + this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(103, 20); + this.label1.TabIndex = 11; + this.label1.Text = "Video device:"; + // + // pictureBox + // + this.pictureBox.Image = global::Accord.Video.DirectShow.Properties.Resources.camera; + this.pictureBox.Location = new System.Drawing.Point(30, 43); + this.pictureBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.pictureBox.Name = "pictureBox"; + this.pictureBox.Size = new System.Drawing.Size(96, 98); + this.pictureBox.TabIndex = 10; + this.pictureBox.TabStop = false; + // + // VideoCaptureDeviceForm + // + this.AcceptButton = this.okButton; + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.CancelButton = this.cancelButton; + this.ClientSize = new System.Drawing.Size(693, 340); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.cancelButton); + this.Controls.Add(this.okButton); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; + this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.Name = "VideoCaptureDeviceForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Open local video capture device"; + this.Load += new System.EventHandler(this.VideoCaptureDeviceForm_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button cancelButton; + private System.Windows.Forms.Button okButton; + private System.Windows.Forms.ComboBox devicesCombo; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.PictureBox pictureBox; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label snapshotsLabel; + private System.Windows.Forms.ComboBox snapshotResolutionsCombo; + private System.Windows.Forms.ComboBox videoResolutionsCombo; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.ComboBox videoInputsCombo; + private System.Windows.Forms.Label label3; + } +} \ No newline at end of file diff --git a/Sources/Accord.Video.DirectShow/VideoCaptureDeviceForm.cs b/Sources/Accord.Video.DirectShow/VideoCaptureDeviceForm.cs new file mode 100644 index 0000000000..395978d00 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/VideoCaptureDeviceForm.cs @@ -0,0 +1,354 @@ +// AForge Direct Show Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2009-2013 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +using AForge.Video.DirectShow; + +namespace AForge.Video.DirectShow +{ + /// + /// Local video device selection form. + /// + /// + /// The form provides a standard way of selecting local video + /// device (USB web camera, capture board, etc. - anything supporting DirectShow + /// interface), which can be reused across applications. It allows selecting video + /// device, video size and snapshots size (if device supports snapshots and + /// user needs them). + /// + /// + /// + /// + public partial class VideoCaptureDeviceForm : Form + { + // collection of available video devices + private FilterInfoCollection videoDevices; + // selected video device + private VideoCaptureDevice videoDevice; + + // supported capabilities of video and snapshots + private Dictionary videoCapabilitiesDictionary = new Dictionary(); + private Dictionary snapshotCapabilitiesDictionary = new Dictionary(); + + // available video inputs + private VideoInput[] availableVideoInputs = null; + + // flag telling if user wants to configure snapshots as well + private bool configureSnapshots = false; + + /// + /// Specifies if snapshot configuration should be done or not. + /// + /// + /// The property specifies if the dialog form should + /// allow configuration of snapshot sizes (if selected video source supports + /// snapshots). If the property is set to , then + /// the form will provide additional combo box enumerating supported + /// snapshot sizes. Otherwise the combo boxes will be hidden. + /// + /// + /// If the property is set to and selected + /// device supports snapshots, then + /// property of the configured device is set to + /// . + /// + /// Default value of the property is set to . + /// + /// + public bool ConfigureSnapshots + { + get { return configureSnapshots; } + set + { + configureSnapshots = value; + snapshotsLabel.Visible = value; + snapshotResolutionsCombo.Visible = value; + } + } + + /// + /// Provides configured video device. + /// + /// + /// The property provides configured video device if user confirmed + /// the dialog using "OK" button. If user canceled the dialog, the property is + /// set to . + /// + public VideoCaptureDevice VideoDevice + { + get { return videoDevice; } + } + + private string videoDeviceMoniker = string.Empty; + private Size captureSize = new Size(0, 0); + private Size snapshotSize = new Size(0, 0); + private VideoInput videoInput = VideoInput.Default; + + /// + /// Moniker string of the selected video device. + /// + /// + /// The property allows to get moniker string of the selected device + /// on form completion or set video device which should be selected by default on + /// form loading. + /// + public string VideoDeviceMoniker + { + get { return videoDeviceMoniker; } + set { videoDeviceMoniker = value; } + } + + /// + /// Video frame size of the selected device. + /// + /// + /// The property allows to get video size of the selected device + /// on form completion or set the size to be selected by default on form loading. + /// + /// + public Size CaptureSize + { + get { return captureSize; } + set { captureSize = value; } + } + + /// + /// Snapshot frame size of the selected device. + /// + /// + /// The property allows to get snapshot size of the selected device + /// on form completion or set the size to be selected by default on form loading + /// (if property is set ). + /// + public Size SnapshotSize + { + get { return snapshotSize; } + set { snapshotSize = value; } + } + + /// + /// Video input to use with video capture card. + /// + /// + /// The property allows to get video input of the selected device + /// on form completion or set it to be selected by default on form loading. + /// + public VideoInput VideoInput + { + get { return videoInput; } + set { videoInput = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public VideoCaptureDeviceForm() + { + InitializeComponent(); + ConfigureSnapshots = false; + + // show device list + try + { + // enumerate video devices + videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice); + + if (videoDevices.Count == 0) + throw new ApplicationException(); + + // add all devices to combo + foreach (FilterInfo device in videoDevices) + { + devicesCombo.Items.Add(device.Name); + } + } + catch (ApplicationException) + { + devicesCombo.Items.Add("No local capture devices"); + devicesCombo.Enabled = false; + okButton.Enabled = false; + } + } + + // On form loaded + private void VideoCaptureDeviceForm_Load(object sender, EventArgs e) + { + int selectedCameraIndex = 0; + + for (int i = 0; i < videoDevices.Count; i++) + { + if (videoDeviceMoniker == videoDevices[i].MonikerString) + { + selectedCameraIndex = i; + break; + } + } + + devicesCombo.SelectedIndex = selectedCameraIndex; + } + + // Ok button clicked + private void okButton_Click(object sender, EventArgs e) + { + videoDeviceMoniker = videoDevice.Source; + + // set video size + if (videoCapabilitiesDictionary.Count != 0) + { + VideoCapabilities caps = videoCapabilitiesDictionary[(string)videoResolutionsCombo.SelectedItem]; + + videoDevice.VideoResolution = caps; + captureSize = caps.FrameSize; + } + + if (configureSnapshots) + { + // set snapshots size + if (snapshotCapabilitiesDictionary.Count != 0) + { + VideoCapabilities caps = snapshotCapabilitiesDictionary[(string)snapshotResolutionsCombo.SelectedItem]; + + videoDevice.ProvideSnapshots = true; + videoDevice.SnapshotResolution = caps; + + snapshotSize = caps.FrameSize; + } + } + + if (availableVideoInputs.Length != 0) + { + videoInput = availableVideoInputs[videoInputsCombo.SelectedIndex]; + videoDevice.CrossbarVideoInput = videoInput; + } + } + + // New video device is selected + private void devicesCombo_SelectedIndexChanged(object sender, EventArgs e) + { + if (videoDevices.Count != 0) + { + videoDevice = new VideoCaptureDevice(videoDevices[devicesCombo.SelectedIndex].MonikerString); + EnumeratedSupportedFrameSizes(videoDevice); + } + } + + // Collect supported video and snapshot sizes + private void EnumeratedSupportedFrameSizes(VideoCaptureDevice videoDevice) + { + this.Cursor = Cursors.WaitCursor; + + videoResolutionsCombo.Items.Clear(); + snapshotResolutionsCombo.Items.Clear(); + videoInputsCombo.Items.Clear(); + + videoCapabilitiesDictionary.Clear(); + snapshotCapabilitiesDictionary.Clear(); + + try + { + // collect video capabilities + VideoCapabilities[] videoCapabilities = videoDevice.VideoCapabilities; + int videoResolutionIndex = 0; + + foreach (VideoCapabilities capabilty in videoCapabilities) + { + string item = string.Format( + "{0} x {1}", capabilty.FrameSize.Width, capabilty.FrameSize.Height); + + if (!videoResolutionsCombo.Items.Contains(item)) + { + if (captureSize == capabilty.FrameSize) + { + videoResolutionIndex = videoResolutionsCombo.Items.Count; + } + + videoResolutionsCombo.Items.Add(item); + } + + if (!videoCapabilitiesDictionary.ContainsKey(item)) + { + videoCapabilitiesDictionary.Add(item, capabilty); + } + } + + if (videoCapabilities.Length == 0) + { + videoResolutionsCombo.Items.Add("Not supported"); + } + + videoResolutionsCombo.SelectedIndex = videoResolutionIndex; + + + if (configureSnapshots) + { + // collect snapshot capabilities + VideoCapabilities[] snapshotCapabilities = videoDevice.SnapshotCapabilities; + int snapshotResolutionIndex = 0; + + foreach (VideoCapabilities capabilty in snapshotCapabilities) + { + string item = string.Format( + "{0} x {1}", capabilty.FrameSize.Width, capabilty.FrameSize.Height); + + if (!snapshotResolutionsCombo.Items.Contains(item)) + { + if (snapshotSize == capabilty.FrameSize) + { + snapshotResolutionIndex = snapshotResolutionsCombo.Items.Count; + } + + snapshotResolutionsCombo.Items.Add(item); + snapshotCapabilitiesDictionary.Add(item, capabilty); + } + } + + if (snapshotCapabilities.Length == 0) + { + snapshotResolutionsCombo.Items.Add("Not supported"); + } + + snapshotResolutionsCombo.SelectedIndex = snapshotResolutionIndex; + } + + // get video inputs + availableVideoInputs = videoDevice.AvailableCrossbarVideoInputs; + int videoInputIndex = 0; + + foreach (VideoInput input in availableVideoInputs) + { + string item = string.Format("{0}: {1}", input.Index, input.Type); + + if ((input.Index == videoInput.Index) && (input.Type == videoInput.Type)) + { + videoInputIndex = videoInputsCombo.Items.Count; + } + + videoInputsCombo.Items.Add(item); + } + + if (availableVideoInputs.Length == 0) + { + videoInputsCombo.Items.Add("Not supported"); + } + + videoInputsCombo.SelectedIndex = videoInputIndex; + } + finally + { + this.Cursor = Cursors.Default; + } + } + } +} diff --git a/Sources/Accord.Video.DirectShow/VideoCaptureDeviceForm.resx b/Sources/Accord.Video.DirectShow/VideoCaptureDeviceForm.resx new file mode 100644 index 0000000000..c7e0d4bdf --- /dev/null +++ b/Sources/Accord.Video.DirectShow/VideoCaptureDeviceForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Sources/Accord.Video.DirectShow/VideoInput.cs b/Sources/Accord.Video.DirectShow/VideoInput.cs new file mode 100644 index 0000000000..d88b64d30 --- /dev/null +++ b/Sources/Accord.Video.DirectShow/VideoInput.cs @@ -0,0 +1,47 @@ +// AForge Direct Show Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2009-2012 +// contacts@aforgenet.com +// + +namespace AForge.Video.DirectShow +{ + using System; + + /// + /// Video input of a capture board. + /// + /// + /// The class is used to describe video input of devices like video capture boards, + /// which usually provide several inputs. + /// + /// + public class VideoInput + { + /// + /// Index of the video input. + /// + public readonly int Index; + + /// + /// Type of the video input. + /// + public readonly PhysicalConnectorType Type; + + internal VideoInput( int index, PhysicalConnectorType type ) + { + Index = index; + Type = type; + } + + /// + /// Default video input. Used to specify that it should not be changed. + /// + public static VideoInput Default + { + get { return new VideoInput( -1, PhysicalConnectorType.Default ); } + } + } +} diff --git a/Sources/Accord.Video.Kinect/Accord.Video.Kinect.cd b/Sources/Accord.Video.Kinect/Accord.Video.Kinect.cd new file mode 100644 index 0000000000..088c6eeac --- /dev/null +++ b/Sources/Accord.Video.Kinect/Accord.Video.Kinect.cd @@ -0,0 +1,157 @@ + + + + + + + + Kinect.cs + + + + + Kinect.cs + + + + + AEIRAAAAALBMQAAQAVBAAAAAEACAAAgIIAACMACAABA= + Kinect.cs + + + + + + + + + AAEAAQYCArQCEAgAEBAAQCQAAAAhAAAAIQAAAIAABAA= + KinectDepthCamera.cs + + + + + + + + + + + KinectNative.cs + + + + + KinectNative.cs + + + + + KinectNative.cs + + + + + KinectNative.cs + + + + + KinectNative.cs + + + + + KinectNative.cs + + + + + KinectNative.cs + + + + + KinectNative.cs + + + + + KinectNative.cs + + + + + KinectNative.cs + + + + + KinectNative.cs + + + + + gCEAACACQomAIAYgBAwmQAIAEkgBAIIAAAAAgmAAEgg= + KinectNative.cs + + + + + + + + AAEAAQYCArACEAgAEBAAQCQAAAAhAQAAIQAAAIAABAA= + KinectVideoCamera.cs + + + + + + + AACAAIAAAAAAAgAAAAAAAAAAAAAAAQAAAAAAADAAAAA= + KinectNative.cs + + + + + + AAAAAAAAAAAAAAAAAgAAAAAAAAgAAAAAAAAAAAAEAAA= + KinectNative.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAgAAAAQA= + KinectVideoCamera.cs + + + + \ No newline at end of file diff --git a/Sources/Accord.Audio.Formats/Accord.Audio.Formats.csproj b/Sources/Accord.Video.Kinect/Accord.Video.Kinect.csproj similarity index 51% rename from Sources/Accord.Audio.Formats/Accord.Audio.Formats.csproj rename to Sources/Accord.Video.Kinect/Accord.Video.Kinect.csproj index b1b920d99..ecea7623a 100644 --- a/Sources/Accord.Audio.Formats/Accord.Audio.Formats.csproj +++ b/Sources/Accord.Video.Kinect/Accord.Video.Kinect.csproj @@ -1,125 +1,123 @@ - - - - {EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF} - Accord.Audio.Formats - Accord.Audio.Formats - - Debug - AnyCPU - AnyCPU - Library - Properties - True - 4 - True - true - Accord.snk - 3.5 - False - true - ..\Accord.NET.ruleset - false - true - 4096 - true - pdbonly - true - true - true - GlobalSuppressions.cs - - - v4.5 - bin\Debug\ - Full - False - False - True - DEBUG;TRACE - ..\..\Debug\ - - - ..\..\Release\net35 - TRACE;CODE_ANALYSIS;NET35 - v3.5 - ..\..\Release\net35\Accord.Audio.Formats.XML - ..\..\Release\net35\Accord.Audio.Formats.dll.CodeAnalysisLog.xml - - - ..\..\Release\net40 - TRACE;CODE_ANALYSIS;NET40 - v4.0 - ..\..\Release\net40\Accord.Audio.Formats.XML - ..\..\Release\net40\Accord.Audio.Formats.dll.CodeAnalysisLog.xml - - - ..\..\Release\net45 - TRACE;CODE_ANALYSIS;NET45 - v4.5 - ..\..\Release\net45\Accord.Audio.Formats.XML - ..\..\Release\net45\Accord.Audio.Formats.dll.CodeAnalysisLog.xml - - - - - ..\..\Externals\AForge.NET\AForge.Math.dll - False - - - ..\..\Externals\SharpDX\net40\SharpDX.dll - ..\..\Externals\SharpDX\net20\SharpDX.dll - False - - - - 3.5 - - - - - - - Properties\VersionInfo.cs - - - - - - - - - - - - {E7B65F08-82F1-438F-847A-2AAC2BEC9AC0} - Accord.Audio - False - - - {F718E9A8-DB62-4785-8C49-4333A60D256A} - Accord.Math - - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - + + + + {9DA8E727-4038-4E6B-90BD-853730FDFA49} + Accord.Video.Kinect + Accord.Video.Kinect + Debug + AnyCPU + AnyCPU + Library + Properties + True + 4 + True + true + Accord.snk + 3.5 + False + true + ..\Accord.NET.ruleset + false + true + 4096 + true + pdbonly + true + + + v4.5 + Full + False + False + True + DEBUG;TRACE + $(SolutionDir)..\Debug\ + + + $(SolutionDir)..\Release\net35 + TRACE;CODE_ANALYSIS;NET35 + v3.5 + true + $(SolutionDir)..\Release\net35\Accord.Video.Kinect.XML + $(SolutionDir)..\Release\net35\Accord.Video.Kinect.dll.CodeAnalysisLog.xml + + + $(SolutionDir)..\Release\net40 + TRACE;CODE_ANALYSIS;NET40 + v4.0 + $(SolutionDir)..\Release\net40\Accord.Video.Kinect.XML + $(SolutionDir)..\Release\net40\Accord.Video.Kinect.dll.CodeAnalysisLog.xml + AnyCPU + + + $(SolutionDir)..\Release\net45 + TRACE;CODE_ANALYSIS;NET45 + v4.5 + $(SolutionDir)..\Release\net45\Accord.Video.Kinect.XML + $(SolutionDir)..\Release\net45\Accord.Video.Kinect.dll.CodeAnalysisLog.xml + + + + + + + + + + Properties\VersionInfo.cs + + + + + + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + {a177a90c-8207-466a-af70-f2b8452a42ac} + Accord.Core + + + {4959a83d-f78f-439e-80a5-41583eceaac6} + Accord.Imaging + + + {809725dc-6502-4732-a51c-deb7fea12975} + Accord.Video + + + + + + + \ No newline at end of file diff --git a/Sources/Accord.Video.Kinect/Accord.snk b/Sources/Accord.Video.Kinect/Accord.snk new file mode 100644 index 0000000000..ed97b4edd Binary files /dev/null and b/Sources/Accord.Video.Kinect/Accord.snk differ diff --git a/Sources/Accord.Video.Kinect/Images/kinect.jpg b/Sources/Accord.Video.Kinect/Images/kinect.jpg new file mode 100644 index 0000000000..e95b9ebd5 Binary files /dev/null and b/Sources/Accord.Video.Kinect/Images/kinect.jpg differ diff --git a/Sources/Accord.Video.Kinect/Kinect.cs b/Sources/Accord.Video.Kinect/Kinect.cs new file mode 100644 index 0000000000..6a472f2c7 --- /dev/null +++ b/Sources/Accord.Video.Kinect/Kinect.cs @@ -0,0 +1,453 @@ +// AForge Kinect Video Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Video.Kinect +{ + using System; + using System.Collections.Generic; + using System.Threading; + using AForge; + + /// + /// The class provides access to Microsoft's Xbox Kinect + /// controller. + /// + /// + /// The class allows to manipulate Kinec device by changing its LED color, setting motor's + /// tilt value and accessing its camera. See and + /// classes, which provide access to actual video. + /// + /// + /// + /// In order to run correctly the class requires freenect.dll library + /// to be put into solution's output folder. This can be found within the AForge.NET framework's + /// distribution in Externals folder. + /// + /// Sample usage: + /// + /// // get Kinect device + /// Kinect kinectDevice = Kinect.GetDevice( 0 ); + /// // change LED color + /// kinectDevice.LedColor = LedColorOption.Yellow; + /// // set motor tilt angle to -10 degrees + /// kinectDevice.SetMotorTilt( -10 ); + /// // get video camera + /// KinectVideoCamera videoCamera = kinectDevice.GetVideoCamera( ); + /// + /// // see example for video camera also + /// + /// + /// + public class Kinect : IDisposable + { + internal delegate void DeviceFailureHandler(); + + private class DeviceContext + { + public IntPtr Device; + public int ReferenceCounter; + public bool DeviceFailed; + public KinectNative.TiltState TiltState; + + private object sync = new object(); + private List failureHanlders = new List(); + + public DeviceContext(IntPtr device) + { + Device = device; + ReferenceCounter = 0; + DeviceFailed = false; + } + + public void AddFailureHandler(DeviceFailureHandler handler) + { + lock (sync) + { + failureHanlders.Add(handler); + } + } + + public void FireFailureHandlers() + { + lock (sync) + { + foreach (DeviceFailureHandler handler in failureHanlders) + { + handler(); + } + failureHanlders.Clear(); + } + } + } + + // dictionary of all opened devices + private static Dictionary openDevices = new Dictionary(); + + // thread for Kinect status updates and an event for stopping it + private static Thread updateStatusThread; + //private static Thread watchDogThread; + private static ManualResetEvent stopEvent; + + // pointer to the freekinect's opened device + private IntPtr rawDevice; + // ID of the opened device + private readonly int deviceID; + + // dummy object to lock for synchronization + private object sync = new object(); + + /// + /// ID of the opened Kinect device. + /// + /// + public int DeviceID + { + get { return deviceID; } + } + + internal IntPtr RawDevice + { + get { return rawDevice; } + } + + /// + /// Number of Kinect devices available in the system. + /// + public static int DeviceCount + { + get { return KinectNative.freenect_num_devices(KinectNative.Context); } + } + + /// + /// Get initialized instance of the Kinect device. + /// + /// + /// ID of the Kinect device to get instance of, [0, ), + /// + /// Returns initialized Kinect device. Use method + /// when the device is no longer required. + /// + /// There is no Kinect device with specified ID connected to the system. + /// Failed connecting to the Kinect device specified ID. + /// + public static Kinect GetDevice(int deviceID) + { + if ((deviceID < 0) || (deviceID >= DeviceCount)) + { + throw new ArgumentException("There is no Kinect device with specified ID connected to the system."); + } + + bool needToStartStatusThread = false; + Kinect kinect = null; + + lock (openDevices) + { + needToStartStatusThread = (openDevices.Count == 0); + + // check if the device is open already + if (!openDevices.ContainsKey(deviceID)) + { + IntPtr devicePointer = IntPtr.Zero; + + // connect to Kinect device witht the specified ID + if (KinectNative.freenect_open_device(KinectNative.Context, ref devicePointer, deviceID) != 0) + { + throw new ConnectionFailedException("Failed connecting to the Kinect device with ID: " + deviceID); + } + + openDevices.Add(deviceID, new DeviceContext(devicePointer)); + } + + openDevices[deviceID].ReferenceCounter++; + kinect = new Kinect(openDevices[deviceID].Device, deviceID); + } + + if (needToStartStatusThread) + { + StartStatusThread(); + } + + return kinect; + } + + // Private constructor to make sure class instance can be obtained through GetDevice() only + private Kinect(IntPtr rawDevice, int deviceID) + { + this.rawDevice = rawDevice; + this.deviceID = deviceID; + KinectNative.OnError += new KinectNative.ErrorHandler(Kinect_OnError); + } + + /// + /// Object finalizer/destructor makes sure unmanaged resource are freed if user did not call . + /// + ~Kinect() + { + Dispose(false); + } + + /// + /// Dispose device freeing all associated unmanaged resources. + /// + /// + public void Dispose() + { + Dispose(true); + + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + lock (sync) + { + if (rawDevice == IntPtr.Zero) + return; + + bool needToStopStatusThread = false; + + lock (openDevices) + { + // decrease reference counter and check if we need to close the device + if (--openDevices[deviceID].ReferenceCounter == 0) + { + if (!openDevices[deviceID].DeviceFailed) + { + KinectNative.freenect_close_device(rawDevice); + } + openDevices.Remove(deviceID); + } + + needToStopStatusThread = (openDevices.Count == 0); + } + + rawDevice = IntPtr.Zero; + + if (needToStopStatusThread) + { + StopStatusThread(); + } + } + + KinectNative.OnError -= new KinectNative.ErrorHandler(Kinect_OnError); + } + + // Check if the device was disposed or not + private void CheckDevice() + { + if (rawDevice == IntPtr.Zero) + { + throw new ObjectDisposedException("Cannot access already disposed object."); + } + } + + /// + /// Set color of Kinect's LED. + /// + /// + /// LED color to set. + /// + /// Some error occurred with the device. Check error message. + /// + public void SetLedColor(LedColorOption ledColor) + { + lock (sync) + { + CheckDevice(); + + int result = KinectNative.freenect_set_led(rawDevice, ledColor); + + if (result != 0) + { + throw new DeviceErrorException("Failed setting LED color to " + ledColor + ". Error code: " + result); + } + } + } + + /// + /// Set motor's tilt value. + /// + /// + /// Tilt value to set, [-31, 30] degrees. + /// + /// Motor tilt has to be in the [-31, 31] range. + /// Some error occurred with the device. Check error message. + /// + public void SetMotorTilt(int angle) + { + lock (sync) + { + CheckDevice(); + + // check if value is in valid range + if ((angle < -31) || (angle > 31)) + { + throw new ArgumentOutOfRangeException("angle", "Motor tilt has to be in the [-31, 31] range."); + } + + int result = KinectNative.freenect_set_tilt_degs(rawDevice, angle); + if (result != 0) + { + throw new DeviceErrorException("Failed setting motor tilt. Error code: " + result); + } + } + } + + private const double CountsPerGravity = 819.0; + private const double Gravity = 9.80665; + + /// + /// Get accelerometer values for 3 axes. + /// + /// + /// X axis value on the accelerometer. + /// Y axis value on the accelerometer. + /// Z axis value on the accelerometer. + /// + /// Units of all 3 values are m/s2. The g value used + /// for calculations is taken as 9.80665 m/s2. + /// + public void GetAccelerometerValues(out double x, out double y, out double z) + { + KinectNative.TiltState tiltState = new KinectNative.TiltState(); + + lock (sync) + { + CheckDevice(); + tiltState = openDevices[deviceID].TiltState; + } + + x = (double)tiltState.AccelerometerX / CountsPerGravity * Gravity; + y = (double)tiltState.AccelerometerY / CountsPerGravity * Gravity; + z = (double)tiltState.AccelerometerZ / CountsPerGravity * Gravity; + } + + /// + /// Get Kinect's video camera. + /// + /// + /// Returns Kinect's video camera. + /// + /// The method simply creates instance of the class + /// by calling its appropriate constructor. Use method + /// to start the video then. + /// + public KinectVideoCamera GetVideoCamera() + { + return new KinectVideoCamera(deviceID); + } + + /// + /// Get Kinect's depth camera. + /// + /// + /// Returns Kinect's depth camera. + /// + /// The method simply creates instance of the class + /// by calling its appropriate constructor. Use method + /// to start the video then. + /// + public KinectDepthCamera GetDepthCamera() + { + return new KinectDepthCamera(deviceID); + } + + #region Kinect Status Thread + + private static object statusThreadSync = new object(); + + // Start status thread to handle freenect's events + private static void StartStatusThread() + { + lock (statusThreadSync) + { + stopEvent = new ManualResetEvent(false); + updateStatusThread = new Thread(KinectStatusThread); + updateStatusThread.IsBackground = true; + updateStatusThread.Start(); + } + } + + // Stop the status thread + private static void StopStatusThread() + { + lock (statusThreadSync) + { + stopEvent.Set(); + if (!updateStatusThread.Join(2000)) + { + updateStatusThread.Abort(); + } + + stopEvent.Close(); + updateStatusThread = null; + stopEvent = null; + } + } + + // Kinect's status thread to process freenect's events + private static void KinectStatusThread() + { + while (!stopEvent.WaitOne(100, false)) + { + lock (openDevices) + { + if (openDevices.Count != 0) + { + // update the status for each open device + foreach (DeviceContext deviceContext in openDevices.Values) + { + if (deviceContext.DeviceFailed) + { + continue; + } + + if (KinectNative.freenect_update_tilt_state(deviceContext.Device) < 0) + { + deviceContext.DeviceFailed = true; + deviceContext.FireFailureHandlers(); + } + else + { + // get updated device status + IntPtr ptr = KinectNative.freenect_get_tilt_state(deviceContext.Device); + deviceContext.TiltState = (KinectNative.TiltState) + System.Runtime.InteropServices.Marshal.PtrToStructure(ptr, typeof(KinectNative.TiltState)); + } + } + } + } + + // let the kinect library handle any pending stuff on the usb stream + KinectNative.freenect_process_events_timeout0(KinectNative.Context); + } + } + + private void Kinect_OnError(IntPtr device) + { + if (device == rawDevice) + { + Console.WriteLine("Error is detected in device : " + deviceID); + } + } + + internal bool IsDeviceFailed(int deviceID) + { + return ((openDevices.ContainsKey(deviceID)) && (openDevices[deviceID].DeviceFailed)); + } + + internal void AddFailureHandler(int deviceID, DeviceFailureHandler handler) + { + if (openDevices.ContainsKey(deviceID)) + { + openDevices[deviceID].AddFailureHandler(handler); + } + } + #endregion + } +} diff --git a/Sources/Accord.Video.Kinect/KinectDepthCamera.cs b/Sources/Accord.Video.Kinect/KinectDepthCamera.cs new file mode 100644 index 0000000000..649fa9570 --- /dev/null +++ b/Sources/Accord.Video.Kinect/KinectDepthCamera.cs @@ -0,0 +1,543 @@ +// AForge Kinect Video Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Video.Kinect +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + using System.Runtime.InteropServices; + + using AForge; + using AForge.Video; + + /// + /// Video source for Microsoft Kinect's depth sensor. + /// + /// + /// The video source captures depth data from Microsoft Kinect + /// depth sensor, which is aimed originally as a gaming device for XBox 360 platform. + /// + /// Prior to using the class, make sure you've installed Kinect's drivers + /// as described on Open Kinect + /// project's page. + /// + /// In order to run correctly the class requires freenect.dll library + /// to be put into solution's output folder. This can be found within the AForge.NET framework's + /// distribution in Externals folder. + /// + /// Sample usage: + /// + /// // create video source + /// KinectDepthCamera videoSource = new KinectDepthCamera( 0 ); + /// // set NewFrame event handler + /// videoSource.NewFrame += new NewFrameEventHandler( video_NewFrame ); + /// // start the video source + /// videoSource.Start( ); + /// // ... + /// + /// private void video_NewFrame( object sender, NewFrameEventArgs eventArgs ) + /// { + /// // get new frame + /// Bitmap bitmap = eventArgs.Frame; + /// // process the frame + /// } + /// + /// + /// + public class KinectDepthCamera : IVideoSource + { + // Kinect's device ID + private int deviceID; + // received frames count + private int framesReceived; + // recieved byte count + private long bytesReceived; + // specifies of original 11 bit depth images (as 16 bit) should be provided and 24 bit color image + private bool provideOriginalDepthImage = false; + private ushort[] gamma = new ushort[2048]; + // camera resolution to set + private CameraResolution resolution = CameraResolution.Medium; + // list of currently running cameras + private static List runningCameras = new List( ); + + // dummy object to lock for synchronization + private object sync = new object( ); + + /// + /// New frame event. + /// + /// + /// Notifies clients about new available frames from the video source. + /// + /// Since video source may have multiple clients, each client is responsible for + /// making a copy (cloning) of the passed video frame, because the video source disposes its + /// own original copy after notifying of clients. + /// + /// + public event NewFrameEventHandler NewFrame; + + /// + /// Video source error event. + /// + /// + /// This event is used to notify clients about any type of errors occurred in + /// video source object, for example internal exceptions. + /// + public event VideoSourceErrorEventHandler VideoSourceError; + + /// + /// Video playing finished event. + /// + /// + /// This event is used to notify clients that the video playing has finished. + /// + /// + public event PlayingFinishedEventHandler PlayingFinished; + + /// + /// Provide original depth image or colored depth map. + /// + /// + /// The property specifies if the video source should provide original data + /// provided by Kinect's depth sensor or provide colored depth map. If the property is set to + /// , then the video source will provide 16 bpp grayscale images, where + /// 11 least significant bits represent data provided by the sensor. If the property is + /// set to , then the video source will provide 24 bpp color images, + /// which represents depth map. In this case depth is encoded by color gradient: + /// white->red->yellow->green->cyan->blue->black. So colors which are closer to white represent + /// objects which are closer to the Kinect sensor, but colors which are closer to black represent + /// objects which are further away from Kinect. + /// + /// The property must be set before running the video source to take effect. + /// + /// Default value is set to . + /// + /// + private bool ProvideOriginalDepthImage + { + get { return provideOriginalDepthImage; } + set { provideOriginalDepthImage = value; } + } + + /// + /// Resolution of depth sensor to set. + /// + /// + /// The property must be set before running the video source to take effect. + /// + /// Default value of the property is set to . + /// + /// + public CameraResolution Resolution + { + get { return resolution; } + set { resolution = value; } + } + + /// + /// A string identifying the video source. + /// + /// + public virtual string Source + { + get { return "Kinect:DepthCamera:" + deviceID; } + } + + /// + /// State of the video source. + /// + /// + /// Current state of video source object - running or not. + /// + public bool IsRunning + { + get + { + lock ( sync ) + { + return ( device != null ); + } + } + } + + /// + /// Received bytes count. + /// + /// + /// Number of bytes the video source provided from the moment of the last + /// access to the property. + /// + /// + public long BytesReceived + { + get + { + long bytes = bytesReceived; + bytesReceived = 0; + return bytes; + } + } + + /// + /// Received frames count. + /// + /// + /// Number of frames the video source provided from the moment of the last + /// access to the property. + /// + /// + public int FramesReceived + { + get + { + int frames = framesReceived; + framesReceived = 0; + return frames; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Kinect's device ID (index) to connect to. + /// + public KinectDepthCamera( int deviceID ) : this( deviceID, CameraResolution.Medium, false ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Kinect's device ID (index) to connect to. + /// Resolution of depth sensor to set. + /// + public KinectDepthCamera( int deviceID, CameraResolution resolution ) : this( deviceID, resolution, false ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Kinect's device ID (index) to connect to. + /// Resolution of depth sensor to set. + /// Provide original depth image or colored depth map + /// (see property). + /// + public KinectDepthCamera( int deviceID, CameraResolution resolution, bool provideOriginalDepthImage ) + { + this.deviceID = deviceID; + this.resolution = resolution; + this.provideOriginalDepthImage = provideOriginalDepthImage; + + // initialize gamma values (as shown in the original Kinect samples) + for ( int i = 0; i < 2048; i++ ) + { + double value = i / 2048.0; + value = Math.Pow( value, 3.0 ); + gamma[i] = (ushort) ( value * 36.0 * 256.0 ); + } + } + + private Kinect device = null; + private IntPtr imageBuffer = IntPtr.Zero; + private KinectNative.BitmapInfoHeader depthModeInfo; + + /// + /// Start video source. + /// + /// + /// Starts video source and returns execution to caller. Video camera will be started + /// and will provide new video frames through the event. + /// + /// The specified resolution is not supported for the selected + /// mode of the Kinect depth sensor. + /// Could not connect to Kinect's depth sensor. + /// Another connection to the specified depth sensor is already running. + /// + public void Start( ) + { + lock ( sync ) + { + lock ( runningCameras ) + { + if ( device == null ) + { + bool success = false; + + try + { + if ( runningCameras.Contains( deviceID ) ) + { + throw new DeviceBusyException( "Another connection to the specified depth camera is already running." ); + } + + device = Kinect.GetDevice( deviceID ); + + // find depth format parameters + depthModeInfo = KinectNative.freenect_find_depth_mode( resolution, KinectNative.DepthCameraFormat.Format11Bit ); + + if ( depthModeInfo.IsValid == 0 ) + { + throw new ArgumentException( "The specified resolution is not supported for the selected mode of the Kinect depth camera." ); + } + + // set depth format + if ( KinectNative.freenect_set_depth_mode( device.RawDevice, depthModeInfo ) != 0 ) + { + throw new VideoException( "Could not switch to the specified depth format." ); + } + + // allocate video buffer and provide it freenect + imageBuffer = Marshal.AllocHGlobal( (int) depthModeInfo.Bytes ); + KinectNative.freenect_set_depth_buffer( device.RawDevice, imageBuffer ); + + // set video callback + videoCallback = new KinectNative.FreenectDepthDataCallback( HandleDataReceived ); + KinectNative.freenect_set_depth_callback( device.RawDevice, videoCallback ); + + // start the camera + if ( KinectNative.freenect_start_depth( device.RawDevice ) != 0 ) + { + throw new ConnectionFailedException( "Could not start depth stream." ); + } + + success = true; + runningCameras.Add( deviceID ); + + device.AddFailureHandler( deviceID, Stop ); + } + finally + { + if ( !success ) + { + if ( device != null ) + { + device.Dispose( ); + device = null; + } + + if ( imageBuffer != IntPtr.Zero ) + { + Marshal.FreeHGlobal( imageBuffer ); + imageBuffer = IntPtr.Zero; + } + } + } + } + } + } + } + + /// + /// Signal video source to stop its work. + /// + /// + /// Calling this method is equivalent to calling + /// for Kinect video camera. + /// + public void SignalToStop( ) + { + Stop( ); + } + + /// + /// Wait for video source has stopped. + /// + /// + /// Calling this method is equivalent to calling + /// for Kinect video camera. + /// + public void WaitForStop( ) + { + Stop( ); + } + + /// + /// Stop video source. + /// + /// + /// The method stop the video source, so it no longer provides new video frames + /// and does not consume any resources. + /// + /// + public void Stop( ) + { + lock ( sync ) + { + lock ( runningCameras ) + { + if ( device != null ) + { + bool deviceFailed = device.IsDeviceFailed( deviceID ); + + if ( !deviceFailed ) + { + KinectNative.freenect_stop_depth( device.RawDevice ); + } + + device.Dispose( ); + device = null; + runningCameras.Remove( deviceID ); + + if ( PlayingFinished != null ) + { + PlayingFinished( this, ( !deviceFailed ) ? + ReasonToFinishPlaying.StoppedByUser : ReasonToFinishPlaying.DeviceLost ); + } + } + + if ( imageBuffer != IntPtr.Zero ) + { + Marshal.FreeHGlobal( imageBuffer ); + imageBuffer = IntPtr.Zero; + } + + videoCallback = null; + } + } + } + + // New video data event handler + private KinectNative.FreenectDepthDataCallback videoCallback = null; + + private void HandleDataReceived( IntPtr device, IntPtr depthData, UInt32 timestamp ) + { + int width = depthModeInfo.Width; + int height = depthModeInfo.Height; + + Bitmap image = null; + BitmapData data = null; + + try + { + image = new Bitmap( width, height, ( !provideOriginalDepthImage ) ? + PixelFormat.Format24bppRgb : PixelFormat.Format16bppGrayScale ); + + data = image.LockBits( new Rectangle( 0, 0, width, height ), + ImageLockMode.ReadWrite, image.PixelFormat ); + + unsafe + { + ushort* src = (ushort*) imageBuffer.ToPointer( ); + + if ( !provideOriginalDepthImage ) + { + // color the depth image into white->red->yellow->green->cyan->blue->black gradient + byte* dst = (byte*) data.Scan0.ToPointer( ); + int offset = data.Stride - width * 3; + byte red, green, blue; + + for ( int y = 0; y < height; y++ ) + { + for ( int x = 0; x < width; x++, src++, dst += 3 ) + { + ushort pval = gamma[*src]; + ushort lb = (ushort) ( pval & 0xff ); + + switch ( pval >> 8 ) + { + case 0: // white to red + red = 255; + green = (byte) ( 255 - lb ); + blue = (byte) ( 255 - lb ); + break; + case 1: // red to yellow + red = 255; + green = (byte) lb; + blue = 0; + break; + case 2: // yellow to green + red = (byte) ( 255 - lb ); + green = 255; + blue = 0; + break; + case 3: // green to cyan + red = 0; + green = 255; + blue = (byte) lb; + break; + case 4: // cyan to blue + red = 0; + green = (byte) ( 255 - lb ); + blue = 255; + break; + case 5: // blue to black + red = 0; + green = 0; + blue = (byte) ( 255 - lb ); + break; + default: + red = green = blue = 0; + break; + } + + dst[2] = red; + dst[1] = green; + dst[0] = blue; + } + dst += offset; + } + } + else + { + // copy original depth image + ushort* dst = (ushort*) data.Scan0.ToPointer( ); + int offset = ( data.Stride >> 1 ) - width; + + if ( offset == 0 ) + { + SystemTools.CopyUnmanagedMemory( (byte*) dst, (byte*) src, height * width * 2 ); + } + else + { + for ( int y = 0; y < height; y++ ) + { + SystemTools.CopyUnmanagedMemory( (byte*) dst, (byte*) src, width * 2 ); + + dst += width; + src += width; + dst += offset; + } + } + } + } + + image.UnlockBits( data ); + framesReceived++; + bytesReceived += (int) depthModeInfo.Bytes; + } + catch ( Exception ex ) + { + if ( VideoSourceError != null ) + { + VideoSourceError( this, new VideoSourceErrorEventArgs( ex.Message ) ); + } + + if ( image != null ) + { + if ( data != null ) + { + image.UnlockBits( data ); + } + image.Dispose( ); + image = null; + } + } + + if ( image != null ) + { + if ( NewFrame != null ) + { + NewFrame( this, new NewFrameEventArgs( image ) ); + } + image.Dispose( ); + } + } + } +} diff --git a/Sources/Accord.Video.Kinect/KinectNative.cs b/Sources/Accord.Video.Kinect/KinectNative.cs new file mode 100644 index 0000000000..2dc5b7f8d --- /dev/null +++ b/Sources/Accord.Video.Kinect/KinectNative.cs @@ -0,0 +1,387 @@ +// AForge Kinect Video Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Video.Kinect +{ + using System; + using System.Runtime.InteropServices; + + /// + /// Kinect's LED color options. + /// + /// + public enum LedColorOption + { + /// + /// The LED is off. + /// + /// + Off = 0, + + /// + /// The LED is on and has green color. + /// + /// + Green = 1, + + /// + /// The LED is on and has red color. + /// + /// + Red = 2, + + /// + /// The LED is on and has yellow color. + /// + /// + Yellow = 3, + + /// + /// The LED is blinking with green color. + /// + /// + BlinkGreen = 4, + + /// + /// The LED is blinking from red to yellow color. + /// + /// + BlinkRedYellow = 6 + } + + /// + /// Kinect's resolutions of video and depth cameras. + /// + public enum CameraResolution + { + /// + /// Low resolution. + /// + Low, + + /// + /// Medium resolution. + /// + Medium, + + /// + /// Hight resolution. + /// + High, + } + + internal static class KinectNative + { + // dummy object for synchronization + // Note: it was noticed that if freenect_stop_depth() is called together with freenect_process_events() + // in different threads, then the call may hang sometimes for about 30 seconds or more making impression + // of dead lock or so. Putting lock around those calls seems to help. + private static object sync = new object(); + + // Logging levels + public enum LogLevelOptions + { + Fatal = 0, + Error, + Warning, + Notice, + Info, + Debug, + Spew, + Flood, + } + + // Video camera data formats + public enum VideoCameraFormat + { + RGB = 0, + Bayer = 1, + IR8Bit = 2, + IR10Bit = 3, + IR10BitPacked = 4 + } + + // Depth camera data formats + public enum DepthCameraFormat + { + Format11Bit = 0, + Format10Bit = 1, + FormatPacked11Bit = 2, + FormatPacked10Bit = 3 + } + + // Different states the tilt motor can be in operation + public enum TiltStatusOption + { + Stopped = 0x00, + AtLimit = 0x01, + Moving = 0x04 + } + + // Device tilt state values. This holds stuff like accelerometer and tilt status. + public struct TiltState + { + public Int16 AccelerometerX; + public Int16 AccelerometerY; + public Int16 AccelerometerZ; + public SByte TiltAngle; + public TiltStatusOption TiltStatus; + + public TiltState(Int16 x, Int16 y, Int16 z) + { + AccelerometerX = x; + AccelerometerY = y; + AccelerometerZ = z; + TiltAngle = 0; + TiltStatus = TiltStatusOption.Stopped; + } + } + + // Information about certain picture format + [StructLayout(LayoutKind.Sequential)] + public struct BitmapInfoHeader + { + public uint Reserved; + public uint Resolution; + public uint Format; + // Total buffer size in bytes to hold a single frame of data + public uint Bytes; + // Width of the frame, in pixels + public short Width; + // Height of the frame, in pixels + public short Height; + // Number of bits of information needed for each pixel + public byte DataBitsPerPixel; + // Number of bits of padding for alignment used for each pixel + public byte PaddingBitsPerPixel; + // Approximate expected frame rate + public byte Framerate; + // If 0, this structure is invalid and does not describe a supported mode. Otherwise, it is valid. + public byte IsValid; + } + + // BSD like time value + [StructLayout(LayoutKind.Sequential)] + internal class timeval + { + public int sec; + public int usec; + } + + // Native callback for freenect library logging + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void FreenectLogCallback(IntPtr device, LogLevelOptions logLevel, string message); + + // Native callback for depth data + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void FreenectDepthDataCallback(IntPtr device, IntPtr depthData, UInt32 timestamp); + + // Native callback for video image data + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void FreenectVideoDataCallback(IntPtr device, IntPtr imageData, UInt32 timestamp); + + [DllImport("freenect", CallingConvention = CallingConvention.Cdecl)] + public static extern int freenect_init(ref IntPtr context, IntPtr freenectUSBContext); + + [DllImport("freenect", EntryPoint = "freenect_process_events", CallingConvention = CallingConvention.Cdecl)] + private static extern int native_freenect_process_events(IntPtr context); + + public static int freenect_process_events(IntPtr context) + { + lock (sync) + { + return native_freenect_process_events(context); + } + } + + [DllImport("freenect", EntryPoint = "freenect_process_events_timeout", CallingConvention = CallingConvention.Cdecl)] + private static extern int native_freenect_process_events_timeout(IntPtr context, [In] IntPtr timeout); + + public static int freenect_process_events_timeout0(IntPtr context) + { + lock (sync) + { + return native_freenect_process_events_timeout(context, IntPtr.Zero); + } + } + + [DllImport("freenect", CallingConvention = CallingConvention.Cdecl)] + public static extern void freenect_set_log_level(IntPtr context, LogLevelOptions level); + + [DllImport("freenect", CallingConvention = CallingConvention.Cdecl)] + public static extern void freenect_set_log_callback(IntPtr context, FreenectLogCallback callback); + + [DllImport("freenect", CallingConvention = CallingConvention.Cdecl)] + public static extern int freenect_shutdown(IntPtr context); + + [DllImport("freenect", CallingConvention = CallingConvention.Cdecl)] + public static extern int freenect_num_devices(IntPtr context); + + [DllImport("freenect", CallingConvention = CallingConvention.Cdecl)] + public static extern int freenect_open_device(IntPtr context, ref IntPtr device, int index); + + [DllImport("freenect", CallingConvention = CallingConvention.Cdecl)] + public static extern int freenect_close_device(IntPtr device); + + [DllImport("freenect", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Struct)] + public static extern BitmapInfoHeader freenect_find_video_mode(CameraResolution resolution, VideoCameraFormat videoFormat); + + [DllImport("freenect", CallingConvention = CallingConvention.Cdecl)] + public static extern int freenect_set_video_mode(IntPtr device, [In, MarshalAs(UnmanagedType.Struct)] BitmapInfoHeader infoHeader); + + [DllImport("freenect", CallingConvention = CallingConvention.Cdecl)] + public static extern int freenect_set_video_buffer(IntPtr device, IntPtr buffer); + + [DllImport("freenect", CallingConvention = CallingConvention.Cdecl)] + public static extern void freenect_set_video_callback(IntPtr device, FreenectVideoDataCallback callback); + + [DllImport("freenect", EntryPoint = "freenect_start_video", CallingConvention = CallingConvention.Cdecl)] + private static extern int native_freenect_start_video(IntPtr device); + + public static int freenect_start_video(IntPtr device) + { + lock (sync) + { + return native_freenect_start_video(device); + } + } + + [DllImport("freenect", EntryPoint = "freenect_stop_video", CallingConvention = CallingConvention.Cdecl)] + private static extern int native_freenect_stop_video(IntPtr device); + + public static int freenect_stop_video(IntPtr device) + { + lock (sync) + { + return native_freenect_stop_video(device); + } + } + + [DllImport("freenect", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Struct)] + public static extern BitmapInfoHeader freenect_find_depth_mode(CameraResolution resolution, DepthCameraFormat depthFormat); + + [DllImport("freenect", CallingConvention = CallingConvention.Cdecl)] + public static extern int freenect_set_depth_mode(IntPtr device, BitmapInfoHeader infoHeader); + + [DllImport("freenect", CallingConvention = CallingConvention.Cdecl)] + public static extern int freenect_set_depth_buffer(IntPtr device, IntPtr buffer); + + [DllImport("freenect", CallingConvention = CallingConvention.Cdecl)] + public static extern void freenect_set_depth_callback(IntPtr device, FreenectDepthDataCallback callback); + + [DllImport("freenect", EntryPoint = "freenect_start_depth", CallingConvention = CallingConvention.Cdecl)] + private static extern int native_freenect_start_depth(IntPtr device); + + public static int freenect_start_depth(IntPtr device) + { + lock (sync) + { + return native_freenect_start_depth(device); + } + } + + [DllImport("freenect", EntryPoint = "freenect_stop_depth", CallingConvention = CallingConvention.Cdecl)] + private static extern int native_freenect_stop_depth(IntPtr device); + + public static int freenect_stop_depth(IntPtr device) + { + lock (sync) + { + return native_freenect_stop_depth(device); + } + } + + [DllImport("freenect", CallingConvention = CallingConvention.Cdecl)] + public static extern int freenect_set_led(IntPtr device, LedColorOption option); + + [DllImport("freenect", CallingConvention = CallingConvention.Cdecl)] + public static extern int freenect_update_tilt_state(IntPtr device); + + [DllImport("freenect", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr freenect_get_tilt_state(IntPtr device); + + [DllImport("freenect", CallingConvention = CallingConvention.Cdecl)] + public static extern int freenect_set_tilt_degs(IntPtr device, double angle); + + // feenect context + private static IntPtr freenectContext = IntPtr.Zero; + // logging calback + private static FreenectLogCallback logCallback = new FreenectLogCallback(LogCallback); + + // Gets a freenect context to work with. + public static IntPtr Context + { + get + { + if (freenectContext == IntPtr.Zero) + { + KinectNative.InitializeContext(); + } + + return freenectContext; + } + } + + // Initializes the freenect context + private static void InitializeContext() + { + try + { + int result = freenect_init(ref KinectNative.freenectContext, IntPtr.Zero); + + if (result != 0) + { + throw new ApplicationException("Could not initialize freenect context. Error Code:" + result); + } + + // set callback for logging + KinectNative.freenect_set_log_level(freenectContext, LogLevelOptions.Error); + KinectNative.freenect_set_log_callback(freenectContext, logCallback); + } + catch (DllNotFoundException ex) + { + throw new DllNotFoundException("Freenect.dll library could not be found. Please " + + "make sure that you also have installed LibUSB for your Kinect device.", ex); + } + + } + + // Shuts down the context and closes any open devices + public static void ShutdownContext() + { + if (freenectContext != IntPtr.Zero) + { + // shutdown context + int result = KinectNative.freenect_shutdown(freenectContext); + if (result != 0) + { + throw new ApplicationException("Could not shutdown freenect context. Error Code:" + result); + } + + // Dispose pointer + KinectNative.freenectContext = IntPtr.Zero; + } + } + + // Logging callback + internal static void LogCallback(IntPtr device, LogLevelOptions logLevel, string message) + { + Console.WriteLine(string.Format("[{0}] : {1}", logLevel, message)); + + if (OnError != null) + { + OnError(device); + } + } + + public delegate void ErrorHandler(IntPtr device); + public static event ErrorHandler OnError; + } +} diff --git a/Sources/Accord.Video.Kinect/KinectVideoCamera.cs b/Sources/Accord.Video.Kinect/KinectVideoCamera.cs new file mode 100644 index 0000000000..7d7c482b9 --- /dev/null +++ b/Sources/Accord.Video.Kinect/KinectVideoCamera.cs @@ -0,0 +1,523 @@ +// AForge Kinect Video Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Video.Kinect +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Imaging; + using System.Runtime.InteropServices; + + using AForge; + using AForge.Imaging; + using AForge.Video; + + /// + /// Enumeration of video camera modes for the . + /// + public enum VideoCameraMode + { + /// + /// 24 bit per pixel RGB mode. + /// + Color, + + /// + /// 8 bit per pixel Bayer mode. + /// + Bayer, + + /// + /// 8 bit per pixel Infra Red mode. + /// + InfraRed + } + + /// + /// Video source for Microsoft Kinect's video camera. + /// + /// + /// The video source captures video data from Microsoft Kinect + /// video camera, which is aimed originally as a gaming device for XBox 360 platform. + /// + /// Prior to using the class, make sure you've installed Kinect's drivers + /// as described on Open Kinect + /// project's page. + /// + /// In order to run correctly the class requires freenect.dll library + /// to be put into solution's output folder. This can be found within the AForge.NET framework's + /// distribution in Externals folder. + /// + /// Sample usage: + /// + /// // create video source + /// KinectVideoCamera videoSource = new KinectVideoCamera( 0 ); + /// // set NewFrame event handler + /// videoSource.NewFrame += new NewFrameEventHandler( video_NewFrame ); + /// // start the video source + /// videoSource.Start( ); + /// // ... + /// + /// private void video_NewFrame( object sender, NewFrameEventArgs eventArgs ) + /// { + /// // get new frame + /// Bitmap bitmap = eventArgs.Frame; + /// // process the frame + /// } + /// + /// + /// + public class KinectVideoCamera : IVideoSource + { + // Kinect's device ID + private int deviceID; + // received frames count + private int framesReceived; + // recieved byte count + private long bytesReceived; + // camera mode + private VideoCameraMode cameraMode = VideoCameraMode.Color; + // camera resolution to set + private CameraResolution resolution = CameraResolution.Medium; + // list of currently running cameras + private static List runningCameras = new List( ); + + // dummy object to lock for synchronization + private object sync = new object( ); + + /// + /// New frame event. + /// + /// + /// Notifies clients about new available frames from the video source. + /// + /// Since video source may have multiple clients, each client is responsible for + /// making a copy (cloning) of the passed video frame, because the video source disposes its + /// own original copy after notifying of clients. + /// + /// + public event NewFrameEventHandler NewFrame; + + /// + /// Video source error event. + /// + /// + /// This event is used to notify clients about any type of errors occurred in + /// video source object, for example internal exceptions. + /// + public event VideoSourceErrorEventHandler VideoSourceError; + + /// + /// Video playing finished event. + /// + /// + /// This event is used to notify clients that the video playing has finished. + /// + /// + public event PlayingFinishedEventHandler PlayingFinished; + + /// + /// Specifies video mode for the camera. + /// + /// + /// + /// The property must be set before running the video source to take effect. + /// + /// Default value of the property is set to . + /// + /// + public VideoCameraMode CameraMode + { + get { return cameraMode; } + set { cameraMode = value; } + } + + /// + /// Resolution of video camera to set. + /// + /// + /// The property must be set before running the video source to take effect. + /// + /// Default value of the property is set to . + /// + /// + public CameraResolution Resolution + { + get { return resolution; } + set { resolution = value; } + } + + /// + /// A string identifying the video source. + /// + /// + public virtual string Source + { + get { return "Kinect:VideoCamera:" + deviceID; } + } + + /// + /// State of the video source. + /// + /// + /// Current state of video source object - running or not. + /// + public bool IsRunning + { + get + { + lock ( sync ) + { + return ( device != null ); + } + } + } + + /// + /// Received bytes count. + /// + /// + /// Number of bytes the video source provided from the moment of the last + /// access to the property. + /// + /// + public long BytesReceived + { + get + { + long bytes = bytesReceived; + bytesReceived = 0; + return bytes; + } + } + + /// + /// Received frames count. + /// + /// + /// Number of frames the video source provided from the moment of the last + /// access to the property. + /// + /// + public int FramesReceived + { + get + { + int frames = framesReceived; + framesReceived = 0; + return frames; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Kinect's device ID (index) to connect to. + /// + public KinectVideoCamera( int deviceID ) + { + this.deviceID = deviceID; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Kinect's device ID (index) to connect to. + /// Resolution of video camera to set. + /// + public KinectVideoCamera( int deviceID, CameraResolution resolution ) + { + this.deviceID = deviceID; + this.resolution = resolution; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Kinect's device ID (index) to connect to. + /// Resolution of video camera to set. + /// Sets video camera mode. + /// + public KinectVideoCamera( int deviceID, CameraResolution resolution, VideoCameraMode cameraMode ) + { + this.deviceID = deviceID; + this.resolution = resolution; + this.cameraMode = cameraMode; + } + + private Kinect device = null; + private IntPtr imageBuffer = IntPtr.Zero; + private KinectNative.BitmapInfoHeader videoModeInfo; + + /// + /// Start video source. + /// + /// + /// Starts video source and returns execution to caller. Video camera will be started + /// and will provide new video frames through the event. + /// + /// The specified resolution is not supported for the selected + /// mode of the Kinect video camera. + /// Could not connect to Kinect's video camera. + /// Another connection to the specified video camera is already running. + /// + public void Start( ) + { + lock ( sync ) + { + lock ( runningCameras ) + { + if ( device == null ) + { + bool success = false; + + try + { + if ( runningCameras.Contains( deviceID ) ) + { + throw new DeviceBusyException( "Another connection to the specified video camera is already running." ); + } + + // get Kinect device + device = Kinect.GetDevice( deviceID ); + + KinectNative.VideoCameraFormat dataFormat = KinectNative.VideoCameraFormat.RGB; + + if ( cameraMode == VideoCameraMode.Bayer ) + { + dataFormat = KinectNative.VideoCameraFormat.Bayer; + } + else if ( cameraMode == VideoCameraMode.InfraRed ) + { + dataFormat = KinectNative.VideoCameraFormat.IR8Bit; + } + + // find video format parameters + videoModeInfo = KinectNative.freenect_find_video_mode( resolution, dataFormat ); + + if ( videoModeInfo.IsValid == 0 ) + { + throw new ArgumentException( "The specified resolution is not supported for the selected mode of the Kinect video camera." ); + } + + // set video format + if ( KinectNative.freenect_set_video_mode( device.RawDevice, videoModeInfo ) != 0 ) + { + throw new VideoException( "Could not switch to the specified video format." ); + } + + // allocate video buffer and provide it freenect + imageBuffer = Marshal.AllocHGlobal( (int) videoModeInfo.Bytes ); + KinectNative.freenect_set_video_buffer( device.RawDevice, imageBuffer ); + + // set video callback + videoCallback = new KinectNative.FreenectVideoDataCallback( HandleDataReceived ); + KinectNative.freenect_set_video_callback( device.RawDevice, videoCallback ); + + // start the camera + if ( KinectNative.freenect_start_video( device.RawDevice ) != 0 ) + { + throw new ConnectionFailedException( "Could not start video stream." ); + } + + success = true; + runningCameras.Add( deviceID ); + + device.AddFailureHandler( deviceID, Stop ); + } + finally + { + if ( !success ) + { + if ( device != null ) + { + device.Dispose( ); + device = null; + } + + if ( imageBuffer != IntPtr.Zero ) + { + Marshal.FreeHGlobal( imageBuffer ); + imageBuffer = IntPtr.Zero; + } + } + } + } + } + } + } + + /// + /// Signal video source to stop its work. + /// + /// + /// Calling this method is equivalent to calling + /// for Kinect video camera. + /// + public void SignalToStop( ) + { + Stop( ); + } + + /// + /// Wait for video source has stopped. + /// + /// + /// Calling this method is equivalent to calling + /// for Kinect video camera. + /// + public void WaitForStop( ) + { + Stop( ); + } + + /// + /// Stop video source. + /// + /// + /// The method stops the video source, so it no longer provides new video frames + /// and does not consume any resources. + /// + /// + public void Stop( ) + { + lock ( sync ) + { + lock ( runningCameras ) + { + if ( device != null ) + { + bool deviceFailed = device.IsDeviceFailed( deviceID ); + + if ( !deviceFailed ) + { + KinectNative.freenect_stop_video( device.RawDevice ); + } + + device.Dispose( ); + device = null; + runningCameras.Remove( deviceID ); + + if ( PlayingFinished != null ) + { + PlayingFinished( this, ( !deviceFailed ) ? + ReasonToFinishPlaying.StoppedByUser : ReasonToFinishPlaying.DeviceLost ); + } + } + + if ( imageBuffer != IntPtr.Zero ) + { + Marshal.FreeHGlobal( imageBuffer ); + imageBuffer = IntPtr.Zero; + } + + videoCallback = null; + } + } + } + + // New video data event handler + private KinectNative.FreenectVideoDataCallback videoCallback = null; + + private void HandleDataReceived( IntPtr device, IntPtr imageData, UInt32 timeStamp ) + { + int width = videoModeInfo.Width; + int height = videoModeInfo.Height; + + Bitmap image = null; + BitmapData data = null; + + try + { + image = ( cameraMode == VideoCameraMode.Color ) ? + new Bitmap( width, height, PixelFormat.Format24bppRgb ) : + AForge.Imaging.Image.CreateGrayscaleImage( width, height ); + + data = image.LockBits( new Rectangle( 0, 0, width, height ), + ImageLockMode.ReadWrite, image.PixelFormat ); + + unsafe + { + byte* dst = (byte*) data.Scan0.ToPointer( ); + byte* src = (byte*) imageBuffer.ToPointer( ); + + if ( cameraMode == VideoCameraMode.Color ) + { + // color RGB 24 mode + int offset = data.Stride - width * 3; + + for ( int y = 0; y < height; y++ ) + { + for ( int x = 0; x < width; x++, src += 3, dst += 3 ) + { + dst[0] = src[2]; + dst[1] = src[1]; + dst[2] = src[0]; + } + dst += offset; + } + } + else + { + // infra red mode - grayscale output + int stride = data.Stride; + + if ( stride != width ) + { + for ( int y = 0; y < height; y++ ) + { + SystemTools.CopyUnmanagedMemory( dst, src, width ); + dst += stride; + src += width; + } + } + else + { + SystemTools.CopyUnmanagedMemory( dst, src, width * height ); + } + } + } + image.UnlockBits( data ); + + framesReceived++; + bytesReceived += width * height; + } + catch ( Exception ex ) + { + if ( VideoSourceError != null ) + { + VideoSourceError( this, new VideoSourceErrorEventArgs( ex.Message ) ); + } + + if ( image != null ) + { + if ( data != null ) + { + image.UnlockBits( data ); + } + image.Dispose( ); + image = null; + } + } + + if ( image != null ) + { + if ( NewFrame != null ) + { + NewFrame( this, new NewFrameEventArgs( image ) ); + } + + image.Dispose( ); + } + } + } +} diff --git a/Sources/Accord.Video.Kinect/Properties/AssemblyInfo.cs b/Sources/Accord.Video.Kinect/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..bda31f4e4 --- /dev/null +++ b/Sources/Accord.Video.Kinect/Properties/AssemblyInfo.cs @@ -0,0 +1,13 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Accord.Video.Kinect")] +[assembly: AssemblyDescription("Accord.NET - Kinect Interface Library")] +[assembly: AssemblyConfiguration("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. +[assembly: ComVisible(false)] diff --git a/Sources/Accord.Video.VFW/AVIFileVideoSource.cs b/Sources/Accord.Video.VFW/AVIFileVideoSource.cs new file mode 100644 index 0000000000..f3f2ac3f0 --- /dev/null +++ b/Sources/Accord.Video.VFW/AVIFileVideoSource.cs @@ -0,0 +1,398 @@ +// AForge Video for Windows Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Video.VFW +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + using System.IO; + using System.Threading; + + using AForge.Video; + + /// + /// AVI file video source. + /// + /// + /// The video source reads AVI files using Video for Windows. + /// + /// Sample usage: + /// + /// // create AVI file video source + /// AVIFileVideoSource source = new AVIFileVideoSource( "some file" ); + /// // set event handlers + /// source.NewFrame += new NewFrameEventHandler( video_NewFrame ); + /// // start the video source + /// source.Start( ); + /// // ... + /// // signal to stop + /// source.SignalToStop( ); + /// + /// // New frame event handler, which is invoked on each new available video frame + /// private void video_NewFrame( object sender, NewFrameEventArgs eventArgs ) + /// { + /// // get new frame + /// Bitmap bitmap = eventArgs.Frame; + /// // process the frame + /// } + /// + /// + /// + public class AVIFileVideoSource : IVideoSource + { + // video file name + private string source; + // received frames count + private int framesReceived; + // recieved byte count + private long bytesReceived; + // frame interval in milliseconds + private int frameInterval = 0; + // get frame interval from source or use manually specified + private bool frameIntervalFromSource = true; + + private Thread thread = null; + private ManualResetEvent stopEvent = null; + + /// + /// New frame event. + /// + /// + /// Notifies clients about new available frame from video source. + /// + /// Since video source may have multiple clients, each client is responsible for + /// making a copy (cloning) of the passed video frame, because the video source disposes its + /// own original copy after notifying of clients. + /// + /// + public event NewFrameEventHandler NewFrame; + + /// + /// Video source error event. + /// + /// + /// This event is used to notify clients about any type of errors occurred in + /// video source object, for example internal exceptions. + /// + public event VideoSourceErrorEventHandler VideoSourceError; + + /// + /// Video playing finished event. + /// + /// + /// This event is used to notify clients that the video playing has finished. + /// + /// + public event PlayingFinishedEventHandler PlayingFinished; + + /// + /// Frame interval. + /// + /// + /// The property sets the interval in milliseconds between frames. If the property is + /// set to 100, then the desired frame rate will be 10 frames per second. + /// + /// Setting this property to 0 leads to no delay between video frames - frames + /// are read as fast as possible. + /// + /// Default value is set to 0. + /// + /// + public int FrameInterval + { + get { return frameInterval; } + set { frameInterval = value; } + } + + /// + /// Get frame interval from source or use manually specified. + /// + /// + /// The property specifies which frame rate to use for video playing. + /// If the property is set to , then video is played + /// with original frame rate, which is set in source AVI file. If the property is + /// set to , then custom frame rate is used, which is + /// calculated based on the manually specified frame interval. + /// + /// Default value is set to . + /// + /// + public bool FrameIntervalFromSource + { + get { return frameIntervalFromSource; } + set { frameIntervalFromSource = value; } + } + + /// + /// Video source. + /// + /// + /// Video file name to play. + /// + public virtual string Source + { + get { return source; } + set { source = value; } + } + + /// + /// Received frames count. + /// + /// + /// Number of frames the video source provided from the moment of the last + /// access to the property. + /// + /// + public int FramesReceived + { + get + { + int frames = framesReceived; + framesReceived = 0; + return frames; + } + } + + /// + /// Received bytes count. + /// + /// + /// Number of bytes the video source provided from the moment of the last + /// access to the property. + /// + /// + public long BytesReceived + { + get + { + long bytes = bytesReceived; + bytesReceived = 0; + return bytes; + } + } + + /// + /// State of the video source. + /// + /// + /// Current state of video source object - running or not. + /// + public bool IsRunning + { + get + { + if ( thread != null ) + { + // check thread status + if ( thread.Join( 0 ) == false ) + return true; + + // the thread is not running, so free resources + Free( ); + } + return false; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public AVIFileVideoSource( ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Video file name. + /// + public AVIFileVideoSource( string source ) + { + this.source = source; + } + + /// + /// Start video source. + /// + /// + /// Starts video source and return execution to caller. Video source + /// object creates background thread and notifies about new frames with the + /// help of event. + /// + /// Video source is not specified. + /// + public void Start( ) + { + if ( !IsRunning ) + { + // check source + if ( string.IsNullOrEmpty( source ) ) + throw new ArgumentException( "Video source is not specified." ); + + framesReceived = 0; + bytesReceived = 0; + + // create events + stopEvent = new ManualResetEvent( false ); + + // create and start new thread + thread = new Thread( new ThreadStart( WorkerThread ) ); + thread.Name = source; + thread.Start( ); + } + } + + /// + /// Signal video source to stop its work. + /// + /// + /// Signals video source to stop its background thread, stop to + /// provide new frames and free resources. + /// + public void SignalToStop( ) + { + // stop thread + if ( thread != null ) + { + // signal to stop + stopEvent.Set( ); + } + } + + /// + /// Wait for video source has stopped. + /// + /// + /// Waits for source stopping after it was signalled to stop using + /// method. + /// + public void WaitForStop( ) + { + if ( thread != null ) + { + // wait for thread stop + thread.Join( ); + + Free( ); + } + } + + /// + /// Stop video source. + /// + /// + /// Stops video source aborting its thread. + /// + /// Since the method aborts background thread, its usage is highly not preferred + /// and should be done only if there are no other options. The correct way of stopping camera + /// is signaling it stop and then + /// waiting for background thread's completion. + /// + /// + public void Stop( ) + { + if ( this.IsRunning ) + { + thread.Abort( ); + WaitForStop( ); + } + } + + /// + /// Free resource. + /// + /// + private void Free( ) + { + thread = null; + + // release events + stopEvent.Close( ); + stopEvent = null; + } + + /// + /// Worker thread. + /// + /// + private void WorkerThread( ) + { + ReasonToFinishPlaying reasonToStop = ReasonToFinishPlaying.StoppedByUser; + // AVI reader + AVIReader aviReader = new AVIReader( ); + + try + { + // open file + aviReader.Open( source ); + + // stop positions + int stopPosition = aviReader.Start + aviReader.Length; + + // frame interval + int interval = ( frameIntervalFromSource ) ? (int) ( 1000 / aviReader.FrameRate ) : frameInterval; + + while ( !stopEvent.WaitOne( 0, false ) ) + { + // start time + DateTime start = DateTime.Now; + + // get next frame + Bitmap bitmap = aviReader.GetNextFrame( ); + + framesReceived++; + bytesReceived += bitmap.Width * bitmap.Height * + ( Bitmap.GetPixelFormatSize( bitmap.PixelFormat ) >> 3 ); + + if ( NewFrame != null ) + NewFrame( this, new NewFrameEventArgs( bitmap ) ); + + // free image + bitmap.Dispose( ); + + // check current position + if ( aviReader.Position >= stopPosition ) + { + reasonToStop = ReasonToFinishPlaying.EndOfStreamReached; + break; + } + + // wait for a while ? + if ( interval > 0 ) + { + // get frame extract duration + TimeSpan span = DateTime.Now.Subtract( start ); + + // miliseconds to sleep + int msec = interval - (int) span.TotalMilliseconds; + + if ( ( msec > 0 ) && ( stopEvent.WaitOne( msec, false ) ) ) + break; + } + } + } + catch ( Exception exception ) + { + // provide information to clients + if ( VideoSourceError != null ) + { + VideoSourceError( this, new VideoSourceErrorEventArgs( exception.Message ) ); + } + } + + aviReader.Dispose( ); + aviReader = null; + + if ( PlayingFinished != null ) + { + PlayingFinished( this, reasonToStop ); + } + } + } +} diff --git a/Sources/Accord.Video.VFW/AVIReader.cs b/Sources/Accord.Video.VFW/AVIReader.cs new file mode 100644 index 0000000000..476c3755b --- /dev/null +++ b/Sources/Accord.Video.VFW/AVIReader.cs @@ -0,0 +1,381 @@ +// AForge Video for Windows Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Video.VFW +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + using System.Runtime.InteropServices; + using AForge; + + /// + /// AVI files reading using Video for Windows. + /// + /// + /// The class allows to read AVI files using Video for Windows API. + /// + /// Sample usage: + /// + /// // instantiate AVI reader + /// AVIReader reader = new AVIReader( ); + /// // open video file + /// reader.Open( "test.avi" ); + /// // read the video file + /// while ( reader.Position - reader.Start < reader.Length ) + /// { + /// // get next frame + /// Bitmap image = reader.GetNextFrame( ); + /// // .. process the frame somehow or display it + /// } + /// reader.Close( ); + /// + /// + /// + public class AVIReader : IDisposable + { + // AVI file + private IntPtr file; + // video stream + private IntPtr stream; + // get frame object + private IntPtr getFrame; + + // width of video frames + private int width; + // height of vide frames + private int height; + // current position in video stream + private int position; + // starting position in video stream + private int start; + // length of video stream + private int length; + // frame rate + private float rate; + // codec used for video compression + private string codec; + + // dummy object to lock for synchronization + private object sync = new object( ); + + /// + /// Width of video frames. + /// + /// + /// The property specifies the width of video frames within the opened video + /// file. + /// + public int Width + { + get { return width; } + } + + /// + /// Height of video frames. + /// + /// + /// The property specifies the height of video frames within the opened video + /// file. + /// + public int Height + { + get { return height; } + } + + /// + /// Current position in video stream. + /// + /// + /// Setting position outside of video range, will lead to reseting position to the start. + /// + public int Position + { + get { return position; } + set { position = ( ( value < start ) || ( value >= start + length ) ) ? start : value; } + } + + /// + /// Starting position of video stream. + /// + /// + public int Start + { + get { return start; } + } + + /// + /// Video stream length. + /// + /// + public int Length + { + get { return length; } + } + + /// + /// Desired playing frame rate. + /// + /// + /// The property specifies the frame rate, which should be used to play the opened video + /// file. + /// + public float FrameRate + { + get { return rate; } + } + + /// + /// Codec used for video compression. + /// + /// + /// The property tells about which codec was used to encode the opened video file. + /// + public string Codec + { + get { return codec; } + } + + + /// + /// Initializes a new instance of the class. + /// + /// + /// Initializes Video for Windows library. + /// + public AVIReader( ) + { + Win32.AVIFileInit( ); + } + + /// + /// Destroys the instance of the class. + /// + /// + ~AVIReader( ) + { + Dispose( false ); + } + + /// + /// Dispose the object. + /// + /// + /// Frees unmanaged resources used by the object. The object becomes unusable + /// after that. + /// + public void Dispose( ) + { + Dispose( true ); + // remove me from the Finalization queue + GC.SuppressFinalize( this ); + } + + /// + /// Dispose the object. + /// + /// + /// Indicates if disposing was initiated manually. + /// + protected virtual void Dispose( bool disposing ) + { + if ( disposing ) + { + // dispose managed resources + } + // close current AVI file if any opened and uninitialize AVI library + Close( ); + Win32.AVIFileExit( ); + } + + /// + /// Open AVI file. + /// + /// + /// AVI file name to open. + /// + /// The method opens a video file and prepares the stream and decoder for + /// reading video frames with the help of method. + /// + /// + /// Failed opening the specified file. + /// A error occurred while opening the video file. See exception message. + /// + /// + public void Open( string fileName ) + { + // close previous file + Close( ); + + bool success = false; + + try + { + lock ( sync ) + { + // open AVI file + if ( Win32.AVIFileOpen( out file, fileName, Win32.OpenFileMode.ShareDenyWrite, IntPtr.Zero ) != 0 ) + throw new System.IO.IOException( "Failed opening the specified AVI file." ); + + // get first video stream + if ( Win32.AVIFileGetStream( file, out stream, Win32.mmioFOURCC( "vids" ), 0 ) != 0 ) + throw new VideoException( "Failed getting video stream." ); + + // get stream info + Win32.AVISTREAMINFO info = new Win32.AVISTREAMINFO( ); + Win32.AVIStreamInfo( stream, ref info, Marshal.SizeOf( info ) ); + + width = info.rectFrame.right; + height = info.rectFrame.bottom; + position = info.start; + start = info.start; + length = info.length; + rate = (float) info.rate / (float) info.scale; + codec = Win32.decode_mmioFOURCC( info.handler ); + + // prepare decompressor + Win32.BITMAPINFOHEADER bitmapInfoHeader = new Win32.BITMAPINFOHEADER( ); + + bitmapInfoHeader.size = Marshal.SizeOf( bitmapInfoHeader.GetType( ) ); + bitmapInfoHeader.width = width; + bitmapInfoHeader.height = height; + bitmapInfoHeader.planes = 1; + bitmapInfoHeader.bitCount = 24; + bitmapInfoHeader.compression = 0; // BI_RGB + + // get frame object + if ( ( getFrame = Win32.AVIStreamGetFrameOpen( stream, ref bitmapInfoHeader ) ) == IntPtr.Zero ) + { + bitmapInfoHeader.height = -height; + + if ( ( getFrame = Win32.AVIStreamGetFrameOpen( stream, ref bitmapInfoHeader ) ) == IntPtr.Zero ) + throw new VideoException( "Failed initializing decompressor." ); + } + + success = true; + } + } + finally + { + if ( !success ) + { + Close( ); + } + } + } + + /// + /// Close video file. + /// + /// + public void Close( ) + { + lock ( sync ) + { + // release get frame object + if ( getFrame != IntPtr.Zero ) + { + Win32.AVIStreamGetFrameClose( getFrame ); + getFrame = IntPtr.Zero; + } + + // release stream + if ( stream != IntPtr.Zero ) + { + Win32.AVIStreamRelease( stream ); + stream = IntPtr.Zero; + } + + // release file + if ( file != IntPtr.Zero ) + { + Win32.AVIFileRelease( file ); + file = IntPtr.Zero; + } + } + } + + /// + /// Get next frame of opened video stream. + /// + /// + /// Returns next frame as a bitmap. + /// + /// The method reads and returns the next video frame in the opened video stream + /// at the position, which is set in property. + /// + /// Thrown if no video file was open. + /// A error occurred while reading next video frame. See exception message. + /// + public Bitmap GetNextFrame( ) + { + lock ( sync ) + { + if ( file == IntPtr.Zero ) + { + throw new System.IO.IOException( "Cannot read video frames since video file is not open." ); + } + + // get frame at specified position + IntPtr DIB = Win32.AVIStreamGetFrame( getFrame, position ); + if ( DIB == IntPtr.Zero ) + throw new VideoException( "Failed getting frame." ); + + Win32.BITMAPINFOHEADER bitmapInfoHeader; + + // copy BITMAPINFOHEADER from unmanaged memory + bitmapInfoHeader = (Win32.BITMAPINFOHEADER) Marshal.PtrToStructure( DIB, typeof( Win32.BITMAPINFOHEADER ) ); + + // create new bitmap + Bitmap image = new Bitmap( width, height, PixelFormat.Format24bppRgb ); + + // lock bitmap data + BitmapData imageData = image.LockBits( + new Rectangle( 0, 0, width, height ), + ImageLockMode.ReadWrite, + PixelFormat.Format24bppRgb ); + + // copy image data + int srcStride = imageData.Stride; + int dstStride = imageData.Stride; + + // check image direction + if ( bitmapInfoHeader.height > 0 ) + { + // it`s a bottom-top image + int dst = imageData.Scan0.ToInt32( ) + dstStride * ( height - 1 ); + int src = DIB.ToInt32( ) + Marshal.SizeOf( typeof( Win32.BITMAPINFOHEADER ) ); + + for ( int y = 0; y < height; y++ ) + { + Win32.memcpy( dst, src, srcStride ); + dst -= dstStride; + src += srcStride; + } + } + else + { + // it`s a top bootom image + int dst = imageData.Scan0.ToInt32( ); + int src = DIB.ToInt32( ) + Marshal.SizeOf( typeof( Win32.BITMAPINFOHEADER ) ); + + // copy the whole image + Win32.memcpy( dst, src, srcStride * height ); + } + + // unlock bitmap data + image.UnlockBits( imageData ); + + // move position to the next frame + position++; + + return image; + } + } + } +} diff --git a/Sources/Accord.Video.VFW/AVIWriter.cs b/Sources/Accord.Video.VFW/AVIWriter.cs new file mode 100644 index 0000000000..cee6dd65a --- /dev/null +++ b/Sources/Accord.Video.VFW/AVIWriter.cs @@ -0,0 +1,427 @@ +// AForge Video for Windows Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Video.VFW +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + using System.Runtime.InteropServices; + using AForge; + + /// + /// AVI files writing using Video for Windows interface. + /// + /// + /// The class allows to write AVI files using Video for Windows API. + /// + /// Sample usage: + /// + /// // instantiate AVI writer, use WMV3 codec + /// AVIWriter writer = new AVIWriter( "wmv3" ); + /// // create new AVI file and open it + /// writer.Open( "test.avi", 320, 240 ); + /// // create frame image + /// Bitmap image = new Bitmap( 320, 240 ); + /// + /// for ( int i = 0; i < 240; i++ ) + /// { + /// // update image + /// image.SetPixel( i, i, Color.Red ); + /// // add the image as a new frame of video file + /// writer.AddFrame( image ); + /// } + /// writer.Close( ); + /// + /// + /// + public class AVIWriter : IDisposable + { + // AVI file + private IntPtr file; + // video stream + private IntPtr stream; + // compressed stream + private IntPtr streamCompressed; + // buffer + private IntPtr buffer = IntPtr.Zero; + + // width of video frames + private int width; + // height of vide frames + private int height; + // length of one line + private int stride; + // quality + private int quality = -1; + // frame rate + private int rate = 25; + // current position + private int position; + // codec used for video compression + private string codec = "DIB "; + + // dummy object to lock for synchronization + private object sync = new object( ); + + /// + /// Width of video frames. + /// + /// + /// The property specifies the width of video frames, which are acceptable + /// by method for saving, which is set in + /// method. + /// + public int Width + { + get { return ( buffer != IntPtr.Zero ) ? width : 0; } + } + + /// + /// Height of video frames. + /// + /// + /// The property specifies the height of video frames, which are acceptable + /// by method for saving, which is set in + /// method. + /// + public int Height + { + get { return ( buffer != IntPtr.Zero ) ? height : 0; } + } + + /// + /// Current position in video stream. + /// + /// + /// The property tell current position in video stream, which actually equals + /// to the amount of frames added using method. + /// + public int Position + { + get { return position; } + } + + /// + /// Desired playing frame rate. + /// + /// + /// The property sets the video frame rate, which should be use during playing + /// of the video to be saved. + /// + /// The property should be set befor opening new file to take effect. + /// + /// Default frame rate is set to 25. + /// + public int FrameRate + { + get { return rate; } + set { rate = value; } + } + + /// + /// Codec used for video compression. + /// + /// + /// The property sets the FOURCC code of video compression codec, which needs to + /// be used for video encoding. + /// + /// The property should be set befor opening new file to take effect. + /// + /// Default video codec is set "DIB ", which means no compression. + /// + public string Codec + { + get { return codec; } + set { codec = value; } + } + + /// + /// Compression video quality. + /// + /// + /// The property sets video quality used by codec in order to balance compression rate + /// and image quality. The quality is measured usually in the [0, 100] range. + /// + /// The property should be set befor opening new file to take effect. + /// + /// Default value is set to -1 - default compression quality of the codec. + /// + public int Quality + { + get { return quality; } + set { quality = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Initializes Video for Windows library. + /// + public AVIWriter( ) + { + Win32.AVIFileInit( ); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Codec to use for compression. + /// + /// Initializes Video for Windows library. + /// + public AVIWriter( string codec ) : this( ) + { + this.codec = codec; + } + + /// + /// Destroys the instance of the class. + /// + /// + ~AVIWriter( ) + { + Dispose( false ); + } + + /// + /// Dispose the object. + /// + /// + /// Frees unmanaged resources used by the object. The object becomes unusable + /// after that. + /// + public void Dispose( ) + { + Dispose( true ); + // remove me from the Finalization queue + GC.SuppressFinalize( this ); + } + + /// + /// Dispose the object. + /// + /// + /// Indicates if disposing was initiated manually. + /// + protected virtual void Dispose( bool disposing ) + { + if ( disposing ) + { + // dispose managed resources + } + // close current AVI file if any opened and uninitialize AVI library + Close( ); + Win32.AVIFileExit( ); + } + + /// + /// Create new AVI file and open it for writing. + /// + /// + /// AVI file name to create. + /// Video width. + /// Video height. + /// + /// The method opens (creates) a video files, configure video codec and prepares + /// the stream for saving video frames with a help of method. + /// + /// Failed opening the specified file. + /// A error occurred while creating new video file. See exception message. + /// Insufficient memory for internal buffer. + /// Video file resolution must be a multiple of two. + /// + public void Open( string fileName, int width, int height ) + { + // close previous file + Close( ); + + // check width and height + if ( ( ( width & 1 ) != 0 ) || ( ( height & 1 ) != 0 ) ) + { + throw new ArgumentException( "Video file resolution must be a multiple of two." ); + } + + bool success = false; + + try + { + lock ( sync ) + { + // calculate stride + stride = width * 3; + if ( ( stride % 4 ) != 0 ) + stride += ( 4 - stride % 4 ); + + // create new file + if ( Win32.AVIFileOpen( out file, fileName, Win32.OpenFileMode.Create | Win32.OpenFileMode.Write, IntPtr.Zero ) != 0 ) + throw new System.IO.IOException( "Failed opening the specified file." ); + + this.width = width; + this.height = height; + + // describe new stream + Win32.AVISTREAMINFO info = new Win32.AVISTREAMINFO( ); + + info.type = Win32.mmioFOURCC( "vids" ); + info.handler = Win32.mmioFOURCC( codec ); + info.scale = 1; + info.rate = rate; + info.suggestedBufferSize = stride * height; + + // create stream + if ( Win32.AVIFileCreateStream( file, out stream, ref info ) != 0 ) + throw new VideoException( "Failed creating stream." ); + + // describe compression options + Win32.AVICOMPRESSOPTIONS options = new Win32.AVICOMPRESSOPTIONS( ); + + options.handler = Win32.mmioFOURCC( codec ); + options.quality = quality; + + // uncomment if video settings dialog is required to show + // Win32.AVISaveOptions( stream, ref options ); + + // create compressed stream + if ( Win32.AVIMakeCompressedStream( out streamCompressed, stream, ref options, IntPtr.Zero ) != 0 ) + throw new VideoException( "Failed creating compressed stream." ); + + // describe frame format + Win32.BITMAPINFOHEADER bitmapInfoHeader = new Win32.BITMAPINFOHEADER( ); + + bitmapInfoHeader.size = Marshal.SizeOf( bitmapInfoHeader.GetType( ) ); + bitmapInfoHeader.width = width; + bitmapInfoHeader.height = height; + bitmapInfoHeader.planes = 1; + bitmapInfoHeader.bitCount = 24; + bitmapInfoHeader.sizeImage = 0; + bitmapInfoHeader.compression = 0; // BI_RGB + + // set frame format + if ( Win32.AVIStreamSetFormat( streamCompressed, 0, ref bitmapInfoHeader, Marshal.SizeOf( bitmapInfoHeader.GetType( ) ) ) != 0 ) + throw new VideoException( "Failed setting format of the compressed stream." ); + + // alloc unmanaged memory for frame + buffer = Marshal.AllocHGlobal( stride * height ); + + if ( buffer == IntPtr.Zero ) + { + throw new OutOfMemoryException( "Insufficient memory for internal buffer." ); + } + + position = 0; + success = true; + } + } + finally + { + if ( !success ) + { + Close( ); + } + } + } + + /// + /// Close video file. + /// + /// + public void Close( ) + { + lock ( sync ) + { + // free unmanaged memory + if ( buffer != IntPtr.Zero ) + { + Marshal.FreeHGlobal( buffer ); + buffer = IntPtr.Zero; + } + + // release compressed stream + if ( streamCompressed != IntPtr.Zero ) + { + Win32.AVIStreamRelease( streamCompressed ); + streamCompressed = IntPtr.Zero; + } + + // release stream + if ( stream != IntPtr.Zero ) + { + Win32.AVIStreamRelease( stream ); + stream = IntPtr.Zero; + } + + // release file + if ( file != IntPtr.Zero ) + { + Win32.AVIFileRelease( file ); + file = IntPtr.Zero; + } + } + } + + /// + /// Add new frame to the AVI file. + /// + /// + /// New frame image. + /// + /// The method adds new video frame to an opened video file. The width and heights + /// of the frame should be the same as it was specified in method + /// (see and properties). + /// + /// Thrown if no video file was open. + /// Bitmap size must be of the same as video size, which was specified on opening video file. + /// A error occurred while writing new video frame. See exception message. + /// + public void AddFrame( Bitmap frameImage ) + { + lock ( sync ) + { + // check if AVI file was properly opened + if ( buffer == IntPtr.Zero ) + throw new System.IO.IOException( "AVI file should be successfully opened before writing." ); + + // check image dimension + if ( ( frameImage.Width != width ) || ( frameImage.Height != height ) ) + throw new ArgumentException( "Bitmap size must be of the same as video size, which was specified on opening video file." ); + + // lock bitmap data + BitmapData imageData = frameImage.LockBits( + new Rectangle( 0, 0, width, height ), + ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb ); + + // copy image data + int srcStride = imageData.Stride; + int dstStride = stride; + + int src = imageData.Scan0.ToInt32( ) + srcStride * ( height - 1 ); + int dst = buffer.ToInt32( ); + + for ( int y = 0; y < height; y++ ) + { + Win32.memcpy( dst, src, dstStride ); + dst += dstStride; + src -= srcStride; + } + + // unlock bitmap data + frameImage.UnlockBits( imageData ); + + // write to stream + if ( Win32.AVIStreamWrite( streamCompressed, position, 1, buffer, + stride * height, 0, IntPtr.Zero, IntPtr.Zero ) != 0 ) + throw new VideoException( "Failed adding frame." ); + + position++; + } + } + } +} diff --git a/Sources/Accord.Video.VFW/Accord.Video.VFW.cd b/Sources/Accord.Video.VFW/Accord.Video.VFW.cd new file mode 100644 index 0000000000..65f74d4a3 --- /dev/null +++ b/Sources/Accord.Video.VFW/Accord.Video.VFW.cd @@ -0,0 +1,98 @@ + + + + + + + + AAAABAYAAiACEAsAABAQQAQAAAAAAAAIIUAAAIBAAAI= + AVIFileVideoSource.cs + + + + + + + + + AAAAAEAABbAAIAUgQEAAIEJAAAAAAAAADCAAAACAAAA= + AVIReader.cs + + + + + + + + + AAAAAEAABeAAIAVgQAAAIEAgAAAAAAAADCFAAACAAAA= + AVIWriter.cs + + + + + + + + + Win32.cs + + + + + Win32.cs + + + + + Win32.cs + + + + + Win32.cs + + + + + Win32.cs + + + + + AAgACBAAAsQAgAAAFAAAAAAAAAAcEIAAKQQAAAAIACA= + Win32.cs + + + + \ No newline at end of file diff --git a/Sources/Accord.Video.VFW/Accord.Video.VFW.csproj b/Sources/Accord.Video.VFW/Accord.Video.VFW.csproj new file mode 100644 index 0000000000..75d93953f --- /dev/null +++ b/Sources/Accord.Video.VFW/Accord.Video.VFW.csproj @@ -0,0 +1,128 @@ + + + + {22E852C0-17FF-4106-9DF6-41EABB8C0613} + Accord.Video.VFW + Accord.Video.VFW + Debug + AnyCPU + AnyCPU + Library + Properties + True + 4 + True + true + Accord.snk + 3.5 + False + true + ..\Accord.NET.ruleset + false + true + 4096 + true + pdbonly + true + + + v4.5 + Full + False + False + True + DEBUG;TRACE + $(SolutionDir)..\Debug\ + + + $(SolutionDir)..\Release\net35 + TRACE;CODE_ANALYSIS;NET35 + v3.5 + true + $(SolutionDir)..\Release\net35\Accord.Video.VFW.XML + $(SolutionDir)..\Release\net35\Accord.Video.VFW.dll.CodeAnalysisLog.xml + + + $(SolutionDir)..\Release\net40 + TRACE;CODE_ANALYSIS;NET40 + v4.0 + $(SolutionDir)..\Release\net40\Accord.Video.VFW.XML + $(SolutionDir)..\Release\net40\Accord.Video.VFW.dll.CodeAnalysisLog.xml + + + $(SolutionDir)..\Release\net45 + TRACE;CODE_ANALYSIS;NET45 + v4.5 + $(SolutionDir)..\Release\net45\Accord.Video.VFW.XML + $(SolutionDir)..\Release\net45\Accord.Video.VFW.dll.CodeAnalysisLog.xml + + + + + + + + + + Properties\VersionInfo.cs + + + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 2.0 %28x86%29 + false + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + true + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + {a177a90c-8207-466a-af70-f2b8452a42ac} + Accord.Core + + + {809725dc-6502-4732-a51c-deb7fea12975} + Accord.Video + + + + + + + + \ No newline at end of file diff --git a/Sources/Accord.Video.VFW/Accord.snk b/Sources/Accord.Video.VFW/Accord.snk new file mode 100644 index 0000000000..ed97b4edd Binary files /dev/null and b/Sources/Accord.Video.VFW/Accord.snk differ diff --git a/Sources/Accord.Video.VFW/Properties/AssemblyInfo.cs b/Sources/Accord.Video.VFW/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..febe8264c --- /dev/null +++ b/Sources/Accord.Video.VFW/Properties/AssemblyInfo.cs @@ -0,0 +1,13 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Accord.Video.VFW")] +[assembly: AssemblyDescription("Accord.NET - Video For Windows Interface Library")] +[assembly: AssemblyConfiguration("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. +[assembly: ComVisible(false)] diff --git a/Sources/Accord.Video.VFW/Win32.cs b/Sources/Accord.Video.VFW/Win32.cs new file mode 100644 index 0000000000..18d6455f9 --- /dev/null +++ b/Sources/Accord.Video.VFW/Win32.cs @@ -0,0 +1,784 @@ +// AForge Video for Windows Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2007-2011 +// contacts@aforgenet.com + +// +namespace AForge.Video.VFW +{ + using System; + using System.Runtime.InteropServices; + + /// + /// Windows API functions and structures. + /// + /// + /// The class provides Video for Windows and some other Win32 functions and structurs. + /// + internal static class Win32 + { + /// + /// Copy a block of memory. + /// + /// + /// Destination pointer. + /// Source pointer. + /// Memory block's length to copy. + /// + /// Return's the value of dst - pointer to destination. + /// + [DllImport( "ntdll.dll", CallingConvention = CallingConvention.Cdecl )] + public static extern int memcpy( + int dst, + int src, + int count ); + + + // --- Video for Windows Functions + + /// + /// Initialize the AVIFile library. + /// + /// + [DllImport( "avifil32.dll" )] + public static extern void AVIFileInit( ); + + /// + /// Exit the AVIFile library. + /// + [DllImport( "avifil32.dll" )] + public static extern void AVIFileExit( ); + + /// + /// Open an AVI file. + /// + /// + /// Opened AVI file interface. + /// AVI file name. + /// Opening mode (see ). + /// Handler to use (null to use default). + /// + /// Returns zero on success or error code otherwise. + /// + [DllImport( "avifil32.dll", CharSet = CharSet.Unicode )] + public static extern int AVIFileOpen( + out IntPtr aviHandler, + String fileName, + OpenFileMode mode, + IntPtr handler ); + + /// + /// Release an open AVI stream. + /// + /// + /// Open AVI file interface. + /// + /// Returns the reference count of the file. + /// + [DllImport( "avifil32.dll" )] + public static extern int AVIFileRelease( + IntPtr aviHandler ); + + /// + /// Get stream interface that is associated with a specified AVI file + /// + /// + /// Handler to an open AVI file. + /// Stream interface. + /// Stream type to open. + /// Count of the stream type. Identifies which occurrence of the specified stream type to access. + /// + /// + /// + [DllImport( "avifil32.dll" )] + public static extern int AVIFileGetStream( + IntPtr aviHandler, + out IntPtr streamHandler, + int streamType, + int streamNumner ); + + /// + /// Create a new stream in an existing file and creates an interface to the new stream. + /// + /// + /// Handler to an open AVI file. + /// Stream interface. + /// Pointer to a structure containing information about the new stream. + /// + /// Returns zero if successful or an error otherwise. + /// + [DllImport( "avifil32.dll" )] + public static extern int AVIFileCreateStream( + IntPtr aviHandler, + out IntPtr streamHandler, + ref AVISTREAMINFO streamInfo ); + + /// + /// Release an open AVI stream. + /// + /// + /// Handle to an open stream. + /// + /// Returns the current reference count of the stream. + /// + [DllImport( "avifil32.dll" )] + public static extern int AVIStreamRelease( + IntPtr streamHandler ); + + /// + /// Set the format of a stream at the specified position. + /// + /// + /// Handle to an open stream. + /// Position in the stream to receive the format. + /// Pointer to a structure containing the new format. + /// Size, in bytes, of the block of memory referenced by format. + /// + /// Returns zero if successful or an error otherwise. + /// + [DllImport( "avifil32.dll" )] + public static extern int AVIStreamSetFormat( + IntPtr streamHandler, + int position, + ref BITMAPINFOHEADER format, + int formatSize ); + + /// + /// Get the starting sample number for the stream. + /// + /// + /// Handle to an open stream. + /// + /// Returns the number if successful or 1 otherwise. + /// + [DllImport( "avifil32.dll" )] + public static extern int AVIStreamStart( + IntPtr streamHandler ); + + /// + /// Get the length of the stream. + /// + /// + /// Handle to an open stream. + /// + /// Returns the stream's length, in samples, if successful or -1 otherwise. + /// + [DllImport( "avifil32.dll" )] + public static extern int AVIStreamLength( + IntPtr streamHandler ); + + /// + /// Obtain stream header information. + /// + /// + /// Handle to an open stream. + /// Pointer to a structure to contain the stream information. + /// Size, in bytes, of the structure used for streamInfo. + /// + /// Returns zero if successful or an error otherwise. + /// + [DllImport( "avifil32.dll", CharSet = CharSet.Unicode )] + public static extern int AVIStreamInfo( + IntPtr streamHandler, + ref AVISTREAMINFO streamInfo, + int infoSize ); + + /// + /// Prepare to decompress video frames from the specified video stream + /// + /// + /// Pointer to the video stream used as the video source. + /// Pointer to a structure that defines the desired video format. Specify NULL to use a default format. + /// + /// Returns an object that can be used with the function. + /// + [DllImport( "avifil32.dll" )] + public static extern IntPtr AVIStreamGetFrameOpen( + IntPtr streamHandler, + ref BITMAPINFOHEADER wantedFormat ); + + /// + /// Prepare to decompress video frames from the specified video stream. + /// + /// + /// Pointer to the video stream used as the video source. + /// Pointer to a structure that defines the desired video format. Specify NULL to use a default format. + /// + /// Returns a GetFrame object that can be used with the function. + /// + [DllImport( "avifil32.dll" )] + public static extern IntPtr AVIStreamGetFrameOpen( + IntPtr streamHandler, + int wantedFormat ); + + /// + /// Releases resources used to decompress video frames. + /// + /// + /// Handle returned from the function. + /// + /// Returns zero if successful or an error otherwise. + /// + [DllImport( "avifil32.dll" )] + public static extern int AVIStreamGetFrameClose( + IntPtr getFrameObject ); + + /// + /// Return the address of a decompressed video frame. + /// + /// + /// Pointer to a GetFrame object. + /// Position, in samples, within the stream of the desired frame. + /// + /// Returns a pointer to the frame data if successful or NULL otherwise. + /// + [DllImport( "avifil32.dll" )] + public static extern IntPtr AVIStreamGetFrame( + IntPtr getFrameObject, + int position ); + + /// + /// Write data to a stream. + /// + /// + /// Handle to an open stream. + /// First sample to write. + /// Number of samples to write. + /// Pointer to a buffer containing the data to write. + /// Size of the buffer referenced by buffer. + /// Flag associated with this data. + /// Pointer to a buffer that receives the number of samples written. This can be set to NULL. + /// Pointer to a buffer that receives the number of bytes written. This can be set to NULL. + /// + /// Returns zero if successful or an error otherwise. + /// + [DllImport( "avifil32.dll" )] + public static extern int AVIStreamWrite( + IntPtr streamHandler, + int start, + int samples, + IntPtr buffer, + int bufferSize, + int flags, + IntPtr samplesWritten, + IntPtr bytesWritten ); + + /// + /// Retrieve the save options for a file and returns them in a buffer. + /// + /// + /// Handle to the parent window for the Compression Options dialog box. + /// Flags for displaying the Compression Options dialog box. + /// Number of streams that have their options set by the dialog box. + /// Pointer to an array of stream interface pointers. + /// Pointer to an array of pointers to AVICOMPRESSOPTIONS structures. + /// + /// Returns TRUE if the user pressed OK, FALSE for CANCEL, or an error otherwise. + /// + [DllImport( "avifil32.dll" )] + public static extern int AVISaveOptions( + IntPtr window, + int flags, + int streams, + [In, MarshalAs( UnmanagedType.LPArray, SizeParamIndex = 0 )] IntPtr[] streamInterfaces, + [In, MarshalAs( UnmanagedType.LPArray, SizeParamIndex = 0 )] IntPtr[] options ); + + /// + /// Free the resources allocated by the AVISaveOptions function. + /// + /// + /// Count of the AVICOMPRESSOPTIONS structures referenced in options. + /// Pointer to an array of pointers to AVICOMPRESSOPTIONS structures. + /// + /// Returns 0. + /// + [DllImport( "avifil32.dll" )] + public static extern int AVISaveOptionsFree( + int streams, + [In, MarshalAs( UnmanagedType.LPArray, SizeParamIndex = 0 )] IntPtr[] options ); + + /// + /// Create a compressed stream from an uncompressed stream and a + /// compression filter, and returns the address of a pointer to + /// the compressed stream. + /// + /// + /// Pointer to a buffer that receives the compressed stream pointer. + /// Pointer to the stream to be compressed. + /// Pointer to a structure that identifies the type of compression to use and the options to apply. + /// Pointer to a class identifier used to create the stream. + /// + /// Returns 0 if successful or an error otherwise. + /// + [DllImport( "avifil32.dll" )] + public static extern int AVIMakeCompressedStream( + out IntPtr compressedStream, + IntPtr sourceStream, + ref AVICOMPRESSOPTIONS options, + IntPtr clsidHandler ); + + // --- structures + + /// + /// Structure to define the coordinates of the upper-left and + /// lower-right corners of a rectangle. + /// + /// + [StructLayout( LayoutKind.Sequential, Pack = 1 )] + public struct RECT + { + /// + /// x-coordinate of the upper-left corner of the rectangle. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int left; + + /// + /// y-coordinate of the upper-left corner of the rectangle. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int top; + + /// + /// x-coordinate of the bottom-right corner of the rectangle. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int right; + + /// + /// y-coordinate of the bottom-right corner of the rectangle. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int bottom; + } + + /// + /// Structure, which contains information for a single stream . + /// + /// + [StructLayout( LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1 )] + public struct AVISTREAMINFO + { + /// + /// Four-character code indicating the stream type. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int type; + + /// + /// Four-character code of the compressor handler that will compress this video stream when it is saved. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int handler; + + /// + /// Applicable flags for the stream. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int flags; + + /// + /// Capability flags; currently unused. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int Capabilities; + + /// + /// Priority of the stream. + /// + /// + [MarshalAs( UnmanagedType.I2 )] + public short priority; + + /// + /// Language of the stream. + /// + /// + [MarshalAs( UnmanagedType.I2 )] + public short language; + + /// + /// Time scale applicable for the stream. + /// + /// + /// Dividing rate by scale gives the playback rate in number of samples per second. + /// + [MarshalAs( UnmanagedType.I4 )] + public int scale; + + /// + /// Rate in an integer format. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int rate; + + /// + /// Sample number of the first frame of the AVI file. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int start; + + /// + /// Length of this stream. + /// + /// + /// The units are defined by rate and scale. + /// + [MarshalAs( UnmanagedType.I4 )] + public int length; + + /// + /// Audio skew. This member specifies how much to skew the audio data ahead of the video frames in interleaved files. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int initialFrames; + + /// + /// Recommended buffer size, in bytes, for the stream. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int suggestedBufferSize; + + /// + /// Quality indicator of the video data in the stream. + /// + /// + /// Quality is represented as a number between 0 and 10,000. + /// + [MarshalAs( UnmanagedType.I4 )] + public int quality; + + /// + /// Size, in bytes, of a single data sample. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int sampleSize; + + /// + /// Dimensions of the video destination rectangle. + /// + /// + [MarshalAs( UnmanagedType.Struct, SizeConst = 16 )] + public RECT rectFrame; + + /// + /// Number of times the stream has been edited. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int editCount; + + /// + /// Number of times the stream format has changed. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int formatChangeCount; + + /// + /// Description of the stream. + /// + /// + [MarshalAs( UnmanagedType.ByValTStr, SizeConst = 64 )] + public string name; + } + + /// + /// Structure, which contains information about the dimensions and color format of a DIB. + /// + /// + [StructLayout( LayoutKind.Sequential, Pack = 1 )] + public struct BITMAPINFOHEADER + { + /// + /// Specifies the number of bytes required by the structure. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int size; + + /// + /// Specifies the width of the bitmap, in pixels. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int width; + + /// + /// Specifies the height of the bitmap, in pixels. + /// + /// + /// If height is positive, the bitmap is a bottom-up DIB and its origin is + /// the lower-left corner. If height is negative, the bitmap is a top-down DIB and its + /// origin is the upper-left corner. + /// + [MarshalAs( UnmanagedType.I4 )] + public int height; + + /// + /// Specifies the number of planes for the target device. This value must be set to 1. + /// + /// + [MarshalAs( UnmanagedType.I2 )] + public short planes; + + /// + /// Specifies the number of bits-per-pixel. + /// + /// + [MarshalAs( UnmanagedType.I2 )] + public short bitCount; + + /// + /// Specifies the type of compression for a compressed bottom-up bitmap (top-down DIBs cannot be compressed). + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int compression; + + /// + /// Specifies the size, in bytes, of the image. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int sizeImage; + + /// + /// Specifies the horizontal resolution, in pixels-per-meter, of the target device for the bitmap. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int xPelsPerMeter; + + /// + /// Specifies the vertical resolution, in pixels-per-meter, of the target device for the bitmap. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int yPelsPerMeter; + + /// + /// Specifies the number of color indexes in the color table that are actually used by the bitmap. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int colorsUsed; + + /// + /// Specifies the number of color indexes that are required for displaying the bitmap. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int colorsImportant; + } + + /// + /// Structure, which contains information about a stream and how it is compressed and saved. + /// + /// + [StructLayout( LayoutKind.Sequential, Pack = 1 )] + public struct AVICOMPRESSOPTIONS + { + /// + /// Four-character code indicating the stream type. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int type; + + /// + /// Four-character code for the compressor handler that will compress this video stream when it is saved. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int handler; + + /// + /// Maximum period between video key frames. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int keyFrameEvery; + + /// + /// Quality value passed to a video compressor. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int quality; + + /// + /// Video compressor data rate. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int bytesPerSecond; + + /// + /// Flags used for compression. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int flags; + + /// + /// Pointer to a structure defining the data format. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int format; + + /// + /// Size, in bytes, of the data referenced by format. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int formatSize; + + /// + /// Video-compressor-specific data; used internally. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int parameters; + + /// + /// Size, in bytes, of the data referenced by parameters. + /// + [MarshalAs( UnmanagedType.I4 )] + public int parametersSize; + + /// + /// Interleave factor for interspersing stream data with data from the first stream. + /// + /// + [MarshalAs( UnmanagedType.I4 )] + public int interleaveEvery; + } + + // --- enumerations + + /// + /// File access modes. + /// + /// + [Flags] + public enum OpenFileMode + { + Read = 0x00000000, + Write = 0x00000001, + ReadWrite = 0x00000002, + ShareCompat = 0x00000000, + ShareExclusive = 0x00000010, + ShareDenyWrite = 0x00000020, + ShareDenyRead = 0x00000030, + ShareDenyNone = 0x00000040, + Parse = 0x00000100, + Delete = 0x00000200, + Verify = 0x00000400, + Cancel = 0x00000800, + Create = 0x00001000, + Prompt = 0x00002000, + Exist = 0x00004000, + Reopen = 0x00008000 + } + + /// + /// .NET replacement of mmioFOURCC macros. Converts four characters to code. + /// + /// + /// Four characters string. + /// + /// Returns the code created from provided characters. + /// + public static int mmioFOURCC( string str ) + { + return ( + ( (int) (byte) ( str[0] ) ) | + ( (int) (byte) ( str[1] ) << 8 ) | + ( (int) (byte) ( str[2] ) << 16 ) | + ( (int) (byte) ( str[3] ) << 24 ) ); + } + + /// + /// Inverse to . Converts code to fout characters string. + /// + /// + /// Code to convert. + /// + /// Returns four characters string. + /// + public static string decode_mmioFOURCC( int code ) + { + char[] chs = new char[4]; + + for ( int i = 0; i < 4; i++ ) + { + chs[i] = (char) (byte) ( ( code >> ( i << 3 ) ) & 0xFF ); + if ( !char.IsLetterOrDigit( chs[i] ) ) + chs[i] = ' '; + } + return new string( chs ); + } + + + /// + /// Version of for one stream only. + /// + /// + /// Stream to configure. + /// Stream options. + /// + /// Returns TRUE if the user pressed OK, FALSE for CANCEL, or an error otherwise. + /// + public static int AVISaveOptions( IntPtr stream, ref AVICOMPRESSOPTIONS options ) + { + IntPtr[] streams = new IntPtr[1]; + IntPtr[] infPtrs = new IntPtr[1]; + IntPtr mem; + int ret; + + // alloc unmanaged memory + mem = Marshal.AllocHGlobal( Marshal.SizeOf( typeof( AVICOMPRESSOPTIONS ) ) ); + + // copy from managed structure to unmanaged memory + Marshal.StructureToPtr( options, mem, false ); + + streams[0] = stream; + infPtrs[0] = mem; + + // show dialog with a list of available compresors and configuration + ret = AVISaveOptions( IntPtr.Zero, 0, 1, streams, infPtrs ); + + // copy from unmanaged memory to managed structure + options = (AVICOMPRESSOPTIONS) Marshal.PtrToStructure( mem, typeof( AVICOMPRESSOPTIONS ) ); + + // free AVI compression options + AVISaveOptionsFree( 1, infPtrs ); + + // clear it, because the information already freed by AVISaveOptionsFree + options.format = 0; + options.parameters = 0; + + // free unmanaged memory + Marshal.FreeHGlobal( mem ); + + return ret; + } + } +} diff --git a/Sources/Accord.Video.Ximea/Accord.Video.Ximea.cd b/Sources/Accord.Video.Ximea/Accord.Video.Ximea.cd new file mode 100644 index 0000000000..d55a97cfd --- /dev/null +++ b/Sources/Accord.Video.Ximea/Accord.Video.Ximea.cd @@ -0,0 +1,109 @@ + + + + + + + + CameraParameter.cs + + + + + CameraParameter.cs + + + + + CameraParameter.cs + + + + + CameraParameter.cs + + + + + CameraParameter.cs + + + + + CameraParameter.cs + + + + + IAACGHIABQwAMhAigBABAEAQIAgBYDDAACAKAADBAAA= + CameraParameter.cs + + + + + + + + QABAAEAIAJBAIAAAABAAAAAQAAAIAAEAQAABEACIAAA= + XimeaCamera.cs + + + + + + + + QAAABAYAArBCEAkAABAAQAQAAAAIAAAIIUAAAIBIAAI= + XimeaVideoSource.cs + + + + + + + AAAAAIAAAAAAABAAAAAAAAAAABAAAAAAAAAAAAAAAAA= + GpiMode.cs + + + + + + BAAAAIAAQAAAAAAAAAAAAAQAAAAAAAAAAAQAAAAAAIA= + GpoMode.cs + + + + + + AAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAABAAAAAEAIA= + ImageFormat.cs + + + + + + ACAAIIAAQAAIAAAAAAAAAAAAAAABAAAAAAQAQAAAAIA= + LedMode.cs + + + + + + AAAAAIAAAAEAAAAAAAAAAAAACCAAAAAAAAAAAAAAAAA= + TriggerSource.cs + + + + \ No newline at end of file diff --git a/Sources/Accord.Video.Ximea/Accord.Video.Ximea.csproj b/Sources/Accord.Video.Ximea/Accord.Video.Ximea.csproj new file mode 100644 index 0000000000..fd7465014 --- /dev/null +++ b/Sources/Accord.Video.Ximea/Accord.Video.Ximea.csproj @@ -0,0 +1,125 @@ + + + + {AEDD6CFB-747B-4077-9288-9CD2A86090F1} + Accord.Video.Ximea + Accord.Video.Ximea + Debug + AnyCPU + AnyCPU + Library + Properties + True + 4 + True + true + Accord.snk + 3.5 + False + true + ..\Accord.NET.ruleset + false + true + 4096 + true + pdbonly + true + + + v4.5 + Full + False + true + False + True + DEBUG;TRACE + $(SolutionDir)..\Debug\ + + + $(SolutionDir)..\Release\net35 + TRACE;CODE_ANALYSIS;NET35 + v3.5 + $(SolutionDir)..\Release\net35\Accord.Video.Ximea.XML + $(SolutionDir)..\Release\net35\Accord.Video.Ximea.dll.CodeAnalysisLog.xml + + + $(SolutionDir)..\Release\net40 + TRACE;CODE_ANALYSIS;NET40 + v4.0 + $(SolutionDir)..\Release\net40\Accord.Video.Ximea.XML + $(SolutionDir)..\Release\net40\Accord.Video.Ximea.dll.CodeAnalysisLog.xml + + + $(SolutionDir)..\Release\net45 + TRACE;CODE_ANALYSIS;NET45 + v4.5 + $(SolutionDir)..\Release\net45\Accord.Video.Ximea.XML + $(SolutionDir)..\Release\net45\Accord.Video.Ximea.dll.CodeAnalysisLog.xml + + + + + + + + + + Properties\VersionInfo.cs + + + + + + + + + + + + + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + {a177a90c-8207-466a-af70-f2b8452a42ac} + Accord.Core + + + {809725dc-6502-4732-a51c-deb7fea12975} + Accord.Video + + + + + + + + \ No newline at end of file diff --git a/Sources/Accord.Video.Ximea/Accord.snk b/Sources/Accord.Video.Ximea/Accord.snk new file mode 100644 index 0000000000..ed97b4edd Binary files /dev/null and b/Sources/Accord.Video.Ximea/Accord.snk differ diff --git a/Sources/Accord.Video.Ximea/CameraParameter.cs b/Sources/Accord.Video.Ximea/CameraParameter.cs new file mode 100644 index 0000000000..814576d64 --- /dev/null +++ b/Sources/Accord.Video.Ximea/CameraParameter.cs @@ -0,0 +1,515 @@ +// AForge XIMEA Video Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Video.Ximea +{ + using System; + + /// + /// Set of available configuration options for XIMEA cameras. + /// + /// + /// The class defines list of parameters, which are available + /// to set/get using corresponding methods of and + /// classes. + /// + public static class CameraParameter + { + /// + /// Get camera model name. Type string. + /// + public const string DeviceName = "device_name:info"; + + /// + /// Get device serial number in decimal format. Type string, integer, float + /// + public const string DeviceSerialNumber = "device_sn:info"; + + /// + /// Returns device type (1394, USB2.0, CURRERA…..). Type string. + /// + public const string DeviceType = "device_type:info"; + + /// + /// Set/Get exposure time in microseconds. Type integer. + /// + public const string Exposure = "exposure"; + + /// + /// Get longest possible exposure to be set on camera in microseconds. Type integer. + /// + public const string ExposureMax = "exposure:max"; + + /// + /// Get shortest possible exposure to be set on camera in microseconds. Type integer. + /// + public const string ExposureMin = "exposure:min"; + + /// + /// Set/Get camera gain in dB. Type float. + /// + public const string Gain = "gain"; + + /// + /// Get highest possible camera gain in dB. Type float. + /// + public const string GainMax = "gain:max"; + + /// + /// Get lowest possible camera gain in dB. Type float. + /// + public const string GainMin = "gain:min"; + + /// + /// Set/Get width of the image provided by the camera (in pixels). Type integer. + /// + public const string Width = "width"; + + /// + /// Get maximal image width provided by the camera (in pixels). Type integer. + /// + public const string WidthMax = "width:max"; + + /// + /// Get minimum image width provided by the camera (in pixels). Type integer. + /// + public const string WidthMin = "width:min"; + + /// + /// Set/Get height of the image provided by the camera (in pixels). Type integer. + /// + public const string Height = "height"; + + /// + /// Get maximal image height provided by the camera (in pixels). Type integer. + /// + public const string HeightMax = "height:max"; + + /// + /// Get minimum image height provided by the camera (in pixels). Type integer. + /// + public const string HeightMin = "height:min"; + + /// + /// Set/Get image resolution by binning or skipping. Type integer. + /// + public const string Downsampling = "downsampling"; + + /// + /// Get highest value for binning or skipping. Type integer. + /// + public const string DownsamplingMax = "downsampling:max"; + + /// + /// Get lowest value for binning or skipping. Type integer. + /// + public const string DownsamplingMin = "downsampling:min"; + + /// + /// Get frames per second. Type float. + /// + public const string Framerate = "framerate"; + + /// + /// Get highest possible framerate for current camera settings. Type float. + /// + public const string FramerateMax = "framerate:max"; + + /// + /// Get lowest framerate for current camera settings. Type float. + /// + public const string FramerateMin = "framerate:min"; + + /// + /// Set/Get horizontal offset from the origin to the area of interest (in pixels). Type integer. + /// + public const string OffsetX = "offsetX"; + + /// + /// Get maximum horizontal offset from the origin to the area of interest (in pixels). Type integer. + /// + public const string OffsetXMax = "offsetX:max"; + + /// + /// Get minimum horizontal offset from the origin to the area of interest (in pixels). Type integer. + /// + public const string OffsetXMin = "offsetX:min"; + + /// + /// Set/Get vertical offset from the origin to the area of interest (in pixels). Type integer. + /// + public const string OffsetY = "offsetY"; + + /// + /// Get maximum vertical offset from the origin to the area of interest (in pixels). Type integer. + /// + public const string OffsetYMax = "offsetY:max"; + + /// + /// Get minimal vertical offset from the origin to the area of interest (in pixels). Type integer. + /// + public const string OffsetYMin = "offsetY:min"; + + /// + /// Set/Get white balance blue coefficient. Type float. + /// + public const string WhiteBalanceBlue = "wb_kb"; + + /// + /// Set/Get white balance red coefficient. Type float. + /// + public const string WhiteBalanceRed = "wb_kr"; + + /// + /// Set/Get white balance green coefficient. Type float. + /// + public const string WhiteBalanceGreen = "wb_kg"; + + /// + /// Set/Get sharpness strenght. Type float. + /// + public const string Sharpness = "sharpness"; + + /// + /// Set/Get luminosity gamma value. Type float. By default 1.0. + /// + public const string GammaY = "gammaY"; + + /// + /// Set/Get chromaticity gamma value. Type float. By default 0. + /// + public const string GammaC = "gammaC"; + + /// + /// Set default color correction matrx. + /// + public const string SetDefaultColorCorrectonMatrix = "defccMTX"; + + /// + /// Set/Get image format provided by the camera. Type integer. Use + /// enumeraton for possible values. + /// + public const string ImageFormat = "imgdataformat"; + + /// + /// Set/Get camera's trigger mode. Type integer. Use + /// enumeration for possible values. + /// + public const string Trigger = "trigger_source"; + + /// + /// Generates an internal trigger. must be set to . + /// Type integer. + /// + public const string SoftwareTrigger = "trigger_software"; + + /// + /// Calculates white balance. Takes white balance from image center (should be white/grey object + /// in the center of scene). Type integer. + /// + public const string CalculateWhiteBalance = "manual_wb"; + + /// + /// Enable/disable automatic white balance. Type integer. By default 0. + /// + /// + /// Set 0 to disable automatic white balance or 1 to enable. + /// + public const string AutoWhiteBalance = "auto_wb"; + + /// + /// Enable/disable bad pixels correction. Type integer. By default 0. + /// + /// + /// Set 0 to disable bad pixels correction or 1 to enable. + /// + public const string BadPixelsCorrection = "bpc"; + + /// + /// Set/Get acquisition buffer size in bytes. Type integer. By default 53248000. + /// + /// + /// Defines acquisition buffer size in bytes. This buffer contains images' + /// data from sensor. This parameter can be set only when acquisition is stopped. + /// + /// See for additional information. + /// + /// + public const string AcquisitionBufferSize = "acq_buffer_size"; + + /// + /// Set/Get maximum number of images to store in queue. Type integer. By default 4. + /// + /// + /// + /// + /// + /// See also for additional information. + /// + /// + public const string BufferQueueSize = "buffers_queue_size"; + + /// + /// Set of configuration options to configure Automatic Exposure/Gain (AEAG) parameters. + /// + public static class AEAG + { + /// + /// Enable/disable automatic exposure/gain control. Type integer. By default 0. + /// + /// + /// Set 0 to disable automatic exposure/gain control or 1 to enable. + /// + public const string Enable = "aeag"; + + /// + /// Set/Get maximum limit of exposure in AEAG procedure. Type integer. By default 100. Units - ms. + /// + public const string ExposureMaxLimit = "ae_max_limit"; + + /// + /// Set/Get maximum limit of gain in AEAG procedure. Type float. Default depends on camera type. Units - dB. + /// + public const string GainMaxLimit = "ag_max_limit"; + + /// + /// Set/Get exposure priority, [0, 1]. Type float. By default 0.8. + /// + /// + /// Setting the value to 0.5, for example, set exposure priority to 50% + /// and gain priority to 50%. + /// + public const string ExposurePriority = "exp_priority"; + + /// + /// Set/Get average intensity of output signal AEAG should achieve (in %). Type float. By default 40. + /// + public const string Level = "aeag_level"; + } + + /// + /// Set of configuration options to configure camera's LEDs. Currently supported only for Currera-R cameras. + /// + public static class LED + { + /// + /// Selects camera LED to be used. Type integer. + /// + public const string Selector = "led_selector"; + + /// + /// Get highest LED number on camera. Type integer. + /// + public const string Max = "led_selector:max"; + + /// + /// Get lowest LED number on camera. Type integer. + /// + public const string Min = "led_selector:min"; + + /// + /// Set/Get LED functionality. Select LED by using parameter. + /// Use enumeration for possible parameter values. Type integer. + /// + public const string Mode = "led_mode"; + } + + /// + /// Set of configuration options to configure GPO (General Purpose Output) ports. + /// + public static class GPO + { + /// + /// Select camera GPO port. Type integer. + /// + public const string Selector = "gpo_selector"; + + /// + /// Get highest GPO port number on camera. Type integer. + /// + public const string Max = "gpo_selector:max"; + + /// + /// Get lowest GPO port number on camera. Type integer + /// + public const string Min = "gpo_selector:min"; + + /// + /// Set/Get GPO port functionality. Select port by using parameter. + /// Use enumeration to set mode. Type integer. + /// + public const string Mode = "gpo_mode"; + } + + /// + /// Set of configuration options to access/configure GPI (General Purpose Input) ports. + /// + public static class GPI + { + /// + /// Select camera GPI port. Type integer. + /// + public const string Selector = "gpi_selector"; + + /// + /// Get highest GPI port number on camera. Type integer. + /// + public const string Max = "gpi_selector:max"; + + /// + /// Get lowest GPI port number on camera. Type integer + /// + public const string Min = "gpi_selector:min"; + + /// + /// Set/Get GPI port functionality. Select port by using parameter. + /// Use enumeration to set mode. Type integer. + /// + public const string Mode = "gpi_mode"; + + /// + /// Get current GPI level. Type integer. + /// + public const string Level = "gpi_level"; + } + + /// + /// Set of configuration options to configure camera's LUT - Look-Up-Table. + /// Currently available only for Currera-R cameras. + /// + public static class LUT + { + /// + /// Enable/Disable LUT. Type integer. Default 0. + /// + /// + /// Set 0 to disable LUT - sensor pixels are transferred directly. + /// Set 1 to enable LUT - sensor pixels are mapped through LUT. + /// + public static string Enable = "LUTEnable"; + + /// + /// Set/Get the index (offset) of the coefficient to access in the LUT. Type integer. + /// + public static string Index = "LUTIndex"; + + /// + /// Get lowest LUT index (offset) of the coefficient to access in the LUT. Type integer. + /// + public static string IndexMin = "LUTIndex:min"; + + /// + /// Get highest LUT index (offset) of the coefficient to access in the LUT. Type integer. + /// + public static string IndexMax = "LUTIndex:max"; + + /// + /// Set/Get value in the LUT. Index of the value must be selected using + /// parameter. Type integer. + /// + public static string Value = "LUTValue"; + + /// + /// Get highest value to be set in LUT. Type integer. + /// + public static string ValueMin = "LUTValue:min"; + + /// + /// Get lowest value to be set in LUT. Type integer. + /// + public static string ValueMax = "LUTValue:max"; + } + + /// + /// Set of configuration options to access elements of Color Correction Matrix. + /// + /// + public static class ColorCorrectionMatrix + { + /// + /// Set/Get color correction matrix element [0][0]. Type float. By default 1.0. + /// + public const string V00 = "ccMTX00"; + + /// + /// Set/Get color correction matrix element [0][1]. Type float. By default 0.0. + /// + public const string V01 = "ccMTX01"; + + /// + /// Set/Get color correction matrix element [0][2]. Type float. By default 0.0. + /// + public const string V02 = "ccMTX02"; + + /// + /// Set/Get color correction matrix element [0][3]. Type float. By default 0.0. + /// + public const string V03 = "ccMTX03"; + + /// + /// Set/Get color correction matrix element [1][0]. Type float. By default 0.0. + /// + public const string V10 = "ccMTX10"; + + /// + /// Set/Get color correction matrix element [1][1]. Type float. By default 1.0. + /// + public const string V11 = "ccMTX11"; + + /// + /// Set/Get color correction matrix element [1][2]. Type float. By default 0.0. + /// + public const string V12 = "ccMTX12"; + + /// + /// Set/Get color correction matrix element [1][3]. Type float. By default 0.0. + /// + public const string V13 = "ccMTX13"; + + /// + /// Set/Get color correction matrix element [2][0]. Type float. By default 0.0. + /// + public const string V20 = "ccMTX20"; + + /// + /// Set/Get color correction matrix element [2][1]. Type float. By default 0.0. + /// + public const string V21 = "ccMTX21"; + + /// + /// Set/Get color correction matrix element [2][2]. Type float. By default 1.0. + /// + public const string V22 = "ccMTX22"; + + /// + /// Set/Get color correction matrix element [2][3]. Type float. By default 0.0. + /// + public const string V23 = "ccMTX23"; + + /// + /// Set/Get color correction matrix element [3][0]. Type float. By default 0.0. + /// + public const string V30 = "ccMTX30"; + + /// + /// Set/Get color correction matrix element [3][1]. Type float. By default 0.0. + /// + public const string V31 = "ccMTX31"; + + /// + /// Set/Get color correction matrix element [3][2]. Type float. By default 0.0. + /// + public const string V32 = "ccMTX32"; + + /// + /// Set/Get color correction matrix element [3][3]. Type float. By default 1.0. + /// + public const string V33 = "ccMTX33"; + } + } +} diff --git a/Sources/Accord.Video.Ximea/GpiMode.cs b/Sources/Accord.Video.Ximea/GpiMode.cs new file mode 100644 index 0000000000..ed14fbc65 --- /dev/null +++ b/Sources/Accord.Video.Ximea/GpiMode.cs @@ -0,0 +1,33 @@ +// AForge XIMEA Video Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Video.Ximea +{ + using System; + + /// + /// XIMEA camera's GPI port modes. + /// + public enum GpiMode : int + { + /// + /// Input is off. + /// + Off = 0, + + /// + /// Trigger input. + /// + Trigger = 1, + + /// + /// External signal input. + /// + ExternalEvent = 2 + } +} diff --git a/Sources/Accord.Video.Ximea/GpoMode.cs b/Sources/Accord.Video.Ximea/GpoMode.cs new file mode 100644 index 0000000000..7233b62e3 --- /dev/null +++ b/Sources/Accord.Video.Ximea/GpoMode.cs @@ -0,0 +1,48 @@ +// AForge XIMEA Video Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Video.Ximea +{ + using System; + + /// + /// XIMEA camera's GPO port modes. + /// + public enum GpoMode : int + { + /// + /// Output off. + /// + Off = 0, + + /// + /// Logical level. + /// + On = 1, + + /// + /// High during exposure (integration) time + readout time + data transfer time. + /// + FrameActive = 2, + + /// + /// Low during exposure (integration) time + readout time + data trasnfer time. + /// + FrameActiveNew = 3, + + /// + /// High during exposure(integration) time. + /// + ExposureActive = 4, + + /// + /// Low during exposure(integration) time. + /// + ExposureActiveNeg = 5 + } +} diff --git a/Sources/Accord.Video.Ximea/ImageFormat.cs b/Sources/Accord.Video.Ximea/ImageFormat.cs new file mode 100644 index 0000000000..cbd141895 --- /dev/null +++ b/Sources/Accord.Video.Ximea/ImageFormat.cs @@ -0,0 +1,38 @@ +// AForge XIMEA Video Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Video.Ximea +{ + using System; + + /// + /// Enumeration of image formats supported by XIMEA cameras. + /// + public enum ImageFormat : int + { + /// + /// 8 bits per pixel. + /// + Grayscale8 = 0, + + /// + /// 16 bits per pixel. + /// + Grayscale16 = 1, + + /// + /// RGB data format. + /// + RGB24 = 2, + + /// + /// RGBA data format. + /// + RGB32 = 3 + } +} diff --git a/Sources/Accord.Video.Ximea/Images/HW_SW_buffers.png b/Sources/Accord.Video.Ximea/Images/HW_SW_buffers.png new file mode 100644 index 0000000000..aaf6e1a28 Binary files /dev/null and b/Sources/Accord.Video.Ximea/Images/HW_SW_buffers.png differ diff --git a/Sources/Accord.Video.Ximea/Internal/ParameterType.cs b/Sources/Accord.Video.Ximea/Internal/ParameterType.cs new file mode 100644 index 0000000000..3236d5bd0 --- /dev/null +++ b/Sources/Accord.Video.Ximea/Internal/ParameterType.cs @@ -0,0 +1,19 @@ +// AForge XIMEA Video Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +using System; + +namespace AForge.Video.Ximea.Internal +{ + internal enum ParameterType + { + Integer = 0, + Float = 1, + String = 2 + } +} diff --git a/Sources/Accord.Video.Ximea/Internal/XimeaAPI.cs b/Sources/Accord.Video.Ximea/Internal/XimeaAPI.cs new file mode 100644 index 0000000000..c63bbd0e2 --- /dev/null +++ b/Sources/Accord.Video.Ximea/Internal/XimeaAPI.cs @@ -0,0 +1,45 @@ +// AForge XIMEA Video Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +using System; +using System.Runtime.InteropServices; + +namespace AForge.Video.Ximea.Internal +{ + internal static class XimeaAPI + { + [DllImport( "m3api.dll" )] + public static extern unsafe int xiGetNumberDevices( out int numDevices ); + + [DllImport( "m3api.dll" )] + public static extern unsafe int xiOpenDevice( int deviceID, [Out] out IntPtr hDevice ); + [DllImport( "m3api.dll" )] + public static extern int xiCloseDevice( IntPtr deviceHandle ); + + [DllImport( "m3api.dll" )] + public static extern int xiStartAcquisition( IntPtr deviceHandle ); + [DllImport( "m3api.dll" )] + public static extern int xiStopAcquisition( IntPtr deviceHandle ); + + [DllImport( "m3api.dll" )] + public static extern int xiGetImage( IntPtr deviceHandle, int timeout, [In, MarshalAs( UnmanagedType.Struct )] ref XimeaImage image ); + + [DllImport( "m3api.dll" )] + public static extern unsafe int xiGetParam( IntPtr deviceHandle, string parameter, byte* value, out int size, ref ParameterType type ); + [DllImport( "m3api.dll" )] + public static extern int xiGetParam( IntPtr deviceHandle, string parameter, out int value, out int size, ref ParameterType type ); + [DllImport( "m3api.dll" )] + public static extern int xiGetParam( IntPtr deviceHandle, string parameter, out float value, out int size, ref ParameterType type ); + + [DllImport( "m3api.dll" )] + public static extern int xiSetParam( IntPtr deviceHandle, string parameter, ref float value, int size, ParameterType type ); + [DllImport( "m3api.dll" )] + public static extern int xiSetParam( IntPtr deviceHandle, string parameter, ref int value, int size, ParameterType type ); + + } +} diff --git a/Sources/Accord.Video.Ximea/Internal/XimeaImage.cs b/Sources/Accord.Video.Ximea/Internal/XimeaImage.cs new file mode 100644 index 0000000000..7301878bd --- /dev/null +++ b/Sources/Accord.Video.Ximea/Internal/XimeaImage.cs @@ -0,0 +1,25 @@ +// AForge XIMEA Video Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +using System; +using System.Runtime.InteropServices; + +namespace AForge.Video.Ximea.Internal +{ + [StructLayout( LayoutKind.Sequential )] + internal struct XimeaImage + { + public int StructSize; + public IntPtr BitmapData; + public int Size; + public ImageFormat PixelFormat; + public int Width; + public int Height; + public int FrameNumber; + } +} diff --git a/Sources/Accord.Video.Ximea/LedMode.cs b/Sources/Accord.Video.Ximea/LedMode.cs new file mode 100644 index 0000000000..e3d712eea --- /dev/null +++ b/Sources/Accord.Video.Ximea/LedMode.cs @@ -0,0 +1,63 @@ +// AForge XIMEA Video Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Video.Ximea +{ + using System; + + /// + /// XIMEA camera's LED state options. + /// + public enum LedMode : int + { + /// + /// Blink if link is ok (led 1), heartbeat mode (led 2). + /// + Heartbeat = 0, + + /// + /// Blink led if trigger detected. + /// + TriggerActive = 1, + + /// + /// Blink led if external signal detected. + /// + ExternalEventActive = 2, + + /// + /// Blink led during data streaming. + /// + Acquisition = 3, + + /// + /// Blink led during sensor integration time. + /// + ExposureActive = 4, + + /// + /// Blink if device busy/not busy. + /// + FrameActive = 5, + + /// + /// Blink led if link is OK. + /// + Link = 6, + + /// + /// Turn off LED. + /// + Off = 7, + + /// + /// Turn on LED. + /// + On = 8 + } +} diff --git a/Sources/Accord.Video.Ximea/Properties/AssemblyInfo.cs b/Sources/Accord.Video.Ximea/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..81fdbec14 --- /dev/null +++ b/Sources/Accord.Video.Ximea/Properties/AssemblyInfo.cs @@ -0,0 +1,13 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Accord.Video.Ximea")] +[assembly: AssemblyDescription("Accord.NET - Ximea Interface Library")] +[assembly: AssemblyConfiguration("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. +[assembly: ComVisible(false)] diff --git a/Sources/Accord.Video.Ximea/TriggerSource.cs b/Sources/Accord.Video.Ximea/TriggerSource.cs new file mode 100644 index 0000000000..34d53f943 --- /dev/null +++ b/Sources/Accord.Video.Ximea/TriggerSource.cs @@ -0,0 +1,38 @@ +// AForge XIMEA Video Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Video.Ximea +{ + using System; + + /// + /// Enumeration of camera's trigger modes. + /// + public enum TriggerSource : int + { + /// + /// Camera works in free run mode. + /// + Off = 0, + + /// + /// External trigger (rising edge). + /// + EdgeRising = 1, + + /// + /// External trigger (falling edge). + /// + EdgeFalling = 2, + + /// + /// Software (manual) trigger. + /// + Software = 3 + } +} diff --git a/Sources/Accord.Video.Ximea/XimeaCamera.cs b/Sources/Accord.Video.Ximea/XimeaCamera.cs new file mode 100644 index 0000000000..380972acd --- /dev/null +++ b/Sources/Accord.Video.Ximea/XimeaCamera.cs @@ -0,0 +1,787 @@ +// AForge XIMEA Video Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Video.Ximea +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + using System.Text; + using AForge.Video.Ximea.Internal; + + /// + /// The class provides access to XIMEA cameras. + /// + /// + /// The class allows to perform image acquisition from XIMEA cameras. + /// It wraps XIMEA'a xiAPI, which means that users of this class will also require m3api.dll and a correct + /// TM file for the camera model connected to the system (both are provided with XIMEA API software package). + /// + /// Sample usage: + /// + /// XimeaCamera camera = new XimeaCamera( ); + /// + /// // open camera and start data acquisition + /// camera.Open( 0 ); + /// camera.StartAcquisition( ); + /// + /// // set exposure time to 10 milliseconds + /// camera.SetParam( CameraParameter.Exposure, 10 * 1000 ); + /// + /// // get image from the camera + /// Bitmap bitmap = camera.GetImage( ); + /// // process the image + /// // ... + /// + /// // dispose the image when it is no longer needed + /// bitmap.Dispose( ); + /// + /// // stop data acquisition and close the camera + /// camera.StopAcquisition( ); + /// camera.Close( ); + /// + /// + /// + /// + /// + public class XimeaCamera + { + private IntPtr deviceHandle = IntPtr.Zero; + private bool isAcquisitionStarted = false; + private int deviceID = 0; + + // dummy object to lock for synchronization + private object sync = new object( ); + + /// + /// Get number of XIMEA camera connected to the system. + /// + public static int CamerasCount + { + get + { + int count; + + int errorCode = XimeaAPI.xiGetNumberDevices( out count ); + HandleError( errorCode ); + + return count; + } + } + + /// + /// Specifies if camera's data acquisition is currently active for the opened camera (if any). + /// + public bool IsAcquisitionStarted + { + get + { + lock ( sync ) + { + return isAcquisitionStarted; + } + } + } + + /// + /// Specifies if a camera is currently opened by the instance of the class. + /// + public bool IsDeviceOpen + { + get + { + lock ( sync ) + { + return ( deviceHandle != IntPtr.Zero ); + } + } + } + + /// + /// ID of the the recently opened XIMEA camera. + /// + public int DeviceID + { + get { return deviceID; } + } + + /// + /// Open XIMEA camera. + /// + /// + /// Camera ID to open. + /// + /// Opens the specified XIMEA camera preparing it for starting video acquisition + /// which is done using method. The + /// property can be used at any time to find if a camera was opened or not. + /// + /// An error occurred while communicating with a camera. See error + /// message for additional information. + /// + public void Open( int deviceID ) + { + lock ( sync ) + { + IntPtr deviceHandle; + int errorCode = XimeaAPI.xiOpenDevice( deviceID, out deviceHandle ); + HandleError( errorCode ); + // save the device handle is everything is fine + this.deviceHandle = deviceHandle; + this.isAcquisitionStarted = false; + this.deviceID = deviceID; + } + } + + /// + /// Close opened camera (if any) and release allocated resources. + /// + /// + /// The method also calls method if it was not + /// done by user. + /// + /// An error occurred while communicating with a camera. See error + /// message for additional information. + /// + public void Close( ) + { + lock ( sync ) + { + if ( deviceHandle != IntPtr.Zero ) + { + if ( isAcquisitionStarted ) + { + try + { + StopAcquisition( ); + } + catch + { + } + } + + try + { + int errorCode = XimeaAPI.xiCloseDevice( deviceHandle ); + HandleError( errorCode ); + } + finally + { + deviceHandle = IntPtr.Zero; + } + } + } + } + + /// + /// Begin camera's work cycle and start data acquisition from it. + /// + /// + /// The property can be used at any time to find if the + /// acquisition was started or not. + /// + /// An error occurred while communicating with a camera. See error + /// message for additional information. + /// No camera was opened, so can not access its methods. + /// + public void StartAcquisition( ) + { + lock ( sync ) + { + CheckConnection( ); + + int errorCode = XimeaAPI.xiStartAcquisition( deviceHandle ); + HandleError( errorCode ); + + isAcquisitionStarted = true; + } + } + + /// + /// End camera's work cycle and stops data acquisition. + /// + /// + /// An error occurred while communicating with a camera. See error + /// message for additional information. + /// No camera was opened, so can not access its methods. + /// + public void StopAcquisition( ) + { + lock ( sync ) + { + CheckConnection( ); + + try + { + int errorCode = XimeaAPI.xiStopAcquisition( deviceHandle ); + HandleError( errorCode ); + } + finally + { + isAcquisitionStarted = false; + } + } + } + + /// + /// Set camera's parameter. + /// + /// + /// Parameter name. + /// Integer parameter value. + /// + /// The method allows to control different camera's parameters, like exposure time, gain value, etc. + /// See class for the list of some possible configuration parameters. See + /// XIMEA documentation for the complete list of supported parameters. + /// + /// + /// An error occurred while communicating with a camera. See error + /// message for additional information. + /// No camera was opened, so can not access its methods. + /// + public void SetParam( string parameterName, int value ) + { + lock ( sync ) + { + CheckConnection( ); + + int errorCode = XimeaAPI.xiSetParam( deviceHandle, parameterName, ref value, 4, ParameterType.Integer ); + HandleError( errorCode ); + } + } + + /// + /// Set camera's parameter. + /// + /// + /// Parameter name. + /// Float parameter value. + /// + /// The method allows to control different camera's parameters, like exposure time, gain value, etc. + /// See class for the list of some possible configuration parameters. See + /// XIMEA documentation for the complete list of supported parameters. + /// + /// + /// An error occurred while communicating with a camera. See error + /// message for additional information. + /// No camera was opened, so can not access its methods. + /// + public void SetParam( string parameterName, float value ) + { + lock ( sync ) + { + CheckConnection( ); + + int errorCode = XimeaAPI.xiSetParam( deviceHandle, parameterName, ref value, 4, ParameterType.Float ); + HandleError( errorCode ); + } + } + + /// + /// Get camera's parameter as integer value. + /// + /// + /// Parameter name to get from camera. + /// + /// Returns integer value of the requested parameter. + /// + /// See class for the list of some possible configuration parameters. See + /// XIMEA documentation for the complete list of supported parameters. + /// + /// An error occurred while communicating with a camera. See error + /// message for additional information. + /// No camera was opened, so can not access its methods. + /// + public int GetParamInt( string parameterName ) + { + lock ( sync ) + { + CheckConnection( ); + + int value; + int size; + ParameterType type = ParameterType.Integer; + + int errorCode = XimeaAPI.xiGetParam( deviceHandle, parameterName, out value, out size, ref type ); + HandleError( errorCode ); + + return value; + } + } + + /// + /// Get camera's parameter as float value. + /// + /// + /// Parameter name to get from camera. + /// + /// Returns float value of the requested parameter. + /// + /// See class for the list of some possible configuration parameters. See + /// XIMEA documentation for the complete list of supported parameters. + /// + /// An error occurred while communicating with a camera. See error + /// message for additional information. + /// No camera was opened, so can not access its methods. + /// + public float GetParamFloat( string parameterName ) + { + lock ( sync ) + { + CheckConnection( ); + + float value; + int size; + ParameterType type = ParameterType.Float; + + int errorCode = XimeaAPI.xiGetParam( deviceHandle, parameterName, out value, out size, ref type ); + HandleError( errorCode ); + + return value; + } + } + + /// + /// Get camera's parameter as string value. + /// + /// + /// Parameter name to get from camera. + /// + /// Returns string value of the requested parameter. + /// + /// See class for the list of some possible configuration parameters. See + /// XIMEA documentation for the complete list of supported parameters. + /// + /// An error occurred while communicating with a camera. See error + /// message for additional information. + /// No camera was opened, so can not access its methods. + /// + public string GetParamString( string parameterName ) + { + lock ( sync ) + { + CheckConnection( ); + + byte[] bytes = new byte[260]; + int size = bytes.Length; + ParameterType type = ParameterType.String; + + unsafe + { + fixed ( byte* ptr = bytes ) + { + int errorCode = XimeaAPI.xiGetParam( deviceHandle, parameterName, ptr, out size, ref type ); + HandleError( errorCode ); + } + } + + return Encoding.ASCII.GetString( bytes, 0, size ); + } + } + + /// + /// Get image from the opened XIMEA camera. + /// + /// + /// Returns image retrieved from the camera. + /// + /// The method calls method specifying 5000 as the timeout + /// value. + /// + public Bitmap GetImage( ) + { + return GetImage( 5000 ); + } + + /// + /// Get image from the opened XIMEA camera. + /// + /// + /// Maximum time to wait in milliseconds till image becomes available. + /// + /// Returns image retrieved from the camera. + /// + /// The method calls method specifying + /// the makeCopy parameter. + /// + public Bitmap GetImage( int timeout ) + { + return GetImage( timeout, true ); + } + + /// + /// Get image from the opened XIMEA camera. + /// + /// + /// Maximum time to wait in milliseconds till image becomes available. + /// Make a copy of the camera's image or not. + /// + /// Returns image retrieved from the camera. + /// + /// If the is set to , then the method + /// creates a managed copy of the camera's image, so the managed image stays valid even when the camera + /// is closed. However, setting this parameter to creates a managed image which is + /// just a wrapper around camera's unmanaged image. So if camera is closed and its resources are freed, the + /// managed image becomes no longer valid and accessing it will generate an exception. + /// + /// An error occurred while communicating with a camera. See error + /// message for additional information. + /// No camera was opened, so can not access its methods. + /// Time out value reached - no image is available within specified time value. + /// + public Bitmap GetImage( int timeout, bool makeCopy ) + { + lock ( sync ) + { + CheckConnection( ); + + int errorCode; + + XimeaImage ximeaImage = new XimeaImage( ); + unsafe + { + ximeaImage.StructSize = sizeof( XimeaImage ); + } + + // get image from XIMEA camera + try + { + errorCode = XimeaAPI.xiGetImage( deviceHandle, timeout, ref ximeaImage ); + } + catch ( AccessViolationException ) + { + errorCode = 9; + } + + // handle error if any + HandleError( errorCode ); + + // create managed bitmap for the unmanaged image provided by camera + PixelFormat pixelFormat = PixelFormat.Undefined; + int stride = 0; + + switch ( ximeaImage.PixelFormat ) + { + case ImageFormat.Grayscale8: + pixelFormat = PixelFormat.Format8bppIndexed; + stride = ximeaImage.Width; + break; + + case ImageFormat.RGB24: + pixelFormat = PixelFormat.Format24bppRgb; + stride = ximeaImage.Width * 3; + break; + + case ImageFormat.RGB32: + pixelFormat = PixelFormat.Format32bppRgb; + stride = ximeaImage.Width * 4; + break; + + default: + throw new VideoException( "Unsupported pixel format." ); + } + + Bitmap bitmap = null; + + if ( !makeCopy ) + { + bitmap = new Bitmap( ximeaImage.Width, ximeaImage.Height, stride, pixelFormat, ximeaImage.BitmapData ); + } + else + { + bitmap = new Bitmap( ximeaImage.Width, ximeaImage.Height, pixelFormat ); + + // lock destination bitmap data + BitmapData bitmapData = bitmap.LockBits( + new Rectangle( 0, 0, ximeaImage.Width, ximeaImage.Height ), + ImageLockMode.ReadWrite, pixelFormat ); + + int dstStride = bitmapData.Stride; + int lineSize = Math.Min( stride, dstStride ); + + unsafe + { + byte* dst = (byte*) bitmapData.Scan0.ToPointer( ); + byte* src = (byte*) ximeaImage.BitmapData.ToPointer( ); + + if ( stride != dstStride ) + { + // copy image + for ( int y = 0; y < ximeaImage.Height; y++ ) + { + AForge.SystemTools.CopyUnmanagedMemory( dst, src, lineSize ); + dst += dstStride; + src += stride; + } + } + else + { + AForge.SystemTools.CopyUnmanagedMemory( dst, src, stride * ximeaImage.Height ); + } + } + + // unlock destination images + bitmap.UnlockBits( bitmapData ); + } + + // set palette for grayscale image + if ( ximeaImage.PixelFormat == ImageFormat.Grayscale8 ) + { + ColorPalette palette = bitmap.Palette; + for ( int i = 0; i < 256; i++ ) + { + palette.Entries[i] = Color.FromArgb( i, i, i ); + } + bitmap.Palette = palette; + } + + return bitmap; + } + } + + + // Handle errors from XIMEA API + private static void HandleError( int errorCode ) + { + if ( errorCode != 0 ) + { + if ( errorCode == 10 ) + { + throw new TimeoutException( "Time out while waiting for camera response." ); + } + + string errorMessage = string.Empty; + + switch ( errorCode ) + { + case 1: + errorMessage = "Invalid handle"; + break; + + case 2: + errorMessage = "Register read error"; + break; + + case 3: + errorMessage = "Register write error"; + break; + + case 4: + errorMessage = "Freeing resiurces error"; + break; + + case 5: + errorMessage = "Freeing channel error"; + break; + + case 6: + errorMessage = "Freeing bandwith error"; + break; + + case 7: + errorMessage = "Read block error"; + break; + + case 8: + errorMessage = "Write block error"; + break; + + case 9: + errorMessage = "No image"; + break; + + case 11: + errorMessage = "Invalid arguments supplied"; + break; + + case 12: + errorMessage = "Not supported"; + break; + + case 13: + errorMessage = "Attach buffers error"; + break; + + case 14: + errorMessage = "Overlapped result"; + break; + + case 15: + errorMessage = "Memory allocation error"; + break; + + case 16: + errorMessage = "DLL context is NULL"; + break; + + case 17: + errorMessage = "DLL context is non zero"; + break; + + case 18: + errorMessage = "DLL context exists"; + break; + + case 19: + errorMessage = "Too many devices connected"; + break; + + case 20: + errorMessage = "Camera context error"; + break; + + case 21: + errorMessage = "Unknown hardware"; + break; + + case 22: + errorMessage = "Invalid TM file"; + break; + + case 23: + errorMessage = "Invalid TM tag"; + break; + + case 24: + errorMessage = "Incomplete TM"; + break; + + case 25: + errorMessage = "Bus reset error"; + break; + + case 26: + errorMessage = "Not implemented"; + break; + + case 27: + errorMessage = "Shading too bright"; + break; + + case 28: + errorMessage = "Shading too dark"; + break; + + case 29: + errorMessage = "Gain is too low"; + break; + + case 30: + errorMessage = "Invalid bad pixel list"; + break; + + case 31: + errorMessage = "Bad pixel list realloc error"; + break; + + case 32: + errorMessage = "Invalid pixel list"; + break; + + case 33: + errorMessage = "Invalid Flash File System"; + break; + + case 34: + errorMessage = "Invalid profile"; + break; + + case 35: + errorMessage = "Invalid calibration"; + break; + + case 36: + errorMessage = "Invalid buffer"; + break; + + case 38: + errorMessage = "Invalid data"; + break; + + case 39: + errorMessage = "Timing generator is busy"; + break; + + case 40: + errorMessage = "Wrong operation open/write/read/close"; + break; + + case 41: + errorMessage = "Acquisition already started"; + break; + + case 42: + errorMessage = "Old version of device driver installed to the system"; + break; + + case 44: + errorMessage = "Data can't be processed"; + break; + + case 45: + errorMessage = "Error occured and acquisition has been stoped or didn't start"; + break; + + case 46: + errorMessage = "Acquisition has been stoped with error"; + break; + + case 100: + errorMessage = "Unknown parameter"; + break; + + case 101: + errorMessage = "Wrong parameter value"; + break; + + case 103: + errorMessage = "Wrong parameter type"; + break; + + case 104: + errorMessage = "Wrong parameter size"; + break; + + case 105: + errorMessage = "Input buffer too small"; + break; + + case 106: + errorMessage = "Parameter info not supported"; + break; + + case 107: + errorMessage = "Parameter info not supported"; + break; + + case 108: + errorMessage = "Data format not supported"; + break; + + case 109: + errorMessage = "Read only parameter"; + break; + + case 110: + errorMessage = "No devices found"; + break; + } + + throw new VideoException( string.Format( "Error code: {0}, Message: {1}", errorCode, errorMessage ) ); + } + } + + // Check if a camera is open or not + private void CheckConnection( ) + { + if ( deviceHandle == IntPtr.Zero ) + { + throw new NotConnectedException( "No established connection to XIMEA camera." ); + } + } + } +} diff --git a/Sources/Accord.Video.Ximea/XimeaVideoSource.cs b/Sources/Accord.Video.Ximea/XimeaVideoSource.cs new file mode 100644 index 0000000000..a72057151 --- /dev/null +++ b/Sources/Accord.Video.Ximea/XimeaVideoSource.cs @@ -0,0 +1,483 @@ +// AForge XIMEA Video Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Video.Ximea +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + using System.Threading; + using AForge.Video; + using AForge.Video.Ximea.Internal; + + /// + /// The class provides continues access to XIMEA cameras. + /// + /// + /// The video source class is aimed to provide continues access to XIMEA camera, when + /// images are continuosly acquired from camera and provided throw the event. + /// It just creates a background thread and gets new images from XIMEA camera + /// keeping the specified time interval between image acquisition. + /// Essentially it is a wrapper class around providing interface. + /// + /// Sample usage: + /// + /// // create video source for the XIMEA camera with ID 0 + /// XimeaVideoSource videoSource = new XimeaVideoSource( 0 ); + /// // set event handlers + /// videoSource.NewFrame += new NewFrameEventHandler( video_NewFrame ); + /// // start the video source + /// videoSource.Start( ); + /// + /// // set exposure time to 10 milliseconds + /// videoSource.SetParam( CameraParameter.Exposure, 10 * 1000 ); + /// + /// // ... + /// + /// // New frame event handler, which is invoked on each new available video frame + /// private void video_NewFrame( object sender, NewFrameEventArgs eventArgs ) + /// { + /// // get new frame + /// Bitmap bitmap = eventArgs.Frame; + /// // process the frame + /// } + /// + /// + /// + /// + /// + public class XimeaVideoSource : IVideoSource + { + // XIMEA camera to capture images from + private XimeaCamera camera = new XimeaCamera( ); + + // camera ID + private int deviceID; + // received frames count + private int framesReceived; + // recieved byte count + private long bytesReceived; + // frame interval in milliseconds + private int frameInterval = 200; + + private Thread thread = null; + private ManualResetEvent stopEvent = null; + + // dummy object to lock for synchronization + private object sync = new object( ); + + /// + /// New frame event. + /// + /// + /// Notifies clients about new available frames from the video source. + /// + /// Since video source may have multiple clients, each client is responsible for + /// making a copy (cloning) of the passed video frame, because the video source disposes its + /// own original copy after notifying of clients. + /// + /// + public event NewFrameEventHandler NewFrame; + + /// + /// Video source error event. + /// + /// + /// This event is used to notify clients about any type of errors occurred in + /// video source object, for example internal exceptions. + /// + public event VideoSourceErrorEventHandler VideoSourceError; + + /// + /// Video playing finished event. + /// + /// + /// This event is used to notify clients that the video playing has finished. + /// + /// + public event PlayingFinishedEventHandler PlayingFinished; + + /// + /// A string identifying the video source. + /// + /// + public virtual string Source + { + get { return "Ximea:" + deviceID; } + } + + /// + /// State of the video source. + /// + /// + /// Current state of video source object - running or not. + /// + public bool IsRunning + { + get + { + Thread tempThread = null; + + lock ( sync ) + { + tempThread = thread; + } + + if ( tempThread != null ) + { + // check thread status + if ( tempThread.Join( 0 ) == false ) + return true; + + // the thread is not running, so free resources + Free( ); + } + + return false; + } + } + + /// + /// Received bytes count. + /// + /// + /// Number of bytes the video source provided from the moment of the last + /// access to the property. + /// + /// + public long BytesReceived + { + get + { + long bytes = bytesReceived; + bytesReceived = 0; + return bytes; + } + } + + /// + /// Received frames count. + /// + /// + /// Number of frames the video source provided from the moment of the last + /// access to the property. + /// + /// + public int FramesReceived + { + get + { + int frames = framesReceived; + framesReceived = 0; + return frames; + } + } + + /// + /// Time interval between frames. + /// + /// + /// The property sets the interval in milliseconds between getting new frames from the camera. + /// If the property is set to 100, then the desired frame rate should be about 10 frames per second. + /// + /// Setting this property to 0 leads to no delay between video frames - frames + /// are read as fast as possible. + /// + /// Default value is set to 200. + /// + /// + public int FrameInterval + { + get { return frameInterval; } + set { frameInterval = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// XIMEA camera ID (index) to connect to. + /// + public XimeaVideoSource( int deviceID ) + { + this.deviceID = deviceID; + } + + /// + /// Start video source. + /// + /// + /// Starts video source and returns execution to caller. Video camera will be started + /// and will provide new video frames through the event. + /// + /// There is no XIMEA camera with specified ID connected to the system. + /// An error occurred while communicating with a camera. See error + /// message for additional information. + /// + public void Start( ) + { + if ( IsRunning ) + return; + + lock ( sync ) + { + if ( thread == null ) + { + // check source + if ( deviceID >= XimeaCamera.CamerasCount ) + { + throw new ArgumentException( "There is no XIMEA camera with specified ID connected to the system." ); + } + + // prepare the camera + camera.Open( deviceID ); + + framesReceived = 0; + bytesReceived = 0; + + // create events + stopEvent = new ManualResetEvent( false ); + + // create and start new thread + thread = new Thread( new ThreadStart( WorkerThread ) ); + thread.Name = Source; + thread.Start( ); + } + } + } + + /// + /// Signal video source to stop its work. + /// + /// + /// + /// + public void SignalToStop( ) + { + lock ( sync ) + { + // stop thread + if ( thread != null ) + { + // signal to stop + stopEvent.Set( ); + } + } + } + + /// + /// Wait for video source has stopped. + /// + /// + /// + /// + public void WaitForStop( ) + { + Thread tempThread = null; + + lock ( sync ) + { + tempThread = thread; + } + + if ( tempThread != null ) + { + // wait for thread stop + tempThread.Join( ); + + Free( ); + } + } + + /// + /// Stop video source. + /// + /// + /// The method stops the video source, so it no longer provides new video frames + /// and does not consume any resources. + /// + /// + public void Stop( ) + { + Thread tempThread = null; + + lock ( sync ) + { + tempThread = thread; + } + + if ( tempThread != null ) + { + if ( tempThread.Join( 0 ) == false ) + { + tempThread.Abort( ); + tempThread.Join( ); + } + Free( ); + } + } + + /// + /// Set camera's parameter. + /// + /// + /// Parameter name. + /// Integer parameter value. + /// + /// The call is redirected to . + /// + public void SetParam( string parameterName, int value ) + { + camera.SetParam( parameterName, value ); + } + + /// + /// Set camera's parameter. + /// + /// + /// Parameter name. + /// Float parameter value. + /// + /// The call is redirected to . + /// + public void SetParam( string parameterName, float value ) + { + camera.SetParam( parameterName, value ); + } + + /// + /// Get camera's parameter as integer value. + /// + /// + /// Parameter name to get from camera. + /// + /// Returns integer value of the requested parameter. + /// + /// The call is redirected to . + /// + public int GetParamInt( string parameterName ) + { + return camera.GetParamInt( parameterName ); + } + + /// + /// Get camera's parameter as float value. + /// + /// + /// Parameter name to get from camera. + /// + /// Returns float value of the requested parameter. + /// + /// The call is redirected to . + /// + public float GetParamFloat( string parameterName ) + { + return camera.GetParamFloat( parameterName ); + } + + /// + /// Get camera's parameter as string value. + /// + /// + /// Parameter name to get from camera. + /// + /// Returns string value of the requested parameter. + /// + /// The call is redirected to . + /// + public string GetParamString( string parameterName ) + { + return camera.GetParamString( parameterName ); + } + + // Free resources + private void Free( ) + { + lock ( sync ) + { + thread = null; + + // release events + if ( stopEvent != null ) + { + stopEvent.Close( ); + stopEvent = null; + } + + camera.Close( ); + } + } + + // Worker thread + private void WorkerThread( ) + { + ReasonToFinishPlaying reasonToStop = ReasonToFinishPlaying.StoppedByUser; + + try + { + camera.StartAcquisition( ); + + // while there is no request for stop + while ( !stopEvent.WaitOne( 0, false ) ) + { + // start time + DateTime start = DateTime.Now; + + // get next frame + Bitmap bitmap = camera.GetImage( 15000, false ); + + framesReceived++; + bytesReceived += bitmap.Width * bitmap.Height * ( Bitmap.GetPixelFormatSize( bitmap.PixelFormat ) >> 3 ); + + if ( NewFrame != null ) + NewFrame( this, new NewFrameEventArgs( bitmap ) ); + + // free image + bitmap.Dispose( ); + + // wait for a while ? + if ( frameInterval > 0 ) + { + // get frame duration + TimeSpan span = DateTime.Now.Subtract( start ); + + // miliseconds to sleep + int msec = frameInterval - (int) span.TotalMilliseconds; + + if ( ( msec > 0 ) && ( stopEvent.WaitOne( msec, false ) ) ) + break; + } + } + } + catch ( Exception exception ) + { + reasonToStop = ReasonToFinishPlaying.VideoSourceError; + // provide information to clients + if ( VideoSourceError != null ) + { + VideoSourceError( this, new VideoSourceErrorEventArgs( exception.Message ) ); + } + } + finally + { + try + { + camera.StopAcquisition( ); + } + catch + { + } + } + + if ( PlayingFinished != null ) + { + PlayingFinished( this, reasonToStop ); + } + } + } +} diff --git a/Sources/Accord.Video/Accord.Video.cd b/Sources/Accord.Video/Accord.Video.cd new file mode 100644 index 0000000000..02411806d --- /dev/null +++ b/Sources/Accord.Video/Accord.Video.cd @@ -0,0 +1,152 @@ + + + + + + + + AAAAAAYAAiACAAyAABAEQAIQCAAAAAAAIQANAIAUAAI= + AsyncVideoSource.cs + + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAABAAAAAAAA= + ByteArrayUtils.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + Exceptions.cs + + + + + + + + AEAALAYACiAKEAsIABCAQAQAAQAAAAEKIUAQAoBAEAI= + JPEGStream.cs + + + + + + + + + AEAAbBYACiACEAsIABSAQAQAAAAAAAAKIQAQAoBAEAI= + MJPEGStream.cs + + + + + + + + + AACABAYAgiACAAkAABAAQAQAAAAAAAAIIUAAAIBAAAI= + ScreenCaptureStream.cs + + + + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAE= + VideoEvents.cs + + + + + + AAAAAAAAAAAgAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAA= + VideoEvents.cs + + + + + + AAAAAAYAAiACAAgAABAAQAAAAAAAAAAAIQAAAIAAAAA= + IVideoSource.cs + + + + + + AAAAAAAAAAACAAAAABAAAAAAAAAgAAAAAAAAAAAIAAA= + VideoEvents.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAABAAAAAAAA= + VideoEvents.cs + + + + + + AAAAAAAAAAAgAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAA= + VideoEvents.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAACAAAA= + VideoEvents.cs + + + + \ No newline at end of file diff --git a/Sources/Accord.Video/Accord.Video.csproj b/Sources/Accord.Video/Accord.Video.csproj new file mode 100644 index 0000000000..98d6eb3d5 --- /dev/null +++ b/Sources/Accord.Video/Accord.Video.csproj @@ -0,0 +1,134 @@ + + + + {809725DC-6502-4732-A51C-DEB7FEA12975} + Accord.Video + Accord.Video + Debug + AnyCPU + AnyCPU + Library + Properties + True + 4 + True + true + Accord.snk + 3.5 + False + true + ..\Accord.NET.ruleset + false + true + 4096 + true + pdbonly + true + + + v4.5 + Full + False + true + False + True + DEBUG;TRACE + $(SolutionDir)..\Debug\ + + + $(SolutionDir)..\Release\net35 + TRACE;CODE_ANALYSIS;NET35 + v3.5 + $(SolutionDir)..\Release\net35\Accord.Video.XML + $(SolutionDir)..\Release\net35\Accord.Video.dll.CodeAnalysisLog.xml + + + $(SolutionDir)..\Release\net40 + TRACE;CODE_ANALYSIS;NET40 + v4.0 + $(SolutionDir)..\Release\net40\Accord.Video.XML + $(SolutionDir)..\Release\net40\Accord.Video.dll.CodeAnalysisLog.xml + + + $(SolutionDir)..\Release\net45 + TRACE;CODE_ANALYSIS;NET45 + v4.5 + $(SolutionDir)..\Release\net45\Accord.Video.XML + $(SolutionDir)..\Release\net45\Accord.Video.dll.CodeAnalysisLog.xml + + + + + + + + Properties\VersionInfo.cs + + + + + + + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 2.0 %28x86%29 + false + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + true + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + {a177a90c-8207-466a-af70-f2b8452a42ac} + Accord.Core + + + {4959a83d-f78f-439e-80a5-41583eceaac6} + Accord.Imaging + + + {f718e9a8-db62-4785-8c49-4333a60d256a} + Accord.Math + + + + + + + + \ No newline at end of file diff --git a/Sources/Accord.Video/Accord.snk b/Sources/Accord.Video/Accord.snk new file mode 100644 index 0000000000..ed97b4edd Binary files /dev/null and b/Sources/Accord.Video/Accord.snk differ diff --git a/Sources/Accord.Video/AsyncVideoSource.cs b/Sources/Accord.Video/AsyncVideoSource.cs new file mode 100644 index 0000000000..448cb1683 --- /dev/null +++ b/Sources/Accord.Video/AsyncVideoSource.cs @@ -0,0 +1,474 @@ +// AForge Video Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Video +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + using System.Threading; + + /// + /// Proxy video source for asynchronous processing of another nested video source. + /// + /// + /// The class represents a simple proxy, which wraps the specified + /// with the aim of asynchronous processing of received video frames. The class intercepts + /// event from the nested video source and fires it to clients from its own thread, which is different from the thread + /// used by nested video source for video acquisition. This allows clients to perform processing of video frames + /// without blocking video acquisition thread, which continue to run and acquire next video frame while current is still + /// processed. + /// + /// For example, let’s suppose that it takes 100 ms for the nested video source to acquire single frame, so the original + /// frame rate is 10 frames per second. Also let’s assume that we have an image processing routine, which also takes + /// 100 ms to process a single frame. If the acquisition and processing are done sequentially, then resulting + /// frame rate will drop to 5 frames per second. However, if doing both in parallel, then there is a good chance to + /// keep resulting frame rate equal (or close) to the original frame rate. + /// + /// The class provides a bonus side effect - easer debugging of image processing routines, which are put into + /// event handler. In many cases video source classes fire their + /// event from a try/catch block, which makes it very hard to spot error made in user's code - the catch block simply + /// hides exception raised in user’s code. The does not have any try/catch blocks around + /// firing of event, so always user gets exception in the case it comes from his code. At the same time + /// nested video source is not affected by the user's exception, since it runs in different thread. + /// + /// Sample usage: + /// + /// // usage of AsyncVideoSource is the same as usage of any + /// // other video source class, so code change is very little + /// + /// // create nested video source, for example JPEGStream + /// JPEGStream stream = new JPEGStream( "some url" ); + /// // create async video source + /// AsyncVideoSource asyncSource = new AsyncVideoSource( stream ); + /// // set NewFrame event handler + /// asyncSource.NewFrame += new NewFrameEventHandler( video_NewFrame ); + /// // start the video source + /// asyncSource.Start( ); + /// // ... + /// + /// private void video_NewFrame( object sender, NewFrameEventArgs eventArgs ) + /// { + /// // get new frame + /// Bitmap bitmap = eventArgs.Frame; + /// // process the frame + /// } + /// + /// + /// + public class AsyncVideoSource : IVideoSource + { + private readonly IVideoSource nestedVideoSource = null; + private Bitmap lastVideoFrame = null; + + private Thread imageProcessingThread = null; + private AutoResetEvent isNewFrameAvailable = null; + private AutoResetEvent isProcessingThreadAvailable = null; + + // skip frames or not in the case if processing thread is busy + private bool skipFramesIfBusy = false; + // processed frames count + private int framesProcessed; + + /// + /// New frame event. + /// + /// + /// Notifies clients about new available frame from video source. + /// + /// This event is fired from a different thread other than the video acquisition thread created + /// by . This allows nested video frame to continue acquisition of the next + /// video frame while clients perform processing of the current video frame. + /// + /// Since video source may have multiple clients, each client is responsible for + /// making a copy (cloning) of the passed video frame, because the video source disposes its + /// own original copy after notifying of clients. + /// + /// + public event NewFrameEventHandler NewFrame; + + /// + /// Video source error event. + /// + /// + /// This event is used to notify clients about any type of errors occurred in + /// video source object, for example internal exceptions. + /// + /// Unlike event, this event is simply redirected to the corresponding + /// event of the , so it is fired from the thread of the nested video source. + /// + /// + public event VideoSourceErrorEventHandler VideoSourceError + { + add { nestedVideoSource.VideoSourceError += value; } + remove { nestedVideoSource.VideoSourceError -= value; } + } + + /// + /// Video playing finished event. + /// + /// + /// This event is used to notify clients that the video playing has finished. + /// + /// Unlike event, this event is simply redirected to the corresponding + /// event of the , so it is fired from the thread of the nested video source. + /// + /// + public event PlayingFinishedEventHandler PlayingFinished + { + add { nestedVideoSource.PlayingFinished += value; } + remove { nestedVideoSource.PlayingFinished -= value; } + } + + /// + /// Nested video source which is the target for asynchronous processing. + /// + /// + /// The property is set through the class constructor. + /// + /// All calls to this object are actually redirected to the nested video source. The only + /// exception is the event, which is handled differently. This object gets + /// event from the nested class and then fires another + /// event, but from a different thread. + /// + /// + public IVideoSource NestedVideoSource + { + get { return nestedVideoSource; } + } + + /// + /// Specifies if the object should skip frames from the nested video source when it is busy. + /// + /// + /// Specifies if the object should skip frames from the nested video source + /// in the case if it is still busy processing the previous video frame in its own thread. + /// + /// Default value is set to . + /// + public bool SkipFramesIfBusy + { + get { return skipFramesIfBusy; } + set { skipFramesIfBusy = value; } + } + + /// + /// Video source string. + /// + /// + /// The property is redirected to the corresponding property of , + /// so check its documentation to find what it means. + /// + public string Source + { + get { return nestedVideoSource.Source; } + } + + /// + /// Received frames count. + /// + /// + /// Number of frames the nested video source received from + /// the moment of the last access to the property. + /// + /// + public int FramesReceived + { + get { return nestedVideoSource.FramesReceived; } + } + + /// + /// Received bytes count. + /// + /// + /// Number of bytes the nested video source received from + /// the moment of the last access to the property. + /// + public long BytesReceived + { + get { return nestedVideoSource.BytesReceived; } + } + + /// + /// Processed frames count. + /// + /// + /// The property keeps the number of processed video frames since the last access to this property. + /// + /// + /// The value of this property equals to in most cases if the + /// property is set to - every received frame gets processed + /// sooner or later. However, if the property is set to , + /// then value of this property may be lower than the value of the property, which + /// means that nested video source performs acquisition faster than client perform processing of the received frame + /// and some frame are skipped from processing. + /// + /// + public int FramesProcessed + { + get + { + int frames = framesProcessed; + framesProcessed = 0; + return frames; + } + } + + /// + /// State of the video source. + /// + /// + /// Current state of the video source object - running or not. + /// + public bool IsRunning + { + get + { + bool isRunning = nestedVideoSource.IsRunning; + + if ( !isRunning ) + { + Free( ); + } + + return isRunning; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Nested video source which is the target for asynchronous processing. + /// + public AsyncVideoSource( IVideoSource nestedVideoSource ) + { + this.nestedVideoSource = nestedVideoSource; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Nested video source which is the target for asynchronous processing. + /// Specifies if the object should skip frames from the nested video source + /// in the case if it is still busy processing the previous video frame. + /// + public AsyncVideoSource( IVideoSource nestedVideoSource, bool skipFramesIfBusy ) + { + this.nestedVideoSource = nestedVideoSource; + this.skipFramesIfBusy = skipFramesIfBusy; + } + + /// + /// Start video source. + /// + /// + /// Starts the nested video source and returns execution to caller. This object creates + /// an extra thread which is used to fire events, so the image processing could be + /// done on another thread without blocking video acquisition thread. + /// + public void Start( ) + { + if ( !IsRunning ) + { + framesProcessed = 0; + + // create all synchronization events + isNewFrameAvailable = new AutoResetEvent( false ); + isProcessingThreadAvailable = new AutoResetEvent( true ); + + // create image processing thread + imageProcessingThread = new Thread( new ThreadStart( imageProcessingThread_Worker ) ); + imageProcessingThread.Start( ); + + // start the nested video source + nestedVideoSource.NewFrame += new NewFrameEventHandler( nestedVideoSource_NewFrame ); + nestedVideoSource.Start( ); + } + } + + /// + /// Signal video source to stop its work. + /// + /// + /// Signals video source to stop its background thread, stop to + /// provide new frames and free resources. + /// + public void SignalToStop( ) + { + nestedVideoSource.SignalToStop( ); + Free( ); + } + + /// + /// Wait for video source has stopped. + /// + /// + /// Waits for video source stopping after it was signalled to stop using + /// method. + /// + public void WaitForStop( ) + { + nestedVideoSource.WaitForStop( ); + Free( ); + } + + /// + /// Stop video source. + /// + /// + /// Stops nested video source by calling its method. + /// See documentation of the particular video source for additional details. + /// + public void Stop( ) + { + nestedVideoSource.Stop( ); + Free( ); + } + + private void Free( ) + { + if ( imageProcessingThread != null ) + { + nestedVideoSource.NewFrame -= new NewFrameEventHandler( nestedVideoSource_NewFrame ); + + // make sure processing thread does nothing + isProcessingThreadAvailable.WaitOne( ); + // signal worker thread to stop and wait for it + lastVideoFrame = null; + isNewFrameAvailable.Set( ); + imageProcessingThread.Join( ); + imageProcessingThread = null; + + // release events + isNewFrameAvailable.Close( ); + isNewFrameAvailable = null; + + isProcessingThreadAvailable.Close( ); + isProcessingThreadAvailable = null; + } + } + + // New frame from nested video source + private void nestedVideoSource_NewFrame( object sender, NewFrameEventArgs eventArgs ) + { + // don't even try doing something if there are no clients + if ( NewFrame == null ) + return; + + if ( skipFramesIfBusy ) + { + if ( !isProcessingThreadAvailable.WaitOne( 0, false ) ) + { + // return in the case if image processing thread is still busy and + // we are allowed to skip frames + return; + } + } + else + { + // make sure image processing thread is available in the case we cannot skip frames + isProcessingThreadAvailable.WaitOne( ); + } + + // pass the image to processing frame and exit + lastVideoFrame = CloneImage( eventArgs.Frame ); + isNewFrameAvailable.Set( ); + } + + private void imageProcessingThread_Worker( ) + { + while ( true ) + { + // wait for new frame to process + isNewFrameAvailable.WaitOne( ); + + // if it is null, then we need to exit + if ( lastVideoFrame == null ) + { + break; + } + + if ( NewFrame != null ) + { + NewFrame( this, new NewFrameEventArgs( lastVideoFrame ) ); + } + + lastVideoFrame.Dispose( ); + lastVideoFrame = null; + framesProcessed++; + + // we are free now for new image + isProcessingThreadAvailable.Set( ); + } + } + + // Note: image cloning is taken from AForge.Imaging.Image.Clone() to avoid reference, + // which may be unwanted + + private static Bitmap CloneImage( Bitmap source ) + { + // lock source bitmap data + BitmapData sourceData = source.LockBits( + new Rectangle( 0, 0, source.Width, source.Height ), + ImageLockMode.ReadOnly, source.PixelFormat ); + + // create new image + Bitmap destination = CloneImage( sourceData ); + + // unlock source image + source.UnlockBits( sourceData ); + + // + if ( + ( source.PixelFormat == PixelFormat.Format1bppIndexed ) || + ( source.PixelFormat == PixelFormat.Format4bppIndexed ) || + ( source.PixelFormat == PixelFormat.Format8bppIndexed ) || + ( source.PixelFormat == PixelFormat.Indexed ) ) + { + ColorPalette srcPalette = source.Palette; + ColorPalette dstPalette = destination.Palette; + + int n = srcPalette.Entries.Length; + + // copy pallete + for ( int i = 0; i < n; i++ ) + { + dstPalette.Entries[i] = srcPalette.Entries[i]; + } + + destination.Palette = dstPalette; + } + + return destination; + } + + private static Bitmap CloneImage( BitmapData sourceData ) + { + // get source image size + int width = sourceData.Width; + int height = sourceData.Height; + + // create new image + Bitmap destination = new Bitmap( width, height, sourceData.PixelFormat ); + + // lock destination bitmap data + BitmapData destinationData = destination.LockBits( + new Rectangle( 0, 0, width, height ), + ImageLockMode.ReadWrite, destination.PixelFormat ); + + AForge.SystemTools.CopyUnmanagedMemory( destinationData.Scan0, sourceData.Scan0, height * sourceData.Stride ); + + // unlock destination image + destination.UnlockBits( destinationData ); + + return destination; + } + } +} diff --git a/Sources/Accord.Video/ByteArrayUtils.cs b/Sources/Accord.Video/ByteArrayUtils.cs new file mode 100644 index 0000000000..50e612e71 --- /dev/null +++ b/Sources/Accord.Video/ByteArrayUtils.cs @@ -0,0 +1,91 @@ +// AForge Video Library +// AForge.NET framework +// +// Copyright Andrew Kirillov, 2007-2008 +// andrew.kirillov@gmail.com +// + +namespace AForge.Video +{ + using System; + + /// + /// Some internal utilities for handling arrays. + /// + /// + internal static class ByteArrayUtils + { + /// + /// Check if the array contains needle at specified position. + /// + /// + /// Source array to check for needle. + /// Needle we are searching for. + /// Start index in source array. + /// + /// Returns true if the source array contains the needle at + /// the specified index. Otherwise it returns false. + /// + public static bool Compare( byte[] array, byte[] needle, int startIndex ) + { + int needleLen = needle.Length; + // compare + for ( int i = 0, p = startIndex; i < needleLen; i++, p++ ) + { + if ( array[p] != needle[i] ) + { + return false; + } + } + return true; + } + + /// + /// Find subarray in the source array. + /// + /// + /// Source array to search for needle. + /// Needle we are searching for. + /// Start index in source array. + /// Number of bytes in source array, where the needle is searched for. + /// + /// Returns starting position of the needle if it was found or -1 otherwise. + /// + public static int Find( byte[] array, byte[] needle, int startIndex, int sourceLength ) + { + int needleLen = needle.Length; + int index; + + while ( sourceLength >= needleLen ) + { + // find needle's starting element + index = Array.IndexOf( array, needle[0], startIndex, sourceLength - needleLen + 1 ); + + // if we did not find even the first element of the needls, then the search is failed + if ( index == -1 ) + return -1; + + int i, p; + // check for needle + for ( i = 0, p = index; i < needleLen; i++, p++ ) + { + if ( array[p] != needle[i] ) + { + break; + } + } + + if ( i == needleLen ) + { + // needle was found + return index; + } + + // continue to search for needle + sourceLength -= ( index - startIndex + 1 ); + startIndex = index + 1; + } + return -1; + } + } +} diff --git a/Sources/Accord.Video/Exceptions.cs b/Sources/Accord.Video/Exceptions.cs new file mode 100644 index 0000000000..c0219d4e5 --- /dev/null +++ b/Sources/Accord.Video/Exceptions.cs @@ -0,0 +1,31 @@ +// AForge Video Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Video +{ + using System; + + /// + /// Video related exception. + /// + /// + /// The exception is thrown in the case of some video related issues, like + /// failure of initializing codec, compression, etc. + /// + public class VideoException : Exception + { + /// + /// Initializes a new instance of the class. + /// + /// + /// Exception's message. + /// + public VideoException( string message ) : + base( message ) { } + } +} diff --git a/Sources/Accord.Video/IVideoSource.cs b/Sources/Accord.Video/IVideoSource.cs new file mode 100644 index 0000000000..d6ae3e59c --- /dev/null +++ b/Sources/Accord.Video/IVideoSource.cs @@ -0,0 +1,126 @@ +// AForge Video Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Video +{ + using System; + + /// + /// Video source interface. + /// + /// + /// The interface describes common methods for different type of video sources. + /// + public interface IVideoSource + { + /// + /// New frame event. + /// + /// + /// This event is used to notify clients about new available video frame. + /// + /// Since video source may have multiple clients, each client is responsible for + /// making a copy (cloning) of the passed video frame, but video source is responsible for + /// disposing its own original copy after notifying of clients. + /// + /// + event NewFrameEventHandler NewFrame; + + /// + /// Video source error event. + /// + /// + /// This event is used to notify clients about any type of errors occurred in + /// video source object, for example internal exceptions. + /// + event VideoSourceErrorEventHandler VideoSourceError; + + /// + /// Video playing finished event. + /// + /// + /// This event is used to notify clients that the video playing has finished. + /// + /// + event PlayingFinishedEventHandler PlayingFinished; + + /// + /// Video source. + /// + /// + /// The meaning of the property depends on particular video source. + /// Depending on video source it may be a file name, URL or any other string + /// describing the video source. + /// + string Source { get; } + + /// + /// Received frames count. + /// + /// + /// Number of frames the video source provided from the moment of the last + /// access to the property. + /// + /// + int FramesReceived { get; } + + /// + /// Received bytes count. + /// + /// + /// Number of bytes the video source provided from the moment of the last + /// access to the property. + /// + /// + long BytesReceived { get; } + + /// + /// State of the video source. + /// + /// + /// Current state of video source object - running or not. + /// + bool IsRunning { get; } + + /// + /// Start video source. + /// + /// + /// Starts video source and return execution to caller. Video source + /// object creates background thread and notifies about new frames with the + /// help of event. + /// + void Start( ); + + /// + /// Signal video source to stop its work. + /// + /// + /// Signals video source to stop its background thread, stop to + /// provide new frames and free resources. + /// + void SignalToStop( ); + + /// + /// Wait for video source has stopped. + /// + /// + /// Waits for video source stopping after it was signalled to stop using + /// method. + /// + void WaitForStop( ); + + /// + /// Stop video source. + /// + /// + /// Stops video source aborting its thread. + /// + void Stop( ); + } +} diff --git a/Sources/Accord.Video/JPEGStream.cs b/Sources/Accord.Video/JPEGStream.cs new file mode 100644 index 0000000000..6d85ff28e --- /dev/null +++ b/Sources/Accord.Video/JPEGStream.cs @@ -0,0 +1,587 @@ +// AForge Video Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Video +{ + using System; + using System.Drawing; + using System.IO; + using System.Text; + using System.Threading; + using System.Net; + using System.Security; + + /// + /// JPEG video source. + /// + /// + /// The video source constantly downloads JPEG files from the specified URL. + /// + /// Sample usage: + /// + /// // create JPEG video source + /// JPEGStream stream = new JPEGStream( "some url" ); + /// // set NewFrame event handler + /// stream.NewFrame += new NewFrameEventHandler( video_NewFrame ); + /// // start the video source + /// stream.Start( ); + /// // ... + /// // signal to stop + /// stream.SignalToStop( ); + /// // ... + /// + /// private void video_NewFrame( object sender, NewFrameEventArgs eventArgs ) + /// { + /// // get new frame + /// Bitmap bitmap = eventArgs.Frame; + /// // process the frame + /// } + /// + /// + /// Some cameras produce HTTP header, which does not conform strictly to + /// standard, what leads to .NET exception. To avoid this exception the useUnsafeHeaderParsing + /// configuration option of httpWebRequest should be set, what may be done using application + /// configuration file. + /// + /// <configuration> + /// <system.net> + /// <settings> + /// <httpWebRequest useUnsafeHeaderParsing="true" /> + /// </settings> + /// </system.net> + /// </configuration> + /// + /// + /// + public class JPEGStream : IVideoSource + { + // URL for JPEG files + private string source; + // login and password for HTTP authentication + private string login = null; + private string password = null; + // proxy information + private IWebProxy proxy = null; + // received frames count + private int framesReceived; + // recieved byte count + private long bytesReceived; + // use separate HTTP connection group or use default + private bool useSeparateConnectionGroup = false; + // prevent cashing or not + private bool preventCaching = true; + // frame interval in milliseconds + private int frameInterval = 0; + // timeout value for web request + private int requestTimeout = 10000; + // if we should use basic authentication when connecting to the video source + private bool forceBasicAuthentication = false; + + // buffer size used to download JPEG image + private const int bufferSize = 1024 * 1024; + // size of portion to read at once + private const int readSize = 1024; + + private Thread thread = null; + private ManualResetEvent stopEvent = null; + + /// + /// New frame event. + /// + /// + /// Notifies clients about new available frame from video source. + /// + /// Since video source may have multiple clients, each client is responsible for + /// making a copy (cloning) of the passed video frame, because the video source disposes its + /// own original copy after notifying of clients. + /// + /// + public event NewFrameEventHandler NewFrame; + + /// + /// Video source error event. + /// + /// + /// This event is used to notify clients about any type of errors occurred in + /// video source object, for example internal exceptions. + /// + public event VideoSourceErrorEventHandler VideoSourceError; + + /// + /// Video playing finished event. + /// + /// + /// This event is used to notify clients that the video playing has finished. + /// + /// + public event PlayingFinishedEventHandler PlayingFinished; + + /// + /// Use or not separate connection group. + /// + /// + /// The property indicates to open web request in separate connection group. + /// + public bool SeparateConnectionGroup + { + get { return useSeparateConnectionGroup; } + set { useSeparateConnectionGroup = value; } + } + + /// + /// Use or not caching. + /// + /// + /// If the property is set to true, then a fake random parameter will be added + /// to URL to prevent caching. It's required for clients, who are behind proxy server. + /// + public bool PreventCaching + { + get { return preventCaching; } + set { preventCaching = value; } + } + + /// + /// Frame interval. + /// + /// + /// The property sets the interval in milliseconds betwen frames. If the property is + /// set to 100, then the desired frame rate will be 10 frames per second. Default value is 0 - + /// get new frames as fast as possible. + /// + public int FrameInterval + { + get { return frameInterval; } + set { frameInterval = value; } + } + + /// + /// Video source. + /// + /// + /// URL, which provides JPEG files. + /// + public virtual string Source + { + get { return source; } + set { source = value; } + } + + /// + /// Login value. + /// + /// + /// Login required to access video source. + /// + public string Login + { + get { return login; } + set { login = value; } + } + + /// + /// Password value. + /// + /// + /// Password required to access video source. + /// + public string Password + { + get { return password; } + set { password = value; } + } + + /// + /// Gets or sets proxy information for the request. + /// + /// + /// The local computer or application config file may specify that a default + /// proxy to be used. If the Proxy property is specified, then the proxy settings from the Proxy + /// property overridea the local computer or application config file and the instance will use + /// the proxy settings specified. If no proxy is specified in a config file + /// and the Proxy property is unspecified, the request uses the proxy settings + /// inherited from Internet Explorer on the local computer. If there are no proxy settings + /// in Internet Explorer, the request is sent directly to the server. + /// + /// + public IWebProxy Proxy + { + get { return proxy; } + set { proxy = value; } + } + + /// + /// Received frames count. + /// + /// + /// Number of frames the video source provided from the moment of the last + /// access to the property. + /// + /// + public int FramesReceived + { + get + { + int frames = framesReceived; + framesReceived = 0; + return frames; + } + } + + /// + /// Received bytes count. + /// + /// + /// Number of bytes the video source provided from the moment of the last + /// access to the property. + /// + /// + public long BytesReceived + { + get + { + long bytes = bytesReceived; + bytesReceived = 0; + return bytes; + } + } + + /// + /// Request timeout value. + /// + /// + /// The property sets timeout value in milliseconds for web requests. + /// + /// Default value is set 10000 milliseconds. + /// + public int RequestTimeout + { + get { return requestTimeout; } + set { requestTimeout = value; } + } + + /// + /// State of the video source. + /// + /// + /// Current state of video source object - running or not. + /// + public bool IsRunning + { + get + { + if ( thread != null ) + { + // check thread status + if ( thread.Join( 0 ) == false ) + return true; + + // the thread is not running, free resources + Free( ); + } + return false; + } + } + + /// + /// Force using of basic authentication when connecting to the video source. + /// + /// + /// For some IP cameras (TrendNET IP cameras, for example) using standard .NET's authentication via credentials + /// does not seem to be working (seems like camera does not request for authentication, but expects corresponding headers to be + /// present on connection request). So this property allows to force basic authentication by adding required HTTP headers when + /// request is sent. + /// + /// Default value is set to . + /// + /// + public bool ForceBasicAuthentication + { + get { return forceBasicAuthentication; } + set { forceBasicAuthentication = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public JPEGStream( ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// URL, which provides JPEG files. + /// + public JPEGStream( string source ) + { + this.source = source; + } + + /// + /// Start video source. + /// + /// + /// Starts video source and return execution to caller. Video source + /// object creates background thread and notifies about new frames with the + /// help of event. + /// + /// Video source is not specified. + /// + public void Start( ) + { + if ( !IsRunning ) + { + // check source + if ( ( source == null ) || ( source == string.Empty ) ) + throw new ArgumentException( "Video source is not specified." ); + + framesReceived = 0; + bytesReceived = 0; + + // create events + stopEvent = new ManualResetEvent( false ); + + // create and start new thread + thread = new Thread( new ThreadStart( WorkerThread ) ); + thread.Name = source; // mainly for debugging + thread.Start( ); + } + } + + /// + /// Signal video source to stop its work. + /// + /// + /// Signals video source to stop its background thread, stop to + /// provide new frames and free resources. + /// + public void SignalToStop( ) + { + // stop thread + if ( thread != null ) + { + // signal to stop + stopEvent.Set( ); + } + } + + /// + /// Wait for video source has stopped. + /// + /// + /// Waits for source stopping after it was signalled to stop using + /// method. + /// + public void WaitForStop( ) + { + if ( thread != null ) + { + // wait for thread stop + thread.Join( ); + + Free( ); + } + } + + /// + /// Stop video source. + /// + /// + /// Stops video source aborting its thread. + /// + /// Since the method aborts background thread, its usage is highly not preferred + /// and should be done only if there are no other options. The correct way of stopping camera + /// is signaling it stop and then + /// waiting for background thread's completion. + /// + /// + public void Stop( ) + { + if ( this.IsRunning ) + { + stopEvent.Set( ); + thread.Abort( ); + WaitForStop( ); + } + } + + /// + /// Free resource. + /// + /// + private void Free( ) + { + thread = null; + + // release events + stopEvent.Close( ); + stopEvent = null; + } + + // Worker thread + private void WorkerThread( ) + { + // buffer to read stream + byte[] buffer = new byte[bufferSize]; + // HTTP web request + HttpWebRequest request = null; + // web responce + WebResponse response = null; + // stream for JPEG downloading + Stream stream = null; + // random generator to add fake parameter for cache preventing + Random rand = new Random( (int) DateTime.Now.Ticks ); + // download start time and duration + DateTime start; + TimeSpan span; + + while ( !stopEvent.WaitOne( 0, false ) ) + { + int read, total = 0; + + try + { + // set dowbload start time + start = DateTime.Now; + + // create request + if ( !preventCaching ) + { + // request without cache prevention + request = (HttpWebRequest) WebRequest.Create( source ); + } + else + { + // request with cache prevention + request = (HttpWebRequest) WebRequest.Create( source + ( ( source.IndexOf( '?' ) == -1 ) ? '?' : '&' ) + "fake=" + rand.Next( ).ToString( ) ); + } + + // set proxy + if ( proxy != null ) + { + request.Proxy = proxy; + } + + // set timeout value for the request + request.Timeout = requestTimeout; + // set login and password + if ( ( login != null ) && ( password != null ) && ( login != string.Empty ) ) + request.Credentials = new NetworkCredential( login, password ); + // set connection group name + if ( useSeparateConnectionGroup ) + request.ConnectionGroupName = GetHashCode( ).ToString( ); + // force basic authentication through extra headers if required + if ( forceBasicAuthentication ) + { + string authInfo = string.Format( "{0}:{1}", login, password ); + authInfo = Convert.ToBase64String( Encoding.Default.GetBytes( authInfo ) ); + request.Headers["Authorization"] = "Basic " + authInfo; + } + // get response + response = request.GetResponse( ); + // get response stream + stream = response.GetResponseStream( ); + stream.ReadTimeout = requestTimeout; + + // loop + while ( !stopEvent.WaitOne( 0, false ) ) + { + // check total read + if ( total > bufferSize - readSize ) + { + total = 0; + } + + // read next portion from stream + if ( ( read = stream.Read( buffer, total, readSize ) ) == 0 ) + break; + + total += read; + + // increment received bytes counter + bytesReceived += read; + } + + if ( !stopEvent.WaitOne( 0, false ) ) + { + // increment frames counter + framesReceived++; + + // provide new image to clients + if ( NewFrame != null ) + { + Bitmap bitmap = (Bitmap) Bitmap.FromStream( new MemoryStream( buffer, 0, total ) ); + // notify client + NewFrame( this, new NewFrameEventArgs( bitmap ) ); + // release the image + bitmap.Dispose( ); + bitmap = null; + } + } + + // wait for a while ? + if ( frameInterval > 0 ) + { + // get download duration + span = DateTime.Now.Subtract( start ); + // miliseconds to sleep + int msec = frameInterval - (int) span.TotalMilliseconds; + + if ( ( msec > 0 ) && ( stopEvent.WaitOne( msec, false ) ) ) + break; + } + } + catch ( ThreadAbortException ) + { + break; + } + catch ( Exception exception ) + { + // provide information to clients + if ( VideoSourceError != null ) + { + VideoSourceError( this, new VideoSourceErrorEventArgs( exception.Message ) ); + } + // wait for a while before the next try + Thread.Sleep( 250 ); + } + finally + { + // abort request + if ( request != null) + { + request.Abort( ); + request = null; + } + // close response stream + if ( stream != null ) + { + stream.Close( ); + stream = null; + } + // close response + if ( response != null ) + { + response.Close( ); + response = null; + } + } + + // need to stop ? + if ( stopEvent.WaitOne( 0, false ) ) + break; + } + + if ( PlayingFinished != null ) + { + PlayingFinished( this, ReasonToFinishPlaying.StoppedByUser ); + } + } + } +} diff --git a/Sources/Accord.Video/MJPEGStream.cs b/Sources/Accord.Video/MJPEGStream.cs new file mode 100644 index 0000000000..612533a97 --- /dev/null +++ b/Sources/Accord.Video/MJPEGStream.cs @@ -0,0 +1,704 @@ +// AForge Video Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Video +{ + using System; + using System.Drawing; + using System.IO; + using System.Text; + using System.Threading; + using System.Net; + using System.Security; + + /// + /// MJPEG video source. + /// + /// + /// The video source downloads JPEG images from the specified URL, which represents + /// MJPEG stream. + /// + /// Sample usage: + /// + /// // create MJPEG video source + /// MJPEGStream stream = new MJPEGStream( "some url" ); + /// // set event handlers + /// stream.NewFrame += new NewFrameEventHandler( video_NewFrame ); + /// // start the video source + /// stream.Start( ); + /// // ... + /// + /// + /// Some cameras produce HTTP header, which does not conform strictly to + /// standard, what leads to .NET exception. To avoid this exception the useUnsafeHeaderParsing + /// configuration option of httpWebRequest should be set, what may be done using application + /// configuration file. + /// + /// <configuration> + /// <system.net> + /// <settings> + /// <httpWebRequest useUnsafeHeaderParsing="true" /> + /// </settings> + /// </system.net> + /// </configuration> + /// + /// + /// + public class MJPEGStream : IVideoSource + { + // URL for MJPEG stream + private string source; + // login and password for HTTP authentication + private string login = null; + private string password = null; + // proxy information + private IWebProxy proxy = null; + // received frames count + private int framesReceived; + // recieved byte count + private long bytesReceived; + // use separate HTTP connection group or use default + private bool useSeparateConnectionGroup = true; + // timeout value for web request + private int requestTimeout = 10000; + // if we should use basic authentication when connecting to the video source + private bool forceBasicAuthentication = false; + + // buffer size used to download MJPEG stream + private const int bufSize = 1024 * 1024; + // size of portion to read at once + private const int readSize = 1024; + + private Thread thread = null; + private ManualResetEvent stopEvent = null; + private ManualResetEvent reloadEvent = null; + + private string userAgent = "Mozilla/5.0"; + + /// + /// New frame event. + /// + /// + /// Notifies clients about new available frame from video source. + /// + /// Since video source may have multiple clients, each client is responsible for + /// making a copy (cloning) of the passed video frame, because the video source disposes its + /// own original copy after notifying of clients. + /// + /// + public event NewFrameEventHandler NewFrame; + + /// + /// Video source error event. + /// + /// + /// This event is used to notify clients about any type of errors occurred in + /// video source object, for example internal exceptions. + /// + public event VideoSourceErrorEventHandler VideoSourceError; + + /// + /// Video playing finished event. + /// + /// + /// This event is used to notify clients that the video playing has finished. + /// + /// + public event PlayingFinishedEventHandler PlayingFinished; + + /// + /// Use or not separate connection group. + /// + /// + /// The property indicates to open web request in separate connection group. + /// + public bool SeparateConnectionGroup + { + get { return useSeparateConnectionGroup; } + set { useSeparateConnectionGroup = value; } + } + + /// + /// Video source. + /// + /// + /// URL, which provides MJPEG stream. + /// + public string Source + { + get { return source; } + set + { + source = value; + // signal to reload + if ( thread != null ) + reloadEvent.Set( ); + } + } + + /// + /// Login value. + /// + /// + /// Login required to access video source. + /// + public string Login + { + get { return login; } + set { login = value; } + } + + /// + /// Password value. + /// + /// + /// Password required to access video source. + /// + public string Password + { + get { return password; } + set { password = value; } + } + + /// + /// Gets or sets proxy information for the request. + /// + /// + /// The local computer or application config file may specify that a default + /// proxy to be used. If the Proxy property is specified, then the proxy settings from the Proxy + /// property overridea the local computer or application config file and the instance will use + /// the proxy settings specified. If no proxy is specified in a config file + /// and the Proxy property is unspecified, the request uses the proxy settings + /// inherited from Internet Explorer on the local computer. If there are no proxy settings + /// in Internet Explorer, the request is sent directly to the server. + /// + /// + public IWebProxy Proxy + { + get { return proxy; } + set { proxy = value; } + } + + /// + /// User agent to specify in HTTP request header. + /// + /// + /// Some IP cameras check what is the requesting user agent and depending + /// on it they provide video in different formats or do not provide it at all. The property + /// sets the value of user agent string, which is sent to camera in request header. + /// + /// + /// Default value is set to "Mozilla/5.0". If the value is set to , + /// the user agent string is not sent in request header. + /// + /// + public string HttpUserAgent + { + get { return userAgent; } + set { userAgent = value; } + } + + /// + /// Received frames count. + /// + /// + /// Number of frames the video source provided from the moment of the last + /// access to the property. + /// + /// + public int FramesReceived + { + get + { + int frames = framesReceived; + framesReceived = 0; + return frames; + } + } + + /// + /// Received bytes count. + /// + /// + /// Number of bytes the video source provided from the moment of the last + /// access to the property. + /// + /// + public long BytesReceived + { + get + { + long bytes = bytesReceived; + bytesReceived = 0; + return bytes; + } + } + + /// + /// Request timeout value. + /// + /// + /// The property sets timeout value in milliseconds for web requests. + /// Default value is 10000 milliseconds. + /// + public int RequestTimeout + { + get { return requestTimeout; } + set { requestTimeout = value; } + } + + /// + /// State of the video source. + /// + /// + /// Current state of video source object - running or not. + /// + public bool IsRunning + { + get + { + if ( thread != null ) + { + // check thread status + if ( thread.Join( 0 ) == false ) + return true; + + // the thread is not running, so free resources + Free( ); + } + return false; + } + } + + /// + /// Force using of basic authentication when connecting to the video source. + /// + /// + /// For some IP cameras (TrendNET IP cameras, for example) using standard .NET's authentication via credentials + /// does not seem to be working (seems like camera does not request for authentication, but expects corresponding headers to be + /// present on connection request). So this property allows to force basic authentication by adding required HTTP headers when + /// request is sent. + /// + /// Default value is set to . + /// + /// + public bool ForceBasicAuthentication + { + get { return forceBasicAuthentication; } + set { forceBasicAuthentication = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public MJPEGStream( ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// URL, which provides MJPEG stream. + /// + public MJPEGStream( string source ) + { + this.source = source; + } + + /// + /// Start video source. + /// + /// + /// Starts video source and return execution to caller. Video source + /// object creates background thread and notifies about new frames with the + /// help of event. + /// + /// Video source is not specified. + /// + public void Start( ) + { + if ( !IsRunning ) + { + // check source + if ( ( source == null ) || ( source == string.Empty ) ) + throw new ArgumentException( "Video source is not specified." ); + + framesReceived = 0; + bytesReceived = 0; + + // create events + stopEvent = new ManualResetEvent( false ); + reloadEvent = new ManualResetEvent( false ); + + // create and start new thread + thread = new Thread( new ThreadStart( WorkerThread ) ); + thread.Name = source; + thread.Start( ); + } + } + + /// + /// Signal video source to stop its work. + /// + /// + /// Signals video source to stop its background thread, stop to + /// provide new frames and free resources. + /// + public void SignalToStop( ) + { + // stop thread + if ( thread != null ) + { + // signal to stop + stopEvent.Set( ); + } + } + + /// + /// Wait for video source has stopped. + /// + /// + /// Waits for source stopping after it was signalled to stop using + /// method. + /// + public void WaitForStop( ) + { + if ( thread != null ) + { + // wait for thread stop + thread.Join( ); + + Free( ); + } + } + + /// + /// Stop video source. + /// + /// + /// Stops video source aborting its thread. + /// + /// Since the method aborts background thread, its usage is highly not preferred + /// and should be done only if there are no other options. The correct way of stopping camera + /// is signaling it stop and then + /// waiting for background thread's completion. + /// + /// + public void Stop( ) + { + if ( this.IsRunning ) + { + stopEvent.Set( ); + thread.Abort( ); + WaitForStop( ); + } + } + + /// + /// Free resource. + /// + /// + private void Free( ) + { + thread = null; + + // release events + stopEvent.Close( ); + stopEvent = null; + reloadEvent.Close( ); + reloadEvent = null; + } + + // Worker thread + private void WorkerThread( ) + { + // buffer to read stream + byte[] buffer = new byte[bufSize]; + // JPEG magic number + byte[] jpegMagic = new byte[] { 0xFF, 0xD8, 0xFF }; + int jpegMagicLength = 3; + + ASCIIEncoding encoding = new ASCIIEncoding( ); + + while ( !stopEvent.WaitOne( 0, false ) ) + { + // reset reload event + reloadEvent.Reset( ); + + // HTTP web request + HttpWebRequest request = null; + // web responce + WebResponse response = null; + // stream for MJPEG downloading + Stream stream = null; + // boundary betweeen images (string and binary versions) + byte[] boundary = null; + string boudaryStr = null; + // length of boundary + int boundaryLen; + // flag signaling if boundary was checked or not + bool boundaryIsChecked = false; + // read amounts and positions + int read, todo = 0, total = 0, pos = 0, align = 1; + int start = 0, stop = 0; + + // align + // 1 = searching for image start + // 2 = searching for image end + + try + { + // create request + request = (HttpWebRequest) WebRequest.Create( source ); + // set user agent + if ( userAgent != null ) + { + request.UserAgent = userAgent; + } + + // set proxy + if ( proxy != null ) + { + request.Proxy = proxy; + } + + // set timeout value for the request + request.Timeout = requestTimeout; + // set login and password + if ( ( login != null ) && ( password != null ) && ( login != string.Empty ) ) + request.Credentials = new NetworkCredential( login, password ); + // set connection group name + if ( useSeparateConnectionGroup ) + request.ConnectionGroupName = GetHashCode( ).ToString( ); + // force basic authentication through extra headers if required + if ( forceBasicAuthentication ) + { + string authInfo = string.Format( "{0}:{1}", login, password ); + authInfo = Convert.ToBase64String( Encoding.Default.GetBytes( authInfo ) ); + request.Headers["Authorization"] = "Basic " + authInfo; + } + // get response + response = request.GetResponse( ); + + // check content type + string contentType = response.ContentType; + string[] contentTypeArray = contentType.Split( '/' ); + + // "application/octet-stream" + if ( ( contentTypeArray[0] == "application" ) && ( contentTypeArray[1] == "octet-stream" ) ) + { + boundaryLen = 0; + boundary = new byte[0]; + } + else if ( ( contentTypeArray[0] == "multipart" ) && ( contentType.Contains( "mixed" ) ) ) + { + // get boundary + int boundaryIndex = contentType.IndexOf( "boundary", 0 ); + if ( boundaryIndex != -1 ) + { + boundaryIndex = contentType.IndexOf( "=", boundaryIndex + 8 ); + } + + if ( boundaryIndex == -1 ) + { + // try same scenario as with octet-stream, i.e. without boundaries + boundaryLen = 0; + boundary = new byte[0]; + } + else + { + boudaryStr = contentType.Substring( boundaryIndex + 1 ); + // remove spaces and double quotes, which may be added by some IP cameras + boudaryStr = boudaryStr.Trim( ' ', '"' ); + + boundary = encoding.GetBytes( boudaryStr ); + boundaryLen = boundary.Length; + boundaryIsChecked = false; + } + } + else + { + throw new Exception( "Invalid content type." ); + } + + // get response stream + stream = response.GetResponseStream( ); + stream.ReadTimeout = requestTimeout; + + // loop + while ( ( !stopEvent.WaitOne( 0, false ) ) && ( !reloadEvent.WaitOne( 0, false ) ) ) + { + // check total read + if ( total > bufSize - readSize ) + { + total = pos = todo = 0; + } + + // read next portion from stream + if ( ( read = stream.Read( buffer, total, readSize ) ) == 0 ) + throw new ApplicationException( ); + + total += read; + todo += read; + + // increment received bytes counter + bytesReceived += read; + + // do we need to check boundary ? + if ( ( boundaryLen != 0 ) && ( !boundaryIsChecked ) ) + { + // some IP cameras, like AirLink, claim that boundary is "myboundary", + // when it is really "--myboundary". this needs to be corrected. + + pos = ByteArrayUtils.Find( buffer, boundary, 0, todo ); + // continue reading if boudary was not found + if ( pos == -1 ) + continue; + + for ( int i = pos - 1; i >= 0; i-- ) + { + byte ch = buffer[i]; + + if ( ( ch == (byte) '\n' ) || ( ch == (byte) '\r' ) ) + { + break; + } + + boudaryStr = (char) ch + boudaryStr; + } + + boundary = encoding.GetBytes( boudaryStr ); + boundaryLen = boundary.Length; + boundaryIsChecked = true; + } + + // search for image start + if ( ( align == 1 ) && ( todo >= jpegMagicLength ) ) + { + start = ByteArrayUtils.Find( buffer, jpegMagic, pos, todo ); + if ( start != -1 ) + { + // found JPEG start + pos = start + jpegMagicLength; + todo = total - pos; + align = 2; + } + else + { + // delimiter not found + todo = jpegMagicLength - 1; + pos = total - todo; + } + } + + // search for image end ( boundaryLen can be 0, so need extra check ) + while ( ( align == 2 ) && ( todo != 0 ) && ( todo >= boundaryLen ) ) + { + stop = ByteArrayUtils.Find( buffer, + ( boundaryLen != 0 ) ? boundary : jpegMagic, + pos, todo ); + + if ( stop != -1 ) + { + pos = stop; + todo = total - pos; + + // increment frames counter + framesReceived ++; + + // image at stop + if ( ( NewFrame != null ) && ( !stopEvent.WaitOne( 0, false ) ) ) + { + Bitmap bitmap = (Bitmap) Bitmap.FromStream ( new MemoryStream( buffer, start, stop - start ) ); + // notify client + NewFrame( this, new NewFrameEventArgs( bitmap ) ); + // release the image + bitmap.Dispose( ); + bitmap = null; + } + + // shift array + pos = stop + boundaryLen; + todo = total - pos; + Array.Copy( buffer, pos, buffer, 0, todo ); + + total = todo; + pos = 0; + align = 1; + } + else + { + // boundary not found + if ( boundaryLen != 0 ) + { + todo = boundaryLen - 1; + pos = total - todo; + } + else + { + todo = 0; + pos = total; + } + } + } + } + } + catch ( ApplicationException ) + { + // do nothing for Application Exception, which we raised on our own + // wait for a while before the next try + Thread.Sleep( 250 ); + } + catch ( ThreadAbortException ) + { + break; + } + catch ( Exception exception ) + { + // provide information to clients + if ( VideoSourceError != null ) + { + VideoSourceError( this, new VideoSourceErrorEventArgs( exception.Message ) ); + } + // wait for a while before the next try + Thread.Sleep( 250 ); + } + finally + { + // abort request + if ( request != null) + { + request.Abort( ); + request = null; + } + // close response stream + if ( stream != null ) + { + stream.Close( ); + stream = null; + } + // close response + if ( response != null ) + { + response.Close( ); + response = null; + } + } + + // need to stop ? + if ( stopEvent.WaitOne( 0, false ) ) + break; + } + + if ( PlayingFinished != null ) + { + PlayingFinished( this, ReasonToFinishPlaying.StoppedByUser ); + } + } + } +} diff --git a/Sources/Accord.Video/Properties/AssemblyInfo.cs b/Sources/Accord.Video/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..cf19cb0a8 --- /dev/null +++ b/Sources/Accord.Video/Properties/AssemblyInfo.cs @@ -0,0 +1,13 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Accord.Video")] +[assembly: AssemblyDescription("Accord.NET - Video Library")] +[assembly: AssemblyConfiguration("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. +[assembly: ComVisible(false)] diff --git a/Sources/Accord.Video/ScreenCaptureStream.cs b/Sources/Accord.Video/ScreenCaptureStream.cs new file mode 100644 index 0000000000..d4a007780 --- /dev/null +++ b/Sources/Accord.Video/ScreenCaptureStream.cs @@ -0,0 +1,396 @@ +// AForge Video Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2012 +// contacts@aforgenet.com +// +// Copyright © César Souza, 2012 +// cesarsouza@gmail.com +// + +namespace AForge.Video +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + using System.Threading; + + /// + /// Screen capture video source. + /// + /// + /// The video source constantly captures the desktop screen. + /// + /// Sample usage: + /// + /// // get entire desktop area size + /// Rectangle screenArea = Rectangle.Empty; + /// foreach ( System.Windows.Forms.Screen screen in + /// System.Windows.Forms.Screen.AllScreens ) + /// { + /// screenArea = Rectangle.Union( screenArea, screen.Bounds ); + /// } + /// + /// // create screen capture video source + /// ScreenCaptureStream stream = new ScreenCaptureStream( screenArea ); + /// + /// // set NewFrame event handler + /// stream.NewFrame += new NewFrameEventHandler( video_NewFrame ); + /// + /// // start the video source + /// stream.Start( ); + /// + /// // ... + /// // signal to stop + /// stream.SignalToStop( ); + /// // ... + /// + /// private void video_NewFrame( object sender, NewFrameEventArgs eventArgs ) + /// { + /// // get new frame + /// Bitmap bitmap = eventArgs.Frame; + /// // process the frame + /// } + /// + /// + /// + public class ScreenCaptureStream : IVideoSource + { + private Rectangle region; + + // frame interval in milliseconds + private int frameInterval = 100; + // received frames count + private int framesReceived; + + private Thread thread = null; + private ManualResetEvent stopEvent = null; + + /// + /// New frame event. + /// + /// + /// Notifies clients about new available frame from video source. + /// + /// Since video source may have multiple clients, each client is responsible for + /// making a copy (cloning) of the passed video frame, because the video source disposes its + /// own original copy after notifying of clients. + /// + /// + public event NewFrameEventHandler NewFrame; + + /// + /// Video source error event. + /// + /// + /// This event is used to notify clients about any type of errors occurred in + /// video source object, for example internal exceptions. + /// + public event VideoSourceErrorEventHandler VideoSourceError; + + /// + /// Video playing finished event. + /// + /// + /// This event is used to notify clients that the video playing has finished. + /// + /// + public event PlayingFinishedEventHandler PlayingFinished; + + /// + /// Video source. + /// + /// + public virtual string Source + { + get { return "Screen Capture"; } + } + + /// + /// Gets or sets the screen capture region. + /// + /// + /// This property specifies which region (rectangle) of the screen to capture. It may cover multiple displays + /// if those are available in the system. + /// + /// The property must be set before starting video source to have any effect. + /// + /// + public Rectangle Region + { + get { return region; } + set { region = value; } + } + + /// + /// Time interval between making screen shots, ms. + /// + /// + /// The property specifies time interval in milliseconds between consequent screen captures. + /// Expected frame rate of the stream should be approximately 1000/FrameInteval. + /// + /// If the property is set to 0, then the stream will capture screen as fast as the system allows. + /// + /// Default value is set to 100. + /// + /// + public int FrameInterval + { + get { return frameInterval; } + set { frameInterval = Math.Max( 0, value ); } + } + + /// + /// Received frames count. + /// + /// + /// Number of frames the video source provided from the moment of the last + /// access to the property. + /// + /// + public int FramesReceived + { + get + { + int frames = framesReceived; + framesReceived = 0; + return frames; + } + } + + /// + /// Received bytes count. + /// + /// + /// The property is not implemented for this video source and always returns 0. + /// + /// + public long BytesReceived + { + get { return 0; } + } + + /// + /// State of the video source. + /// + /// + /// Current state of video source object - running or not. + /// + public bool IsRunning + { + get + { + if ( thread != null ) + { + // check thread status + if ( thread.Join( 0 ) == false ) + return true; + + // the thread is not running, free resources + Free( ); + } + return false; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Screen's rectangle to capture (the rectangle may cover multiple displays). + /// + public ScreenCaptureStream( Rectangle region ) + { + this.region = region; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Screen's rectangle to capture (the rectangle may cover multiple displays). + /// Time interval between making screen shots, ms. + /// + public ScreenCaptureStream( Rectangle region, int frameInterval ) + { + this.region = region; + this.FrameInterval = frameInterval; + } + + /// + /// Start video source. + /// + /// + /// Starts video source and return execution to caller. Video source + /// object creates background thread and notifies about new frames with the + /// help of event. + /// + /// Video source is not specified. + /// + public void Start( ) + { + if ( !IsRunning ) + { + framesReceived = 0; + + // create events + stopEvent = new ManualResetEvent( false ); + + // create and start new thread + thread = new Thread( new ThreadStart( WorkerThread ) ); + thread.Name = Source; // mainly for debugging + thread.Start( ); + } + } + + /// + /// Signal video source to stop its work. + /// + /// + /// Signals video source to stop its background thread, stop to + /// provide new frames and free resources. + /// + public void SignalToStop( ) + { + // stop thread + if ( thread != null ) + { + // signal to stop + stopEvent.Set( ); + } + } + + /// + /// Wait for video source has stopped. + /// + /// + /// Waits for source stopping after it was signalled to stop using + /// method. + /// + public void WaitForStop( ) + { + if ( thread != null ) + { + // wait for thread stop + thread.Join( ); + + Free( ); + } + } + + /// + /// Stop video source. + /// + /// + /// Stops video source aborting its thread. + /// + /// Since the method aborts background thread, its usage is highly not preferred + /// and should be done only if there are no other options. The correct way of stopping camera + /// is signaling it stop and then + /// waiting for background thread's completion. + /// + /// + public void Stop( ) + { + if ( this.IsRunning ) + { + stopEvent.Set( ); + thread.Abort( ); + WaitForStop( ); + } + } + + /// + /// Free resource. + /// + /// + private void Free( ) + { + thread = null; + + // release events + stopEvent.Close( ); + stopEvent = null; + } + + // Worker thread + private void WorkerThread( ) + { + int width = region.Width; + int height = region.Height; + int x = region.Location.X; + int y = region.Location.Y; + Size size = region.Size; + + Bitmap bitmap = new Bitmap( width, height, PixelFormat.Format32bppArgb ); + Graphics graphics = Graphics.FromImage( bitmap ); + + // download start time and duration + DateTime start; + TimeSpan span; + + while ( !stopEvent.WaitOne( 0, false ) ) + { + // set dowbload start time + start = DateTime.Now; + + try + { + // capture the screen + graphics.CopyFromScreen( x, y, 0, 0, size, CopyPixelOperation.SourceCopy ); + + // increment frames counter + framesReceived++; + + // provide new image to clients + if ( NewFrame != null ) + { + // notify client + NewFrame( this, new NewFrameEventArgs( bitmap ) ); + } + + // wait for a while ? + if ( frameInterval > 0 ) + { + // get download duration + span = DateTime.Now.Subtract( start ); + + // miliseconds to sleep + int msec = frameInterval - (int) span.TotalMilliseconds; + + if ( ( msec > 0 ) && ( stopEvent.WaitOne( msec, false ) ) ) + break; + } + } + catch ( ThreadAbortException ) + { + break; + } + catch ( Exception exception ) + { + // provide information to clients + if ( VideoSourceError != null ) + { + VideoSourceError( this, new VideoSourceErrorEventArgs( exception.Message ) ); + } + // wait for a while before the next try + Thread.Sleep( 250 ); + } + + // need to stop ? + if ( stopEvent.WaitOne( 0, false ) ) + break; + } + + // release resources + graphics.Dispose( ); + bitmap.Dispose( ); + + if ( PlayingFinished != null ) + { + PlayingFinished( this, ReasonToFinishPlaying.StoppedByUser ); + } + } + } +} diff --git a/Sources/Accord.Video/VideoEvents.cs b/Sources/Accord.Video/VideoEvents.cs new file mode 100644 index 0000000000..c5729e54d --- /dev/null +++ b/Sources/Accord.Video/VideoEvents.cs @@ -0,0 +1,125 @@ +// AForge Video Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2009-2011 +// contacts@aforgenet.com +// + +namespace AForge.Video +{ + using System; + + /// + /// Delegate for new frame event handler. + /// + /// + /// Sender object. + /// Event arguments. + /// + public delegate void NewFrameEventHandler( object sender, NewFrameEventArgs eventArgs ); + + /// + /// Delegate for video source error event handler. + /// + /// + /// Sender object. + /// Event arguments. + /// + public delegate void VideoSourceErrorEventHandler( object sender, VideoSourceErrorEventArgs eventArgs ); + + /// + /// Delegate for playing finished event handler. + /// + /// + /// Sender object. + /// Reason of finishing video playing. + /// + public delegate void PlayingFinishedEventHandler( object sender, ReasonToFinishPlaying reason ); + + /// + /// Reason of finishing video playing. + /// + /// + /// When video source class fire the event, they + /// need to specify reason of finishing video playing. For example, it may be end of stream reached. + /// + public enum ReasonToFinishPlaying + { + /// + /// Video playing has finished because it end was reached. + /// + EndOfStreamReached, + /// + /// Video playing has finished because it was stopped by user. + /// + StoppedByUser, + /// + /// Video playing has finished because the device was lost (unplugged). + /// + DeviceLost, + /// + /// Video playing has finished because of some error happened the video source (camera, stream, file, etc.). + /// A error reporting event usually is fired to provide error information. + /// + VideoSourceError + } + + /// + /// Arguments for new frame event from video source. + /// + /// + public class NewFrameEventArgs : EventArgs + { + private System.Drawing.Bitmap frame; + + /// + /// Initializes a new instance of the class. + /// + /// + /// New frame. + /// + public NewFrameEventArgs( System.Drawing.Bitmap frame ) + { + this.frame = frame; + } + + /// + /// New frame from video source. + /// + /// + public System.Drawing.Bitmap Frame + { + get { return frame; } + } + } + + /// + /// Arguments for video source error event from video source. + /// + /// + public class VideoSourceErrorEventArgs : EventArgs + { + private string description; + + /// + /// Initializes a new instance of the class. + /// + /// + /// Error description. + /// + public VideoSourceErrorEventArgs( string description ) + { + this.description = description; + } + + /// + /// Video source error description. + /// + /// + public string Description + { + get { return description; } + } + } +} diff --git a/Sources/Accord.Vision/AForge/Motion/BlobCountingObjectsProcessing.cs b/Sources/Accord.Vision/AForge/Motion/BlobCountingObjectsProcessing.cs new file mode 100644 index 0000000000..be4a65d2d --- /dev/null +++ b/Sources/Accord.Vision/AForge/Motion/BlobCountingObjectsProcessing.cs @@ -0,0 +1,306 @@ +// AForge Vision Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Vision.Motion +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + using AForge.Imaging; + + /// + /// Motion processing algorithm, which counts separate moving objects and highlights them. + /// + /// + /// The aim of this motion processing algorithm is to count separate objects + /// in the motion frame, which is provided by motion detection algorithm. + /// In the case if property is set to , + /// found objects are also highlighted on the original video frame. The algorithm + /// counts and highlights only those objects, which size satisfies + /// and properties. + /// + /// The motion processing algorithm is supposed to be used only with motion detection + /// algorithms, which are based on finding difference with background frame + /// (see and + /// as simple implementations) and allow extract moving objects clearly. + /// + /// Sample usage: + /// + /// // create instance of motion detection algorithm + /// IMotionDetector motionDetector = new ... ; + /// // create instance of motion processing algorithm + /// BlobCountingObjectsProcessing motionProcessing = new BlobCountingObjectsProcessing( ); + /// // create motion detector + /// MotionDetector detector = new MotionDetector( motionDetector, motionProcessing ); + /// + /// // continuously feed video frames to motion detector + /// while ( ... ) + /// { + /// // process new video frame and check motion level + /// if ( detector.ProcessFrame( videoFrame ) > 0.02 ) + /// { + /// // check number of detected objects + /// if ( motionProcessing.ObjectsCount > 1 ) + /// { + /// // ... + /// } + /// } + /// } + /// + /// + /// + /// + /// + /// + public class BlobCountingObjectsProcessing : IMotionProcessing + { + // blob counter to detect separate blobs + private BlobCounter blobCounter = new BlobCounter( ); + // color used for blobs highlighting + private Color highlightColor = Color.Red; + // highlight motion regions or not + private bool highlightMotionRegions = true; + + /// + /// Highlight motion regions or not. + /// + /// + /// The property specifies if detected moving objects should be highlighted + /// with rectangle or not. + /// + /// Default value is set to . + /// + /// Turning the value on leads to additional processing time of video frame. + /// + /// + public bool HighlightMotionRegions + { + get { return highlightMotionRegions; } + set { highlightMotionRegions = value; } + } + + /// + /// Color used to highlight motion regions. + /// + /// + /// + /// Default value is set to red color. + /// + /// + public Color HighlightColor + { + get { return highlightColor; } + set { highlightColor = value; } + } + + /// + /// Minimum width of acceptable object. + /// + /// + /// The property sets minimum width of an object to count and highlight. If + /// objects have smaller width, they are not counted and are not highlighted. + /// + /// Default value is set to 10. + /// + /// + public int MinObjectsWidth + { + get { return blobCounter.MinWidth; } + set + { + lock ( blobCounter ) + { + blobCounter.MinWidth = value; + } + } + } + + /// + /// Minimum height of acceptable object. + /// + /// + /// The property sets minimum height of an object to count and highlight. If + /// objects have smaller height, they are not counted and are not highlighted. + /// + /// Default value is set to 10. + /// + /// + public int MinObjectsHeight + { + get { return blobCounter.MinHeight; } + set + { + lock ( blobCounter ) + { + blobCounter.MinHeight = value; + } + } + } + + /// + /// Number of detected objects. + /// + /// + /// The property provides number of moving objects detected by + /// the last call of method. + /// + public int ObjectsCount + { + get + { + lock ( blobCounter ) + { + return blobCounter.ObjectsCount; + } + } + } + + /// + /// Rectangles of moving objects. + /// + /// + /// The property provides array of moving objects' rectangles + /// detected by the last call of method. + /// + public Rectangle[] ObjectRectangles + { + get + { + lock ( blobCounter ) + { + return blobCounter.GetObjectsRectangles( ); + } + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public BlobCountingObjectsProcessing( ) : this( 10, 10 ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Highlight motion regions or not (see property). + /// + public BlobCountingObjectsProcessing( bool highlightMotionRegions ) : this( 10, 10, highlightMotionRegions ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Minimum width of acceptable object (see property). + /// Minimum height of acceptable object (see property). + /// + public BlobCountingObjectsProcessing( int minWidth, int minHeight ) : + this( minWidth, minHeight, Color.Red ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Minimum width of acceptable object (see property). + /// Minimum height of acceptable object (see property). + /// Color used to highlight motion regions. + /// + public BlobCountingObjectsProcessing( int minWidth, int minHeight, Color highlightColor ) + { + blobCounter.FilterBlobs = true; + blobCounter.MinHeight = minHeight; + blobCounter.MinWidth = minWidth; + + this.highlightColor = highlightColor; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Minimum width of acceptable object (see property). + /// Minimum height of acceptable object (see property). + /// Highlight motion regions or not (see property). + /// + public BlobCountingObjectsProcessing( int minWidth, int minHeight, bool highlightMotionRegions ) + : this( minWidth, minHeight ) + { + this.highlightMotionRegions = highlightMotionRegions; + } + + /// + /// Process video and motion frames doing further post processing after + /// performed motion detection. + /// + /// + /// Original video frame. + /// Motion frame provided by motion detection + /// algorithm (see ). + /// + /// Processes provided motion frame and counts number of separate + /// objects, which size satisfies and + /// properties. In the case if property is + /// set to , the found object are also highlighted on the + /// original video frame. + /// + /// + /// Motion frame is not 8 bpp image, but it must be so. + /// Video frame must be 8 bpp grayscale image or 24/32 bpp color image. + /// + public void ProcessFrame( UnmanagedImage videoFrame, UnmanagedImage motionFrame ) + { + if ( motionFrame.PixelFormat != PixelFormat.Format8bppIndexed ) + { + throw new InvalidImagePropertiesException( "Motion frame must be 8 bpp image." ); + } + + if ( ( videoFrame.PixelFormat != PixelFormat.Format8bppIndexed ) && + ( videoFrame.PixelFormat != PixelFormat.Format24bppRgb ) && + ( videoFrame.PixelFormat != PixelFormat.Format32bppRgb ) && + ( videoFrame.PixelFormat != PixelFormat.Format32bppArgb ) ) + { + throw new UnsupportedImageFormatException( "Video frame must be 8 bpp grayscale image or 24/32 bpp color image." ); + } + + int width = videoFrame.Width; + int height = videoFrame.Height; + + if ( ( motionFrame.Width != width ) || ( motionFrame.Height != height ) ) + return; + + lock ( blobCounter ) + { + blobCounter.ProcessImage( motionFrame ); + } + + if ( highlightMotionRegions ) + { + // highlight each moving object + Rectangle[] rects = blobCounter.GetObjectsRectangles( ); + + foreach ( Rectangle rect in rects ) + { + Drawing.Rectangle( videoFrame, rect, highlightColor ); + } + } + } + + /// + /// Reset internal state of motion processing algorithm. + /// + /// + /// The method allows to reset internal state of motion processing + /// algorithm and prepare it for processing of next video stream or to restart + /// the algorithm. + /// + public void Reset( ) + { + } + } +} diff --git a/Sources/Accord.Vision/AForge/Motion/CustomFrameDifferenceDetector.cs b/Sources/Accord.Vision/AForge/Motion/CustomFrameDifferenceDetector.cs new file mode 100644 index 0000000000..6c3df4e07 --- /dev/null +++ b/Sources/Accord.Vision/AForge/Motion/CustomFrameDifferenceDetector.cs @@ -0,0 +1,473 @@ +// AForge Vision Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Vision.Motion +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + using AForge.Imaging; + using AForge.Imaging.Filters; + + /// + /// Motion detector based on difference with predefined background frame. + /// + /// + /// The class implements motion detection algorithm, which is based on + /// difference of current video frame with predefined background frame. The difference frame + /// is thresholded and the amount of difference pixels is calculated. + /// To suppress stand-alone noisy pixels erosion morphological operator may be applied, which + /// is controlled by property. + /// + /// In the case if precise motion area's borders are required (for example, + /// for further motion post processing), then property + /// may be used to restore borders after noise suppression. + /// + /// In the case if custom background frame is not specified by using + /// method, the algorithm takes first video frame + /// as a background frame and calculates difference of further video frames with it. + /// + /// Unlike motion detection algorithm, this algorithm + /// allows to identify quite clearly all objects, which are not part of the background (scene) - + /// most likely moving objects. + /// + /// Sample usage: + /// + /// // create motion detector + /// MotionDetector detector = new MotionDetector( + /// new CustomFrameDifferenceDetector( ), + /// new MotionAreaHighlighting( ) ); + /// + /// // continuously feed video frames to motion detector + /// while ( ... ) + /// { + /// // process new video frame and check motion level + /// if ( detector.ProcessFrame( videoFrame ) > 0.02 ) + /// { + /// // ring alarm or do somethng else + /// } + /// } + /// + /// + /// + /// + /// + public class CustomFrameDifferenceDetector : IMotionDetector + { + // frame's dimension + private int width; + private int height; + private int frameSize; + + // previous frame of video stream + private UnmanagedImage backgroundFrame; + // current frame of video sream + private UnmanagedImage motionFrame; + // temporary buffer used for suppressing noise + private UnmanagedImage tempFrame; + // number of pixels changed in the new frame of video stream + private int pixelsChanged; + + private bool manuallySetBackgroundFrame = false; + + // suppress noise + private bool suppressNoise = true; + private bool keepObjectEdges = false; + + // threshold values + private int differenceThreshold = 15; + private int differenceThresholdNeg = -15; + + // binary erosion filter + private BinaryErosion3x3 erosionFilter = new BinaryErosion3x3( ); + // binary dilatation filter + private BinaryDilatation3x3 dilatationFilter = new BinaryDilatation3x3( ); + + // dummy object to lock for synchronization + private object sync = new object( ); + + /// + /// Difference threshold value, [1, 255]. + /// + /// + /// The value specifies the amount off difference between pixels, which is treated + /// as motion pixel. + /// + /// Default value is set to 15. + /// + /// + public int DifferenceThreshold + { + get { return differenceThreshold; } + set + { + lock ( sync ) + { + differenceThreshold = Math.Max( 1, Math.Min( 255, value ) ); + differenceThresholdNeg = -differenceThreshold; + } + } + } + + /// + /// Motion level value, [0, 1]. + /// + /// + /// Amount of changes in the last processed frame. For example, if value of + /// this property equals to 0.1, then it means that last processed frame has 10% difference + /// with defined background frame. + /// + /// + public float MotionLevel + { + get + { + lock ( sync ) + { + return (float) pixelsChanged / ( width * height ); + } + } + } + + /// + /// Motion frame containing detected areas of motion. + /// + /// + /// Motion frame is a grayscale image, which shows areas of detected motion. + /// All black pixels in the motion frame correspond to areas, where no motion is + /// detected. But white pixels correspond to areas, where motion is detected. + /// + /// The property is set to after processing of the first + /// video frame by the algorithm in the case if custom background frame was not set manually + /// by using method (it will be not + /// after second call in this case). If correct custom background + /// was set then the property should bet set to estimated motion frame after + /// method call. + /// + /// + public UnmanagedImage MotionFrame + { + get + { + lock ( sync ) + { + return motionFrame; + } + } + } + + /// + /// Suppress noise in video frames or not. + /// + /// + /// The value specifies if additional filtering should be + /// done to suppress standalone noisy pixels by applying 3x3 erosion image processing + /// filter. See property, if it is required to restore + /// edges of objects, which are not noise. + /// + /// Default value is set to . + /// + /// Turning the value on leads to more processing time of video frame. + /// + /// + public bool SuppressNoise + { + get { return suppressNoise; } + set + { + lock ( sync ) + { + suppressNoise = value; + + // allocate temporary frame if required + if ( ( suppressNoise ) && ( tempFrame == null ) && ( motionFrame != null ) ) + { + tempFrame = UnmanagedImage.Create( width, height, PixelFormat.Format8bppIndexed ); + } + + // check if temporary frame is not required + if ( ( !suppressNoise ) && ( tempFrame != null ) ) + { + tempFrame.Dispose( ); + tempFrame = null; + } + } + } + } + + /// + /// Restore objects edges after noise suppression or not. + /// + /// + /// The value specifies if additional filtering should be done + /// to restore objects' edges after noise suppression by applying 3x3 dilatation + /// image processing filter. + /// + /// Default value is set to . + /// + /// Turning the value on leads to more processing time of video frame. + /// + /// + public bool KeepObjectsEdges + { + get { return keepObjectEdges; } + set + { + lock ( sync ) + { + keepObjectEdges = value; + } + } + } + + /// + /// Initializes a new instance of the class. + /// + public CustomFrameDifferenceDetector( ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Suppress noise in video frames or not (see property). + /// + public CustomFrameDifferenceDetector( bool suppressNoise ) + { + this.suppressNoise = suppressNoise; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Suppress noise in video frames or not (see property). + /// Restore objects edges after noise suppression or not (see property). + /// + public CustomFrameDifferenceDetector( bool suppressNoise, bool keepObjectEdges ) + { + this.suppressNoise = suppressNoise; + this.keepObjectEdges = keepObjectEdges; + } + + /// + /// Process new video frame. + /// + /// + /// Video frame to process (detect motion in). + /// + /// Processes new frame from video source and detects motion in it. + /// + /// Check property to get information about amount of motion + /// (changes) in the processed frame. + /// + /// + public void ProcessFrame( UnmanagedImage videoFrame ) + { + lock ( sync ) + { + // check background frame + if ( backgroundFrame == null ) + { + // save image dimension + width = videoFrame.Width; + height = videoFrame.Height; + + // alocate memory for background frame + backgroundFrame = UnmanagedImage.Create( width, height, PixelFormat.Format8bppIndexed ); + frameSize = backgroundFrame.Stride * height; + + // convert source frame to grayscale + Tools.ConvertToGrayscale( videoFrame, backgroundFrame ); + + return; + } + + // check image dimension + if ( ( videoFrame.Width != width ) || ( videoFrame.Height != height ) ) + return; + + // check motion frame + if ( motionFrame == null ) + { + motionFrame = UnmanagedImage.Create( width, height, PixelFormat.Format8bppIndexed ); + + // temporary buffer + if ( suppressNoise ) + { + tempFrame = UnmanagedImage.Create( width, height, PixelFormat.Format8bppIndexed ); + } + } + + // convert current image to grayscale + Tools.ConvertToGrayscale( videoFrame, motionFrame ); + + unsafe + { + // pointers to background and current frames + byte* backFrame; + byte* currFrame; + int diff; + + backFrame = (byte*) backgroundFrame.ImageData.ToPointer( ); + currFrame = (byte*) motionFrame.ImageData.ToPointer( ); + + // 1 - get difference between frames + // 2 - threshold the difference + for ( int i = 0; i < frameSize; i++, backFrame++, currFrame++ ) + { + // difference + diff = (int) *currFrame - (int) *backFrame; + // treshold + *currFrame = ( ( diff >= differenceThreshold ) || ( diff <= differenceThresholdNeg ) ) ? (byte) 255 : (byte) 0; + } + + if ( suppressNoise ) + { + // suppress noise and calculate motion amount + AForge.SystemTools.CopyUnmanagedMemory( tempFrame.ImageData, motionFrame.ImageData, frameSize ); + erosionFilter.Apply( tempFrame, motionFrame ); + + if ( keepObjectEdges ) + { + AForge.SystemTools.CopyUnmanagedMemory( tempFrame.ImageData, motionFrame.ImageData, frameSize ); + dilatationFilter.Apply( tempFrame, motionFrame ); + } + } + + // calculate amount of motion pixels + pixelsChanged = 0; + byte* motion = (byte*) motionFrame.ImageData.ToPointer( ); + + for ( int i = 0; i < frameSize; i++, motion++ ) + { + pixelsChanged += ( *motion & 1 ); + } + } + } + } + + /// + /// Reset motion detector to initial state. + /// + /// + /// Resets internal state and variables of motion detection algorithm. + /// Usually this is required to be done before processing new video source, but + /// may be also done at any time to restart motion detection algorithm. + /// + /// In the case if custom background frame was set using + /// method, this method does not reset it. + /// The method resets only automatically generated background frame. + /// + /// + /// + public void Reset( ) + { + // clear background frame only in the case it was not set manually + Reset( false ); + } + + // Reset motion detector to initial state + private void Reset( bool force ) + { + lock ( sync ) + { + if ( + ( backgroundFrame != null ) && + ( ( force == true ) || ( manuallySetBackgroundFrame == false ) ) + ) + { + backgroundFrame.Dispose( ); + backgroundFrame = null; + } + + if ( motionFrame != null ) + { + motionFrame.Dispose( ); + motionFrame = null; + } + + if ( tempFrame != null ) + { + tempFrame.Dispose( ); + tempFrame = null; + } + } + } + + /// + /// Set background frame. + /// + /// + /// Background frame to set. + /// + /// The method sets background frame, which will be used to calculate + /// difference with. + /// + public void SetBackgroundFrame( Bitmap backgroundFrame ) + { + BitmapData data = backgroundFrame.LockBits( + new Rectangle( 0, 0, backgroundFrame.Width, backgroundFrame.Height ), + ImageLockMode.ReadOnly, backgroundFrame.PixelFormat ); + + try + { + SetBackgroundFrame( data ); + } + finally + { + backgroundFrame.UnlockBits( data ); + } + } + + /// + /// Set background frame. + /// + /// + /// Background frame to set. + /// + /// The method sets background frame, which will be used to calculate + /// difference with. + /// + public void SetBackgroundFrame( BitmapData backgroundFrame ) + { + SetBackgroundFrame( new UnmanagedImage( backgroundFrame ) ); + } + + /// + /// Set background frame. + /// + /// + /// Background frame to set. + /// + /// The method sets background frame, which will be used to calculate + /// difference with. + /// + public void SetBackgroundFrame( UnmanagedImage backgroundFrame ) + { + // reset motion detection algorithm + Reset( true ); + + lock ( sync ) + { + // save image dimension + width = backgroundFrame.Width; + height = backgroundFrame.Height; + + // alocate memory for previous and current frames + this.backgroundFrame = UnmanagedImage.Create( width, height, PixelFormat.Format8bppIndexed ); + frameSize = this.backgroundFrame.Stride * height; + + // convert source frame to grayscale + Tools.ConvertToGrayscale( backgroundFrame, this.backgroundFrame ); + + manuallySetBackgroundFrame = true; + } + } + } +} diff --git a/Sources/Accord.Vision/AForge/Motion/GridMotionAreaProcessing.cs b/Sources/Accord.Vision/AForge/Motion/GridMotionAreaProcessing.cs new file mode 100644 index 0000000000..8c83b1e94 --- /dev/null +++ b/Sources/Accord.Vision/AForge/Motion/GridMotionAreaProcessing.cs @@ -0,0 +1,397 @@ +// AForge Vision Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Vision.Motion +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + using AForge.Imaging; + + /// + /// Motion processing algorithm, which performs grid processing of motion frame. + /// + /// + /// The aim of this motion processing algorithm is to do grid processing + /// of motion frame. This means that entire motion frame is divided by a grid into + /// certain amount of cells and the motion level is calculated for each cell. The + /// information about each cell's motion level may be retrieved using + /// property. + /// + /// In addition the algorithm can highlight those cells, which have motion + /// level above the specified threshold (see + /// property). To enable this it is required to set + /// property to . + /// + /// Sample usage: + /// + /// // create instance of motion detection algorithm + /// IMotionDetector motionDetector = new ... ; + /// // create instance of motion processing algorithm + /// GridMotionAreaProcessing motionProcessing = new GridMotionAreaProcessing( 16, 16 ); + /// // create motion detector + /// MotionDetector detector = new MotionDetector( motionDetector, motionProcessing ); + /// + /// // continuously feed video frames to motion detector + /// while ( ... ) + /// { + /// // process new video frame + /// detector.ProcessFrame( videoFrame ); + /// + /// // check motion level in 5th row 8th column + /// if ( motionProcessing.MotionGrid[5, 8] > 0.15 ) + /// { + /// // ... + /// } + /// } + /// + /// + /// + /// + /// + /// + public class GridMotionAreaProcessing : IMotionProcessing + { + // color used for highlighting motion grid + private Color highlightColor = Color.Red; + // highlight motion grid or not + private bool highlightMotionGrid = true; + + private float motionAmountToHighlight = 0.15f; + + private int gridWidth = 16; + private int gridHeight = 16; + + private float[,] motionGrid = null; + + /// + /// Color used to highlight motion regions. + /// + /// + /// + /// Default value is set to red color. + /// + /// + public Color HighlightColor + { + get { return highlightColor; } + set { highlightColor = value; } + } + + /// + /// Highlight motion regions or not. + /// + /// + /// The property specifies if motion grid should be highlighted - + /// if cell, which have motion level above the + /// specified value, should be highlighted. + /// + /// Default value is set to . + /// + /// Turning the value on leads to additional processing time of video frame. + /// + /// + public bool HighlightMotionGrid + { + get { return highlightMotionGrid; } + set { highlightMotionGrid = value; } + } + + /// + /// Motion amount to highlight cell. + /// + /// + /// The property specifies motion level threshold for highlighting grid's + /// cells. If motion level of a certain cell is higher than this value, then the cell + /// is highlighted. + /// + /// Default value is set to 0.15. + /// + /// + public float MotionAmountToHighlight + { + get { return motionAmountToHighlight; } + set { motionAmountToHighlight = value; } + } + + /// + /// Motion levels of each grid's cell. + /// + /// + /// The property represents an array of size + /// x, which keeps motion level + /// of each grid's cell. If certain cell has motion level equal to 0.2, then it + /// means that this cell has 20% of changes. + /// + /// + public float[,] MotionGrid + { + get { return motionGrid; } + } + + /// + /// Width of motion grid, [2, 64]. + /// + /// + /// The property specifies motion grid's width - number of grid' columns. + /// + /// Default value is set to 16. + /// + /// + public int GridWidth + { + get { return gridWidth; } + set + { + gridWidth = Math.Min( 64, Math.Max( 2, value ) ); + motionGrid = new float[gridHeight, gridWidth]; + } + } + + /// + /// Height of motion grid, [2, 64]. + /// + /// + /// The property specifies motion grid's height - number of grid' rows. + /// + /// Default value is set to 16. + /// + /// + public int GridHeight + { + get { return gridHeight; } + set + { + gridHeight = Math.Min( 64, Math.Max( 2, value ) ); + motionGrid = new float[gridHeight, gridWidth]; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public GridMotionAreaProcessing( ) : this( 16, 16 ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Width of motion grid (see property). + /// Height of motion grid (see property). + /// + public GridMotionAreaProcessing( int gridWidth, int gridHeight ) : this( gridWidth, gridHeight, true ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Width of motion grid (see property). + /// Height of motion grid (see property). + /// Highlight motion regions or not (see property). + /// + public GridMotionAreaProcessing( int gridWidth, int gridHeight, bool highlightMotionGrid ) + : this( gridWidth, gridHeight, highlightMotionGrid, 0.15f ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Width of motion grid (see property). + /// Height of motion grid (see property). + /// Highlight motion regions or not (see property). + /// Motion amount to highlight cell (see property). + /// + public GridMotionAreaProcessing( int gridWidth, int gridHeight, bool highlightMotionGrid, float motionAmountToHighlight ) + { + this.gridWidth = Math.Min( 64, Math.Max( 2, gridWidth ) ); + this.gridHeight = Math.Min( 64, Math.Max( 2, gridHeight ) ); + + motionGrid = new float[gridHeight, gridWidth]; + + this.highlightMotionGrid = highlightMotionGrid; + this.motionAmountToHighlight = motionAmountToHighlight; + } + + /// + /// Process video and motion frames doing further post processing after + /// performed motion detection. + /// + /// + /// Original video frame. + /// Motion frame provided by motion detection + /// algorithm (see ). + /// + /// Processes provided motion frame and calculates motion level + /// for each grid's cell. In the case if property is + /// set to , the cell with motion level above threshold are + /// highlighted. + /// + /// Motion frame is not 8 bpp image, but it must be so. + /// Video frame must be 8 bpp grayscale image or 24/32 bpp color image. + /// + public void ProcessFrame( UnmanagedImage videoFrame, UnmanagedImage motionFrame ) + { + if ( motionFrame.PixelFormat != PixelFormat.Format8bppIndexed ) + { + throw new InvalidImagePropertiesException( "Motion frame must be 8 bpp image." ); + } + + if ( ( videoFrame.PixelFormat != PixelFormat.Format8bppIndexed ) && + ( videoFrame.PixelFormat != PixelFormat.Format24bppRgb ) && + ( videoFrame.PixelFormat != PixelFormat.Format32bppRgb ) && + ( videoFrame.PixelFormat != PixelFormat.Format32bppArgb ) ) + { + throw new UnsupportedImageFormatException( "Video frame must be 8 bpp grayscale image or 24/32 bpp color image." ); + } + + int width = videoFrame.Width; + int height = videoFrame.Height; + int pixelSize = Bitmap.GetPixelFormatSize( videoFrame.PixelFormat ) / 8; + + if ( ( motionFrame.Width != width ) || ( motionFrame.Height != height ) ) + return; + + int cellWidth = width / gridWidth; + int cellHeight = height / gridHeight; + + // temporary variables + int xCell, yCell; + + unsafe + { + // process motion frame calculating amount of changed pixels + // in each grid's cell + byte* motion = (byte*) motionFrame.ImageData.ToPointer( ); + int motionOffset = motionFrame.Stride - width; + + for ( int y = 0; y < height; y++ ) + { + // get current grid's row + yCell = y / cellHeight; + // correct row number if image was not divided by grid equally + if ( yCell >= gridHeight ) + yCell = gridHeight - 1; + + for ( int x = 0; x < width; x++, motion++ ) + { + if ( *motion != 0 ) + { + // get current grid's collumn + xCell = x / cellWidth; + // correct column number if image was not divided by grid equally + if ( xCell >= gridWidth ) + xCell = gridWidth - 1; + + motionGrid[yCell, xCell]++; + } + } + motion += motionOffset; + } + + // update motion grid converting absolute number of changed + // pixel to relative for each cell + int gridHeightM1 = gridHeight - 1; + int gridWidthM1 = gridWidth - 1; + + int lastRowHeight = height - cellHeight * gridHeightM1; + int lastColumnWidth = width - cellWidth * gridWidthM1; + + for ( int y = 0; y < gridHeight; y++ ) + { + int ch = ( y != gridHeightM1 ) ? cellHeight : lastRowHeight; + + for ( int x = 0; x < gridWidth; x++ ) + { + int cw = ( x != gridWidthM1 ) ? cellWidth : lastColumnWidth; + + motionGrid[y, x] /= ( cw * ch ); + } + } + + if ( highlightMotionGrid ) + { + // highlight motion grid - cells, which have enough motion + + byte* src = (byte*) videoFrame.ImageData.ToPointer( ); + int srcOffset = videoFrame.Stride - width * pixelSize; + + if ( pixelSize == 1 ) + { + // grayscale case + byte fillG = (byte) ( 0.2125 * highlightColor.R + + 0.7154 * highlightColor.G + + 0.0721 * highlightColor.B ); + + for ( int y = 0; y < height; y++ ) + { + yCell = y / cellHeight; + if ( yCell >= gridHeight ) + yCell = gridHeight - 1; + + for ( int x = 0; x < width; x++, src++ ) + { + xCell = x / cellWidth; + if ( xCell >= gridWidth ) + xCell = gridWidth - 1; + + if ( ( motionGrid[yCell, xCell] > motionAmountToHighlight ) && ( ( ( x + y ) & 1 ) == 0 ) ) + { + *src = fillG; + } + } + src += srcOffset; + } + } + else + { + // color case + byte fillR = highlightColor.R; + byte fillG = highlightColor.G; + byte fillB = highlightColor.B; + + for ( int y = 0; y < height; y++ ) + { + yCell = y / cellHeight; + if ( yCell >= gridHeight ) + yCell = gridHeight - 1; + + for ( int x = 0; x < width; x++, src += pixelSize ) + { + xCell = x / cellWidth; + if ( xCell >= gridWidth ) + xCell = gridWidth - 1; + + if ( ( motionGrid[yCell, xCell] > motionAmountToHighlight ) && ( ( ( x + y ) & 1 ) == 0 ) ) + { + src[RGB.R] = fillR; + src[RGB.G] = fillG; + src[RGB.B] = fillB; + } + } + src += srcOffset; + } + } + } + } + } + + /// + /// Reset internal state of motion processing algorithm. + /// + /// + /// The method allows to reset internal state of motion processing + /// algorithm and prepare it for processing of next video stream or to restart + /// the algorithm. + /// + public void Reset( ) + { + } + } +} diff --git a/Sources/Accord.Vision/AForge/Motion/IMotionDetector.cs b/Sources/Accord.Vision/AForge/Motion/IMotionDetector.cs new file mode 100644 index 0000000000..0aae86ce9 --- /dev/null +++ b/Sources/Accord.Vision/AForge/Motion/IMotionDetector.cs @@ -0,0 +1,75 @@ +// AForge Vision Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Vision.Motion +{ + using System; + using AForge.Imaging; + + /// + /// Interface of motion detector algorithm. + /// + /// + /// The interface specifies methods, which should be implemented + /// by all motion detection algorithms - algorithms which perform processing of video + /// frames in order to detect motion. Amount of detected motion may be checked using + /// property. Also property may + /// be used in order to see all the detected motion areas. For example, the property + /// is used by motion processing algorithms for further motion post processing, like + /// highlighting motion areas, counting number of detected moving object, etc. + /// + /// + /// + /// + /// + /// + public interface IMotionDetector + { + /// + /// Motion level value, [0, 1]. + /// + /// + /// Amount of changes in the last processed frame. For example, if value of + /// this property equals to 0.1, then it means that last processed frame has 10% of changes + /// (however it is up to specific implementation to decide how to compare specified frame). + /// + /// + float MotionLevel { get; } + + /// + /// Motion frame containing detected areas of motion. + /// + /// + /// Motion frame is a grayscale image, which shows areas of detected motion. + /// All black pixels in the motion frame correspond to areas, where no motion is + /// detected. But white pixels correspond to areas, where motion is detected. + /// + UnmanagedImage MotionFrame { get; } + + /// + /// Process new video frame. + /// + /// + /// Video frame to process (detect motion in). + /// + /// Processes new frame from video source and detects motion in it. + /// + void ProcessFrame( UnmanagedImage videoFrame ); + + /// + /// Reset motion detector to initial state. + /// + /// + /// Resets internal state and variables of motion detection algorithm. + /// Usually this is required to be done before processing new video source, but + /// may be also done at any time to restart motion detection algorithm. + /// + /// + void Reset( ); + } +} diff --git a/Sources/Accord.Vision/AForge/Motion/IMotionProcessing.cs b/Sources/Accord.Vision/AForge/Motion/IMotionProcessing.cs new file mode 100644 index 0000000000..88f4b2c34 --- /dev/null +++ b/Sources/Accord.Vision/AForge/Motion/IMotionProcessing.cs @@ -0,0 +1,59 @@ +// AForge Vision Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2005-2009 +// andrew.kirillov@aforgenet.com +// + +namespace AForge.Vision.Motion +{ + using System; + using AForge.Imaging; + + /// + /// Interface of motion processing algorithm. + /// + /// + /// The interface specifies methods, which should be implemented + /// by all motion processng algorithms - algorithm which perform further post processing + /// of detected motion, which is done by motion detection algorithms (see ). + /// + /// + /// + /// + /// + public interface IMotionProcessing + { + /// + /// Process video and motion frames doing further post processing after + /// performed motion detection. + /// + /// + /// Original video frame. + /// Motion frame provided by motion detection + /// algorithm (see ). + /// + /// The method does father post processing of detected motion. + /// Type of motion post processing is specified by specific implementation + /// of the interface - it may motion + /// area highlighting, motion objects counting, etc. + /// + void ProcessFrame( UnmanagedImage videoFrame, UnmanagedImage motionFrame ); + + /// + /// Reset internal state of motion processing algorithm. + /// + /// + /// The method allows to reset internal state of motion processing + /// algorithm and prepare it for processing of next video stream or to restart + /// the algorithm. + /// + /// Some motion processing algorithms may not have any stored internal + /// states and may just process provided video frames without relying on any motion + /// history etc. In this case such algorithms provide empty implementation of this method. + /// + /// + void Reset( ); + } +} diff --git a/Sources/Accord.Vision/AForge/Motion/MotionAreaHighlighting.cs b/Sources/Accord.Vision/AForge/Motion/MotionAreaHighlighting.cs new file mode 100644 index 0000000000..8e83b77e1 --- /dev/null +++ b/Sources/Accord.Vision/AForge/Motion/MotionAreaHighlighting.cs @@ -0,0 +1,182 @@ +// AForge Vision Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Vision.Motion +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + using AForge.Imaging; + + /// + /// Motion processing algorithm, which highlights motion areas. + /// + /// + /// The aim of this motion processing algorithm is to highlight + /// motion areas with grid pattern of the specified color. + /// + /// + /// Sample usage: + /// + /// // create motion detector + /// MotionDetector detector = new MotionDetector( + /// /* motion detection algorithm */, + /// new MotionAreaHighlighting( ) ); + /// + /// // continuously feed video frames to motion detector + /// while ( ... ) + /// { + /// // process new video frame + /// detector.ProcessFrame( videoFrame ); + /// } + /// + /// + /// + /// + /// + /// + public class MotionAreaHighlighting : IMotionProcessing + { + private Color highlightColor = Color.Red; + + /// + /// Color used to highlight motion regions. + /// + /// + /// + /// Default value is set to red color. + /// + /// + public Color HighlightColor + { + get { return highlightColor; } + set { highlightColor = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public MotionAreaHighlighting( ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Color used to highlight motion regions. + /// + public MotionAreaHighlighting( Color highlightColor ) + { + this.highlightColor = highlightColor; + } + + /// + /// Process video and motion frames doing further post processing after + /// performed motion detection. + /// + /// + /// Original video frame. + /// Motion frame provided by motion detection + /// algorithm (see ). + /// + /// Processes provided motion frame and highlights motion areas + /// on the original video frame with specified color. + /// + /// + /// Motion frame is not 8 bpp image, but it must be so. + /// Video frame must be 8 bpp grayscale image or 24/32 bpp color image. + /// + public void ProcessFrame( UnmanagedImage videoFrame, UnmanagedImage motionFrame ) + { + if ( motionFrame.PixelFormat != PixelFormat.Format8bppIndexed ) + { + throw new InvalidImagePropertiesException( "Motion frame must be 8 bpp image." ); + } + + if ( ( videoFrame.PixelFormat != PixelFormat.Format8bppIndexed ) && + ( videoFrame.PixelFormat != PixelFormat.Format24bppRgb ) && + ( videoFrame.PixelFormat != PixelFormat.Format32bppRgb ) && + ( videoFrame.PixelFormat != PixelFormat.Format32bppArgb ) ) + { + throw new UnsupportedImageFormatException( "Video frame must be 8 bpp grayscale image or 24/32 bpp color image." ); + } + + int width = videoFrame.Width; + int height = videoFrame.Height; + int pixelSize = Bitmap.GetPixelFormatSize( videoFrame.PixelFormat ) / 8; + + if ( ( motionFrame.Width != width ) || ( motionFrame.Height != height ) ) + return; + + unsafe + { + byte* src = (byte*) videoFrame.ImageData.ToPointer( ); + byte* motion = (byte*) motionFrame.ImageData.ToPointer( ); + + int srcOffset = videoFrame.Stride - width * pixelSize; + int motionOffset = motionFrame.Stride - width; + + if ( pixelSize == 1 ) + { + // grayscale case + byte fillG = (byte) ( 0.2125 * highlightColor.R + + 0.7154 * highlightColor.G + + 0.0721 * highlightColor.B ); + + for ( int y = 0; y < height; y++ ) + { + for ( int x = 0; x < width; x++, motion++, src++ ) + { + if ( ( *motion != 0 ) && ( ( ( x + y ) & 1 ) == 0 ) ) + { + *src = fillG; + } + } + src += srcOffset; + motion += motionOffset; + } + } + else + { + // color case + byte fillR = highlightColor.R; + byte fillG = highlightColor.G; + byte fillB = highlightColor.B; + + for ( int y = 0; y < height; y++ ) + { + for ( int x = 0; x < width; x++, motion++, src += pixelSize ) + { + if ( ( *motion != 0 ) && ( ( ( x + y ) & 1 ) == 0 ) ) + { + src[RGB.R] = fillR; + src[RGB.G] = fillG; + src[RGB.B] = fillB; + } + } + src += srcOffset; + motion += motionOffset; + } + } + } + } + + /// + /// Reset internal state of motion processing algorithm. + /// + /// + /// The method allows to reset internal state of motion processing + /// algorithm and prepare it for processing of next video stream or to restart + /// the algorithm. + /// + public void Reset( ) + { + } + } +} diff --git a/Sources/Accord.Vision/AForge/Motion/MotionBorderHighlighting.cs b/Sources/Accord.Vision/AForge/Motion/MotionBorderHighlighting.cs new file mode 100644 index 0000000000..2f24b27ba --- /dev/null +++ b/Sources/Accord.Vision/AForge/Motion/MotionBorderHighlighting.cs @@ -0,0 +1,196 @@ +// AForge Vision Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Vision.Motion +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + using AForge.Imaging; + + /// + /// Motion processing algorithm, which highlights border of motion areas. + /// + /// + /// The aim of this motion processing algorithm is to highlight + /// borders of motion areas with the specified color. + /// + /// + /// The motion processing algorithm is supposed to be used only with motion detection + /// algorithms, which are based on finding difference with background frame + /// (see and + /// as simple implementations) and allow extract moving objects clearly. + /// + /// Sample usage: + /// + /// // create motion detector + /// MotionDetector detector = new MotionDetector( + /// /* motion detection algorithm */, + /// new MotionBorderHighlighting( ) ); + /// + /// // continuously feed video frames to motion detector + /// while ( ... ) + /// { + /// // process new video frame + /// detector.ProcessFrame( videoFrame ); + /// } + /// + /// + /// + /// + /// + /// + public class MotionBorderHighlighting : IMotionProcessing + { + private Color highlightColor = Color.Red; + + /// + /// Color used to highlight motion regions. + /// + /// + /// + /// Default value is set to red color. + /// + /// + public Color HighlightColor + { + get { return highlightColor; } + set { highlightColor = value; } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public MotionBorderHighlighting( ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Color used to highlight motion regions. + /// + public MotionBorderHighlighting( Color highlightColor ) + { + this.highlightColor = highlightColor; + } + + /// + /// Process video and motion frames doing further post processing after + /// performed motion detection. + /// + /// + /// Original video frame. + /// Motion frame provided by motion detection + /// algorithm (see ). + /// + /// Processes provided motion frame and highlights borders of motion areas + /// on the original video frame with specified color. + /// + /// + /// Motion frame is not 8 bpp image, but it must be so. + /// Video frame must be 8 bpp grayscale image or 24/32 bpp color image. + /// + public void ProcessFrame( UnmanagedImage videoFrame, UnmanagedImage motionFrame ) + { + if ( motionFrame.PixelFormat != PixelFormat.Format8bppIndexed ) + { + throw new InvalidImagePropertiesException( "Motion frame must be 8 bpp image." ); + } + + if ( ( videoFrame.PixelFormat != PixelFormat.Format8bppIndexed ) && + ( videoFrame.PixelFormat != PixelFormat.Format24bppRgb ) && + ( videoFrame.PixelFormat != PixelFormat.Format32bppRgb ) && + ( videoFrame.PixelFormat != PixelFormat.Format32bppArgb ) ) + { + throw new UnsupportedImageFormatException( "Video frame must be 8 bpp grayscale image or 24/32 bpp color image." ); + } + + int width = videoFrame.Width; + int height = videoFrame.Height; + int pixelSize = Bitmap.GetPixelFormatSize( videoFrame.PixelFormat ) / 8; + + if ( ( motionFrame.Width != width ) || ( motionFrame.Height != height ) ) + return; + + unsafe + { + byte* src = (byte*) videoFrame.ImageData.ToPointer( ); + byte* motion = (byte*) motionFrame.ImageData.ToPointer( ); + + int srcOffset = videoFrame.Stride - ( width - 2 ) * pixelSize; + int motionOffset = motionFrame.Stride - ( width - 2 ); + + src += videoFrame.Stride + pixelSize; + motion += motionFrame.Stride + 1; + + int widthM1 = width - 1; + int heightM1 = height - 1; + + // use simple edge detector + if ( pixelSize == 1 ) + { + // grayscale case + byte fillG = (byte) ( 0.2125 * highlightColor.R + + 0.7154 * highlightColor.G + + 0.0721 * highlightColor.B ); + + for ( int y = 1; y < heightM1; y++ ) + { + for ( int x = 1; x < widthM1; x++, motion++, src++ ) + { + if ( 4 * *motion - motion[-width] - motion[width] - motion[1] - motion[-1] != 0 ) + { + *src = fillG; + } + } + + motion += motionOffset; + src += srcOffset; + } + } + else + { + // color case + byte fillR = highlightColor.R; + byte fillG = highlightColor.G; + byte fillB = highlightColor.B; + + for ( int y = 1; y < heightM1; y++ ) + { + for ( int x = 1; x < widthM1; x++, motion++, src += pixelSize ) + { + if ( 4 * *motion - motion[-width] - motion[width] - motion[1] - motion[-1] != 0 ) + { + src[RGB.R] = fillR; + src[RGB.G] = fillG; + src[RGB.B] = fillB; + } + } + + motion += motionOffset; + src += srcOffset; + } + } + } + } + + /// + /// Reset internal state of motion processing algorithm. + /// + /// + /// The method allows to reset internal state of motion processing + /// algorithm and prepare it for processing of next video stream or to restart + /// the algorithm. + /// + public void Reset( ) + { + } + } +} diff --git a/Sources/Accord.Vision/AForge/Motion/MotionDetector.cs b/Sources/Accord.Vision/AForge/Motion/MotionDetector.cs new file mode 100644 index 0000000000..b62862a3d --- /dev/null +++ b/Sources/Accord.Vision/AForge/Motion/MotionDetector.cs @@ -0,0 +1,357 @@ +// AForge Vision Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Vision.Motion +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + + using AForge.Imaging; + + /// + /// Motion detection wrapper class, which performs motion detection and processing. + /// + /// + /// The class serves as a wrapper class for + /// motion detection and + /// motion processing algorithms, allowing to call them with + /// single call. Unlike motion detection and motion processing interfaces, the class also + /// provides additional methods for convenience, so the algorithms could be applied not + /// only to , but to .NET's class + /// as well. + /// + /// In addition to wrapping of motion detection and processing algorthms, the class provides + /// some additional functionality. Using property it is possible to specify + /// set of rectangular zones to observe - only motion in these zones is counted and post procesed. + /// + /// Sample usage: + /// + /// // create motion detector + /// MotionDetector detector = new MotionDetector( + /// new SimpleBackgroundModelingDetector( ), + /// new MotionAreaHighlighting( ) ); + /// + /// // continuously feed video frames to motion detector + /// while ( ... ) + /// { + /// // process new video frame and check motion level + /// if ( detector.ProcessFrame( videoFrame ) > 0.02 ) + /// { + /// // ring alarm or do somethng else + /// } + /// } + /// + /// + /// + public class MotionDetector + { + private IMotionDetector detector; + private IMotionProcessing processor; + + // motion detectoin zones + private Rectangle[] motionZones = null; + // image of motion zones + private UnmanagedImage zonesFrame; + // size of video frame + private int videoWidth, videoHeight; + + // dummy object to lock for synchronization + private object sync = new object( ); + + /// + /// Motion detection algorithm to apply to each video frame. + /// + /// + /// The property sets motion detection algorithm, which is used by + /// method in order to calculate + /// motion level and + /// motion frame. + /// + /// + public IMotionDetector MotionDetectionAlgorithm + { + get { return detector; } + set + { + lock ( sync ) + { + detector = value; + } + } + } + + /// + /// Motion processing algorithm to apply to each video frame after + /// motion detection is done. + /// + /// + /// The property sets motion processing algorithm, which is used by + /// method after motion detection in order to do further + /// post processing of motion frames. The aim of further post processing depends on + /// actual implementation of the specified motion processing algorithm - it can be + /// highlighting of motion area, objects counting, etc. + /// + /// + public IMotionProcessing MotionProcessingAlgorithm + { + get { return processor; } + set + { + lock ( sync ) + { + processor = value; + } + } + } + + /// + /// Set of zones to detect motion in. + /// + /// + /// The property keeps array of rectangular zones, which are observed for motion detection. + /// Motion outside of these zones is ignored. + /// + /// In the case if this property is set, the method + /// will filter out all motion witch was detected by motion detection algorithm, but is not + /// located in the specified zones. + /// + /// + public Rectangle[] MotionZones + { + get { return motionZones; } + set + { + motionZones = value; + CreateMotionZonesFrame( ); + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Motion detection algorithm to apply to each video frame. + /// + public MotionDetector( IMotionDetector detector ) : this( detector, null ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Motion detection algorithm to apply to each video frame. + /// Motion processing algorithm to apply to each video frame after + /// motion detection is done. + /// + public MotionDetector( IMotionDetector detector, IMotionProcessing processor ) + { + this.detector = detector; + this.processor = processor; + } + + /// + /// Process new video frame. + /// + /// + /// Video frame to process (detect motion in). + /// + /// Returns amount of motion, which is provided + /// property of the motion detection algorithm in use. + /// + /// See for additional details. + /// + /// + public float ProcessFrame( Bitmap videoFrame ) + { + float motionLevel = 0; + + BitmapData videoData = videoFrame.LockBits( + new Rectangle( 0, 0, videoFrame.Width, videoFrame.Height ), + ImageLockMode.ReadWrite, videoFrame.PixelFormat ); + + try + { + motionLevel = ProcessFrame( new UnmanagedImage( videoData ) ); + } + finally + { + videoFrame.UnlockBits( videoData ); + } + + return motionLevel; + } + + /// + /// Process new video frame. + /// + /// + /// Video frame to process (detect motion in). + /// + /// Returns amount of motion, which is provided + /// property of the motion detection algorithm in use. + /// + /// See for additional details. + /// + /// + public float ProcessFrame( BitmapData videoFrame ) + { + return ProcessFrame( new UnmanagedImage( videoFrame ) ); + } + + /// + /// Process new video frame. + /// + /// + /// Video frame to process (detect motion in). + /// + /// Returns amount of motion, which is provided + /// property of the motion detection algorithm in use. + /// + /// The method first of all applies motion detection algorithm to the specified video + /// frame to calculate motion level and + /// motion frame. After this it applies motion processing algorithm + /// (if it was set) to do further post processing, like highlighting motion areas, counting moving + /// objects, etc. + /// + /// In the case if property is set, this method will perform + /// motion filtering right after motion algorithm is done and before passing motion frame to motion + /// processing algorithm. The method does filtering right on the motion frame, which is produced + /// by motion detection algorithm. At the same time the method recalculates motion level and returns + /// new value, which takes motion zones into account (but the new value is not set back to motion detection + /// algorithm' property). + /// + /// + /// + public float ProcessFrame( UnmanagedImage videoFrame ) + { + lock ( sync ) + { + if ( detector == null ) + return 0; + + videoWidth = videoFrame.Width; + videoHeight = videoFrame.Height; + + float motionLevel = 0; + // call motion detection + detector.ProcessFrame( videoFrame ); + motionLevel = detector.MotionLevel; + + // check if motion zones are specified + if ( motionZones != null ) + { + if ( zonesFrame == null ) + { + CreateMotionZonesFrame( ); + } + + if ( ( videoWidth == zonesFrame.Width ) && ( videoHeight == zonesFrame.Height ) ) + { + unsafe + { + // pointers to background and current frames + byte* zonesPtr = (byte*) zonesFrame.ImageData.ToPointer( ); + byte* motionPtr = (byte*) detector.MotionFrame.ImageData.ToPointer( ); + + motionLevel = 0; + + for ( int i = 0, frameSize = zonesFrame.Stride * videoHeight; i < frameSize; i++, zonesPtr++, motionPtr++ ) + { + *motionPtr &= *zonesPtr; + motionLevel += ( *motionPtr & 1 ); + } + motionLevel /= ( videoWidth * videoHeight ); + } + } + } + + // call motion post processing + if ( ( processor != null ) && ( detector.MotionFrame != null ) ) + { + processor.ProcessFrame( videoFrame, detector.MotionFrame ); + } + + return motionLevel; + } + } + + /// + /// Reset motion detector to initial state. + /// + /// + /// The method resets motion detection and motion processing algotithms by calling + /// their and methods. + /// + /// + public void Reset( ) + { + lock ( sync ) + { + if ( detector != null ) + { + detector.Reset( ); + } + if ( processor != null ) + { + processor.Reset( ); + } + + videoWidth = 0; + videoHeight = 0; + + if ( zonesFrame != null ) + { + zonesFrame.Dispose( ); + zonesFrame = null; + } + } + } + + // Create motion zones' image + private unsafe void CreateMotionZonesFrame( ) + { + lock ( sync ) + { + // free previous motion zones frame + if ( zonesFrame != null ) + { + zonesFrame.Dispose( ); + zonesFrame = null; + } + + // create motion zones frame only in the case if the algorithm has processed at least one frame + if ( ( motionZones != null ) && ( motionZones.Length != 0 ) && ( videoWidth != 0 ) ) + { + zonesFrame = UnmanagedImage.Create( videoWidth, videoHeight, PixelFormat.Format8bppIndexed ); + + Rectangle imageRect = new Rectangle( 0, 0, videoWidth, videoHeight ); + + // draw all motion zones on motion frame + foreach ( Rectangle rect in motionZones ) + { + rect.Intersect( imageRect ); + + // rectangle's dimenstion + int rectWidth = rect.Width; + int rectHeight = rect.Height; + + // start pointer + int stride = zonesFrame.Stride; + byte* ptr = (byte*) zonesFrame.ImageData.ToPointer( ) + rect.Y * stride + rect.X; + + for ( int y = 0; y < rectHeight; y++ ) + { + AForge.SystemTools.SetUnmanagedMemory( ptr, 255, rectWidth ); + ptr += stride; + } + } + } + } + } + } +} diff --git a/Sources/Accord.Vision/AForge/Motion/SimpleBackgroundModelingDetector.cs b/Sources/Accord.Vision/AForge/Motion/SimpleBackgroundModelingDetector.cs new file mode 100644 index 0000000000..4e03ce549 --- /dev/null +++ b/Sources/Accord.Vision/AForge/Motion/SimpleBackgroundModelingDetector.cs @@ -0,0 +1,528 @@ +// AForge Vision Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Vision.Motion +{ + using System; + using System.Drawing.Imaging; + + using AForge.Imaging; + using AForge.Imaging.Filters; + + /// + /// Motion detector based on simple background modeling. + /// + /// + /// The class implements motion detection algorithm, which is based on + /// difference of current video frame with modeled background frame. + /// The difference frame is thresholded and the + /// amount of difference pixels is calculated. + /// To suppress stand-alone noisy pixels erosion morphological operator may be applied, which + /// is controlled by property. + /// + /// In the case if precise motion area's borders are required (for example, + /// for further motion post processing), then property + /// may be used to restore borders after noise suppression. + /// + /// As the first approximation of background frame, the first frame of video stream is taken. + /// During further video processing the background frame is constantly updated, so it + /// changes in the direction to decrease difference with current video frame (the background + /// frame is moved towards current frame). See + /// properties, which control the rate of + /// background frame update. + /// + /// Unlike motion detection algorithm, this algorithm + /// allows to identify quite clearly all objects, which are not part of the background (scene) - + /// most likely moving objects. And unlike motion + /// detection algorithm, this algorithm includes background adaptation feature, which allows it + /// to update its modeled background frame in order to take scene changes into account. + /// + /// Because of the adaptation feature of the algorithm, it may adopt + /// to background changes, what algorithm can not do. + /// However, if moving object stays on the scene for a while (so algorithm adopts to it and does + /// not treat it as a new moving object any more) and then starts to move again, the algorithm may + /// find two moving objects - the true one, which is really moving, and the false one, which does not (the + /// place, where the object stayed for a while). + /// + /// The algorithm is not applicable to such cases, when moving object resides + /// in camera's view most of the time (laptops camera monitoring a person sitting in front of it, + /// for example). The algorithm is mostly supposed for cases, when camera monitors some sort + /// of static scene, where moving objects appear from time to time - street, road, corridor, etc. + /// + /// + /// Sample usage: + /// + /// // create motion detector + /// MotionDetector detector = new MotionDetector( + /// new SimpleBackgroundModelingDetector( ), + /// new MotionAreaHighlighting( ) ); + /// + /// // continuously feed video frames to motion detector + /// while ( ... ) + /// { + /// // process new video frame and check motion level + /// if ( detector.ProcessFrame( videoFrame ) > 0.02 ) + /// { + /// // ring alarm or do somethng else + /// } + /// } + /// + /// + /// + /// + /// + public class SimpleBackgroundModelingDetector : IMotionDetector + { + // frame's dimension + private int width; + private int height; + private int frameSize; + + // previous frame of video stream + private UnmanagedImage backgroundFrame; + // current frame of video sream + private UnmanagedImage motionFrame; + // temporary buffer used for suppressing noise + private UnmanagedImage tempFrame; + // number of pixels changed in the new frame of video stream + private int pixelsChanged; + + // suppress noise + private bool suppressNoise = true; + private bool keepObjectEdges = false; + + // threshold values + private int differenceThreshold = 15; + private int differenceThresholdNeg = -15; + + private int framesPerBackgroundUpdate = 2; + private int framesCounter = 0; + + private int millisecondsPerBackgroundUpdate = 0; + private int millisecondsLeftUnprocessed = 0; + private DateTime lastTimeMeasurment; + + // binary erosion filter + private BinaryErosion3x3 erosionFilter = new BinaryErosion3x3( ); + // binary dilatation filter + private BinaryDilatation3x3 dilatationFilter = new BinaryDilatation3x3( ); + + // dummy object to lock for synchronization + private object sync = new object( ); + + /// + /// Difference threshold value, [1, 255]. + /// + /// + /// The value specifies the amount off difference between pixels, which is treated + /// as motion pixel. + /// + /// Default value is set to 15. + /// + /// + public int DifferenceThreshold + { + get { return differenceThreshold; } + set + { + lock ( sync ) + { + differenceThreshold = Math.Max( 1, Math.Min( 255, value ) ); + differenceThresholdNeg = -differenceThreshold; + } + } + } + + /// + /// Motion level value, [0, 1]. + /// + /// + /// Amount of changes in the last processed frame. For example, if value of + /// this property equals to 0.1, then it means that last processed frame has 10% difference + /// with modeled background frame. + /// + /// + public float MotionLevel + { + get + { + lock ( sync ) + { + return (float) pixelsChanged / ( width * height ); + } + } + } + + /// + /// Motion frame containing detected areas of motion. + /// + /// + /// Motion frame is a grayscale image, which shows areas of detected motion. + /// All black pixels in the motion frame correspond to areas, where no motion is + /// detected. But white pixels correspond to areas, where motion is detected. + /// + /// The property is set to after processing of the first + /// video frame by the algorithm. + /// + /// + public UnmanagedImage MotionFrame + { + get + { + lock ( sync ) + { + return motionFrame; + } + } + } + + /// + /// Suppress noise in video frames or not. + /// + /// + /// The value specifies if additional filtering should be + /// done to suppress standalone noisy pixels by applying 3x3 erosion image processing + /// filter. See property, if it is required to restore + /// edges of objects, which are not noise. + /// + /// Default value is set to . + /// + /// Turning the value on leads to more processing time of video frame. + /// + /// + public bool SuppressNoise + { + get { return suppressNoise; } + set + { + lock ( sync ) + { + suppressNoise = value; + + // allocate temporary frame if required + if ( ( suppressNoise ) && ( tempFrame == null ) && ( motionFrame != null ) ) + { + tempFrame = UnmanagedImage.Create( width, height, PixelFormat.Format8bppIndexed ); + } + + // check if temporary frame is not required + if ( ( !suppressNoise ) && ( tempFrame != null ) ) + { + tempFrame.Dispose( ); + tempFrame = null; + } + } + } + } + + /// + /// Restore objects edges after noise suppression or not. + /// + /// + /// The value specifies if additional filtering should be done + /// to restore objects' edges after noise suppression by applying 3x3 dilatation + /// image processing filter. + /// + /// Default value is set to . + /// + /// Turning the value on leads to more processing time of video frame. + /// + /// + public bool KeepObjectsEdges + { + get { return keepObjectEdges; } + set + { + lock ( sync ) + { + keepObjectEdges = value; + } + } + } + + /// + /// Frames per background update, [1, 50]. + /// + /// + /// The value controls the speed of modeled background adaptation to + /// scene changes. After each specified amount of frames the background frame is updated + /// in the direction to decrease difference with current processing frame. + /// + /// Default value is set to 2. + /// + /// The property has effect only in the case if + /// property is set to 0. Otherwise it does not have effect and background + /// update is managed according to the + /// property settings. + /// + /// + public int FramesPerBackgroundUpdate + { + get { return framesPerBackgroundUpdate; } + set { framesPerBackgroundUpdate = Math.Max( 1, Math.Min( 50, value ) ); } + } + + /// + /// Milliseconds per background update, [0, 5000]. + /// + /// + /// The value represents alternate way of controlling the speed of modeled + /// background adaptation to scene changes. The value sets number of milliseconds, which + /// should elapse between two consequent video frames to result in background update + /// for one intensity level. For example, if this value is set to 100 milliseconds and + /// the amount of time elapsed between two last video frames equals to 350, then background + /// frame will be update for 3 intensity levels in the direction to decrease difference + /// with current video frame (the remained 50 milliseconds will be added to time difference + /// between two next consequent frames, so the accuracy is preserved). + /// + /// Unlike background update method controlled using + /// method, the method guided by this property is not affected by changes + /// in frame rates. If, for some reasons, a video source starts to provide delays between + /// frames (frame rate drops down), the amount of background update still stays consistent. + /// When background update is controlled by this property, it is always possible to estimate + /// amount of time required to change, for example, absolutely black background (0 intensity + /// values) into absolutely white background (255 intensity values). If value of this + /// property is set to 100, then it will take approximately 25.5 seconds for such update + /// regardless of frame rate. + /// + /// Background update controlled by this property is slightly slower then + /// background update controlled by property, + /// so it has a bit greater impact on performance. + /// + /// If this property is set to 0, then corresponding background updating + /// method is not used (turned off), but background update guided by + /// property is used. + /// + /// Default value is set to 0. + /// + /// + public int MillisecondsPerBackgroundUpdate + { + get { return millisecondsPerBackgroundUpdate; } + set { millisecondsPerBackgroundUpdate = Math.Max( 0, Math.Min( 5000, value ) ); } + } + + /// + /// Initializes a new instance of the class. + /// + public SimpleBackgroundModelingDetector( ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Suppress noise in video frames or not (see property). + /// + public SimpleBackgroundModelingDetector( bool suppressNoise ) + { + this.suppressNoise = suppressNoise; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Suppress noise in video frames or not (see property). + /// Restore objects edges after noise suppression or not (see property). + /// + public SimpleBackgroundModelingDetector( bool suppressNoise, bool keepObjectEdges ) + { + this.suppressNoise = suppressNoise; + this.keepObjectEdges = keepObjectEdges; + } + + /// + /// Process new video frame. + /// + /// + /// Video frame to process (detect motion in). + /// + /// Processes new frame from video source and detects motion in it. + /// + /// Check property to get information about amount of motion + /// (changes) in the processed frame. + /// + /// + public void ProcessFrame( UnmanagedImage videoFrame ) + { + lock ( sync ) + { + // check background frame + if ( backgroundFrame == null ) + { + lastTimeMeasurment = DateTime.Now; + + // save image dimension + width = videoFrame.Width; + height = videoFrame.Height; + + // alocate memory for previous and current frames + backgroundFrame = UnmanagedImage.Create( width, height, PixelFormat.Format8bppIndexed ); + motionFrame = UnmanagedImage.Create( width, height, PixelFormat.Format8bppIndexed ); + + frameSize = motionFrame.Stride * height; + + // temporary buffer + if ( suppressNoise ) + { + tempFrame = UnmanagedImage.Create( width, height, PixelFormat.Format8bppIndexed ); + } + + // convert source frame to grayscale + Tools.ConvertToGrayscale( videoFrame, backgroundFrame ); + + return; + } + + // check image dimension + if ( ( videoFrame.Width != width ) || ( videoFrame.Height != height ) ) + return; + + // convert current image to grayscale + Tools.ConvertToGrayscale( videoFrame, motionFrame ); + + unsafe + { + // pointers to background and current frames + byte* backFrame; + byte* currFrame; + int diff; + + // update background frame + if ( millisecondsPerBackgroundUpdate == 0 ) + { + // update background frame using frame counter as a base + if ( ++framesCounter == framesPerBackgroundUpdate ) + { + framesCounter = 0; + + backFrame = (byte*) backgroundFrame.ImageData.ToPointer( ); + currFrame = (byte*) motionFrame.ImageData.ToPointer( ); + + for ( int i = 0; i < frameSize; i++, backFrame++, currFrame++ ) + { + diff = *currFrame - *backFrame; + if ( diff > 0 ) + { + ( *backFrame )++; + } + else if ( diff < 0 ) + { + ( *backFrame )--; + } + } + } + } + else + { + // update background frame using timer as a base + + // get current time and calculate difference + DateTime currentTime = DateTime.Now; + TimeSpan timeDff = currentTime - lastTimeMeasurment; + // save current time as the last measurment + lastTimeMeasurment = currentTime; + + int millisonds = (int) timeDff.TotalMilliseconds + millisecondsLeftUnprocessed; + + // save remainder so it could be taken into account in the future + millisecondsLeftUnprocessed = millisonds % millisecondsPerBackgroundUpdate; + // get amount for background update + int updateAmount = (int) ( millisonds / millisecondsPerBackgroundUpdate ); + + backFrame = (byte*) backgroundFrame.ImageData.ToPointer( ); + currFrame = (byte*) motionFrame.ImageData.ToPointer( ); + + for ( int i = 0; i < frameSize; i++, backFrame++, currFrame++ ) + { + diff = *currFrame - *backFrame; + if ( diff > 0 ) + { + ( *backFrame ) += (byte) ( ( diff < updateAmount ) ? diff : updateAmount ); + } + else if ( diff < 0 ) + { + ( *backFrame ) += (byte) ( ( -diff < updateAmount ) ? diff : -updateAmount ); + } + } + } + + backFrame = (byte*) backgroundFrame.ImageData.ToPointer( ); + currFrame = (byte*) motionFrame.ImageData.ToPointer( ); + + // 1 - get difference between frames + // 2 - threshold the difference + for ( int i = 0; i < frameSize; i++, backFrame++, currFrame++ ) + { + // difference + diff = (int) *currFrame - (int) *backFrame; + // treshold + *currFrame = ( ( diff >= differenceThreshold ) || ( diff <= differenceThresholdNeg ) ) ? (byte) 255 : (byte) 0; + } + + if ( suppressNoise ) + { + // suppress noise and calculate motion amount + AForge.SystemTools.CopyUnmanagedMemory( tempFrame.ImageData, motionFrame.ImageData, frameSize ); + erosionFilter.Apply( tempFrame, motionFrame ); + + if ( keepObjectEdges ) + { + AForge.SystemTools.CopyUnmanagedMemory( tempFrame.ImageData, motionFrame.ImageData, frameSize ); + dilatationFilter.Apply( tempFrame, motionFrame ); + } + } + + // calculate amount of motion pixels + pixelsChanged = 0; + byte* motion = (byte*) motionFrame.ImageData.ToPointer( ); + + for ( int i = 0; i < frameSize; i++, motion++ ) + { + pixelsChanged += ( *motion & 1 ); + } + } + } + } + + /// + /// Reset motion detector to initial state. + /// + /// + /// Resets internal state and variables of motion detection algorithm. + /// Usually this is required to be done before processing new video source, but + /// may be also done at any time to restart motion detection algorithm. + /// + /// + public void Reset( ) + { + lock ( sync ) + { + if ( backgroundFrame != null ) + { + backgroundFrame.Dispose( ); + backgroundFrame = null; + } + + if ( motionFrame != null ) + { + motionFrame.Dispose( ); + motionFrame = null; + } + + if ( tempFrame != null ) + { + tempFrame.Dispose( ); + tempFrame = null; + } + + framesCounter = 0; + } + } + } +} diff --git a/Sources/Accord.Vision/AForge/Motion/TwoFramesDifferenceDetector.cs b/Sources/Accord.Vision/AForge/Motion/TwoFramesDifferenceDetector.cs new file mode 100644 index 0000000000..196246c14 --- /dev/null +++ b/Sources/Accord.Vision/AForge/Motion/TwoFramesDifferenceDetector.cs @@ -0,0 +1,323 @@ +// AForge Vision Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Vision.Motion +{ + using System; + using System.Drawing.Imaging; + + using AForge.Imaging; + using AForge.Imaging.Filters; + + /// + /// Motion detector based on two continues frames difference. + /// + /// + /// The class implements the simplest motion detection algorithm, which is + /// based on difference of two continues frames. The difference frame + /// is thresholded and the amount of difference pixels is calculated. + /// To suppress stand-alone noisy pixels erosion morphological operator may be applied, which + /// is controlled by property. + /// + /// Although the class may be used on its own to perform motion detection, it is preferred + /// to use it in conjunction with class, which provides additional + /// features and allows to use moton post processing algorithms. + /// + /// Sample usage: + /// + /// // create motion detector + /// MotionDetector detector = new MotionDetector( + /// new TwoFramesDifferenceDetector( ), + /// new MotionAreaHighlighting( ) ); + /// + /// // continuously feed video frames to motion detector + /// while ( ... ) + /// { + /// // process new video frame and check motion level + /// if ( detector.ProcessFrame( videoFrame ) > 0.02 ) + /// { + /// // ring alarm or do somethng else + /// } + /// } + /// + /// + /// + /// + /// + public class TwoFramesDifferenceDetector : IMotionDetector + { + // frame's dimension + private int width; + private int height; + private int frameSize; + + // previous frame of video stream + private UnmanagedImage previousFrame; + // current frame of video sream + private UnmanagedImage motionFrame; + // temporary buffer used for suppressing noise + private UnmanagedImage tempFrame; + // number of pixels changed in the new frame of video stream + private int pixelsChanged; + + // suppress noise + private bool suppressNoise = true; + + // threshold values + private int differenceThreshold = 15; + private int differenceThresholdNeg = -15; + + // binary erosion filter + private BinaryErosion3x3 erosionFilter = new BinaryErosion3x3( ); + + // dummy object to lock for synchronization + private object sync = new object( ); + + /// + /// Difference threshold value, [1, 255]. + /// + /// + /// The value specifies the amount off difference between pixels, which is treated + /// as motion pixel. + /// + /// Default value is set to 15. + /// + /// + public int DifferenceThreshold + { + get { return differenceThreshold; } + set + { + lock ( sync ) + { + differenceThreshold = Math.Max( 1, Math.Min( 255, value ) ); + differenceThresholdNeg = -differenceThreshold; + } + } + } + + /// + /// Motion level value, [0, 1]. + /// + /// + /// Amount of changes in the last processed frame. For example, if value of + /// this property equals to 0.1, then it means that last processed frame has 10% difference + /// with previous frame. + /// + /// + public float MotionLevel + { + get + { + lock ( sync ) + { + return (float) pixelsChanged / ( width * height ); + } + } + } + + /// + /// Motion frame containing detected areas of motion. + /// + /// + /// Motion frame is a grayscale image, which shows areas of detected motion. + /// All black pixels in the motion frame correspond to areas, where no motion is + /// detected. But white pixels correspond to areas, where motion is detected. + /// + /// The property is set to after processing of the first + /// video frame by the algorithm. + /// + /// + public UnmanagedImage MotionFrame + { + get + { + lock ( sync ) + { + return motionFrame; + } + } + } + + /// + /// Suppress noise in video frames or not. + /// + /// + /// The value specifies if additional filtering should be + /// done to suppress standalone noisy pixels by applying 3x3 erosion image processing + /// filter. + /// + /// Default value is set to . + /// + /// Turning the value on leads to more processing time of video frame. + /// + /// + public bool SuppressNoise + { + get { return suppressNoise; } + set + { + lock ( sync ) + { + suppressNoise = value; + + // allocate temporary frame if required + if ( ( suppressNoise ) && ( tempFrame == null ) && ( motionFrame != null ) ) + { + tempFrame = UnmanagedImage.Create( width, height, PixelFormat.Format8bppIndexed ); + } + + // check if temporary frame is not required + if ( ( !suppressNoise ) && ( tempFrame != null ) ) + { + tempFrame.Dispose( ); + tempFrame = null; + } + } + } + } + + /// + /// Initializes a new instance of the class. + /// + /// + public TwoFramesDifferenceDetector( ) { } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Suppress noise in video frames or not (see property). + /// + public TwoFramesDifferenceDetector( bool suppressNoise ) + { + this.suppressNoise = suppressNoise; + } + + /// + /// Process new video frame. + /// + /// + /// Video frame to process (detect motion in). + /// + /// Processes new frame from video source and detects motion in it. + /// + /// Check property to get information about amount of motion + /// (changes) in the processed frame. + /// + /// + public void ProcessFrame( UnmanagedImage videoFrame ) + { + lock ( sync ) + { + // check previous frame + if ( previousFrame == null ) + { + // save image dimension + width = videoFrame.Width; + height = videoFrame.Height; + + // alocate memory for previous and current frames + previousFrame = UnmanagedImage.Create( width, height, PixelFormat.Format8bppIndexed ); + motionFrame = UnmanagedImage.Create( width, height, PixelFormat.Format8bppIndexed ); + + frameSize = motionFrame.Stride * height; + + // temporary buffer + if ( suppressNoise ) + { + tempFrame = UnmanagedImage.Create( width, height, PixelFormat.Format8bppIndexed ); + } + + // convert source frame to grayscale + Tools.ConvertToGrayscale( videoFrame, previousFrame ); + + return; + } + + // check image dimension + if ( ( videoFrame.Width != width ) || ( videoFrame.Height != height ) ) + return; + + // convert current image to grayscale + Tools.ConvertToGrayscale( videoFrame, motionFrame ); + + unsafe + { + // pointers to previous and current frames + byte* prevFrame = (byte*) previousFrame.ImageData.ToPointer( ); + byte* currFrame = (byte*) motionFrame.ImageData.ToPointer( ); + // difference value + int diff; + + // 1 - get difference between frames + // 2 - threshold the difference + // 3 - copy current frame to previous frame + for ( int i = 0; i < frameSize; i++, prevFrame++, currFrame++ ) + { + // difference + diff = (int) *currFrame - (int) *prevFrame; + // copy current frame to previous + *prevFrame = *currFrame; + // treshold + *currFrame = ( ( diff >= differenceThreshold ) || ( diff <= differenceThresholdNeg ) ) ? (byte) 255 : (byte) 0; + } + + if ( suppressNoise ) + { + // suppress noise and calculate motion amount + AForge.SystemTools.CopyUnmanagedMemory( tempFrame.ImageData, motionFrame.ImageData, frameSize ); + erosionFilter.Apply( tempFrame, motionFrame ); + } + + // calculate amount of motion pixels + pixelsChanged = 0; + byte* motion = (byte*) motionFrame.ImageData.ToPointer( ); + + for ( int i = 0; i < frameSize; i++, motion++ ) + { + pixelsChanged += ( *motion & 1 ); + } + } + } + } + + /// + /// Reset motion detector to initial state. + /// + /// + /// Resets internal state and variables of motion detection algorithm. + /// Usually this is required to be done before processing new video source, but + /// may be also done at any time to restart motion detection algorithm. + /// + /// + public void Reset( ) + { + lock ( sync ) + { + if ( previousFrame != null ) + { + previousFrame.Dispose( ); + previousFrame = null; + } + + if ( motionFrame != null ) + { + motionFrame.Dispose( ); + motionFrame = null; + } + + if ( tempFrame != null ) + { + tempFrame.Dispose( ); + tempFrame = null; + } + } + } + } +} \ No newline at end of file diff --git a/Sources/Accord.Vision/AForge/Tools.cs b/Sources/Accord.Vision/AForge/Tools.cs new file mode 100644 index 0000000000..1e29a2c61 --- /dev/null +++ b/Sources/Accord.Vision/AForge/Tools.cs @@ -0,0 +1,32 @@ +// AForge Vision Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2005-2011 +// contacts@aforgenet.com +// + +namespace AForge.Vision +{ + using System; + using System.Drawing; + using System.Drawing.Imaging; + using AForge.Imaging; + using AForge.Imaging.Filters; + + internal static class Tools + { + // Get grayscale image out of the specified one + public static void ConvertToGrayscale( UnmanagedImage source, UnmanagedImage destination ) + { + if ( source.PixelFormat != PixelFormat.Format8bppIndexed ) + { + Grayscale.CommonAlgorithms.BT709.Apply( source, destination ); + } + else + { + source.Copy( destination ); + } + } + } +} diff --git a/Sources/Accord.Vision/Accord.Vision.csproj b/Sources/Accord.Vision/Accord.Vision.csproj index 1e0a2c964..7ad76c40d 100644 --- a/Sources/Accord.Vision/Accord.Vision.csproj +++ b/Sources/Accord.Vision/Accord.Vision.csproj @@ -36,47 +36,31 @@ False True DEBUG;TRACE - ..\..\Debug\ + $(SolutionDir)..\Debug\ - ..\..\Release\net35 + $(SolutionDir)..\Release\net35 TRACE;CODE_ANALYSIS;NET35 v3.5 true - ..\..\Release\net35\Accord.Vision.XML - ..\..\Release\net35\Accord.Vision.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net35\Accord.Vision.XML + $(SolutionDir)..\Release\net35\Accord.Vision.dll.CodeAnalysisLog.xml - ..\..\Release\net40 + $(SolutionDir)..\Release\net40 TRACE;CODE_ANALYSIS;NET40 v4.0 - ..\..\Release\net40\Accord.Vision.XML - ..\..\Release\net40\Accord.Vision.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net40\Accord.Vision.XML + $(SolutionDir)..\Release\net40\Accord.Vision.dll.CodeAnalysisLog.xml - ..\..\Release\net45 + $(SolutionDir)..\Release\net45 TRACE;CODE_ANALYSIS;NET45 v4.5 - ..\..\Release\net45\Accord.Vision.XML - ..\..\Release\net45\Accord.Vision.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net45\Accord.Vision.XML + $(SolutionDir)..\Release\net45\Accord.Vision.dll.CodeAnalysisLog.xml - - ..\..\Externals\AForge.NET\AForge.dll - False - - - ..\..\Externals\AForge.NET\AForge.Imaging.dll - False - - - ..\..\Externals\AForge.NET\AForge.Math.dll - False - - - ..\..\Externals\AForge.NET\AForge.Vision.dll - False - 3.5 @@ -103,7 +87,18 @@ + + + + + + + + + + + @@ -162,11 +157,11 @@ - - \ No newline at end of file + diff --git a/Sources/Accord.Vision/Properties/AssemblyInfo.cs b/Sources/Accord.Vision/Properties/AssemblyInfo.cs index 990e54b83..e3594cbe5 100644 --- a/Sources/Accord.Vision/Properties/AssemblyInfo.cs +++ b/Sources/Accord.Vision/Properties/AssemblyInfo.cs @@ -5,7 +5,7 @@ // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("Accord.Vision")] -[assembly: AssemblyDescription("Accord.NET - Statistics Library")] +[assembly: AssemblyDescription("Accord.NET - Vision Library")] [assembly: AssemblyConfiguration("")] // This sets the default COM visibility of types in the assembly to invisible. diff --git a/Sources/Accord.Vision/Tracking/Camshift.cs b/Sources/Accord.Vision/Tracking/Camshift.cs index 42092274c..f17e3013b 100644 --- a/Sources/Accord.Vision/Tracking/Camshift.cs +++ b/Sources/Accord.Vision/Tracking/Camshift.cs @@ -355,7 +355,7 @@ public Bitmap GetBackprojection() /// /// Generates a image of the histogram backprojection /// - public unsafe Bitmap GetBackprojection(PixelFormat format) + public Bitmap GetBackprojection(PixelFormat format) { return GetBackprojection(format, new Rectangle(0, 0, map.GetLength(1), map.GetLength(0))); @@ -388,7 +388,7 @@ public Bitmap GetBackprojection(PixelFormat format, Rectangle rectangle) /// /// Generates a image of the histogram backprojection /// - public unsafe void GetBackprojection(UnmanagedImage image, Rectangle rectangle) + public void GetBackprojection(UnmanagedImage image, Rectangle rectangle) { lock (sync) { @@ -404,45 +404,47 @@ public unsafe void GetBackprojection(UnmanagedImage image, Rectangle rectangle) int stride = image.Stride; int offset = stride - width * pixelSize; - - // Do work - fixed (float* map_ptr = &map[starty, startx]) + unsafe { - byte* dst = (byte*)image.ImageData.ToPointer(); - float* src = map_ptr; - - // Check if image is grayscale (8bpp) - if (format == PixelFormat.Format8bppIndexed) + // Do work + fixed (float* map_ptr = &map[starty, startx]) { - for (int y = 0; y < height; y++) + byte* dst = (byte*)image.ImageData.ToPointer(); + float* src = map_ptr; + + // Check if image is grayscale (8bpp) + if (format == PixelFormat.Format8bppIndexed) { - for (int x = 0; x < width; x++, dst++, src++) + for (int y = 0; y < height; y++) { - // probability map contains values between 0 and 1 - *dst = (byte)Math.Floor(255f * (*src)); + for (int x = 0; x < width; x++, dst++, src++) + { + // probability map contains values between 0 and 1 + *dst = (byte)Math.Floor(255f * (*src)); + } + dst += offset; + src += srcOffset; } - dst += offset; - src += srcOffset; } - } - else // Image is 24bpp - { - for (int y = 0; y < height; y++) + else // Image is 24bpp { - for (int x = 0; x < width; x++, dst += pixelSize, src++) + for (int y = 0; y < height; y++) { - // probability map contains values between 0 and 1 - byte value = (byte)Math.Floor(255f * (*src)); - *(dst + 0) = value; - *(dst + 1) = value; - *(dst + 2) = value; + for (int x = 0; x < width; x++, dst += pixelSize, src++) + { + // probability map contains values between 0 and 1 + byte value = (byte)Math.Floor(255f * (*src)); + *(dst + 0) = value; + *(dst + 1) = value; + *(dst + 2) = value; + } + dst += offset; + src += srcOffset; } - dst += offset; - src += srcOffset; } - } - } + } + } } } #endregion diff --git a/Sources/Extras/Accord.MachineLearning.GPL/Accord.MachineLearning (GPL).csproj b/Sources/Extras/Accord.MachineLearning.GPL/Accord.MachineLearning (GPL).csproj index e4f145058..1ee021f91 100644 --- a/Sources/Extras/Accord.MachineLearning.GPL/Accord.MachineLearning (GPL).csproj +++ b/Sources/Extras/Accord.MachineLearning.GPL/Accord.MachineLearning (GPL).csproj @@ -30,7 +30,7 @@ v4.5 - ..\..\..\Debug\ + $(SolutionDir)..\Debug\GPL\ Full False False @@ -38,34 +38,28 @@ DEBUG;TRACE - ..\..\..\Release\net35\GPL\ + $(SolutionDir)..\Release\net35\GPL\ TRACE;CODE_ANALYSIS;NET35 v3.5 true - ..\..\..\Release\net35\GPL\Accord.MachineLearning.GPL.XML - ..\..\..\Release\net35\GPL\Accord.MachineLearning.GPL.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net35\GPL\Accord.MachineLearning.GPL.XML + $(SolutionDir)..\Release\net35\GPL\Accord.MachineLearning.GPL.dll.CodeAnalysisLog.xml - ..\..\..\Release\net40\GPL\ + $(SolutionDir)..\Release\net40\GPL\ TRACE;CODE_ANALYSIS;NET40 v4.0 - ..\..\..\Release\net40\GPL\Accord.MachineLearning.GPL.XML - ..\..\..\Release\net40\GPL\Accord.MachineLearning.GPL.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net40\GPL\Accord.MachineLearning.GPL.XML + $(SolutionDir)..\Release\net40\GPL\Accord.MachineLearning.GPL.dll.CodeAnalysisLog.xml - ..\..\..\Release\net45\GPL\ + $(SolutionDir)..\Release\net45\GPL\ TRACE;CODE_ANALYSIS;NET45 v4.5 - ..\..\..\Release\net45\GPL\Accord.MachineLearning.GPL.XML - ..\..\..\Release\net45\GPL\Accord.MachineLearning.GPL.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net45\GPL\Accord.MachineLearning.GPL.XML + $(SolutionDir)..\Release\net45\GPL\Accord.MachineLearning.GPL.dll.CodeAnalysisLog.xml - - ..\..\..\Externals\AForge.NET\AForge.dll - - - ..\..\..\Externals\AForge.NET\AForge.Math.dll - @@ -113,4 +107,4 @@ --> - \ No newline at end of file + diff --git a/Sources/Extras/Accord.Math.NonCommercial/Accord.Math (Noncommercial).csproj b/Sources/Extras/Accord.Math.NonCommercial/Accord.Math (Noncommercial).csproj index 13bdc2881..0a72b9f87 100644 --- a/Sources/Extras/Accord.Math.NonCommercial/Accord.Math (Noncommercial).csproj +++ b/Sources/Extras/Accord.Math.NonCommercial/Accord.Math (Noncommercial).csproj @@ -29,7 +29,7 @@ GlobalSuppressions.cs - ..\..\..\Debug\ + $(SolutionDir)..\Debug\Noncommercial\ v4.5 Full False @@ -38,37 +38,29 @@ DEBUG;TRACE - ..\..\..\Release\net35\Noncommercial\ + $(SolutionDir)..\Release\net35\Noncommercial\ TRACE;CODE_ANALYSIS;NET35 v3.5 true - ..\..\..\Release\net35\Noncommercial\Accord.Math.Noncommercial.XML - ..\..\..\Release\net35\Noncommercial\Accord.Math.Noncommercial.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net35\Noncommercial\Accord.Math.Noncommercial.XML + $(SolutionDir)..\Release\net35\Noncommercial\Accord.Math.Noncommercial.dll.CodeAnalysisLog.xml - ..\..\..\Release\net40\Noncommercial\ + $(SolutionDir)..\Release\net40\Noncommercial\ TRACE;CODE_ANALYSIS;NET40 v4.0 - ..\..\..\Release\net40\Noncommercial\Accord.Math.Noncommercial.XML - ..\..\..\Release\net40\Noncommercial\Accord.Math.Noncommercial.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net40\Noncommercial\Accord.Math.Noncommercial.XML + $(SolutionDir)..\Release\net40\Noncommercial\Accord.Math.Noncommercial.dll.CodeAnalysisLog.xml - ..\..\..\Release\net45\Noncommercial\ + $(SolutionDir)..\Release\net45\Noncommercial\ TRACE;CODE_ANALYSIS;NET45 v4.5 - ..\..\..\Release\net45\Noncommercial\Accord.Math.Noncommercial.XML - ..\..\..\Release\net45\Noncommercial\Accord.Math.Noncommercial.dll.CodeAnalysisLog.xml + $(SolutionDir)..\Release\net45\Noncommercial\Accord.Math.Noncommercial.XML + $(SolutionDir)..\Release\net45\Noncommercial\Accord.Math.Noncommercial.dll.CodeAnalysisLog.xml - - ..\..\..\Externals\AForge.NET\AForge.dll - False - - - ..\..\..\Externals\AForge.NET\AForge.Math.dll - False - @@ -121,4 +113,4 @@ - \ No newline at end of file + diff --git a/Sources/Extras/Accord.Tests.MachineLearning.GPL/Accord.Tests.MachineLearning (GPL).csproj b/Sources/Extras/Accord.Tests.MachineLearning.GPL/Accord.Tests.MachineLearning (GPL).csproj index dacc560e4..3ad7576fb 100644 --- a/Sources/Extras/Accord.Tests.MachineLearning.GPL/Accord.Tests.MachineLearning (GPL).csproj +++ b/Sources/Extras/Accord.Tests.MachineLearning.GPL/Accord.Tests.MachineLearning (GPL).csproj @@ -4,7 +4,6 @@ {944A7FDE-890A-45CE-A958-AAE6553E2E24} Accord.Tests.Math Accord.Tests.Math - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} Debug AnyCPU v4.5 @@ -52,32 +51,26 @@ x86 - - ..\..\..\Externals\AForge.NET\AForge.dll - - - ..\..\..\Externals\AForge.NET\AForge.Math.dll + + ..\..\..\Externals\NUnit\nunit.framework.dll 3.5 + + + @@ -92,7 +85,6 @@ {A177A90C-8207-466A-AF70-F2B8452A42AC} Accord.Core - global {7ab4bbcc-6222-423d-9ff9-ba9cb7c09199} @@ -146,12 +138,15 @@ Designer + + + - \ No newline at end of file diff --git a/Sources/Extras/Accord.Tests.MachineLearning.GPL/SequentialMinimalOptimizationRegressionTest.cs b/Sources/Extras/Accord.Tests.MachineLearning.GPL/SequentialMinimalOptimizationRegressionTest.cs index ed00ae913..6bd646582 100644 --- a/Sources/Extras/Accord.Tests.MachineLearning.GPL/SequentialMinimalOptimizationRegressionTest.cs +++ b/Sources/Extras/Accord.Tests.MachineLearning.GPL/SequentialMinimalOptimizationRegressionTest.cs @@ -25,12 +25,12 @@ namespace Accord.Tests.MachineLearning.GPL using Accord.MachineLearning.VectorMachines; using Accord.MachineLearning.VectorMachines.Learning; using Accord.Statistics.Kernels; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass] + [TestFixture] public class SequentialMinimalOptimizationRegressionTest { - [TestMethod()] + [Test] public void TrainTest() { Accord.Math.Tools.SetupGenerator(0); diff --git a/Sources/Extras/Accord.Tests.Math.Noncommercial/Accord.Tests.Math (Noncommercial).csproj b/Sources/Extras/Accord.Tests.Math.Noncommercial/Accord.Tests.Math (Noncommercial).csproj index 44c02bef6..1b7996adc 100644 --- a/Sources/Extras/Accord.Tests.Math.Noncommercial/Accord.Tests.Math (Noncommercial).csproj +++ b/Sources/Extras/Accord.Tests.Math.Noncommercial/Accord.Tests.Math (Noncommercial).csproj @@ -4,7 +4,6 @@ {4C525826-D64B-4D2D-8BB3-33AF46649B05} Accord.Tests.Math Accord.Tests.Math.Noncommercial - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} Debug AnyCPU v4.5 @@ -52,32 +51,26 @@ x86 - - ..\..\..\Externals\AForge.NET\AForge.dll - - - ..\..\..\Externals\AForge.NET\AForge.Math.dll + + ..\..\..\Externals\NUnit\nunit.framework.dll 3.5 + + + @@ -92,7 +85,6 @@ {A177A90C-8207-466A-AF70-F2B8452A42AC} Accord.Core - global {F718E9A8-DB62-4785-8C49-4333A60D256A} @@ -138,12 +130,15 @@ Designer + + + - \ No newline at end of file diff --git a/Sources/Extras/Accord.Tests.Math.Noncommercial/Optimization/NonlinearConjugateGradientTest.cs b/Sources/Extras/Accord.Tests.Math.Noncommercial/Optimization/NonlinearConjugateGradientTest.cs index 9fff57835..13eaffde0 100644 --- a/Sources/Extras/Accord.Tests.Math.Noncommercial/Optimization/NonlinearConjugateGradientTest.cs +++ b/Sources/Extras/Accord.Tests.Math.Noncommercial/Optimization/NonlinearConjugateGradientTest.cs @@ -23,14 +23,14 @@ namespace Accord.Tests.Math { using Accord.Math.Optimization; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using System; - - [TestClass()] + using NUnit.Framework; + using System; + + [TestFixture] public class NonlinearConjugateGradientTest { - [TestMethod()] + [Test] public void MinimizeTest() { Func f = rosenbrockFunction; @@ -70,7 +70,7 @@ public void MinimizeTest() Assert.IsFalse(double.IsNaN(d[1])); } - [TestMethod()] + [Test] public void expDiffTest() { Accord.Math.Tools.SetupGenerator(0); @@ -114,7 +114,7 @@ private static void createExpDiff(out Func f, out Func function = // min f(x) = 10 * (x+1)^2 + y^2 @@ -139,27 +139,27 @@ public void ConstructorTest2() double expectedMinimum = function(target.Solution); Assert.AreEqual(expectedMinimum, minimum); - } - - - // The famous Rosenbrock test function. - public static double rosenbrockFunction(double[] x) - { - double a = x[1] - x[0] * x[0]; - double b = 1 - x[0]; - return b * b + 100 * a * a; - } - - // Gradient of the Rosenbrock test function. - public static double[] rosenbrockGradient(double[] x) - { - double a = x[1] - x[0] * x[0]; - double b = 1 - x[0]; - - double f0 = -2 * b - 400 * x[0] * a; - double f1 = 200 * a; - - return new[] { f0, f1 }; + } + + + // The famous Rosenbrock test function. + public static double rosenbrockFunction(double[] x) + { + double a = x[1] - x[0] * x[0]; + double b = 1 - x[0]; + return b * b + 100 * a * a; + } + + // Gradient of the Rosenbrock test function. + public static double[] rosenbrockGradient(double[] x) + { + double a = x[1] - x[0] * x[0]; + double b = 1 - x[0]; + + double f0 = -2 * b - 400 * x[0] * a; + double f1 = 200 * a; + + return new[] { f0, f1 }; } } } diff --git a/Sources/Extras/Accord.Video.FFMPEG.GPL/Accord.snk b/Sources/Extras/Accord.Video.FFMPEG.GPL/Accord.snk new file mode 100644 index 0000000000..ed97b4edd Binary files /dev/null and b/Sources/Extras/Accord.Video.FFMPEG.GPL/Accord.snk differ diff --git a/Sources/Extras/Accord.Video.FFMPEG.GPL/AssemblyInfo.cpp b/Sources/Extras/Accord.Video.FFMPEG.GPL/AssemblyInfo.cpp new file mode 100644 index 0000000000..d2e04d1a8 --- /dev/null +++ b/Sources/Extras/Accord.Video.FFMPEG.GPL/AssemblyInfo.cpp @@ -0,0 +1,17 @@ +#include "stdafx.h" + +using namespace System::Reflection; + +[assembly:AssemblyProduct("Accord.NET Framework")] +[assembly:AssemblyCopyright("Copyright Accord.NET authors, 2009-2015")] +[assembly:AssemblyCompany("Accord.NET")] +[assembly:AssemblyTrademark("")] +[assembly:AssemblyCulture("")] + +[assembly:AssemblyKeyFileAttribute("Accord.snk")]; +[assembly:AssemblyDelaySignAttribute(true)]; + +[assembly:AssemblyVersionAttribute("3.0.0.0")]; +[assembly:AssemblyInformationalVersion("3.0.0.0")]; +[assembly:AssemblyFileVersionAttribute("3.0.0.0")]; + diff --git a/Sources/Extras/Accord.Video.FFMPEG.GPL/Stdafx.cpp b/Sources/Extras/Accord.Video.FFMPEG.GPL/Stdafx.cpp new file mode 100644 index 0000000000..c338e3fc6 --- /dev/null +++ b/Sources/Extras/Accord.Video.FFMPEG.GPL/Stdafx.cpp @@ -0,0 +1,5 @@ +// stdafx.cpp : source file that includes just the standard includes +// Video.FFMPEG.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" diff --git a/Sources/Extras/Accord.Video.FFMPEG.GPL/Stdafx.h b/Sources/Extras/Accord.Video.FFMPEG.GPL/Stdafx.h new file mode 100644 index 0000000000..7da7ddf47 --- /dev/null +++ b/Sources/Extras/Accord.Video.FFMPEG.GPL/Stdafx.h @@ -0,0 +1,7 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, +// but are changed infrequently + +#pragma once + +#include \ No newline at end of file diff --git a/Sources/Extras/Accord.Video.FFMPEG.GPL/Video.FFMPEG.log b/Sources/Extras/Accord.Video.FFMPEG.GPL/Video.FFMPEG.log new file mode 100644 index 0000000000..100c85c0d --- /dev/null +++ b/Sources/Extras/Accord.Video.FFMPEG.GPL/Video.FFMPEG.log @@ -0,0 +1 @@ +C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V110\Microsoft.Cpp.Platform.targets(44,5): error MSB8020: The builds tools for v120 (Platform Toolset = 'v120') cannot be found. To build using the v120 build tools, either click the Project menu or right-click the solution, and then select "Update VC++ Projects...". Install v120 to build using the v120 build tools. diff --git a/Sources/Extras/Accord.Video.FFMPEG.GPL/Video.FFMPEG.sln b/Sources/Extras/Accord.Video.FFMPEG.GPL/Video.FFMPEG.sln new file mode 100644 index 0000000000..0905bb365 --- /dev/null +++ b/Sources/Extras/Accord.Video.FFMPEG.GPL/Video.FFMPEG.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C++ Express 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Video.FFMPEG", "Video.FFMPEG.vcxproj", "{FF31DD24-127D-4EB1-929C-F5738147E886}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FF31DD24-127D-4EB1-929C-F5738147E886}.Debug|Win32.ActiveCfg = Debug|Win32 + {FF31DD24-127D-4EB1-929C-F5738147E886}.Debug|Win32.Build.0 = Debug|Win32 + {FF31DD24-127D-4EB1-929C-F5738147E886}.Release|Win32.ActiveCfg = Release|Win32 + {FF31DD24-127D-4EB1-929C-F5738147E886}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Sources/Extras/Accord.Video.FFMPEG.GPL/Video.FFMPEG.vcxproj b/Sources/Extras/Accord.Video.FFMPEG.GPL/Video.FFMPEG.vcxproj new file mode 100644 index 0000000000..eeb9e8437 --- /dev/null +++ b/Sources/Extras/Accord.Video.FFMPEG.GPL/Video.FFMPEG.vcxproj @@ -0,0 +1,167 @@ + + + + + Debug + Win32 + + + NET35 + Win32 + + + NET40 + Win32 + + + NET45 + Win32 + + + + {FF31DD24-127D-4EB1-929C-F5738147E886} + VideoFFMPEG + Accord.Video.FFMPEG (GPL) + ManagedCProj + DynamicLibrary + v4.5 + Unicode + true + v120 + Accord.Video.FFMPEG + false + $(ProjectDir)obj\$(Configuration)\ + + + + v4.5 + + + v3.5 + true + + + v4.0 + true + + + v4.5 + true + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)..\Debug\GPL\ + $(SolutionDir)..\Release\net35\GPL\ + $(SolutionDir)..\Release\net40\GPL\ + $(SolutionDir)..\Release\net45\GPL\ + + + + $(SolutionDir)..\Externals\ffmpeg\include;$(SolutionDir)..\Externals\msinttypes;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;__STDC_CONSTANT_MACROS;%(PreprocessorDefinitions) + NotUsing + MultiThreadedDLL + Level3 + ProgramDatabase + + + avformat.lib;avcodec.lib;avutil.lib;swscale.lib + $(OutDir)$(TargetName).dll + $(ProjectDir)lib;$(SolutionDir)..\Externals\ffmpeg\lib;$(SolutionDir)..\Externals\ffmpeg\bin;%(AdditionalLibraryDirectories) + true + MachineX86 + /ignore:4248 %(AdditionalOptions) + + + false + + + + + Disabled + WIN32;_DEBUG;__STDC_CONSTANT_MACROS;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + + + true + true + + + + + true + Level3 + + + sn -Ra "$(TargetPath)" "$(ProjectDir)Accord.snk" + + + + + true + Level3 + + + sn -Ra "$(TargetPath)" "$(ProjectDir)Accord.snk" + + + + + true + Level3 + + + sn -Ra "$(TargetPath)" "$(ProjectDir)Accord.snk" + + + + + true + true + + + true + true + + + true + true + + + + + + Create + Create + Create + Create + + + + + + + + + + + + + + + + {809725dc-6502-4732-a51c-deb7fea12975} + + + + + + + + + \ No newline at end of file diff --git a/Sources/Extras/Accord.Video.FFMPEG.GPL/Video.FFMPEG.vcxproj.filters b/Sources/Extras/Accord.Video.FFMPEG.GPL/Video.FFMPEG.vcxproj.filters new file mode 100644 index 0000000000..219d5a81b --- /dev/null +++ b/Sources/Extras/Accord.Video.FFMPEG.GPL/Video.FFMPEG.vcxproj.filters @@ -0,0 +1,55 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + \ No newline at end of file diff --git a/Sources/Extras/Accord.Video.FFMPEG.GPL/VideoCodec.cpp b/Sources/Extras/Accord.Video.FFMPEG.GPL/VideoCodec.cpp new file mode 100644 index 0000000000..734a85d85 --- /dev/null +++ b/Sources/Extras/Accord.Video.FFMPEG.GPL/VideoCodec.cpp @@ -0,0 +1,48 @@ +// AForge FFMPEG Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2009-2011 +// contacts@aforgenet.com +// + +#include "StdAfx.h" +#include "VideoCodec.h" + +namespace libffmpeg +{ + extern "C" + { + #pragma warning(disable:4635) + #pragma warning(disable:4244) + #include "libavcodec\avcodec.h" + } +} + +int video_codecs[] = +{ + libffmpeg::CODEC_ID_MPEG4, + libffmpeg::CODEC_ID_WMV1, + libffmpeg::CODEC_ID_WMV2, + libffmpeg::CODEC_ID_MSMPEG4V2, + libffmpeg::CODEC_ID_MSMPEG4V3, + libffmpeg::CODEC_ID_H263P, + libffmpeg::CODEC_ID_FLV1, + libffmpeg::CODEC_ID_MPEG2VIDEO, + libffmpeg::CODEC_ID_RAWVIDEO +}; + +int pixel_formats[] = +{ + libffmpeg::PIX_FMT_YUV420P, + libffmpeg::PIX_FMT_YUV420P, + libffmpeg::PIX_FMT_YUV420P, + libffmpeg::PIX_FMT_YUV420P, + libffmpeg::PIX_FMT_YUV420P, + libffmpeg::PIX_FMT_YUV420P, + libffmpeg::PIX_FMT_YUV420P, + libffmpeg::PIX_FMT_YUV420P, + libffmpeg::PIX_FMT_BGR24, +}; + +int CODECS_COUNT ( sizeof( video_codecs ) / sizeof( libffmpeg::CodecID ) ); \ No newline at end of file diff --git a/Sources/Extras/Accord.Video.FFMPEG.GPL/VideoCodec.h b/Sources/Extras/Accord.Video.FFMPEG.GPL/VideoCodec.h new file mode 100644 index 0000000000..c26502cd9 --- /dev/null +++ b/Sources/Extras/Accord.Video.FFMPEG.GPL/VideoCodec.h @@ -0,0 +1,67 @@ +// AForge FFMPEG Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2009-2011 +// contacts@aforgenet.com +// + +#pragma once + +using namespace System; + +extern int video_codecs[]; +extern int pixel_formats[]; + +extern int CODECS_COUNT; + +namespace AForge { namespace Video { namespace FFMPEG +{ + /// + /// Enumeration of some video codecs from FFmpeg library, which are available for writing video files. + /// + public enum class VideoCodec + { + /// + /// Default video codec, which FFmpeg library selects for the specified file format. + /// + Default = -1, + /// + /// MPEG-4 part 2. + /// + MPEG4 = 0, + /// + /// Windows Media Video 7. + /// + WMV1, + /// + /// Windows Media Video 8. + /// + WMV2, + /// + /// MPEG-4 part 2 Microsoft variant version 2. + /// + MSMPEG4v2, + /// + /// MPEG-4 part 2 Microsoft variant version 3. + /// + MSMPEG4v3, + /// + /// H.263+ / H.263-1998 / H.263 version 2. + /// + H263P, + /// + /// Flash Video (FLV) / Sorenson Spark / Sorenson H.263. + /// + FLV1, + /// + /// MPEG-2 part 2. + /// + MPEG2, + /// + /// Raw (uncompressed) video. + /// + Raw, + }; + +} } } \ No newline at end of file diff --git a/Sources/Extras/Accord.Video.FFMPEG.GPL/VideoFileReader.cpp b/Sources/Extras/Accord.Video.FFMPEG.GPL/VideoFileReader.cpp new file mode 100644 index 0000000000..eb17cc591 --- /dev/null +++ b/Sources/Extras/Accord.Video.FFMPEG.GPL/VideoFileReader.cpp @@ -0,0 +1,321 @@ +// AForge FFMPEG Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2009-2012 +// contacts@aforgenet.com +// + +#include "StdAfx.h" +#include "VideoFileReader.h" + +namespace libffmpeg +{ + extern "C" + { + // disable warnings about badly formed documentation from FFmpeg, which we don't need at all + #pragma warning(disable:4635) + // disable warning about conversion int64 to int32 + #pragma warning(disable:4244) + + #include "libavformat\avformat.h" + #include "libavformat\avio.h" + #include "libavcodec\avcodec.h" + #include "libswscale\swscale.h" + } +} + +namespace AForge { namespace Video { namespace FFMPEG +{ +#pragma region Some private FFmpeg related stuff hidden out of header file + +// A structure to encapsulate all FFMPEG related private variable +ref struct ReaderPrivateData +{ +public: + libffmpeg::AVFormatContext* FormatContext; + libffmpeg::AVStream* VideoStream; + libffmpeg::AVCodecContext* CodecContext; + libffmpeg::AVFrame* VideoFrame; + struct libffmpeg::SwsContext* ConvertContext; + + libffmpeg::AVPacket* Packet; + int BytesRemaining; + + ReaderPrivateData( ) + { + FormatContext = NULL; + VideoStream = NULL; + CodecContext = NULL; + VideoFrame = NULL; + ConvertContext = NULL; + + Packet = NULL; + BytesRemaining = 0; + } +}; +#pragma endregion + +// Class constructor +VideoFileReader::VideoFileReader( void ) : + data( nullptr ), disposed( false ) +{ + libffmpeg::av_register_all( ); +} + +#pragma managed(push, off) +static libffmpeg::AVFormatContext* open_file( char* fileName ) +{ + libffmpeg::AVFormatContext* formatContext; + + if ( libffmpeg::av_open_input_file( &formatContext, fileName, NULL, 0, NULL ) !=0 ) + { + return NULL; + } + return formatContext; +} +#pragma managed(pop) + +// Opens the specified video file +void VideoFileReader::Open( String^ fileName ) +{ + CheckIfDisposed( ); + + // close previous file if any was open + Close( ); + + data = gcnew ReaderPrivateData( ); + data->Packet = new libffmpeg::AVPacket( ); + data->Packet->data = NULL; + + bool success = false; + + // convert specified managed String to UTF8 unmanaged string + IntPtr ptr = System::Runtime::InteropServices::Marshal::StringToHGlobalUni( fileName ); + wchar_t* nativeFileNameUnicode = (wchar_t*) ptr.ToPointer( ); + int utf8StringSize = WideCharToMultiByte( CP_UTF8, 0, nativeFileNameUnicode, -1, NULL, 0, NULL, NULL ); + char* nativeFileName = new char[utf8StringSize]; + WideCharToMultiByte( CP_UTF8, 0, nativeFileNameUnicode, -1, nativeFileName, utf8StringSize, NULL, NULL ); + + try + { + // open the specified video file + data->FormatContext = open_file( nativeFileName ); + if ( data->FormatContext == NULL ) + { + throw gcnew System::IO::IOException( "Cannot open the video file." ); + } + + // retrieve stream information + if ( libffmpeg::av_find_stream_info( data->FormatContext ) < 0 ) + { + throw gcnew VideoException( "Cannot find stream information." ); + } + + // search for the first video stream + for ( unsigned int i = 0; i < data->FormatContext->nb_streams; i++ ) + { + if( data->FormatContext->streams[i]->codec->codec_type == libffmpeg::AVMEDIA_TYPE_VIDEO ) + { + // get the pointer to the codec context for the video stream + data->CodecContext = data->FormatContext->streams[i]->codec; + data->VideoStream = data->FormatContext->streams[i]; + break; + } + } + if ( data->VideoStream == NULL ) + { + throw gcnew VideoException( "Cannot find video stream in the specified file." ); + } + + // find decoder for the video stream + libffmpeg::AVCodec* codec = libffmpeg::avcodec_find_decoder( data->CodecContext->codec_id ); + if ( codec == NULL ) + { + throw gcnew VideoException( "Cannot find codec to decode the video stream." ); + } + + // open the codec + if ( libffmpeg::avcodec_open( data->CodecContext, codec ) < 0 ) + { + throw gcnew VideoException( "Cannot open video codec." ); + } + + // allocate video frame + data->VideoFrame = libffmpeg::avcodec_alloc_frame( ); + + // prepare scaling context to convert RGB image to video format + data->ConvertContext = libffmpeg::sws_getContext( data->CodecContext->width, data->CodecContext->height, data->CodecContext->pix_fmt, + data->CodecContext->width, data->CodecContext->height, libffmpeg::PIX_FMT_BGR24, + SWS_BICUBIC, NULL, NULL, NULL ); + + if ( data->ConvertContext == NULL ) + { + throw gcnew VideoException( "Cannot initialize frames conversion context." ); + } + + // get some properties of the video file + m_width = data->CodecContext->width; + m_height = data->CodecContext->height; + m_frameRate = data->VideoStream->r_frame_rate.num / data->VideoStream->r_frame_rate.den; + m_codecName = gcnew String( data->CodecContext->codec->name ); + m_framesCount = data->VideoStream->nb_frames; + + success = true; + } + finally + { + System::Runtime::InteropServices::Marshal::FreeHGlobal( ptr ); + delete [] nativeFileName; + + if ( !success ) + { + Close( ); + } + } +} + +// Close current video file +void VideoFileReader::Close( ) +{ + if ( data != nullptr ) + { + if ( data->VideoFrame != NULL ) + { + libffmpeg::av_free( data->VideoFrame ); + } + + if ( data->CodecContext != NULL ) + { + libffmpeg::avcodec_close( data->CodecContext ); + } + + if ( data->FormatContext != NULL ) + { + libffmpeg::av_close_input_file( data->FormatContext ); + } + + if ( data->ConvertContext != NULL ) + { + libffmpeg::sws_freeContext( data->ConvertContext ); + } + + if ( data->Packet->data != NULL ) + { + libffmpeg::av_free_packet( data->Packet ); + } + + data = nullptr; + } +} + +// Read next video frame of the current video file +Bitmap^ VideoFileReader::ReadVideoFrame( ) +{ + CheckIfDisposed( ); + + if ( data == nullptr ) + { + throw gcnew System::IO::IOException( "Cannot read video frames since video file is not open." ); + } + + int frameFinished; + Bitmap^ bitmap = nullptr; + + int bytesDecoded; + bool exit = false; + + while ( true ) + { + // work on the current packet until we have decoded all of it + while ( data->BytesRemaining > 0 ) + { + // decode the next chunk of data + bytesDecoded = libffmpeg::avcodec_decode_video2( data->CodecContext, data->VideoFrame, &frameFinished, data->Packet ); + + // was there an error? + if ( bytesDecoded < 0 ) + { + throw gcnew VideoException( "Error while decoding frame." ); + } + + data->BytesRemaining -= bytesDecoded; + + // did we finish the current frame? Then we can return + if ( frameFinished ) + { + return DecodeVideoFrame( ); + } + } + + // read the next packet, skipping all packets that aren't + // for this stream + do + { + // free old packet if any + if ( data->Packet->data != NULL ) + { + libffmpeg::av_free_packet( data->Packet ); + data->Packet->data = NULL; + } + + // read new packet + if ( libffmpeg::av_read_frame( data->FormatContext, data->Packet ) < 0) + { + exit = true; + break; + } + } + while ( data->Packet->stream_index != data->VideoStream->index ); + + // exit ? + if ( exit ) + break; + + data->BytesRemaining = data->Packet->size; + } + + // decode the rest of the last frame + bytesDecoded = libffmpeg::avcodec_decode_video2( + data->CodecContext, data->VideoFrame, &frameFinished, data->Packet ); + + // free last packet + if ( data->Packet->data != NULL ) + { + libffmpeg::av_free_packet( data->Packet ); + data->Packet->data = NULL; + } + + // is there a frame + if ( frameFinished ) + { + bitmap = DecodeVideoFrame( ); + } + + return bitmap; +} + +// Decodes video frame into managed Bitmap +Bitmap^ VideoFileReader::DecodeVideoFrame( ) +{ + Bitmap^ bitmap = gcnew Bitmap( data->CodecContext->width, data->CodecContext->height, PixelFormat::Format24bppRgb ); + + // lock the bitmap + BitmapData^ bitmapData = bitmap->LockBits( System::Drawing::Rectangle( 0, 0, data->CodecContext->width, data->CodecContext->height ), + ImageLockMode::ReadOnly, PixelFormat::Format24bppRgb ); + + libffmpeg::uint8_t* ptr = reinterpret_cast( static_cast( bitmapData->Scan0 ) ); + + libffmpeg::uint8_t* srcData[4] = { ptr, NULL, NULL, NULL }; + int srcLinesize[4] = { bitmapData->Stride, 0, 0, 0 }; + + // convert video frame to the RGB bitmap + libffmpeg::sws_scale( data->ConvertContext, data->VideoFrame->data, data->VideoFrame->linesize, 0, + data->CodecContext->height, srcData, srcLinesize ); + + bitmap->UnlockBits( bitmapData ); + + return bitmap; +} + +} } } \ No newline at end of file diff --git a/Sources/Extras/Accord.Video.FFMPEG.GPL/VideoFileReader.h b/Sources/Extras/Accord.Video.FFMPEG.GPL/VideoFileReader.h new file mode 100644 index 0000000000..b1b7d5f7e --- /dev/null +++ b/Sources/Extras/Accord.Video.FFMPEG.GPL/VideoFileReader.h @@ -0,0 +1,242 @@ +// AForge FFMPEG Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2009-2011 +// contacts@aforgenet.com +// + +#pragma once + +using namespace System; +using namespace System::Drawing; +using namespace System::Drawing::Imaging; +using namespace AForge::Video; + +namespace AForge { namespace Video { namespace FFMPEG +{ + ref struct ReaderPrivateData; + + /// + /// Class for reading video files utilizing FFmpeg library. + /// + /// + /// The class allows to read video files using FFmpeg library. + /// + /// Make sure you have FFmpeg binaries (DLLs) in the output folder of your application in order + /// to use this class successfully. FFmpeg binaries can be found in Externals folder provided with AForge.NET + /// framework's distribution. + /// + /// Sample usage: + /// + /// // create instance of video reader + /// VideoFileReader reader = new VideoFileReader( ); + /// // open video file + /// reader.Open( "test.avi" ); + /// // check some of its attributes + /// Console.WriteLine( "width: " + reader.Width ); + /// Console.WriteLine( "height: " + reader.Height ); + /// Console.WriteLine( "fps: " + reader.FrameRate ); + /// Console.WriteLine( "codec: " + reader.CodecName ); + /// // read 100 video frames out of it + /// for ( int i = 0; i < 100; i++ ) + /// { + /// Bitmap videoFrame = reader.ReadVideoFrame( ); + /// // process the frame somehow + /// // ... + /// + /// // dispose the frame when it is no longer required + /// videoFrame.Dispose( ); + /// } + /// reader.Close( ); + /// + /// + /// + public ref class VideoFileReader : IDisposable + { + public: + + /// + /// Frame width of the opened video file. + /// + /// + /// Thrown if no video file was open. + /// + property int Width + { + int get( ) + { + CheckIfVideoFileIsOpen( ); + return m_width; + } + } + + /// + /// Frame height of the opened video file. + /// + /// + /// Thrown if no video file was open. + /// + property int Height + { + int get( ) + { + CheckIfVideoFileIsOpen( ); + return m_height; + } + } + + /// + /// Frame rate of the opened video file. + /// + /// + /// Thrown if no video file was open. + /// + property int FrameRate + { + int get( ) + { + CheckIfVideoFileIsOpen( ); + return m_frameRate; + } + } + + /// + /// Number of video frames in the opened video file. + /// + /// + /// Warning: some video file formats may report different value + /// from the actual number of video frames in the file (subject to fix/investigate). + /// + /// + /// Thrown if no video file was open. + /// + property Int64 FrameCount + { + Int64 get( ) + { + CheckIfVideoFileIsOpen( ); + return m_framesCount; + } + } + + /// + /// Name of codec used for encoding the opened video file. + /// + /// + /// Thrown if no video file was open. + /// + property String^ CodecName + { + String^ get( ) + { + CheckIfVideoFileIsOpen( ); + return m_codecName; + } + } + + /// + /// The property specifies if a video file is opened or not by this instance of the class. + /// + property bool IsOpen + { + bool get ( ) + { + return ( data != nullptr ); + } + } + + protected: + + /// + /// Object's finalizer. + /// + /// + !VideoFileReader( ) + { + Close( ); + } + + public: + + /// + /// Initializes a new instance of the class. + /// + /// + VideoFileReader( void ); + + /// + /// Disposes the object and frees its resources. + /// + /// + ~VideoFileReader( ) + { + this->!VideoFileReader( ); + disposed = true; + } + + /// + /// Open video file with the specified name. + /// + /// + /// Video file name to open. + /// + /// Cannot open video file with the specified name. + /// A error occurred while opening the video file. See exception message. + /// + void Open( String^ fileName ); + + /// + /// Read next video frame of the currently opened video file. + /// + /// + /// Returns next video frame of the opened file or if end of + /// file was reached. The returned video frame has 24 bpp color format. + /// + /// Thrown if no video file was open. + /// A error occurred while reading next video frame. See exception message. + /// + Bitmap^ ReadVideoFrame( ); + + /// + /// Close currently opened video file if any. + /// + /// + void Close( ); + + private: + + int m_width; + int m_height; + int m_frameRate; + String^ m_codecName; + Int64 m_framesCount; + + private: + Bitmap^ DecodeVideoFrame( ); + + // Checks if video file was opened + void CheckIfVideoFileIsOpen( ) + { + if ( data == nullptr ) + { + throw gcnew System::IO::IOException( "Video file is not open, so can not access its properties." ); + } + } + + // Check if the object was already disposed + void CheckIfDisposed( ) + { + if ( disposed ) + { + throw gcnew System::ObjectDisposedException( "The object was already disposed." ); + } + } + + private: + // private data of the class + ReaderPrivateData^ data; + bool disposed; + }; + +} } } diff --git a/Sources/Extras/Accord.Video.FFMPEG.GPL/VideoFileSource.cpp b/Sources/Extras/Accord.Video.FFMPEG.GPL/VideoFileSource.cpp new file mode 100644 index 0000000000..c76af0aaf --- /dev/null +++ b/Sources/Extras/Accord.Video.FFMPEG.GPL/VideoFileSource.cpp @@ -0,0 +1,148 @@ +// AForge FFMPEG Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2009-2011 +// contacts@aforgenet.com +// + +#include "StdAfx.h" +#include "VideoFileSource.h" +#include "VideoFileReader.h" + +namespace AForge { namespace Video { namespace FFMPEG +{ + +VideoFileSource::VideoFileSource( String^ fileName ) +{ + m_fileName = fileName; + m_workerThread = nullptr; + m_needToStop = nullptr; + + m_frameIntervalFromSource = true; + m_frameInterval = 0; +} + +void VideoFileSource::Start( ) +{ + if ( !IsRunning ) + { + // check source + if ( String::IsNullOrEmpty( m_fileName ) ) + { + throw gcnew ArgumentException( "Video file name is not specified." ); + } + + m_framesReceived = 0; + m_bytesReceived = 0; + + // create events + m_needToStop = gcnew ManualResetEvent( false ); + + // create and start new thread + m_workerThread = gcnew Thread( gcnew ThreadStart( this, &VideoFileSource::WorkerThreadHandler ) ); + m_workerThread->Name = m_fileName; // just for debugging + m_workerThread->Start( ); + } +} + +void VideoFileSource::SignalToStop( ) +{ + if ( m_workerThread != nullptr ) + { + // signal to stop + m_needToStop->Set( ); + } +} + +void VideoFileSource::WaitForStop( ) +{ + if ( m_workerThread != nullptr ) + { + // wait for thread stop + m_workerThread->Join( ); + + Free( ); + } +} + +void VideoFileSource::Stop( ) +{ + if ( IsRunning ) + { + m_workerThread->Abort( ); + WaitForStop( ); + } +} + +void VideoFileSource::Free( ) +{ + m_workerThread = nullptr; + + // release events + m_needToStop->Close( ); + m_needToStop = nullptr; +} + +void VideoFileSource::WorkerThreadHandler( ) +{ + ReasonToFinishPlaying reasonToStop = ReasonToFinishPlaying::StoppedByUser; + VideoFileReader^ videoReader = gcnew VideoFileReader( ); + + try + { + videoReader->Open( m_fileName ); + + // frame interval + int interval = ( m_frameIntervalFromSource ) ? + (int) ( 1000 / ( ( videoReader->FrameRate == 0 ) ? 25 : videoReader->FrameRate ) ) : + m_frameInterval; + + while ( !m_needToStop->WaitOne( 0, false ) ) + { + // start time + DateTime start = DateTime::Now; + + // get next video frame + Bitmap^ bitmap = videoReader->ReadVideoFrame( ); + + if ( bitmap == nullptr ) + { + reasonToStop = ReasonToFinishPlaying::EndOfStreamReached; + break; + } + + m_framesReceived++; + m_bytesReceived += bitmap->Width * bitmap->Height * + ( Bitmap::GetPixelFormatSize( bitmap->PixelFormat ) >> 3 ); + + // notify clients about the new video frame + NewFrame( this, gcnew NewFrameEventArgs( bitmap ) ); + + // dispose the frame since we no longer need it + delete bitmap; + + // wait for a while ? + if ( interval > 0 ) + { + // get frame extract duration + TimeSpan^ span = DateTime::Now.Subtract( start ); + + // miliseconds to sleep + int msec = interval - (int) span->TotalMilliseconds; + + if ( ( msec > 0 ) && ( m_needToStop->WaitOne( msec, false ) == true ) ) + break; + } + } + } + catch ( Exception^ exception ) + { + VideoSourceError( this, gcnew VideoSourceErrorEventArgs( exception->Message ) ); + } + + videoReader->Close( ); + PlayingFinished( this, reasonToStop ); +} + +} } } \ No newline at end of file diff --git a/Sources/Extras/Accord.Video.FFMPEG.GPL/VideoFileSource.h b/Sources/Extras/Accord.Video.FFMPEG.GPL/VideoFileSource.h new file mode 100644 index 0000000000..a5358f123 --- /dev/null +++ b/Sources/Extras/Accord.Video.FFMPEG.GPL/VideoFileSource.h @@ -0,0 +1,285 @@ +// AForge FFMPEG Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2009-2011 +// contacts@aforgenet.com +// + +#pragma once + +using namespace System; +using namespace System::Drawing; +using namespace System::Drawing::Imaging; +using namespace System::Threading; +using namespace AForge::Video; + +namespace AForge { namespace Video { namespace FFMPEG +{ + /// + /// Video source for video files. + /// + /// + /// The video source provides access to video files using FFmpeg library. + /// + /// The class provides video only. Sound is not supported. + /// + /// The class ignores presentation time of video frames while retrieving them from + /// video file. Instead it provides video frames according to the FPS rate of the video file + /// or the configured . + /// + /// Make sure you have FFmpeg binaries (DLLs) in the output folder of your application in order + /// to use this class successfully. FFmpeg binaries can be found in Externals folder provided with AForge.NET + /// framework's distribution. + /// + /// Sample usage: + /// + /// // create video source + /// VideoFileSource videoSource = new VideoFileSource( fileName ); + /// // set NewFrame event handler + /// videoSource.NewFrame += new NewFrameEventHandler( video_NewFrame ); + /// // start the video source + /// videoSource.Start( ); + /// // ... + /// + /// // New frame event handler, which is invoked on each new available video frame + /// private void video_NewFrame( object sender, NewFrameEventArgs eventArgs ) + /// { + /// // get new frame + /// Bitmap bitmap = eventArgs.Frame; + /// // process the frame + /// } + /// + /// + /// + public ref class VideoFileSource : IVideoSource + { + public: + + /// + /// New frame event. + /// + /// + /// Notifies clients about new available frame from video source. + /// + /// Since video source may have multiple clients, each client is responsible for + /// making a copy (cloning) of the passed video frame, because the video source disposes its + /// own original copy after notifying of clients. + /// + /// + virtual event NewFrameEventHandler^ NewFrame; + + /// + /// Video source error event. + /// + /// + /// This event is used to notify clients about any type of errors occurred in + /// video source object, for example internal exceptions. + /// + virtual event VideoSourceErrorEventHandler^ VideoSourceError; + + /// + /// Video playing finished event. + /// + /// + /// This event is used to notify clients that the video playing has finished. + /// + /// + virtual event PlayingFinishedEventHandler^ PlayingFinished; + + /// + /// Video source. + /// + /// + /// Video file name to play. + /// + property String^ Source + { + virtual String^ get( ) + { + return m_fileName; + } + void set( String^ fileName ) + { + m_fileName = fileName; + } + } + + /// + /// Received frames count. + /// + /// + /// Number of frames the video source provided from the moment of the last + /// access to the property. + /// + /// + property int FramesReceived + { + virtual int get( ) + { + int frames = m_framesReceived; + m_framesReceived = 0; + return frames; + } + } + + /// + /// Received bytes count. + /// + /// + /// Number of bytes the video source provided from the moment of the last + /// access to the property. + /// + /// + property long long BytesReceived + { + virtual long long get( ) + { + return 0; + } + } + + /// + /// State of the video source. + /// + /// + /// Current state of video source object - running or not. + /// + property bool IsRunning + { + virtual bool get( ) + { + if ( m_workerThread != nullptr ) + { + // check if the thread is still running + if ( m_workerThread->Join( 0 ) == false ) + return true; + + Free( ); + } + return false; + } + } + + /// + /// Frame interval. + /// + /// + /// The property sets the interval in milliseconds between frames. If the property is + /// set to 100, then the desired frame rate will be 10 frames per second. + /// + /// Setting this property to 0 leads to no delay between video frames - frames + /// are read as fast as possible. + /// + /// Setting this property has effect only when + /// is set to . + /// + /// Default value is set to 0. + /// + /// + property int FrameInterval + { + int get( ) + { + return m_frameInterval; + } + void set( int frameInterval ) + { + m_frameInterval = frameInterval; + } + } + + /// + /// Get frame interval from source or use manually specified. + /// + /// + /// The property specifies which frame rate to use for video playing. + /// If the property is set to , then video is played + /// with original frame rate, which is set in source video file. If the property is + /// set to , then custom frame rate is used, which is + /// calculated based on the manually specified frame interval. + /// + /// Default value is set to . + /// + /// + property bool FrameIntervalFromSource + { + bool get( ) + { + return m_frameIntervalFromSource; + } + void set( bool fpsFromSource ) + { + m_frameIntervalFromSource = fpsFromSource; + } + } + + public: + + /// + /// Initializes a new instance of the class. + /// + /// + VideoFileSource( String^ fileName ); + + /// + /// Start video source. + /// + /// + /// Starts video source and return execution to caller. Video source + /// object creates background thread and notifies about new frames with the + /// help of event. + /// + /// Video source is not specified. + /// + virtual void Start( ); + + /// + /// Signal video source to stop its work. + /// + /// + /// Signals video source to stop its background thread, stop to + /// provide new frames and free resources. + /// + virtual void SignalToStop( ); + + /// + /// Wait for video source has stopped. + /// + /// + /// Waits for source stopping after it was signalled to stop using + /// method. + /// + virtual void WaitForStop( ); + + /// + /// Stop video source. + /// + /// + /// Stops video source aborting its thread. + /// + /// Since the method aborts background thread, its usage is highly not preferred + /// and should be done only if there are no other options. The correct way of stopping camera + /// is signaling it stop and then + /// waiting for background thread's completion. + /// + /// + virtual void Stop( ); + + private: + String^ m_fileName; + Thread^ m_workerThread; + ManualResetEvent^ m_needToStop; + + int m_framesReceived; + int m_bytesReceived; + bool m_frameIntervalFromSource; + int m_frameInterval; + + + private: + void Free( ); + void WorkerThreadHandler( ); + }; + +} } } diff --git a/Sources/Extras/Accord.Video.FFMPEG.GPL/VideoFileWriter.cpp b/Sources/Extras/Accord.Video.FFMPEG.GPL/VideoFileWriter.cpp new file mode 100644 index 0000000000..afcefada6 --- /dev/null +++ b/Sources/Extras/Accord.Video.FFMPEG.GPL/VideoFileWriter.cpp @@ -0,0 +1,479 @@ +// AForge FFMPEG Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2009-2012 +// contacts@aforgenet.com +// + +#include "StdAfx.h" +#include "VideoFileWriter.h" + +namespace libffmpeg +{ + extern "C" + { + // disable warnings about badly formed documentation from FFmpeg, which don't need at all + #pragma warning(disable:4635) + // disable warning about conversion int64 to int32 + #pragma warning(disable:4244) + + #include "libavformat\avformat.h" + #include "libavformat\avio.h" + #include "libavcodec\avcodec.h" + #include "libswscale\swscale.h" + } +} + +namespace AForge { namespace Video { namespace FFMPEG +{ +#pragma region Some private FFmpeg related stuff hidden out of header file + +static void write_video_frame( WriterPrivateData^ data ); +static void open_video( WriterPrivateData^ data ); +static void add_video_stream( WriterPrivateData^ data, int width, int height, int frameRate, int bitRate, + enum libffmpeg::CodecID codec_id, enum libffmpeg::PixelFormat pixelFormat ); + +// A structure to encapsulate all FFMPEG related private variable +ref struct WriterPrivateData +{ +public: + libffmpeg::AVFormatContext* FormatContext; + libffmpeg::AVStream* VideoStream; + libffmpeg::AVFrame* VideoFrame; + struct libffmpeg::SwsContext* ConvertContext; + struct libffmpeg::SwsContext* ConvertContextGrayscale; + + libffmpeg::uint8_t* VideoOutputBuffer; + int VideoOutputBufferSize; + + WriterPrivateData( ) + { + FormatContext = NULL; + VideoStream = NULL; + VideoFrame = NULL; + ConvertContext = NULL; + ConvertContextGrayscale = NULL; + VideoOutputBuffer = NULL; + } +}; +#pragma endregion + +// Class constructor +VideoFileWriter::VideoFileWriter( void ) : + data( nullptr ), disposed( false ) +{ + libffmpeg::av_register_all( ); +} + +void VideoFileWriter::Open( String^ fileName, int width, int height ) +{ + Open( fileName, width, height, 25 ); +} + +void VideoFileWriter::Open( String^ fileName, int width, int height, int frameRate ) +{ + Open( fileName, width, height, frameRate, VideoCodec::Default ); +} + +void VideoFileWriter::Open( String^ fileName, int width, int height, int frameRate, VideoCodec codec ) +{ + Open( fileName, width, height, frameRate, codec, 400000 ); +} + +// Creates a video file with the specified name and properties +void VideoFileWriter::Open( String^ fileName, int width, int height, int frameRate, VideoCodec codec, int bitRate ) +{ + CheckIfDisposed( ); + + // close previous file if any open + Close( ); + + data = gcnew WriterPrivateData( ); + bool success = false; + + // check width and height + if ( ( ( width & 1 ) != 0 ) || ( ( height & 1 ) != 0 ) ) + { + throw gcnew ArgumentException( "Video file resolution must be a multiple of two." ); + } + + // check video codec + if ( ( (int) codec < -1 ) || ( (int) codec >= CODECS_COUNT ) ) + { + throw gcnew ArgumentException( "Invalid video codec is specified." ); + } + + m_width = width; + m_height = height; + m_codec = codec; + m_frameRate = frameRate; + m_bitRate = bitRate; + + // convert specified managed String to unmanaged string + IntPtr ptr = System::Runtime::InteropServices::Marshal::StringToHGlobalUni( fileName ); + wchar_t* nativeFileNameUnicode = (wchar_t*) ptr.ToPointer( ); + int utf8StringSize = WideCharToMultiByte( CP_UTF8, 0, nativeFileNameUnicode, -1, NULL, 0, NULL, NULL ); + char* nativeFileName = new char[utf8StringSize]; + WideCharToMultiByte( CP_UTF8, 0, nativeFileNameUnicode, -1, nativeFileName, utf8StringSize, NULL, NULL ); + + try + { + // gues about destination file format from its file name + libffmpeg::AVOutputFormat* outputFormat = libffmpeg::av_guess_format( NULL, nativeFileName, NULL ); + + if ( !outputFormat ) + { + // gues about destination file format from its short name + outputFormat = libffmpeg::av_guess_format( "mpeg", NULL, NULL ); + + if ( !outputFormat ) + { + throw gcnew VideoException( "Cannot find suitable output format." ); + } + } + + // prepare format context + data->FormatContext = libffmpeg::avformat_alloc_context( ); + + if ( !data->FormatContext ) + { + throw gcnew VideoException( "Cannot allocate format context." ); + } + data->FormatContext->oformat = outputFormat; + + // add video stream using the specified video codec + add_video_stream( data, width, height, frameRate, bitRate, + ( codec == VideoCodec::Default ) ? outputFormat->video_codec : (libffmpeg::CodecID) video_codecs[(int) codec], + ( codec == VideoCodec::Default ) ? libffmpeg::PIX_FMT_YUV420P : (libffmpeg::PixelFormat) pixel_formats[(int) codec] ); + + // set the output parameters (must be done even if no parameters) + if ( libffmpeg::av_set_parameters( data->FormatContext, NULL ) < 0 ) + { + throw gcnew VideoException( "Failed configuring format context." ); + } + + open_video( data ); + + // open output file + if ( !( outputFormat->flags & AVFMT_NOFILE ) ) + { + if ( libffmpeg::avio_open( &data->FormatContext->pb, nativeFileName, AVIO_FLAG_WRITE ) < 0 ) + { + throw gcnew System::IO::IOException( "Cannot open the video file." ); + } + } + + libffmpeg::av_write_header( data->FormatContext ); + + success = true; + } + finally + { + System::Runtime::InteropServices::Marshal::FreeHGlobal( ptr ); + delete [] nativeFileName; + + if ( !success ) + { + Close( ); + } + } +} + +// Close current video file +void VideoFileWriter::Close( ) +{ + if ( data != nullptr ) + { + if ( data->FormatContext ) + { + if ( data->FormatContext->pb != NULL ) + { + libffmpeg::av_write_trailer( data->FormatContext ); + } + + if ( data->VideoStream ) + { + libffmpeg::avcodec_close( data->VideoStream->codec ); + } + + if ( data->VideoFrame ) + { + libffmpeg::av_free( data->VideoFrame->data[0] ); + libffmpeg::av_free( data->VideoFrame ); + } + + if ( data->VideoOutputBuffer ) + { + libffmpeg::av_free( data->VideoOutputBuffer ); + } + + for ( unsigned int i = 0; i < data->FormatContext->nb_streams; i++ ) + { + libffmpeg::av_freep( &data->FormatContext->streams[i]->codec ); + libffmpeg::av_freep( &data->FormatContext->streams[i] ); + } + + if ( data->FormatContext->pb != NULL ) + { + libffmpeg::avio_close( data->FormatContext->pb ); + } + + libffmpeg::av_free( data->FormatContext ); + } + + if ( data->ConvertContext != NULL ) + { + libffmpeg::sws_freeContext( data->ConvertContext ); + } + + if ( data->ConvertContextGrayscale != NULL ) + { + libffmpeg::sws_freeContext( data->ConvertContextGrayscale ); + } + + data = nullptr; + } + + m_width = 0; + m_height = 0; +} + +// Writes new video frame to the opened video file +void VideoFileWriter::WriteVideoFrame( Bitmap^ frame ) +{ + WriteVideoFrame( frame, TimeSpan::MinValue ); +} + +// Writes new video frame to the opened video file +void VideoFileWriter::WriteVideoFrame( Bitmap^ frame, TimeSpan timestamp ) +{ + CheckIfDisposed( ); + + if ( data == nullptr ) + { + throw gcnew System::IO::IOException( "A video file was not opened yet." ); + } + + if ( ( frame->PixelFormat != PixelFormat::Format24bppRgb ) && + ( frame->PixelFormat != PixelFormat::Format32bppArgb ) && + ( frame->PixelFormat != PixelFormat::Format32bppPArgb ) && + ( frame->PixelFormat != PixelFormat::Format32bppRgb ) && + ( frame->PixelFormat != PixelFormat::Format8bppIndexed ) ) + { + throw gcnew ArgumentException( "The provided bitmap must be 24 or 32 bpp color image or 8 bpp grayscale image." ); + } + + if ( ( frame->Width != m_width ) || ( frame->Height != m_height ) ) + { + throw gcnew ArgumentException( "Bitmap size must be of the same as video size, which was specified on opening video file." ); + } + + // lock the bitmap + BitmapData^ bitmapData = frame->LockBits( System::Drawing::Rectangle( 0, 0, m_width, m_height ), + ImageLockMode::ReadOnly, + ( frame->PixelFormat == PixelFormat::Format8bppIndexed ) ? PixelFormat::Format8bppIndexed : PixelFormat::Format24bppRgb ); + + libffmpeg::uint8_t* ptr = reinterpret_cast( static_cast( bitmapData->Scan0 ) ); + + libffmpeg::uint8_t* srcData[4] = { ptr, NULL, NULL, NULL }; + int srcLinesize[4] = { bitmapData->Stride, 0, 0, 0 }; + + // convert source image to the format of the video file + if ( frame->PixelFormat == PixelFormat::Format8bppIndexed ) + { + libffmpeg::sws_scale( data->ConvertContextGrayscale, srcData, srcLinesize, 0, m_height, data->VideoFrame->data, data->VideoFrame->linesize ); + } + else + { + libffmpeg::sws_scale( data->ConvertContext, srcData, srcLinesize, 0, m_height, data->VideoFrame->data, data->VideoFrame->linesize ); + } + + frame->UnlockBits( bitmapData ); + + if ( timestamp.Ticks >= 0 ) + { + const double frameNumber = timestamp.TotalSeconds * m_frameRate; + data->VideoFrame->pts = static_cast( frameNumber ); + } + + // write the converted frame to the video file + write_video_frame( data ); +} + +#pragma region Private methods +// Writes video frame to opened video file +void write_video_frame( WriterPrivateData^ data ) +{ + libffmpeg::AVCodecContext* codecContext = data->VideoStream->codec; + int out_size, ret = 0; + + if ( data->FormatContext->oformat->flags & AVFMT_RAWPICTURE ) + { + Console::WriteLine( "raw picture must be written" ); + } + else + { + // encode the image + out_size = libffmpeg::avcodec_encode_video( codecContext, data->VideoOutputBuffer, + data->VideoOutputBufferSize, data->VideoFrame ); + + // if zero size, it means the image was buffered + if ( out_size > 0 ) + { + libffmpeg::AVPacket packet; + libffmpeg::av_init_packet( &packet ); + + if ( codecContext->coded_frame->pts != AV_NOPTS_VALUE ) + { + packet.pts = libffmpeg::av_rescale_q( codecContext->coded_frame->pts, codecContext->time_base, data->VideoStream->time_base ); + } + + if ( codecContext->coded_frame->key_frame ) + { + packet.flags |= AV_PKT_FLAG_KEY; + } + + packet.stream_index = data->VideoStream->index; + packet.data = data->VideoOutputBuffer; + packet.size = out_size; + + // write the compressed frame to the media file + ret = libffmpeg::av_interleaved_write_frame( data->FormatContext, &packet ); + } + else + { + // image was buffered + } + } + + if ( ret != 0 ) + { + throw gcnew VideoException( "Error while writing video frame." ); + } +} + +// Allocate picture of the specified format and size +static libffmpeg::AVFrame* alloc_picture( enum libffmpeg::PixelFormat pix_fmt, int width, int height ) +{ + libffmpeg::AVFrame* picture; + void* picture_buf; + int size; + + picture = libffmpeg::avcodec_alloc_frame( ); + if ( !picture ) + { + return NULL; + } + + size = libffmpeg::avpicture_get_size( pix_fmt, width, height ); + picture_buf = libffmpeg::av_malloc( size ); + if ( !picture_buf ) + { + libffmpeg::av_free( picture ); + return NULL; + } + + libffmpeg::avpicture_fill( (libffmpeg::AVPicture *) picture, (libffmpeg::uint8_t *) picture_buf, pix_fmt, width, height ); + + return picture; +} + +// Create new video stream and configure it +void add_video_stream( WriterPrivateData^ data, int width, int height, int frameRate, int bitRate, + enum libffmpeg::CodecID codecId, enum libffmpeg::PixelFormat pixelFormat ) +{ + libffmpeg::AVCodecContext* codecContex; + + // create new stream + data->VideoStream = libffmpeg::av_new_stream( data->FormatContext, 0 ); + if ( !data->VideoStream ) + { + throw gcnew VideoException( "Failed creating new video stream." ); + } + + codecContex = data->VideoStream->codec; + codecContex->codec_id = codecId; + codecContex->codec_type = libffmpeg::AVMEDIA_TYPE_VIDEO; + + // put sample parameters + codecContex->bit_rate = bitRate; + codecContex->width = width; + codecContex->height = height; + + // time base: this is the fundamental unit of time (in seconds) in terms + // of which frame timestamps are represented. for fixed-fps content, + // timebase should be 1/framerate and timestamp increments should be + // identically 1. + codecContex->time_base.den = frameRate; + codecContex->time_base.num = 1; + + codecContex->gop_size = 12; // emit one intra frame every twelve frames at most + codecContex->pix_fmt = pixelFormat; + + if ( codecContex->codec_id == libffmpeg::CODEC_ID_MPEG1VIDEO ) + { + // Needed to avoid using macroblocks in which some coeffs overflow. + // This does not happen with normal video, it just happens here as + // the motion of the chroma plane does not match the luma plane. + codecContex->mb_decision = 2; + } + + // some formats want stream headers to be separate + if( data->FormatContext->oformat->flags & AVFMT_GLOBALHEADER ) + { + codecContex->flags |= CODEC_FLAG_GLOBAL_HEADER; + } +} + +// Open video codec and prepare out buffer and picture +void open_video( WriterPrivateData^ data ) +{ + libffmpeg::AVCodecContext* codecContext = data->VideoStream->codec; + libffmpeg::AVCodec* codec = avcodec_find_encoder( codecContext->codec_id ); + + if ( !codec ) + { + throw gcnew VideoException( "Cannot find video codec." ); + } + + // open the codec + if ( avcodec_open( codecContext, codec ) < 0 ) + { + throw gcnew VideoException( "Cannot open video codec." ); + } + + data->VideoOutputBuffer = NULL; + if ( !( data->FormatContext->oformat->flags & AVFMT_RAWPICTURE ) ) + { + // allocate output buffer + data->VideoOutputBufferSize = 6 * codecContext->width * codecContext->height; // more than enough even for raw video + data->VideoOutputBuffer = (libffmpeg::uint8_t*) libffmpeg::av_malloc( data->VideoOutputBufferSize ); + } + + // allocate the encoded raw picture + data->VideoFrame = alloc_picture( codecContext->pix_fmt, codecContext->width, codecContext->height ); + + if ( !data->VideoFrame ) + { + throw gcnew VideoException( "Cannot allocate video picture." ); + } + + // prepare scaling context to convert RGB image to video format + data->ConvertContext = libffmpeg::sws_getContext( codecContext->width, codecContext->height, libffmpeg::PIX_FMT_BGR24, + codecContext->width, codecContext->height, codecContext->pix_fmt, + SWS_BICUBIC, NULL, NULL, NULL ); + // prepare scaling context to convert grayscale image to video format + data->ConvertContextGrayscale = libffmpeg::sws_getContext( codecContext->width, codecContext->height, libffmpeg::PIX_FMT_GRAY8, + codecContext->width, codecContext->height, codecContext->pix_fmt, + SWS_BICUBIC, NULL, NULL, NULL ); + + if ( ( data->ConvertContext == NULL ) || ( data->ConvertContextGrayscale == NULL ) ) + { + throw gcnew VideoException( "Cannot initialize frames conversion context." ); + } +} +#pragma endregion + +} } } + diff --git a/Sources/Extras/Accord.Video.FFMPEG.GPL/VideoFileWriter.h b/Sources/Extras/Accord.Video.FFMPEG.GPL/VideoFileWriter.h new file mode 100644 index 0000000000..43b221ceb --- /dev/null +++ b/Sources/Extras/Accord.Video.FFMPEG.GPL/VideoFileWriter.h @@ -0,0 +1,336 @@ +// AForge FFMPEG Library +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright AForge.NET, 2009-2011 +// contacts@aforgenet.com +// + +#pragma once + +using namespace System; +using namespace System::Drawing; +using namespace System::Drawing::Imaging; +using namespace AForge::Video; + +#include "VideoCodec.h" + +namespace AForge { namespace Video { namespace FFMPEG +{ + ref struct WriterPrivateData; + + /// + /// Class for writing video files utilizing FFmpeg library. + /// + /// + /// The class allows to write video files using FFmpeg library. + /// + /// Make sure you have FFmpeg binaries (DLLs) in the output folder of your application in order + /// to use this class successfully. FFmpeg binaries can be found in Externals folder provided with AForge.NET + /// framework's distribution. + /// + /// Sample usage: + /// + /// int width = 320; + /// int height = 240; + /// + /// // create instance of video writer + /// VideoFileWriter writer = new VideoFileWriter( ); + /// // create new video file + /// writer.Open( "test.avi", width, height, 25, VideoCodec.MPEG4 ); + /// // create a bitmap to save into the video file + /// Bitmap image = new Bitmap( width, height, PixelFormat.Format24bppRgb ); + /// // write 1000 video frames + /// for ( int i = 0; i < 1000; i++ ) + /// { + /// image.SetPixel( i % width, i % height, Color.Red ); + /// writer.WriteVideoFrame( image ); + /// } + /// writer.Close( ); + /// + /// + /// + public ref class VideoFileWriter : IDisposable + { + public: + + /// + /// Frame width of the opened video file. + /// + /// + /// Thrown if no video file was open. + /// + property int Width + { + int get( ) + { + CheckIfVideoFileIsOpen( ); + return m_width; + } + } + + /// + /// Frame height of the opened video file. + /// + /// + /// Thrown if no video file was open. + /// + property int Height + { + int get( ) + { + CheckIfVideoFileIsOpen( ); + return m_height; + } + } + + /// + /// Frame rate of the opened video file. + /// + /// + /// Thrown if no video file was open. + /// + property int FrameRate + { + int get( ) + { + CheckIfVideoFileIsOpen( ); + return m_frameRate; + } + } + + /// + /// Bit rate of the video stream. + /// + /// + /// Thrown if no video file was open. + /// + property int BitRate + { + int get( ) + { + CheckIfVideoFileIsOpen( ); + return m_bitRate; + } + } + + /// + /// Codec to use for the video file. + /// + /// + /// Thrown if no video file was open. + /// + property VideoCodec Codec + { + VideoCodec get( ) + { + CheckIfVideoFileIsOpen( ); + return m_codec; + } + } + + /// + /// The property specifies if a video file is opened or not by this instance of the class. + /// + property bool IsOpen + { + bool get ( ) + { + return ( data != nullptr ); + } + } + + protected: + + /// + /// Object's finalizer. + /// + /// + !VideoFileWriter( ) + { + Close( ); + } + + public: + + /// + /// Initializes a new instance of the class. + /// + /// + VideoFileWriter( void ); + + /// + /// Disposes the object and frees its resources. + /// + /// + ~VideoFileWriter( ) + { + this->!VideoFileWriter( ); + disposed = true; + } + + /// + /// Create video file with the specified name and attributes. + /// + /// + /// Video file name to create. + /// Frame width of the video file. + /// Frame height of the video file. + /// + /// See documentation to the + /// for more information and the list of possible exceptions. + /// + /// The method opens the video file using + /// codec and 25 fps frame rate. + /// + /// + void Open( String^ fileName, int width, int height ); + + /// + /// Create video file with the specified name and attributes. + /// + /// + /// Video file name to create. + /// Frame width of the video file. + /// Frame height of the video file. + /// Frame rate of the video file. + /// + /// See documentation to the + /// for more information and the list of possible exceptions. + /// + /// The method opens the video file using + /// codec. + /// + /// + void Open( String^ fileName, int width, int height, int frameRate ); + + /// + /// Create video file with the specified name and attributes. + /// + /// + /// Video file name to create. + /// Frame width of the video file. + /// Frame height of the video file. + /// Frame rate of the video file. + /// Video codec to use for compression. + /// + /// The methods creates new video file with the specified name. + /// If a file with such name already exists in the file system, it will be overwritten. + /// + /// When adding new video frames using method, + /// the video frame must have width and height as specified during file opening. + /// + /// + /// Video file resolution must be a multiple of two. + /// Invalid video codec is specified. + /// A error occurred while creating new video file. See exception message. + /// Cannot open video file with the specified name. + /// + void Open( String^ fileName, int width, int height, int frameRate, VideoCodec codec ); + + /// + /// Create video file with the specified name and attributes. + /// + /// + /// Video file name to create. + /// Frame width of the video file. + /// Frame height of the video file. + /// Frame rate of the video file. + /// Video codec to use for compression. + /// Bit rate of the video stream. + /// + /// The methods creates new video file with the specified name. + /// If a file with such name already exists in the file system, it will be overwritten. + /// + /// When adding new video frames using method, + /// the video frame must have width and height as specified during file opening. + /// + /// The bit rate parameter represents a trade-off value between video quality + /// and video file size. Higher bit rate value increase video quality and result in larger + /// file size. Smaller values result in opposite worse quality and small video files. + /// + /// + /// Video file resolution must be a multiple of two. + /// Invalid video codec is specified. + /// A error occurred while creating new video file. See exception message. + /// Cannot open video file with the specified name. + /// + void Open( String^ fileName, int width, int height, int frameRate, VideoCodec codec, int bitRate ); + + /// + /// Write new video frame into currently opened video file. + /// + /// + /// Bitmap to add as a new video frame. + /// + /// The specified bitmap must be either color 24 or 32 bpp image or grayscale 8 bpp (indexed) image. + /// + /// + /// Thrown if no video file was open. + /// The provided bitmap must be 24 or 32 bpp color image or 8 bpp grayscale image. + /// Bitmap size must be of the same as video size, which was specified on opening video file. + /// A error occurred while writing new video frame. See exception message. + /// + void WriteVideoFrame( Bitmap^ frame ); + + /// + /// Write new video frame with a specific timestamp into currently opened video file. + /// + /// + /// Bitmap to add as a new video frame. + /// Frame timestamp, total time since recording started. + /// + /// The specified bitmap must be either color 24 or 32 bpp image or grayscale 8 bpp (indexed) image. + /// + /// The parameter allows user to specify presentation + /// time of the frame being saved. However, it is user's responsibility to make sure the value is increasing + /// over time. + /// + /// + /// Thrown if no video file was open. + /// The provided bitmap must be 24 or 32 bpp color image or 8 bpp grayscale image. + /// Bitmap size must be of the same as video size, which was specified on opening video file. + /// A error occurred while writing new video frame. See exception message. + /// + void WriteVideoFrame( Bitmap^ frame, TimeSpan timestamp ); + + /// + /// Close currently opened video file if any. + /// + /// + void Close( ); + + private: + + int m_width; + int m_height; + int m_frameRate; + int m_bitRate; + VideoCodec m_codec; + + private: + // Checks if video file was opened + void CheckIfVideoFileIsOpen( ) + { + if ( data == nullptr ) + { + throw gcnew System::IO::IOException( "Video file is not open, so can not access its properties." ); + } + } + + // Check if the object was already disposed + void CheckIfDisposed( ) + { + if ( disposed ) + { + throw gcnew System::ObjectDisposedException( "The object was already disposed." ); + } + } + + private: + // private data of the class + WriterPrivateData^ data; + bool disposed; + }; + +} } } diff --git a/Tests.cmd b/Tests.cmd new file mode 100644 index 0000000000..60f2f0f2e --- /dev/null +++ b/Tests.cmd @@ -0,0 +1,23 @@ +@echo OFF +setlocal enabledelayedexpansion + +set TESTS=Unit Tests\bin\Release\net45\ +set NUNIT="Externals\NUnit\nunit-console-x86.exe" + +:: Run unit tests in the Mono solution +set LIST=%LIST% "%TESTS%Accord.Tests.Audio.dll" +set LIST=%LIST% "%TESTS%Accord.Tests.Controls.dll" +set LIST=%LIST% "%TESTS%Accord.Tests.Core.dll" +set LIST=%LIST% "%TESTS%Accord.Tests.Imaging.dll" +set LIST=%LIST% "%TESTS%Accord.Tests.IO.dll" +set LIST=%LIST% "%TESTS%Accord.Tests.MachineLearning.dll" +set LIST=%LIST% "%TESTS%Accord.Tests.Math.dll" +set LIST=%LIST% "%TESTS%Accord.Tests.Neuro.dll" +set LIST=%LIST% "%TESTS%Accord.Tests.Vision.dll" +set LIST=%LIST% "%TESTS%Accord.Tests.Statistics.dll" + +%NUNIT% -noxml -nodots -labels /process=multiple %LIST% /framework:net-4.0 + + + + diff --git a/Tests.sh b/Tests.sh new file mode 100755 index 0000000000..736aa1831 --- /dev/null +++ b/Tests.sh @@ -0,0 +1,21 @@ +#!/bin/bash +########### + +TESTS="Unit Tests/bin/Release/net40/" +NUNIT="Externals/NUnit/nunit-console-x86.exe" +LIST=() + +# Run unit tests in the Mono solution +LIST+=("${TESTS}Accord.Tests.Audio.dll") +LIST+=("${TESTS}Accord.Tests.Controls.dll") +LIST+=("${TESTS}Accord.Tests.Core.dll") +LIST+=("${TESTS}Accord.Tests.Imaging.dll") +LIST+=("${TESTS}Accord.Tests.IO.dll") +LIST+=("${TESTS}Accord.Tests.MachineLearning.dll") +LIST+=("${TESTS}Accord.Tests.Math.dll") +LIST+=("${TESTS}Accord.Tests.Neuro.dll") +LIST+=("${TESTS}Accord.Tests.Vision.dll") +LIST+=("${TESTS}Accord.Tests.Statistics.dll") + + +mono --runtime=v4.0 ${NUNIT} -noxml -nodots -labels -exclude:Intensive,WinForms,Office -process=multiple "${LIST[@]/#/}" diff --git a/Tools/DebuggerVisualizers/AForge.DebuggerVisualizers.snk b/Tools/DebuggerVisualizers/AForge.DebuggerVisualizers.snk new file mode 100644 index 0000000000..2a664a9ad Binary files /dev/null and b/Tools/DebuggerVisualizers/AForge.DebuggerVisualizers.snk differ diff --git a/Tools/DebuggerVisualizers/BitmapDataVisualizer.cs b/Tools/DebuggerVisualizers/BitmapDataVisualizer.cs new file mode 100644 index 0000000000..7d8156e0a --- /dev/null +++ b/Tools/DebuggerVisualizers/BitmapDataVisualizer.cs @@ -0,0 +1,47 @@ +// AForge debugging visualizers +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2011 +// contacts@aforgenet.com +// + +using System; +using System.IO; +using System.Drawing; +using System.Drawing.Imaging; +using System.Windows.Forms; +using System.Runtime.Serialization.Formatters.Binary; +using Microsoft.VisualStudio.DebuggerVisualizers; + +[assembly: System.Diagnostics.DebuggerVisualizer( + typeof( AForge.DebuggerVisualizers.BitmapDataVisualizer ), + typeof( AForge.DebuggerVisualizers.BitmapDataObjectSource ), + Target = typeof( System.Drawing.Imaging.BitmapData ), + Description = "Bitmap Data Visualizer" )] + +namespace AForge.DebuggerVisualizers +{ + class BitmapDataVisualizer : DialogDebuggerVisualizer + { + override protected void Show( IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider ) + { + Image image = (Image) objectProvider.GetObject( ); + + ImageView imageViewer = new ImageView( ); + imageViewer.SetImage( image ); + + windowService.ShowDialog( imageViewer ); + } + } + + public class BitmapDataObjectSource : VisualizerObjectSource + { + public override void GetData( object target, Stream outgoingData ) + { + BinaryFormatter bf = new BinaryFormatter( ); + bf.Serialize( outgoingData, + ( new AForge.Imaging.UnmanagedImage( (BitmapData) target ) ).ToManagedImage( ) ); + } + } +} diff --git a/Tools/DebuggerVisualizers/DebuggerVisualizers (2008).csproj b/Tools/DebuggerVisualizers/DebuggerVisualizers (2008).csproj new file mode 100644 index 0000000000..af01f4bf9 --- /dev/null +++ b/Tools/DebuggerVisualizers/DebuggerVisualizers (2008).csproj @@ -0,0 +1,100 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {E72A7F76-D6CF-498F-B995-2DAA847146A8} + Library + Properties + AForge.DebuggerVisualizers + AForge.DebuggerVisualizers %282008%29 + v3.5 + 512 + true + AForge.DebuggerVisualizers.snk + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\..\Release\ + TRACE + prompt + 4 + + + + False + ..\..\Release\AForge.dll + + + False + ..\..\Release\AForge.Controls.dll + + + False + ..\..\Release\AForge.Imaging.dll + + + False + ..\..\Release\AForge.Math.dll + + + + + 3.5 + + + + + + + + + + Form + + + HistogramView.cs + + + + Form + + + ImageView.cs + + + + + + + + + + + HistogramView.cs + + + ImageView.cs + + + + + \ No newline at end of file diff --git a/Tools/DebuggerVisualizers/DebuggerVisualizers (2008).sln b/Tools/DebuggerVisualizers/DebuggerVisualizers (2008).sln new file mode 100644 index 0000000000..c31e2b74a --- /dev/null +++ b/Tools/DebuggerVisualizers/DebuggerVisualizers (2008).sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual C# Express 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DebuggerVisualizers", "DebuggerVisualizers (2008).csproj", "{E72A7F76-D6CF-498F-B995-2DAA847146A8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E72A7F76-D6CF-498F-B995-2DAA847146A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E72A7F76-D6CF-498F-B995-2DAA847146A8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E72A7F76-D6CF-498F-B995-2DAA847146A8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E72A7F76-D6CF-498F-B995-2DAA847146A8}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Tools/DebuggerVisualizers/DebuggerVisualizers (2010).csproj b/Tools/DebuggerVisualizers/DebuggerVisualizers (2010).csproj new file mode 100644 index 0000000000..85f583141 --- /dev/null +++ b/Tools/DebuggerVisualizers/DebuggerVisualizers (2010).csproj @@ -0,0 +1,142 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {E72A7F76-D6CF-498F-B995-2DAA847146A8} + Library + Properties + AForge.DebuggerVisualizers + AForge.DebuggerVisualizers %282010%29 + v4.0 + 512 + true + AForge.DebuggerVisualizers.snk + + + + + 3.5 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + ..\..\Release\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\..\Release\ + TRACE + prompt + 4 + + + + False + ..\..\Release\AForge.dll + + + False + ..\..\Release\AForge.Controls.dll + + + False + ..\..\Release\AForge.Imaging.dll + + + False + ..\..\Release\AForge.Math.dll + + + + + 3.5 + + + + + + + + + + Form + + + HistogramView.cs + + + + Form + + + ImageView.cs + + + + + + + + + + + HistogramView.cs + + + ImageView.cs + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + \ No newline at end of file diff --git a/Tools/DebuggerVisualizers/DebuggerVisualizers (2010).sln b/Tools/DebuggerVisualizers/DebuggerVisualizers (2010).sln new file mode 100644 index 0000000000..47c6d5a60 --- /dev/null +++ b/Tools/DebuggerVisualizers/DebuggerVisualizers (2010).sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C# Express 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DebuggerVisualizers (2010)", "DebuggerVisualizers (2010).csproj", "{E72A7F76-D6CF-498F-B995-2DAA847146A8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E72A7F76-D6CF-498F-B995-2DAA847146A8}.Debug|Any CPU.ActiveCfg = Release|Any CPU + {E72A7F76-D6CF-498F-B995-2DAA847146A8}.Debug|Any CPU.Build.0 = Release|Any CPU + {E72A7F76-D6CF-498F-B995-2DAA847146A8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E72A7F76-D6CF-498F-B995-2DAA847146A8}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Tools/DebuggerVisualizers/HistogramView.Designer.cs b/Tools/DebuggerVisualizers/HistogramView.Designer.cs new file mode 100644 index 0000000000..4657a53d9 --- /dev/null +++ b/Tools/DebuggerVisualizers/HistogramView.Designer.cs @@ -0,0 +1,126 @@ +namespace AForge.DebuggerVisualizers +{ + partial class HistogramView + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager( typeof( HistogramView ) ); + this.mainPanel = new System.Windows.Forms.Panel( ); + this.histogramControl = new AForge.Controls.Histogram( ); + this.textBox = new System.Windows.Forms.TextBox( ); + this.statsBox = new System.Windows.Forms.TextBox( ); + this.logCheck = new System.Windows.Forms.CheckBox( ); + this.mainPanel.SuspendLayout( ); + this.SuspendLayout( ); + // + // mainPanel + // + this.mainPanel.Anchor = ( (System.Windows.Forms.AnchorStyles) ( ( ( ( System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom ) + | System.Windows.Forms.AnchorStyles.Left ) + | System.Windows.Forms.AnchorStyles.Right ) ) ); + this.mainPanel.Controls.Add( this.histogramControl ); + this.mainPanel.Location = new System.Drawing.Point( 10, 10 ); + this.mainPanel.Name = "mainPanel"; + this.mainPanel.Size = new System.Drawing.Size( 474, 159 ); + this.mainPanel.TabIndex = 0; + // + // histogramControl + // + this.histogramControl.AllowSelection = true; + this.histogramControl.BackColor = System.Drawing.SystemColors.ControlDarkDark; + this.histogramControl.Color = System.Drawing.Color.DodgerBlue; + this.histogramControl.Location = new System.Drawing.Point( 154, 33 ); + this.histogramControl.Name = "histogramControl"; + this.histogramControl.Size = new System.Drawing.Size( 196, 73 ); + this.histogramControl.TabIndex = 0; + this.histogramControl.Values = null; + this.histogramControl.SelectionChanged += new AForge.Controls.HistogramEventHandler( this.histogramControl_SelectionChanged ); + this.histogramControl.PositionChanged += new AForge.Controls.HistogramEventHandler( this.histogramControl_PositionChanged ); + // + // textBox + // + this.textBox.Anchor = ( (System.Windows.Forms.AnchorStyles) ( ( ( System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left ) + | System.Windows.Forms.AnchorStyles.Right ) ) ); + this.textBox.Location = new System.Drawing.Point( 10, 203 ); + this.textBox.Name = "textBox"; + this.textBox.ReadOnly = true; + this.textBox.Size = new System.Drawing.Size( 424, 20 ); + this.textBox.TabIndex = 2; + // + // statsBox + // + this.statsBox.Anchor = ( (System.Windows.Forms.AnchorStyles) ( ( ( System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left ) + | System.Windows.Forms.AnchorStyles.Right ) ) ); + this.statsBox.Location = new System.Drawing.Point( 10, 175 ); + this.statsBox.Name = "statsBox"; + this.statsBox.ReadOnly = true; + this.statsBox.Size = new System.Drawing.Size( 474, 20 ); + this.statsBox.TabIndex = 1; + // + // logCheck + // + this.logCheck.Anchor = ( (System.Windows.Forms.AnchorStyles) ( ( System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right ) ) ); + this.logCheck.AutoSize = true; + this.logCheck.Location = new System.Drawing.Point( 440, 206 ); + this.logCheck.Name = "logCheck"; + this.logCheck.Size = new System.Drawing.Size( 44, 17 ); + this.logCheck.TabIndex = 3; + this.logCheck.Text = "&Log"; + this.logCheck.UseVisualStyleBackColor = true; + this.logCheck.CheckedChanged += new System.EventHandler( this.logCheck_CheckedChanged ); + // + // HistogramView + // + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.ClientSize = new System.Drawing.Size( 494, 231 ); + this.Controls.Add( this.logCheck ); + this.Controls.Add( this.statsBox ); + this.Controls.Add( this.textBox ); + this.Controls.Add( this.mainPanel ); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.Icon = ( (System.Drawing.Icon) ( resources.GetObject( "$this.Icon" ) ) ); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.MinimumSize = new System.Drawing.Size( 400, 250 ); + this.Name = "HistogramView"; + this.ShowInTaskbar = false; + this.Text = "Histogram"; + this.mainPanel.ResumeLayout( false ); + this.ResumeLayout( false ); + this.PerformLayout( ); + + } + + #endregion + + private System.Windows.Forms.Panel mainPanel; + private AForge.Controls.Histogram histogramControl; + private System.Windows.Forms.TextBox textBox; + private System.Windows.Forms.TextBox statsBox; + private System.Windows.Forms.CheckBox logCheck; + } +} \ No newline at end of file diff --git a/Tools/DebuggerVisualizers/HistogramView.cs b/Tools/DebuggerVisualizers/HistogramView.cs new file mode 100644 index 0000000000..17b9489f4 --- /dev/null +++ b/Tools/DebuggerVisualizers/HistogramView.cs @@ -0,0 +1,103 @@ +// AForge debugging visualizers +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Windows.Forms; +using AForge.Math; + +namespace AForge.DebuggerVisualizers +{ + public partial class HistogramView : Form + { + private const int HistogramHeight = 100; + private Histogram histogram; + + public HistogramView( ) + { + InitializeComponent( ); + } + + public void SetHistogram( Histogram histogram ) + { + this.histogram = histogram; + + histogramControl.Values = histogram.Values; + int length = histogram.Values.Length; + + Text = string.Format( "Histogram - {0} values", length ); + statsBox.Text = string.Format( "Min: {0} Max: {1} Mean: {2:F2} Std.Dev.: {3:F2}", + histogram.Min, histogram.Max, histogram.Mean, histogram.StdDev ); + + // set form size + int formWidth = System.Math.Min( 800, length ) + 40; + int formHeight = HistogramHeight + 120; + + this.Size = new Size( formWidth, formHeight ); + + // set histogram control size + int width = length + 2; + int height = HistogramHeight + 2; + + int x = ( width > mainPanel.ClientSize.Width ) ? 0 : ( mainPanel.ClientSize.Width - width ) / 2; + int y = ( height > mainPanel.ClientSize.Height ) ? 0 : ( mainPanel.ClientSize.Height - height ) / 2; + + histogramControl.SuspendLayout( ); + histogramControl.Size = new Size( width, height ); + histogramControl.Location = new System.Drawing.Point( x, y ); + histogramControl.ResumeLayout( ); + } + + // Mouse cursor's position has changed within histogram control + private void histogramControl_PositionChanged( object sender, AForge.Controls.HistogramEventArgs e ) + { + if ( histogram != null ) + { + int pos = e.Position; + + if ( pos != -1 ) + { + textBox.Text = string.Format( "Value: {0} Count: {1} Percent: {2:F2}", + pos, histogram.Values[pos], ( (float) histogram.Values[pos] * 100 / histogram.TotalCount ) ); + } + else + { + textBox.Text = string.Empty; + } + } + } + + // Selection has changed within histogram control + private void histogramControl_SelectionChanged( object sender, AForge.Controls.HistogramEventArgs e ) + { + if ( histogram != null ) + { + int min = e.Min; + int max = e.Max; + int count = 0; + + // count pixels + for ( int i = min; i <= max; i++ ) + { + count += histogram.Values[i]; + } + + textBox.Text = string.Format( "Values: {0}...{1} Count: {2} Percent: {3:F2}", + min, max, count, ( (float) count * 100 / histogram.TotalCount ) ); + } + } + + private void logCheck_CheckedChanged( object sender, EventArgs e ) + { + histogramControl.IsLogarithmicView = logCheck.Checked; + } + } +} diff --git a/Tools/DebuggerVisualizers/HistogramView.resx b/Tools/DebuggerVisualizers/HistogramView.resx new file mode 100644 index 0000000000..e9e326aac --- /dev/null +++ b/Tools/DebuggerVisualizers/HistogramView.resx @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AABlREzBZURM5WVETOVlREzlZURM5WVETOVlREzlZURM5WVETOVlREzlZURM5WVETOVlREzlZURM5WVE + TMH///8AZURM5f///////////////////////////////39/f/////////////////////////////// + //9lREzl////AGVETOX///////////////////////////////+/v7////////////////////////// + ////////ZURM5f///wBlREzl//7+///+/v///v7///7+///+/v///v7/f39//794C/+8cgD///7+///+ + /v///v7///7+/2VETOX///8AZURM5f/////9/Pz//fz8//38/P/9/Pz//fz8/8OAGf/9/Pz//fz8/7xy + AP/9/Pz//fz8//38/P9lREzl////AGVETOX//v7//Pr6//z6+v/8+vr//Pr6//z6+v/Cfxn//Pr6//z6 + +v+8cgD//Pr6//z6+v/8+vr/ZURM5f///wBlREzlv4CA//v4+P/7+Pj/+/j4//v4+P/IiSr/v7+///v4 + +P/7+Pj/+/j4/7xyAP/7+Pj/+/j4/2VETOX///8AZURM5b+AgP+/v7//f39//7+/v/9/f3//x4or/39/ + f/+/v7//f39//7+/v/+8cgD/v7+//39/f/9lREzl////AGVETOW/gID/+PPz//jz8//48/P/+PPz/8iJ + Kv+/v7//+PPz//jz8//48/P/vHIA//jz8//48/P/ZURM5f///wBlREzl/fz8/964gP/28fH/9vHx/8yU + Pv/28fH/f39///bx8f/28fH/9vHx//bx8f+8cgD/9vHx/2VETOX///8AZURM5f37+//duX//9e7u//Xu + 7v/MlT7/9e7u/7+/v//17u7/9e7u//Xu7v/17u7/vHIA//Xu7v9lREzl////AGVETOX9+/v/9Ozs/9is + af/Rn1P/9Ozs//Ts7P9/f3//9Ozs//Ts7P/07Oz/9Ozs//Ts7P+8cgD/ZURM5f///wBlREzl/Pr6//Lq + 6v/y6ur/8urq//Lq6v/y6ur/v7+///Lq6v/y6ur/8urq//Lq6v/y6ur/8urq/2VETOX///8AZURM5f37 + +//49fX/+PX1//j19f/8+vr//Pr6/7+/v//8+vr//Pr6//z6+v/8+vr//Pr6//j19f9lREzl////AGVE + TMFlREzlZURM5WVETOVlREzlZURM5WVETOVlREzlZURM5WVETOVlREzlZURM5WVETOVlREzlZURMwf// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8AAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAB + AAAAAQAA//8AAA== + + + \ No newline at end of file diff --git a/Tools/DebuggerVisualizers/HistogramVisualizer.cs b/Tools/DebuggerVisualizers/HistogramVisualizer.cs new file mode 100644 index 0000000000..853de2109 --- /dev/null +++ b/Tools/DebuggerVisualizers/HistogramVisualizer.cs @@ -0,0 +1,34 @@ +// AForge debugging visualizers +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2011 +// contacts@aforgenet.com +// + +using System; +using System.Drawing; +using System.Windows.Forms; +using Microsoft.VisualStudio.DebuggerVisualizers; + +[assembly: System.Diagnostics.DebuggerVisualizer( + typeof( AForge.DebuggerVisualizers.HistogramVisualizer ), + typeof( VisualizerObjectSource ), + Target = typeof( AForge.Math.Histogram ), + Description = "Histogram Visualizer" )] + +namespace AForge.DebuggerVisualizers +{ + public class HistogramVisualizer : DialogDebuggerVisualizer + { + override protected void Show( IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider ) + { + AForge.Math.Histogram histogram = (AForge.Math.Histogram) objectProvider.GetObject( ); + + HistogramView histogramView = new HistogramView( ); + histogramView.SetHistogram( histogram ); + + windowService.ShowDialog( histogramView ); + } + } +} diff --git a/Tools/DebuggerVisualizers/ImageView.Designer.cs b/Tools/DebuggerVisualizers/ImageView.Designer.cs new file mode 100644 index 0000000000..0176f9d4c --- /dev/null +++ b/Tools/DebuggerVisualizers/ImageView.Designer.cs @@ -0,0 +1,152 @@ +namespace AForge.DebuggerVisualizers +{ + partial class ImageView + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager( typeof( ImageView ) ); + this.groupBox1 = new System.Windows.Forms.GroupBox( ); + this.imagePanel = new System.Windows.Forms.Panel( ); + this.pictureBox = new AForge.Controls.PictureBox( ); + this.groupBox2 = new System.Windows.Forms.GroupBox( ); + this.saveButton = new System.Windows.Forms.Button( ); + this.clipboardButton = new System.Windows.Forms.Button( ); + this.saveFileDialog = new System.Windows.Forms.SaveFileDialog( ); + this.groupBox1.SuspendLayout( ); + this.imagePanel.SuspendLayout( ); + ( (System.ComponentModel.ISupportInitialize) ( this.pictureBox ) ).BeginInit( ); + this.groupBox2.SuspendLayout( ); + this.SuspendLayout( ); + // + // groupBox1 + // + this.groupBox1.Anchor = ( (System.Windows.Forms.AnchorStyles) ( ( ( ( System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom ) + | System.Windows.Forms.AnchorStyles.Left ) + | System.Windows.Forms.AnchorStyles.Right ) ) ); + this.groupBox1.Controls.Add( this.imagePanel ); + this.groupBox1.Location = new System.Drawing.Point( 10, 75 ); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size( 362, 333 ); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Image"; + // + // imagePanel + // + this.imagePanel.Anchor = ( (System.Windows.Forms.AnchorStyles) ( ( ( ( System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom ) + | System.Windows.Forms.AnchorStyles.Left ) + | System.Windows.Forms.AnchorStyles.Right ) ) ); + this.imagePanel.AutoScroll = true; + this.imagePanel.Controls.Add( this.pictureBox ); + this.imagePanel.Location = new System.Drawing.Point( 10, 20 ); + this.imagePanel.Name = "imagePanel"; + this.imagePanel.Size = new System.Drawing.Size( 342, 302 ); + this.imagePanel.TabIndex = 0; + // + // pictureBox + // + this.pictureBox.BackColor = System.Drawing.SystemColors.ControlDarkDark; + this.pictureBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.pictureBox.Image = null; + this.pictureBox.Location = new System.Drawing.Point( 50, 51 ); + this.pictureBox.Name = "pictureBox"; + this.pictureBox.Size = new System.Drawing.Size( 243, 193 ); + this.pictureBox.TabIndex = 0; + this.pictureBox.TabStop = false; + // + // groupBox2 + // + this.groupBox2.Anchor = ( (System.Windows.Forms.AnchorStyles) ( ( ( System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left ) + | System.Windows.Forms.AnchorStyles.Right ) ) ); + this.groupBox2.Controls.Add( this.clipboardButton ); + this.groupBox2.Controls.Add( this.saveButton ); + this.groupBox2.Location = new System.Drawing.Point( 10, 10 ); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size( 362, 55 ); + this.groupBox2.TabIndex = 1; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Options"; + // + // saveButton + // + this.saveButton.Location = new System.Drawing.Point( 10, 20 ); + this.saveButton.Name = "saveButton"; + this.saveButton.Size = new System.Drawing.Size( 75, 23 ); + this.saveButton.TabIndex = 0; + this.saveButton.Text = "&Save"; + this.saveButton.UseVisualStyleBackColor = true; + this.saveButton.Click += new System.EventHandler( this.saveButton_Click ); + // + // clipboardButton + // + this.clipboardButton.Location = new System.Drawing.Point( 100, 20 ); + this.clipboardButton.Name = "clipboardButton"; + this.clipboardButton.Size = new System.Drawing.Size( 100, 23 ); + this.clipboardButton.TabIndex = 1; + this.clipboardButton.Text = "Put to &Clipboard"; + this.clipboardButton.UseVisualStyleBackColor = true; + this.clipboardButton.Click += new System.EventHandler( this.clipboardButton_Click ); + // + // saveFileDialog + // + this.saveFileDialog.Filter = "PNG files (*.png)|*.png|JPG files (*.jpg)|*.jpg|BMP files (*.bmp)|*.bmp"; + this.saveFileDialog.Title = "Save image"; + // + // ImageView + // + this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 13F ); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size( 384, 418 ); + this.Controls.Add( this.groupBox2 ); + this.Controls.Add( this.groupBox1 ); + this.Icon = ( (System.Drawing.Icon) ( resources.GetObject( "$this.Icon" ) ) ); + this.MinimizeBox = false; + this.MinimumSize = new System.Drawing.Size( 160, 120 ); + this.Name = "ImageView"; + this.ShowInTaskbar = false; + this.Text = "ImageView"; + this.Load += new System.EventHandler( this.ImageView_Load ); + this.Resize += new System.EventHandler( this.ImageView_Resize ); + this.groupBox1.ResumeLayout( false ); + this.imagePanel.ResumeLayout( false ); + ( (System.ComponentModel.ISupportInitialize) ( this.pictureBox ) ).EndInit( ); + this.groupBox2.ResumeLayout( false ); + this.ResumeLayout( false ); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Panel imagePanel; + private AForge.Controls.PictureBox pictureBox; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.Button clipboardButton; + private System.Windows.Forms.Button saveButton; + private System.Windows.Forms.SaveFileDialog saveFileDialog; + } +} \ No newline at end of file diff --git a/Tools/DebuggerVisualizers/ImageView.cs b/Tools/DebuggerVisualizers/ImageView.cs new file mode 100644 index 0000000000..48d9a2f13 --- /dev/null +++ b/Tools/DebuggerVisualizers/ImageView.cs @@ -0,0 +1,135 @@ +// AForge debugging visualizers +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Drawing.Imaging; +using System.Windows.Forms; +using System.IO; + +namespace AForge.DebuggerVisualizers +{ + public partial class ImageView : Form + { + public ImageView( ) + { + InitializeComponent( ); + } + + private void ImageView_Resize( object sender, EventArgs e ) + { + UpdateViewSize( ); + } + + private void ImageView_Load( object sender, EventArgs e ) + { + if ( pictureBox.Image != null ) + { + // if image was already set by the time of form loading, update form's size + int width = System.Math.Max( 64, System.Math.Min( 800, pictureBox.Image.Width ) ); + int height = System.Math.Max( 64, System.Math.Min( 600, pictureBox.Image.Height ) ); + this.Size = new Size( width + 80, height + 155 ); + } + } + + public void SetImage( Image image ) + { + pictureBox.Image = image; + + if ( image == null ) + { + Text = "Image not set"; + saveButton.Enabled = false; + clipboardButton.Enabled = false; + } + else + { + Text = string.Format( "Width: {0}, Height: {1}", image.Width, image.Height ); + saveButton.Enabled = true; + clipboardButton.Enabled = true; + } + + UpdateViewSize( ); + } + + private void UpdateViewSize( ) + { + pictureBox.SuspendLayout( ); + + int width = 160; + int height = 120; + + if ( pictureBox.Image != null ) + { + width = pictureBox.Image.Width + 2; + height = pictureBox.Image.Height + 2; + } + + int x = ( width > imagePanel.ClientSize.Width ) ? 0 : ( imagePanel.ClientSize.Width - width ) / 2; + int y = ( height > imagePanel.ClientSize.Height ) ? 0 : ( imagePanel.ClientSize.Height - height) / 2; + + pictureBox.Size = new Size( width, height ); + pictureBox.Location = new System.Drawing.Point( x, y ); + + pictureBox.ResumeLayout( ); + } + + // Put image into clipboard + private void clipboardButton_Click( object sender, EventArgs e ) + { + if ( pictureBox.Image != null ) + { + Clipboard.SetDataObject( pictureBox.Image ); + } + } + + // Save image to file + private void saveButton_Click( object sender, EventArgs e ) + { + if ( pictureBox.Image != null ) + { + if ( saveFileDialog.ShowDialog( ) == DialogResult.OK ) + { + ImageFormat format = ImageFormat.Jpeg; + + // resolve file format + switch ( Path.GetExtension( saveFileDialog.FileName ).ToLower( ) ) + { + case ".jpg": + format = ImageFormat.Jpeg; + break; + case ".bmp": + format = ImageFormat.Bmp; + break; + case ".png": + format = ImageFormat.Png; + break; + default: + MessageBox.Show( this, "Unsupported image format was specified", "Error", + MessageBoxButtons.OK, MessageBoxIcon.Error ); + return; + } + + // save the image + try + { + pictureBox.Image.Save( saveFileDialog.FileName, format ); + } + catch ( Exception ex ) + { + MessageBox.Show( this, "Failed writing image file.\r\n\r\n" + ex.Message, "Error", + MessageBoxButtons.OK, MessageBoxIcon.Error ); + } + } + } + } + } +} diff --git a/Tools/DebuggerVisualizers/ImageView.resx b/Tools/DebuggerVisualizers/ImageView.resx new file mode 100644 index 0000000000..d2f27652f --- /dev/null +++ b/Tools/DebuggerVisualizers/ImageView.resx @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + AAABAAEAEBAAAAEACABoBQAAFgAAACgAAAAQAAAAIAAAAAEACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAIRcCADIcEgAoGx8ANiIxACwjNAA/MToAKzhAAFE3PwBVPzgAKkNAAExEOgBQR00AQEVrAFZQ + TgBCU08ANVVOAF1NYgBBV1EASFhRAFNOcwBnUHQAR1N9AIRgVgBYWYkAQmhjAG9nXgCIZWMAYGWAAFFx + ZABwcZUAc3aFAFR+eABqj4MA3ZJdAOCVYgBwkpYAdIe7AOGXYgDfl2MA35dkAOCXZADfl2UA4JhlAN+Z + ZgDhmWcA4ppmALaadgCTkqYA5J1oAHiamgDnnmcA4KBxAOmjbADqpGsA6qRtAOqkbwDspWsA6qZtAOyn + cgDwqG4A7KlxAIqnnwDtq3EA8KxzAPGveADwsHgA8LJ5APayegDys30A77R+APK0fgDztH8A/7p5APi6 + hAD/vXsAtLS0APi7hwD/vYEA/b6MAPbAkQD/wo0A/sWTAP/KhwD/zZUA/9aZAP/ZlQD/150A/96YAP/g + nwD/4KMA/+OiAP/vwwD/8b4A//a8AP/7uQD7+fkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMTExMTExMTExMTExMTExMTGBgYGBg + YGBgYGBgYGBgTExgChkyJCAdEhM+IRAPYExMYBcJAwIIHwwEBRUGEWBMTGBcXTAcDgcAARoUGA1gTExg + UldaHiUbVl5fVS8LYExMYEpNU1AWNFtRT1RZWGBMTGBAQ0JJS05BRUZHSERgTExgMzY3NTw3ODo9Oz85 + YExMYCIpJignKiwrLS4xI2BMTGBgYGBgYGBgYGBgYGBgTExMTExMTExMTExMTExMTEwAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//AAD//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA//8AAP//AAA= + + + \ No newline at end of file diff --git a/Tools/DebuggerVisualizers/ImageVisualizer.cs b/Tools/DebuggerVisualizers/ImageVisualizer.cs new file mode 100644 index 0000000000..a1c7efb7f --- /dev/null +++ b/Tools/DebuggerVisualizers/ImageVisualizer.cs @@ -0,0 +1,34 @@ +// AForge debugging visualizers +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2011 +// contacts@aforgenet.com +// + +using System; +using System.Drawing; +using System.Windows.Forms; +using Microsoft.VisualStudio.DebuggerVisualizers; + +[assembly: System.Diagnostics.DebuggerVisualizer( + typeof( AForge.DebuggerVisualizers.ImageVisualizer ), + typeof( VisualizerObjectSource ), + Target = typeof( System.Drawing.Image ), + Description = "Image Visualizer" )] + +namespace AForge.DebuggerVisualizers +{ + public class ImageVisualizer : DialogDebuggerVisualizer + { + override protected void Show( IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider ) + { + Image image = (Image) objectProvider.GetObject( ); + + ImageView imageViewer = new ImageView( ); + imageViewer.SetImage( image ); + + windowService.ShowDialog( imageViewer ); + } + } +} diff --git a/Tools/DebuggerVisualizers/Images/histogram.ico b/Tools/DebuggerVisualizers/Images/histogram.ico new file mode 100644 index 0000000000..94f03211c Binary files /dev/null and b/Tools/DebuggerVisualizers/Images/histogram.ico differ diff --git a/Tools/DebuggerVisualizers/Images/image.ico b/Tools/DebuggerVisualizers/Images/image.ico new file mode 100644 index 0000000000..13e51a266 Binary files /dev/null and b/Tools/DebuggerVisualizers/Images/image.ico differ diff --git a/Tools/DebuggerVisualizers/Properties/AssemblyInfo.cs b/Tools/DebuggerVisualizers/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..ff09ff46e --- /dev/null +++ b/Tools/DebuggerVisualizers/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle( "AForge.DebuggerVisualizers" )] +[assembly: AssemblyDescription( "Debugger visualizers for some AForge.NET types" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "AForge" )] +[assembly: AssemblyProduct( "AForge.NET" )] +[assembly: AssemblyCopyright( "AForge © 2012" )] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible( false )] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid( "6273d551-235d-49cb-a7e9-8855e463114b" )] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion( "1.0.0.0" )] +[assembly: AssemblyFileVersion( "1.0.0.0" )] diff --git a/Tools/DebuggerVisualizers/UnmanagedImageVisualizer.cs b/Tools/DebuggerVisualizers/UnmanagedImageVisualizer.cs new file mode 100644 index 0000000000..60d1f1595 --- /dev/null +++ b/Tools/DebuggerVisualizers/UnmanagedImageVisualizer.cs @@ -0,0 +1,45 @@ +// AForge debugging visualizers +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2011 +// contacts@aforgenet.com +// + +using System; +using System.IO; +using System.Drawing; +using System.Windows.Forms; +using System.Runtime.Serialization.Formatters.Binary; +using Microsoft.VisualStudio.DebuggerVisualizers; + +[assembly: System.Diagnostics.DebuggerVisualizer( + typeof( AForge.DebuggerVisualizers.UnmanagedImageVisualizer ), + typeof( AForge.DebuggerVisualizers.UnmanagedImageObjectSource ), + Target = typeof( AForge.Imaging.UnmanagedImage ), + Description = "Unmanaged Image Visualizer" )] + +namespace AForge.DebuggerVisualizers +{ + public class UnmanagedImageVisualizer : DialogDebuggerVisualizer + { + override protected void Show( IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider ) + { + Image image = (Image) objectProvider.GetObject( ); + + ImageView imageViewer = new ImageView( ); + imageViewer.SetImage( image ); + + windowService.ShowDialog( imageViewer ); + } + } + + public class UnmanagedImageObjectSource : VisualizerObjectSource + { + public override void GetData( object target, Stream outgoingData ) + { + BinaryFormatter bf = new BinaryFormatter( ); + bf.Serialize( outgoingData, ( (AForge.Imaging.UnmanagedImage) target ).ToManagedImage( ) ); + } + } +} diff --git a/Tools/IPPrototyper/AForge.IPPrototyper.snk b/Tools/IPPrototyper/AForge.IPPrototyper.snk new file mode 100644 index 0000000000..e11ec0d27 Binary files /dev/null and b/Tools/IPPrototyper/AForge.IPPrototyper.snk differ diff --git a/Tools/IPPrototyper/AboutForm.Designer.cs b/Tools/IPPrototyper/AboutForm.Designer.cs new file mode 100644 index 0000000000..6cb06f65a --- /dev/null +++ b/Tools/IPPrototyper/AboutForm.Designer.cs @@ -0,0 +1,120 @@ +namespace IPPrototyper +{ + partial class AboutForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.emailLabel = new System.Windows.Forms.LinkLabel( ); + this.label3 = new System.Windows.Forms.Label( ); + this.aforgeFrameworkLabel = new System.Windows.Forms.LinkLabel( ); + this.label2 = new System.Windows.Forms.Label( ); + this.label1 = new System.Windows.Forms.Label( ); + this.SuspendLayout( ); + // + // emailLabel + // + this.emailLabel.AutoSize = true; + this.emailLabel.Location = new System.Drawing.Point( 71, 99 ); + this.emailLabel.Name = "emailLabel"; + this.emailLabel.Size = new System.Drawing.Size( 153, 13 ); + this.emailLabel.TabIndex = 12; + this.emailLabel.TabStop = true; + this.emailLabel.Text = "andrew.kirillov@aforgenet.com"; + this.emailLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler( this.LinkClicked ); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point( 65, 84 ); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size( 165, 13 ); + this.label3.TabIndex = 11; + this.label3.Text = "Copyright © 2010, Andrew Kirillov"; + // + // aforgeFrameworkLabel + // + this.aforgeFrameworkLabel.AutoSize = true; + this.aforgeFrameworkLabel.Location = new System.Drawing.Point( 51, 59 ); + this.aforgeFrameworkLabel.Name = "aforgeFrameworkLabel"; + this.aforgeFrameworkLabel.Size = new System.Drawing.Size( 192, 13 ); + this.aforgeFrameworkLabel.TabIndex = 10; + this.aforgeFrameworkLabel.TabStop = true; + this.aforgeFrameworkLabel.Text = "http://www.aforgenet.com/framework/"; + this.aforgeFrameworkLabel.VisitedLinkColor = System.Drawing.Color.Blue; + this.aforgeFrameworkLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler( this.LinkClicked ); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point( 63, 44 ); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size( 169, 13 ); + this.label2.TabIndex = 9; + this.label2.Text = "Based on AForge.NET Framework"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Font = new System.Drawing.Font( "Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ( (byte) ( 204 ) ) ); + this.label1.Location = new System.Drawing.Point( 46, 14 ); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size( 202, 13 ); + this.label1.TabIndex = 8; + this.label1.Text = "Image Processing Prototyper 1.0.1"; + // + // AboutForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 13F ); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size( 294, 126 ); + this.Controls.Add( this.emailLabel ); + this.Controls.Add( this.label3 ); + this.Controls.Add( this.aforgeFrameworkLabel ); + this.Controls.Add( this.label2 ); + this.Controls.Add( this.label1 ); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "AboutForm"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "About ..."; + this.ResumeLayout( false ); + this.PerformLayout( ); + + } + + #endregion + + private System.Windows.Forms.LinkLabel emailLabel; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.LinkLabel aforgeFrameworkLabel; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + } +} \ No newline at end of file diff --git a/Tools/IPPrototyper/AboutForm.cs b/Tools/IPPrototyper/AboutForm.cs new file mode 100644 index 0000000000..a385d0903 --- /dev/null +++ b/Tools/IPPrototyper/AboutForm.cs @@ -0,0 +1,36 @@ +// Image Processing Prototyper +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © Andrew Kirillov, 2010 +// andrew.kirillov@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace IPPrototyper +{ + internal partial class AboutForm : Form + { + public AboutForm( ) + { + InitializeComponent( ); + + // initialize links + emailLabel.Links.Add( 0, emailLabel.Text.Length, "mailto:" + emailLabel.Text ); + aforgeFrameworkLabel.Links.Add( 0, aforgeFrameworkLabel.Text.Length, aforgeFrameworkLabel.Text ); + } + + // Link clicked + private void LinkClicked( object sender, LinkLabelLinkClickedEventArgs e ) + { + System.Diagnostics.Process.Start( e.Link.LinkData.ToString( ) ); + } + } +} diff --git a/Tools/IPPrototyper/AboutForm.resx b/Tools/IPPrototyper/AboutForm.resx new file mode 100644 index 0000000000..19dc0dd8b --- /dev/null +++ b/Tools/IPPrototyper/AboutForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Tools/IPPrototyper/Configuration.cs b/Tools/IPPrototyper/Configuration.cs new file mode 100644 index 0000000000..77eb1ca60 --- /dev/null +++ b/Tools/IPPrototyper/Configuration.cs @@ -0,0 +1,234 @@ +// Image Processing Prototyper +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2010-2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Text; +using System.IO; +using System.Xml; + +namespace IPPrototyper +{ + // Manages/loads/saves application's configuration + internal class Configuration + { + private static Configuration singleton = null; + + // list of configuration options + private Dictionary options = new Dictionary( ); + + private const string configFolderName = "AForge"; + private const string baseConfigFileName = "ipprototyper.cfg"; + private string configFileName = null; + bool isSuccessfullyLoaded = false; + + #region XML Tag Names + private const string mainTag = "IPPrototyper"; + private const string optionsTag = "Options"; + #endregion + + // Configuration load status + public bool IsSuccessfullyLoaded + { + get { return isSuccessfullyLoaded; } + } + + // Disable making class instances + private Configuration( ) + { + configFileName = Path.Combine( + Environment.GetFolderPath( Environment.SpecialFolder.LocalApplicationData ), + configFolderName ); + configFileName = Path.Combine( configFileName, baseConfigFileName ); + } + + // Get instance of the configuration storage + public static Configuration Instance + { + get + { + if ( singleton == null ) + { + singleton = new Configuration( ); + } + return singleton; + } + } + + // Set configuration option's value to store + public void SetConfigurationOption( string option, string value ) + { + if ( options.ContainsKey( option ) ) + { + options[option] = value; + } + else + { + options.Add( option, value ); + } + } + + // Get value of configuration option + public string GetConfigurationOption( string option ) + { + return ( options.ContainsKey( option ) ) ? options[option] : null; + } + + // Save application's configuration + public void Save( ) + { + lock ( baseConfigFileName ) + { + // make sure directory exists + Directory.CreateDirectory( Path.GetDirectoryName( configFileName ) ); + + // open file + FileStream fs = new FileStream( configFileName, FileMode.Create ); + // create XML writer + XmlTextWriter xmlOut = new XmlTextWriter( fs, Encoding.UTF8 ); + + // use indenting for readability + xmlOut.Formatting = Formatting.Indented; + + // start document + xmlOut.WriteStartDocument( ); + xmlOut.WriteComment( "IPPrototyper configuration file" ); + + // main node + xmlOut.WriteStartElement( mainTag ); + + // save configuration options + xmlOut.WriteStartElement( optionsTag ); + SaveOptions( xmlOut ); + xmlOut.WriteEndElement( ); + + xmlOut.WriteEndElement( ); // end of main node + // close file + xmlOut.Close( ); + } + } + + // Load application's configration + public bool Load( ) + { + isSuccessfullyLoaded = false; + + lock ( baseConfigFileName ) + { + // check file existance + if ( File.Exists( configFileName ) ) + { + FileStream fs = null; + XmlTextReader xmlIn = null; + + try + { + // open file + fs = new FileStream( configFileName, FileMode.Open ); + // create XML reader + xmlIn = new XmlTextReader( fs ); + + xmlIn.WhitespaceHandling = WhitespaceHandling.None; + xmlIn.MoveToContent( ); + + // check main node + if ( xmlIn.Name != mainTag ) + throw new ApplicationException( ); + + // move to next node + xmlIn.Read( ); + + while ( true ) + { + // ignore anything if it is not under main tag + while ( ( xmlIn.Depth > 1 ) || ( + ( xmlIn.Depth == 1 ) && ( xmlIn.NodeType != XmlNodeType.Element ) ) ) + { + xmlIn.Read( ); + } + + // break if end element is reached + if ( xmlIn.Depth == 0 ) + break; + + int tagStartLineNummber = xmlIn.LineNumber; + + switch ( xmlIn.Name ) + { + case optionsTag: + LoadOptions( xmlIn ); + break; + } + + // read to the next node, if loader did not move any further + if ( xmlIn.LineNumber == tagStartLineNummber ) + { + xmlIn.Read( ); + } + } + + isSuccessfullyLoaded = true; + // ignore the rest + } + catch + { + } + finally + { + if ( xmlIn != null ) + xmlIn.Close( ); + } + } + } + + return isSuccessfullyLoaded; + } + + // Save configuration options + private void SaveOptions( XmlTextWriter xmlOut ) + { + foreach ( KeyValuePair kvp in options ) + { + xmlOut.WriteStartElement( kvp.Key ); + xmlOut.WriteString( kvp.Value ); + xmlOut.WriteEndElement( ); + } + } + + // Load configuration options + private void LoadOptions( XmlTextReader xmlIn ) + { + options.Clear( ); + // read to the first node + xmlIn.Read( ); + + int startingDept = xmlIn.Depth; + + while ( ( xmlIn.NodeType == XmlNodeType.Element ) && ( xmlIn.Depth == startingDept ) ) + { + string option = xmlIn.Name; + string value = null; + + if ( !xmlIn.IsEmptyElement ) + { + // read to the content + xmlIn.Read( ); + // read content as string + value = xmlIn.ReadString( ); + + // add the value to options list + options.Add( option, value ); + } + + // read to the next option + xmlIn.Read( ); + } + } + } +} diff --git a/Tools/IPPrototyper/HistogramForm.Designer.cs b/Tools/IPPrototyper/HistogramForm.Designer.cs new file mode 100644 index 0000000000..844359946 --- /dev/null +++ b/Tools/IPPrototyper/HistogramForm.Designer.cs @@ -0,0 +1,275 @@ +namespace IPPrototyper +{ + partial class HistogramForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.histogram = new AForge.Controls.Histogram( ); + this.label1 = new System.Windows.Forms.Label( ); + this.channelCombo = new System.Windows.Forms.ComboBox( ); + this.label2 = new System.Windows.Forms.Label( ); + this.label3 = new System.Windows.Forms.Label( ); + this.label4 = new System.Windows.Forms.Label( ); + this.label5 = new System.Windows.Forms.Label( ); + this.label6 = new System.Windows.Forms.Label( ); + this.meanLabel = new System.Windows.Forms.Label( ); + this.stdDevLabel = new System.Windows.Forms.Label( ); + this.medianLabel = new System.Windows.Forms.Label( ); + this.minLabel = new System.Windows.Forms.Label( ); + this.maxLabel = new System.Windows.Forms.Label( ); + this.label7 = new System.Windows.Forms.Label( ); + this.label8 = new System.Windows.Forms.Label( ); + this.label9 = new System.Windows.Forms.Label( ); + this.levelLabel = new System.Windows.Forms.Label( ); + this.countLabel = new System.Windows.Forms.Label( ); + this.percentileLabel = new System.Windows.Forms.Label( ); + this.SuspendLayout( ); + // + // histogram + // + this.histogram.AllowSelection = true; + this.histogram.BackColor = System.Drawing.SystemColors.ControlDark; + this.histogram.Location = new System.Drawing.Point( 11, 37 ); + this.histogram.Name = "histogram"; + this.histogram.Size = new System.Drawing.Size( 258, 150 ); + this.histogram.TabIndex = 0; + this.histogram.Values = null; + this.histogram.SelectionChanged += new AForge.Controls.HistogramEventHandler( this.histogram_SelectionChanged ); + this.histogram.PositionChanged += new AForge.Controls.HistogramEventHandler( this.histogram_PositionChanged ); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point( 10, 12 ); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size( 49, 13 ); + this.label1.TabIndex = 1; + this.label1.Text = "Channel:"; + // + // channelCombo + // + this.channelCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.channelCombo.Enabled = false; + this.channelCombo.FormattingEnabled = true; + this.channelCombo.Items.AddRange( new object[] { + "Red", + "Green", + "Blue"} ); + this.channelCombo.Location = new System.Drawing.Point( 65, 10 ); + this.channelCombo.Name = "channelCombo"; + this.channelCombo.Size = new System.Drawing.Size( 100, 21 ); + this.channelCombo.TabIndex = 2; + this.channelCombo.SelectedIndexChanged += new System.EventHandler( this.channelCombo_SelectedIndexChanged ); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point( 10, 200 ); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size( 37, 13 ); + this.label2.TabIndex = 3; + this.label2.Text = "Mean:"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point( 10, 220 ); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size( 49, 13 ); + this.label3.TabIndex = 4; + this.label3.Text = "Std Dev:"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point( 10, 240 ); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size( 45, 13 ); + this.label4.TabIndex = 5; + this.label4.Text = "Median:"; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point( 10, 260 ); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size( 27, 13 ); + this.label5.TabIndex = 6; + this.label5.Text = "Min:"; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point( 10, 280 ); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size( 30, 13 ); + this.label6.TabIndex = 7; + this.label6.Text = "Max:"; + // + // meanLabel + // + this.meanLabel.Location = new System.Drawing.Point( 65, 200 ); + this.meanLabel.Name = "meanLabel"; + this.meanLabel.Size = new System.Drawing.Size( 66, 20 ); + this.meanLabel.TabIndex = 8; + // + // stdDevLabel + // + this.stdDevLabel.Location = new System.Drawing.Point( 65, 220 ); + this.stdDevLabel.Name = "stdDevLabel"; + this.stdDevLabel.Size = new System.Drawing.Size( 55, 13 ); + this.stdDevLabel.TabIndex = 9; + // + // medianLabel + // + this.medianLabel.Location = new System.Drawing.Point( 65, 240 ); + this.medianLabel.Name = "medianLabel"; + this.medianLabel.Size = new System.Drawing.Size( 55, 13 ); + this.medianLabel.TabIndex = 10; + // + // minLabel + // + this.minLabel.Location = new System.Drawing.Point( 65, 260 ); + this.minLabel.Name = "minLabel"; + this.minLabel.Size = new System.Drawing.Size( 55, 13 ); + this.minLabel.TabIndex = 11; + // + // maxLabel + // + this.maxLabel.Location = new System.Drawing.Point( 65, 280 ); + this.maxLabel.Name = "maxLabel"; + this.maxLabel.Size = new System.Drawing.Size( 55, 13 ); + this.maxLabel.TabIndex = 12; + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point( 160, 200 ); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size( 36, 13 ); + this.label7.TabIndex = 13; + this.label7.Text = "Level:"; + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point( 160, 220 ); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size( 38, 13 ); + this.label8.TabIndex = 14; + this.label8.Text = "Count:"; + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Location = new System.Drawing.Point( 160, 240 ); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size( 57, 13 ); + this.label9.TabIndex = 15; + this.label9.Text = "Percentile:"; + // + // levelLabel + // + this.levelLabel.Location = new System.Drawing.Point( 220, 200 ); + this.levelLabel.Name = "levelLabel"; + this.levelLabel.Size = new System.Drawing.Size( 49, 13 ); + this.levelLabel.TabIndex = 16; + // + // countLabel + // + this.countLabel.Location = new System.Drawing.Point( 220, 220 ); + this.countLabel.Name = "countLabel"; + this.countLabel.Size = new System.Drawing.Size( 49, 13 ); + this.countLabel.TabIndex = 17; + // + // percentileLabel + // + this.percentileLabel.Location = new System.Drawing.Point( 220, 240 ); + this.percentileLabel.Name = "percentileLabel"; + this.percentileLabel.Size = new System.Drawing.Size( 49, 13 ); + this.percentileLabel.TabIndex = 18; + // + // HistogramForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 13F ); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size( 281, 306 ); + this.Controls.Add( this.percentileLabel ); + this.Controls.Add( this.countLabel ); + this.Controls.Add( this.levelLabel ); + this.Controls.Add( this.label9 ); + this.Controls.Add( this.label8 ); + this.Controls.Add( this.label7 ); + this.Controls.Add( this.maxLabel ); + this.Controls.Add( this.minLabel ); + this.Controls.Add( this.medianLabel ); + this.Controls.Add( this.stdDevLabel ); + this.Controls.Add( this.meanLabel ); + this.Controls.Add( this.label6 ); + this.Controls.Add( this.label5 ); + this.Controls.Add( this.label4 ); + this.Controls.Add( this.label3 ); + this.Controls.Add( this.label2 ); + this.Controls.Add( this.channelCombo ); + this.Controls.Add( this.label1 ); + this.Controls.Add( this.histogram ); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "HistogramForm"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.Text = "Histogram"; + this.TopMost = true; + this.ResumeLayout( false ); + this.PerformLayout( ); + + } + + #endregion + + private AForge.Controls.Histogram histogram; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.ComboBox channelCombo; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Label meanLabel; + private System.Windows.Forms.Label stdDevLabel; + private System.Windows.Forms.Label medianLabel; + private System.Windows.Forms.Label minLabel; + private System.Windows.Forms.Label maxLabel; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.Label levelLabel; + private System.Windows.Forms.Label countLabel; + private System.Windows.Forms.Label percentileLabel; + } +} \ No newline at end of file diff --git a/Tools/IPPrototyper/HistogramForm.cs b/Tools/IPPrototyper/HistogramForm.cs new file mode 100644 index 0000000000..984a11dd1 --- /dev/null +++ b/Tools/IPPrototyper/HistogramForm.cs @@ -0,0 +1,132 @@ +// Image Processing Prototyper +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2010-2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +using AForge.Math; +using AForge.Imaging; + +namespace IPPrototyper +{ + // Form to display image's histogram(s) and basic statistics like mean, std.dev, etc + internal partial class HistogramForm : Form + { + private ImageStatistics stats; + private Histogram activeHistogram; + + public HistogramForm( ) + { + InitializeComponent( ); + } + + // Set image statistics to display + public void SetImageStatistics( ImageStatistics stats ) + { + this.stats = stats; + + if ( stats.IsGrayscale ) + { + activeHistogram = stats.Gray; + histogram.Color = Color.Black; + channelCombo.Enabled = false; + + ShowInfoForActiveHistogram( ); + } + else + { + channelCombo.Enabled = true; + channelCombo.SelectedIndex = 0; + SelectChannel( 0 ); + } + } + + // Show information for the currently active histogram + private void ShowInfoForActiveHistogram( ) + { + histogram.Values = activeHistogram.Values; + meanLabel.Text = activeHistogram.Mean.ToString( "F2" ); + stdDevLabel.Text = activeHistogram.StdDev.ToString( "F2" ); + medianLabel.Text = activeHistogram.Median.ToString( ); + minLabel.Text = activeHistogram.Min.ToString( ); + maxLabel.Text = activeHistogram.Max.ToString( ); + + histogram.Values = activeHistogram.Values; + } + + // Show histogram for the specified RGB channel + private void SelectChannel( int c ) + { + switch ( c ) + { + case 0: + activeHistogram = stats.Red; + histogram.Color = Color.Red; + break; + case 1: + activeHistogram = stats.Green; + histogram.Color = Color.Green; + break; + case 2: + activeHistogram = stats.Blue; + histogram.Color = Color.Blue; + break; + } + + ShowInfoForActiveHistogram( ); + } + + // Selection has changed in RGB channel combo + private void channelCombo_SelectedIndexChanged( object sender, EventArgs e ) + { + SelectChannel( channelCombo.SelectedIndex ); + } + + // Mouse cursor's position has changed within histogram control + private void histogram_PositionChanged( object sender, AForge.Controls.HistogramEventArgs e ) + { + int pos = e.Position; + + if ( pos != -1 ) + { + levelLabel.Text = pos.ToString( ); + countLabel.Text = activeHistogram.Values[pos].ToString( ); + percentileLabel.Text = ( (float) activeHistogram.Values[pos] * 100 / stats.PixelsCount ).ToString( "F2" ); + } + else + { + levelLabel.Text = ""; + countLabel.Text = ""; + percentileLabel.Text = ""; + } + } + + // Selection has changed within histogram control + private void histogram_SelectionChanged( object sender, AForge.Controls.HistogramEventArgs e ) + { + int min = e.Min; + int max = e.Max; + int count = 0; + + levelLabel.Text = min.ToString( ) + "..." + max.ToString( ); + + // count pixels + for ( int i = min; i <= max; i++ ) + { + count += activeHistogram.Values[i]; + } + countLabel.Text = count.ToString( ); + percentileLabel.Text = ( (float) count * 100 / stats.PixelsCount ).ToString( "F2" ); + } + } +} diff --git a/Tools/IPPrototyper/HistogramForm.resx b/Tools/IPPrototyper/HistogramForm.resx new file mode 100644 index 0000000000..19dc0dd8b --- /dev/null +++ b/Tools/IPPrototyper/HistogramForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Tools/IPPrototyper/Interfaces/AForge.Imaging.IPPrototyper.snk b/Tools/IPPrototyper/Interfaces/AForge.Imaging.IPPrototyper.snk new file mode 100644 index 0000000000..90acfcca5 Binary files /dev/null and b/Tools/IPPrototyper/Interfaces/AForge.Imaging.IPPrototyper.snk differ diff --git a/Tools/IPPrototyper/Interfaces/IImageProcessingLog.cs b/Tools/IPPrototyper/Interfaces/IImageProcessingLog.cs new file mode 100644 index 0000000000..c140f998b --- /dev/null +++ b/Tools/IPPrototyper/Interfaces/IImageProcessingLog.cs @@ -0,0 +1,45 @@ +// Image Processing Prototyper +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2010-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.IPPrototyper +{ + using System; + using System.Drawing; + + /// + /// Interface for image processing loggers, which keep information about image + /// processing steps. + /// + public interface IImageProcessingLog + { + /// + /// Add new image to the log. + /// + /// + /// Key/name of the image (image processing step). + /// Image to add to the log. + /// + /// Adds new image to the image processing log or replaces existing + /// image if specified key already exists in the log. + /// + void AddImage( string key, Bitmap image ); + + /// + /// Add messafe to the log. + /// + /// + /// Message to add to the image processing log. + /// + void AddMessage( string message ); + + /// + /// Clear image processing log removing all images and messages from it. + /// + void Clear( ); + } +} diff --git a/Tools/IPPrototyper/Interfaces/IImageProcessingRoutine.cs b/Tools/IPPrototyper/Interfaces/IImageProcessingRoutine.cs new file mode 100644 index 0000000000..95db1a6de --- /dev/null +++ b/Tools/IPPrototyper/Interfaces/IImageProcessingRoutine.cs @@ -0,0 +1,33 @@ +// Image Processing Prototyper +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2010-2011 +// contacts@aforgenet.com +// + +namespace AForge.Imaging.IPPrototyper +{ + using System; + using System.Drawing; + + /// + /// Interface to implement by image processing routine. + /// + public interface IImageProcessingRoutine + { + /// + /// Image processing routine's name. + /// + string Name { get; } + + /// + /// Perform image processing routine. + /// + /// + /// Source image to perform image processing on. + /// Logger to use to put information about image processing steps/results. + /// + void Process( Bitmap image, IImageProcessingLog log ); + } +} diff --git a/Tools/IPPrototyper/Interfaces/ImageProcessingLog.cs b/Tools/IPPrototyper/Interfaces/ImageProcessingLog.cs new file mode 100644 index 0000000000..2a46e25f7 --- /dev/null +++ b/Tools/IPPrototyper/Interfaces/ImageProcessingLog.cs @@ -0,0 +1,90 @@ +// Image Processing Prototyper +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2010-2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using AForge.Imaging.IPPrototyper; + +namespace AForge.Imaging.IPPrototyper +{ + /// + /// Default implementation of interface. + /// + public class ImageProcessingLog : IImageProcessingLog + { + private Dictionary images = new Dictionary( ); + private List messages = new List( ); + + /// + /// Collection of images representing image processing steps. + /// + public Dictionary Images + { + get { return images; } + } + + /// + /// List of messages stored in the log. + /// + public List Messages + { + get { return messages; } + } + + /// + /// Clear image processing log removing all images and messages from it. + /// + public void Clear( ) + { + foreach ( KeyValuePair kvp in images ) + { + kvp.Value.Dispose( ); + } + images.Clear( ); + messages.Clear( ); + } + + /// + /// Add new image to the log. + /// + /// + /// Key/name of the image (image processing step). + /// Image to add to the log. + /// + /// Adds new image to the image processing log or replaces existing + /// image if specified key already exists in the log. + /// + public void AddImage( string key, Bitmap image ) + { + Bitmap imageToStore = (Bitmap) image.Clone( ); + + if ( images.ContainsKey( key ) ) + { + images[key].Dispose( ); + images[key] = imageToStore; + } + else + { + images.Add( key, imageToStore ); + } + } + + /// + /// Add messafe to the log. + /// + /// + /// Message to add to the image processing log. + /// + public void AddMessage( string message ) + { + messages.Add( message ); + } + } +} diff --git a/Tools/IPPrototyper/Interfaces/Interfaces.csproj b/Tools/IPPrototyper/Interfaces/Interfaces.csproj new file mode 100644 index 0000000000..e6f2b62a6 --- /dev/null +++ b/Tools/IPPrototyper/Interfaces/Interfaces.csproj @@ -0,0 +1,99 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {BE2859E0-ED2E-4038-9B11-9E410FEA25F0} + Library + Properties + AForge.Imaging.IPPrototyper + AForge.Imaging.IPPrototyper + v2.0 + 512 + true + AForge.Imaging.IPPrototyper.snk + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + full + false + ..\..\..\Release\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\..\..\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + \ No newline at end of file diff --git a/Tools/IPPrototyper/Interfaces/Properties/AssemblyInfo.cs b/Tools/IPPrototyper/Interfaces/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..31d14529a --- /dev/null +++ b/Tools/IPPrototyper/Interfaces/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle( "AForge.Imaging.IPPrototyper" )] +[assembly: AssemblyDescription( "Interfaces for IPPrototyper tool" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "AForge" )] +[assembly: AssemblyProduct( "AForge.NET" )] +[assembly: AssemblyCopyright( "AForge © 2012" )] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible( false )] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid( "894e5929-c328-4c50-8a3b-ac46c3c43a0e" )] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion( "1.0.1.1" )] +[assembly: AssemblyFileVersion( "1.0.1.1" )] diff --git a/Tools/IPPrototyper/MainForm.Designer.cs b/Tools/IPPrototyper/MainForm.Designer.cs new file mode 100644 index 0000000000..33936d329 --- /dev/null +++ b/Tools/IPPrototyper/MainForm.Designer.cs @@ -0,0 +1,508 @@ +namespace IPPrototyper +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if ( disposing && ( components != null ) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.menuStrip = new System.Windows.Forms.MenuStrip( ); + this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.openFolderToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator( ); + this.recentFoldersToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator( ); + this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.toolsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.copyImageClipboardToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.showhistogramToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.modulesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.settingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.imageviewToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.normalToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.centerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.stretchToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.openLastFolderOnStartToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.statusStrip = new System.Windows.Forms.StatusStrip( ); + this.imagesCountLabel = new System.Windows.Forms.ToolStripStatusLabel( ); + this.processingTimeLabel = new System.Windows.Forms.ToolStripStatusLabel( ); + this.imageSizeLabel = new System.Windows.Forms.ToolStripStatusLabel( ); + this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel( ); + this.mainPanel = new System.Windows.Forms.Panel( ); + this.mainSplitContainer = new System.Windows.Forms.SplitContainer( ); + this.splitContainer1 = new System.Windows.Forms.SplitContainer( ); + this.filesListView = new System.Windows.Forms.ListView( ); + this.fileNameColumn = new System.Windows.Forms.ColumnHeader( ); + this.logListView = new System.Windows.Forms.ListView( ); + this.processingStepsColumn = new System.Windows.Forms.ColumnHeader( ); + this.splitContainer2 = new System.Windows.Forms.SplitContainer( ); + this.pictureBox = new System.Windows.Forms.PictureBox( ); + this.logBox = new System.Windows.Forms.TextBox( ); + this.folderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog( ); + this.autoSizeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem( ); + this.menuStrip.SuspendLayout( ); + this.statusStrip.SuspendLayout( ); + this.mainPanel.SuspendLayout( ); + this.mainSplitContainer.Panel1.SuspendLayout( ); + this.mainSplitContainer.Panel2.SuspendLayout( ); + this.mainSplitContainer.SuspendLayout( ); + this.splitContainer1.Panel1.SuspendLayout( ); + this.splitContainer1.Panel2.SuspendLayout( ); + this.splitContainer1.SuspendLayout( ); + this.splitContainer2.Panel1.SuspendLayout( ); + this.splitContainer2.Panel2.SuspendLayout( ); + this.splitContainer2.SuspendLayout( ); + ( (System.ComponentModel.ISupportInitialize) ( this.pictureBox ) ).BeginInit( ); + this.SuspendLayout( ); + // + // menuStrip + // + this.menuStrip.Items.AddRange( new System.Windows.Forms.ToolStripItem[] { + this.fileToolStripMenuItem, + this.toolsToolStripMenuItem, + this.modulesToolStripMenuItem, + this.settingsToolStripMenuItem, + this.helpToolStripMenuItem} ); + this.menuStrip.Location = new System.Drawing.Point( 0, 0 ); + this.menuStrip.Name = "menuStrip"; + this.menuStrip.Size = new System.Drawing.Size( 694, 24 ); + this.menuStrip.TabIndex = 0; + this.menuStrip.Text = "menuStrip1"; + // + // fileToolStripMenuItem + // + this.fileToolStripMenuItem.DropDownItems.AddRange( new System.Windows.Forms.ToolStripItem[] { + this.openFolderToolStripMenuItem, + this.toolStripMenuItem1, + this.recentFoldersToolStripMenuItem, + this.toolStripMenuItem2, + this.exitToolStripMenuItem} ); + this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; + this.fileToolStripMenuItem.Size = new System.Drawing.Size( 37, 20 ); + this.fileToolStripMenuItem.Text = "&File"; + // + // openFolderToolStripMenuItem + // + this.openFolderToolStripMenuItem.Name = "openFolderToolStripMenuItem"; + this.openFolderToolStripMenuItem.ShortcutKeys = ( (System.Windows.Forms.Keys) ( ( System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O ) ) ); + this.openFolderToolStripMenuItem.Size = new System.Drawing.Size( 180, 22 ); + this.openFolderToolStripMenuItem.Text = "&Open folder"; + this.openFolderToolStripMenuItem.Click += new System.EventHandler( this.openFolderToolStripMenuItem_Click ); + // + // toolStripMenuItem1 + // + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + this.toolStripMenuItem1.Size = new System.Drawing.Size( 177, 6 ); + // + // recentFoldersToolStripMenuItem + // + this.recentFoldersToolStripMenuItem.Name = "recentFoldersToolStripMenuItem"; + this.recentFoldersToolStripMenuItem.Size = new System.Drawing.Size( 180, 22 ); + this.recentFoldersToolStripMenuItem.Text = "&Recent Folders"; + // + // toolStripMenuItem2 + // + this.toolStripMenuItem2.Name = "toolStripMenuItem2"; + this.toolStripMenuItem2.Size = new System.Drawing.Size( 177, 6 ); + // + // exitToolStripMenuItem + // + this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; + this.exitToolStripMenuItem.Size = new System.Drawing.Size( 180, 22 ); + this.exitToolStripMenuItem.Text = "E&xit"; + this.exitToolStripMenuItem.Click += new System.EventHandler( this.exitToolStripMenuItem_Click ); + // + // toolsToolStripMenuItem + // + this.toolsToolStripMenuItem.DropDownItems.AddRange( new System.Windows.Forms.ToolStripItem[] { + this.copyImageClipboardToolStripMenuItem, + this.showhistogramToolStripMenuItem} ); + this.toolsToolStripMenuItem.Name = "toolsToolStripMenuItem"; + this.toolsToolStripMenuItem.Size = new System.Drawing.Size( 48, 20 ); + this.toolsToolStripMenuItem.Text = "&Tools"; + this.toolsToolStripMenuItem.DropDownOpening += new System.EventHandler( this.toolsToolStripMenuItem_DropDownOpening ); + // + // copyImageClipboardToolStripMenuItem + // + this.copyImageClipboardToolStripMenuItem.Name = "copyImageClipboardToolStripMenuItem"; + this.copyImageClipboardToolStripMenuItem.Size = new System.Drawing.Size( 205, 22 ); + this.copyImageClipboardToolStripMenuItem.Text = "&Copy image to clipboard"; + this.copyImageClipboardToolStripMenuItem.Click += new System.EventHandler( this.copyImageClipboardToolStripMenuItem_Click ); + // + // showhistogramToolStripMenuItem + // + this.showhistogramToolStripMenuItem.Name = "showhistogramToolStripMenuItem"; + this.showhistogramToolStripMenuItem.Size = new System.Drawing.Size( 205, 22 ); + this.showhistogramToolStripMenuItem.Text = "Show &histogram"; + this.showhistogramToolStripMenuItem.Click += new System.EventHandler( this.showhistogramToolStripMenuItem_Click ); + // + // modulesToolStripMenuItem + // + this.modulesToolStripMenuItem.Name = "modulesToolStripMenuItem"; + this.modulesToolStripMenuItem.Size = new System.Drawing.Size( 65, 20 ); + this.modulesToolStripMenuItem.Text = "&Modules"; + this.modulesToolStripMenuItem.DropDownOpening += new System.EventHandler( this.modulesToolStripMenuItem_DropDownOpening ); + // + // settingsToolStripMenuItem + // + this.settingsToolStripMenuItem.DropDownItems.AddRange( new System.Windows.Forms.ToolStripItem[] { + this.imageviewToolStripMenuItem, + this.openLastFolderOnStartToolStripMenuItem} ); + this.settingsToolStripMenuItem.Name = "settingsToolStripMenuItem"; + this.settingsToolStripMenuItem.Size = new System.Drawing.Size( 61, 20 ); + this.settingsToolStripMenuItem.Text = "&Settings"; + // + // imageviewToolStripMenuItem + // + this.imageviewToolStripMenuItem.DropDownItems.AddRange( new System.Windows.Forms.ToolStripItem[] { + this.normalToolStripMenuItem, + this.centerToolStripMenuItem, + this.stretchToolStripMenuItem, + this.autoSizeToolStripMenuItem} ); + this.imageviewToolStripMenuItem.Name = "imageviewToolStripMenuItem"; + this.imageviewToolStripMenuItem.Size = new System.Drawing.Size( 201, 22 ); + this.imageviewToolStripMenuItem.Text = "Image &view"; + this.imageviewToolStripMenuItem.DropDownOpening += new System.EventHandler( this.imageviewToolStripMenuItem_DropDownOpening ); + // + // normalToolStripMenuItem + // + this.normalToolStripMenuItem.Name = "normalToolStripMenuItem"; + this.normalToolStripMenuItem.Size = new System.Drawing.Size( 152, 22 ); + this.normalToolStripMenuItem.Text = "&Normal"; + this.normalToolStripMenuItem.Click += new System.EventHandler( this.normalToolStripMenuItem_Click ); + // + // centerToolStripMenuItem + // + this.centerToolStripMenuItem.Name = "centerToolStripMenuItem"; + this.centerToolStripMenuItem.Size = new System.Drawing.Size( 152, 22 ); + this.centerToolStripMenuItem.Text = "&Center"; + this.centerToolStripMenuItem.Click += new System.EventHandler( this.centerToolStripMenuItem_Click ); + // + // stretchToolStripMenuItem + // + this.stretchToolStripMenuItem.Name = "stretchToolStripMenuItem"; + this.stretchToolStripMenuItem.Size = new System.Drawing.Size( 152, 22 ); + this.stretchToolStripMenuItem.Text = "&Stretch"; + this.stretchToolStripMenuItem.Click += new System.EventHandler( this.stretchToolStripMenuItem_Click ); + // + // openLastFolderOnStartToolStripMenuItem + // + this.openLastFolderOnStartToolStripMenuItem.Name = "openLastFolderOnStartToolStripMenuItem"; + this.openLastFolderOnStartToolStripMenuItem.Size = new System.Drawing.Size( 201, 22 ); + this.openLastFolderOnStartToolStripMenuItem.Text = "&Open last folder on start"; + this.openLastFolderOnStartToolStripMenuItem.Click += new System.EventHandler( this.openLastFolderOnStartToolStripMenuItem_Click ); + // + // helpToolStripMenuItem + // + this.helpToolStripMenuItem.DropDownItems.AddRange( new System.Windows.Forms.ToolStripItem[] { + this.aboutToolStripMenuItem} ); + this.helpToolStripMenuItem.Name = "helpToolStripMenuItem"; + this.helpToolStripMenuItem.Size = new System.Drawing.Size( 44, 20 ); + this.helpToolStripMenuItem.Text = "&Help"; + // + // aboutToolStripMenuItem + // + this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem"; + this.aboutToolStripMenuItem.Size = new System.Drawing.Size( 107, 22 ); + this.aboutToolStripMenuItem.Text = "&About"; + this.aboutToolStripMenuItem.Click += new System.EventHandler( this.aboutToolStripMenuItem_Click ); + // + // statusStrip + // + this.statusStrip.Items.AddRange( new System.Windows.Forms.ToolStripItem[] { + this.imagesCountLabel, + this.processingTimeLabel, + this.imageSizeLabel, + this.toolStripStatusLabel1} ); + this.statusStrip.Location = new System.Drawing.Point( 0, 436 ); + this.statusStrip.Name = "statusStrip"; + this.statusStrip.Size = new System.Drawing.Size( 694, 22 ); + this.statusStrip.TabIndex = 1; + this.statusStrip.Text = "statusStrip1"; + // + // imagesCountLabel + // + this.imagesCountLabel.AutoSize = false; + this.imagesCountLabel.BorderSides = ( (System.Windows.Forms.ToolStripStatusLabelBorderSides) ( ( ( ( System.Windows.Forms.ToolStripStatusLabelBorderSides.Left | System.Windows.Forms.ToolStripStatusLabelBorderSides.Top ) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Right ) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Bottom ) ) ); + this.imagesCountLabel.BorderStyle = System.Windows.Forms.Border3DStyle.SunkenInner; + this.imagesCountLabel.Name = "imagesCountLabel"; + this.imagesCountLabel.Size = new System.Drawing.Size( 150, 17 ); + this.imagesCountLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // processingTimeLabel + // + this.processingTimeLabel.AutoSize = false; + this.processingTimeLabel.BorderSides = ( (System.Windows.Forms.ToolStripStatusLabelBorderSides) ( ( ( ( System.Windows.Forms.ToolStripStatusLabelBorderSides.Left | System.Windows.Forms.ToolStripStatusLabelBorderSides.Top ) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Right ) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Bottom ) ) ); + this.processingTimeLabel.BorderStyle = System.Windows.Forms.Border3DStyle.SunkenInner; + this.processingTimeLabel.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.processingTimeLabel.Name = "processingTimeLabel"; + this.processingTimeLabel.Size = new System.Drawing.Size( 150, 17 ); + this.processingTimeLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.processingTimeLabel.ToolTipText = "Time taken processing last image"; + // + // imageSizeLabel + // + this.imageSizeLabel.AutoSize = false; + this.imageSizeLabel.BorderSides = ( (System.Windows.Forms.ToolStripStatusLabelBorderSides) ( ( ( ( System.Windows.Forms.ToolStripStatusLabelBorderSides.Left | System.Windows.Forms.ToolStripStatusLabelBorderSides.Top ) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Right ) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Bottom ) ) ); + this.imageSizeLabel.BorderStyle = System.Windows.Forms.Border3DStyle.SunkenInner; + this.imageSizeLabel.Name = "imageSizeLabel"; + this.imageSizeLabel.Size = new System.Drawing.Size( 150, 17 ); + this.imageSizeLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.imageSizeLabel.ToolTipText = "Size of currently shown image"; + // + // toolStripStatusLabel1 + // + this.toolStripStatusLabel1.BorderSides = ( (System.Windows.Forms.ToolStripStatusLabelBorderSides) ( ( ( ( System.Windows.Forms.ToolStripStatusLabelBorderSides.Left | System.Windows.Forms.ToolStripStatusLabelBorderSides.Top ) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Right ) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Bottom ) ) ); + this.toolStripStatusLabel1.BorderStyle = System.Windows.Forms.Border3DStyle.SunkenInner; + this.toolStripStatusLabel1.Name = "toolStripStatusLabel1"; + this.toolStripStatusLabel1.Size = new System.Drawing.Size( 229, 17 ); + this.toolStripStatusLabel1.Spring = true; + // + // mainPanel + // + this.mainPanel.Controls.Add( this.mainSplitContainer ); + this.mainPanel.Dock = System.Windows.Forms.DockStyle.Fill; + this.mainPanel.Location = new System.Drawing.Point( 0, 24 ); + this.mainPanel.Name = "mainPanel"; + this.mainPanel.Size = new System.Drawing.Size( 694, 412 ); + this.mainPanel.TabIndex = 2; + // + // mainSplitContainer + // + this.mainSplitContainer.Dock = System.Windows.Forms.DockStyle.Fill; + this.mainSplitContainer.Location = new System.Drawing.Point( 0, 0 ); + this.mainSplitContainer.Name = "mainSplitContainer"; + // + // mainSplitContainer.Panel1 + // + this.mainSplitContainer.Panel1.Controls.Add( this.splitContainer1 ); + this.mainSplitContainer.Panel1.Resize += new System.EventHandler( this.mainSplitContainer_Panel1_Resize ); + // + // mainSplitContainer.Panel2 + // + this.mainSplitContainer.Panel2.Controls.Add( this.splitContainer2 ); + this.mainSplitContainer.Size = new System.Drawing.Size( 694, 412 ); + this.mainSplitContainer.SplitterDistance = 185; + this.mainSplitContainer.TabIndex = 4; + // + // splitContainer1 + // + this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer1.Location = new System.Drawing.Point( 0, 0 ); + this.splitContainer1.Name = "splitContainer1"; + this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal; + // + // splitContainer1.Panel1 + // + this.splitContainer1.Panel1.Controls.Add( this.filesListView ); + // + // splitContainer1.Panel2 + // + this.splitContainer1.Panel2.Controls.Add( this.logListView ); + this.splitContainer1.Size = new System.Drawing.Size( 185, 412 ); + this.splitContainer1.SplitterDistance = 206; + this.splitContainer1.TabIndex = 3; + // + // filesListView + // + this.filesListView.Columns.AddRange( new System.Windows.Forms.ColumnHeader[] { + this.fileNameColumn} ); + this.filesListView.Dock = System.Windows.Forms.DockStyle.Fill; + this.filesListView.FullRowSelect = true; + this.filesListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.filesListView.HideSelection = false; + this.filesListView.Location = new System.Drawing.Point( 0, 0 ); + this.filesListView.MultiSelect = false; + this.filesListView.Name = "filesListView"; + this.filesListView.Size = new System.Drawing.Size( 185, 206 ); + this.filesListView.Sorting = System.Windows.Forms.SortOrder.Ascending; + this.filesListView.TabIndex = 0; + this.filesListView.UseCompatibleStateImageBehavior = false; + this.filesListView.View = System.Windows.Forms.View.Details; + this.filesListView.SelectedIndexChanged += new System.EventHandler( this.filesListView_SelectedIndexChanged ); + // + // fileNameColumn + // + this.fileNameColumn.Text = "File names"; + this.fileNameColumn.Width = 130; + // + // logListView + // + this.logListView.Columns.AddRange( new System.Windows.Forms.ColumnHeader[] { + this.processingStepsColumn} ); + this.logListView.Dock = System.Windows.Forms.DockStyle.Fill; + this.logListView.FullRowSelect = true; + this.logListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.logListView.HideSelection = false; + this.logListView.Location = new System.Drawing.Point( 0, 0 ); + this.logListView.MultiSelect = false; + this.logListView.Name = "logListView"; + this.logListView.Size = new System.Drawing.Size( 185, 202 ); + this.logListView.TabIndex = 2; + this.logListView.UseCompatibleStateImageBehavior = false; + this.logListView.View = System.Windows.Forms.View.Details; + this.logListView.SelectedIndexChanged += new System.EventHandler( this.logListView_SelectedIndexChanged ); + // + // processingStepsColumn + // + this.processingStepsColumn.Text = "Processing steps"; + this.processingStepsColumn.Width = 130; + // + // splitContainer2 + // + this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer2.Location = new System.Drawing.Point( 0, 0 ); + this.splitContainer2.Name = "splitContainer2"; + this.splitContainer2.Orientation = System.Windows.Forms.Orientation.Horizontal; + // + // splitContainer2.Panel1 + // + this.splitContainer2.Panel1.Controls.Add( this.pictureBox ); + // + // splitContainer2.Panel2 + // + this.splitContainer2.Panel2.Controls.Add( this.logBox ); + this.splitContainer2.Size = new System.Drawing.Size( 505, 412 ); + this.splitContainer2.SplitterDistance = 301; + this.splitContainer2.TabIndex = 6; + // + // pictureBox + // + this.pictureBox.BackColor = System.Drawing.SystemColors.ControlDark; + this.pictureBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.pictureBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.pictureBox.Location = new System.Drawing.Point( 0, 0 ); + this.pictureBox.Name = "pictureBox"; + this.pictureBox.Size = new System.Drawing.Size( 505, 301 ); + this.pictureBox.TabIndex = 1; + this.pictureBox.TabStop = false; + // + // logBox + // + this.logBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.logBox.Location = new System.Drawing.Point( 0, 0 ); + this.logBox.Multiline = true; + this.logBox.Name = "logBox"; + this.logBox.ReadOnly = true; + this.logBox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; + this.logBox.Size = new System.Drawing.Size( 505, 107 ); + this.logBox.TabIndex = 7; + // + // folderBrowserDialog + // + this.folderBrowserDialog.Description = "Select folder containing images to process:"; + // + // autoSizeToolStripMenuItem + // + this.autoSizeToolStripMenuItem.Name = "autoSizeToolStripMenuItem"; + this.autoSizeToolStripMenuItem.Size = new System.Drawing.Size( 152, 22 ); + this.autoSizeToolStripMenuItem.Text = "&Auto Size"; + this.autoSizeToolStripMenuItem.Click += new System.EventHandler( this.autoSizeToolStripMenuItem_Click ); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 13F ); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size( 694, 458 ); + this.Controls.Add( this.mainPanel ); + this.Controls.Add( this.statusStrip ); + this.Controls.Add( this.menuStrip ); + this.MainMenuStrip = this.menuStrip; + this.Name = "MainForm"; + this.Text = "Image Processing Prototyper"; + this.Load += new System.EventHandler( this.MainForm_Load ); + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler( this.MainForm_FormClosing ); + this.menuStrip.ResumeLayout( false ); + this.menuStrip.PerformLayout( ); + this.statusStrip.ResumeLayout( false ); + this.statusStrip.PerformLayout( ); + this.mainPanel.ResumeLayout( false ); + this.mainSplitContainer.Panel1.ResumeLayout( false ); + this.mainSplitContainer.Panel2.ResumeLayout( false ); + this.mainSplitContainer.ResumeLayout( false ); + this.splitContainer1.Panel1.ResumeLayout( false ); + this.splitContainer1.Panel2.ResumeLayout( false ); + this.splitContainer1.ResumeLayout( false ); + this.splitContainer2.Panel1.ResumeLayout( false ); + this.splitContainer2.Panel2.ResumeLayout( false ); + this.splitContainer2.Panel2.PerformLayout( ); + this.splitContainer2.ResumeLayout( false ); + ( (System.ComponentModel.ISupportInitialize) ( this.pictureBox ) ).EndInit( ); + this.ResumeLayout( false ); + this.PerformLayout( ); + + } + + #endregion + + private System.Windows.Forms.MenuStrip menuStrip; + private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem openFolderToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; + private System.Windows.Forms.StatusStrip statusStrip; + private System.Windows.Forms.Panel mainPanel; + private System.Windows.Forms.FolderBrowserDialog folderBrowserDialog; + private System.Windows.Forms.ListView filesListView; + private System.Windows.Forms.ColumnHeader fileNameColumn; + private System.Windows.Forms.PictureBox pictureBox; + private System.Windows.Forms.ListView logListView; + private System.Windows.Forms.ColumnHeader processingStepsColumn; + private System.Windows.Forms.ToolStripMenuItem settingsToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem imageviewToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem normalToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem centerToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem stretchToolStripMenuItem; + private System.Windows.Forms.SplitContainer splitContainer1; + private System.Windows.Forms.ToolStripMenuItem modulesToolStripMenuItem; + private System.Windows.Forms.SplitContainer mainSplitContainer; + private System.Windows.Forms.SplitContainer splitContainer2; + private System.Windows.Forms.TextBox logBox; + private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem toolsToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem copyImageClipboardToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem showhistogramToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem recentFoldersToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripMenuItem2; + private System.Windows.Forms.ToolStripMenuItem openLastFolderOnStartToolStripMenuItem; + private System.Windows.Forms.ToolStripStatusLabel imagesCountLabel; + private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1; + private System.Windows.Forms.ToolStripStatusLabel processingTimeLabel; + private System.Windows.Forms.ToolStripStatusLabel imageSizeLabel; + private System.Windows.Forms.ToolStripMenuItem autoSizeToolStripMenuItem; + } +} + diff --git a/Tools/IPPrototyper/MainForm.cs b/Tools/IPPrototyper/MainForm.cs new file mode 100644 index 0000000000..1afe7eef3 --- /dev/null +++ b/Tools/IPPrototyper/MainForm.cs @@ -0,0 +1,674 @@ +// Image Processing Prototyper +// AForge.NET framework +// http://www.aforgenet.com/framework/ +// +// Copyright © AForge.NET, 2010-2011 +// contacts@aforgenet.com +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; +using System.IO; +using System.Reflection; + +using AForge; +using AForge.Imaging; +using AForge.Imaging.IPPrototyper; + +namespace IPPrototyper +{ + internal partial class MainForm : Form + { + // selected folder containing images to process + private string selectedFolder; + // list of found image processing routines + private Dictionary processingRoutines = new Dictionary( ); + // currently active image processing routine to use + private IImageProcessingRoutine ipRoutineToUse = null; + // image processing log + private ImageProcessingLog processingLog = new ImageProcessingLog( ); + + private HistogramForm histogramForm = null; + + // list of recently used folders + private List recentFolders = new List( ); + + // stopwatch to measure time taken by image processing routine + System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch( ); + + #region Configuration Option Names + private const string mainFormXOption = "MainFormX"; + private const string mainFormYOption = "MainFormY"; + private const string mainFormWidthOption = "MainFormWidth"; + private const string mainFormHeightOption = "MainFormHeight"; + private const string mainFormStateOption = "MainFormState"; + private const string splitter1Option = "Splitter1"; + private const string splitter2Option = "Splitter2"; + private const string splitter3Option = "Splitter3"; + private const string recentFolderOption = "RecentFolder"; + private const string pictureSizeModeOption = "PictureSizeMode"; + private const string openLastOption = "OpenLastFolder"; + #endregion + + + public MainForm( ) + { + InitializeComponent( ); + + } + + // On form loading + private void MainForm_Load( object sender, EventArgs e ) + { + // collect available modules in application's directory + CollectModules( Path.GetDirectoryName( Application.ExecutablePath ) ); + // add modules' name to application's menu + foreach ( string routineName in processingRoutines.Keys ) + { + ToolStripItem item = modulesToolStripMenuItem.DropDownItems.Add( routineName ); + + item.Click += new System.EventHandler( this.module_Click ); + + if ( ipRoutineToUse == null ) + { + ipRoutineToUse = processingRoutines[routineName]; + } + } + + // load configuratio + Configuration config = Configuration.Instance; + + if ( config.Load( ) ) + { + try + { + bool windowPositionIsValid = false; + // get window location/size + Size windowSize = new Size( + int.Parse( config.GetConfigurationOption( mainFormWidthOption ) ), + int.Parse( config.GetConfigurationOption( mainFormHeightOption ) ) ); + System.Drawing.Point windowTopLeft = new System.Drawing.Point( + int.Parse( config.GetConfigurationOption( mainFormXOption ) ), + int.Parse( config.GetConfigurationOption( mainFormYOption ) ) ); + System.Drawing.Point windowTopRight = new System.Drawing.Point( + windowTopLeft.X + windowSize.Width, windowTopLeft.Y ); + + // check if window location is within of the displays + foreach ( Screen screen in Screen.AllScreens ) + { + if ( ( screen.WorkingArea.Contains( windowTopLeft ) ) || + ( screen.WorkingArea.Contains( windowTopRight ) ) ) + { + windowPositionIsValid = true; + break; + } + } + + if ( windowPositionIsValid ) + { + Location = windowTopLeft; + Size = windowSize; + + WindowState = (FormWindowState) Enum.Parse( typeof( FormWindowState ), + config.GetConfigurationOption( mainFormStateOption ) ); + + mainSplitContainer.SplitterDistance = int.Parse( config.GetConfigurationOption( splitter1Option ) ); + splitContainer1.SplitterDistance = int.Parse( config.GetConfigurationOption( splitter2Option ) ); + splitContainer2.SplitterDistance = int.Parse( config.GetConfigurationOption( splitter3Option ) ); + } + + // get size mode of picture box + SetPictureBoxSizeMode( (PictureBoxSizeMode) Enum.Parse( typeof( PictureBoxSizeMode ), + config.GetConfigurationOption( pictureSizeModeOption ) ) ); + + // get recent folders + for ( int i = 0; i < 7; i++ ) + { + string rf = config.GetConfigurationOption( recentFolderOption + i ); + + if ( rf != null ) + recentFolders.Add( rf ); + } + + RebuildRecentFoldersList( ); + + bool openLast = bool.Parse( config.GetConfigurationOption( openLastOption ) ); + openLastFolderOnStartToolStripMenuItem.Checked = openLast; + + if ( ( openLast ) && ( recentFolders.Count > 0 ) ) + { + OpenFolder( recentFolders[0] ); + } + } + catch + { + } + } + } + + // Rebuild menu with the list of recently used folders + private void RebuildRecentFoldersList( ) + { + // unsubscribe from events + foreach ( ToolStripItem item in recentFoldersToolStripMenuItem.DropDownItems ) + { + item.Click -= new EventHandler( recentFolder_Click ); + } + + // remove all current items + recentFoldersToolStripMenuItem.DropDownItems.Clear( ); + + // add new items + foreach ( string folderName in recentFolders ) + { + ToolStripItem item = recentFoldersToolStripMenuItem.DropDownItems.Add( folderName ); + + item.Click += new EventHandler( recentFolder_Click ); + } + } + + // On form closing + private void MainForm_FormClosing( object sender, FormClosingEventArgs e ) + { + Configuration config = Configuration.Instance; + + // save window location/size + if ( WindowState != FormWindowState.Minimized ) + { + if ( WindowState != FormWindowState.Maximized ) + { + config.SetConfigurationOption( mainFormXOption, Location.X.ToString( ) ); + config.SetConfigurationOption( mainFormYOption, Location.Y.ToString( ) ); + config.SetConfigurationOption( mainFormWidthOption, Width.ToString( ) ); + config.SetConfigurationOption( mainFormHeightOption, Height.ToString( ) ); + } + config.SetConfigurationOption( mainFormStateOption, WindowState.ToString( ) ); + + config.SetConfigurationOption( splitter1Option, mainSplitContainer.SplitterDistance.ToString( ) ); + config.SetConfigurationOption( splitter2Option, splitContainer1.SplitterDistance.ToString( ) ); + config.SetConfigurationOption( splitter3Option, splitContainer2.SplitterDistance.ToString( ) ); + } + + // save size mode of picture box + config.SetConfigurationOption( pictureSizeModeOption, pictureBox.SizeMode.ToString( ) ); + + // save recent folders + for ( int i = 0, n = recentFolders.Count; i < n; i++ ) + { + config.SetConfigurationOption( recentFolderOption + i, recentFolders[i] ); + } + config.SetConfigurationOption( openLastOption, openLastFolderOnStartToolStripMenuItem.Checked.ToString( ) ); + + try + { + config.Save( ); + } + catch ( IOException ex ) + { + MessageBox.Show( "Failed saving confguration file.\r\n\r\n" + ex.Message, + "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); + } + } + + // Add folder to the list of recently used folders + public void AddRecentFolder( string folderName ) + { + int index = recentFolders.IndexOf( folderName ); + + if ( index != 0 ) + { + if ( index != -1 ) + { + // remove previous entry + recentFolders.RemoveAt( index ); + } + + // put this folder as the most recent + recentFolders.Insert( 0, folderName ); + + if ( recentFolders.Count > 7 ) + { + recentFolders.RemoveAt( 7 ); + } + } + } + + // Remove specified folder from the list of recently used folders + public void RemoveRecentFolder( string folderName ) + { + recentFolders.Remove( folderName ); + } + + // Update check style of modules' items + private void modulesToolStripMenuItem_DropDownOpening( object sender, EventArgs e ) + { + foreach ( ToolStripMenuItem item in modulesToolStripMenuItem.DropDownItems ) + { + item.Checked = ( ( ipRoutineToUse != null ) && ( ipRoutineToUse.Name == item.Text ) ); + } + } + + // Item is clicked in modules' menu + private void module_Click( object sender, EventArgs e ) + { + ipRoutineToUse = processingRoutines[( (ToolStripMenuItem) sender ).Text]; + ProcessSelectedImage( ); + } + + // Exit from application + private void exitToolStripMenuItem_Click( object sender, EventArgs e ) + { + this.Close( ); + } + + // Collect information about available modules + private void CollectModules( string path ) + { + // create directory info + DirectoryInfo dir = new DirectoryInfo( path ); + + // get all dll files from the directory + FileInfo[] files = dir.GetFiles( "*.dll" ); + + // walk through all files + foreach ( FileInfo f in files ) + { + CollectImageProcessingRoutines( Path.Combine( path, f.Name ) ); + } + } + + // Collect available image processing routines in the specified assembly + private void CollectImageProcessingRoutines( string fname ) + { + Type typeIImageProcessingRoutine = typeof( IImageProcessingRoutine ); + Assembly assembly = null; + + try + { + // try to load assembly + assembly = Assembly.LoadFrom( fname ); + + // get types of the assembly + Type[] types = assembly.GetTypes( ); + + // check all types + foreach ( Type type in types ) + { + // get interfaces ot the type + Type[] interfaces = type.GetInterfaces( ); + + // check, if the type is inherited from IImageProcessingRoutine + if ( Array.IndexOf( interfaces, typeIImageProcessingRoutine ) != -1 ) + { + IImageProcessingRoutine ipRoutine = null; + + try + { + // create an instance of the type + ipRoutine = (IImageProcessingRoutine) Activator.CreateInstance( type ); + // add routine to collection + if ( !processingRoutines.ContainsKey( ipRoutine.Name ) ) + processingRoutines.Add( ipRoutine.Name, ipRoutine ); + } + catch ( Exception ) + { + // something failed during instance creatinion + } + } + } + } + catch ( Exception ) + { + } + } + + // Open folder + private void openFolderToolStripMenuItem_Click( object sender, EventArgs e ) + { + if ( folderBrowserDialog.ShowDialog( ) == DialogResult.OK ) + { + if ( OpenFolder( folderBrowserDialog.SelectedPath ) ) + { + // remember this folder + AddRecentFolder( selectedFolder ); + RebuildRecentFoldersList( ); + } + } + } + + // Item is clicked in recent folders list + private void recentFolder_Click( object sender, EventArgs e ) + { + string folderName = ( (ToolStripMenuItem) sender ).Text; + + if ( OpenFolder( folderName ) ) + { + // move the folder up in the list + AddRecentFolder( folderName ); + } + else + { + // remove failing folder + RemoveRecentFolder( folderName ); + } + RebuildRecentFoldersList( ); + } + + // Open specified folder + private bool OpenFolder( string folderName ) + { + bool success = false; + + try + { + DirectoryInfo dirInfo = new DirectoryInfo( folderName ); + FileInfo[] fileInfos = dirInfo.GetFiles( ); + + filesListView.Items.Clear( ); + + // collect all image files + foreach ( FileInfo fi in fileInfos ) + { + string ext = fi.Extension.ToLower( ); + + // check for supported extension + if ( + ( ext == ".jpg" ) || ( ext == ".jpeg" ) || + ( ext == ".bmp" ) || ( ext == ".png" ) ) + { + filesListView.Items.Add( fi.Name ); + } + } + + logListView.Items.Clear( ); + filesListView.Focus( ); + ProcessSelectedImage( ); + + selectedFolder = folderName; + success = true; + } + catch + { + MessageBox.Show( "Failed opening the folder:\n" + folderName, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); + } + + UpdateImageCountStatus( ); + + return success; + } + + // Selection has changed in files list view control + private void filesListView_SelectedIndexChanged( object sender, EventArgs e ) + { + ProcessSelectedImage( ); + } + + // Process currently selected image + private void ProcessSelectedImage( ) + { + if ( filesListView.SelectedItems.Count == 1 ) + { + Bitmap image = null; + + try + { + image = (Bitmap) Bitmap.FromFile( Path.Combine( selectedFolder, filesListView.SelectedItems[0].Text ) ); + } + catch + { + } + + if ( image != null ) + { + ProcessImage( image ); + ShowLogMessages( ); + UpdateLogView( ); + return; + } + else + { + MessageBox.Show( "Failed loading file: " + filesListView.SelectedItems[0].Text, + "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); + filesListView.Items.Remove( filesListView.SelectedItems[0] ); + UpdateImageCountStatus( ); + } + } + + pictureBox.Image = null; + logBox.Text = string.Empty; + } + + // Process specified image + private void ProcessImage( Bitmap image ) + { + processingLog.Clear( ); + processingLog.AddImage( "Source", image ); + + if ( ipRoutineToUse != null ) + { + stopWatch.Reset( ); + stopWatch.Start( ); + + // process image with selected image processing routine + ipRoutineToUse.Process( image, processingLog ); + + stopWatch.Stop( ); + + UpdateProcessingTimeStatus( stopWatch.ElapsedMilliseconds ); + } + } + + // Update log view + private void UpdateLogView( ) + { + string currentSelection = string.Empty; + int newSelectionIndex = 0; + int i = 0; + + if ( logListView.SelectedIndices.Count > 0 ) + { + currentSelection = logListView.Items[logListView.SelectedIndices[0]].Text; + } + + logListView.Items.Clear( ); + + foreach ( KeyValuePair kvp in processingLog.Images ) + { + logListView.Items.Add( kvp.Key ); + + if ( kvp.Key == currentSelection ) + newSelectionIndex = i; + + i++; + } + + logListView.SelectedIndices.Add( newSelectionIndex ); + logListView.EnsureVisible( newSelectionIndex ); + } + + // Display log messages + private void ShowLogMessages( ) + { + StringBuilder sb = new StringBuilder( ); + + foreach ( string message in processingLog.Messages ) + { + sb.Append( message ); + sb.Append( "\r\n" ); + } + + logBox.Text = sb.ToString( ); + } + + // Selection has changed in log list view - update image + private void logListView_SelectedIndexChanged( object sender, EventArgs e ) + { + if ( logListView.SelectedIndices.Count == 1 ) + { + string stepName = logListView.SelectedItems[0].Text; + + Bitmap oldImage = (Bitmap) pictureBox.Image; + pictureBox.Image = (Bitmap) processingLog.Images[stepName].Clone( ); + + if ( oldImage != null ) + { + oldImage.Dispose( ); + } + + ShowCurrentImageHistogram( ); + UpdateImageSizeStatus( ); + } + } + + // Update status of menu items in Settings->Image view + private void imageviewToolStripMenuItem_DropDownOpening( object sender, EventArgs e ) + { + normalToolStripMenuItem.Checked = ( pictureBox.SizeMode == PictureBoxSizeMode.Normal ); + centerToolStripMenuItem.Checked = ( pictureBox.SizeMode == PictureBoxSizeMode.CenterImage ); + stretchToolStripMenuItem.Checked = ( pictureBox.SizeMode == PictureBoxSizeMode.StretchImage ); + autoSizeToolStripMenuItem.Checked = ( pictureBox.SizeMode == PictureBoxSizeMode.AutoSize ); + } + + // Set Normal view for images + private void normalToolStripMenuItem_Click( object sender, EventArgs e ) + { + SetPictureBoxSizeMode( PictureBoxSizeMode.Normal ); + } + + // Set Centred view for images + private void centerToolStripMenuItem_Click( object sender, EventArgs e ) + { + SetPictureBoxSizeMode( PictureBoxSizeMode.CenterImage ); + } + + // Set Stretched view for images + private void stretchToolStripMenuItem_Click( object sender, EventArgs e ) + { + SetPictureBoxSizeMode( PictureBoxSizeMode.StretchImage ); + } + + // Set Auto Size view for image + private void autoSizeToolStripMenuItem_Click( object sender, EventArgs e ) + { + SetPictureBoxSizeMode( PictureBoxSizeMode.AutoSize ); + } + + // Set size mode for picture box + private void SetPictureBoxSizeMode( PictureBoxSizeMode sizeMode ) + { + if ( sizeMode == PictureBoxSizeMode.AutoSize ) + { + pictureBox.Dock = DockStyle.None; + pictureBox.Location = new System.Drawing.Point( 0, 0 ); + splitContainer2.Panel1.AutoScroll = true; + } + else + { + pictureBox.Dock = DockStyle.Fill; + splitContainer2.Panel1.AutoScroll = false; + } + + pictureBox.SizeMode = sizeMode; + } + + // Switch option for openning last folder on application load + private void openLastFolderOnStartToolStripMenuItem_Click( object sender, EventArgs e ) + { + openLastFolderOnStartToolStripMenuItem.Checked = !openLastFolderOnStartToolStripMenuItem.Checked; + } + + // Show about form + private void aboutToolStripMenuItem_Click( object sender, EventArgs e ) + { + AboutForm form = new AboutForm( ); + + form.ShowDialog( ); + } + + // Copy current image to clipboard + private void copyImageClipboardToolStripMenuItem_Click( object sender, EventArgs e ) + { + if ( pictureBox.Image != null ) + { + Clipboard.SetImage( pictureBox.Image ); + } + } + + // Update status of "copy to clipboard" menu item + private void toolsToolStripMenuItem_DropDownOpening( object sender, EventArgs e ) + { + copyImageClipboardToolStripMenuItem.Enabled = ( pictureBox.Image != null ); + } + + // Show histogram window + private void showhistogramToolStripMenuItem_Click( object sender, EventArgs e ) + { + if ( histogramForm == null ) + { + histogramForm = new HistogramForm( ); + histogramForm.FormClosing += delegate( object eventSender, FormClosingEventArgs eventArgs ) + { + histogramForm = null; + }; + } + + histogramForm.Show( ); + ShowCurrentImageHistogram( ); + } + + // Show histomgram for + private void ShowCurrentImageHistogram( ) + { + if ( ( pictureBox.Image != null ) && ( histogramForm != null ) ) + { + histogramForm.SetImageStatistics( new ImageStatistics( (Bitmap) pictureBox.Image ) ); + } + } + + // Update status label displaying number of available images + private void UpdateImageCountStatus( ) + { + imagesCountLabel.Text = "Images: " + filesListView.Items.Count.ToString( ); + } + + // Update staus label displaying processing time of last routine + private void UpdateProcessingTimeStatus( long msTime ) + { + double sTime = (double) msTime / 1000; + + processingTimeLabel.Text = string.Format( "Processing time: {0}s", sTime.ToString( "F3" ) ); + } + + // Update status label displaying size of selected image + private void UpdateImageSizeStatus( ) + { + if ( pictureBox.Image != null ) + { + imageSizeLabel.Text = string.Format( "Image size: {0}x{1}", + pictureBox.Image.Width, pictureBox.Image.Height ); + } + else + { + imageSizeLabel.Text = string.Empty; + } + } + + // Resize columns of file list view and log list view + private void mainSplitContainer_Panel1_Resize( object sender, EventArgs e ) + { + if ( fileNameColumn != null ) + { + fileNameColumn.Width = filesListView.Width - 24; + } + if ( processingStepsColumn != null ) + { + processingStepsColumn.Width = logListView.Width - 24; + } + } + } +} diff --git a/Tools/IPPrototyper/MainForm.resx b/Tools/IPPrototyper/MainForm.resx new file mode 100644 index 0000000000..0a5687e62 --- /dev/null +++ b/Tools/IPPrototyper/MainForm.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 132, 17 + + + 241, 17 + + \ No newline at end of file diff --git a/Tools/IPPrototyper/Program.cs b/Tools/IPPrototyper/Program.cs new file mode 100644 index 0000000000..feb98a86a --- /dev/null +++ b/Tools/IPPrototyper/Program.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; + +namespace IPPrototyper +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main( ) + { + Application.EnableVisualStyles( ); + Application.SetCompatibleTextRenderingDefault( false ); + Application.Run( new MainForm( ) ); + } + } +} diff --git a/Tools/IPPrototyper/Properties/AssemblyInfo.cs b/Tools/IPPrototyper/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..7b1a509e5 --- /dev/null +++ b/Tools/IPPrototyper/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle( "Image Processing Prototyper" )] +[assembly: AssemblyDescription( "" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "AForge" )] +[assembly: AssemblyProduct( "AForge.NET" )] +[assembly: AssemblyCopyright( "AForge © 2012" )] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible( false )] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid( "8bfe1665-04fd-49b8-bb89-ce8f07027925" )] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion( "1.0.1.1" )] +[assembly: AssemblyFileVersion( "1.0.1.1" )] diff --git a/Tools/IPPrototyper/Properties/Resources.Designer.cs b/Tools/IPPrototyper/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..b29af8f57 --- /dev/null +++ b/Tools/IPPrototyper/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.239 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace IPPrototyper.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("IPPrototyper.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Tools/IPPrototyper/Properties/Resources.resx b/Tools/IPPrototyper/Properties/Resources.resx new file mode 100644 index 0000000000..af7dbebba --- /dev/null +++ b/Tools/IPPrototyper/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Tools/IPPrototyper/Properties/Settings.Designer.cs b/Tools/IPPrototyper/Properties/Settings.Designer.cs new file mode 100644 index 0000000000..528f113fb --- /dev/null +++ b/Tools/IPPrototyper/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.239 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace IPPrototyper.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Tools/IPPrototyper/Properties/Settings.settings b/Tools/IPPrototyper/Properties/Settings.settings new file mode 100644 index 0000000000..39645652a --- /dev/null +++ b/Tools/IPPrototyper/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Tools/IPPrototyper/ipprototyper.csproj b/Tools/IPPrototyper/ipprototyper.csproj new file mode 100644 index 0000000000..884a05d91 --- /dev/null +++ b/Tools/IPPrototyper/ipprototyper.csproj @@ -0,0 +1,172 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {257502A9-6C82-4F86-815D-2CE0FA8C0036} + WinExe + Properties + IPPrototyper + IPPrototyper + v2.0 + 512 + false + true + AForge.IPPrototyper.snk + + + 3.5 + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true + + + true + full + false + ..\..\Release\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\..\Release\ + TRACE + prompt + 4 + + + + False + ..\..\Release\AForge.dll + + + False + ..\..\Release\AForge.Controls.dll + + + False + ..\..\Release\AForge.Imaging.dll + + + False + ..\..\Release\AForge.Math.dll + + + + + + + + + + + Form + + + AboutForm.cs + + + + Form + + + HistogramForm.cs + + + Form + + + MainForm.cs + + + + + AboutForm.cs + + + HistogramForm.cs + + + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 2.0 %28x86%29 + true + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + false + + + False + .NET Framework 3.5 SP1 + false + + + + + {BE2859E0-ED2E-4038-9B11-9E410FEA25F0} + Interfaces + + + + + \ No newline at end of file diff --git a/Tools/IPPrototyper/ipprototyper.sln b/Tools/IPPrototyper/ipprototyper.sln new file mode 100644 index 0000000000..14eb128e6 --- /dev/null +++ b/Tools/IPPrototyper/ipprototyper.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C# Express 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ipprototyper", "ipprototyper.csproj", "{257502A9-6C82-4F86-815D-2CE0FA8C0036}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Interfaces", "Interfaces\Interfaces.csproj", "{BE2859E0-ED2E-4038-9B11-9E410FEA25F0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {257502A9-6C82-4F86-815D-2CE0FA8C0036}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {257502A9-6C82-4F86-815D-2CE0FA8C0036}.Debug|Any CPU.Build.0 = Debug|Any CPU + {257502A9-6C82-4F86-815D-2CE0FA8C0036}.Release|Any CPU.ActiveCfg = Release|Any CPU + {257502A9-6C82-4F86-815D-2CE0FA8C0036}.Release|Any CPU.Build.0 = Release|Any CPU + {BE2859E0-ED2E-4038-9B11-9E410FEA25F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BE2859E0-ED2E-4038-9B11-9E410FEA25F0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE2859E0-ED2E-4038-9B11-9E410FEA25F0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BE2859E0-ED2E-4038-9B11-9E410FEA25F0}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Unit Tests/Accord.Tests.Audio/Accord.Tests.Audio.csproj b/Unit Tests/Accord.Tests.Audio/Accord.Tests.Audio.csproj index 77f6afe20..3087e8818 100644 --- a/Unit Tests/Accord.Tests.Audio/Accord.Tests.Audio.csproj +++ b/Unit Tests/Accord.Tests.Audio/Accord.Tests.Audio.csproj @@ -4,7 +4,6 @@ {19385AE1-57CA-4082-AD33-62480D02C1D9} Accord.Tests.Audio Accord.Tests.Audio - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} Debug AnyCPU Library @@ -32,29 +31,24 @@ true full false - bin\Debug\ + $(SolutionDir)..\Unit Tests\bin\Debug\ DEBUG;TRACE - bin\Release\net35 + $(SolutionDir)..\Unit Tests\bin\Release\net35\ TRACE;NET35 - bin\Release\net40 + $(SolutionDir)..\Unit Tests\bin\Release\net40\ TRACE;NET40 - bin\Release\net45 + $(SolutionDir)..\Unit Tests\bin\Release\net45\ TRACE;NET45 - - False - ..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\Externals\AForge.NET\AForge.Math.dll + + ..\..\Externals\NUnit\nunit.framework.dll ..\..\Externals\SharpDX\net40\SharpDX.dll @@ -69,20 +63,18 @@ 3.5 - - c:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll - + - - True True Resources.resx + + @@ -90,17 +82,17 @@ - + PreserveNewest - + PreserveNewest - - {EC70C2A7-2B49-40D3-AE82-4C2F6E1724AF} - Accord.Audio.Formats + + {456db2e8-745a-4f87-a2bd-c43cf8677770} + Accord.Audio.DirectSound {E7B65F08-82F1-438F-847A-2AAC2BEC9AC0} @@ -110,9 +102,9 @@ {0AB27A20-925C-4556-9FA4-6E2C109E448E} Accord.Controls - - {456DB2E8-745A-4F87-A2BD-C43CF8677770} - Accord.DirectSound + + {a177a90c-8207-466a-af70-f2b8452a42ac} + Accord.Core {F718E9A8-DB62-4785-8C49-4333A60D256A} @@ -122,8 +114,8 @@ ResXFileCodeGenerator - Resources.Designer.cs Designer + Resources.Designer.cs @@ -148,6 +140,9 @@ true + + + + + + True True Resources.resx + {A177A90C-8207-466A-AF70-F2B8452A42AC} Accord.Core - global {F718E9A8-DB62-4785-8C49-4333A60D256A} Accord.Math - - {161BD953-537D-4325-8A00-22475FC9088E} - Accord.Tests.Math.Cpp - - + + + False diff --git a/Unit Tests/Accord.Tests.Core/IntPointTest.cs b/Unit Tests/Accord.Tests.Core/IntPointTest.cs new file mode 100644 index 0000000000..2b612119d --- /dev/null +++ b/Unit Tests/Accord.Tests.Core/IntPointTest.cs @@ -0,0 +1,47 @@ +using NUnit.Framework; + +namespace AForge.Tests +{ + [TestFixture] + public class IntPointTest + { + [TestCase( 0, 0, 0 )] + [TestCase( 0, 1, 1 )] + [TestCase( 0, 10, 10 )] + [TestCase( 10, 0, 10 )] + [TestCase( 3, 4, 5 )] + [TestCase( -3, 4, 5 )] + [TestCase( 3, -4, 5 )] + [TestCase( -3, -4, 5 )] + public void EuclideanNormTest( int x, int y, double expectedNorm ) + { + IntPoint point = new IntPoint( x, y ); + + Assert.AreEqual( point.EuclideanNorm( ), expectedNorm ); + } + + [TestCase( 1, 2, 1, 2, true )] + [TestCase( 1, 2, 3, 2, false )] + [TestCase( 1, 2, 1, 4, false )] + [TestCase( 1, 2, 3, 4, false )] + public void EqualityOperatorTest( int x1, int y1, int x2, int y2, bool areEqual ) + { + IntPoint point1 = new IntPoint( x1, y1 ); + IntPoint point2 = new IntPoint( x2, y2 ); + + Assert.AreEqual( point1 == point2, areEqual ); + } + + [TestCase( 1, 2, 1, 2, false )] + [TestCase( 1, 2, 3, 2, true )] + [TestCase( 1, 2, 1, 4, true )] + [TestCase( 1, 2, 3, 4, true )] + public void InequalityOperatorTest( int x1, int y1, int x2, int y2, bool areNotEqual ) + { + IntPoint point1 = new IntPoint( x1, y1 ); + IntPoint point2 = new IntPoint( x2, y2 ); + + Assert.AreEqual( point1 != point2, areNotEqual ); + } + } +} diff --git a/Unit Tests/Accord.Tests.Core/IntRangeTest.cs b/Unit Tests/Accord.Tests.Core/IntRangeTest.cs new file mode 100644 index 0000000000..1fa23d181 --- /dev/null +++ b/Unit Tests/Accord.Tests.Core/IntRangeTest.cs @@ -0,0 +1,50 @@ +using NUnit.Framework; + +namespace AForge.Tests +{ + [TestFixture] + public class IntRangeTest + { + [TestCase( 0, 1, 1, 2, true )] + [TestCase( 0, 1, 2, 3, false )] + [TestCase( 0, 10, 2, 4, true )] + [TestCase( 0, 10, 5, 15, true )] + [TestCase( 0, 10, -5, 5, true )] + [TestCase( 2, 4, 0, 10, true )] + [TestCase( 5, 15, 0, 10, true )] + [TestCase( -5, 5, 0, 10, true )] + public void IsOverlappingTest( int min1, int max1, int min2, int max2, bool expectedResult ) + { + IntRange range1 = new IntRange( min1, max1 ); + IntRange range2 = new IntRange( min2, max2 ); + + Assert.AreEqual( expectedResult, range1.IsOverlapping( range2 ) ); + } + + [TestCase( 0, 1, 0, 1 )] + [TestCase( -1, 0, -1, 0 )] + public void ToRangeTest( int iMin, int iMax, float fMin, float fMax ) + { + IntRange iRange = new IntRange( iMin, iMax ); + Range range = iRange; + + Assert.AreEqual( fMin, range.Min ); + Assert.AreEqual( fMax, range.Max ); + } + + [TestCase( 1, 2, 1, 2, true )] + [TestCase( -2, -1, -2, -1, true )] + [TestCase( 1, 2, 2, 3, false )] + [TestCase( 1, 2, 1, 4, false )] + [TestCase( 1, 2, 3, 4, false )] + public void EqualityOperatorTest( int min1, int max1, int min2, int max2, bool areEqual ) + { + IntRange range1 = new IntRange( min1, max1 ); + IntRange range2 = new IntRange( min2, max2 ); + + Assert.AreEqual( range1.Equals( range2 ), areEqual ); + Assert.AreEqual( range1 == range2, areEqual ); + Assert.AreEqual( range1 != range2, !areEqual ); + } + } +} diff --git a/Unit Tests/Accord.Tests.Core/PointTest.cs b/Unit Tests/Accord.Tests.Core/PointTest.cs new file mode 100644 index 0000000000..22f68ef3a --- /dev/null +++ b/Unit Tests/Accord.Tests.Core/PointTest.cs @@ -0,0 +1,64 @@ +using NUnit.Framework; + +namespace AForge.Tests +{ + [TestFixture] + public class PointTest + { + [TestCase( 0, 0, 0 )] + [TestCase( 0, 1, 1 )] + [TestCase( 0, 10, 10 )] + [TestCase( 10, 0, 10 )] + [TestCase( 3, 4, 5 )] + [TestCase( -3, 4, 5 )] + [TestCase( 3, -4, 5 )] + [TestCase( -3, -4, 5 )] + [TestCase( 0.3f, 0.4f, 0.5f )] + public void EuclideanNormTest( float x, float y, float expectedNorm ) + { + Point point = new Point( x, y ); + + Assert.AreEqual( point.EuclideanNorm( ), expectedNorm ); + } + + [TestCase( 0, 0, 0, 0 )] + [TestCase( 1, 2, 1, 2 )] + [TestCase( -1, -2, -1, -2 )] + [TestCase( 1.4f, 3.3f, 1, 3 )] + [TestCase( 1.6f, 3.7f, 2, 4 )] + [TestCase( -1.6f, -3.3f, -2, -3 )] + [TestCase( -1.5f, 1.5f, -2, 2 )] + [TestCase( -2.5f, 2.5f, -2, 2 )] + public void RoundTest( float x, float y, int expectedX, int expectedY ) + { + Point point = new Point( x, y ); + IntPoint iPoint = new IntPoint( expectedX, expectedY ); + + Assert.AreEqual( iPoint, point.Round( ) ); + } + + [TestCase( 1.1f, 2.2f, 1.1f, 2.2f, true )] + [TestCase( 1.1f, 2.2f, 3.3f, 2.2f, false )] + [TestCase( 1.1f, 2.2f, 1.1f, 4.4f, false )] + [TestCase( 1.1f, 2.2f, 3.3f, 4.4f, false )] + public void EqualityOperatorTest( float x1, float y1, float x2, float y2, bool areEqual ) + { + Point point1 = new Point( x1, y1 ); + Point point2 = new Point( x2, y2 ); + + Assert.AreEqual( point1 == point2, areEqual ); + } + + [TestCase( 1.1f, 2.2f, 1.1f, 2.2f, false )] + [TestCase( 1.1f, 2.2f, 3.3f, 2.2f, true )] + [TestCase( 1.1f, 2.2f, 1.1f, 4.4f, true )] + [TestCase( 1.1f, 2.2f, 3.3f, 4.4f, true )] + public void InequalityOperatorTest( float x1, float y1, float x2, float y2, bool areNotEqual ) + { + Point point1 = new Point( x1, y1 ); + Point point2 = new Point( x2, y2 ); + + Assert.AreEqual( point1 != point2, areNotEqual ); + } + } +} diff --git a/Unit Tests/Accord.Tests.Core/RangeTest.cs b/Unit Tests/Accord.Tests.Core/RangeTest.cs new file mode 100644 index 0000000000..9a8d24407 --- /dev/null +++ b/Unit Tests/Accord.Tests.Core/RangeTest.cs @@ -0,0 +1,52 @@ +using NUnit.Framework; + +namespace AForge.Tests +{ + [TestFixture] + public class RangeTest + { + [TestCase( 0, 1, 1, 2, true )] + [TestCase( 0, 1, 2, 3, false )] + [TestCase( 0, 10, 2, 4, true )] + [TestCase( 0, 10, 5, 15, true )] + [TestCase( 0, 10, -5, 5, true )] + [TestCase( 2, 4, 0, 10, true )] + [TestCase( 5, 15, 0, 10, true )] + [TestCase( -5, 5, 0, 10, true )] + public void IsOverlappingTest( float min1, float max1, float min2, float max2, bool expectedResult ) + { + Range range1 = new Range( min1, max1 ); + Range range2 = new Range( min2, max2 ); + + Assert.AreEqual( expectedResult, range1.IsOverlapping( range2 ) ); + } + + [TestCase( 0.4f, 7.3f, 1, 7, true )] + [TestCase( -6.6f, -0.1f, -6, -1, true )] + [TestCase( 0.4f, 7.3f, 0, 8, false )] + [TestCase( -6.6f, -0.1f, -7, 0, false )] + public void ToRangeTest( float fMin, float fMax, int iMin, int iMax, bool innerRange ) + { + Range range = new Range( fMin, fMax ); + IntRange iRange = range.ToIntRange( innerRange ); + + Assert.AreEqual( iMin, iRange.Min ); + Assert.AreEqual( iMax, iRange.Max ); + } + + [TestCase( 1.1f, 2.2f, 1.1f, 2.2f, true )] + [TestCase( -2.2f, -1.1f, -2.2f, -1.1f, true )] + [TestCase( 1.1f, 2.2f, 2.2f, 3.3f, false )] + [TestCase( 1.1f, 2.2f, 1.1f, 4.4f, false )] + [TestCase( 1.1f, 2.2f, 3.3f, 4.4f, false )] + public void EqualityOperatorTest( float min1, float max1, float min2, float max2, bool areEqual ) + { + Range range1 = new Range( min1, max1 ); + Range range2 = new Range( min2, max2 ); + + Assert.AreEqual( range1.Equals( range2 ), areEqual ); + Assert.AreEqual( range1 == range2, areEqual ); + Assert.AreEqual( range1 != range2, !areEqual ); + } + } +} diff --git a/Unit Tests/Accord.Tests.IO/Accord.Tests.IO.csproj b/Unit Tests/Accord.Tests.IO/Accord.Tests.IO.csproj index e3168ae7b..8e759f440 100644 --- a/Unit Tests/Accord.Tests.IO/Accord.Tests.IO.csproj +++ b/Unit Tests/Accord.Tests.IO/Accord.Tests.IO.csproj @@ -4,7 +4,6 @@ {2562C6B4-088E-48AC-B408-15BC99AE6760} Accord.Tests.IO Accord.Tests.IO - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} Debug AnyCPU Library @@ -32,31 +31,31 @@ true full false - bin\Debug\ + $(SolutionDir)..\Unit Tests\bin\Debug\ DEBUG;TRACE - bin\Release\net35 + $(SolutionDir)..\Unit Tests\bin\Release\net35\ TRACE;NET35 - bin\Release\net40 + $(SolutionDir)..\Unit Tests\bin\Release\net40\ TRACE;NET40 - bin\Release\net45 + $(SolutionDir)..\Unit Tests\bin\Release\net45\ TRACE;NET45 + + ..\..\Externals\NUnit\nunit.framework.dll + 3.5 - - c:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll - + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets + + + $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets + + + + + + + + + + + True + + + ..\..\Externals\NUnit\nunit.framework.dll + + + + + + + Accord.Core + {a177a90c-8207-466a-af70-f2b8452a42ac} + True + + + Accord.MachineLearning + {7ab4bbcc-6222-423d-9ff9-ba9cb7c09199} + True + + + Accord.Math + {f718e9a8-db62-4785-8c49-4333a60d256a} + True + + + + \ No newline at end of file diff --git a/Unit Tests/Accord.Tests.Math.FSharp/Accord.snk b/Unit Tests/Accord.Tests.Math.FSharp/Accord.snk new file mode 100644 index 0000000000..ed97b4edd Binary files /dev/null and b/Unit Tests/Accord.Tests.Math.FSharp/Accord.snk differ diff --git a/Unit Tests/Accord.Tests.Math.FSharp/AssemblyInfo.fs b/Unit Tests/Accord.Tests.Math.FSharp/AssemblyInfo.fs new file mode 100644 index 0000000000..fdbd90321 --- /dev/null +++ b/Unit Tests/Accord.Tests.Math.FSharp/AssemblyInfo.fs @@ -0,0 +1,9 @@ +module AssemblyProperties + +open System +open System.Reflection; +open System.Runtime.InteropServices; + +[] + +do() \ No newline at end of file diff --git a/Unit Tests/Accord.Tests.Math.FSharp/CobylaTest.fs b/Unit Tests/Accord.Tests.Math.FSharp/CobylaTest.fs new file mode 100644 index 0000000000..c78d46516 --- /dev/null +++ b/Unit Tests/Accord.Tests.Math.FSharp/CobylaTest.fs @@ -0,0 +1,35 @@ +namespace Accord.Tests.MachineLearning + +open System +open System.IO +open System.Collections.Generic + +open Accord +open Accord.Math +open Accord.Math.Optimization + +open NUnit.Framework + + +type CobylaTest() = + + + [] + member x.InconsistentConstraintsTest() = + + let obj12 = QuadraticObjectiveFunction("a - a*a"); + let c12 = QuadraticConstraint(obj12, Array2D.zeroCreate 1 1, [| 10.0 |], ConstraintType.LesserThanOrEqualTo, 4.0) + let c13 = QuadraticConstraint(obj12, Array2D.zeroCreate 1 1, [| 10.0 |], ConstraintType.GreaterThanOrEqualTo, 45.0) + + let p1 = List() + p1.Add(c12) + p1.Add(c13) + let solver1 = Cobyla(obj12, p1) + let success = solver1.Maximize() + let value = solver1.Value + let solution = solver1.Solution + let r = solver1.Status + + Assert.IsFalse(success) + Assert.AreEqual(r, CobylaStatus.NoPossibleSolution) + diff --git a/Unit Tests/Accord.Tests.Math.Interop/Accord.Tests.Math.Interop.csproj b/Unit Tests/Accord.Tests.Math.Interop/Accord.Tests.Math.Interop.csproj new file mode 100644 index 0000000000..cbd16db04 --- /dev/null +++ b/Unit Tests/Accord.Tests.Math.Interop/Accord.Tests.Math.Interop.csproj @@ -0,0 +1,146 @@ + + + + {F5820249-C973-4EF3-91B3-4B46F2961816} + Accord.Tests.Math + Accord.Tests.Math + Debug + AnyCPU + v4.5 + Library + Properties + 512 + 3.5 + true + 0 + 1.0.0.%2a + false + true + + true + true + pdbonly + AnyCPU + prompt + 4 + true + true + Accord.snk + x86 + + + true + full + false + $(SolutionDir)..\Unit Tests\bin\Debug\ + DEBUG;TRACE + + + $(SolutionDir)..\Unit Tests\bin\Release\net35\ + TRACE;NET35 + + + $(SolutionDir)..\Unit Tests\bin\Release\net40\ + TRACE;NET40 + + + $(SolutionDir)..\Unit Tests\bin\Release\net45\ + TRACE;NET45 + + + + ..\..\Externals\NUnit\nunit.framework.dll + + + + 3.5 + + + + + + + + + + + + + + + + True + True + Resources.resx + + + + + + + {A177A90C-8207-466A-AF70-F2B8452A42AC} + Accord.Core + + + {F718E9A8-DB62-4785-8C49-4333A60D256A} + Accord.Math + + + {161bd953-537d-4325-8a00-22475fc9088e} + Accord.Tests.Math.Cpp + + + + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + + + \ No newline at end of file diff --git a/Unit Tests/Accord.Tests.Math.Interop/Accord.snk b/Unit Tests/Accord.Tests.Math.Interop/Accord.snk new file mode 100644 index 0000000000..ed97b4edd Binary files /dev/null and b/Unit Tests/Accord.Tests.Math.Interop/Accord.snk differ diff --git a/Unit Tests/Accord.Tests.Math.Interop/BoundedBroydenFletcherGoldfarbShannoTest.cs b/Unit Tests/Accord.Tests.Math.Interop/BoundedBroydenFletcherGoldfarbShannoTest.cs new file mode 100644 index 0000000000..e69bcfe6a --- /dev/null +++ b/Unit Tests/Accord.Tests.Math.Interop/BoundedBroydenFletcherGoldfarbShannoTest.cs @@ -0,0 +1,62 @@ +// Accord Unit Tests +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Tests.Math +{ + using Accord.Math.Optimization; + using AccordTestsMathCpp2; + using NUnit.Framework; + using System; + + [TestFixture] + public class BoundedBroydenFletcherGoldfarbShannoTest + { + + [Test] + public void ConstructorTest2() + { + Function function = // min f(x) = 10 * (x+1)^2 + y^2 + x => 10.0 * Math.Pow(x[0] + 1.0, 2.0) + Math.Pow(x[1], 2.0); + + Gradient gradient = x => new[] { 20 * (x[0] + 1), 2 * x[1] }; + + + double[] start = new double[2]; + + var target = new BoundedBroydenFletcherGoldfarbShanno(2, + function.Invoke, gradient.Invoke); + + Assert.IsTrue(target.Minimize()); + double minimum = target.Value; + + double[] solution = target.Solution; + + Assert.AreEqual(0, minimum, 1e-10); + Assert.AreEqual(-1, solution[0], 1e-5); + Assert.AreEqual(0, solution[1], 1e-5); + + double expectedMinimum = function(target.Solution); + Assert.AreEqual(expectedMinimum, minimum); + } + + } +} diff --git a/Unit Tests/Accord.Tests.Math.Interop/BroydenFletcherGoldfarbShannoTest.cs b/Unit Tests/Accord.Tests.Math.Interop/BroydenFletcherGoldfarbShannoTest.cs new file mode 100644 index 0000000000..159d166da --- /dev/null +++ b/Unit Tests/Accord.Tests.Math.Interop/BroydenFletcherGoldfarbShannoTest.cs @@ -0,0 +1,62 @@ +// Accord Unit Tests +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Tests.Math +{ + using Accord.Math.Optimization; + using AccordTestsMathCpp2; + using NUnit.Framework; + using System; + + [TestFixture] + public class BroydenFletcherGoldfarbShannoTest + { + + [Test] + public void ConstructorTest2() + { + Function function = // min f(x) = 10 * (x+1)^2 + y^2 + x => 10.0 * Math.Pow(x[0] + 1.0, 2.0) + Math.Pow(x[1], 2.0); + + Gradient gradient = x => new[] { 20 * (x[0] + 1), 2 * x[1] }; + + + double[] start = new double[2]; + + BroydenFletcherGoldfarbShanno target = new BroydenFletcherGoldfarbShanno(2, + function.Invoke, gradient.Invoke); + + Assert.IsTrue(target.Minimize()); + double minimum = target.Value; + + double[] solution = target.Solution; + + Assert.AreEqual(0, minimum, 1e-10); + Assert.AreEqual(-1, solution[0], 1e-5); + Assert.AreEqual(0, solution[1], 1e-5); + + double expectedMinimum = function(target.Solution); + Assert.AreEqual(expectedMinimum, minimum); + } + + } +} diff --git a/Unit Tests/Accord.Tests.Math/Optimization/Quadprog/QuadprogComparisonTest.cs b/Unit Tests/Accord.Tests.Math.Interop/IntegralTest.cs similarity index 56% rename from Unit Tests/Accord.Tests.Math/Optimization/Quadprog/QuadprogComparisonTest.cs rename to Unit Tests/Accord.Tests.Math.Interop/IntegralTest.cs index 6df4137a4..9fc148e57 100644 --- a/Unit Tests/Accord.Tests.Math/Optimization/Quadprog/QuadprogComparisonTest.cs +++ b/Unit Tests/Accord.Tests.Math.Interop/IntegralTest.cs @@ -1,55 +1,57 @@ -// Accord Unit Tests -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Tests.Math -{ - using Accord.Math.Optimization; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using System; - using AccordTestsMathCpp2; - using System.Collections.Generic; - using Accord.Tests.Math.Optimization; - using AForge; - using Accord.Math; - - [TestClass()] - public class QuadprogComparisonTest - { - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - - - } -} +// Accord Unit Tests +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Tests.Math +{ + using Accord.Math; + using Accord.Math.Integration; + using AccordTestsMathCpp2; + using NUnit.Framework; + using System; + + [TestFixture] + public class IntegralTest + { + + [Test] + public void InfiniteGaussKronrodTest() + { + for (int i = -10; i < 10; i++) + { + Func pdf = (x) => Normal.Derivative(x - i); + + Func E = (x) => x * pdf(x); + UFunction UE = (x) => x * pdf(x); + + double expected = Quadpack.Integrate(UE, + Double.NegativeInfinity, Double.PositiveInfinity); + + double actual = InfiniteAdaptiveGaussKronrod.Integrate(E, + Double.NegativeInfinity, Double.PositiveInfinity); + + Assert.AreEqual(expected, actual, 1e-3); + Assert.AreEqual(i, actual, 1e-3); + } + } + + } +} diff --git a/Unit Tests/Accord.Tests.Math/Optimization/Lbfgsb3/LbfgsbComparer.cs b/Unit Tests/Accord.Tests.Math.Interop/Lbfgsb3/LbfgsbComparer.cs similarity index 73% rename from Unit Tests/Accord.Tests.Math/Optimization/Lbfgsb3/LbfgsbComparer.cs rename to Unit Tests/Accord.Tests.Math.Interop/Lbfgsb3/LbfgsbComparer.cs index c107a4024..37836abac 100644 --- a/Unit Tests/Accord.Tests.Math/Optimization/Lbfgsb3/LbfgsbComparer.cs +++ b/Unit Tests/Accord.Tests.Math.Interop/Lbfgsb3/LbfgsbComparer.cs @@ -1,111 +1,131 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using AccordTestsMathCpp2; -using Accord.Math.Optimization; - -namespace Accord.Tests.Math.Optimization -{ - public class LbfgsbComparer - { - private List actual; - - public double factr; - public double[] l; - public double[] u; - public double pgtol; - public int m = 5; - public int max_iterations; - - public string ActualMessage; - - public LbfgsbComparer() - { - actual = new List(); - } - - public Info[] Expected(Specification problem) - { - NativeCode = String.Empty; - - Function function = problem.Function.Invoke; - Gradient gradient = problem.Gradient.Invoke; - - if (l == null) - { - l = new double[problem.Start.Length]; - for (int i = 0; i < l.Length; i++) - l[i] = Double.NegativeInfinity; - } - - if (u == null) - { - u = new double[problem.Start.Length]; - for (int i = 0; i < l.Length; i++) - u[i] = Double.PositiveInfinity; - } - - Param2 param = new Param2() - { - factr = factr, - l = l, - u = u, - pgtol = pgtol, - m = m, - max_iterations = max_iterations - }; - - NativeCode = Wrapper.Lbfgsb3((double[])problem.Start.Clone(), function, gradient, param).Trim(); - - return Wrapper.list.ToArray(); - } - - public string NativeCode { get; private set; } - - public OptimizationProgressEventArgs[] Actual(Specification problem) - { - ActualMessage = String.Empty; - - BoundedBroydenFletcherGoldfarbShanno target = - new BoundedBroydenFletcherGoldfarbShanno(problem.Variables) - { - FunctionTolerance = factr, - GradientTolerance = pgtol, - Corrections = m, - MaxIterations = max_iterations - }; - - for (int i = 0; i < target.LowerBounds.Length; i++) - { - if (l != null) - target.LowerBounds[i] = l[i]; - if (u != null) - target.UpperBounds[i] = u[i]; - } - - - target.Function = problem.Function; - target.Gradient = problem.Gradient; - - actual.Clear(); - target.Progress += new EventHandler(target_Progress); - - target.Minimize((double[])problem.Start.Clone()); - - if (target.Status == BoundedBroydenFletcherGoldfarbShannoStatus.GradientConvergence) - ActualMessage = "CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PGTOL"; - else if (target.Status == BoundedBroydenFletcherGoldfarbShannoStatus.FunctionConvergence) - ActualMessage = "CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH"; - else if (target.Status == BoundedBroydenFletcherGoldfarbShannoStatus.LineSearchFailed) - ActualMessage = "ABNORMAL_TERMINATION_IN_LNSRCH"; - - return actual.ToArray(); - } - - void target_Progress(object sender, OptimizationProgressEventArgs e) - { - actual.Add(e); - } - } -} +// Accord Unit Tests +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Tests.Math.Optimization +{ + using Accord.Math.Optimization; + using AccordTestsMathCpp2; + using System; + using System.Collections.Generic; + + public class LbfgsbComparer + { + private List actual; + + public double factr; + public double[] l; + public double[] u; + public double pgtol; + public int m = 5; + public int max_iterations; + + public string ActualMessage; + + public LbfgsbComparer() + { + actual = new List(); + } + + public Info[] Expected(Specification problem) + { + NativeCode = String.Empty; + + Function function = problem.Function.Invoke; + Gradient gradient = problem.Gradient.Invoke; + + if (l == null) + { + l = new double[problem.Start.Length]; + for (int i = 0; i < l.Length; i++) + l[i] = Double.NegativeInfinity; + } + + if (u == null) + { + u = new double[problem.Start.Length]; + for (int i = 0; i < l.Length; i++) + u[i] = Double.PositiveInfinity; + } + + Param2 param = new Param2() + { + factr = factr, + l = l, + u = u, + pgtol = pgtol, + m = m, + max_iterations = max_iterations + }; + + NativeCode = Wrapper.Lbfgsb3((double[])problem.Start.Clone(), function, gradient, param).Trim(); + + return Wrapper.list.ToArray(); + } + + public string NativeCode { get; private set; } + + public OptimizationProgressEventArgs[] Actual(Specification problem) + { + ActualMessage = String.Empty; + + BoundedBroydenFletcherGoldfarbShanno target = + new BoundedBroydenFletcherGoldfarbShanno(problem.Variables) + { + FunctionTolerance = factr, + GradientTolerance = pgtol, + Corrections = m, + MaxIterations = max_iterations + }; + + for (int i = 0; i < target.LowerBounds.Length; i++) + { + if (l != null) + target.LowerBounds[i] = l[i]; + if (u != null) + target.UpperBounds[i] = u[i]; + } + + + target.Function = problem.Function; + target.Gradient = problem.Gradient; + + actual.Clear(); + target.Progress += new EventHandler(target_Progress); + + target.Minimize((double[])problem.Start.Clone()); + + if (target.Status == BoundedBroydenFletcherGoldfarbShannoStatus.GradientConvergence) + ActualMessage = "CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PGTOL"; + else if (target.Status == BoundedBroydenFletcherGoldfarbShannoStatus.FunctionConvergence) + ActualMessage = "CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH"; + else if (target.Status == BoundedBroydenFletcherGoldfarbShannoStatus.LineSearchFailed) + ActualMessage = "ABNORMAL_TERMINATION_IN_LNSRCH"; + + return actual.ToArray(); + } + + void target_Progress(object sender, OptimizationProgressEventArgs e) + { + actual.Add(e); + } + } +} diff --git a/Unit Tests/Accord.Tests.Math/Optimization/Lbfgsb3/LbfgsbComparisonTest.cs b/Unit Tests/Accord.Tests.Math.Interop/Lbfgsb3/LbfgsbComparisonTest.cs similarity index 91% rename from Unit Tests/Accord.Tests.Math/Optimization/Lbfgsb3/LbfgsbComparisonTest.cs rename to Unit Tests/Accord.Tests.Math.Interop/Lbfgsb3/LbfgsbComparisonTest.cs index 341b7a86d..0ab5ec632 100644 --- a/Unit Tests/Accord.Tests.Math/Optimization/Lbfgsb3/LbfgsbComparisonTest.cs +++ b/Unit Tests/Accord.Tests.Math.Interop/Lbfgsb3/LbfgsbComparisonTest.cs @@ -23,30 +23,16 @@ namespace Accord.Tests.Math { using Accord.Math.Optimization; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using System; + using Accord.Tests.Math.Optimization; using AccordTestsMathCpp2; + using NUnit.Framework; + using System; using System.Collections.Generic; - using Accord.Tests.Math.Optimization; - using AForge; - [TestClass()] + [TestFixture] public class LbfgsbComparisonTest { private List problems; - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } public LbfgsbComparisonTest() { @@ -94,7 +80,7 @@ public LbfgsbComparisonTest() problems = list; } - [TestMethod()] + [Test] public void DefaultBatchTest() { foreach (var problem in problems) @@ -108,7 +94,7 @@ public void DefaultBatchTest() } } - [TestMethod()] + [Test] public void ParameterTest1() { LbfgsbComparer cmp = new LbfgsbComparer() @@ -124,7 +110,7 @@ public void ParameterTest1() } - [TestMethod()] + [Test] public void ParameterRangeTest() { LbfgsbComparer[] tests = @@ -231,7 +217,7 @@ private static void check(OptimizationProgressEventArgs[] actual, Info[] expecte } } - [TestMethod()] + [Test] public void InvalidLineSearchTest() { double t = 0; @@ -266,7 +252,7 @@ public void InvalidLineSearchTest() compute(new List() { problem }, cmp); } - [TestMethod()] + [Test] public void InvalidLineSearchTest2() { int n = 10; diff --git a/Unit Tests/Accord.Tests.Math/Optimization/LibBFGS/LBFGSComparer.cs b/Unit Tests/Accord.Tests.Math.Interop/LibBFGS/LBFGSComparer.cs similarity index 77% rename from Unit Tests/Accord.Tests.Math/Optimization/LibBFGS/LBFGSComparer.cs rename to Unit Tests/Accord.Tests.Math.Interop/LibBFGS/LBFGSComparer.cs index c2263a050..ee5aaefe7 100644 --- a/Unit Tests/Accord.Tests.Math/Optimization/LibBFGS/LBFGSComparer.cs +++ b/Unit Tests/Accord.Tests.Math.Interop/LibBFGS/LBFGSComparer.cs @@ -1,136 +1,156 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using AccordTestsMathCpp2; -using Accord.Math.Optimization; - -namespace Accord.Tests.Math.Optimization -{ - public class Specification - { - public Specification(int n, Func function, - Func gradient, double[] start) - { - this.Variables = n; - this.Function = function; - this.Gradient = gradient; - this.Start = start; - - if (start == null) - this.Start = new double[n]; - } - - public int Variables; - public Func Function; - public Func Gradient; - public double[] Start; - } - - public class LBFGSComparer - { - private List actual; - - public int m = 6; - public double epsilon = 1e-5; - public int past = 0; - public double delta = 1e-5; - public int max_iterations = 0; - public LineSearch linesearch = LineSearch.Default; - public int max_linesearch = 40; - public double min_step = 1e-20; - public double max_step = 1e20; - public double ftol = 1e-4; - public double wolfe = 0.9; - public double gtol = 0.9; - public double xtol = 1.0e-16; - public double orthantwise_c = 0; - public int orthantwise_start = 0; - public int orthantwise_end = -1; - - public string ActualMessage; - - public LBFGSComparer() - { - actual = new List(); - } - - public Info[] Expected(Specification problem) - { - Function function = problem.Function.Invoke; - Gradient gradient = problem.Gradient.Invoke; - - Param param = new Param() - { - m = m, - epsilon = epsilon, - past = past, - delta = delta, - max_iterations = max_iterations, - linesearch = (int)linesearch, - max_linesearch = max_linesearch, - min_step = min_step, - max_step = max_step, - ftol = ftol, - wolfe = wolfe, - gtol = gtol, - xtol = xtol, - orthantwise_c = orthantwise_c, - orthantwise_start = orthantwise_start, - orthantwise_end = orthantwise_end - }; - - NativeCode = Wrapper.Libbfgs((double[])problem.Start.Clone(), function, gradient, param); - - // Convergence and success have the same - // enumeration value in the original code - if (NativeCode == "LBFGS_CONVERGENCE") - NativeCode = "LBFGS_SUCCESS"; - - return Wrapper.list.ToArray(); - } - - public string NativeCode { get; private set; } - - public OptimizationProgressEventArgs[] Actual(Specification problem) - { - BroydenFletcherGoldfarbShanno target = new BroydenFletcherGoldfarbShanno(problem.Variables) - { - Corrections = m, - Epsilon = epsilon, - Past = past, - Delta = delta, - MaxIterations = max_iterations, - LineSearch = (LineSearch)linesearch, - MaxLineSearch = max_linesearch, - MinStep = min_step, - MaxStep = max_step, - ParameterTolerance = ftol, - Wolfe = wolfe, - GradientTolerance = gtol, - FunctionTolerance = xtol, - OrthantwiseC = orthantwise_c, - OrthantwiseStart = orthantwise_start, - OrthantwiseEnd = orthantwise_end - }; - - target.Function = problem.Function; - target.Gradient = problem.Gradient; - - actual.Clear(); - target.Progress += new EventHandler(target_Progress); - - target.Minimize((double[])problem.Start.Clone()); - - ActualMessage = target.Status.GetDescription(); - - - return actual.ToArray(); - } - - void target_Progress(object sender, OptimizationProgressEventArgs e) - { - actual.Add(e); - } - } -} +// Accord Unit Tests +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Tests.Math.Optimization +{ + using Accord.Math.Optimization; + using AccordTestsMathCpp2; + using System; + using System.Collections.Generic; + + public class Specification + { + public Specification(int n, Func function, + Func gradient, double[] start) + { + this.Variables = n; + this.Function = function; + this.Gradient = gradient; + this.Start = start; + + if (start == null) + this.Start = new double[n]; + } + + public int Variables; + public Func Function; + public Func Gradient; + public double[] Start; + } + + public class LBFGSComparer + { + private List actual; + + public int m = 6; + public double epsilon = 1e-5; + public int past = 0; + public double delta = 1e-5; + public int max_iterations = 0; + public LineSearch linesearch = LineSearch.Default; + public int max_linesearch = 40; + public double min_step = 1e-20; + public double max_step = 1e20; + public double ftol = 1e-4; + public double wolfe = 0.9; + public double gtol = 0.9; + public double xtol = 1.0e-16; + public double orthantwise_c = 0; + public int orthantwise_start = 0; + public int orthantwise_end = -1; + + public string ActualMessage; + + public LBFGSComparer() + { + actual = new List(); + } + + public Info[] Expected(Specification problem) + { + Function function = problem.Function.Invoke; + Gradient gradient = problem.Gradient.Invoke; + + Param param = new Param() + { + m = m, + epsilon = epsilon, + past = past, + delta = delta, + max_iterations = max_iterations, + linesearch = (int)linesearch, + max_linesearch = max_linesearch, + min_step = min_step, + max_step = max_step, + ftol = ftol, + wolfe = wolfe, + gtol = gtol, + xtol = xtol, + orthantwise_c = orthantwise_c, + orthantwise_start = orthantwise_start, + orthantwise_end = orthantwise_end + }; + + NativeCode = Wrapper.Libbfgs((double[])problem.Start.Clone(), function, gradient, param); + + // Convergence and success have the same + // enumeration value in the original code + if (NativeCode == "LBFGS_CONVERGENCE") + NativeCode = "LBFGS_SUCCESS"; + + return Wrapper.list.ToArray(); + } + + public string NativeCode { get; private set; } + + public OptimizationProgressEventArgs[] Actual(Specification problem) + { + BroydenFletcherGoldfarbShanno target = new BroydenFletcherGoldfarbShanno(problem.Variables) + { + Corrections = m, + Epsilon = epsilon, + Past = past, + Delta = delta, + MaxIterations = max_iterations, + LineSearch = (LineSearch)linesearch, + MaxLineSearch = max_linesearch, + MinStep = min_step, + MaxStep = max_step, + ParameterTolerance = ftol, + Wolfe = wolfe, + GradientTolerance = gtol, + FunctionTolerance = xtol, + OrthantwiseC = orthantwise_c, + OrthantwiseStart = orthantwise_start, + OrthantwiseEnd = orthantwise_end + }; + + target.Function = problem.Function; + target.Gradient = problem.Gradient; + + actual.Clear(); + target.Progress += new EventHandler(target_Progress); + + target.Minimize((double[])problem.Start.Clone()); + + ActualMessage = target.Status.GetDescription(); + + + return actual.ToArray(); + } + + void target_Progress(object sender, OptimizationProgressEventArgs e) + { + actual.Add(e); + } + } +} diff --git a/Unit Tests/Accord.Tests.Math/Optimization/LibBFGS/LibBFGSComparisonTest.cs b/Unit Tests/Accord.Tests.Math.Interop/LibBFGS/LibBFGSComparisonTest.cs similarity index 95% rename from Unit Tests/Accord.Tests.Math/Optimization/LibBFGS/LibBFGSComparisonTest.cs rename to Unit Tests/Accord.Tests.Math.Interop/LibBFGS/LibBFGSComparisonTest.cs index 23660d10c..8f75c82fe 100644 --- a/Unit Tests/Accord.Tests.Math/Optimization/LibBFGS/LibBFGSComparisonTest.cs +++ b/Unit Tests/Accord.Tests.Math.Interop/LibBFGS/LibBFGSComparisonTest.cs @@ -21,32 +21,17 @@ // namespace Accord.Tests.Math -{ - using Accord.Math.Optimization; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using System; - using AccordTestsMathCpp2; - using System.Collections.Generic; - using Accord.Tests.Math.Optimization; - using AForge; - - [TestClass()] +{ + using Accord.Math.Optimization; + using Accord.Tests.Math.Optimization; + using NUnit.Framework; + using System; + using System.Collections.Generic; + + [TestFixture] public class LibBFGSComparisonTest { private List problems; - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } public LibBFGSComparisonTest() { @@ -94,7 +79,7 @@ public LibBFGSComparisonTest() problems = list; } - [TestMethod()] + [Test] public void DefaultBatchTest() { foreach (var problem in problems) @@ -120,7 +105,7 @@ public void DefaultBatchTest() } } - [TestMethod()] + [Test] public void ParameterTest1() { LBFGSComparer cmp = new LBFGSComparer() @@ -143,7 +128,7 @@ public void ParameterTest1() compute(problems, cmp); } - [TestMethod()] + [Test] public void ParameterBatchTest() { for (var past = 0; past < 10; past += 3) @@ -153,7 +138,7 @@ public void ParameterBatchTest() } - [TestMethod()] + [Test] public void ParameterBatchTest2() { for (var m = 2; m < 10; m++) @@ -206,7 +191,7 @@ private static void inner(List problems, int m, } - [TestMethod()] + [Test] public void ParameterRangeTest() { LBFGSComparer[] tests = @@ -319,7 +304,7 @@ private static void compute(List problems, LBFGSComparer cmp) } } - [TestMethod()] + [Test] public void InvalidLineSearchTest() { double t = 0; @@ -354,7 +339,7 @@ public void InvalidLineSearchTest() compute(new List() { problem }, cmp); } - [TestMethod()] + [Test] public void InvalidLineSearchTest2() { int n = 10; diff --git a/Unit Tests/Accord.Tests.Math.Interop/Properties/AssemblyInfo.cs b/Unit Tests/Accord.Tests.Math.Interop/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..0ce2a94cd --- /dev/null +++ b/Unit Tests/Accord.Tests.Math.Interop/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Accord.Tests.Math")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("effcebe0-5b09-4a1f-8f74-31446fd46095")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Unit Tests/Accord.Tests.Math.Interop/Properties/Resources.Designer.cs b/Unit Tests/Accord.Tests.Math.Interop/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..79b3b1b86 --- /dev/null +++ b/Unit Tests/Accord.Tests.Math.Interop/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Accord.Tests.Math.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Accord.Tests.Math.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Unit Tests/Accord.Tests.Math.Interop/Properties/Resources.resx b/Unit Tests/Accord.Tests.Math.Interop/Properties/Resources.resx new file mode 100644 index 0000000000..7c0911ec1 --- /dev/null +++ b/Unit Tests/Accord.Tests.Math.Interop/Properties/Resources.resx @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + \ No newline at end of file diff --git a/Unit Tests/Accord.Tests.Math/Optimization/Quadprog/UnsafeGoldfarbIdnani.cs b/Unit Tests/Accord.Tests.Math.Interop/Quadprog/UnsafeGoldfarbIdnani.cs similarity index 100% rename from Unit Tests/Accord.Tests.Math/Optimization/Quadprog/UnsafeGoldfarbIdnani.cs rename to Unit Tests/Accord.Tests.Math.Interop/Quadprog/UnsafeGoldfarbIdnani.cs diff --git a/Unit Tests/Accord.Tests.Math/AForge/Geometry/ClosePointsMergingOptimizerTest.cs b/Unit Tests/Accord.Tests.Math/AForge/Geometry/ClosePointsMergingOptimizerTest.cs new file mode 100644 index 0000000000..2b6cb3682 --- /dev/null +++ b/Unit Tests/Accord.Tests.Math/AForge/Geometry/ClosePointsMergingOptimizerTest.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using AForge; +using AForge.Math.Geometry; +using NUnit.Framework; + +namespace AForge.Math.Geometry.Tests +{ + [TestFixture] + public class ClosePointsMergingOptimizerTest + { + private IShapeOptimizer optimizer = new ClosePointsMergingOptimizer( 3 ); + + + [TestCase( new int[] { 0, 0, 10, 0, 10, 10 }, new int[] { 0, 0, 10, 0, 10, 10 } )] + [TestCase( new int[] { 0, 0, 10, 0, 1, 1 }, new int[] { 0, 0, 10, 0, 1, 1 } )] + [TestCase( new int[] { 0, 0, 10, 0, 10, 10, 2, 2 }, new int[] { 1, 1, 10, 0, 10, 10 } )] + [TestCase( new int[] { 0, 0, 10, 0, 10, 10, 3, 3 }, new int[] { 0, 0, 10, 0, 10, 10, 3, 3 } )] + [TestCase( new int[] { 0, 0, 8, 0, 10, 2, 10, 10 }, new int[] { 0, 0, 9, 1, 10, 10 } )] + [TestCase( new int[] { 2, 0, 8, 0, 10, 2, 10, 8, 8, 10, 0, 2 }, new int[] { 1, 1, 9, 1, 9, 9 } )] + public void OptimizationTest( int[] coordinates, int[] expectedCoordinates ) + { + ShapeOptimizerTestBase.TestOptimizer( coordinates, expectedCoordinates, optimizer ); + } + } +} diff --git a/Unit Tests/Accord.Tests.Math/AForge/Geometry/FlatAnglesOptimizerTest.cs b/Unit Tests/Accord.Tests.Math/AForge/Geometry/FlatAnglesOptimizerTest.cs new file mode 100644 index 0000000000..8a2e8fdaf --- /dev/null +++ b/Unit Tests/Accord.Tests.Math/AForge/Geometry/FlatAnglesOptimizerTest.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using AForge; +using AForge.Math.Geometry; +using NUnit.Framework; + +namespace AForge.Math.Geometry.Tests +{ + [TestFixture] + public class FlatAnglesOptimizerTest + { + private IShapeOptimizer optimizer = new FlatAnglesOptimizer( 160 ); + + + [TestCase( new int[] { 0, 0, 10, 0, 10, 10 }, new int[] { 0, 0, 10, 0, 10, 10 } )] + [TestCase( new int[] { 0, 0, 20, 0, 10, 1 }, new int[] { 0, 0, 20, 0, 10, 1 } )] + [TestCase( new int[] { 0, 0, 10, 1, 20, 0, 20, 20 }, new int[] { 0, 0, 20, 0, 20, 20 } )] + [TestCase( new int[] { 0, 0, 5, 1, 10, 0, 10, 10 }, new int[] { 0, 0, 5, 1, 10, 0, 10, 10 } )] + [TestCase( new int[] { 0, 0, 20, 0, 20, 20, 11, 9 }, new int[] { 0, 0, 20, 0, 20, 20 } )] + [TestCase( new int[] { 0, 0, 20, 0, 20, 20, 9, 11 }, new int[] { 0, 0, 20, 0, 20, 20 } )] + [TestCase( new int[] { 9, 11, 0, 0, 10, 1, 20, 0, 21, 10, 20, 20 }, new int[] { 0, 0, 20, 0, 20, 20 } )] + [TestCase( new int[] { 11, 9, 0, 0, 10, -1, 20, 0, 19, 10, 20, 20 }, new int[] { 0, 0, 20, 0, 20, 20 } )] + public void OptimizationTest( int[] coordinates, int[] expectedCoordinates ) + { + ShapeOptimizerTestBase.TestOptimizer( coordinates, expectedCoordinates, optimizer ); + } + } +} diff --git a/Unit Tests/Accord.Tests.Math/AForge/Geometry/GeometryToolsTest.cs b/Unit Tests/Accord.Tests.Math/AForge/Geometry/GeometryToolsTest.cs new file mode 100644 index 0000000000..9010d3dc0 --- /dev/null +++ b/Unit Tests/Accord.Tests.Math/AForge/Geometry/GeometryToolsTest.cs @@ -0,0 +1,49 @@ +using System; +using AForge; +using AForge.Math.Geometry; +using NUnit.Framework; + +namespace AForge.Math.Geometry.Tests +{ + [TestFixture] + public class GeometryToolsTest + { + + [TestCase( 0, 0, 10, 0, 100, 0, 0 )] + [TestCase( 0, 0, 10, 10, 100, 100, 0 )] + [TestCase( 0, 0, 10, 0, 0, 100, 90 )] + [TestCase( 0, 0, 10, 0, 100, 100, 45 )] + [TestCase( 0, 0, 10, 10, -100, 100, 90 )] + [TestCase( 0, 0, 10, 0, -100, 100, 135 )] + [TestCase( 0, 0, 10, 0, -100, 0, 180 )] + [TestCase( 0, 0, 10, 0, -100, -100, 135 )] + public void GetAngleBetweenVectorsTest( int sx, int sy, int ex1, int ey1, int ex2, int ey2, float expectedAngle ) + { + IntPoint startPoint = new IntPoint( sx, sy ); + IntPoint vector1end = new IntPoint( ex1, ey1 ); + IntPoint vector2end = new IntPoint( ex2, ey2 ); + + float angle = GeometryTools.GetAngleBetweenVectors( startPoint, vector1end, vector2end ); + + Assert.AreEqual( expectedAngle, angle, 0.00001f ); + } + + + [TestCase( 0, 0, 10, 0, 0, 10, 10, 10, 0 )] + [TestCase( 0, 0, 10, 0, 0, 10, 0, 20, 90 )] + [TestCase( 0, 0, 10, 0, 1, 1, 10, 10, 45 )] + [TestCase( 0, 0, 10, 0, 1, 1, -8, 10, 45 )] + [TestCase( 0, 0, 10, 10, 0, 0, -100, 100, 90 )] + public void GetAngleBetweenLinesTest( int sx1, int sy1, int ex1, int ey1, int sx2, int sy2, int ex2, int ey2, float expectedAngle ) + { + IntPoint line1start = new IntPoint( sx1, sy1 ); + IntPoint line1end = new IntPoint( ex1, ey1 ); + IntPoint line2start = new IntPoint( sx2, sy2 ); + IntPoint line2end = new IntPoint( ex2, ey2 ); + + float angle = GeometryTools.GetAngleBetweenLines( line1start, line1end, line2start, line2end ); + + Assert.AreEqual( expectedAngle, angle, 0.00001f ); + } + } +} diff --git a/Unit Tests/Accord.Tests.Math/AForge/Geometry/GrahamConvexHullTest.cs b/Unit Tests/Accord.Tests.Math/AForge/Geometry/GrahamConvexHullTest.cs new file mode 100644 index 0000000000..922d015ac --- /dev/null +++ b/Unit Tests/Accord.Tests.Math/AForge/Geometry/GrahamConvexHullTest.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; +using AForge; +using AForge.Math.Geometry; +using NUnit.Framework; + +namespace AForge.Math.Geometry.Tests +{ + [TestFixture] + public class GrahamConvexHullTest + { + private List pointsList0 = new List( ); + private List pointsList1 = new List( ); + private List pointsList2 = new List( ); + private List pointsList3 = new List( ); + private List pointsList4 = new List( ); + private List pointsList5 = new List( ); + private List pointsList6 = new List( ); + + private List pointsList7 = new List( ); + private List pointsList8 = new List( ); + private List pointsList9 = new List( ); + + private List expectedHull8 = new List( ); + + private List> pointsLists = new List>( ); + private List> expectedHulls = new List>( ); + + public GrahamConvexHullTest( ) + { + // prepare 0st list + pointsList0.Add( new IntPoint( 0, 0 ) ); + + // prepare 1st list + pointsList1.Add( new IntPoint( 0, 0 ) ); + pointsList1.Add( new IntPoint( 100, 0 ) ); + + // prepare 2nd list + pointsList2.AddRange( pointsList1 ); + pointsList2.Add( new IntPoint( 100, 100 ) ); + + // prepare 3rd list + pointsList3.AddRange( pointsList2 ); + pointsList3.Add( new IntPoint( 0, 100 ) ); + + // prepare 4th list + pointsList4.AddRange( pointsList2 ); + pointsList4.Add( new IntPoint( 60, 40 ) ); + + // prepare 5th list + pointsList5.AddRange( pointsList3 ); + pointsList5.Add( new IntPoint( 50, 50 ) ); + + // prepare 6th list + pointsList6.AddRange( pointsList3 ); + pointsList6.Add( new IntPoint( 0, 0 ) ); + + // prepare 7th list + pointsList7.AddRange( pointsList3 ); + pointsList7.AddRange( pointsList3 ); + + // prepare 8th list + pointsList8.AddRange( pointsList3 ); + pointsList8.Add( new IntPoint( 50, -10 ) ); + pointsList8.Add( new IntPoint( 110, 50 ) ); + pointsList8.Add( new IntPoint( 50, 110 ) ); + + expectedHull8.AddRange( pointsList3 ); + expectedHull8.Insert( 1, new IntPoint( 50, -10 ) ); + expectedHull8.Insert( 3, new IntPoint( 110, 50 ) ); + expectedHull8.Insert( 5, new IntPoint( 50, 110 ) ); + + // prepare 9th list + pointsList9.AddRange( pointsList8 ); + pointsList9.Add( new IntPoint( 50, 10 ) ); + pointsList9.Add( new IntPoint( 90, 50 ) ); + pointsList9.Add( new IntPoint( 50, 90 ) ); + pointsList9.Add( new IntPoint( 10, 50 ) ); + + // now prepare list of tests + pointsLists.Add( pointsList0 ); + pointsLists.Add( pointsList1 ); + pointsLists.Add( pointsList2 ); + pointsLists.Add( pointsList3 ); + + expectedHulls.AddRange( pointsLists ); + + pointsLists.Add( pointsList4 ); + expectedHulls.Add( pointsList2 ); + + pointsLists.Add( pointsList5 ); + expectedHulls.Add( pointsList3 ); + + pointsLists.Add( pointsList6 ); + expectedHulls.Add( pointsList3 ); + + pointsLists.Add( pointsList7 ); + expectedHulls.Add( pointsList3 ); + + pointsLists.Add( pointsList8 ); + expectedHulls.Add( expectedHull8 ); + + pointsLists.Add( pointsList9 ); + expectedHulls.Add( expectedHull8 ); + } + + [Test] + public void FindHullTest( ) + { + GrahamConvexHull grahamHull = new GrahamConvexHull( ); + + for ( int i = 0, n = pointsLists.Count; i < n; i++ ) + { + ComparePointsLists( grahamHull.FindHull( pointsLists[i] ), expectedHulls[i] ); + } + } + + private void ComparePointsLists( List list1, List list2 ) + { + Assert.AreEqual( list1.Count, list2.Count ); + + if ( list1.Count == list2.Count ) + { + for ( int i = 0, n = list1.Count; i < n; i++ ) + { + Assert.AreEqual( list2[i], list1[i] ); + } + } + } + } +} diff --git a/Unit Tests/Accord.Tests.Math/AForge/Geometry/LineSegmentTest.cs b/Unit Tests/Accord.Tests.Math/AForge/Geometry/LineSegmentTest.cs new file mode 100644 index 0000000000..dd8d8b270 --- /dev/null +++ b/Unit Tests/Accord.Tests.Math/AForge/Geometry/LineSegmentTest.cs @@ -0,0 +1,191 @@ +using System; +using NUnit.Framework; + +namespace AForge.Math.Geometry.Tests +{ + [TestFixture] + public class LineSegmentTest + { + + [TestCase( 0, 0, 10, 0, 10 )] + [TestCase( 0, 0, 0, 10, 10 )] + [TestCase( 0, 0, 3, 4, 5 )] + [TestCase( 0, 0, -3, 4, 5 )] + [TestCase( 0, 0, -3, -4, 5 )] + public void LengthTest( float sx, float sy, float ex, float ey, float expectedResult ) + { + LineSegment segment = new LineSegment( new Point( sx, sy ), new Point( ex, ey ) ); + + Assert.AreEqual( expectedResult, segment.Length ); + } + + + [TestCase( 0, 0, 5, 0, 8, 0, 5 )] + [TestCase( 6f, 2.5f, 5f, 0f, 8f, 0f, 2.5f )] + [TestCase( 2.5f, 6f, 0f, 5f, 0f, 8f, 2.5f )] + [TestCase( 9, 0, 5, 0, 8, 0, 1 )] + [TestCase( 3, 4, 0, 0, -10, 0, 5 )] + public void DistanceToPointTest( float x, float y, float x1, float y1, float x2, float y2, float expectedDistance ) + { + Point pt = new Point( x, y ); + Point pt1 = new Point( x1, y1 ); + Point pt2 = new Point( x2, y2 ); + LineSegment segment = new LineSegment( pt1, pt2 ); + + Assert.AreEqual( expectedDistance, segment.DistanceToPoint( pt ) ); + } + + // Denotes which versions of the test are supposed to return non-null values: + // SegmentA means that the segment A1-A2 intersects with the line B1-B2, but not + // with the segment B1-B2. + public enum IntersectionType { None, LinesOnly, SegmentA, SegmentB, AllFour }; + + + [TestCase( 0, 0, 4, 4, 0, 4, 4, 0, 2, 2, IntersectionType.AllFour )] + [TestCase( 0, 0, 4, 0, 0, 0, 0, 4, 0, 0, IntersectionType.AllFour )] + [TestCase( 0, 0, 4, 4, 4, 8, 8, 4, 6, 6, IntersectionType.SegmentB )] + [TestCase( -4, -4, 0, 0, 4, 0, 8, -4, 2, 2, IntersectionType.LinesOnly )] + [TestCase( 0, 0, 6, 0, 5, 1, 5, 5, 5, 0, IntersectionType.SegmentA )] + [TestCase( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, IntersectionType.LinesOnly, ExpectedException = typeof( ArgumentException ), ExpectedMessage = "Start point of the line cannot be the same as its end point." )] + [TestCase( 0, 0, 0, 5, 1, 0, 1, 5, 0, 0, IntersectionType.None)] + public void IntersectionPointTest( float ax1, float ay1, float ax2, float ay2, float bx1, float by1, float bx2, float by2, float ix, float iy, IntersectionType type ) + { + LineSegment segA = new LineSegment( new Point( ax1, ay1 ), new Point( ax2, ay2 ) ); + LineSegment segB = new LineSegment( new Point( bx1, by1 ), new Point( bx2, by2 ) ); + Point expectedIntersection = new Point( ix, iy ); + + Assert.DoesNotThrow( ( ) => + { + Point? segSeg = segA.GetIntersectionWith( segB ); + Point? segLine = segA.GetIntersectionWith( (Line) segB ); + Point? lineSeg = ( (Line) segA ).GetIntersectionWith( segB ); + + if ( type == IntersectionType.AllFour ) + { + Assert.AreEqual( expectedIntersection, segSeg ); + } + else + { + Assert.AreEqual( null, segSeg ); + } + + if ( ( type == IntersectionType.AllFour ) || ( type == IntersectionType.SegmentA ) ) + { + Assert.AreEqual( expectedIntersection, segLine ); + } + else + { + Assert.AreEqual( null, segLine ); + } + + if ( ( type == IntersectionType.AllFour ) || ( type == IntersectionType.SegmentB ) ) + { + Assert.AreEqual( expectedIntersection, lineSeg ); + } + else + { + Assert.AreEqual( null, lineSeg ); + } + } ); + + Point? lineLine = ( (Line) segA ).GetIntersectionWith( (Line) segB ); + + if ( type != IntersectionType.None ) + { + Assert.AreEqual( expectedIntersection, lineLine ); + } + else + { + Assert.AreEqual( null, lineLine ); + } + } + + + [TestCase( 0, 0, 0, 1, 1, 1, 1, 2 )] + [TestCase( 0, 0, 4, 4, 3, -1, 7, 3 )] + [TestCase( 0, 0, 1, 0, 1, 1, 2, 1 )] + public void ParallelIntersectionPointTest( float ax1, float ay1, float ax2, float ay2, float bx1, float by1, float bx2, float by2 ) + { + LineSegment segA = new LineSegment( new Point( ax1, ay1 ), new Point( ax2, ay2 ) ); + LineSegment segB = new LineSegment( new Point( bx1, by1 ), new Point( bx2, by2 ) ); + + // are we really parallel? + Assert.AreEqual( null, ( (Line) segA ).GetIntersectionWith( (Line) segB ) ); + + Assert.AreEqual( null, segA.GetIntersectionWith( (Line) segB ) ); + Assert.AreEqual( null, ( (Line) segA ).GetIntersectionWith( segB ) ); + Assert.AreEqual( null, segB.GetIntersectionWith( (Line) segA ) ); + Assert.AreEqual( null, ( (Line) segB ).GetIntersectionWith( segA ) ); + Assert.AreEqual( null, segB.GetIntersectionWith( segA ) ); + Assert.AreEqual( null, segA.GetIntersectionWith( segB ) ); + } + + + [TestCase( 0, 0, 1, 1, 2, 2, 3, 3 )] + [TestCase( 0, 1, 0, 2, 0, 3, 0, 4 )] + [TestCase( 0, 0, -1, 1, -2, 2, -3, 3 )] + [TestCase( 1, 0, 2, 0, 3, 0, 4, 0 )] + [TestCase(0, 0, 0, 1, 0, 2, 0, 3 )] + public void CollinearIntersectionPointTest(float ax1, float ay1, float ax2, float ay2, float bx1, float by1, float bx2, float by2) + { + LineSegment segA = new LineSegment( new Point( ax1, ay1 ), new Point( ax2, ay2 ) ); + LineSegment segB = new LineSegment( new Point( bx1, by1 ), new Point( bx2, by2 ) ); + + // are we really collinear? + Assert.Throws( ( ) => ( (Line) segA ).GetIntersectionWith( (Line) segB ) ); + + Assert.Throws( ( ) => segA.GetIntersectionWith( (Line) segB ) ); + Assert.Throws( ( ) => ( (Line) segA ).GetIntersectionWith( segB ) ); + Assert.Throws( ( ) => segB.GetIntersectionWith( (Line) segA ) ); + Assert.Throws( ( ) => ( (Line) segB ).GetIntersectionWith( segA ) ); + Assert.AreEqual( null, segB.GetIntersectionWith( segA ) ); + Assert.AreEqual( null, segA.GetIntersectionWith( segB ) ); + } + + + [TestCase( 0, 0, 1, 1, 1, 1, 3, 3, 1, 1 )] + [TestCase( 0, 0, 1, 1, 3, 3, 1, 1, 1, 1 )] + [TestCase( 0, 0, 1, 1, 0, 0, -3, -3, 0, 0 )] + [TestCase( 0, 0, 1, 1, -1, -1, 0, 0, 0, 0 )] + [TestCase( 0, 1, 0, 2, 0, 1, 0, 0, 0, 1 )] + [TestCase( 0, 1, 0, 2, 0, 2, 0, 4, 0, 2 )] + [TestCase( 0, 1, 0, 2, 0, 0, 0, 1, 0, 1 )] + [TestCase( 0, 1, 0, 2, 0, 3, 0, 2, 0, 2 )] + public void CommonIntersectionPointTest( float ax1, float ay1, float ax2, float ay2, float bx1, float by1, float bx2, float by2, float ix, float iy ) + { + LineSegment segA = new LineSegment( new Point( ax1, ay1 ), new Point( ax2, ay2 ) ); + LineSegment segB = new LineSegment( new Point( bx1, by1 ), new Point( bx2, by2 ) ); + Point expectedIntersection = new Point( ix, iy ); + + // are we really collinear? + Assert.Throws( ( ) => ( (Line) segA ).GetIntersectionWith( (Line) segB ) ); + + Assert.Throws( ( ) => segA.GetIntersectionWith( (Line) segB ) ); + Assert.Throws( ( ) => ( (Line) segA ).GetIntersectionWith( segB ) ); + Assert.Throws( ( ) => segB.GetIntersectionWith( (Line) segA ) ); + Assert.Throws( ( ) => ( (Line) segB ).GetIntersectionWith( segA ) ); + Assert.AreEqual( expectedIntersection, segB.GetIntersectionWith( segA ) ); + Assert.AreEqual( expectedIntersection, segA.GetIntersectionWith( segB ) ); + } + + + [TestCase( 0, 0, 0, 2, 0, 1, 0, 3 )] + [TestCase( 1, 2, 3, 4, 2, 3, 4, 5 )] + [TestCase( 0, 0, 2, 0, 3, 0, 1, 0 )] + public void OverlappingSegmentIntersectionPointTest( float ax1, float ay1, float ax2, float ay2, float bx1, float by1, float bx2, float by2 ) + { + LineSegment segA = new LineSegment( new Point( ax1, ay1 ), new Point( ax2, ay2 ) ); + LineSegment segB = new LineSegment( new Point( bx1, by1 ), new Point( bx2, by2 ) ); + + // are we really collinear? + Assert.Throws( ( ) => ( (Line) segA ).GetIntersectionWith( (Line) segB ) ); + + Assert.Throws( ( ) => segA.GetIntersectionWith( (Line) segB ) ); + Assert.Throws( ( ) => ( (Line) segA ).GetIntersectionWith( segB ) ); + Assert.Throws( ( ) => segB.GetIntersectionWith( (Line) segA ) ); + Assert.Throws( ( ) => ( (Line) segB ).GetIntersectionWith( segA ) ); + Assert.Throws( ( ) => segB.GetIntersectionWith( segA ) ); + Assert.Throws( ( ) => segA.GetIntersectionWith( segB ) ); + } + } +} diff --git a/Unit Tests/Accord.Tests.Math/AForge/Geometry/LineStraighteningOptimizerTest.cs b/Unit Tests/Accord.Tests.Math/AForge/Geometry/LineStraighteningOptimizerTest.cs new file mode 100644 index 0000000000..0d8281235 --- /dev/null +++ b/Unit Tests/Accord.Tests.Math/AForge/Geometry/LineStraighteningOptimizerTest.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using AForge; +using AForge.Math.Geometry; +using NUnit.Framework; + +namespace AForge.Math.Geometry.Tests +{ + [TestFixture] + public class LineStraighteningOptimizerTest + { + private IShapeOptimizer optimizer = new LineStraighteningOptimizer( 3 ); + + + [TestCase( new int[] { 0, 0, 10, 0, 10, 10 }, new int[] { 0, 0, 10, 0, 10, 10 } )] + [TestCase( new int[] { 0, 0, 10, 0, 5, 1 }, new int[] { 0, 0, 10, 0, 5, 1 } )] + [TestCase( new int[] { 0, 0, 10, 0, 10, 10, 5, 5 }, new int[] { 0, 0, 10, 0, 10, 10 } )] + [TestCase( new int[] { 0, 0, 10, 0, 10, 10, 4, 6 }, new int[] { 0, 0, 10, 0, 10, 10 } )] + [TestCase( new int[] { 0, 0, 10, 0, 10, 10, 6, 4 }, new int[] { 0, 0, 10, 0, 10, 10 } )] + [TestCase( new int[] { 0, 0, 10, 0, 10, 10, 7, 3 }, new int[] { 0, 0, 10, 0, 10, 10 } )] + [TestCase( new int[] { 0, 0, 10, 0, 10, 10, 8, 2 }, new int[] { 0, 0, 10, 0, 10, 10, 8, 2 } )] + [TestCase( new int[] { 4, 6, 0, 0, 5, 1, 10, 0, 10, 5, 10, 10 }, new int[] { 0, 0, 10, 0, 10, 10 } )] + [TestCase( new int[] { 6, 4, 0, 0, 6, -1, 10, 0, 9, 4, 10, 10 }, new int[] { 0, 0, 10, 0, 10, 10 } )] + public void OptimizationTest( int[] coordinates, int[] expectedCoordinates ) + { + ShapeOptimizerTestBase.TestOptimizer( coordinates, expectedCoordinates, optimizer ); + } + } +} diff --git a/Unit Tests/Accord.Tests.Math/AForge/Geometry/LineTest.cs b/Unit Tests/Accord.Tests.Math/AForge/Geometry/LineTest.cs new file mode 100644 index 0000000000..ebaa9fc66 --- /dev/null +++ b/Unit Tests/Accord.Tests.Math/AForge/Geometry/LineTest.cs @@ -0,0 +1,124 @@ +using System; +using NUnit.Framework; + +namespace AForge.Math.Geometry.Tests +{ + [TestFixture] + public class LineTest + { + private const float Error = 0.00001f; + + + [TestCase( 1, 1, 45, 1.41421356f, -1, 2 )] + [TestCase( -2, 2, 135, 2 * 1.41421356f, 1, 4 )] + [TestCase( -0.5f, -1.73205081f / 2, 240, 1, -1 / 1.73205081f, -2 / 1.73205081f )] + [TestCase( 1, 0, 0, 1, float.NegativeInfinity, 1 )] + [TestCase( 0, -1, 270, 1, 0, -1 )] + public void RThetaTest( float x, float y, float theta, float expectedRadius, float expectedSlope, float expectedIntercept ) + { + Point pt = new Point( x, y ); + + // test Point-Theta factory + Line line = Line.FromPointTheta( pt, theta ); + Assert.AreEqual( expectedSlope, line.Slope, Error ); + Assert.AreEqual( expectedIntercept, line.Intercept, Error ); + + // calculate radius + float radius = pt.EuclideanNorm( ); + Assert.AreEqual( expectedRadius, radius, Error ); + + // test R-Theta factory + line = Line.FromRTheta( radius, theta ); + Assert.AreEqual( expectedSlope, line.Slope, Error ); + Assert.AreEqual( expectedIntercept, line.Intercept, Error ); + } + + + [TestCase( 0, 0, 0, 10, true, float.PositiveInfinity, 0 )] + [TestCase( 0, 0, 0, -10, true, float.NegativeInfinity, 0 )] + [TestCase( 0, 0, 10, 10, false, 1, 0 )] + [TestCase( 0, 0, 10, 0, false, 0, 0 )] + public void IsVerticalTest( float sx, float sy, float ex, float ey, bool expectedResult, float expectedSlope, float expectedIntercept ) + { + Line line = Line.FromPoints( new Point( sx, sy ), new Point( ex, ey ) ); + + Assert.AreEqual( expectedResult, line.IsVertical ); + Assert.AreEqual( expectedSlope, line.Slope ); + Assert.AreEqual( expectedIntercept, line.Intercept ); + } + + + [TestCase( 0, 0, 10, 0, true, 0, 0 )] + [TestCase( 0, 0, -10, 0, true, 0, 0 )] + [TestCase( 0, 0, 10, 10, false, 1, 0 )] + [TestCase( 0, 0, 0, 10, false, float.PositiveInfinity, 0 )] + public void IsHorizontalTest( float sx, float sy, float ex, float ey, bool expectedResult, float expectedSlope, float expectedIntercept ) + { + Line line = Line.FromPoints( new Point( sx, sy ), new Point( ex, ey ) ); + + Assert.AreEqual( expectedResult, line.IsHorizontal ); + Assert.AreEqual( expectedSlope, line.Slope ); + Assert.AreEqual( expectedIntercept, line.Intercept ); + } + + + [TestCase( 0, 0, 10, 0, 0, 10, 10, 10, 0 )] + [TestCase( 0, 0, 10, 0, 0, 10, 0, 20, 90 )] + [TestCase( 0, 0, 10, 0, 1, 1, 10, 10, 45 )] + [TestCase( 0, 0, 10, 0, 1, 1, -8, 10, 45 )] + [TestCase( 0, 0, 10, 10, 0, 0, -100, 100, 90 )] + public void GetAngleBetweenLinesTest( float sx1, float sy1, float ex1, float ey1, float sx2, float sy2, float ex2, float ey2, float expectedAngle ) + { + Line line1 = Line.FromPoints( new Point( sx1, sy1 ), new Point( ex1, ey1 ) ); + Line line2 = Line.FromPoints( new Point( sx2, sy2 ), new Point( ex2, ey2 ) ); + + float angle = line1.GetAngleBetweenLines( line2 ); + + Assert.AreEqual( expectedAngle, angle, Error ); + } + + + [TestCase( 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, false )] + [TestCase( 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, false )] + [TestCase( 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, false, ExpectedException = typeof( InvalidOperationException ) )] + [TestCase( 0, 0, 1, 1, 0, 1, 1, 2, 0, 0, false )] + [TestCase( 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, true )] + [TestCase( 0, 0, 1, 0, 0, 1, 1, 2, -1, 0, true )] + [TestCase( 0, 0, 1, 0, 1, 1, 1, 2, 1, 0, true )] + [TestCase( 0, 0, 0, 1, 0, 1, -1, 1, 0, 1, true )] + [TestCase( -1, -1, 1, 1, 1, -1, -1, 1, 0, 0, true )] + public void GetIntersectionPointTest( float sx1, float sy1, float ex1, float ey1, + float sx2, float sy2, float ex2, float ey2, float xRet, float yRet, bool hasResult ) + { + Line line1 = Line.FromPoints( new Point( sx1, sy1 ), new Point( ex1, ey1 ) ); + Line line2 = Line.FromPoints( new Point( sx2, sy2 ), new Point( ex2, ey2 ) ); + + Point? result = line1.GetIntersectionWith( line2 ); + + if ( hasResult ) + { + Assert.IsTrue( result == new Point( xRet, yRet ) ); + } + else + { + Assert.AreEqual( null, result ); + } + } + + + [TestCase( 0, 0, 5, 0, 8, 0, 0 )] + [TestCase( 6, 2, 5, 0, 8, 0, 2 )] + [TestCase( 2, 6, 0, 5, 0, 8, 2 )] + [TestCase( 9, 0, 5, 0, 8, 0, 0 )] + [TestCase( 3, 0, 0, 0, 3, 4, 2.4f )] + public void DistanceToPointTest( float x, float y, float x1, float y1, float x2, float y2, float expectedDistance ) + { + Point pt = new Point( x, y ); + Point pt1 = new Point( x1, y1 ); + Point pt2 = new Point( x2, y2 ); + Line line = Line.FromPoints( pt1, pt2 ); + + Assert.AreEqual( expectedDistance, line.DistanceToPoint( pt ), Error ); + } + } +} diff --git a/Unit Tests/Accord.Tests.Math/AForge/Geometry/ShapeOptimizerTestBase.cs b/Unit Tests/Accord.Tests.Math/AForge/Geometry/ShapeOptimizerTestBase.cs new file mode 100644 index 0000000000..637ee9b88 --- /dev/null +++ b/Unit Tests/Accord.Tests.Math/AForge/Geometry/ShapeOptimizerTestBase.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using AForge; +using AForge.Math.Geometry; +using NUnit.Framework; + +namespace AForge.Math.Geometry.Tests +{ + static class ShapeOptimizerTestBase + { + public static void TestOptimizer( int[] coordinates, int[] expectedCoordinates, IShapeOptimizer optimizer ) + { + List shape = new List( ); + List expectedShape = new List( ); + + // build a shape top optimize + for ( int i = 0, n = coordinates.Length / 2; i < n; i++ ) + { + shape.Add( new IntPoint( coordinates[i * 2], coordinates[i * 2 + 1] ) ); + } + + // build a shape, which should be result of optimization + for ( int i = 0, n = expectedCoordinates.Length / 2; i < n; i++ ) + { + expectedShape.Add( new IntPoint( expectedCoordinates[i * 2], expectedCoordinates[i * 2 + 1] ) ); + } + + List optimizedShape = optimizer.OptimizeShape( shape ); + + // check number of points in result shape + Assert.AreEqual( expectedShape.Count, optimizedShape.Count ); + + // check that all points matches with expected + for ( int i = 0, n = optimizedShape.Count; i < n; i++ ) + { + Assert.AreEqual( expectedShape[i], optimizedShape[i] ); + } + } + } +} diff --git a/Unit Tests/Accord.Tests.Math/AForge/Geometry/SimpleShapeCheckerTest.cs b/Unit Tests/Accord.Tests.Math/AForge/Geometry/SimpleShapeCheckerTest.cs new file mode 100644 index 0000000000..39566e8cb --- /dev/null +++ b/Unit Tests/Accord.Tests.Math/AForge/Geometry/SimpleShapeCheckerTest.cs @@ -0,0 +1,303 @@ +using System; +using System.Collections.Generic; +using AForge; +using AForge.Math.Geometry; +using NUnit.Framework; + +namespace AForge.Math.Geometry.Tests +{ + [TestFixture] + public class SimpleShapeCheckerTest + { + private SimpleShapeChecker shapeChecker = new SimpleShapeChecker( ); + + private List idealCicle = new List( ); + private List distorredCircle = new List( ); + + private List square1 = new List( ); + private List square1Test = new List( ); + private List square2 = new List( ); + private List square2Test = new List( ); + private List square3 = new List( ); + private List rectangle = new List( ); + + private List triangle1 = new List( ); + private List isoscelesTriangle = new List( ); + private List equilateralTriangle = new List( ); + private List rectangledTriangle = new List( ); + + public SimpleShapeCheckerTest( ) + { + System.Random rand = new System.Random( ); + + // generate sample circles + double radius = 100; + + for ( int i = 0; i < 360; i += 10 ) + { + double angle = (double) i / 180 * System.Math.PI; + + // add point to ideal circle + idealCicle.Add( new IntPoint( + (int) ( radius * System.Math.Cos( angle ) ), + (int) ( radius * System.Math.Sin( angle ) ) ) ); + + // add a bit distortion for distorred cirlce + double distorredRadius = radius + rand.Next( 7 ) - 3; + + distorredCircle.Add( new IntPoint( + (int) ( distorredRadius * System.Math.Cos( angle ) ), + (int) ( distorredRadius * System.Math.Sin( angle ) ) ) ); + } + + // generate sample squares + square1.Add( new IntPoint( 0, 0 ) ); + square1.Add( new IntPoint( 50, 0 ) ); + square1.Add( new IntPoint( 100, 0 ) ); + square1.Add( new IntPoint( 100, 50 ) ); + square1.Add( new IntPoint( 100, 100 ) ); + square1.Add( new IntPoint( 50, 100 ) ); + square1.Add( new IntPoint( 0, 100 ) ); + square1.Add( new IntPoint( 0, 50 ) ); + + square2.Add( new IntPoint( 50, 0 ) ); + square2.Add( new IntPoint( 75, 25 ) ); + square2.Add( new IntPoint( 100, 50 ) ); + square2.Add( new IntPoint( 75, 75 ) ); + square2.Add( new IntPoint( 50, 100 ) ); + square2.Add( new IntPoint( 25, 75 ) ); + square2.Add( new IntPoint( 0, 50 ) ); + square2.Add( new IntPoint( 25, 25 ) ); + + // these should be obtained as corners + square1Test.Add( new IntPoint( 0, 0 ) ); + square1Test.Add( new IntPoint( 100, 0 ) ); + square1Test.Add( new IntPoint( 100, 100 ) ); + square1Test.Add( new IntPoint( 0, 100 ) ); + + square2Test.Add( new IntPoint( 50, 0 ) ); + square2Test.Add( new IntPoint( 100, 50 ) ); + square2Test.Add( new IntPoint( 50, 100 ) ); + square2Test.Add( new IntPoint( 0, 50 ) ); + + // special square, which may look like circle, but should be recognized as circle + square3.Add( new IntPoint( 50, 0 ) ); + square3.Add( new IntPoint( 100, 50 ) ); + square3.Add( new IntPoint( 50, 100 ) ); + square3.Add( new IntPoint( 0, 50 ) ); + + // generate sample rectangle + rectangle.Add( new IntPoint( 0, 0 ) ); + rectangle.Add( new IntPoint( 50, 0 ) ); + rectangle.Add( new IntPoint( 100, 0 ) ); + rectangle.Add( new IntPoint( 100, 20 ) ); + rectangle.Add( new IntPoint( 100, 40 ) ); + rectangle.Add( new IntPoint( 50, 40 ) ); + rectangle.Add( new IntPoint( 0, 40 ) ); + rectangle.Add( new IntPoint( 0, 20 ) ); + + // generate some triangles + triangle1.Add( new IntPoint( 0, 0 ) ); + triangle1.Add( new IntPoint( 50, 10 ) ); + triangle1.Add( new IntPoint( 100, 20 ) ); + triangle1.Add( new IntPoint( 90, 50 ) ); + triangle1.Add( new IntPoint( 80, 80 ) ); + triangle1.Add( new IntPoint( 40, 40 ) ); + + isoscelesTriangle.Add( new IntPoint( 0, 0 ) ); + isoscelesTriangle.Add( new IntPoint( 50, 0 ) ); + isoscelesTriangle.Add( new IntPoint( 100, 0 ) ); + isoscelesTriangle.Add( new IntPoint( 75, 20 ) ); + isoscelesTriangle.Add( new IntPoint( 50, 40 ) ); + isoscelesTriangle.Add( new IntPoint( 25, 20 ) ); + + equilateralTriangle.Add( new IntPoint( 0, 0 ) ); + equilateralTriangle.Add( new IntPoint( 50, 0 ) ); + equilateralTriangle.Add( new IntPoint( 100, 0 ) ); + equilateralTriangle.Add( new IntPoint( 75, 43 ) ); + equilateralTriangle.Add( new IntPoint( 50, 86 ) ); + equilateralTriangle.Add( new IntPoint( 25, 43 ) ); + + rectangledTriangle.Add( new IntPoint( 0, 0 ) ); + rectangledTriangle.Add( new IntPoint( 20, 0 ) ); + rectangledTriangle.Add( new IntPoint( 40, 0 ) ); + rectangledTriangle.Add( new IntPoint( 20, 50 ) ); + rectangledTriangle.Add( new IntPoint( 0, 100 ) ); + rectangledTriangle.Add( new IntPoint( 0, 50 ) ); + } + + [Test] + public void IsCircleTest( ) + { + Assert.AreEqual( true, shapeChecker.IsCircle( idealCicle ) ); + Assert.AreEqual( true, shapeChecker.IsCircle( distorredCircle ) ); + + Assert.AreEqual( false, shapeChecker.IsCircle( square1 ) ); + Assert.AreEqual( false, shapeChecker.IsCircle( square2 ) ); + Assert.AreEqual( false, shapeChecker.IsCircle( square3 ) ); + Assert.AreEqual( false, shapeChecker.IsCircle( rectangle ) ); + + Assert.AreEqual( false, shapeChecker.IsCircle( triangle1 ) ); + Assert.AreEqual( false, shapeChecker.IsCircle( equilateralTriangle ) ); + Assert.AreEqual( false, shapeChecker.IsCircle( isoscelesTriangle ) ); + Assert.AreEqual( false, shapeChecker.IsCircle( rectangledTriangle ) ); + } + + [Test] + public void IsQuadrilateralTest( ) + { + Assert.AreEqual( true, shapeChecker.IsQuadrilateral( square1 ) ); + Assert.AreEqual( true, shapeChecker.IsQuadrilateral( square2 ) ); + Assert.AreEqual( true, shapeChecker.IsQuadrilateral( square3 ) ); + Assert.AreEqual( true, shapeChecker.IsQuadrilateral( rectangle ) ); + + Assert.AreEqual( false, shapeChecker.IsQuadrilateral( idealCicle ) ); + Assert.AreEqual( false, shapeChecker.IsQuadrilateral( distorredCircle ) ); + + Assert.AreEqual( false, shapeChecker.IsQuadrilateral( triangle1 ) ); + Assert.AreEqual( false, shapeChecker.IsQuadrilateral( equilateralTriangle ) ); + Assert.AreEqual( false, shapeChecker.IsQuadrilateral( isoscelesTriangle ) ); + Assert.AreEqual( false, shapeChecker.IsQuadrilateral( rectangledTriangle ) ); + } + + [Test] + public void CheckQuadrilateralCornersTest( ) + { + List corners; + + Assert.AreEqual( true, shapeChecker.IsQuadrilateral( square1, out corners ) ); + Assert.AreEqual( 4, corners.Count ); + Assert.AreEqual( true, CompareShape( corners, square1Test ) ); + + Assert.AreEqual( true, shapeChecker.IsQuadrilateral( square2, out corners ) ); + Assert.AreEqual( 4, corners.Count ); + Assert.AreEqual( true, CompareShape( corners, square2Test ) ); + } + + [Test] + public void IsTriangleTest( ) + { + Assert.AreEqual( true, shapeChecker.IsTriangle( triangle1 ) ); + Assert.AreEqual( true, shapeChecker.IsTriangle( equilateralTriangle ) ); + Assert.AreEqual( true, shapeChecker.IsTriangle( isoscelesTriangle ) ); + Assert.AreEqual( true, shapeChecker.IsTriangle( rectangledTriangle ) ); + + Assert.AreEqual( false, shapeChecker.IsTriangle( idealCicle ) ); + Assert.AreEqual( false, shapeChecker.IsTriangle( distorredCircle ) ); + + Assert.AreEqual( false, shapeChecker.IsTriangle( square1 ) ); + Assert.AreEqual( false, shapeChecker.IsTriangle( square2 ) ); + Assert.AreEqual( false, shapeChecker.IsTriangle( square3 ) ); + Assert.AreEqual( false, shapeChecker.IsTriangle( rectangle ) ); + } + + [Test] + public void IsConvexPolygon( ) + { + List corners; + + Assert.AreEqual( true, shapeChecker.IsConvexPolygon( triangle1, out corners ) ); + Assert.AreEqual( 3, corners.Count ); + Assert.AreEqual( true, shapeChecker.IsConvexPolygon( equilateralTriangle, out corners ) ); + Assert.AreEqual( 3, corners.Count ); + Assert.AreEqual( true, shapeChecker.IsConvexPolygon( isoscelesTriangle, out corners ) ); + Assert.AreEqual( 3, corners.Count ); + Assert.AreEqual( true, shapeChecker.IsConvexPolygon( rectangledTriangle, out corners ) ); + Assert.AreEqual( 3, corners.Count ); + + Assert.AreEqual( true, shapeChecker.IsConvexPolygon( square1, out corners ) ); + Assert.AreEqual( 4, corners.Count ); + Assert.AreEqual( true, shapeChecker.IsConvexPolygon( square2, out corners ) ); + Assert.AreEqual( 4, corners.Count ); + Assert.AreEqual( true, shapeChecker.IsConvexPolygon( square3, out corners ) ); + Assert.AreEqual( 4, corners.Count ); + Assert.AreEqual( true, shapeChecker.IsConvexPolygon( rectangle, out corners ) ); + Assert.AreEqual( 4, corners.Count ); + + Assert.AreEqual( false, shapeChecker.IsConvexPolygon( idealCicle, out corners ) ); + Assert.AreEqual( false, shapeChecker.IsConvexPolygon( distorredCircle, out corners ) ); + } + + [Test] + public void CheckShapeTypeTest( ) + { + Assert.AreEqual( ShapeType.Circle, shapeChecker.CheckShapeType( idealCicle ) ); + Assert.AreEqual( ShapeType.Circle, shapeChecker.CheckShapeType( distorredCircle ) ); + + Assert.AreEqual( ShapeType.Quadrilateral, shapeChecker.CheckShapeType( square1 ) ); + Assert.AreEqual( ShapeType.Quadrilateral, shapeChecker.CheckShapeType( square2 ) ); + Assert.AreEqual( ShapeType.Quadrilateral, shapeChecker.CheckShapeType( square3 ) ); + Assert.AreEqual( ShapeType.Quadrilateral, shapeChecker.CheckShapeType( rectangle ) ); + + Assert.AreEqual( ShapeType.Triangle, shapeChecker.CheckShapeType( triangle1 ) ); + Assert.AreEqual( ShapeType.Triangle, shapeChecker.CheckShapeType( equilateralTriangle ) ); + Assert.AreEqual( ShapeType.Triangle, shapeChecker.CheckShapeType( isoscelesTriangle ) ); + Assert.AreEqual( ShapeType.Triangle, shapeChecker.CheckShapeType( rectangledTriangle ) ); + } + + private bool CompareShape( List shape1, List shape2 ) + { + if ( shape1.Count != shape2.Count ) + return false; + if ( shape1.Count == 0 ) + return true; + + int index = shape1.IndexOf( shape2[0] ); + + if ( index == -1 ) + return false; + + index++; + + for ( int i = 1; i < shape2.Count; i++, index++ ) + { + if ( index >= shape1.Count ) + index = 0; + + if ( !shape1[index].Equals( shape2[i] ) ) + return false; + } + + return true; + } + + + [TestCase( PolygonSubType.Unknown, new int[] { 0, 0, 100, 0, 90, 10 } )] // just a triangle + [TestCase( PolygonSubType.IsoscelesTriangle, new int[] { 0, 0, 100, 0, 50, 10 } )] + [TestCase( PolygonSubType.IsoscelesTriangle, new int[] { 0, 0, 100, 0, 50, 200 } )] + [TestCase( PolygonSubType.EquilateralTriangle, new int[] { 0, 0, 100, 0, 50, 86 } )] + [TestCase( PolygonSubType.RectangledIsoscelesTriangle, new int[] { 0, 0, 100, 0, 50, 50 } )] + [TestCase( PolygonSubType.RectangledIsoscelesTriangle, new int[] { 0, 0, 100, 0, 0, 100 } )] + [TestCase( PolygonSubType.RectangledTriangle, new int[] { 0, 0, 100, 0, 0, 50 } )] + [TestCase( PolygonSubType.Unknown, new int[] { 0, 0, 100, 0, 90, 50, 10, 70 } )] // just a quadrilateral + [TestCase( PolygonSubType.Trapezoid, new int[] { 0, 0, 100, 0, 90, 50, 10, 50 } )] + [TestCase( PolygonSubType.Trapezoid, new int[] { 0, 0, 100, 0, 90, 50, 0, 50 } )] + [TestCase( PolygonSubType.Trapezoid, new int[] { 0, 0, 100, 0, 90, 50, 0, 53 } )] // a bit disformed + [TestCase( PolygonSubType.Parallelogram, new int[] { 0, 0, 100, 0, 120, 50, 20, 50 } )] + [TestCase( PolygonSubType.Parallelogram, new int[] { 0, 0, 100, 0, 70, 50, -30, 50 } )] + [TestCase( PolygonSubType.Rectangle, new int[] { 0, 0, 100, 0, 100, 50, 0, 50 } )] + [TestCase( PolygonSubType.Rectangle, new int[] { 0, 0, 100, 0, 100, 52, -3, 50 } )] // a bit disformed + [TestCase( PolygonSubType.Square, new int[] { 0, 0, 100, 0, 100, 100, 0, 100 } )] + [TestCase( PolygonSubType.Square, new int[] { 50, 0, 100, 50, 50, 100, 0, 50 } )] + [TestCase( PolygonSubType.Square, new int[] { 51, 0, 100, 49, 50, 101, 1, 50 } )] // a bit disformed + [TestCase( PolygonSubType.Rhombus, new int[] { 30, 0, 60, 50, 30, 100, 0, 50 } )] + [TestCase( PolygonSubType.Rhombus, new int[] { 0, 0, 100, 0, 130, 95, 30, 95 } )] + [TestCase( PolygonSubType.Unknown, new int[] { 0, 0, 100, 0, 90, 50, 40, 70, 10, 40 } )] // unknown if 5 corners or more + public void CheckPolygonSubTypeTest( PolygonSubType expectedSubType, int[] corners ) + { + Assert.AreEqual( expectedSubType, shapeChecker.CheckPolygonSubType( GetListOfPointFromArray( corners ) ) ); + } + + private List GetListOfPointFromArray( int[] points ) + { + List list = new List( ); + + for ( int i = 0, n = points.Length; i < n; i += 2 ) + { + list.Add( new IntPoint( points[i], points[i + 1] ) ); + } + + return list; + } + } +} diff --git a/Unit Tests/Accord.Tests.Math/AForge/Matrix3x3Test.cs b/Unit Tests/Accord.Tests.Math/AForge/Matrix3x3Test.cs new file mode 100644 index 0000000000..99dd0b3af --- /dev/null +++ b/Unit Tests/Accord.Tests.Math/AForge/Matrix3x3Test.cs @@ -0,0 +1,421 @@ +using System; +using AForge; +using AForge.Math; +using NUnit.Framework; + +namespace AForge.Math.Tests +{ + [TestFixture] + public class Matrix3x3Test + { + private const float Epsilon = 0.000001f; + + private Matrix3x3 a1 = new Matrix3x3( ); + private Matrix3x3 a2 = new Matrix3x3( ); + + public Matrix3x3Test( ) + { + // prepare 1st argument + a1.V00 = 1; + a1.V01 = 2; + a1.V02 = 3; + + a1.V10 = 3; + a1.V11 = 2; + a1.V12 = 1; + + a1.V20 = 1; + a1.V21 = 3; + a1.V22 = 2; + + // prepare 2nd argument + a2.V00 = 2; + a2.V01 = 1; + a2.V02 = 3; + + a2.V10 = 1; + a2.V11 = 3; + a2.V12 = 2; + + a2.V20 = 3; + a2.V21 = 2; + a2.V22 = 1; + } + + [Test] + public void ToArrayTest( ) + { + Matrix3x3 matrix = new Matrix3x3( ); + + matrix.V00 = 1; + matrix.V01 = 2; + matrix.V02 = 3; + + matrix.V10 = 4; + matrix.V11 = 5; + matrix.V12 = 6; + + matrix.V20 = 7; + matrix.V21 = 8; + matrix.V22 = 9; + + float[] array = matrix.ToArray( ); + + for ( int i = 0; i < 9; i++ ) + { + Assert.AreEqual( array[i], (float) ( i + 1 ) ); + } + } + + [Test] + public void CreateFromRowsTest( ) + { + Vector3 row0 = new Vector3( 1, 2, 3 ); + Vector3 row1 = new Vector3( 4, 5, 6 ); + Vector3 row2 = new Vector3( 7, 8, 9 ); + Matrix3x3 matrix = Matrix3x3.CreateFromRows( row0, row1, row2 ); + + float[] array = matrix.ToArray( ); + + for ( int i = 0; i < 9; i++ ) + { + Assert.AreEqual( array[i], (float) ( i + 1 ) ); + } + + Assert.AreEqual( row0, matrix.GetRow( 0 ) ); + Assert.AreEqual( row1, matrix.GetRow( 1 ) ); + Assert.AreEqual( row2, matrix.GetRow( 2 ) ); + + Assert.Throws( ( ) => + { + matrix.GetRow( -1 ); + } + ); + + Assert.Throws( ( ) => + { + matrix.GetRow( 3 ); + } + ); + } + + [Test] + public void CreateFromColumnsTest( ) + { + Vector3 column0 = new Vector3( 1, 4, 7 ); + Vector3 column1 = new Vector3( 2, 5, 8 ); + Vector3 column2 = new Vector3( 3, 6, 9 ); + Matrix3x3 matrix = Matrix3x3.CreateFromColumns( column0, column1, column2 ); + + float[] array = matrix.ToArray( ); + + for ( int i = 0; i < 9; i++ ) + { + Assert.AreEqual( array[i], (float) ( i + 1 ) ); + } + + Assert.AreEqual( column0, matrix.GetColumn( 0 ) ); + Assert.AreEqual( column1, matrix.GetColumn( 1 ) ); + Assert.AreEqual( column2, matrix.GetColumn( 2 ) ); + + Assert.Throws( ( ) => + { + matrix.GetColumn( -1 ); + } + ); + + Assert.Throws( ( ) => + { + matrix.GetColumn( 3 ); + } + ); + } + + + [TestCase( 0 )] + [TestCase( 30 )] + [TestCase( 45 )] + [TestCase( 60 )] + [TestCase( 90 )] + [TestCase( -30 )] + [TestCase( -90 )] + [TestCase( -180 )] + public void CreateRotationYTest( float angle ) + { + float radians = (float) ( angle * System.Math.PI / 180 ); + Matrix3x3 matrix = Matrix3x3.CreateRotationY( radians ); + + float sin = (float) System.Math.Sin( radians ); + float cos = (float) System.Math.Cos( radians ); + + float[] expectedArray = new float[9] + { + cos, 0, sin, 0, 1, 0, -sin, 0, cos + }; + + CompareMatrixWithArray( matrix, expectedArray ); + } + + + [TestCase( 0 )] + [TestCase( 30 )] + [TestCase( 45 )] + [TestCase( 60 )] + [TestCase( 90 )] + [TestCase( -30 )] + [TestCase( -90 )] + [TestCase( -180 )] + public void CreateRotationXTest( float angle ) + { + float radians = (float) ( angle * System.Math.PI / 180 ); + Matrix3x3 matrix = Matrix3x3.CreateRotationX( radians ); + + float sin = (float) System.Math.Sin( radians ); + float cos = (float) System.Math.Cos( radians ); + + float[] expectedArray = new float[9] + { + 1, 0, 0, 0, cos, -sin, 0, sin, cos + }; + + CompareMatrixWithArray( matrix, expectedArray ); + } + + + [TestCase( 0 )] + [TestCase( 30 )] + [TestCase( 45 )] + [TestCase( 60 )] + [TestCase( 90 )] + [TestCase( -30 )] + [TestCase( -90 )] + [TestCase( -180 )] + public void CreateRotationZTest( float angle ) + { + float radians = (float) ( angle * System.Math.PI / 180 ); + Matrix3x3 matrix = Matrix3x3.CreateRotationZ( radians ); + + float sin = (float) System.Math.Sin( radians ); + float cos = (float) System.Math.Cos( radians ); + + float[] expectedArray = new float[9] + { + cos, -sin, 0, sin, cos, 0, 0, 0, 1 + }; + + CompareMatrixWithArray( matrix, expectedArray ); + } + + + [TestCase( 0, 0, 0 )] + [TestCase( 30, 45, 60 )] + [TestCase( 45, 60, 30 )] + [TestCase( 60, 30, 45 )] + [TestCase( 90, 90, 90 )] + [TestCase( -30, -60, -90 )] + [TestCase( -90, -135, -180 )] + [TestCase( -180, -30, -60 )] + public void CreateFromYawPitchRollTest( float yaw, float pitch, float roll ) + { + float radiansYaw = (float) ( yaw * System.Math.PI / 180 ); + float radiansPitch = (float) ( pitch * System.Math.PI / 180 ); + float radiansRoll = (float) ( roll * System.Math.PI / 180 ); + + Matrix3x3 matrix = Matrix3x3.CreateFromYawPitchRoll( radiansYaw, radiansPitch, radiansRoll ); + + Matrix3x3 xMatrix = Matrix3x3.CreateRotationX( radiansPitch ); + Matrix3x3 yMatrix = Matrix3x3.CreateRotationY( radiansYaw ); + Matrix3x3 zMatrix = Matrix3x3.CreateRotationZ( radiansRoll ); + + Matrix3x3 rotationMatrix = ( yMatrix * xMatrix ) * zMatrix; + + CompareMatrixWithArray( matrix, rotationMatrix.ToArray( ) ); + } + + + [TestCase( 0, 0, 0 )] + [TestCase( 30, 45, 60 )] + [TestCase( 45, 60, 30 )] + [TestCase( 60, 30, 45 )] + [TestCase( -30, -60, -90 )] + public void ExtractYawPitchRollTest( float yaw, float pitch, float roll ) + { + float radiansYaw = (float) ( yaw * System.Math.PI / 180 ); + float radiansPitch = (float) ( pitch * System.Math.PI / 180 ); + float radiansRoll = (float) ( roll * System.Math.PI / 180 ); + + Matrix3x3 matrix = Matrix3x3.CreateFromYawPitchRoll( radiansYaw, radiansPitch, radiansRoll ); + + float extractedYaw; + float extractedPitch; + float extractedRoll; + + matrix.ExtractYawPitchRoll( out extractedYaw, out extractedPitch, out extractedRoll ); + + Assert.AreEqual( radiansYaw, extractedYaw, Epsilon ); + Assert.AreEqual( radiansPitch, extractedPitch, Epsilon ); + Assert.AreEqual( radiansRoll, extractedRoll, Epsilon ); + } + + + [TestCase( 1, 2, 3 )] + [TestCase( -1, -2, -3 )] + public void CreateDiagonalTest( float v00, float v11, float v22 ) + { + Vector3 diagonal = new Vector3( v00, v11, v22 ); + Matrix3x3 matrix = Matrix3x3.CreateDiagonal( diagonal ); + + float[] expectedArray = new float[9] { v00, 0, 0, 0, v11, 0, 0, 0, v22 }; + + CompareMatrixWithArray( matrix, expectedArray ); + } + + + [TestCase( 1, 1, 0, 0, 0, 1, 0, 0, 0, 1 )] + [TestCase( 0, 1, 0, 0, 0, 1, 0, 1, 0, 0 )] + [TestCase( 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 )] + [TestCase( -3, 1, 3, 2, 2, 2, 1, 2, 1, 1 )] + public void DeterminantTest( float expectedDeterminant, + float v00, float v01, float v02, + float v10, float v11, float v12, + float v20, float v21, float v22 ) + { + Matrix3x3 matrix = new Matrix3x3( ); + + matrix.V00 = v00; + matrix.V01 = v01; + matrix.V02 = v02; + + matrix.V10 = v10; + matrix.V11 = v11; + matrix.V12 = v12; + + matrix.V20 = v20; + matrix.V21 = v21; + matrix.V22 = v22; + + Assert.AreEqual( expectedDeterminant, matrix.Determinant ); + } + + + [TestCase( 1, 0, 0, 0, 1, 0, 0, 0, 1)] + [TestCase( 1, 0, 0, 0, 1, 0, 1, 0, 0, ExpectedException = typeof( ArgumentException ) )] + [TestCase( 2, 0, 0, 0, 4, 0, 0, 0, 3 )] + [TestCase( 1, 4, 2, 2, 2, 1, 2, 1, 1 )] + public void InverseTest( float v00, float v01, float v02, float v10, float v11, float v12, float v20, float v21, float v22 ) + { + Matrix3x3 matrix = new Matrix3x3( ); + + matrix.V00 = v00; + matrix.V01 = v01; + matrix.V02 = v02; + + matrix.V10 = v10; + matrix.V11 = v11; + matrix.V12 = v12; + + matrix.V20 = v20; + matrix.V21 = v21; + matrix.V22 = v22; + + Matrix3x3 inverse = matrix.Inverse( ); + Matrix3x3 identity = matrix * inverse; + + Assert.AreEqual( true, ApproximateEquals( identity, Matrix3x3.Identity ) ); + } + + [Test] + public void AddMatricesTest( ) + { + Matrix3x3 expectedResult = new Matrix3x3( ); + + expectedResult.V00 = 3; + expectedResult.V01 = 3; + expectedResult.V02 = 6; + + expectedResult.V10 = 4; + expectedResult.V11 = 5; + expectedResult.V12 = 3; + + expectedResult.V20 = 4; + expectedResult.V21 = 5; + expectedResult.V22 = 3; + + Matrix3x3 result = a1 + a2; + + Assert.AreEqual( true, ApproximateEquals( result, expectedResult ) ); + } + + [Test] + public void SubtractMatricesTest( ) + { + Matrix3x3 expectedResult = new Matrix3x3( ); + + expectedResult.V00 = -1; + expectedResult.V01 = 1; + expectedResult.V02 = 0; + + expectedResult.V10 = 2; + expectedResult.V11 = -1; + expectedResult.V12 = -1; + + expectedResult.V20 = -2; + expectedResult.V21 = 1; + expectedResult.V22 = 1; + + Matrix3x3 result = a1 - a2; + + Assert.AreEqual( true, ApproximateEquals( result, expectedResult ) ); + } + + [Test] + public void MultiplyMatricesTest( ) + { + Matrix3x3 expectedResult = new Matrix3x3( ); + + expectedResult.V00 = 13; + expectedResult.V01 = 13; + expectedResult.V02 = 10; + + expectedResult.V10 = 11; + expectedResult.V11 = 11; + expectedResult.V12 = 14; + + expectedResult.V20 = 11; + expectedResult.V21 = 14; + expectedResult.V22 = 11; + + Matrix3x3 result = a1 * a2; + + Assert.AreEqual( true, ApproximateEquals( result, expectedResult ) ); + } + + private void CompareMatrixWithArray( Matrix3x3 matrix, float[] array ) + { + float[] matrixArray = matrix.ToArray( ); + + for ( int i = 0; i < 9; i++ ) + { + Assert.AreEqual( matrixArray[i], array[i] ); + } + } + + private bool ApproximateEquals( Matrix3x3 matrix1, Matrix3x3 matrix2 ) + { + // TODO: better algorithm should be put into the framework actually + return ( + ( System.Math.Abs( matrix1.V00 - matrix2.V00 ) <= Epsilon ) && + ( System.Math.Abs( matrix1.V01 - matrix2.V01 ) <= Epsilon ) && + ( System.Math.Abs( matrix1.V02 - matrix2.V02 ) <= Epsilon ) && + + ( System.Math.Abs( matrix1.V10 - matrix2.V10 ) <= Epsilon ) && + ( System.Math.Abs( matrix1.V11 - matrix2.V11 ) <= Epsilon ) && + ( System.Math.Abs( matrix1.V12 - matrix2.V12 ) <= Epsilon ) && + + ( System.Math.Abs( matrix1.V20 - matrix2.V20 ) <= Epsilon ) && + ( System.Math.Abs( matrix1.V21 - matrix2.V21 ) <= Epsilon ) && + ( System.Math.Abs( matrix1.V22 - matrix2.V22 ) <= Epsilon ) + ); + } + } +} diff --git a/Unit Tests/Accord.Tests.Math/AForge/Matrix4x4Test.cs b/Unit Tests/Accord.Tests.Math/AForge/Matrix4x4Test.cs new file mode 100644 index 0000000000..0b2a605b3 --- /dev/null +++ b/Unit Tests/Accord.Tests.Math/AForge/Matrix4x4Test.cs @@ -0,0 +1,437 @@ +using System; +using AForge; +using AForge.Math; +using NUnit.Framework; + +namespace AForge.Math.Tests +{ + [TestFixture] + public class Matrix4x4Test + { + private const float Epsilon = 0.000001f; + + private Matrix4x4 a1 = new Matrix4x4( ); + private Matrix4x4 a2 = new Matrix4x4( ); + + public Matrix4x4Test( ) + { + // prepare 1st argument + a1.V00 = 1; + a1.V01 = 2; + a1.V02 = 3; + a1.V03 = 4; + + a1.V10 = 4; + a1.V11 = 3; + a1.V12 = 2; + a1.V13 = 1; + + a1.V20 = 3; + a1.V21 = 1; + a1.V22 = 4; + a1.V23 = 2; + + a1.V30 = 2; + a1.V31 = 4; + a1.V32 = 1; + a1.V33 = 3; + + // prepare 2nd argument + a2.V00 = 2; + a2.V01 = 1; + a2.V02 = 4; + a2.V03 = 3; + + a2.V10 = 4; + a2.V11 = 2; + a2.V12 = 3; + a2.V13 = 1; + + a2.V20 = 3; + a2.V21 = 4; + a2.V22 = 1; + a2.V23 = 2; + + a2.V30 = 1; + a2.V31 = 3; + a2.V32 = 2; + a2.V33 = 4; + } + + [Test] + public void ToArrayTest( ) + { + Matrix4x4 matrix = new Matrix4x4( ); + + matrix.V00 = 1; + matrix.V01 = 2; + matrix.V02 = 3; + matrix.V03 = 4; + + matrix.V10 = 5; + matrix.V11 = 6; + matrix.V12 = 7; + matrix.V13 = 8; + + matrix.V20 = 9; + matrix.V21 = 10; + matrix.V22 = 11; + matrix.V23 = 12; + + matrix.V30 = 13; + matrix.V31 = 14; + matrix.V32 = 15; + matrix.V33 = 16; + + float[] array = matrix.ToArray( ); + + for ( int i = 0; i < 16; i++ ) + { + Assert.AreEqual( array[i], (float) ( i + 1 ) ); + } + } + + [Test] + public void CreateFromRowsTest( ) + { + Vector4 row0 = new Vector4( 1, 2, 3, 4 ); + Vector4 row1 = new Vector4( 5, 6, 7, 8 ); + Vector4 row2 = new Vector4( 9, 10, 11, 12 ); + Vector4 row3 = new Vector4( 13, 14, 15, 16 ); + Matrix4x4 matrix = Matrix4x4.CreateFromRows( row0, row1, row2, row3 ); + + float[] array = matrix.ToArray( ); + + for ( int i = 0; i < 16; i++ ) + { + Assert.AreEqual( array[i], (float) ( i + 1 ) ); + } + + Assert.AreEqual( row0, matrix.GetRow( 0 ) ); + Assert.AreEqual( row1, matrix.GetRow( 1 ) ); + Assert.AreEqual( row2, matrix.GetRow( 2 ) ); + Assert.AreEqual( row3, matrix.GetRow( 3 ) ); + + + Assert.Throws( ( ) => + { + matrix.GetRow( -1 ); + } + ); + + Assert.Throws( ( ) => + { + matrix.GetRow( 4 ); + } + ); + } + + [Test] + public void CreateFromColumnsTest( ) + { + Vector4 column0 = new Vector4( 1, 5, 9, 13 ); + Vector4 column1 = new Vector4( 2, 6, 10, 14 ); + Vector4 column2 = new Vector4( 3, 7, 11, 15 ); + Vector4 column3 = new Vector4( 4, 8, 12, 16 ); + Matrix4x4 matrix = Matrix4x4.CreateFromColumns( column0, column1, column2, column3 ); + + float[] array = matrix.ToArray( ); + + for ( int i = 0; i < 16; i++ ) + { + Assert.AreEqual( array[i], (float) ( i + 1 ) ); + } + + Assert.AreEqual( column0, matrix.GetColumn( 0 ) ); + Assert.AreEqual( column1, matrix.GetColumn( 1 ) ); + Assert.AreEqual( column2, matrix.GetColumn( 2 ) ); + Assert.AreEqual( column3, matrix.GetColumn( 3 ) ); + + Assert.Throws( ( ) => + { + matrix.GetColumn( -1 ); + } + ); + + Assert.Throws( ( ) => + { + matrix.GetColumn( 4 ); + } + ); + } + + + [TestCase( 0 )] + [TestCase( 30 )] + [TestCase( 45 )] + [TestCase( 60 )] + [TestCase( 90 )] + [TestCase( -30 )] + [TestCase( -90 )] + [TestCase( -180 )] + public void CreateRotationYTest( float angle ) + { + float radians = (float) ( angle * System.Math.PI / 180 ); + Matrix4x4 matrix = Matrix4x4.CreateRotationY( radians ); + + float sin = (float) System.Math.Sin( radians ); + float cos = (float) System.Math.Cos( radians ); + + float[] expectedArray = new float[16] + { + cos, 0, sin, 0, + 0, 1, 0, 0, + -sin, 0, cos, 0, + 0, 0, 0, 1 + }; + + CompareMatrixWithArray( matrix, expectedArray ); + } + + + [TestCase( 0 )] + [TestCase( 30 )] + [TestCase( 45 )] + [TestCase( 60 )] + [TestCase( 90 )] + [TestCase( -30 )] + [TestCase( -90 )] + [TestCase( -180 )] + public void CreateRotationXTest( float angle ) + { + float radians = (float) ( angle * System.Math.PI / 180 ); + Matrix4x4 matrix = Matrix4x4.CreateRotationX( radians ); + + float sin = (float) System.Math.Sin( radians ); + float cos = (float) System.Math.Cos( radians ); + + float[] expectedArray = new float[16] + { + 1, 0, 0, 0, + 0, cos, -sin, 0, + 0, sin, cos, 0, + 0, 0, 0, 1 + }; + + CompareMatrixWithArray( matrix, expectedArray ); + } + + + [TestCase( 0 )] + [TestCase( 30 )] + [TestCase( 45 )] + [TestCase( 60 )] + [TestCase( 90 )] + [TestCase( -30 )] + [TestCase( -90 )] + [TestCase( -180 )] + public void CreateRotationZTest( float angle ) + { + float radians = (float) ( angle * System.Math.PI / 180 ); + Matrix4x4 matrix = Matrix4x4.CreateRotationZ( radians ); + + float sin = (float) System.Math.Sin( radians ); + float cos = (float) System.Math.Cos( radians ); + + float[] expectedArray = new float[16] + { + cos, -sin, 0, 0, + sin, cos, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1, + }; + + CompareMatrixWithArray( matrix, expectedArray ); + } + + + [TestCase( 0, 0, 0 )] + [TestCase( 30, 45, 60 )] + [TestCase( 45, 60, 30 )] + [TestCase( 60, 30, 45 )] + [TestCase( 90, 90, 90 )] + [TestCase( -30, -60, -90 )] + [TestCase( -90, -135, -180 )] + [TestCase( -180, -30, -60 )] + public void CreateFromYawPitchRollTest( float yaw, float pitch, float roll ) + { + float radiansYaw = (float) ( yaw * System.Math.PI / 180 ); + float radiansPitch = (float) ( pitch * System.Math.PI / 180 ); + float radiansRoll = (float) ( roll * System.Math.PI / 180 ); + + Matrix4x4 matrix = Matrix4x4.CreateFromYawPitchRoll( radiansYaw, radiansPitch, radiansRoll ); + + Matrix4x4 xMatrix = Matrix4x4.CreateRotationX( radiansPitch ); + Matrix4x4 yMatrix = Matrix4x4.CreateRotationY( radiansYaw ); + Matrix4x4 zMatrix = Matrix4x4.CreateRotationZ( radiansRoll ); + + Matrix4x4 rotationMatrix = ( yMatrix * xMatrix ) * zMatrix; + + CompareMatrixWithArray( matrix, rotationMatrix.ToArray( ) ); + } + + + [TestCase( 0, 0, 0 )] + [TestCase( 30, 45, 60 )] + [TestCase( 45, 60, 30 )] + [TestCase( 60, 30, 45 )] + [TestCase( -30, -60, -90 )] + public void ExtractYawPitchRollTest( float yaw, float pitch, float roll ) + { + float radiansYaw = (float) ( yaw * System.Math.PI / 180 ); + float radiansPitch = (float) ( pitch * System.Math.PI / 180 ); + float radiansRoll = (float) ( roll * System.Math.PI / 180 ); + + Matrix4x4 matrix = Matrix4x4.CreateFromYawPitchRoll( radiansYaw, radiansPitch, radiansRoll ); + + float extractedYaw; + float extractedPitch; + float extractedRoll; + + matrix.ExtractYawPitchRoll( out extractedYaw, out extractedPitch, out extractedRoll ); + + Assert.AreEqual( radiansYaw, extractedYaw, Epsilon ); + Assert.AreEqual( radiansPitch, extractedPitch, Epsilon ); + Assert.AreEqual( radiansRoll, extractedRoll, Epsilon ); + } + + + [TestCase( 1, 2, 3, 4 )] + [TestCase( -1, -2, -3, -4 )] + public void CreateDiagonalTest( float v00, float v11, float v22, float v33 ) + { + Vector4 diagonal = new Vector4( v00, v11, v22, v33 ); + Matrix4x4 matrix = Matrix4x4.CreateDiagonal( diagonal ); + + float[] expectedArray = new float[16] { v00, 0, 0, 0, 0, v11, 0, 0, 0, 0, v22, 0, 0, 0, 0, v33 }; + + CompareMatrixWithArray( matrix, expectedArray ); + } + + [Test] + public void AddMatricesTest( ) + { + Matrix4x4 expectedResult = new Matrix4x4( ); + + expectedResult.V00 = 3; + expectedResult.V01 = 3; + expectedResult.V02 = 7; + expectedResult.V03 = 7; + + expectedResult.V10 = 8; + expectedResult.V11 = 5; + expectedResult.V12 = 5; + expectedResult.V13 = 2; + + expectedResult.V20 = 6; + expectedResult.V21 = 5; + expectedResult.V22 = 5; + expectedResult.V23 = 4; + + expectedResult.V30 = 3; + expectedResult.V31 = 7; + expectedResult.V32 = 3; + expectedResult.V33 = 7; + + Matrix4x4 result = a1 + a2; + + Assert.AreEqual( true, ApproximateEquals( result, expectedResult ) ); + } + + [Test] + public void SubtractMatricesTest( ) + { + Matrix4x4 expectedResult = new Matrix4x4( ); + + expectedResult.V00 = -1; + expectedResult.V01 = 1; + expectedResult.V02 = -1; + expectedResult.V03 = 1; + + expectedResult.V10 = 0; + expectedResult.V11 = 1; + expectedResult.V12 = -1; + expectedResult.V13 = 0; + + expectedResult.V20 = 0; + expectedResult.V21 = -3; + expectedResult.V22 = 3; + expectedResult.V23 = 0; + + expectedResult.V30 = 1; + expectedResult.V31 = 1; + expectedResult.V32 = -1; + expectedResult.V33 = -1; + + Matrix4x4 result = a1 - a2; + + Assert.AreEqual( true, ApproximateEquals( result, expectedResult ) ); + } + + [Test] + public void MultiplyMatricesTest( ) + { + Matrix4x4 expectedResult = new Matrix4x4( ); + + expectedResult.V00 = 23; + expectedResult.V01 = 29; + expectedResult.V02 = 21; + expectedResult.V03 = 27; + + expectedResult.V10 = 27; + expectedResult.V11 = 21; + expectedResult.V12 = 29; + expectedResult.V13 = 23; + + expectedResult.V20 = 24; + expectedResult.V21 = 27; + expectedResult.V22 = 23; + expectedResult.V23 = 26; + + expectedResult.V30 = 26; + expectedResult.V31 = 23; + expectedResult.V32 = 27; + expectedResult.V33 = 24; + + Matrix4x4 result = a1 * a2; + + Assert.AreEqual( true, ApproximateEquals( result, expectedResult ) ); + } + + private void CompareMatrixWithArray( Matrix4x4 matrix, float[] array ) + { + float[] matrixArray = matrix.ToArray( ); + + for ( int i = 0; i < 16; i++ ) + { + Assert.AreEqual( matrixArray[i], array[i] ); + } + } + + private bool ApproximateEquals( Matrix4x4 matrix1, Matrix4x4 matrix2 ) + { + // TODO: better algorithm should be put into the framework actually + return ( + ( System.Math.Abs( matrix1.V00 - matrix2.V00 ) <= Epsilon ) && + ( System.Math.Abs( matrix1.V01 - matrix2.V01 ) <= Epsilon ) && + ( System.Math.Abs( matrix1.V02 - matrix2.V02 ) <= Epsilon ) && + ( System.Math.Abs( matrix1.V03 - matrix2.V03 ) <= Epsilon ) && + + ( System.Math.Abs( matrix1.V10 - matrix2.V10 ) <= Epsilon ) && + ( System.Math.Abs( matrix1.V11 - matrix2.V11 ) <= Epsilon ) && + ( System.Math.Abs( matrix1.V12 - matrix2.V12 ) <= Epsilon ) && + ( System.Math.Abs( matrix1.V13 - matrix2.V13 ) <= Epsilon ) && + + ( System.Math.Abs( matrix1.V20 - matrix2.V20 ) <= Epsilon ) && + ( System.Math.Abs( matrix1.V21 - matrix2.V21 ) <= Epsilon ) && + ( System.Math.Abs( matrix1.V22 - matrix2.V22 ) <= Epsilon ) && + ( System.Math.Abs( matrix1.V23 - matrix2.V23 ) <= Epsilon ) && + + ( System.Math.Abs( matrix1.V30 - matrix2.V30 ) <= Epsilon ) && + ( System.Math.Abs( matrix1.V31 - matrix2.V31 ) <= Epsilon ) && + ( System.Math.Abs( matrix1.V32 - matrix2.V32 ) <= Epsilon ) && + ( System.Math.Abs( matrix1.V33 - matrix2.V33 ) <= Epsilon ) + ); + } + } +} diff --git a/Unit Tests/Accord.Tests.Math/AForge/Metrics/MetricsTest.cs b/Unit Tests/Accord.Tests.Math/AForge/Metrics/MetricsTest.cs new file mode 100644 index 0000000000..583c4b953 --- /dev/null +++ b/Unit Tests/Accord.Tests.Math/AForge/Metrics/MetricsTest.cs @@ -0,0 +1,239 @@ +using System; +using System.Collections.Generic; +using AForge; +using AForge.Math.Metrics; +using NUnit.Framework; + +namespace AForge.Math.Metrics.Tests +{ + [TestFixture] + public class MetricsTest + { + // test data + private double[] p0 = new double[] { 1, 0.5 }; + private double[] q0 = new double[] { 0.5, 1 }; + + private double[] p1 = new double[] { 4.5, 1 }; + private double[] q1 = new double[] { 4, 2 }; + + private double[] p2 = new double[] { 0, 0, 0 }; + private double[] q2 = new double[] { 0, 0, 0 }; + + private double[] p3 = new double[] { 1, 1, 1 }; + private double[] q3 = new double[] { 1, 1, 1 }; + + private double[] p4 = new double[] { 2.5, 3.5, 3.0, 3.5, 2.5, 3.0 }; + private double[] q4 = new double[] { 3.0, 3.5, 1.5, 5.0, 3.5, 3.0 }; + + private double[] p5 = new double[] { 1, 3, 5, 6, 8, 9, 6, 4, 3, 2 }; + private double[] q5 = new double[] { 2, 5, 6, 6, 7, 7, 5, 3, 1, 1 }; + + [Test] + public void CosineDistanceTest( ) + { + CosineDistance dist = new CosineDistance( ); + + Assert.Throws( ( ) => dist.GetDistance( p0, q4 ) ); + + double result = dist.GetDistance( p0, q0 ); + Assert.AreEqual( result, .2, 0.00001 ); + + result = dist.GetDistance( p1, q1 ); + Assert.AreEqual( result, 0.029857, 0.00001 ); + + result = dist.GetDistance( p2, q2 ); + Assert.AreEqual( result, 1 ); + + result = dist.GetDistance( p3, q3 ); + Assert.AreEqual( result, 0, 0.00001 ); + + result = dist.GetDistance( p4, q4 ); + Assert.AreEqual( result, 0.039354, 0.00001 ); + + result = dist.GetDistance( p5, q5 ); + Assert.AreEqual( result, 0.031026, 0.00001 ); + } + + [Test] + public void CosineSimilarityTest( ) + { + CosineSimilarity sim = new CosineSimilarity( ); + + Assert.Throws( ( ) => sim.GetSimilarityScore( p0, q4 ) ); + + double result = sim.GetSimilarityScore( p0, q0 ); + Assert.AreEqual( result, .8, 0.00001 ); + + result = sim.GetSimilarityScore( p1, q1 ); + Assert.AreEqual( result, 0.97014, 0.00001 ); + + result = sim.GetSimilarityScore( p2, q2 ); + Assert.AreEqual( result, 0 ); + + result = sim.GetSimilarityScore( p3, q3 ); + Assert.AreEqual( result, 1, 0.00001 ); + + result = sim.GetSimilarityScore( p4, q4 ); + Assert.AreEqual( result, 0.96065, 0.00001 ); + + result = sim.GetSimilarityScore( p5, q5 ); + Assert.AreEqual( result, 0.96897, 0.00001 ); + } + + [Test] + public void EuclideanDistanceTest( ) + { + EuclideanDistance dist = new EuclideanDistance( ); + + Assert.Throws( ( ) => dist.GetDistance( p0, q4 ) ); + + double result = dist.GetDistance( p0, q0 ); + Assert.AreEqual( result, .70711, 0.00001 ); + + result = dist.GetDistance( p1, q1 ); + Assert.AreEqual( result, 1.11803, 0.00001 ); + + result = dist.GetDistance( p2, q2 ); + Assert.AreEqual( result, 0 ); + + result = dist.GetDistance( p3, q3 ); + Assert.AreEqual( result, 0 ); + + result = dist.GetDistance( p4, q4 ); + Assert.AreEqual( result, 2.39792, 0.00001 ); + + result = dist.GetDistance( p5, q5 ); + Assert.AreEqual( result, 4.24264, 0.00001 ); + } + + [Test] + public void EuclideanSimilarityTest( ) + { + EuclideanSimilarity sim = new EuclideanSimilarity( ); + + Assert.Throws( ( ) => sim.GetSimilarityScore( p0, q4 ) ); + + double result = sim.GetSimilarityScore( p0, q0 ); + Assert.AreEqual( result, 0.58578, 0.00001 ); + + result = sim.GetSimilarityScore( p1, q1 ); + Assert.AreEqual( result, 0.47213, 0.00001 ); + + result = sim.GetSimilarityScore( p2, q2 ); + Assert.AreEqual( result, 1 ); + + result = sim.GetSimilarityScore( p3, q3 ); + Assert.AreEqual( result, 1 ); + + result = sim.GetSimilarityScore( p4, q4 ); + Assert.AreEqual( result, 0.2943, 0.00001 ); + + result = sim.GetSimilarityScore( p5, q5 ); + Assert.AreEqual( result, 0.19074, 0.00001 ); + } + + [Test] + public void HammingDistanceTest( ) + { + HammingDistance dist = new HammingDistance( ); + + Assert.Throws( ( ) => dist.GetDistance( p0, q4 ) ); + + double result = dist.GetDistance( p0, q0 ); + Assert.AreEqual( result, 2 ); + + result = dist.GetDistance( p1, q1 ); + Assert.AreEqual( result, 2 ); + + result = dist.GetDistance( p2, q2 ); + Assert.AreEqual( result, 0 ); + + result = dist.GetDistance( p3, q3 ); + Assert.AreEqual( result, 0 ); + + result = dist.GetDistance( p4, q4 ); + Assert.AreEqual( result, 4 ); + + result = dist.GetDistance( p5, q5 ); + Assert.AreEqual( result, 9 ); + } + + [Test] + public void JaccardDistanceTest( ) + { + JaccardDistance dist = new JaccardDistance( ); + + Assert.Throws( ( ) => dist.GetDistance( p0, q4 ) ); + + double result = dist.GetDistance( p0, q0 ); + Assert.AreEqual( result, 1 ); + + result = dist.GetDistance( p1, q1 ); + Assert.AreEqual( result, 1 ); + + result = dist.GetDistance( p2, q2 ); + Assert.AreEqual( result, 0 ); + + result = dist.GetDistance( p3, q3 ); + Assert.AreEqual( result, 0 ); + + result = dist.GetDistance( p4, q4 ); + Assert.AreEqual( result, 0.66666, 0.00001 ); + + result = dist.GetDistance( p5, q5 ); + Assert.AreEqual( result, 0.9, 0.1 ); + } + + [Test] + public void ManhattanDistanceTest( ) + { + ManhattanDistance dist = new ManhattanDistance( ); + + Assert.Throws( ( ) => dist.GetDistance( p0, q4 ) ); + + double result = dist.GetDistance( p0, q0 ); + Assert.AreEqual( result, 1 ); + + result = dist.GetDistance( p1, q1 ); + Assert.AreEqual( result, 1.5 ); + + result = dist.GetDistance( p2, q2 ); + Assert.AreEqual( result, 0 ); + + result = dist.GetDistance( p3, q3 ); + Assert.AreEqual( result, 0 ); + + result = dist.GetDistance( p4, q4 ); + Assert.AreEqual( result, 4.5 ); + + result = dist.GetDistance( p5, q5 ); + Assert.AreEqual( result, 12 ); + } + + [Test] + public void PearsonCorrelationTest( ) + { + PearsonCorrelation sim = new PearsonCorrelation( ); + + Assert.Throws( ( ) => sim.GetSimilarityScore( p0, q4 ) ); + + double result = sim.GetSimilarityScore( p0, q0 ); + Assert.AreEqual( result, -1 ); + + result = sim.GetSimilarityScore( p1, q1 ); + Assert.AreEqual( result, 1 ); + + result = sim.GetSimilarityScore( p2, q2 ); + Assert.AreEqual( result, 0 ); + + result = sim.GetSimilarityScore( p3, q3 ); + Assert.AreEqual( result, 0 ); + + result = sim.GetSimilarityScore( p4, q4 ); + Assert.AreEqual( result, 0.396059, 0.00001 ); + + result = sim.GetSimilarityScore( p5, q5 ); + Assert.AreEqual( result, 0.85470, 0.00001 ); + } + } +} diff --git a/Unit Tests/Accord.Tests.Math/AForge/StatisticsTest.cs b/Unit Tests/Accord.Tests.Math/AForge/StatisticsTest.cs new file mode 100644 index 0000000000..2a1f2f23c --- /dev/null +++ b/Unit Tests/Accord.Tests.Math/AForge/StatisticsTest.cs @@ -0,0 +1,35 @@ +using System; +using AForge; +using AForge.Math; +using NUnit.Framework; + +namespace AForge.Math.Tests +{ + [TestFixture] + public class StatisticsTest + { + [Test] + public void ModeTest( ) + { + int[] values = new int[] { 1, 2, 2, 3, 3, 3 }; + int mode = Statistics.Mode( values ); + Assert.AreEqual( 3, mode ); + + values = new int[] { 1, 1, 1, 2, 2, 2 }; + mode = Statistics.Mode( values ); + Assert.AreEqual( 3, mode ); + + values = new int[] { 2, 2, 2, 1, 1, 1 }; + mode = Statistics.Mode( values ); + Assert.AreEqual( 0, mode ); + + values = new int[] { 0, 0, 0, 0, 0, 0 }; + mode = Statistics.Mode( values ); + Assert.AreEqual( 0, mode ); + + values = new int[] { 1, 1, 2, 3, 6, 8, 11, 12, 7, 3 }; + mode = Statistics.Mode( values ); + Assert.AreEqual( 7, mode ); + } + } +} diff --git a/Unit Tests/Accord.Tests.Math/AForge/ToolsTest.cs b/Unit Tests/Accord.Tests.Math/AForge/ToolsTest.cs new file mode 100644 index 0000000000..df33b7570 --- /dev/null +++ b/Unit Tests/Accord.Tests.Math/AForge/ToolsTest.cs @@ -0,0 +1,32 @@ +using System; +using AForge; +using AForge.Math; +using NUnit.Framework; + +namespace AForge.Math.Tests +{ + [TestFixture] + public class ToolsTest + { + + [TestCase( 0, false )] + [TestCase( 1, true )] + [TestCase( 2, true )] + [TestCase( 3, false )] + [TestCase( 4, true )] + [TestCase( 8, true )] + [TestCase( 0x80, true )] + [TestCase( 0x81, false )] + [TestCase( 0x8000, true )] + [TestCase( 0x8001, false )] + [TestCase( 0x40000000, true )] + [TestCase( 0x3FFFFFFF, false )] + [TestCase( -1, false )] + [TestCase( -8, false )] + [TestCase( int.MinValue, false )] + public void IsPowerOf2Test( int valueToTest, bool expectedResult ) + { + Assert.AreEqual( expectedResult, Tools.IsPowerOf2( valueToTest ) ); + } + } +} diff --git a/Unit Tests/Accord.Tests.Math/AForge/Vector3Test.cs b/Unit Tests/Accord.Tests.Math/AForge/Vector3Test.cs new file mode 100644 index 0000000000..5b4485769 --- /dev/null +++ b/Unit Tests/Accord.Tests.Math/AForge/Vector3Test.cs @@ -0,0 +1,281 @@ +using System; +using AForge; +using AForge.Math; +using NUnit.Framework; + +namespace AForge.Math.Tests +{ + [TestFixture] + public class Vector3Test + { + [Test] + public void ConstructorTest( ) + { + Vector3 v1 = new Vector3( 1, 2, 3 ); + Vector3 v2 = new Vector3( -1, -2, -3 ); + Vector3 v3 = new Vector3( 7 ); + + Assert.AreEqual( v1.X, 1 ); + Assert.AreEqual( v1.Y, 2 ); + Assert.AreEqual( v1.Z, 3 ); + + Assert.AreEqual( v2.X, -1 ); + Assert.AreEqual( v2.Y, -2 ); + Assert.AreEqual( v2.Z, -3 ); + + Assert.AreEqual( v3.X, 7 ); + Assert.AreEqual( v3.Y, 7 ); + Assert.AreEqual( v3.Z, 7 ); + } + + + [TestCase( 0, 0, 0, 0, 0, 0, 0 )] + [TestCase( 0, 7, 7, 0, 7, 0, 1 )] + [TestCase( 0, 0, 7, 0, 7, 0, 2 )] + [TestCase( 0, 7, 0, 0, 7, 0, 1 )] + [TestCase( 7, 0, 7, 0, 7, 1, 0 )] + [TestCase( 5, 7, 9, 5, 9, 0, 2 )] + [TestCase( 5, 9, 7, 5, 9, 0, 1 )] + [TestCase( 7, 5, 9, 5, 9, 1, 2 )] + [TestCase( 7, 9, 5, 5, 9, 2, 1 )] + [TestCase( 9, 5, 7, 5, 9, 1, 0 )] + [TestCase( 9, 7, 5, 5, 9, 2, 0 )] + public void MinMaxTest( float x, float y, float z, float expectedMin, float expectedMax, + int expectedMinIndex, int expectedMaxIndex ) + { + Vector3 vector = new Vector3( x, y, z ); + + Assert.AreEqual( vector.Min, expectedMin ); + Assert.AreEqual( vector.Max, expectedMax ); + + Assert.AreEqual( vector.MinIndex, expectedMinIndex ); + Assert.AreEqual( vector.MaxIndex, expectedMaxIndex ); + } + + + [TestCase( 0, 0, 0, 0 )] + [TestCase( 1, 0, 0, 1 )] + [TestCase( 0, 2, 0, 2 )] + [TestCase( 0, 0, 3, 3 )] + [TestCase( 3, 4, 0, 5 )] + [TestCase( -3, -4, 0, 5 )] + public void NormTest( float x, float y, float z, float expectedNorm ) + { + Vector3 vector = new Vector3( x, y, z ); + + float norm = vector.Norm; + + Assert.AreEqual( norm, expectedNorm ); + Assert.AreEqual( norm * norm, vector.Square ); + } + + + [TestCase( 1, 2, 3, 1, 2, 3, true )] + [TestCase( -1, -2, -3, -1, -2, -3, true )] + [TestCase( -1, -2, -3, -1, -2, 3, false )] + public void EqualityTest( float x1, float y1, float z1, float x2, float y2, float z2, bool expected ) + { + Vector3 vector1 = new Vector3( x1, y1, z1 ); + Vector3 vector2 = new Vector3( x2, y2, z2 ); + + Assert.AreEqual( vector1 == vector2, expected ); + Assert.AreEqual( vector1 != vector2, !expected ); + + Assert.AreEqual( vector1.Equals( vector2 ), expected ); + Assert.AreEqual( vector1.Equals( (object) vector2 ), expected ); + } + + + [TestCase( 1, 2, 3, 4, 5, 6, 5, 7, 9 )] + [TestCase( 1, 2, 3, -4, -5, -6, -3, -3, -3 )] + public void AdditionTest( float x1, float y1, float z1, float x2, float y2, float z2, + float expectedX, float expectedY, float expectedZ ) + { + Vector3 vector1 = new Vector3( x1, y1, z1 ); + Vector3 vector2 = new Vector3( x2, y2, z2 ); + Vector3 expectedResult = new Vector3( expectedX, expectedY, expectedZ ); + + Vector3 result1 = vector1 + vector2; + Vector3 result2 = Vector3.Add( vector1, vector2 ); + + Assert.AreEqual( expectedResult == result1, true ); + Assert.AreEqual( expectedResult == result2, true ); + } + + + [TestCase( 1, 2, 3, 4, 5, 6, 7 )] + [TestCase( 1, 2, 3, -4, -3, -2, -1 )] + public void AdditionWithConstTest( float x, float y, float z, float value, + float expectedX, float expectedY, float expectedZ ) + { + Vector3 vector = new Vector3( x, y, z ); + Vector3 expectedResult = new Vector3( expectedX, expectedY, expectedZ ); + + Vector3 result1 = vector + value; + Vector3 result2 = Vector3.Add( vector, value ); + + Assert.AreEqual( expectedResult == result1, true ); + Assert.AreEqual( expectedResult == result2, true ); + } + + + [TestCase( 1, 2, 3, 4, 5, 6, -3, -3, -3 )] + [TestCase( 1, 2, 3, -4, -5, -6, 5, 7, 9 )] + public void SubtractionTest( float x1, float y1, float z1, float x2, float y2, float z2, + float expectedX, float expectedY, float expectedZ ) + { + Vector3 vector1 = new Vector3( x1, y1, z1 ); + Vector3 vector2 = new Vector3( x2, y2, z2 ); + Vector3 expectedResult = new Vector3( expectedX, expectedY, expectedZ ); + + Vector3 result1 = vector1 - vector2; + Vector3 result2 = Vector3.Subtract( vector1, vector2 ); + + Assert.AreEqual( expectedResult == result1, true ); + Assert.AreEqual( expectedResult == result2, true ); + } + + + [TestCase( 1, 2, 3, 4, -3, -2, -1 )] + [TestCase( 1, 2, 3, -4, 5, 6, 7 )] + public void SubtractionWithConstTest( float x, float y, float z, float value, + float expectedX, float expectedY, float expectedZ ) + { + Vector3 vector = new Vector3( x, y, z ); + Vector3 expectedResult = new Vector3( expectedX, expectedY, expectedZ ); + + Vector3 result1 = vector - value; + Vector3 result2 = Vector3.Subtract( vector, value ); + + Assert.AreEqual( expectedResult == result1, true ); + Assert.AreEqual( expectedResult == result2, true ); + } + + + [TestCase( 1, 2, 3, 4, 5, 6, 4, 10, 18 )] + [TestCase( 1, 2, 3, -4, -5, -6, -4, -10, -18 )] + public void MultiplicationTest( float x1, float y1, float z1, float x2, float y2, float z2, + float expectedX, float expectedY, float expectedZ ) + { + Vector3 vector1 = new Vector3( x1, y1, z1 ); + Vector3 vector2 = new Vector3( x2, y2, z2 ); + Vector3 expectedResult = new Vector3( expectedX, expectedY, expectedZ ); + + Vector3 result1 = vector1 * vector2; + Vector3 result2 = Vector3.Multiply( vector1, vector2 ); + + Assert.AreEqual( expectedResult == result1, true ); + Assert.AreEqual( expectedResult == result2, true ); + } + + + [TestCase( 1, 2, 3, 4, 4, 8, 12 )] + [TestCase( 1, 2, 3, -4, -4, -8, -12 )] + public void MultiplicationWithConstTest( float x, float y, float z, float value, + float expectedX, float expectedY, float expectedZ ) + { + Vector3 vector = new Vector3( x, y, z ); + Vector3 expectedResult = new Vector3( expectedX, expectedY, expectedZ ); + + Vector3 result1 = vector * value; + Vector3 result2 = Vector3.Multiply( vector, value ); + + Assert.AreEqual( expectedResult == result1, true ); + Assert.AreEqual( expectedResult == result2, true ); + } + + + [TestCase( 1f, 2f, 3f, 1f, 4f, 2f, 1f, 0.5f, 1.5f )] + [TestCase( 1f, 2f, 3f, -1f, -4f, -2f, -1f, -0.5f, -1.5f )] + public void DivisionTest( float x1, float y1, float z1, float x2, float y2, float z2, + float expectedX, float expectedY, float expectedZ ) + { + Vector3 vector1 = new Vector3( x1, y1, z1 ); + Vector3 vector2 = new Vector3( x2, y2, z2 ); + Vector3 expectedResult = new Vector3( expectedX, expectedY, expectedZ ); + + Vector3 result1 = vector1 / vector2; + Vector3 result2 = Vector3.Divide( vector1, vector2 ); + + Assert.AreEqual( expectedResult == result1, true ); + Assert.AreEqual( expectedResult == result2, true ); + } + + + [TestCase( 1f, 2f, 3f, 2f, 0.5f, 1f, 1.5f )] + [TestCase( 1f, 2f, 3f, -2f, -0.5f, -1f, -1.5f )] + public void DivisionWithConstTest( float x, float y, float z, float value, + float expectedX, float expectedY, float expectedZ ) + { + Vector3 vector = new Vector3( x, y, z ); + Vector3 expectedResult = new Vector3( expectedX, expectedY, expectedZ ); + + Vector3 result1 = vector / value; + Vector3 result2 = Vector3.Divide( vector, value ); + + Assert.AreEqual( expectedResult == result1, true ); + Assert.AreEqual( expectedResult == result2, true ); + } + + + [TestCase( 1, 0, 0, 1, 0, 0 )] + [TestCase( 0, 1, 0, 0, 1, 0 )] + [TestCase( 0, 0, 1, 0, 0, 1 )] + [TestCase( 3f, 4f, 0f, 0.6f, 0.8f, 0f )] + [TestCase( 3f, 0f, 4f, 0.6f, 0f, 0.8f )] + public void NormalizeTest( float x, float y, float z, float expectedX, float expectedY, float expectedZ ) + { + Vector3 vector = new Vector3( x, y, z ); + Vector3 expectedResult = new Vector3( expectedX, expectedY, expectedZ ); + + float norm1 = vector.Norm; + float norm2 = vector.Normalize( ); + + Assert.AreEqual( expectedResult == vector, true ); + Assert.AreEqual( norm1, norm2 ); + } + + + [TestCase( 1, 0, 0, 1, 0, 0 )] + [TestCase( 0, 0, 0, 0, 0, 0 )] + [TestCase( 2f, 4f, 8f, 0.5f, 0.25f, 0.125f )] + [TestCase( -2f, -4f, -8f, -0.5f, -0.25f, -0.125f )] + [TestCase( 0.5f, 0.25f, 0.125f, 2f, 4f, 8f )] + public void InverseTest( float x, float y, float z, float expectedX, float expectedY, float expectedZ ) + { + Vector3 vector = new Vector3( x, y, z ); + Vector3 expectedResult = new Vector3( expectedX, expectedY, expectedZ ); + + Vector3 result = vector.Inverse( ); + + Assert.AreEqual( expectedResult == result, true ); + } + + + [TestCase( 1, 2, 3, 0, 0, 0, 0 )] + [TestCase( 1, 2, 3, 1, 1, 1, 6 )] + [TestCase( 1, 2, 3, 3, 2, 1, 10 )] + [TestCase( 1, 2, 3, -3, -2, -1, -10 )] + public void DotTest( float x1, float y1, float z1, float x2, float y2, float z2, float expectedResult ) + { + Vector3 vector1 = new Vector3( x1, y1, z1 ); + Vector3 vector2 = new Vector3( x2, y2, z2 ); + + Assert.AreEqual( Vector3.Dot( vector1, vector2 ), expectedResult ); + } + + + [TestCase( 1, 0, 0, 0, 1, 0, 0, 0, 1 )] + [TestCase( 1, 1, 1, 1, 1, 1, 0, 0, 0 )] + [TestCase( 1, 2, 3, 4, 5, 6, -3, 6, -3 )] + public void CrossTest( float x1, float y1, float z1, float x2, float y2, float z2, + float expectedX, float expectedY, float expectedZ ) + { + Vector3 vector1 = new Vector3( x1, y1, z1 ); + Vector3 vector2 = new Vector3( x2, y2, z2 ); + Vector3 expectedResult = new Vector3( expectedX, expectedY, expectedZ ); + + Assert.AreEqual( Vector3.Cross( vector1, vector2 ) == expectedResult, true ); + } + } +} diff --git a/Unit Tests/Accord.Tests.Math/Accord.Tests.Math.csproj b/Unit Tests/Accord.Tests.Math/Accord.Tests.Math.csproj index 2ef9bce13..83bb6172a 100644 --- a/Unit Tests/Accord.Tests.Math/Accord.Tests.Math.csproj +++ b/Unit Tests/Accord.Tests.Math/Accord.Tests.Math.csproj @@ -4,7 +4,6 @@ {F454DBD6-2AB9-461D-9624-2249B921B6E6} Accord.Tests.Math Accord.Tests.Math - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} Debug AnyCPU v4.5 @@ -27,47 +26,37 @@ true true Accord.snk + x86 true full false - bin\Debug\ + $(SolutionDir)..\Unit Tests\bin\Debug\ DEBUG;TRACE - x86 - bin\Release\net35 + $(SolutionDir)..\Unit Tests\bin\Release\net35\ TRACE;NET35 - x86 - bin\Release\net40 + $(SolutionDir)..\Unit Tests\bin\Release\net40\ TRACE;NET40 - x86 - bin\Release\net45 + $(SolutionDir)..\Unit Tests\bin\Release\net45\ TRACE;NET45 - x86 - - False - ..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\Externals\AForge.NET\AForge.Math.dll + + ..\..\Externals\NUnit\nunit.framework.dll 3.5 - - c:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll - + + + + + + + + + + + + + + + + @@ -105,14 +109,8 @@ - - - - - - @@ -172,12 +170,10 @@ {F718E9A8-DB62-4785-8C49-4333A60D256A} Accord.Math - - {161BD953-537D-4325-8A00-22475FC9088E} - Accord.Tests.Math.Cpp - - + + + False diff --git a/Unit Tests/Accord.Tests.Math/Collections/RedBlackTreeDictionaryTest.cs b/Unit Tests/Accord.Tests.Math/Collections/RedBlackTreeDictionaryTest.cs index 866af581e..0333fcc35 100644 --- a/Unit Tests/Accord.Tests.Math/Collections/RedBlackTreeDictionaryTest.cs +++ b/Unit Tests/Accord.Tests.Math/Collections/RedBlackTreeDictionaryTest.cs @@ -25,13 +25,13 @@ namespace Accord.Tests.Math using System; using System.Collections.Generic; using Accord.Collections; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class RedBlackDictionaryTest { - [TestMethod()] + [Test] public void DuplicateTest() { var map = new RedBlackTreeDictionary(); @@ -51,7 +51,7 @@ public void DuplicateTest() Assert.AreEqual(2, map.Count); } - [TestMethod()] + [Test] public void EmptyTest() { var map = new RedBlackTreeDictionary(); @@ -85,7 +85,7 @@ public void EmptyTest() } - [TestMethod()] + [Test] public void NextPrevTest() { bool thrown = false; diff --git a/Unit Tests/Accord.Tests.Math/Collections/RedBlackTreeTest.cs b/Unit Tests/Accord.Tests.Math/Collections/RedBlackTreeTest.cs index 55e8e4e18..7de326285 100644 --- a/Unit Tests/Accord.Tests.Math/Collections/RedBlackTreeTest.cs +++ b/Unit Tests/Accord.Tests.Math/Collections/RedBlackTreeTest.cs @@ -25,21 +25,21 @@ namespace Accord.Tests.Math using System; using Accord.Collections; using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System.Linq; using System.Collections.Generic; - [TestClass()] + [TestFixture] public class RedBlackTreeTest { - [TestMethod()] + [Test] public void BaseTest() { run(10); } - [TestMethod()] + [Test] public void ExtensiveTest() { for (int i = 1; i < 10; i++) @@ -52,7 +52,7 @@ public void ExtensiveTest() } - [TestMethod()] + [Test] public void DuplicateTest() { var t = new RedBlackTree(); @@ -95,7 +95,7 @@ public void DuplicateTest() Assert.AreEqual(0, values.Length); } - [TestMethod()] + [Test] public void ExtensiveDuplicateTest() { for (int i = 1; i < 10; i++) diff --git a/Unit Tests/Accord.Tests.Math/CombinatoricsTest.cs b/Unit Tests/Accord.Tests.Math/CombinatoricsTest.cs index ffde6dcec..11860e32e 100644 --- a/Unit Tests/Accord.Tests.Math/CombinatoricsTest.cs +++ b/Unit Tests/Accord.Tests.Math/CombinatoricsTest.cs @@ -25,9 +25,9 @@ namespace Accord.Tests.Math using System.Collections.Generic; using System.Linq; using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class CombinatoricsTest { @@ -49,7 +49,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void TruthTableTest() { { @@ -122,7 +122,7 @@ public void TruthTableTest() } } - [TestMethod()] + [Test] public void TruthTableTest2() { // Suppose we would like to generate a truth table (i.e. all possible @@ -155,7 +155,7 @@ public void TruthTableTest2() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void SequencesTest() { int[] symbols = { 2, 3, 2 }; @@ -181,7 +181,7 @@ public void SequencesTest() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void SequencesTest2() { int[][] expected = @@ -203,7 +203,7 @@ public void SequencesTest2() } } - [TestMethod()] + [Test] public void PermutationsTest() { // Let's say we would like to generate all possible permutations @@ -225,7 +225,7 @@ public void PermutationsTest() Assert.IsTrue(permutations[5].IsEqual(new[] { 3, 2, 1 })); } - [TestMethod()] + [Test] public void CombinationsTest() { // Let's say we would like to generate all possible combinations diff --git a/Unit Tests/Accord.Tests.Math/Comparers/CustomComparerTest.cs b/Unit Tests/Accord.Tests.Math/Comparers/CustomComparerTest.cs index 64c524c4e..9af744800 100644 --- a/Unit Tests/Accord.Tests.Math/Comparers/CustomComparerTest.cs +++ b/Unit Tests/Accord.Tests.Math/Comparers/CustomComparerTest.cs @@ -23,11 +23,11 @@ namespace Accord.Tests.Math { using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Math.Comparers; - [TestClass()] + [TestFixture] public class CustomComparerTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void CustomComparerConstructorTest() { double[] actual, expected; diff --git a/Unit Tests/Accord.Tests.Math/Comparers/ElementComparerTest.cs b/Unit Tests/Accord.Tests.Math/Comparers/ElementComparerTest.cs index 26d69b15d..8ccd8aefe 100644 --- a/Unit Tests/Accord.Tests.Math/Comparers/ElementComparerTest.cs +++ b/Unit Tests/Accord.Tests.Math/Comparers/ElementComparerTest.cs @@ -23,11 +23,11 @@ namespace Accord.Tests.Math { using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Math.Comparers; - [TestClass()] + [TestFixture] public class ElementComparerTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ElementComparerConstructorTest() { double[][] values = diff --git a/Unit Tests/Accord.Tests.Math/Comparers/GeneralComparerTest.cs b/Unit Tests/Accord.Tests.Math/Comparers/GeneralComparerTest.cs index 13540bf30..aaf6dd347 100644 --- a/Unit Tests/Accord.Tests.Math/Comparers/GeneralComparerTest.cs +++ b/Unit Tests/Accord.Tests.Math/Comparers/GeneralComparerTest.cs @@ -23,11 +23,11 @@ namespace Accord.Tests.Math { using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Math.Comparers; - [TestClass()] + [TestFixture] public class GeneralComparerTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void GeneralComparerConstructorTest() { double[] actual, expected; diff --git a/Unit Tests/Accord.Tests.Math/Convergence/AbsoluteConvergenceTest.cs b/Unit Tests/Accord.Tests.Math/Convergence/AbsoluteConvergenceTest.cs index 6240ba902..c1d347aee 100644 --- a/Unit Tests/Accord.Tests.Math/Convergence/AbsoluteConvergenceTest.cs +++ b/Unit Tests/Accord.Tests.Math/Convergence/AbsoluteConvergenceTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Math { using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; - [TestClass()] + [TestFixture] public class AbsoluteConvergenceTest { @@ -47,7 +47,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void AbsoluteConvergenceConstructorTest() { var criteria = new AbsoluteConvergence(iterations: 10, tolerance: 0.1); diff --git a/Unit Tests/Accord.Tests.Math/Convergence/RelativeConvergenceTest.cs b/Unit Tests/Accord.Tests.Math/Convergence/RelativeConvergenceTest.cs index e0f5c5e44..ab34743fa 100644 --- a/Unit Tests/Accord.Tests.Math/Convergence/RelativeConvergenceTest.cs +++ b/Unit Tests/Accord.Tests.Math/Convergence/RelativeConvergenceTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Math { using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; - [TestClass()] + [TestFixture] public class RelativeConvergenceTest { @@ -47,7 +47,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void RelativeConvergenceConstructorTest() { var criteria = new RelativeConvergence(iterations: 0, tolerance: 0.1); diff --git a/Unit Tests/Accord.Tests.Math/Convergence/RelativeParameterConvergenceTest.cs b/Unit Tests/Accord.Tests.Math/Convergence/RelativeParameterConvergenceTest.cs index 9eaff3f3b..116d8c28b 100644 --- a/Unit Tests/Accord.Tests.Math/Convergence/RelativeParameterConvergenceTest.cs +++ b/Unit Tests/Accord.Tests.Math/Convergence/RelativeParameterConvergenceTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Math { using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; - [TestClass()] + [TestFixture] public class RelativeParameterConvergenceTest { @@ -47,7 +47,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void RelativeParameterConstructorTest() { var criteria = new RelativeParameterConvergence(iterations: 0, tolerance: 0.1); diff --git a/Unit Tests/Accord.Tests.Math/CosineTransformTest.cs b/Unit Tests/Accord.Tests.Math/CosineTransformTest.cs index 4bc1b3a56..7405b9622 100644 --- a/Unit Tests/Accord.Tests.Math/CosineTransformTest.cs +++ b/Unit Tests/Accord.Tests.Math/CosineTransformTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Math { using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using AForge.Math; - [TestClass()] + [TestFixture] public class CosineTransformTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ForwardTest() { double[,] input = @@ -82,7 +82,7 @@ public void ForwardTest() Assert.IsTrue(actual.IsEqual(expected, 0.05)); } - [TestMethod()] + [Test] public void InverseTest() { double[,] input = diff --git a/Unit Tests/Accord.Tests.Math/Decompositions/CholeskyDecompositionTest.cs b/Unit Tests/Accord.Tests.Math/Decompositions/CholeskyDecompositionTest.cs index 37538e60d..8a9aa026e 100644 --- a/Unit Tests/Accord.Tests.Math/Decompositions/CholeskyDecompositionTest.cs +++ b/Unit Tests/Accord.Tests.Math/Decompositions/CholeskyDecompositionTest.cs @@ -23,11 +23,11 @@ namespace Accord.Tests.Math { using Accord.Math.Decompositions; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; using System; - [TestClass()] + [TestFixture] public class CholeskyDecompositionTest { @@ -46,7 +46,7 @@ public TestContext TestContext } } - [TestMethod()] + [Test] public void InverseTestNaN() { int n = 5; @@ -85,7 +85,7 @@ public void InverseTestNaN() } } - [TestMethod()] + [Test] public void CholeskyDecompositionConstructorTest() { // Based on tests by Ken Johnson @@ -118,7 +118,7 @@ public void CholeskyDecompositionConstructorTest() Assert.AreEqual(true, chol.Symmetric); } - [TestMethod()] + [Test] public void SolveTest() { double[,] value = // positive-definite @@ -144,7 +144,7 @@ public void SolveTest() Assert.IsTrue(Matrix.IsEqual(expected, B, 0.0000000000001)); } - [TestMethod()] + [Test] public void SolveTest3() { double[,] value = // positive-definite @@ -169,7 +169,7 @@ public void SolveTest3() Assert.IsTrue(Matrix.IsEqual(expected, B, 0.0000000000001)); } - [TestMethod()] + [Test] public void SolveTest2() { double[,] value = // not positive-definite @@ -197,7 +197,7 @@ public void SolveTest2() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.0000000000001)); } - [TestMethod()] + [Test] public void SolveTest4() { double[,] value = // not positive-definite @@ -219,7 +219,7 @@ public void SolveTest4() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.0000000000001)); } - [TestMethod()] + [Test] public void InverseTest() { double[,] value = // not positive-definite @@ -239,7 +239,7 @@ public void InverseTest() Assert.IsTrue(Matrix.IsEqual(expected, actual, 1e-10)); } - [TestMethod()] + [Test] public void CholeskyDecompositionConstructorTest2() { double[,] value = // positive-definite @@ -280,7 +280,7 @@ public void CholeskyDecompositionConstructorTest2() Assert.AreEqual(true, chol.Symmetric); } - [TestMethod()] + [Test] public void CholeskyDecompositionConstructorTest3() { double[,] value = // not positive-definite @@ -322,7 +322,7 @@ public void CholeskyDecompositionConstructorTest3() } - [TestMethod()] + [Test] public void CholeskyDecompositionConstructorTest4() { // Based on tests by Ken Johnson @@ -368,7 +368,7 @@ public void CholeskyDecompositionConstructorTest4() } - [TestMethod()] + [Test] public void LogDeterminantTest() { CholeskyDecomposition chol = new CholeskyDecomposition(bigmatrix); @@ -380,7 +380,7 @@ public void LogDeterminantTest() } - [TestMethod()] + [Test] public void DeterminantTest() { double[,] value = @@ -397,7 +397,7 @@ public void DeterminantTest() Assert.IsTrue(chol.Symmetric); } - [TestMethod()] + [Test] public void LogDeterminantTest2() { double[,] value = diff --git a/Unit Tests/Accord.Tests.Math/Decompositions/EigenvalueDecompositionTest.cs b/Unit Tests/Accord.Tests.Math/Decompositions/EigenvalueDecompositionTest.cs index 096d2780b..107f6aa8c 100644 --- a/Unit Tests/Accord.Tests.Math/Decompositions/EigenvalueDecompositionTest.cs +++ b/Unit Tests/Accord.Tests.Math/Decompositions/EigenvalueDecompositionTest.cs @@ -23,14 +23,14 @@ namespace Accord.Tests.Math { using Accord.Math.Decompositions; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; - [TestClass()] + [TestFixture] public class EigenvalueDecompositionTest { - [TestMethod()] + [Test] public void InverseTestNaN() { int n = 5; @@ -50,7 +50,7 @@ public void InverseTestNaN() } } - [TestMethod()] + [Test] public void EigenvalueDecompositionConstructorTest() { // Symmetric test @@ -92,7 +92,7 @@ public void EigenvalueDecompositionConstructorTest() - [TestMethod()] + [Test] public void EigenvalueDecompositionConstructorTest2() { // Asymmetric test diff --git a/Unit Tests/Accord.Tests.Math/Decompositions/GeneralizedEigenvalueDecompositionTest.cs b/Unit Tests/Accord.Tests.Math/Decompositions/GeneralizedEigenvalueDecompositionTest.cs index 623a5e9d8..c3aa1b533 100644 --- a/Unit Tests/Accord.Tests.Math/Decompositions/GeneralizedEigenvalueDecompositionTest.cs +++ b/Unit Tests/Accord.Tests.Math/Decompositions/GeneralizedEigenvalueDecompositionTest.cs @@ -23,30 +23,14 @@ namespace Accord.Tests.Math { using Accord.Math.Decompositions; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; - [TestClass()] + [TestFixture] public class GeneralizedEigenvalueDecompositionTest { - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - - [TestMethod()] + [Test] public void GeneralizedEigenvalueDecompositionConstructorTest() { // Suppose we have the following @@ -105,7 +89,7 @@ public void GeneralizedEigenvalueDecompositionConstructorTest() Assert.IsTrue(Matrix.IsEqual(gevd.DiagonalMatrix, expectedValues, 0.00000000001)); } - [TestMethod()] + [Test] public void GeneralizedEigenvalueDecompositionConstructorTest2() { double[,] A = Matrix.Identity(100); @@ -120,7 +104,7 @@ public void GeneralizedEigenvalueDecompositionConstructorTest2() Assert.IsTrue(Matrix.IsEqual(gevd.DiagonalMatrix, expectedValues)); } - [TestMethod()] + [Test] public void GeneralizedEigenvalueDecompositionConstructorTest3() { for (int i = 0; i < 10000; i++) @@ -162,7 +146,7 @@ public void GeneralizedEigenvalueDecompositionConstructorTest3() } } - [TestMethod()] + [Test] public void GeneralizedEigenvalueDecompositionConstructorTest4() { var A = new double[3, 3]; diff --git a/Unit Tests/Accord.Tests.Math/Decompositions/GramSchmidtOrthogonalizationTest.cs b/Unit Tests/Accord.Tests.Math/Decompositions/GramSchmidtOrthogonalizationTest.cs index ba5aea407..4f99df446 100644 --- a/Unit Tests/Accord.Tests.Math/Decompositions/GramSchmidtOrthogonalizationTest.cs +++ b/Unit Tests/Accord.Tests.Math/Decompositions/GramSchmidtOrthogonalizationTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Math { using Accord.Math.Decompositions; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; - [TestClass()] + [TestFixture] public class GramSchmidtTest { @@ -47,7 +47,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest1() { double[,] value = diff --git a/Unit Tests/Accord.Tests.Math/Decompositions/JaggedCholeskyDecompositionFTest.cs b/Unit Tests/Accord.Tests.Math/Decompositions/JaggedCholeskyDecompositionFTest.cs index fe0f1e154..8fa13392c 100644 --- a/Unit Tests/Accord.Tests.Math/Decompositions/JaggedCholeskyDecompositionFTest.cs +++ b/Unit Tests/Accord.Tests.Math/Decompositions/JaggedCholeskyDecompositionFTest.cs @@ -25,9 +25,9 @@ namespace Accord.Tests.Math using System; using Accord.Math; using Accord.Math.Decompositions; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class JaggedCholeskyDecompositionFTest { @@ -47,7 +47,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void InverseTestNaN() { int n = 5; @@ -81,7 +81,7 @@ public void InverseTestNaN() } - [TestMethod()] + [Test] public void JaggedCholeskyDecompositionFConstructorTest() { // Based on tests by Ken Johnson @@ -113,7 +113,7 @@ public void JaggedCholeskyDecompositionFConstructorTest() Assert.AreEqual(true, chol.PositiveDefinite); } - [TestMethod()] + [Test] public void SolveTest() { float[][] value = // positive-definite @@ -139,7 +139,7 @@ public void SolveTest() Assert.IsTrue(Matrix.IsEqual(expected, B, 1e-6f)); } - [TestMethod()] + [Test] public void SolveTest3() { float[][] value = // positive-definite @@ -164,7 +164,7 @@ public void SolveTest3() Assert.IsTrue(Matrix.IsEqual(expected, B, 1e-5f)); } - [TestMethod()] + [Test] public void SolveTest2() { float[][] value = // not positive-definite @@ -193,7 +193,7 @@ public void SolveTest2() Assert.IsTrue(Matrix.IsEqual(expected, actual, 1e-5f)); } - [TestMethod()] + [Test] public void SolveTest4() { float[][] value = // not positive-definite @@ -216,7 +216,7 @@ public void SolveTest4() Assert.AreEqual(expected[i], actual[i], 1e-3); } - [TestMethod()] + [Test] public void InverseTest() { float[][] value = // not positive-definite @@ -243,7 +243,7 @@ public void InverseTest() Assert.IsTrue(Matrix.IsEqual(expected, actual, 1e-6f)); } - [TestMethod()] + [Test] public void InverseTest1() { float[][] value = // positive-definite @@ -270,7 +270,7 @@ public void InverseTest1() Assert.AreEqual(expected[i][j], actual[i][j], 1e-6f); } - [TestMethod()] + [Test] public void InverseDiagonalTest1() { float[][] value = // positive-definite @@ -290,7 +290,7 @@ public void InverseDiagonalTest1() Assert.AreEqual(expected[i], actual[i], 1e-6f); } - [TestMethod()] + [Test] public void InverseDiagonalTest2() { float[][] value = // positive-definite @@ -311,7 +311,7 @@ public void InverseDiagonalTest2() Assert.AreEqual(expected[i], actual[i], 1e-6f); } - [TestMethod()] + [Test] public void InverseDiagonalTest3() { float[][] value = // not positive-definite @@ -333,7 +333,7 @@ public void InverseDiagonalTest3() Assert.AreEqual(expected[i], actual[i], 1e-4f); } - [TestMethod()] + [Test] public void InPlaceTest() { float[][] value = // positive-definite @@ -373,7 +373,7 @@ public void InPlaceTest() Assert.AreEqual(expected[i][j], value[i][j], 1e-3); } - [TestMethod()] + [Test] public void CholeskyDecompositionFConstructorTest2() { float[][] value = // positive-definite @@ -413,7 +413,7 @@ public void CholeskyDecompositionFConstructorTest2() Assert.AreEqual(true, chol.PositiveDefinite); } - [TestMethod()] + [Test] public void CholeskyDecompositionConstructorTest3() { float[][] value = // not positive-definite @@ -454,7 +454,7 @@ public void CholeskyDecompositionConstructorTest3() Assert.AreEqual(false, chol.PositiveDefinite); } - [TestMethod()] + [Test] public void CholeskyDecompositionConstructorTest4() { // Based on tests by Ken Johnson diff --git a/Unit Tests/Accord.Tests.Math/Decompositions/JaggedEigenvalueDecompositionTest.cs b/Unit Tests/Accord.Tests.Math/Decompositions/JaggedEigenvalueDecompositionTest.cs index 4a30681c6..06017f343 100644 --- a/Unit Tests/Accord.Tests.Math/Decompositions/JaggedEigenvalueDecompositionTest.cs +++ b/Unit Tests/Accord.Tests.Math/Decompositions/JaggedEigenvalueDecompositionTest.cs @@ -23,14 +23,14 @@ namespace Accord.Tests.Math { using Accord.Math.Decompositions; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; - [TestClass()] + [TestFixture] public class JaggedEigenvalueDecompositionTest { - [TestMethod()] + [Test] public void InverseTestNaN() { int n = 5; @@ -43,14 +43,14 @@ public void InverseTestNaN() { double[][] value = Matrix.JaggedMagic(n); - value[i][j] = double.NaN; - + value[i][j] = double.NaN; + var target = new JaggedEigenvalueDecomposition(value); } } } - [TestMethod()] + [Test] public void EigenvalueDecompositionConstructorTest() { // Symmetric test @@ -58,8 +58,8 @@ public void EigenvalueDecompositionConstructorTest() { new double[] { 4, 2 }, new double[] { 2, 4 } - }; - + }; + var target = new JaggedEigenvalueDecomposition(A); var D = target.DiagonalMatrix; @@ -92,7 +92,7 @@ public void EigenvalueDecompositionConstructorTest() - [TestMethod()] + [Test] public void EigenvalueDecompositionConstructorTest2() { // Asymmetric test @@ -101,8 +101,8 @@ public void EigenvalueDecompositionConstructorTest2() new double[] { 5, 2, 1 }, new double[] { 1, 4, 1 }, new double[] { -1, 2, 3 } - }; - + }; + var target = new JaggedEigenvalueDecomposition(A); var D = target.DiagonalMatrix; var Q = target.Eigenvectors; diff --git a/Unit Tests/Accord.Tests.Math/Decompositions/JaggedLuDecompositionFTest.cs b/Unit Tests/Accord.Tests.Math/Decompositions/JaggedLuDecompositionFTest.cs index 9b84cc516..39f150bdd 100644 --- a/Unit Tests/Accord.Tests.Math/Decompositions/JaggedLuDecompositionFTest.cs +++ b/Unit Tests/Accord.Tests.Math/Decompositions/JaggedLuDecompositionFTest.cs @@ -23,15 +23,15 @@ namespace Accord.Tests.Math { using Accord.Math.Decompositions; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; using System; - [TestClass()] + [TestFixture] public class JaggedLuDecompositionTest { - [TestMethod()] + [Test] public void InverseTestNaN() { int n = 5; @@ -57,7 +57,7 @@ public void InverseTestNaN() } - [TestMethod()] + [Test] public void SolveTest1() { float[][] value = @@ -83,7 +83,7 @@ public void SolveTest1() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.001)); } - [TestMethod()] + [Test] public void InverseTest() { float[][] value = @@ -107,7 +107,7 @@ public void InverseTest() Assert.IsTrue(Matrix.IsEqual(expectedInverse, actualInverse, 0.001)); } - [TestMethod()] + [Test] public void SolveTest() { float[][] value = @@ -138,7 +138,7 @@ public void SolveTest() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.001)); } - [TestMethod()] + [Test] public void SolveTest3() { float[][] value = @@ -169,7 +169,7 @@ public void SolveTest3() Assert.IsTrue(Matrix.IsEqual(expectedU, U, 0.001)); } - [TestMethod()] + [Test] public void SolveTest4() { float[][] value = @@ -189,7 +189,7 @@ public void SolveTest4() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.001)); } - [TestMethod()] + [Test] public void SolveTest5() { float[][] value = @@ -215,7 +215,7 @@ public void SolveTest5() Assert.IsTrue(thrown); } - [TestMethod()] + [Test] public void SolveTransposeTest() { float[][] a = @@ -243,7 +243,7 @@ public void SolveTransposeTest() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.001)); } - [TestMethod()] + [Test] public void LuDecompositionConstructorTest() { float[][] value = @@ -288,7 +288,7 @@ public void LuDecompositionConstructorTest() Assert.IsTrue(Matrix.IsEqual(expectedU, actualU, 0.001)); } - [TestMethod()] + [Test] public void LogDeterminantTest() { JaggedLuDecompositionF lu = new JaggedLuDecompositionF( @@ -298,7 +298,7 @@ public void LogDeterminantTest() Assert.IsTrue(lu.Nonsingular); } - [TestMethod()] + [Test] public void DeterminantTest() { float[][] value = @@ -313,7 +313,7 @@ public void DeterminantTest() Assert.IsTrue(lu.Nonsingular); } - [TestMethod()] + [Test] public void LogDeterminantTest2() { float[][] value = diff --git a/Unit Tests/Accord.Tests.Math/Decompositions/JaggedQrDecompositionTest.cs b/Unit Tests/Accord.Tests.Math/Decompositions/JaggedQrDecompositionTest.cs index 4e1de32ba..744f0a67d 100644 --- a/Unit Tests/Accord.Tests.Math/Decompositions/JaggedQrDecompositionTest.cs +++ b/Unit Tests/Accord.Tests.Math/Decompositions/JaggedQrDecompositionTest.cs @@ -23,14 +23,14 @@ namespace Accord.Tests.Math { using Accord.Math.Decompositions; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; - [TestClass()] + [TestFixture] public class JaggedQrDecompositionTest { - [TestMethod()] + [Test] public void InverseTestNaN() { int n = 5; @@ -55,14 +55,14 @@ public void InverseTestNaN() } } - [TestMethod()] + [Test] public void QrDecompositionConstructorTest() { - double[][] value = - { - new double[] { 2, -1, 0 }, - new double[] { -1, 2, -1 }, - new double[] { 0, -1, 2 } + double[][] value = + { + new double[] { 2, -1, 0 }, + new double[] { -1, 2, -1 }, + new double[] { 0, -1, 2 } }; @@ -83,21 +83,21 @@ public void QrDecompositionConstructorTest() } - [TestMethod()] + [Test] public void InverseTest() { - double[][] value = - { - new double[] { 2, -1, 0 }, - new double[] { -1, 2, -1 }, - new double[] { 0, -1, 2 } + double[][] value = + { + new double[] { 2, -1, 0 }, + new double[] { -1, 2, -1 }, + new double[] { 0, -1, 2 } }; - double[][] expected = - { - new double[] { 0.7500, 0.5000, 0.2500}, - new double[] { 0.5000, 1.0000, 0.5000}, - new double[] { 0.2500, 0.5000, 0.7500}, + double[][] expected = + { + new double[] { 0.7500, 0.5000, 0.2500}, + new double[] { 0.5000, 1.0000, 0.5000}, + new double[] { 0.2500, 0.5000, 0.7500}, }; @@ -111,14 +111,14 @@ public void InverseTest() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.0000000000001)); } - [TestMethod()] + [Test] public void SolveTest() { - double[][] value = - { - new double[] { 2, -1, 0 }, - new double[] { -1, 2, -1 }, - new double[] { 0, -1, 2 } + double[][] value = + { + new double[] { 2, -1, 0 }, + new double[] { -1, 2, -1 }, + new double[] { 0, -1, 2 } }; double[] b = { 1, 2, 3 }; @@ -131,39 +131,39 @@ public void SolveTest() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.0000000000001)); } - [TestMethod()] + [Test] public void SolveTest2() { // Example from Lecture notes for MATHS 370: Advanced Numerical Methods // http://www.math.auckland.ac.nz/~sharp/370/qr-solving.pdf - double[][] value = - { - new double[] { 1, 0, 0 }, - new double[] { 1, 7, 49 }, - new double[] { 1, 14, 196 }, - new double[] { 1, 21, 441 }, - new double[] { 1, 28, 784 }, - new double[] { 1, 35, 1225 }, + double[][] value = + { + new double[] { 1, 0, 0 }, + new double[] { 1, 7, 49 }, + new double[] { 1, 14, 196 }, + new double[] { 1, 21, 441 }, + new double[] { 1, 28, 784 }, + new double[] { 1, 35, 1225 }, }; // Matrices { - double[][] b = - { - new double[] { 4 }, - new double[] { 1 }, - new double[] { 0 }, - new double[] { 0 }, - new double[] { 2 }, - new double[] { 5 }, + double[][] b = + { + new double[] { 4 }, + new double[] { 1 }, + new double[] { 0 }, + new double[] { 0 }, + new double[] { 2 }, + new double[] { 5 }, }; - double[][] expected = - { - new double[] { 3.9286 }, - new double[] { -0.5031 }, - new double[] { 0.0153 }, + double[][] expected = + { + new double[] { 3.9286 }, + new double[] { -0.5031 }, + new double[] { 0.0153 }, }; var target = new JaggedQrDecomposition(value); @@ -185,28 +185,28 @@ public void SolveTest2() } - [TestMethod()] + [Test] public void SolveTransposeTest() { - double[][] a = - { - new double[] { 2, 1, 4 }, - new double[] { 6, 2, 2 }, - new double[] { 0, 1, 6 }, + double[][] a = + { + new double[] { 2, 1, 4 }, + new double[] { 6, 2, 2 }, + new double[] { 0, 1, 6 }, }; - double[][] b = - { - new double[] { 1, 0, 7 }, - new double[] { 5, 2, 1 }, - new double[] { 1, 5, 2 }, + double[][] b = + { + new double[] { 1, 0, 7 }, + new double[] { 5, 2, 1 }, + new double[] { 1, 5, 2 }, }; - double[][] expected = - { - new double[] { 0.5062, 0.2813, 0.0875 }, - new double[] { 0.1375, 1.1875, -0.0750 }, - new double[] { 0.8063, -0.2188, 0.2875 }, + double[][] expected = + { + new double[] { 0.5062, 0.2813, 0.0875 }, + new double[] { 0.1375, 1.1875, -0.0750 }, + new double[] { 0.8063, -0.2188, 0.2875 }, }; double[][] actual = new JaggedQrDecomposition(b, true).SolveTranspose(a); diff --git a/Unit Tests/Accord.Tests.Math/Decompositions/JaggedSingularValueDecompositionTest.cs b/Unit Tests/Accord.Tests.Math/Decompositions/JaggedSingularValueDecompositionTest.cs index 326819a2f..d83572f36 100644 --- a/Unit Tests/Accord.Tests.Math/Decompositions/JaggedSingularValueDecompositionTest.cs +++ b/Unit Tests/Accord.Tests.Math/Decompositions/JaggedSingularValueDecompositionTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Math { using Accord.Math.Decompositions; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; - [TestClass()] + [TestFixture] public class JaggedSingularValueDecompositionTest { @@ -46,7 +46,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void InverseTestNaN() { int n = 5; @@ -71,7 +71,7 @@ public void InverseTestNaN() } } - [TestMethod()] + [Test] public void InverseTest() { var value = new double[][] @@ -95,7 +95,7 @@ public void InverseTest() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.001)); } - [TestMethod()] + [Test] public void JaggedSingularValueDecompositionConstructorTest1() { // This test catches the bug in SingularValueDecomposition in the line @@ -158,7 +158,7 @@ public void JaggedSingularValueDecompositionConstructorTest1() } - [TestMethod()] + [Test] public void JaggedSingularValueDecompositionConstructorTest3() { // Test using SVD assumption auto-correction feature. @@ -217,7 +217,7 @@ public void JaggedSingularValueDecompositionConstructorTest3() } - [TestMethod()] + [Test] public void JaggedSingularValueDecompositionConstructorTest2() { // test for m-x-n matrices where m > n (4 > 2) @@ -275,7 +275,7 @@ public void JaggedSingularValueDecompositionConstructorTest2() } - [TestMethod()] + [Test] public void JaggedSingularValueDecompositionConstructorTest4() { // Test using SVD assumption auto-correction feature @@ -326,7 +326,7 @@ public void JaggedSingularValueDecompositionConstructorTest4() Assert.IsTrue(Matrix.IsEqual(target.Diagonal, Matrix.Diagonal(S), 0.001)); } - [TestMethod()] + [Test] public void JaggedSingularValueDecompositionConstructorTest5() { // Test using SVD assumption auto-correction feature @@ -378,7 +378,7 @@ public void JaggedSingularValueDecompositionConstructorTest5() } - [TestMethod()] + [Test] public void JaggedSingularValueDecompositionConstructorTest6() { // Test using SVD assumption auto-correction feature in place @@ -408,7 +408,7 @@ public void JaggedSingularValueDecompositionConstructorTest6() } - [TestMethod()] + [Test] public void JaggedSingularValueDecompositionConstructorTest7() { int count = 100; diff --git a/Unit Tests/Accord.Tests.Math/Decompositions/LuDecompositionTest.cs b/Unit Tests/Accord.Tests.Math/Decompositions/LuDecompositionTest.cs index 4ba9e4cba..c285c2cd4 100644 --- a/Unit Tests/Accord.Tests.Math/Decompositions/LuDecompositionTest.cs +++ b/Unit Tests/Accord.Tests.Math/Decompositions/LuDecompositionTest.cs @@ -23,11 +23,11 @@ namespace Accord.Tests.Math { using Accord.Math.Decompositions; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; using System; - [TestClass()] + [TestFixture] public class LuDecompositionTest { @@ -45,7 +45,7 @@ public TestContext TestContext } } - [TestMethod()] + [Test] public void InverseTestNaN() { int n = 5; @@ -71,7 +71,7 @@ public void InverseTestNaN() } - [TestMethod()] + [Test] public void SolveTest1() { double[,] value = @@ -97,7 +97,7 @@ public void SolveTest1() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.001)); } - [TestMethod()] + [Test] public void InverseTest() { double[,] value = @@ -122,7 +122,7 @@ public void InverseTest() } - [TestMethod()] + [Test] public void SolveTest() { double[,] value = @@ -153,7 +153,7 @@ public void SolveTest() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.001)); } - [TestMethod()] + [Test] public void SolveTest3() { double[,] value = @@ -184,7 +184,7 @@ public void SolveTest3() Assert.IsTrue(Matrix.IsEqual(expectedU, U, 0.001)); } - [TestMethod()] + [Test] public void SolveTest4() { double[,] value = @@ -204,7 +204,7 @@ public void SolveTest4() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.001)); } - [TestMethod()] + [Test] public void SolveTest5() { double[,] value = @@ -233,7 +233,7 @@ public void SolveTest5() Assert.IsTrue(thrown); } - [TestMethod()] + [Test] public void SolveTransposeTest() { double[,] a = @@ -261,7 +261,7 @@ public void SolveTransposeTest() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.001)); } - [TestMethod()] + [Test] public void LuDecompositionConstructorTest() { double[,] value = @@ -306,7 +306,7 @@ public void LuDecompositionConstructorTest() Assert.IsTrue(Matrix.IsEqual(expectedU, actualU, 0.001)); } - [TestMethod()] + [Test] public void LogDeterminantTest() { LuDecomposition lu = new LuDecomposition(CholeskyDecompositionTest.bigmatrix); @@ -315,7 +315,7 @@ public void LogDeterminantTest() Assert.IsTrue(lu.Nonsingular); } - [TestMethod()] + [Test] public void DeterminantTest() { double[,] value = @@ -330,7 +330,7 @@ public void DeterminantTest() Assert.IsTrue(lu.Nonsingular); } - [TestMethod()] + [Test] public void LogDeterminantTest2() { double[,] value = diff --git a/Unit Tests/Accord.Tests.Math/Decompositions/NonnegativeMatrixFactorization.cs b/Unit Tests/Accord.Tests.Math/Decompositions/NonnegativeMatrixFactorization.cs index 483368df6..c0a0b217b 100644 --- a/Unit Tests/Accord.Tests.Math/Decompositions/NonnegativeMatrixFactorization.cs +++ b/Unit Tests/Accord.Tests.Math/Decompositions/NonnegativeMatrixFactorization.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Math { using Accord.Math.Decompositions; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; - [TestClass()] + [TestFixture] public class NonnegativeMatrixFactorizationTest { @@ -45,7 +45,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void NonNegativeMatrixFactorizationConstructorTest() { @@ -71,7 +71,7 @@ public void NonNegativeMatrixFactorizationConstructorTest() Assert.IsTrue(R.IsEqual(X, 0.001)); } - [TestMethod()] + [Test] public void NonNegativeMatrixFactorizationConstructorTest2() { double[] data = diff --git a/Unit Tests/Accord.Tests.Math/Decompositions/QrDecompositionTest.cs b/Unit Tests/Accord.Tests.Math/Decompositions/QrDecompositionTest.cs index 6fac30138..317aaf2a6 100644 --- a/Unit Tests/Accord.Tests.Math/Decompositions/QrDecompositionTest.cs +++ b/Unit Tests/Accord.Tests.Math/Decompositions/QrDecompositionTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Math { using Accord.Math.Decompositions; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; - [TestClass()] + [TestFixture] public class QrDecompositionTest { @@ -46,7 +46,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void InverseTestNaN() { int n = 5; @@ -71,7 +71,7 @@ public void InverseTestNaN() } } - [TestMethod()] + [Test] public void QrDecompositionConstructorTest() { double[,] value = @@ -99,7 +99,7 @@ public void QrDecompositionConstructorTest() } - [TestMethod()] + [Test] public void InverseTest() { double[,] value = @@ -127,7 +127,7 @@ public void InverseTest() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.0000000000001)); } - [TestMethod()] + [Test] public void SolveTest() { double[,] value = @@ -147,7 +147,7 @@ public void SolveTest() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.0000000000001)); } - [TestMethod()] + [Test] public void SolveTest2() { // Example from Lecture notes for MATHS 370: Advanced Numerical Methods @@ -201,7 +201,7 @@ public void SolveTest2() } - [TestMethod()] + [Test] public void SolveTransposeTest() { double[,] a = diff --git a/Unit Tests/Accord.Tests.Math/Decompositions/SingularValueDecompositionTest.cs b/Unit Tests/Accord.Tests.Math/Decompositions/SingularValueDecompositionTest.cs index e5122bb64..218520356 100644 --- a/Unit Tests/Accord.Tests.Math/Decompositions/SingularValueDecompositionTest.cs +++ b/Unit Tests/Accord.Tests.Math/Decompositions/SingularValueDecompositionTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Math { using Accord.Math.Decompositions; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; - [TestClass()] + [TestFixture] public class SingularValueDecompositionTest { @@ -47,7 +47,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void InverseTest() { double[,] value = new double[,] @@ -71,7 +71,7 @@ public void InverseTest() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.001)); } - [TestMethod()] + [Test] public void InverseTestNaN() { int n = 5; @@ -97,7 +97,7 @@ public void InverseTestNaN() } - [TestMethod()] + [Test] public void SingularValueDecompositionConstructorTest1() { // This test catches the bug in SingularValueDecomposition in the line @@ -159,7 +159,7 @@ public void SingularValueDecompositionConstructorTest1() } - [TestMethod()] + [Test] public void SingularValueDecompositionConstructorTest3() { // Test using SVD assumption auto-correction feature. @@ -217,7 +217,7 @@ public void SingularValueDecompositionConstructorTest3() } - [TestMethod()] + [Test] public void SingularValueDecompositionConstructorTest2() { // test for m-x-n matrices where m > n (4 > 2) @@ -274,7 +274,7 @@ public void SingularValueDecompositionConstructorTest2() } - [TestMethod()] + [Test] public void SingularValueDecompositionConstructorTest4() { // Test using SVD assumption auto-correction feature @@ -325,7 +325,7 @@ public void SingularValueDecompositionConstructorTest4() Assert.IsTrue(Matrix.IsEqual(target.Diagonal, Matrix.Diagonal(S), 0.001)); } - [TestMethod()] + [Test] public void SingularValueDecompositionConstructorTest5() { // Test using SVD assumption auto-correction feature @@ -377,7 +377,7 @@ public void SingularValueDecompositionConstructorTest5() } - [TestMethod()] + [Test] public void SingularValueDecompositionConstructorTest6() { // Test using SVD assumption auto-correction feature in place @@ -407,7 +407,7 @@ public void SingularValueDecompositionConstructorTest6() } - [TestMethod()] + [Test] public void SingularValueDecompositionConstructorTest7() { int count = 100; diff --git a/Unit Tests/Accord.Tests.Math/Differentiation/FiniteDifferencesTest.cs b/Unit Tests/Accord.Tests.Math/Differentiation/FiniteDifferencesTest.cs index ec54a8ada..f9c70e9f1 100644 --- a/Unit Tests/Accord.Tests.Math/Differentiation/FiniteDifferencesTest.cs +++ b/Unit Tests/Accord.Tests.Math/Differentiation/FiniteDifferencesTest.cs @@ -25,9 +25,9 @@ namespace Accord.Tests.Math using System; using Accord.Math; using Accord.Math.Differentiation; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class FiniteDifferencesTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ComputeTest() { int numberOfParameters = 2; @@ -64,7 +64,7 @@ public void ComputeTest() Assert.IsTrue(expected.IsEqual(actual, 0.05)); } - [TestMethod()] + [Test] public void ComputeTest2() { // Create a simple function with two parameters: f(x,y) = x² + y diff --git a/Unit Tests/Accord.Tests.Math/DistanceTest.cs b/Unit Tests/Accord.Tests.Math/DistanceTest.cs index ef1ce124a..5d9990910 100644 --- a/Unit Tests/Accord.Tests.Math/DistanceTest.cs +++ b/Unit Tests/Accord.Tests.Math/DistanceTest.cs @@ -23,16 +23,16 @@ namespace Accord.Tests.Math { using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Math.Decompositions; - [TestClass()] + [TestFixture] public class DistanceTest { - [TestMethod()] + [Test] public void MahalanobisTest2() { // Example from Statistical Distance Calculator @@ -64,7 +64,7 @@ public void MahalanobisTest2() Assert.AreEqual(expected, actual, 0.0000000000001); } - [TestMethod()] + [Test] public void MahalanobisTest3() { // Example from Statistical Distance Calculator @@ -120,7 +120,7 @@ public void MahalanobisTest3() Assert.AreEqual(expected, actual, 1e-5); } - [TestMethod()] + [Test] public void MahalanobisTest4() { double[] x, y; @@ -157,7 +157,7 @@ public void MahalanobisTest4() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void MahalanobisTest5() { double[] x, y; @@ -194,7 +194,7 @@ public void MahalanobisTest5() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void MahalanobisTest6() { double[] x = { -1, 0, 0 }; @@ -217,7 +217,7 @@ public void MahalanobisTest6() Assert.IsFalse(Double.IsNaN(actual)); } - [TestMethod()] + [Test] public void ManhattanTest() { double[] x = { 3, 6 }; @@ -228,7 +228,7 @@ public void ManhattanTest() } - [TestMethod()] + [Test] public void EuclideanTest() { double[] x = new double[] { 2, 4, 1 }; @@ -239,7 +239,7 @@ public void EuclideanTest() } - [TestMethod()] + [Test] public void ModularTest() { int a = 1; @@ -252,7 +252,7 @@ public void ModularTest() } - [TestMethod()] + [Test] public void BhattacharyyaTest() { double[,] X = @@ -276,7 +276,7 @@ public void BhattacharyyaTest() Assert.IsFalse(Double.IsNaN(actual)); } - [TestMethod()] + [Test] public void BhattacharyyaTest1() { double[] histogram1 = { 0.1, 0.5, 0.4 }; @@ -289,7 +289,7 @@ public void BhattacharyyaTest1() Assert.IsFalse(Double.IsNaN(actual)); } - [TestMethod()] + [Test] public void BhattacharyyaTest2() { double[] x = { 2, 0, 0 }; @@ -317,7 +317,7 @@ public void BhattacharyyaTest2() Assert.IsFalse(Double.IsNaN(actual)); } - [TestMethod()] + [Test] public void BhattacharyyaTest3() { double[] x = { 2, 1, 0 }; @@ -338,7 +338,7 @@ public void BhattacharyyaTest3() Assert.IsFalse(Double.IsNaN(actual)); } - [TestMethod()] + [Test] public void BhattacharyyaTest4() { double[,] X = @@ -355,7 +355,7 @@ public void BhattacharyyaTest4() Assert.IsFalse(Double.IsNaN(actual)); } - [TestMethod()] + [Test] public void EuclideanTest1() { double x1 = 1.5; @@ -371,7 +371,7 @@ public void EuclideanTest1() Assert.IsFalse(double.IsNaN(actual)); } - [TestMethod()] + [Test] public void IsMetricTest() { Assert.IsTrue(Distance.IsMetric(Distance.Euclidean)); diff --git a/Unit Tests/Accord.Tests.Math/Environment/OctaveEnvironmentTest.cs b/Unit Tests/Accord.Tests.Math/Environment/OctaveEnvironmentTest.cs index 8d5456a37..0078f62fc 100644 --- a/Unit Tests/Accord.Tests.Math/Environment/OctaveEnvironmentTest.cs +++ b/Unit Tests/Accord.Tests.Math/Environment/OctaveEnvironmentTest.cs @@ -24,11 +24,11 @@ namespace Accord.Tests.Math { using Accord.Math.Environments; using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using System.CodeDom.Compiler; - [TestClass()] + [TestFixture] public class OctaveEnvironmentTest : OctaveEnvironment { @@ -49,7 +49,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void eyeTest() { var I = eye(3); @@ -95,7 +95,7 @@ public void eyeTest() Assert.IsTrue(expectedD.IsEqual(D)); } - [TestMethod()] + [Test] public void svdTest() { // Declare local matrices @@ -140,7 +140,7 @@ 0.577350269189626 0.707106781186548 0.408248290463863 Assert.IsTrue(expectedV.IsEqual(v, 1e-10)); } - [TestMethod()] + [Test] public void initTest() { MyAlgorithm al = new MyAlgorithm(); diff --git a/Unit Tests/Accord.Tests.Math/Environment/REnvironmentTest.cs b/Unit Tests/Accord.Tests.Math/Environment/REnvironmentTest.cs index 2113ac379..c50d81da4 100644 --- a/Unit Tests/Accord.Tests.Math/Environment/REnvironmentTest.cs +++ b/Unit Tests/Accord.Tests.Math/Environment/REnvironmentTest.cs @@ -24,10 +24,10 @@ namespace Accord.Tests.Math { using Accord.Math.Environments; using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; - [TestClass()] + [TestFixture] public class REnvironmentTest : REnvironment { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void eyeTest() { var x = c(1, 2, 3, 4); diff --git a/Unit Tests/Accord.Tests.Math/FourierTransformTest.cs b/Unit Tests/Accord.Tests.Math/FourierTransformTest.cs index 6f7885e7f..0eff947ea 100644 --- a/Unit Tests/Accord.Tests.Math/FourierTransformTest.cs +++ b/Unit Tests/Accord.Tests.Math/FourierTransformTest.cs @@ -23,16 +23,17 @@ namespace Accord.Tests.Math { using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using AForge.Math; using System; using Accord.Math.Transforms; + using System.Numerics; - [TestClass()] + [TestFixture] public class FourierTransformTest { - [TestMethod()] + [Test] public void FFTTest() { // Tests from diff --git a/Unit Tests/Accord.Tests.Math/Functions/BesselTest.cs b/Unit Tests/Accord.Tests.Math/Functions/BesselTest.cs index 44d8e80da..71b5f3d89 100644 --- a/Unit Tests/Accord.Tests.Math/Functions/BesselTest.cs +++ b/Unit Tests/Accord.Tests.Math/Functions/BesselTest.cs @@ -23,9 +23,9 @@ namespace Accord.Tests.Math { using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class BesselTest { @@ -46,7 +46,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void BesselY0Test() { double actual; @@ -55,7 +55,7 @@ public void BesselY0Test() Assert.AreEqual(0.037067103232088, actual, 0.000001); } - [TestMethod()] + [Test] public void BesselJTest() { double actual; @@ -70,7 +70,7 @@ public void BesselJTest() Assert.AreEqual(0.117351128521774, actual, 0.000001); } - [TestMethod()] + [Test] public void BesselYTest() { double actual; @@ -82,7 +82,7 @@ public void BesselYTest() Assert.AreEqual(0.037067103232088, actual, 0.000001); } - [TestMethod()] + [Test] public void BesselJ0Test() { double actual; diff --git a/Unit Tests/Accord.Tests.Math/Functions/BetaTest.cs b/Unit Tests/Accord.Tests.Math/Functions/BetaTest.cs index d99211715..1ff55d126 100644 --- a/Unit Tests/Accord.Tests.Math/Functions/BetaTest.cs +++ b/Unit Tests/Accord.Tests.Math/Functions/BetaTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Math { using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; - [TestClass()] + [TestFixture] public class BetaTest { @@ -47,7 +47,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void IncompleteTest() { double a = 5; @@ -60,56 +60,56 @@ public void IncompleteTest() Assert.AreEqual(expected, actual, 1e-6); } - [TestMethod()] + [Test] public void FunctionTest() { double actual = Beta.Function(4, 0.42); Assert.AreEqual(1.2155480852832423, actual); } - [TestMethod()] + [Test] public void LogTest() { double actual = Beta.Log(4, 15.2); Assert.AreEqual(-9.46087817876467, actual); } - [TestMethod()] + [Test] public void Incbcf() { double actual = Beta.Incbcf(4, 2, 4.2); Assert.AreEqual(-0.23046874999999992, actual); } - [TestMethod()] + [Test] public void Incbd() { double actual = Beta.Incbd(4, 2, 4.2); Assert.AreEqual(0.7375, actual); } - [TestMethod()] + [Test] public void IncompleteInverse() { double actual = Beta.IncompleteInverse(0.5, 0.6, 0.1); Assert.AreEqual(0.019145979066925722, actual); } - [TestMethod()] + [Test] public void PowerSeries() { double actual = Beta.PowerSeries(4, 2, 4.2); Assert.AreEqual(-3671.801280000001, actual); } - [TestMethod()] + [Test] public void Multinomial() { double actual = Beta.Multinomial(0.42, 0.5, 5.2 ); Assert.AreEqual(0.82641912952987062, actual); } - [TestMethod()] + [Test] public void IbetaTest() { double xx = 0.42; @@ -122,7 +122,7 @@ public void IbetaTest() } - [TestMethod()] + [Test] public void BetaTest2() { double a = 4.2; diff --git a/Unit Tests/Accord.Tests.Math/Functions/GammaTest.cs b/Unit Tests/Accord.Tests.Math/Functions/GammaTest.cs index 61c0a3ec6..014dd55f5 100644 --- a/Unit Tests/Accord.Tests.Math/Functions/GammaTest.cs +++ b/Unit Tests/Accord.Tests.Math/Functions/GammaTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Math { using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; - [TestClass()] + [TestFixture] public class GammaTest { @@ -47,7 +47,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void FunctionTest() { double[] x = @@ -95,7 +95,7 @@ public void FunctionTest() } - [TestMethod()] + [Test] public void LogTest() { double[] x = @@ -142,7 +142,7 @@ public void LogTest() } - [TestMethod()] + [Test] public void DigammaTest() { double[] x = { 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0 }; @@ -172,7 +172,7 @@ public void DigammaTest() } } - [TestMethod()] + [Test] public void GammaFunctionsTest() { double x = 0.17; @@ -201,7 +201,7 @@ public void GammaFunctionsTest() Assert.AreEqual(35.915302055854525, tri); } - [TestMethod()] + [Test] public void GammaTest2() { double x = 171; @@ -210,7 +210,7 @@ public void GammaTest2() Assert.AreEqual(expected, actual, 1e+293); } - [TestMethod()] + [Test] public void LgammaTest() { double x = 57; @@ -220,7 +220,7 @@ public void LgammaTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void DigammaTest2() { double x = 42; @@ -229,7 +229,7 @@ public void DigammaTest2() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void MultivariateGammaTest() { double expected = 35.342917352885181; @@ -237,7 +237,7 @@ public void MultivariateGammaTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void GammaUpperRTest() { // Example values from diff --git a/Unit Tests/Accord.Tests.Math/Functions/NormalTest.cs b/Unit Tests/Accord.Tests.Math/Functions/NormalTest.cs index 81df18bf1..d30e7da67 100644 --- a/Unit Tests/Accord.Tests.Math/Functions/NormalTest.cs +++ b/Unit Tests/Accord.Tests.Math/Functions/NormalTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Math { using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; - [TestClass()] + [TestFixture] public class NormalTest { @@ -47,7 +47,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void FunctionTest() { // p = 0.5 * erfc(-z ./ sqrt(2)) @@ -57,7 +57,7 @@ public void FunctionTest() Assert.AreEqual(expected, actual, 1e-10); } - [TestMethod()] + [Test] public void InverseTest() { double value = 0.662757273151751; @@ -66,7 +66,7 @@ public void InverseTest() Assert.AreEqual(expected, actual, 1e-10); } - [TestMethod()] + [Test] public void BatchTest() { double x = 0.42; @@ -86,7 +86,7 @@ public void BatchTest() Assert.AreEqual(0.33724272684824946, hphic, 1e-10); } - [TestMethod()] + [Test] public void BatchTest2() { double x = 16.6; @@ -102,7 +102,7 @@ public void BatchTest2() } - [TestMethod()] + [Test] public void BivariateFunctionTest() { { diff --git a/Unit Tests/Accord.Tests.Math/Functions/OwensTTest.cs b/Unit Tests/Accord.Tests.Math/Functions/OwensTTest.cs index 6a475b71c..f113138f3 100644 --- a/Unit Tests/Accord.Tests.Math/Functions/OwensTTest.cs +++ b/Unit Tests/Accord.Tests.Math/Functions/OwensTTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Math { using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; - [TestClass()] + [TestFixture] public class OwensTTest { @@ -46,14 +46,14 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void ExampleTest() - { - double x = OwensT.Function(h: 2, a: 42); + { + double x = OwensT.Function(h: 2, a: 42); Assert.AreEqual(0.011375065974089608, x); } - [TestMethod()] + [Test] public void FunctionTest() { diff --git a/Unit Tests/Accord.Tests.Math/GaborTest.cs b/Unit Tests/Accord.Tests.Math/GaborTest.cs index 424487f02..dbaf7eeeb 100644 --- a/Unit Tests/Accord.Tests.Math/GaborTest.cs +++ b/Unit Tests/Accord.Tests.Math/GaborTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Math { using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass] + [TestFixture] public class GaborTest { @@ -47,7 +47,7 @@ public TestContext TestContext - [TestMethod] + [Test] public void KernelTest1() { double[,] expected = @@ -74,7 +74,7 @@ public void KernelTest1() } } - [TestMethod] + [Test] public void KernelTest2() { double[,] expected = diff --git a/Unit Tests/Accord.Tests.Math/HilbertTransformTest.cs b/Unit Tests/Accord.Tests.Math/HilbertTransformTest.cs index a7250e040..d86477503 100644 --- a/Unit Tests/Accord.Tests.Math/HilbertTransformTest.cs +++ b/Unit Tests/Accord.Tests.Math/HilbertTransformTest.cs @@ -23,32 +23,15 @@ namespace Accord.Tests.Math { using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using AForge.Math; + using System.Numerics; - [TestClass()] + [TestFixture] public class HilbertTransformTest { - - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - - - [TestMethod()] + [Test] public void FHTTest() { Complex[] original = { (Complex)1, (Complex)2, (Complex)3, (Complex)4 }; @@ -56,15 +39,15 @@ public void FHTTest() Complex[] actual = (Complex[])original.Clone(); HilbertTransform.FHT(actual, FourierTransform.Direction.Forward); - Assert.AreEqual(actual[0].Re, 1); - Assert.AreEqual(actual[1].Re, 2); - Assert.AreEqual(actual[2].Re, 3); - Assert.AreEqual(actual[3].Re, 4); + Assert.AreEqual(actual[0].Real, 1); + Assert.AreEqual(actual[1].Real, 2); + Assert.AreEqual(actual[2].Real, 3); + Assert.AreEqual(actual[3].Real, 4); - Assert.AreEqual(actual[0].Im, +1, 0.000000001); - Assert.AreEqual(actual[1].Im, -1, 0.000000001); - Assert.AreEqual(actual[2].Im, -1, 0.000000001); - Assert.AreEqual(actual[3].Im, +1, 0.000000001); + Assert.AreEqual(actual[0].Imaginary, +1, 0.000000001); + Assert.AreEqual(actual[1].Imaginary, -1, 0.000000001); + Assert.AreEqual(actual[2].Imaginary, -1, 0.000000001); + Assert.AreEqual(actual[3].Imaginary, +1, 0.000000001); HilbertTransform.FHT(actual, FourierTransform.Direction.Backward); @@ -74,7 +57,7 @@ public void FHTTest() Assert.AreEqual(actual[3], original[3]); } - [TestMethod()] + [Test] public void FHTTest2() { double[] original = { -1.0, -0.8, -0.2, -0.1, 0.1, 0.2, 0.8, 1.0 }; diff --git a/Unit Tests/Accord.Tests.Math/IO/MatReaderTest.cs b/Unit Tests/Accord.Tests.Math/IO/MatReaderTest.cs index 2d232062c..bfc9527d8 100644 --- a/Unit Tests/Accord.Tests.Math/IO/MatReaderTest.cs +++ b/Unit Tests/Accord.Tests.Math/IO/MatReaderTest.cs @@ -25,15 +25,15 @@ namespace Accord.Tests.IO using Accord.IO; using Accord.Math; using Accord.Tests.Math.Properties; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using System.IO; - [TestClass()] + [TestFixture] public class MatReaderTest { - [TestMethod()] + [Test] public void ConstructorTest() { MemoryStream file = new MemoryStream(Resources.simplestruct); @@ -88,7 +88,7 @@ public void ConstructorTest() } - [TestMethod()] + [Test] public void readInt8() { MemoryStream file = new MemoryStream(Resources.int8); @@ -112,7 +112,7 @@ public void readInt8() Assert.IsTrue(expected.IsEqual(value)); } - [TestMethod()] + [Test] public void readInt32() { MemoryStream file = new MemoryStream(Resources.int32); @@ -136,7 +136,7 @@ public void readInt32() Assert.IsTrue(expected.IsEqual(value)); } - [TestMethod()] + [Test] public void readInt64() { MemoryStream file = new MemoryStream(Resources.int64); @@ -160,7 +160,7 @@ public void readInt64() Assert.IsTrue(expected.IsEqual(value)); } - [TestMethod()] + [Test] public void readInt64_2() { MemoryStream file = new MemoryStream(Resources.a64); @@ -188,7 +188,7 @@ public void readInt64_2() Assert.IsTrue(expected.IsEqual(value)); } - [TestMethod()] + [Test] public void readUInt64() { MemoryStream file = new MemoryStream(Resources.uint64); @@ -212,7 +212,7 @@ public void readUInt64() Assert.IsTrue(expected.IsEqual(value)); } - [TestMethod()] + [Test] public void readSingle() { MemoryStream file = new MemoryStream(Resources.single); @@ -236,7 +236,7 @@ public void readSingle() Assert.IsTrue(expected.IsEqual(value)); } - [TestMethod()] + [Test] public void readDouble() { MemoryStream file = new MemoryStream(Resources.matnativedouble); @@ -262,7 +262,7 @@ public void readDouble() Assert.IsTrue(expected.IsEqual(value)); } - [TestMethod()] + [Test] public void readDouble2() { MemoryStream file = new MemoryStream(Resources.matnativedouble2); @@ -288,7 +288,7 @@ public void readDouble2() Assert.IsTrue(expected.IsEqual(value)); } - [TestMethod()] + [Test] public void readLogical() { MemoryStream file = new MemoryStream(Resources.logical); @@ -312,7 +312,7 @@ public void readLogical() Assert.IsTrue(expected.IsEqual(value)); } - [TestMethod()] + [Test] public void readStruct() { MemoryStream file = new MemoryStream(Resources.simplestruct); @@ -346,7 +346,7 @@ public void readStruct() Assert.AreEqual("ala ma kota", s); } - [TestMethod()] + [Test] public void readCell() { MemoryStream file = new MemoryStream(Resources.cell); diff --git a/Unit Tests/Accord.Tests.Math/Integration/IntegralTest.cs b/Unit Tests/Accord.Tests.Math/Integration/IntegralTest.cs index 4c93b0fec..5cc580c6c 100644 --- a/Unit Tests/Accord.Tests.Math/Integration/IntegralTest.cs +++ b/Unit Tests/Accord.Tests.Math/Integration/IntegralTest.cs @@ -24,11 +24,10 @@ namespace Accord.Tests.Math { using Accord.Math; using Accord.Math.Integration; - using AccordTestsMathCpp2; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; - [TestClass()] + [TestFixture] public class IntegralTest { @@ -37,7 +36,7 @@ private static double function1(double x) return 2 + Math.Cos(2 * Math.Sqrt(x)); } - [TestMethod()] + [Test] public void TrapezoidalTest() { double actual; @@ -63,7 +62,7 @@ public void TrapezoidalTest() Assert.IsFalse(Double.IsNaN(actual)); } - [TestMethod()] + [Test] public void MultipleTests_Examples() { // Let's say we would like to compute the definite @@ -99,7 +98,7 @@ private static double function2(double x) return 1 / x; } - [TestMethod()] + [Test] public void RombergTest() { // Example from http://www.mathstat.dal.ca/~tkolokol/classes/1500/romberg.pdf @@ -128,7 +127,7 @@ public static double function3(double x) return x * Math.Exp(-(x * x)); } - [TestMethod()] + [Test] public void GaussKronrodTest() { double expected = Math.Sin(2); @@ -137,26 +136,5 @@ public void GaussKronrodTest() Assert.AreEqual(expected, actual, 1e-6); } - [TestMethod()] - public void InfiniteGaussKronrodTest() - { - for (int i = -10; i < 10; i++) - { - Func pdf = (x) => Normal.Derivative(x - i); - - Func E = (x) => x * pdf(x); - UFunction UE = (x) => x * pdf(x); - - double expected = Quadpack.Integrate(UE, - Double.NegativeInfinity, Double.PositiveInfinity); - - double actual = InfiniteAdaptiveGaussKronrod.Integrate(E, - Double.NegativeInfinity, Double.PositiveInfinity); - - Assert.AreEqual(expected, actual, 1e-3); - Assert.AreEqual(i, actual, 1e-3); - } - } - } } diff --git a/Unit Tests/Accord.Tests.Math/Integration/MonteCarloTest.cs b/Unit Tests/Accord.Tests.Math/Integration/MonteCarloTest.cs index 702f10bd1..d1297de9d 100644 --- a/Unit Tests/Accord.Tests.Math/Integration/MonteCarloTest.cs +++ b/Unit Tests/Accord.Tests.Math/Integration/MonteCarloTest.cs @@ -23,14 +23,14 @@ namespace Accord.Tests.Math { using Accord.Math.Integration; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; - [TestClass()] + [TestFixture] public class MonteCarloIntegralTest { - [TestMethod()] + [Test] public void MonteCarloTest() { Accord.Math.Tools.SetupGenerator(0); diff --git a/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Common.cs b/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Common.cs index 6ec573e3b..d9ebd0eba 100644 --- a/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Common.cs +++ b/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Common.cs @@ -23,13 +23,13 @@ namespace Accord.Tests.Math { using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; public partial class MatrixTest { #region Reshape - [TestMethod()] + [Test] public void ReshapeTest() { int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; @@ -49,7 +49,7 @@ public void ReshapeTest() } - [TestMethod()] + [Test] public void ReshapeTest1() { double[,] array = @@ -69,7 +69,7 @@ public void ReshapeTest1() Assert.IsTrue(Matrix.IsEqual(expected, actual)); } - [TestMethod()] + [Test] public void ReshapeTest2() { double[][] array = @@ -91,7 +91,7 @@ public void ReshapeTest2() } } - [TestMethod()] + [Test] public void ReshapeTest3() { double[][] array = @@ -115,7 +115,7 @@ public void ReshapeTest3() #endregion - [TestMethod()] + [Test] public void RelativelyEqualsTest() { Assert.IsFalse(double.PositiveInfinity.IsRelativelyEqual(1, 1e-10)); diff --git a/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Complex.cs b/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Complex.cs index 123f96532..3e08c6cb9 100644 --- a/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Complex.cs +++ b/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Complex.cs @@ -1,138 +1,123 @@ -// Accord Unit Tests -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Tests.Math -{ - using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using System; - using AForge.Math; - using AForge; - - [TestClass()] - public class ComplexMatrixTest - { - - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - - [TestMethod()] - public void AbsTest() - { - Complex[] x = { new Complex(1, 5), new Complex(2, -1), new Complex(-5, 1) }; - Complex[] expected = { new Complex(Math.Sqrt(26), 0), new Complex(Math.Sqrt(5), 0), new Complex(Math.Sqrt(26), 0) }; - Complex[] actual = ComplexMatrix.Abs(x); - Assert.IsTrue(expected.IsEqual(actual, 1e-5)); - } - - [TestMethod()] - public void ImTest() - { - Complex[] x = { new Complex(1, 5), new Complex(2, -1), new Complex(-5, 1) }; - double[] expected = { 5, -1, 1 }; - double[] actual = ComplexMatrix.Im(x); - Assert.IsTrue(expected.IsEqual(actual)); - } - - [TestMethod()] - public void MagnitudeTest() - { - Complex[] x = { new Complex(1, 5), new Complex(2, -1), new Complex(-5, 1) }; - double[] expected = { Math.Sqrt(26), Math.Sqrt(5), Math.Sqrt(26) }; - double[] actual = ComplexMatrix.Magnitude(x); - - Assert.IsTrue(expected.IsEqual(actual)); - } - - [TestMethod()] - public void MultiplyTest() - { - Complex[] a = { new Complex(7, 5), new Complex(2, -3), new Complex(-5, 1) }; - Complex[] b = { new Complex(1, 5), new Complex(8, -1), new Complex(-4, 8) }; - Complex[] expected = { new Complex(-18, 40), new Complex(13, -26), new Complex(12, -44) }; - Complex[] actual = ComplexMatrix.Multiply(a, b); - - Assert.IsTrue(expected.IsEqual(actual)); - } - - [TestMethod()] - public void PhaseTest() - { - Complex[] x = { new Complex(0, 5), new Complex(2, 0), new Complex(-5, 1) }; - double[] expected = { 1, Math.Sqrt(5), Math.Sqrt(26) }; - double[] actual = ComplexMatrix.Phase(x); - - for (int i = 0; i < x.Length; i++) - Assert.AreEqual(x[i].Phase, Math.Atan2(x[i].Im, x[i].Re)); - } - - - [TestMethod()] - public void ReTest() - { - Complex[] x = { new Complex(1, 5), new Complex(2, -1), new Complex(-5, 1) }; - double[] expected = { 1, 2, -5 }; - double[] actual = ComplexMatrix.Re(x); - - Assert.IsTrue(expected.IsEqual(actual)); - } - - [TestMethod()] - public void SumTest() - { - Complex[] x = { new Complex(1, 5), new Complex(2, -1), new Complex(-5, 1) }; - Complex expected = new Complex(-2, 5); - Complex actual = ComplexMatrix.Sum(x); - - Assert.AreEqual(expected, actual); - } - - [TestMethod()] - public void ToArrayTest() - { - Complex[] c = { new Complex(1, 5), new Complex(2, -1), new Complex(-5, 1) }; - double[,] expected = - { - { 1, 5 }, - { 2, -1 }, - { -5, 1 }, - }; - - double[,] actual = ComplexMatrix.ToArray(c); - - Assert.IsTrue(expected.IsEqual(actual)); - } - } -} +// Accord Unit Tests +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Tests.Math +{ + using Accord.Math; + using NUnit.Framework; + using System; + using AForge.Math; + using AForge; + using System.Numerics; + + [TestFixture] + public class ComplexMatrixTest + { + + [Test] + public void AbsTest() + { + Complex[] x = { new Complex(1, 5), new Complex(2, -1), new Complex(-5, 1) }; + Complex[] expected = { new Complex(Math.Sqrt(26), 0), new Complex(Math.Sqrt(5), 0), new Complex(Math.Sqrt(26), 0) }; + Complex[] actual = ComplexMatrix.Abs(x); + Assert.IsTrue(expected.IsEqual(actual, 1e-5)); + } + + [Test] + public void ImTest() + { + Complex[] x = { new Complex(1, 5), new Complex(2, -1), new Complex(-5, 1) }; + double[] expected = { 5, -1, 1 }; + double[] actual = ComplexMatrix.Im(x); + Assert.IsTrue(expected.IsEqual(actual)); + } + + [Test] + public void MagnitudeTest() + { + Complex[] x = { new Complex(1, 5), new Complex(2, -1), new Complex(-5, 1) }; + double[] expected = { Math.Sqrt(26), Math.Sqrt(5), Math.Sqrt(26) }; + double[] actual = ComplexMatrix.Magnitude(x); + + Assert.IsTrue(expected.IsEqual(actual, 1e-12)); + } + + [Test] + public void MultiplyTest() + { + Complex[] a = { new Complex(7, 5), new Complex(2, -3), new Complex(-5, 1) }; + Complex[] b = { new Complex(1, 5), new Complex(8, -1), new Complex(-4, 8) }; + Complex[] expected = { new Complex(-18, 40), new Complex(13, -26), new Complex(12, -44) }; + Complex[] actual = ComplexMatrix.Multiply(a, b); + + Assert.IsTrue(expected.IsEqual(actual)); + } + + [Test] + public void PhaseTest() + { + Complex[] x = { new Complex(0, 5), new Complex(2, 0), new Complex(-5, 1) }; + double[] expected = { 1, Math.Sqrt(5), Math.Sqrt(26) }; + double[] actual = ComplexMatrix.Phase(x); + + for (int i = 0; i < x.Length; i++) + Assert.AreEqual(x[i].Phase, Math.Atan2(x[i].Imaginary, x[i].Real)); + } + + + [Test] + public void ReTest() + { + Complex[] x = { new Complex(1, 5), new Complex(2, -1), new Complex(-5, 1) }; + double[] expected = { 1, 2, -5 }; + double[] actual = ComplexMatrix.Re(x); + + Assert.IsTrue(expected.IsEqual(actual)); + } + + [Test] + public void SumTest() + { + Complex[] x = { new Complex(1, 5), new Complex(2, -1), new Complex(-5, 1) }; + Complex expected = new Complex(-2, 5); + Complex actual = ComplexMatrix.Sum(x); + + Assert.AreEqual(expected, actual); + } + + [Test] + public void ToArrayTest() + { + Complex[] c = { new Complex(1, 5), new Complex(2, -1), new Complex(-5, 1) }; + double[,] expected = + { + { 1, 5 }, + { 2, -1 }, + { -5, 1 }, + }; + + double[,] actual = ComplexMatrix.ToArray(c); + + Assert.IsTrue(expected.IsEqual(actual)); + } + } +} diff --git a/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Construction.cs b/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Construction.cs index bec680cb9..adc5f9737 100644 --- a/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Construction.cs +++ b/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Construction.cs @@ -23,13 +23,13 @@ namespace Accord.Tests.Math { using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; public partial class MatrixTest { - [TestMethod()] + [Test] public void StackTest() { var x1 = Vector.Ones(1000); diff --git a/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Conversion.cs b/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Conversion.cs index b283f3825..44fcf8bbc 100644 --- a/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Conversion.cs +++ b/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Conversion.cs @@ -1,83 +1,100 @@ -// Accord Unit Tests -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Tests.Math -{ - using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using System.Collections.Generic; - using System; - using System.Data; - using AForge; - - public partial class MatrixTest - { - - [TestMethod()] - public void ToTableTest() - { - double[,] matrix = - { - { 1, 2 }, - { 3, 4 }, - { 5, 6 }, - }; - - string[] columnNames = { "A", "B", }; - DataTable actual = Matrix.ToTable(matrix, columnNames); - - Assert.AreEqual("A", actual.Columns[0].ColumnName); - Assert.AreEqual("B", actual.Columns[1].ColumnName); - - Assert.AreEqual(1, (double)actual.Rows[0][0]); - Assert.AreEqual(2, (double)actual.Rows[0][1]); - Assert.AreEqual(3, (double)actual.Rows[1][0]); - Assert.AreEqual(4, (double)actual.Rows[1][1]); - Assert.AreEqual(5, (double)actual.Rows[2][0]); - Assert.AreEqual(6, (double)actual.Rows[2][1]); - } - - [TestMethod()] - public void FromTableToArrayTest() - { - DataTable table = new DataTable(); - table.Columns.Add("A", typeof(bool)); - table.Columns.Add("B", typeof(string)); - table.Rows.Add(true, "1.0"); - table.Rows.Add(true, "0"); - table.Rows.Add(false, "1"); - table.Rows.Add(false, "0.0"); - - double[][] actual = table.ToArray(System.Globalization.CultureInfo.InvariantCulture); - double[][] expected = - { - new double[] { 1, 1 }, - new double[] { 1, 0 }, - new double[] { 0, 1 }, - new double[] { 0, 0 }, - }; - - Assert.IsTrue(expected.IsEqual(actual)); - } - - } -} +// Accord Unit Tests +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Tests.Math +{ + using Accord.Math; + using NUnit.Framework; + using System.Data; + + public partial class MatrixTest + { + + [Test] + public void ToTableTest() + { + double[,] matrix = + { + { 1, 2 }, + { 3, 4 }, + { 5, 6 }, + }; + + string[] columnNames = { "A", "B", }; + DataTable actual = Matrix.ToTable(matrix, columnNames); + + Assert.AreEqual("A", actual.Columns[0].ColumnName); + Assert.AreEqual("B", actual.Columns[1].ColumnName); + + Assert.AreEqual(1, (double)actual.Rows[0][0]); + Assert.AreEqual(2, (double)actual.Rows[0][1]); + Assert.AreEqual(3, (double)actual.Rows[1][0]); + Assert.AreEqual(4, (double)actual.Rows[1][1]); + Assert.AreEqual(5, (double)actual.Rows[2][0]); + Assert.AreEqual(6, (double)actual.Rows[2][1]); + } + + [Test] + public void ToTableTest2() + { + double[][] matrix = + { + new double[] { 1, 2 }, + new double[] { 3, 4 }, + new double[] { 5, 6 }, + }; + + DataTable actual = Matrix.ToTable(matrix); + + Assert.AreEqual(1, (double)actual.Rows[0][0]); + Assert.AreEqual(2, (double)actual.Rows[0][1]); + Assert.AreEqual(3, (double)actual.Rows[1][0]); + Assert.AreEqual(4, (double)actual.Rows[1][1]); + Assert.AreEqual(5, (double)actual.Rows[2][0]); + Assert.AreEqual(6, (double)actual.Rows[2][1]); + } + + [Test] + public void FromTableToArrayTest() + { + DataTable table = new DataTable(); + table.Columns.Add("A", typeof(bool)); + table.Columns.Add("B", typeof(string)); + table.Rows.Add(true, "1.0"); + table.Rows.Add(true, "0"); + table.Rows.Add(false, "1"); + table.Rows.Add(false, "0.0"); + + double[][] actual = table.ToArray(System.Globalization.CultureInfo.InvariantCulture); + double[][] expected = + { + new double[] { 1, 1 }, + new double[] { 1, 0 }, + new double[] { 0, 1 }, + new double[] { 0, 0 }, + }; + + Assert.IsTrue(expected.IsEqual(actual)); + } + + } +} diff --git a/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Format.cs b/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Format.cs index a7bc26503..8c3be0a4b 100644 --- a/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Format.cs +++ b/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Format.cs @@ -23,11 +23,11 @@ namespace Accord.Tests.Math { using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System.Collections.Generic; using System; - [TestClass()] + [TestFixture] public class MatrixFormatTest { @@ -46,7 +46,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void ParseTest1() { // Parsing a matrix from Octave format @@ -66,7 +66,7 @@ public void ParseTest1() } - [TestMethod()] + [Test] public void ParseTest() { string str; @@ -110,7 +110,7 @@ public void ParseTest() Assert.IsTrue(actual.IsEqual(expected)); } - [TestMethod()] + [Test] public void ParseJaggedTest() { string str; @@ -154,7 +154,7 @@ public void ParseJaggedTest() Assert.IsTrue(actual.IsEqual(expected)); } - [TestMethod()] + [Test] public void ToStringTest() { double[,] matrix = @@ -191,7 +191,7 @@ public void ToStringTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void ToStringTest2() { double[][] matrix = @@ -228,7 +228,7 @@ public void ToStringTest2() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void StringFormat() { double[,] matrix = @@ -281,7 +281,7 @@ public void StringFormat() } - [TestMethod()] + [Test] public void StringFormat2() { double[][] matrix = @@ -311,7 +311,7 @@ public void StringFormat2() } - [TestMethod()] + [Test] public void ToStringTest3() { double[] x = { 1, 2, 3 }; diff --git a/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Multiply.cs b/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Multiply.cs index 356a98bb2..0705ca029 100644 --- a/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Multiply.cs +++ b/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Multiply.cs @@ -23,7 +23,7 @@ namespace Accord.Tests.Math { using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System.Collections.Generic; using System; using System.Data; @@ -31,7 +31,7 @@ namespace Accord.Tests.Math partial class MatrixTest { - [TestMethod()] + [Test] public void TransposeAndMultiplyByDiagonalTest() { double[,] a = @@ -48,7 +48,7 @@ public void TransposeAndMultiplyByDiagonalTest() Assert.IsTrue(Matrix.IsEqual(expected, actual, 1e-10)); } - [TestMethod()] + [Test] public void MultiplyTwoMatrices() { double[,] a = new double[,] @@ -76,7 +76,7 @@ public void MultiplyTwoMatrices() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.0001)); } - [TestMethod()] + [Test] public void MultiplyTwoMatrices2() { float[,] a = @@ -103,7 +103,7 @@ public void MultiplyTwoMatrices2() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.0001f)); } - [TestMethod()] + [Test] public void MultiplyTwoMatrices3() { double[][] a = new double[,] @@ -130,7 +130,7 @@ public void MultiplyTwoMatrices3() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.0001)); } - [TestMethod()] + [Test] public void MultiplyVectorMatrixTest() { double[] a = { 1.000, 2.000, 3.000 }; @@ -147,7 +147,7 @@ public void MultiplyVectorMatrixTest() } - [TestMethod()] + [Test] public void MultiplyMatrixVectorTest() { double[,] a = @@ -165,7 +165,7 @@ public void MultiplyMatrixVectorTest() } - [TestMethod()] + [Test] public void MultiplyByDiagonalTest() { double[,] A = @@ -191,7 +191,7 @@ public void MultiplyByDiagonalTest() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod] + [Test] public void MultiplyByTransposeTest() { double[,] a = Matrix.Magic(5); @@ -202,7 +202,7 @@ public void MultiplyByTransposeTest() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod] + [Test] public void MultiplyByTransposeTest2() { double[,] a = Matrix.Random(2, 3); @@ -215,7 +215,7 @@ public void MultiplyByTransposeTest2() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void TransposeAndMultiplyTest() { double[,] a = Matrix.Random(2, 3); diff --git a/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Submatrix.cs b/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Submatrix.cs index 1760c2d97..0e0a08063 100644 --- a/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Submatrix.cs +++ b/Unit Tests/Accord.Tests.Math/Matrix/Matrix.Submatrix.cs @@ -23,7 +23,7 @@ namespace Accord.Tests.Math { using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System.Collections.Generic; using System; using System.Data; @@ -33,7 +33,7 @@ public partial class MatrixTest { - [TestMethod()] + [Test] public void MatrixSubmatrix() { double[,] value = new double[,] @@ -54,7 +54,7 @@ public void MatrixSubmatrix() Assert.IsTrue(Matrix.IsEqual(actual, expected)); } - [TestMethod()] + [Test] public void MatrixSubmatrix2() { double[,] value = new double[,] @@ -82,7 +82,7 @@ public void MatrixSubmatrix2() Assert.IsTrue(Matrix.IsEqual(actual, value)); } - [TestMethod()] + [Test] public void SubmatrixTest() { double[][] data = @@ -121,7 +121,7 @@ public void SubmatrixTest() Assert.IsTrue(Matrix.IsEqual(expected2, actual2)); } - [TestMethod()] + [Test] public void SubmatrixTest1() { double[,] value = new double[,] @@ -161,7 +161,7 @@ public void SubmatrixTest1() Assert.IsTrue(Matrix.IsEqual(actual, value)); } - [TestMethod()] + [Test] public void SubgroupTest2() { double[] value = { 1, 2, 3, 4, 5, 6, 7 }; @@ -184,7 +184,7 @@ public void SubgroupTest2() Assert.AreEqual(groups[1][3], 7); } - [TestMethod()] + [Test] public void SubgroupTest3() { double[] value = { 1, 2, 3, 4, 5, 6, 7 }; diff --git a/Unit Tests/Accord.Tests.Math/Matrix/MatrixTest.cs b/Unit Tests/Accord.Tests.Math/Matrix/MatrixTest.cs index b26fd3bc0..2bdedc0ae 100644 --- a/Unit Tests/Accord.Tests.Math/Matrix/MatrixTest.cs +++ b/Unit Tests/Accord.Tests.Math/Matrix/MatrixTest.cs @@ -29,30 +29,14 @@ namespace Accord.Tests.Math using Accord.Math; using Accord.Math.Decompositions; using AForge; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public partial class MatrixTest { - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - #region Comparison - [TestMethod()] + [Test] public void IsEqualTest1() { double[,] a = @@ -71,7 +55,7 @@ public void IsEqualTest1() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void IsEqualTest2() { double[,] a = @@ -94,7 +78,7 @@ public void IsEqualTest2() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void IsEqualTest3() { double[] a = { 1, 1, 1 }; @@ -109,7 +93,7 @@ public void IsEqualTest3() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void IsEqualTest() { double[,] matrix = Matrix.Create(2, 2, 1.0); @@ -125,7 +109,7 @@ public void IsEqualTest() #endregion #region Matrix and vector creation - [TestMethod()] + [Test] public void ColumnVectorTest() { double[] values = { 1, 2, 3 }; @@ -139,7 +123,7 @@ public void ColumnVectorTest() Assert.IsTrue(Matrix.IsEqual(expected, actual)); } - [TestMethod()] + [Test] public void RowVectorTest() { double[] values = { 1, 2, 3 }; @@ -151,7 +135,7 @@ public void RowVectorTest() Assert.IsTrue(Matrix.IsEqual(expected, actual)); } - [TestMethod()] + [Test] public void DiagonalTest() { int rows = 2; @@ -169,7 +153,7 @@ public void DiagonalTest() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void DiagonalTest2() { int rows = 3; @@ -188,7 +172,7 @@ public void DiagonalTest2() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void IntervalTest2() { double from = 0; @@ -200,7 +184,7 @@ public void IntervalTest2() Assert.IsTrue(Matrix.IsEqual(expected, actual)); } - [TestMethod()] + [Test] public void IntervalTest3() { double[] actual; @@ -213,7 +197,7 @@ public void IntervalTest3() Assert.AreEqual(actual.Length, 1); } - [TestMethod()] + [Test] public void IntervalTest4() { double[] actual; @@ -226,7 +210,7 @@ public void IntervalTest4() Assert.AreEqual(actual.Length, 1); } - [TestMethod()] + [Test] public void IntervalTest2Inverse() { double from = 10; @@ -238,7 +222,7 @@ public void IntervalTest2Inverse() Assert.IsTrue(Matrix.IsEqual(expected.Reverse().ToArray(), actual)); } - [TestMethod()] + [Test] public void IntervalTest1() { int from = -2; @@ -249,7 +233,7 @@ public void IntervalTest1() Assert.IsTrue(Matrix.IsEqual(expected, actual)); } - [TestMethod()] + [Test] public void IntervalTest() { double from = -1; @@ -261,7 +245,7 @@ public void IntervalTest() Assert.IsTrue(Matrix.IsEqual(expected, Matrix.Round(actual, 15))); } - [TestMethod()] + [Test] public void IntervalTestInverse() { double from = 1; @@ -273,7 +257,7 @@ public void IntervalTestInverse() Assert.IsTrue(Matrix.IsEqual(expected.Reverse().ToArray(), Matrix.Round(actual, 15))); } - [TestMethod()] + [Test] public void IndexesTest() { int from = -1; @@ -283,7 +267,7 @@ public void IndexesTest() Assert.IsTrue(Matrix.IsEqual(expected, actual)); } - [TestMethod()] + [Test] public void IndexesTestInverse() { int from = 6; @@ -295,7 +279,7 @@ public void IndexesTestInverse() #endregion #region Elementwise Operations - [TestMethod()] + [Test] public void ElementwiseMultiplyTest() { double[] a = { 5, 2, 1 }; @@ -305,7 +289,7 @@ public void ElementwiseMultiplyTest() Assert.IsTrue(Matrix.IsEqual(expected, actual)); } - [TestMethod()] + [Test] public void ElementwiseDivideTest2() { double[] a = { 5, 2, 1 }; @@ -315,7 +299,7 @@ public void ElementwiseDivideTest2() Assert.IsTrue(Matrix.IsEqual(expected, actual)); } - [TestMethod()] + [Test] public void ElementwiseDivideTest1() { double[,] a = @@ -340,7 +324,7 @@ public void ElementwiseDivideTest1() Assert.IsTrue(Matrix.IsEqual(expected, actual)); } - [TestMethod()] + [Test] public void ElementwiseDivideTest() { double[,] a = @@ -373,7 +357,7 @@ public void ElementwiseDivideTest() Assert.IsTrue(Matrix.IsEqual(expected, actual)); } - [TestMethod()] + [Test] public void DivideTest1() { double scalar = -2; @@ -393,7 +377,7 @@ public void DivideTest1() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void DivideTest4() { float[] vector = { 4.2f, 1.2f }; @@ -403,7 +387,7 @@ public void DivideTest4() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void ElementwiseMultiplyTest1() { double[,] a = @@ -428,7 +412,7 @@ public void ElementwiseMultiplyTest1() Assert.IsTrue(Matrix.IsEqual(expected, actual)); } - [TestMethod()] + [Test] public void ElementwisePowerTest() { double[] x = { 1, 2, 3 }; @@ -438,7 +422,7 @@ public void ElementwisePowerTest() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void ElementwiseMultiplyTest3() { double[] a = { 0.20, 1.65 }; @@ -448,7 +432,7 @@ public void ElementwiseMultiplyTest3() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void ElementwiseMultiplyTest2() { int[,] a = @@ -473,7 +457,7 @@ public void ElementwiseMultiplyTest2() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void AddTest() { double[,] a = @@ -498,7 +482,7 @@ public void AddTest() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void AddTest1() { double[][] a = @@ -523,7 +507,7 @@ public void AddTest1() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void AddToDiagTest1() { double[,] a = @@ -545,7 +529,7 @@ public void AddToDiagTest1() Assert.IsTrue(actual.IsEqual(a)); } - [TestMethod()] + [Test] public void AddToDiagTest2() { double[][] a = @@ -567,7 +551,7 @@ public void AddToDiagTest2() Assert.IsTrue(actual.IsEqual(a)); } - [TestMethod()] + [Test] public void ElementwiseMultiplyTest4() { double[,] a = @@ -601,7 +585,7 @@ public void ElementwiseMultiplyTest4() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void SubtractTest() { double[,] a = @@ -626,7 +610,7 @@ public void SubtractTest() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void ElementwiseMultiplyTest5() { int[] a = { 2, 1, 6, 1 }; @@ -638,7 +622,7 @@ public void ElementwiseMultiplyTest5() Assert.IsTrue(Matrix.IsEqual(expected, actual)); } - [TestMethod()] + [Test] public void AddMatrixAndVectorTest() { double[,] a = Matrix.Create(3, 5, 0.0); @@ -674,7 +658,7 @@ public void AddMatrixAndVectorTest() } - [TestMethod()] + [Test] public void SubtractTest1() { double a = 0.1; @@ -695,7 +679,7 @@ public void SubtractTest1() Assert.IsTrue(expected.IsEqual(actual, 1e-6)); } - [TestMethod()] + [Test] public void AbsTest() { double[,] value = @@ -736,7 +720,7 @@ public void AbsTest() Assert.IsTrue(aactual.IsEqual(aexpected)); } - [TestMethod()] + [Test] public void SqrtTest() { double[,] value = @@ -757,7 +741,7 @@ public void SqrtTest() #endregion #region Conversions - [TestMethod()] + [Test] public void ToMatrixTest() { double[] array = { 1, 5, 2 }; @@ -766,7 +750,7 @@ public void ToMatrixTest() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void ToArrayTest() { DataTable table = new DataTable("myData"); @@ -794,7 +778,7 @@ public void ToArrayTest() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void ToArrayTest1() { DataTable table = new DataTable("myData"); @@ -826,7 +810,7 @@ public void ToArrayTest1() Assert.IsTrue(expectedNames.IsEqual(actualNames)); } - [TestMethod()] + [Test] public void ToMatrixTest2() { DataTable table = new DataTable("myData"); @@ -858,7 +842,7 @@ public void ToMatrixTest2() Assert.IsTrue(expectedNames.IsEqual(actualNames)); } - [TestMethod()] + [Test] public void ToDoubleTest() { float[,] matrix = @@ -879,7 +863,7 @@ public void ToDoubleTest() #endregion #region Sum and Product - [TestMethod()] + [Test] public void ProductsTest1() { double[] u = { 1, 6, 3 }; @@ -938,7 +922,7 @@ public void ProductsTest1() Assert.IsTrue(new double[,] { { 29, 15 }, { 15, 30 } }.IsEqual(mmt)); } - [TestMethod()] + [Test] public void SumTest() { double[,] value = @@ -961,7 +945,7 @@ public void SumTest() } - [TestMethod()] + [Test] public void SumTest1() { double[] value = { 1, 2, 3 }; @@ -970,7 +954,7 @@ public void SumTest1() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void SumTest2() { int[,] value = @@ -995,7 +979,7 @@ public void SumTest2() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void SumTest4() { double[,] value = @@ -1020,7 +1004,7 @@ public void SumTest4() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void SumTest5() { int[] value = { 9, -2, 1 }; @@ -1029,7 +1013,7 @@ public void SumTest5() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void SumTest6() { double[] value = { 9.2, -2, 1 }; @@ -1038,7 +1022,7 @@ public void SumTest6() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void CumulativeSumTest() { double[] expected1 = { 1, 3, 6, 10, 15 }; @@ -1072,7 +1056,7 @@ public void CumulativeSumTest() Assert.IsTrue(actual3.IsEqual(expected3)); } - [TestMethod()] + [Test] public void ProductTest() { double[] value = { -1, 2.4, 7 }; @@ -1081,7 +1065,7 @@ public void ProductTest() Assert.AreEqual(expected, actual, 0.00001); } - [TestMethod()] + [Test] public void ProductTest1() { int[] value = { -1, 2, 7 }; @@ -1092,7 +1076,7 @@ public void ProductTest1() #endregion #region Combine - [TestMethod()] + [Test] public void CombineTest() { int[][,] matrices = @@ -1129,7 +1113,7 @@ public void CombineTest() Assert.IsTrue(Matrix.IsEqual(expected, actual)); } - [TestMethod()] + [Test] public void CombineTest1() { double[][] vectors = new double[][] @@ -1147,7 +1131,7 @@ public void CombineTest1() } - [TestMethod()] + [Test] public void CombineTest3() { double[] a1 = new double[] { 1, 2 }; @@ -1159,7 +1143,7 @@ public void CombineTest3() Assert.IsTrue(Matrix.IsEqual(expected, actual)); } - [TestMethod()] + [Test] public void CombineTest4() { double[] a1 = new double[] { 1, 2 }; @@ -1171,7 +1155,7 @@ public void CombineTest4() Assert.IsTrue(Matrix.IsEqual(expected, actual)); } - [TestMethod()] + [Test] public void ConcatenateTest2() { double[][] a = @@ -1206,7 +1190,7 @@ public void ConcatenateTest2() } } - [TestMethod()] + [Test] public void CombineTest5() { double[,] A = Matrix.Create(2, 2.0); @@ -1220,14 +1204,14 @@ public void CombineTest5() { 1, 1 } }; - double[,] actual = Matrix.Stack(A, B); + double[,] actual = Matrix.Stack(new [] { A, B }); Assert.IsTrue(Matrix.IsEqual(expected, actual)); } #endregion #region Vectorial Products - [TestMethod()] + [Test] public void OuterProductTest() { double[] a = { 1, 2, 3, 4 }; @@ -1245,7 +1229,7 @@ public void OuterProductTest() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void CartesianProductTest() { int[][] sequences = @@ -1274,7 +1258,7 @@ public void CartesianProductTest() } - [TestMethod()] + [Test] public void CartesianProductTest2() { int[][] sequences = @@ -1297,7 +1281,7 @@ public void CartesianProductTest2() } - [TestMethod()] + [Test] public void CartesianProductTest3() { int[][] sequences = @@ -1322,7 +1306,7 @@ public void CartesianProductTest3() #endregion #region Inverse, division and solving - [TestMethod()] + [Test] public void InverseTest2x2() { double[,] value = @@ -1338,7 +1322,7 @@ public void InverseTest2x2() Assert.IsTrue(Matrix.IsEqual(expected, actual, 1e-6)); } - [TestMethod()] + [Test] public void InverseTest3x3() { double[,] value = @@ -1357,7 +1341,7 @@ public void InverseTest3x3() Assert.IsTrue(Matrix.IsEqual(expected, actual, 1e-6)); } - [TestMethod()] + [Test] public void PseudoInverse() { double[,] value = new double[,] @@ -1374,7 +1358,7 @@ public void PseudoInverse() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.001)); } - [TestMethod()] + [Test] public void PseudoInverse1() { double[,] value = @@ -1397,7 +1381,7 @@ public void PseudoInverse1() Assert.IsTrue(Matrix.IsEqual(expected.Transpose(), actual, 0.001)); } - [TestMethod()] + [Test] public void PseudoInverse2() { double[,] X = @@ -1416,7 +1400,7 @@ public void PseudoInverse2() Assert.IsTrue(expected.IsEqual(actual, 0.001)); } - [TestMethod()] + [Test] public void PseudoInverse3() { double[,] X = @@ -1434,7 +1418,7 @@ public void PseudoInverse3() Assert.IsTrue(expected.IsEqual(actual, 0.001)); } - [TestMethod()] + [Test] public void SolveTest() { double[,] value = @@ -1458,7 +1442,7 @@ public void SolveTest() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.001)); } - [TestMethod()] + [Test] public void SolveTest2() { double[,] value = @@ -1477,7 +1461,7 @@ public void SolveTest2() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.0000000000001)); } - [TestMethod()] + [Test] public void DivideTest() { double[,] a = @@ -1505,7 +1489,7 @@ public void DivideTest() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.001)); } - [TestMethod()] + [Test] public void DivideTest2() { double[,] a = @@ -1533,7 +1517,7 @@ public void DivideTest2() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.001)); } - [TestMethod()] + [Test] public void DivideTest3() { double[,] a = @@ -1557,7 +1541,7 @@ public void DivideTest3() Assert.IsTrue(Matrix.IsEqual(a, actual, 0.001)); } - [TestMethod()] + [Test] public void DivideByDiagonalTest() { double[,] a = @@ -1581,7 +1565,7 @@ public void DivideByDiagonalTest() #endregion #region Matrix characteristics - [TestMethod()] + [Test] public void DeterminantTest() { double[,] m = @@ -1597,7 +1581,7 @@ public void DeterminantTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void DeterminantTest2() { double[,] m = @@ -1623,7 +1607,7 @@ public void DeterminantTest2() Assert.IsFalse(Double.IsNaN(det)); } - [TestMethod()] + [Test] public void DeterminantTest3() { double[,] m = @@ -1670,7 +1654,7 @@ public void DeterminantTest3() } - [TestMethod()] + [Test] public void PositiveDefiniteTest() { double[,] m = @@ -1684,7 +1668,7 @@ public void PositiveDefiniteTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void PositiveDefiniteTest2() { double[,] m = @@ -1699,7 +1683,7 @@ public void PositiveDefiniteTest2() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void PositiveDefiniteJaggedTest() { double[][] m = @@ -1713,7 +1697,7 @@ public void PositiveDefiniteJaggedTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void PositiveDefiniteJaggedTest2() { double[][] m = @@ -1728,7 +1712,7 @@ public void PositiveDefiniteJaggedTest2() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void TraceTest() { double[,] m = @@ -1744,7 +1728,7 @@ public void TraceTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void IsSymmetricTest() { double[,] matrix = @@ -1770,7 +1754,7 @@ public void IsSymmetricTest() } - [TestMethod()] + [Test] public void MaxMinTest1() { double[] a = { 5 }; @@ -1788,7 +1772,7 @@ public void MaxMinTest1() Assert.AreEqual(0, imax); } - [TestMethod()] + [Test] public void MaxMinTest() { double[,] matrix = new double[,] @@ -1840,7 +1824,7 @@ public void MaxMinTest() Assert.IsTrue(Matrix.IsEqual(expected, actual)); } - [TestMethod()] + [Test] public void UpperTriangularTest() { double[,] U = @@ -1877,7 +1861,7 @@ public void UpperTriangularTest() Assert.IsTrue(D.IsDiagonal()); } - [TestMethod()] + [Test] public void UpperTriangularTest2() { double[][] U = @@ -1916,7 +1900,7 @@ public void UpperTriangularTest2() #endregion #region Transpose - [TestMethod()] + [Test] public void TransposeTest() { int[] value = { 1, 5, 2 }; @@ -1931,7 +1915,7 @@ public void TransposeTest() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void TransposeTest2() { int[,] value = @@ -1959,7 +1943,7 @@ public void TransposeTest2() Assert.AreEqual(value, actual); } - [TestMethod()] + [Test] public void TransposeTest3() { double[][] matrix = new double[,] @@ -1981,7 +1965,7 @@ public void TransposeTest3() Assert.IsTrue(actual.IsEqual(expected)); } - [TestMethod()] + [Test] public void GeneralizedTransposeTest() { double[,] a = @@ -1998,7 +1982,7 @@ public void GeneralizedTransposeTest() #endregion #region Apply - [TestMethod()] + [Test] public void ApplyTest() { double[] data = { 42, 1, -5 }; @@ -2015,7 +1999,7 @@ public void ApplyTest() Assert.IsTrue(expected.IsEqual(data)); } - [TestMethod()] + [Test] public void ApplyTest2() { double[,] data = @@ -2041,7 +2025,7 @@ public void ApplyTest2() Assert.IsTrue(expected.IsEqual(data)); } - [TestMethod()] + [Test] public void ApplyTest3() { double[] data = { 42, 1, -5 }; @@ -2055,7 +2039,7 @@ public void ApplyTest3() Assert.AreNotEqual(actual, data); } - [TestMethod()] + [Test] public void ApplyTest4() { double[,] data = @@ -2078,7 +2062,7 @@ public void ApplyTest4() Assert.AreNotEqual(actual, data); } - [TestMethod()] + [Test] public void ApplyTest1() { int[,] matrix = @@ -2101,7 +2085,7 @@ public void ApplyTest1() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void ApplyTest5() { int[] matrix = { 1, 2, 3 }; @@ -2121,7 +2105,7 @@ public void ApplyTest5() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void ApplyInPlaceTest() { float[] vector = { 1, 2, 3 }; @@ -2135,7 +2119,7 @@ public void ApplyInPlaceTest() #endregion #region Floor, Ceiling, Rouding - [TestMethod()] + [Test] public void CeilingTest1() { double[] vector = { 0.1, 0.5, 1.5 }; @@ -2144,7 +2128,7 @@ public void CeilingTest1() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void CeilingTest() { double[,] matrix = @@ -2165,7 +2149,7 @@ public void CeilingTest() /// ///A test for Floor /// - [TestMethod()] + [Test] public void FloorTest1() { double[] vector = { 0.1, 0.5, 1.5 }; @@ -2177,7 +2161,7 @@ public void FloorTest1() /// ///A test for Floor /// - [TestMethod()] + [Test] public void FloorTest() { double[,] matrix = @@ -2197,7 +2181,7 @@ public void FloorTest() #endregion #region Power - [TestMethod()] + [Test] public void PowerTest() { double[,] a = Matrix.Magic(5); @@ -2206,7 +2190,7 @@ public void PowerTest() Assert.IsTrue(Matrix.IsEqual(expected, actual)); } - [TestMethod()] + [Test] public void PowerTest1() { double[,] a = Matrix.Identity(5); @@ -2215,7 +2199,7 @@ public void PowerTest1() Assert.IsTrue(Matrix.IsEqual(expected, actual)); } - [TestMethod()] + [Test] public void PowerTest2() { double[,] a = Matrix.Magic(5); @@ -2234,7 +2218,7 @@ public void PowerTest2() } #endregion - [TestMethod()] + [Test] public void ExpandTest() { double[][] data = @@ -2271,7 +2255,7 @@ public void ExpandTest() - [TestMethod()] + [Test] public void MagicTest() { var actual = Matrix.Magic(3); @@ -2313,7 +2297,7 @@ public void MagicTest() } - [TestMethod()] + [Test] public void FindTest() { double[,] data = @@ -2334,7 +2318,7 @@ public void FindTest() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void InsertColumnTest() { double[,] m = @@ -2355,7 +2339,7 @@ public void InsertColumnTest() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void InsertRowTest() { double[,] I = Matrix.Identity(3); @@ -2413,7 +2397,7 @@ public void InsertRowTest() Assert.IsTrue(actual.IsEqual(expected)); } - [TestMethod()] + [Test] public void InsertRowTest2() { double[,] a = @@ -2451,7 +2435,7 @@ public void InsertRowTest2() Assert.IsTrue(a.GetColumn(3).IsEqual(1, 2, 3, 100)); } - [TestMethod()] + [Test] public void InsertRowTest5() { double[][] a = @@ -2489,7 +2473,7 @@ public void InsertRowTest5() } - [TestMethod()] + [Test] public void InsertRowTest3() { double[,] a = @@ -2523,7 +2507,7 @@ public void InsertRowTest3() Assert.AreEqual(4, a.GetLength(1)); } - [TestMethod()] + [Test] public void InsertRowTest4() { double[][] a = @@ -2557,7 +2541,7 @@ public void InsertRowTest4() Assert.AreEqual(4, a[0].Length); } - [TestMethod()] + [Test] public void ConvolveTest() { double[] a = { 3, 4, 5 }; @@ -2579,7 +2563,7 @@ public void ConvolveTest() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void ConvolveTest2() { double[] a = { 3, 4, 5 }; @@ -2613,7 +2597,7 @@ public void ConvolveTest2() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void TensorProductTest() { double[,] a = @@ -2640,7 +2624,7 @@ public void TensorProductTest() Assert.IsTrue(Matrix.IsEqual(expected, actual)); } - [TestMethod()] + [Test] public void TensorProductTest2() { double[] a = { 1, 2 }; @@ -2656,7 +2640,7 @@ public void TensorProductTest2() - [TestMethod()] + [Test] public void ConcatenateTest() { double[,] matrix = @@ -2681,7 +2665,7 @@ public void ConcatenateTest() - [TestMethod()] + [Test] public void MeshTest() { DoubleRange rowRange = new DoubleRange(-1, 1); @@ -2726,7 +2710,7 @@ public void MeshTest() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void MeshTest2() { // The Mesh method generates all possible (x,y) pairs @@ -2752,7 +2736,7 @@ public void MeshTest2() Assert.IsTrue(expected.IsEqual(grid)); } - [TestMethod()] + [Test] public void MeshTest3() { // The Mesh method can be used to generate all @@ -2771,7 +2755,7 @@ public void MeshTest3() Assert.AreEqual(55, grid.Length); } - [TestMethod()] + [Test] public void MeshTest4() { // The Mesh method can be used to generate all @@ -2790,7 +2774,7 @@ public void MeshTest4() Assert.AreEqual(66, grid.Length); } - [TestMethod()] + [Test] public void MeshGridTest1() { // The MeshGrid method generates two matrices that can be @@ -2851,7 +2835,7 @@ public void MeshGridTest1() } - [TestMethod()] + [Test] public void MultiplyByTransposeTestFloat() { float[,] a = @@ -2880,7 +2864,7 @@ public void MultiplyByTransposeTestFloat() - [TestMethod()] + [Test] public void ConcatenateTest1() { double[][,] matrices = @@ -2911,7 +2895,7 @@ public void ConcatenateTest1() } - [TestMethod()] + [Test] public void RemoveColumnTest() { double[,] matrix = @@ -2949,7 +2933,7 @@ public void RemoveColumnTest() } - [TestMethod()] + [Test] public void RemoveRowTest() { double[,] matrix = @@ -2992,7 +2976,7 @@ public void RemoveRowTest() } - [TestMethod()] + [Test] public void SolveTest1() { double[,] a = @@ -3047,7 +3031,7 @@ public void SolveTest1() } } - [TestMethod()] + [Test] public void SolveTest4() { // Test with more rows than columns @@ -3109,7 +3093,7 @@ public void SolveTest4() } } - [TestMethod()] + [Test] public void SolveTest3() { // Test with more rows than columns @@ -3153,7 +3137,7 @@ public void SolveTest3() } } - [TestMethod()] + [Test] public void SolveTest5() { // Test with singular matrix @@ -3201,7 +3185,7 @@ public void SolveTest5() } } - [TestMethod()] + [Test] public void TopBottomTest() { double[] values = { 9, 3, 6, 3, 1, 8, 4, 1, 8, 4, 4, 1, 0, -2, 4 }; @@ -3230,7 +3214,7 @@ public void TopBottomTest() } - [TestMethod()] + [Test] public void TopBottomTest2() { for (int i = 0; i < 10; i++) diff --git a/Unit Tests/Accord.Tests.Math/Matrix/VectorTest.cs b/Unit Tests/Accord.Tests.Math/Matrix/VectorTest.cs index a31a5eff0..a7bbd9817 100644 --- a/Unit Tests/Accord.Tests.Math/Matrix/VectorTest.cs +++ b/Unit Tests/Accord.Tests.Math/Matrix/VectorTest.cs @@ -23,13 +23,13 @@ namespace Accord.Tests.Math { using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public partial class VectorTest { - [TestMethod()] + [Test] public void ExpandTest() { var v = Vector.Create(5); diff --git a/Unit Tests/Accord.Tests.Math/NormTest.cs b/Unit Tests/Accord.Tests.Math/NormTest.cs index c8542d04c..b144f3594 100644 --- a/Unit Tests/Accord.Tests.Math/NormTest.cs +++ b/Unit Tests/Accord.Tests.Math/NormTest.cs @@ -23,9 +23,9 @@ namespace Accord.Tests.Math { using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class NormTest { @@ -46,7 +46,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void EuclideanTest() { double[,] a = @@ -77,7 +77,7 @@ public void EuclideanTest() Assert.AreEqual(21.9634, actual3, 0.001); } - [TestMethod()] + [Test] public void Norm2Test() { double[,] a = @@ -92,7 +92,7 @@ public void Norm2Test() Assert.AreEqual(expected, actual, 1e-12); } - [TestMethod()] + [Test] public void Norm1Test() { double[,] a = @@ -107,7 +107,7 @@ public void Norm1Test() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void FrobeniusTest() { double[,] a = Matrix.Magic(5); @@ -119,7 +119,7 @@ public void FrobeniusTest() } - [TestMethod()] + [Test] public void EuclideanTest1() { float[,] a = diff --git a/Unit Tests/Accord.Tests.Math/Optimization/AugmentedLagrangianSolverTest.cs b/Unit Tests/Accord.Tests.Math/Optimization/AugmentedLagrangianSolverTest.cs index 1c87d0faa..76d4021b2 100644 --- a/Unit Tests/Accord.Tests.Math/Optimization/AugmentedLagrangianSolverTest.cs +++ b/Unit Tests/Accord.Tests.Math/Optimization/AugmentedLagrangianSolverTest.cs @@ -26,10 +26,10 @@ namespace Accord.Tests.Math using System.Collections.Generic; using Accord.Math; using Accord.Math.Optimization; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class AugmentedLagrangianSolverTest { @@ -51,7 +51,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void AugmentedLagrangianSolverConstructorTest1() { Accord.Math.Tools.SetupGenerator(0); @@ -105,7 +105,7 @@ public void AugmentedLagrangianSolverConstructorTest1() } - [TestMethod()] + [Test] public void AugmentedLagrangianSolverConstructorTest2() { // min 100(y-x*x)²+(1-x)² @@ -161,7 +161,7 @@ public void AugmentedLagrangianSolverConstructorTest2() } #if !NET35 - [TestMethod()] + [Test] public void AugmentedLagrangianSolverConstructorTest3() { // min x*y+ y*z @@ -226,7 +226,7 @@ public void AugmentedLagrangianSolverConstructorTest3() } - [TestMethod()] + [Test] public void AugmentedLagrangianSolverConstructorTest4() { // min x*y+ y*z @@ -298,7 +298,7 @@ public void AugmentedLagrangianSolverConstructorTest4() Assert.IsFalse(Double.IsNaN(solver.Solution[2])); } - [TestMethod()] + [Test] public void AugmentedLagrangianSolverConstructorTest5() { // Suppose we would like to minimize the following function: @@ -368,7 +368,7 @@ public void AugmentedLagrangianSolverConstructorTest5() Assert.IsFalse(Double.IsNaN(solver.Solution[1])); } - [TestMethod()] + [Test] public void AugmentedLagrangianSolverConstructorTest6() { test1(new ConjugateGradient(2), 5e-3); @@ -377,7 +377,7 @@ public void AugmentedLagrangianSolverConstructorTest6() test1(new ResilientBackpropagation(2), 1e-2); } - [TestMethod()] + [Test] public void AugmentedLagrangianSolverConstructorTest7() { test2(new ConjugateGradient(2)); @@ -547,7 +547,7 @@ private static void test2(IGradientOptimizationMethod inner) #endif - [TestMethod] + [Test] public void ConstructorTest2() { Accord.Math.Tools.SetupGenerator(0); @@ -584,7 +584,7 @@ public void ConstructorTest2() Assert.AreEqual(expectedMinimum, minimum); } - [TestMethod] + [Test] public void ConstructorTest3() { // minimize f(x) = x*y*z, @@ -648,7 +648,7 @@ public void ConstructorTest3() Assert.AreEqual(expectedMinimum, minimum); } - [TestMethod] + [Test] public void ConstructorTest4() { // Example code from diff --git a/Unit Tests/Accord.Tests.Math/Optimization/BinarySearchTest.cs b/Unit Tests/Accord.Tests.Math/Optimization/BinarySearchTest.cs index 3a6bb89be..6df28152f 100644 --- a/Unit Tests/Accord.Tests.Math/Optimization/BinarySearchTest.cs +++ b/Unit Tests/Accord.Tests.Math/Optimization/BinarySearchTest.cs @@ -22,12 +22,12 @@ namespace Accord.Tests.Math { using Accord.Math.Optimization; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Math; - [TestClass()] + [TestFixture] public class BinarySearchTest { double[] elements; @@ -56,7 +56,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void ConstructorTest() { // https://www.wolframalpha.com/input/?i=%28x%2B1%29+*+%28x%2B1%29+*+%28x%2B1%29+%2B+2+*+%28x%2B1%29+*+%28x%2B1%29+%3D+0%2C+x+is+integer @@ -75,7 +75,7 @@ public void ConstructorTest() Assert.AreEqual(-3, r2); } - [TestMethod()] + [Test] public void ConstructorTest4() { // (x+5)^3 + 2(x+5)^2 - 10(x+5) @@ -90,7 +90,7 @@ public void ConstructorTest4() Assert.AreEqual(-5, root); } - [TestMethod()] + [Test] public void ConstructorTest1() { Func function = x => elements[x]; @@ -106,7 +106,7 @@ public void ConstructorTest1() } } - [TestMethod()] + [Test] public void ConstructorTest2() { Func function = x => elements[x]; diff --git a/Unit Tests/Accord.Tests.Math/Optimization/BoundedBroydenFletcherGoldfarbShannoTest.cs b/Unit Tests/Accord.Tests.Math/Optimization/BoundedBroydenFletcherGoldfarbShannoTest.cs index 356f67f97..cda62a068 100644 --- a/Unit Tests/Accord.Tests.Math/Optimization/BoundedBroydenFletcherGoldfarbShannoTest.cs +++ b/Unit Tests/Accord.Tests.Math/Optimization/BoundedBroydenFletcherGoldfarbShannoTest.cs @@ -23,11 +23,10 @@ namespace Accord.Tests.Math { using Accord.Math.Optimization; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; - using AccordTestsMathCpp2; - [TestClass()] + [TestFixture] public class BoundedBroydenFletcherGoldfarbShannoTest { @@ -48,7 +47,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void lbfgsTest() { Func f = rosenbrockFunction; @@ -86,7 +85,7 @@ public void lbfgsTest() Assert.AreEqual(0, d[1], 1e-6); } - [TestMethod()] + [Test] public void lbfgsTest2() { Accord.Math.Tools.SetupGenerator(0); @@ -171,7 +170,7 @@ private static void createTestFunction(out Func f, out Func function = // min f(x) = 10 * (x+1)^2 + y^2 @@ -246,35 +245,10 @@ public void ConstructorTest1() Assert.AreEqual(expectedMinimum, minimum); } - [TestMethod] - public void ConstructorTest2() - { - Function function = // min f(x) = 10 * (x+1)^2 + y^2 - x => 10.0 * Math.Pow(x[0] + 1.0, 2.0) + Math.Pow(x[1], 2.0); - - Gradient gradient = x => new[] { 20 * (x[0] + 1), 2 * x[1] }; - - - double[] start = new double[2]; - - var target = new BoundedBroydenFletcherGoldfarbShanno(2, - function.Invoke, gradient.Invoke); - - Assert.IsTrue(target.Minimize()); - double minimum = target.Value; - - double[] solution = target.Solution; - - Assert.AreEqual(0, minimum, 1e-10); - Assert.AreEqual(-1, solution[0], 1e-5); - Assert.AreEqual(0, solution[1], 1e-5); - - double expectedMinimum = function(target.Solution); - Assert.AreEqual(expectedMinimum, minimum); - } + - [TestMethod()] + [Test] public void lbfgsTest3() { Accord.Math.Tools.SetupGenerator(0); diff --git a/Unit Tests/Accord.Tests.Math/Optimization/BrentSearchTest.cs b/Unit Tests/Accord.Tests.Math/Optimization/BrentSearchTest.cs index 0f80303e5..aba8a7086 100644 --- a/Unit Tests/Accord.Tests.Math/Optimization/BrentSearchTest.cs +++ b/Unit Tests/Accord.Tests.Math/Optimization/BrentSearchTest.cs @@ -22,12 +22,12 @@ namespace Accord.Tests.Math { using Accord.Math.Optimization; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Math; - [TestClass()] + [TestFixture] public class BrentSearchTest { @@ -47,7 +47,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void ConstructorTest() { @@ -74,7 +74,7 @@ public void ConstructorTest() } - [TestMethod()] + [Test] public void FindRootTest() { // Example from http://en.wikipedia.org/wiki/Brent%27s_method @@ -91,7 +91,7 @@ public void FindRootTest() } - [TestMethod()] + [Test] public void MaximizeTest() { Func f = x => -2 * x * x - 3 * x + 5; @@ -103,7 +103,7 @@ public void MaximizeTest() } - [TestMethod()] + [Test] public void MinimizeTest() { Func f = x => 2 * x * x - 3 * x + 5; diff --git a/Unit Tests/Accord.Tests.Math/Optimization/BroydenFletcherGoldfarbShannoTest.cs b/Unit Tests/Accord.Tests.Math/Optimization/BroydenFletcherGoldfarbShannoTest.cs index 6cc593506..0ff0a879b 100644 --- a/Unit Tests/Accord.Tests.Math/Optimization/BroydenFletcherGoldfarbShannoTest.cs +++ b/Unit Tests/Accord.Tests.Math/Optimization/BroydenFletcherGoldfarbShannoTest.cs @@ -23,16 +23,15 @@ namespace Accord.Tests.Math { using Accord.Math.Optimization; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; - using AccordTestsMathCpp2; - [TestClass()] + [TestFixture] public class BroydenFletcherGoldfarbShannoTest { - [TestMethod()] + [Test] public void lbfgsTest() { Func f = rosenbrockFunction; @@ -68,7 +67,7 @@ public void lbfgsTest() Assert.AreEqual(0, d[1], 1e-6); } - [TestMethod()] + [Test] public void lbfgsTest2() { Accord.Math.Tools.SetupGenerator(0); @@ -153,7 +152,7 @@ private static void createTestFunction(out Func f, out Func function = // min f(x) = 10 * (x+1)^2 + y^2 @@ -227,35 +226,7 @@ public void ConstructorTest1() Assert.AreEqual(expectedMinimum, minimum); } - [TestMethod] - public void ConstructorTest2() - { - Function function = // min f(x) = 10 * (x+1)^2 + y^2 - x => 10.0 * Math.Pow(x[0] + 1.0, 2.0) + Math.Pow(x[1], 2.0); - - Gradient gradient = x => new[] { 20 * (x[0] + 1), 2 * x[1] }; - - - double[] start = new double[2]; - - BroydenFletcherGoldfarbShanno target = new BroydenFletcherGoldfarbShanno(2, - function.Invoke, gradient.Invoke); - - Assert.IsTrue(target.Minimize()); - double minimum = target.Value; - - double[] solution = target.Solution; - - Assert.AreEqual(0, minimum, 1e-10); - Assert.AreEqual(-1, solution[0], 1e-5); - Assert.AreEqual(0, solution[1], 1e-5); - - double expectedMinimum = function(target.Solution); - Assert.AreEqual(expectedMinimum, minimum); - } - - - [TestMethod()] + [Test] public void lbfgsTest3() { Accord.Math.Tools.SetupGenerator(0); diff --git a/Unit Tests/Accord.Tests.Math/Optimization/CobylaTest.cs b/Unit Tests/Accord.Tests.Math/Optimization/CobylaTest.cs index d8dc268d1..c8ff9b4dd 100644 --- a/Unit Tests/Accord.Tests.Math/Optimization/CobylaTest.cs +++ b/Unit Tests/Accord.Tests.Math/Optimization/CobylaTest.cs @@ -24,30 +24,13 @@ namespace Accord.Tests.Math { using System; using Accord.Math.Optimization; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class CobylaTest { - - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - - [TestMethod] + [Test] public void ConstructorTest1() { Func function = // min f(x) = 10 * (x+1)^2 + y^2 @@ -68,7 +51,7 @@ public void ConstructorTest1() Assert.AreEqual(expectedMinimum, minimum); } - [TestMethod] + [Test] public void ConstructorTest2() { var function = new NonlinearObjectiveFunction(2, x => x[0] * x[1]); @@ -81,9 +64,16 @@ public void ConstructorTest2() Cobyla cobyla = new Cobyla(function, constraints); for (int i = 0; i < cobyla.Solution.Length; i++) - cobyla.Solution[i] = 1; + cobyla.Solution[i] = 1; + + bool success = cobyla.Minimize(); + + double violation = constraints[0].GetViolation(cobyla.Solution); + + var status = cobyla.Status; - Assert.IsTrue(cobyla.Minimize()); + + Assert.IsTrue(success); double minimum = cobyla.Value; double[] solution = cobyla.Solution; @@ -98,7 +88,7 @@ public void ConstructorTest2() Assert.AreEqual(expectedMinimum, minimum); } - [TestMethod] + [Test] public void ConstructorTest2_1() { var function = new NonlinearObjectiveFunction(2, x => x[0] * x[1]); @@ -129,7 +119,7 @@ public void ConstructorTest2_1() Assert.AreEqual(expectedMinimum, minimum); } - [TestMethod] + [Test] public void ConstructorTest2_2() { var function = new NonlinearObjectiveFunction(2, x => x[0] * x[1]); @@ -157,7 +147,7 @@ public void ConstructorTest2_2() Assert.AreEqual(-sqrthalf, solution[1], 1e-5); } - [TestMethod] + [Test] public void ConstructorTest3() { // Easy three dimensional minimization in ellipsoid. @@ -193,7 +183,7 @@ public void ConstructorTest3() Assert.AreEqual(expectedMinimum, minimum); } - [TestMethod] + [Test] public void ConstructorTest4() { // Weak version of Rosenbrock's problem. @@ -214,7 +204,7 @@ public void ConstructorTest4() Assert.AreEqual(expectedMinimum, minimum); } - [TestMethod] + [Test] public void ConstructorTest5() { // Intermediate version of Rosenbrock's problem. @@ -235,7 +225,7 @@ public void ConstructorTest5() Assert.AreEqual(expectedMinimum, minimum); } - [TestMethod] + [Test] public void ConstructorTest6() { // This problem is taken from Fletcher's book Practical Methods of @@ -263,7 +253,7 @@ public void ConstructorTest6() Assert.AreEqual(expectedMinimum, minimum); } - [TestMethod] + [Test] public void ConstructorTest6_0() { // This problem is taken from Fletcher's book Practical Methods of @@ -293,7 +283,7 @@ public void ConstructorTest6_0() Assert.AreEqual(expectedMinimum, minimum); } - [TestMethod] + [Test] public void ConstructorTest6_1() { /// This problem is taken from Fletcher's book Practical Methods of @@ -321,7 +311,7 @@ public void ConstructorTest6_1() Assert.AreEqual(expectedMinimum, minimum); } - [TestMethod] + [Test] public void ConstructorTest6_2() { /// This problem is taken from Fletcher's book Practical Methods of @@ -349,7 +339,7 @@ public void ConstructorTest6_2() Assert.AreEqual(expectedMinimum, minimum); } - [TestMethod] + [Test] public void ConstructorTest6_3() { bool thrown = false; @@ -377,7 +367,7 @@ public void ConstructorTest6_3() Assert.IsTrue(thrown); } - [TestMethod] + [Test] public void ConstructorTest7() { /// This problem is taken from Fletcher's book Practical Methods of @@ -406,7 +396,7 @@ public void ConstructorTest7() Assert.AreEqual(expectedMinimum, minimum); } - [TestMethod] + [Test] public void ConstructorTest8() { /// This problem is taken from page 66 of Hock and Schittkowski's book Test @@ -448,7 +438,7 @@ public void ConstructorTest8() Assert.AreEqual(expectedMinimum, minimum); } - [TestMethod] + [Test] public void ConstructorTest9() { /// This problem is taken from page 111 of Hock and Schittkowski's @@ -489,7 +479,7 @@ public void ConstructorTest9() Assert.AreEqual(expectedMinimum, minimum); } - [TestMethod] + [Test] public void ConstructorTest10() { /// This problem is taken from page 415 of Luenberger's book Applied @@ -516,8 +506,8 @@ public void ConstructorTest10() new NonlinearConstraint(9, x => -x[4] * x[8]), new NonlinearConstraint(9, x => x[4] * x[7] - x[5] * x[6]), new NonlinearConstraint(9, x => x[8]), - }; - + }; + Cobyla cobyla = new Cobyla(function, constraints); for (int i = 0; i < cobyla.Solution.Length; i++) diff --git a/Unit Tests/Accord.Tests.Math/Optimization/ConjugateGradientTest.cs b/Unit Tests/Accord.Tests.Math/Optimization/ConjugateGradientTest.cs index 55ab39635..89d8b0ff5 100644 --- a/Unit Tests/Accord.Tests.Math/Optimization/ConjugateGradientTest.cs +++ b/Unit Tests/Accord.Tests.Math/Optimization/ConjugateGradientTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Math { using Accord.Math.Optimization; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; - [TestClass()] + [TestFixture] public class ConjugateGradientTest { @@ -47,7 +47,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void MinimizeTest() { Func f = BroydenFletcherGoldfarbShannoTest.rosenbrockFunction; @@ -88,7 +88,7 @@ public void MinimizeTest() Assert.IsFalse(double.IsNaN(d[1])); } - [TestMethod()] + [Test] public void MinimizeTest2() { Func f = BroydenFletcherGoldfarbShannoTest.rosenbrockFunction; @@ -129,7 +129,7 @@ public void MinimizeTest2() Assert.IsFalse(double.IsNaN(d[1])); } - [TestMethod()] + [Test] public void MinimizeTest3() { Func f = BroydenFletcherGoldfarbShannoTest.rosenbrockFunction; diff --git a/Unit Tests/Accord.Tests.Math/Optimization/GoldfarbIdnaniTest.cs b/Unit Tests/Accord.Tests.Math/Optimization/GoldfarbIdnaniTest.cs index 7a014c6f2..1c662ec67 100644 --- a/Unit Tests/Accord.Tests.Math/Optimization/GoldfarbIdnaniTest.cs +++ b/Unit Tests/Accord.Tests.Math/Optimization/GoldfarbIdnaniTest.cs @@ -26,13 +26,13 @@ namespace Accord.Tests.Math using System.Collections.Generic; using Accord.Math; using Accord.Math.Optimization; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System.IO; using Accord.Tests.Math.Properties; using System.Globalization; - [TestClass()] + [TestFixture] public class GoldfarbIdnaniTest { @@ -50,7 +50,7 @@ public TestContext TestContext } } - [TestMethod()] + [Test] public void RunTest() { double[,] D = Matrix.Identity(3); @@ -92,7 +92,7 @@ public void RunTest() Assert.IsFalse(double.IsNaN(v)); } - [TestMethod()] + [Test] public void RunTest1() { double[,] D = Matrix.Identity(3); @@ -132,7 +132,7 @@ public void RunTest1() Assert.IsFalse(double.IsNaN(v)); } - [TestMethod()] + [Test] public void RunTest2() { // Maximize f(x) = x² + 4y² -8x -16y @@ -182,7 +182,7 @@ public void RunTest2() Assert.IsFalse(double.IsNaN(v)); } - [TestMethod()] + [Test] public void RunTest3() { // Tested against R's QuadProg package @@ -238,7 +238,7 @@ public void RunTest3() Assert.IsFalse(double.IsNaN(v)); } - [TestMethod()] + [Test] public void RunTest4() { @@ -287,7 +287,7 @@ public void RunTest4() Assert.IsFalse(double.IsNaN(v)); } - [TestMethod()] + [Test] public void RunTest5() { // example from http://www.mail-archive.com/r-help@r-project.org/msg00831.html @@ -334,7 +334,7 @@ public void RunTest5() } - [TestMethod()] + [Test] public void GoldfarbIdnaniConstructorTest1() { double[,] D = Matrix.Identity(3); @@ -362,7 +362,7 @@ public void GoldfarbIdnaniConstructorTest1() Assert.IsTrue(b.IsEqual(target.ConstraintValues)); } - [TestMethod()] + [Test] public void GoldfarbIdnaniConstructorTest2() { // Solve the following optimization problem: @@ -469,7 +469,7 @@ public void GoldfarbIdnaniConstructorTest2() Assert.IsFalse(double.IsNaN(v)); } - [TestMethod()] + [Test] public void GoldfarbIdnaniConstructorTest3() { // http://www.wolframalpha.com/input/?i=min+2x%C2%B2+-+xy+%2B+4y%C2%B2+-+5x+-+6y+s.t.+x+-+y++%3D%3D+++5%2C+x++%3E%3D++10 @@ -536,7 +536,7 @@ public void GoldfarbIdnaniConstructorTest3() Assert.IsTrue(success); } - [TestMethod()] + [Test] public void GoldfarbIdnaniConstructorTest10() { // http://www.wolframalpha.com/input/?i=minimize+f%28x%2Cy%29+%3D+2x%5E2+-+xy+%2B+4y%5E2+-+5x+-+6y+-+100%2C+s.t.+x+-+y++%3D+++5%2C+x++%3E%3D++10 @@ -571,7 +571,7 @@ public void GoldfarbIdnaniConstructorTest10() Assert.IsTrue(success); } - [TestMethod] + [Test] public void GoldfarbIdnaniConstructorTest11() { // http://www.wolframalpha.com/input/?i=minimize+f%28x%2Cy%29+%3D+2x%5E2+-+xy+%2B+4y%5E2+-+5x+-+6y+-+100%2C+s.t.+x+-+y++%3D+++5%2C+x++%3E%3D++10 @@ -606,7 +606,7 @@ public void GoldfarbIdnaniConstructorTest11() Assert.IsTrue(success); } - [TestMethod()] + [Test] public void GoldfarbIdnaniConstructorTest4() { // Solve the following optimization problem: @@ -657,7 +657,7 @@ public void GoldfarbIdnaniConstructorTest4() Assert.IsTrue(d.IsEqual(actuald)); } - [TestMethod()] + [Test] public void GoldfarbIdnaniConstructorTest5() { // min 1x² - 2xy + 3y² +z² - 4x - 5y -z, 6x-7y <= 8, 9x + 1y <= 11, 9x-y <= 11, -z-y = 12 @@ -692,7 +692,7 @@ public void GoldfarbIdnaniConstructorTest5() } - [TestMethod()] + [Test] public void GoldfarbIdnaniConstructorTest6() { // min 1x² - 2xy + 3y² +z² - 4x - 5y -z, 6x-7y <= 8, 9x + 1y <= 11, 9x-y <= 11, -z-y = 12 @@ -723,7 +723,7 @@ public void GoldfarbIdnaniConstructorTest6() Assert.IsFalse(double.IsNaN(v)); } - [TestMethod()] + [Test] public void GoldfarbIdnaniConstructorTest7() { // Solve the following optimization problem: @@ -797,7 +797,7 @@ public void GoldfarbIdnaniConstructorTest7() Assert.IsFalse(double.IsNaN(v)); } - [TestMethod()] + [Test] public void GoldfarbIdnaniConstructorTest8() { // Solve the following optimization problem: @@ -855,7 +855,7 @@ public void GoldfarbIdnaniConstructorTest8() Assert.IsFalse(success); } - [TestMethod()] + [Test] public void GoldfarbIdnaniConstructorTest9() { // Solve the following optimization problem: @@ -952,7 +952,7 @@ public void GoldfarbIdnaniConstructorTest9() Assert.IsFalse(double.IsNaN(v)); } - [TestMethod()] + [Test] public void GoldfarbIdnaniMaximizeTest1() { // Solve the following optimization problem: @@ -984,7 +984,7 @@ public void GoldfarbIdnaniMaximizeTest1() Assert.AreEqual(5 / 8.0, solver.Solution[1]); } - [TestMethod()] + [Test] public void GoldfarbIdnaniParseGlobalizationTestBase() { // minimize 0.5x² + 0.2y² + 0.3xy s.t. 0.01x + 0.02y - 0.03 = 0 AND x + y = 100 @@ -1011,7 +1011,7 @@ public void GoldfarbIdnaniParseGlobalizationTestBase() Assert.AreEqual(15553.60, result, 1e-10); } - [TestMethod()] + [Test] public void GoldfarbIdnaniParseGlobalizationTest() { var fr = CultureInfo.GetCultureInfo("fr-FR"); @@ -1043,7 +1043,7 @@ public void GoldfarbIdnaniParseGlobalizationTest() Assert.AreEqual(15553.60, result, 1e-10); } - [TestMethod()] + [Test] public void GoldfarbIdnaniParseGlobalizationTest2() { String strObjective = 0.5.ToString(CultureInfo.InvariantCulture) @@ -1071,7 +1071,7 @@ public void GoldfarbIdnaniParseGlobalizationTest2() Assert.AreEqual(15553.60, result, 1e-10); } - [TestMethod()] + [Test] public void GoldfarbIdnaniParseTest() { var s = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator; @@ -1098,7 +1098,7 @@ public void GoldfarbIdnaniParseTest() Assert.AreEqual(15553.60, result, 1e-10); } - [TestMethod()] + [Test] public void GoldfarbIdnaniMinimizeWithEqualityTest() { // This test reproduces Issue #33 at Google Code Tracker @@ -1171,7 +1171,7 @@ public void GoldfarbIdnaniMinimizeWithEqualityTest() } } - [TestMethod()] + [Test] public void GoldfarbIdnaniMinimizeLessThanWithEqualityTest() { // This test reproduces Issue #33 at Google Code Tracker @@ -1241,7 +1241,7 @@ public void GoldfarbIdnaniMinimizeLessThanWithEqualityTest() } - [TestMethod()] + [Test] public void GoldfarbIdnaniLargeSampleTest1() { var Q = readMatrixFile(new StringReader(Resources.dmatFull)); @@ -1284,7 +1284,7 @@ public void GoldfarbIdnaniLargeSampleTest1() Assert.AreEqual(expected[i], actual[i], 1e-5); } - [TestMethod()] + [Test] public void GoldfarbIdnaniLargeSampleTest2() { var Q = readMatrixFile(new StringReader(Resources.dmatFull)); @@ -1330,7 +1330,7 @@ public void GoldfarbIdnaniLargeSampleTest2() Assert.AreEqual(expected[i], actual[i], 1e-5); } - [TestMethod()] + [Test] public void GoldfarbIdnaniLargeSampleTest3_InfiniteLoop() { var Q = readMatrixFile(new StringReader(Resources.dmatFull)); @@ -1379,7 +1379,7 @@ public void GoldfarbIdnaniLargeSampleTest3_InfiniteLoop() Assert.AreEqual(expected[i], actual[i], 1e-5); } - [TestMethod()] + [Test] public void GoldfarbIdnani3() { double[] bvec = { 1, 0, -1, 0, -1, 0, -1, 0, -1 }; diff --git a/Unit Tests/Accord.Tests.Math/Optimization/LinearConstraintTest.cs b/Unit Tests/Accord.Tests.Math/Optimization/LinearConstraintTest.cs index 8505a9a58..c41c301b4 100644 --- a/Unit Tests/Accord.Tests.Math/Optimization/LinearConstraintTest.cs +++ b/Unit Tests/Accord.Tests.Math/Optimization/LinearConstraintTest.cs @@ -24,10 +24,10 @@ namespace Accord.Tests.Math { using System; using Accord.Math.Optimization; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; - [TestClass()] + [TestFixture] public class LinearConstraintTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod] + [Test] public void ConstructorTest1() { var f = new QuadraticObjectiveFunction("a + b = 0"); @@ -89,7 +89,7 @@ public void ConstructorTest1() } } - [TestMethod] + [Test] public void ConstructorTest2() { double a = 0, b = 0; diff --git a/Unit Tests/Accord.Tests.Math/Optimization/NelderMeadTest.cs b/Unit Tests/Accord.Tests.Math/Optimization/NelderMeadTest.cs index a6f7f0d75..284f310c1 100644 --- a/Unit Tests/Accord.Tests.Math/Optimization/NelderMeadTest.cs +++ b/Unit Tests/Accord.Tests.Math/Optimization/NelderMeadTest.cs @@ -24,9 +24,9 @@ namespace Accord.Tests.Math { using System; using Accord.Math.Optimization; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class NelderMeadTest { @@ -46,7 +46,7 @@ public TestContext TestContext } - [TestMethod] + [Test] public void ConstructorTest1() { Func function = // min f(x) = 10 * (x+1)^2 + y^2 @@ -67,7 +67,7 @@ public void ConstructorTest1() Assert.AreEqual(expectedMinimum, minimum); } - [TestMethod] + [Test] public void ConstructorTest4() { var function = new NonlinearObjectiveFunction(2, x => @@ -87,7 +87,7 @@ public void ConstructorTest4() Assert.AreEqual(expectedMinimum, minimum); } - [TestMethod] + [Test] public void ConstructorTest5() { var function = new NonlinearObjectiveFunction(2, x => @@ -108,7 +108,7 @@ public void ConstructorTest5() Assert.AreEqual(expectedMinimum, minimum); } - [TestMethod] + [Test] public void SubspaceTest1() { var function = new NonlinearObjectiveFunction(5, x => diff --git a/Unit Tests/Accord.Tests.Math/Optimization/NonlinearConstraintTest.cs b/Unit Tests/Accord.Tests.Math/Optimization/NonlinearConstraintTest.cs index 5f2d5a671..8ee0da104 100644 --- a/Unit Tests/Accord.Tests.Math/Optimization/NonlinearConstraintTest.cs +++ b/Unit Tests/Accord.Tests.Math/Optimization/NonlinearConstraintTest.cs @@ -24,10 +24,10 @@ namespace Accord.Tests.Math { using System; using Accord.Math.Optimization; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; - [TestClass()] + [TestFixture] public class NonlinearConstraintTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod] + [Test] public void ConstructorTest6() { var constraints = new[] @@ -82,7 +82,7 @@ public void ConstructorTest6() } } - [TestMethod] + [Test] public void GetViolationTest1() { NonlinearConstraint[] targets = @@ -112,7 +112,7 @@ public void GetViolationTest1() } } - [TestMethod] + [Test] public void GetViolationTest2() { NonlinearConstraint[] targets = diff --git a/Unit Tests/Accord.Tests.Math/Optimization/QuadraticObjectiveFunctionTest.cs b/Unit Tests/Accord.Tests.Math/Optimization/QuadraticObjectiveFunctionTest.cs index fb21c7304..38612ab16 100644 --- a/Unit Tests/Accord.Tests.Math/Optimization/QuadraticObjectiveFunctionTest.cs +++ b/Unit Tests/Accord.Tests.Math/Optimization/QuadraticObjectiveFunctionTest.cs @@ -26,10 +26,10 @@ namespace Accord.Tests.Math using Accord.Math; using Accord.Math.Differentiation; using Accord.Math.Optimization; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class QuadraticObjectiveFunctionTest { @@ -50,7 +50,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void QuadraticConstructorTest() { double[,] quadraticTerms = @@ -104,7 +104,7 @@ public void QuadraticConstructorTest() } } - [TestMethod()] + [Test] public void LinearTest() { double[,] quadraticTerms = @@ -158,7 +158,7 @@ public void LinearTest() } } - [TestMethod()] + [Test] public void HomogeneousTest() { double[,] quadraticTerms = @@ -198,7 +198,7 @@ public void HomogeneousTest() } } - [TestMethod()] + [Test] public void HomogeneousTest2() { double[,] quadraticTerms = @@ -239,7 +239,7 @@ public void HomogeneousTest2() } - [TestMethod()] + [Test] public void FunctionTest() { double x = 0; @@ -265,7 +265,7 @@ public void FunctionTest() } } - [TestMethod()] + [Test] public void FunctionTest2() { double x = 0; @@ -296,7 +296,7 @@ public void FunctionTest2() } } - [TestMethod()] + [Test] public void FunctionTest3() { double x = 0; @@ -317,7 +317,7 @@ public void FunctionTest3() } } - [TestMethod()] + [Test] public void FunctionTest4() { double x = 0; @@ -348,7 +348,7 @@ public void FunctionTest4() } } - [TestMethod()] + [Test] public void LambdaFunctionTest() { double x = 0; @@ -374,7 +374,7 @@ public void LambdaFunctionTest() } } - [TestMethod()] + [Test] public void LambdaFunctionTest2() { double x = 0; @@ -405,7 +405,7 @@ public void LambdaFunctionTest2() } } - [TestMethod()] + [Test] public void LambdaFunctionTest3() { double x = 0; @@ -426,7 +426,7 @@ public void LambdaFunctionTest3() } } - [TestMethod()] + [Test] public void LambdaFunctionTest4() { double x = 0; @@ -457,7 +457,7 @@ public void LambdaFunctionTest4() } } - [TestMethod()] + [Test] public void FunctionTest5() { var f1 = new QuadraticObjectiveFunction("x² + 1"); diff --git a/Unit Tests/Accord.Tests.Math/Optimization/SubplexTest.cs b/Unit Tests/Accord.Tests.Math/Optimization/SubplexTest.cs index 4ba9b9c37..689ecd222 100644 --- a/Unit Tests/Accord.Tests.Math/Optimization/SubplexTest.cs +++ b/Unit Tests/Accord.Tests.Math/Optimization/SubplexTest.cs @@ -24,9 +24,9 @@ namespace Accord.Tests.Math { using System; using Accord.Math.Optimization; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class SubplexTest { @@ -46,7 +46,7 @@ public TestContext TestContext } - [TestMethod] + [Test] public void ConstructorTest1() { Func function = // min f(x) = 10 * (x+1)^2 + y^2 @@ -67,7 +67,7 @@ public void ConstructorTest1() Assert.AreEqual(expectedMinimum, minimum); } - [TestMethod] + [Test] public void ConstructorTest4() { // Weak version of Rosenbrock's problem. @@ -89,7 +89,7 @@ public void ConstructorTest4() Assert.AreEqual(expectedMinimum, minimum); } - [TestMethod] + [Test] public void ConstructorTest5() { var function = new NonlinearObjectiveFunction(2, x => diff --git a/Unit Tests/Accord.Tests.Math/PlaneTest.cs b/Unit Tests/Accord.Tests.Math/PlaneTest.cs index c02e7b24f..3b5e93419 100644 --- a/Unit Tests/Accord.Tests.Math/PlaneTest.cs +++ b/Unit Tests/Accord.Tests.Math/PlaneTest.cs @@ -23,13 +23,13 @@ namespace Accord.Tests.Math { using Accord.Math.Geometry; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using AForge.Math; using System.Globalization; using Accord.Math; - [TestClass()] + [TestFixture] public class PlaneTest { @@ -50,7 +50,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void FromPointsTest() { Point3 point1 = new Point3(0, 1, -7); @@ -63,7 +63,7 @@ public void FromPointsTest() Assert.AreEqual(expected, actual.Normal); } - [TestMethod()] + [Test] public void FromPointsTest2() { Point3 point1 = new Point3(1, 2, -2); @@ -76,7 +76,7 @@ public void FromPointsTest2() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void ToStringTest() { Plane target = new Plane(-12, 3, -18, 1); diff --git a/Unit Tests/Accord.Tests.Math/Point3Test.cs b/Unit Tests/Accord.Tests.Math/Point3Test.cs index 0679cbf03..28a708571 100644 --- a/Unit Tests/Accord.Tests.Math/Point3Test.cs +++ b/Unit Tests/Accord.Tests.Math/Point3Test.cs @@ -21,7 +21,7 @@ // using Accord.Math.Geometry; -using Microsoft.VisualStudio.TestTools.UnitTesting; +using NUnit.Framework; using System; using Accord.Math; @@ -29,7 +29,7 @@ namespace Accord.Tests.Math { - [TestClass()] + [TestFixture] public class Point3Test { @@ -50,7 +50,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void CollinearTest() { { diff --git a/Unit Tests/Accord.Tests.Math/ReducedRowEchelonFormTest.cs b/Unit Tests/Accord.Tests.Math/ReducedRowEchelonFormTest.cs index 7b00c8104..3f3e38043 100644 --- a/Unit Tests/Accord.Tests.Math/ReducedRowEchelonFormTest.cs +++ b/Unit Tests/Accord.Tests.Math/ReducedRowEchelonFormTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Math { using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; - [TestClass()] + [TestFixture] public class ReducedRowEchelonFormTest { @@ -47,7 +47,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ReducedRowEchelonFormConstructorTest() { double[,] matrix = @@ -71,7 +71,7 @@ public void ReducedRowEchelonFormConstructorTest() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void ReducedRowEchelonFormConstructorTest2() { double[,] matrix = diff --git a/Unit Tests/Accord.Tests.Math/SpecialTest.cs b/Unit Tests/Accord.Tests.Math/SpecialTest.cs index 13d06d66c..a31386750 100644 --- a/Unit Tests/Accord.Tests.Math/SpecialTest.cs +++ b/Unit Tests/Accord.Tests.Math/SpecialTest.cs @@ -23,9 +23,9 @@ namespace Accord.Tests.Math { using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class SpecialTest { @@ -46,7 +46,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void BinomialTest() { int n = 63; @@ -67,7 +67,7 @@ public void BinomialTest() } - [TestMethod()] + [Test] public void Log1pTest() { double precision = 1e-16; @@ -88,7 +88,7 @@ public void Log1pTest() } - [TestMethod()] + [Test] public void FactorialTest() { int n = 3; @@ -102,7 +102,7 @@ public void FactorialTest() Assert.AreEqual(expected, actual, 1e27); } - [TestMethod()] + [Test] public void LnFactorialTest() { int n = 4; @@ -116,7 +116,7 @@ public void LnFactorialTest() Assert.AreEqual(expected, actual, 0.0000000001); } - [TestMethod()] + [Test] public void EpsilonTest() { double x = 0.5; @@ -135,7 +135,7 @@ public void EpsilonTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void BinomialTest2() { int n = 6; @@ -152,7 +152,7 @@ public void BinomialTest2() } - [TestMethod()] + [Test] public void InverseErfTest() { for (int i = 0; i < 100; i++) @@ -168,7 +168,7 @@ public void InverseErfTest() } } - [TestMethod()] + [Test] public void InverseErfcTest() { for (int i = 0; i < 100; i++) diff --git a/Unit Tests/Accord.Tests.Math/ToolsTest.cs b/Unit Tests/Accord.Tests.Math/ToolsTest.cs index df061528d..177c42756 100644 --- a/Unit Tests/Accord.Tests.Math/ToolsTest.cs +++ b/Unit Tests/Accord.Tests.Math/ToolsTest.cs @@ -25,9 +25,9 @@ namespace Accord.Tests.Math using System.Collections.Generic; using Accord.Math; using AForge; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class ToolsTest { @@ -49,7 +49,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ScaleTest1() { double fromMin = 0; @@ -66,7 +66,7 @@ public void ScaleTest1() } - [TestMethod()] + [Test] public void ScaleTest() { IntRange from = new IntRange(0, 100); @@ -78,7 +78,7 @@ public void ScaleTest() } - [TestMethod()] + [Test] public void ScaleTest2() { DoubleRange from = new DoubleRange(-100, 100); @@ -90,7 +90,7 @@ public void ScaleTest2() } - [TestMethod()] + [Test] public void ScaleTest3() { double toMin = 0; @@ -119,7 +119,7 @@ public void ScaleTest3() } - [TestMethod()] + [Test] public void ScaleTest4() { float fromMin = 0f; @@ -138,7 +138,7 @@ public void ScaleTest4() } - [TestMethod()] + [Test] public void AtanhTest() { double d = 0.42; @@ -148,7 +148,7 @@ public void AtanhTest() } - [TestMethod()] + [Test] public void AsinhTest() { double d = 0.42; @@ -158,7 +158,7 @@ public void AsinhTest() } - [TestMethod()] + [Test] public void AcoshTest() { double x = 3.14; @@ -168,7 +168,7 @@ public void AcoshTest() } - [TestMethod()] + [Test] public void InvSqrtTest() { float f = 42f; @@ -179,7 +179,7 @@ public void InvSqrtTest() Assert.AreEqual(expected, actual, 0.001); } - [TestMethod()] + [Test] public void DirectionTest() { IntPoint center = new IntPoint(0, 0); diff --git a/Unit Tests/Accord.Tests.Math/Wavelets/CDF97Test.cs b/Unit Tests/Accord.Tests.Math/Wavelets/CDF97Test.cs index e1ebde475..06dbf9134 100644 --- a/Unit Tests/Accord.Tests.Math/Wavelets/CDF97Test.cs +++ b/Unit Tests/Accord.Tests.Math/Wavelets/CDF97Test.cs @@ -21,7 +21,7 @@ // using Accord.Math.Wavelets; -using Microsoft.VisualStudio.TestTools.UnitTesting; +using NUnit.Framework; using Accord.Math; namespace Accord.Tests.Wavelets { @@ -31,7 +31,7 @@ namespace Accord.Tests.Wavelets ///This is a test class for CDF97Test and is intended ///to contain all CDF97Test Unit Tests /// - [TestClass()] + [TestFixture] public class CDF97Test { @@ -55,7 +55,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void FWT97Test() { double[] x = new double[32]; @@ -102,7 +102,7 @@ public void FWT97Test() } - [TestMethod()] + [Test] public void FWT2DTest() { double[,] x = diff --git a/Unit Tests/Accord.Tests.Math/Wavelets/HaarTest.cs b/Unit Tests/Accord.Tests.Math/Wavelets/HaarTest.cs index 2da3c059f..9fba7a302 100644 --- a/Unit Tests/Accord.Tests.Math/Wavelets/HaarTest.cs +++ b/Unit Tests/Accord.Tests.Math/Wavelets/HaarTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Wavelets { using Accord.Math.Wavelets; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; - [TestClass()] + [TestFixture] public class HaarTest { @@ -47,7 +47,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void FWT2DTest() { double[,] original = @@ -79,7 +79,7 @@ public void FWT2DTest() Assert.IsTrue(Matrix.IsEqual(data, original, 0.0001)); } - [TestMethod()] + [Test] public void FWT2DTest2() { int levels = 2; @@ -113,7 +113,7 @@ public void FWT2DTest2() Assert.IsTrue(Matrix.IsEqual(data, original, 0.0001)); } - [TestMethod()] + [Test] public void IWTTest() { double[] original = { 1, 2, 3, 4 }; diff --git a/Unit Tests/Accord.Tests.Neuro/Accord.Tests.Neuro.csproj b/Unit Tests/Accord.Tests.Neuro/Accord.Tests.Neuro.csproj index 3dffe5535..91d812d57 100644 --- a/Unit Tests/Accord.Tests.Neuro/Accord.Tests.Neuro.csproj +++ b/Unit Tests/Accord.Tests.Neuro/Accord.Tests.Neuro.csproj @@ -4,7 +4,6 @@ {AB8B83D8-F7B4-4C21-AEB4-B0C5D2217DEF} Accord.Tests.Neuro Accord.Tests.Neuro - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} Debug AnyCPU Library @@ -32,43 +31,32 @@ true full false - bin\Debug\ + $(SolutionDir)..\Unit Tests\bin\Debug\ DEBUG;TRACE - bin\Release\net35 + $(SolutionDir)..\Unit Tests\bin\Release\net35\ TRACE;NET35 - bin\Release\net40 + $(SolutionDir)..\Unit Tests\bin\Release\net40\ TRACE;NET40 - bin\Release\net45 + $(SolutionDir)..\Unit Tests\bin\Release\net45\ TRACE;NET45 - - False - ..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\Externals\AForge.NET\AForge.Math.dll - - - False - ..\..\Externals\AForge.NET\AForge.Neuro.dll + + ..\..\Externals\NUnit\nunit.framework.dll 3.5 + - - c:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll - @@ -345,7 +333,9 @@ true - + + + @@ -354,7 +344,9 @@ Always - + + PreserveNewest + PreserveNewest @@ -374,11 +366,11 @@ - \ No newline at end of file diff --git a/Unit Tests/Accord.Tests.Statistics/Analysis/CircularDescriptiveAnalysisTest.cs b/Unit Tests/Accord.Tests.Statistics/Analysis/CircularDescriptiveAnalysisTest.cs index 58907e308..5f144b715 100644 --- a/Unit Tests/Accord.Tests.Statistics/Analysis/CircularDescriptiveAnalysisTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Analysis/CircularDescriptiveAnalysisTest.cs @@ -27,9 +27,9 @@ namespace Accord.Tests.Statistics using Accord.Statistics; using Accord.Statistics.Analysis; using AForge; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class CircularDescriptiveAnalysisTest { @@ -50,7 +50,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void DescriptiveAnalysisConstructorTest1() { double[,] data = @@ -77,7 +77,7 @@ public void DescriptiveAnalysisConstructorTest1() test(analysis); } - [TestMethod()] + [Test] public void DescriptiveAnalysisConstructor_NoCompute() { double[,] data = @@ -201,7 +201,7 @@ private static void test(CircularDescriptiveAnalysis analysis) - [TestMethod()] + [Test] public void DescriptiveAnalysis_InPlaceRow() { double[,] data = @@ -363,7 +363,7 @@ private static void expectedValues(double[] original, int originalLength, } - [TestMethod()] + [Test] public void DataBindTest() { double[,] data = diff --git a/Unit Tests/Accord.Tests.Statistics/Analysis/ConfusionMatrixTest.cs b/Unit Tests/Accord.Tests.Statistics/Analysis/ConfusionMatrixTest.cs index 703619642..b7c68a3e1 100644 --- a/Unit Tests/Accord.Tests.Statistics/Analysis/ConfusionMatrixTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Analysis/ConfusionMatrixTest.cs @@ -23,12 +23,12 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Analysis; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; using Accord.Statistics.Testing; - [TestClass()] + [TestFixture] public class ConfusionMatrixTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConfusionMatrixConstructorTest() { // The correct and expected output values (as confirmed by a Gold @@ -99,7 +99,7 @@ public void ConfusionMatrixConstructorTest() Assert.AreEqual(0.21821789023599239, matrix.MatthewsCorrelationCoefficient); } - [TestMethod()] + [Test] public void ConfusionMatrixConstructorTest2() { // The correct and expected output values (as confirmed by a Gold @@ -132,7 +132,7 @@ public void ConfusionMatrixConstructorTest2() Assert.AreEqual(trueNegatives, matrix.TrueNegatives); } - [TestMethod()] + [Test] public void ConfusionMatrixConstructorTest3() { // System output @@ -173,7 +173,7 @@ public void ConfusionMatrixConstructorTest3() Assert.AreEqual(1.0, target.MatthewsCorrelationCoefficient); } - [TestMethod()] + [Test] public void ConfusionMatrixConstructorTest4() { // Example from http://www.iph.ufrgs.br/corpodocente/marques/cd/rd/presabs.htm @@ -223,7 +223,7 @@ public void ConfusionMatrixConstructorTest4() Assert.IsFalse(double.IsNaN(matrix.NormalizedMutualInformation)); } - [TestMethod()] + [Test] public void ConfusionMatrixConstructorTest5() { // The correct and expected output values (as confirmed by a Gold @@ -269,7 +269,7 @@ public void ConfusionMatrixConstructorTest5() Assert.AreEqual(0.21821789023599239, matrix.MatthewsCorrelationCoefficient); } - [TestMethod()] + [Test] public void ConfusionMatrixConstructorTest6() { // Create a new confusion matrix using the given parameters @@ -290,7 +290,7 @@ public void ConfusionMatrixConstructorTest6() } - [TestMethod()] + [Test] public void ChiSquareTest() { ConfusionMatrix target = new ConfusionMatrix(6, 2, 6, 18); @@ -309,21 +309,21 @@ public void ChiSquareTest() Assert.IsTrue(test.Significant); } - [TestMethod] + [Test] public void MatthewsCorrelationCoefficientTest() { ConfusionMatrix matrix = new ConfusionMatrix(1, 1, 2, 6); Assert.AreEqual(0.21821789023599239, matrix.MatthewsCorrelationCoefficient); } - [TestMethod] + [Test] public void MatthewsCorrelationCoefficientTest2() { ConfusionMatrix matrix = new ConfusionMatrix(100, 100, 200, 600); Assert.AreEqual(0.21821789023599236, matrix.MatthewsCorrelationCoefficient); } - [TestMethod()] + [Test] public void ToGeneralMatrixTest1() { // Example from http://www.iph.ufrgs.br/corpodocente/marques/cd/rd/presabs.htm diff --git a/Unit Tests/Accord.Tests.Statistics/Analysis/DescriptiveAnalysisTest.cs b/Unit Tests/Accord.Tests.Statistics/Analysis/DescriptiveAnalysisTest.cs index f404ef21c..377b1976f 100644 --- a/Unit Tests/Accord.Tests.Statistics/Analysis/DescriptiveAnalysisTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Analysis/DescriptiveAnalysisTest.cs @@ -25,10 +25,10 @@ namespace Accord.Tests.Statistics using Accord.Math; using Accord.Statistics.Analysis; using AForge; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; - [TestClass()] + [TestFixture] public class DescriptiveAnalysisTest { @@ -49,7 +49,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void DescriptiveAnalysisConstructorTest1() { // Suppose we would like to compute descriptive @@ -72,7 +72,7 @@ public void DescriptiveAnalysisConstructorTest1() test(analysis); } - [TestMethod()] + [Test] public void DescriptiveAnalysisConstructorTest4() { double[][] data = @@ -92,7 +92,7 @@ public void DescriptiveAnalysisConstructorTest4() test(analysis); } - [TestMethod()] + [Test] public void DescriptiveAnalysisConstructorTest3() { // Suppose we would like to compute descriptive @@ -195,7 +195,7 @@ public void DescriptiveAnalysisConstructorTest3() Assert.AreEqual(62, quartiles[0].Max); } - [TestMethod()] + [Test] public void DescriptiveAnalysisConstructorTest() { double[,] data = Matrix.Magic(3); @@ -365,7 +365,7 @@ private static void test(DescriptiveAnalysis analysis) Assert.AreEqual(5, quartiles[2].Max); } - [TestMethod()] + [Test] public void DescriptiveAnalysisOneSampleTest() { double[] data = { 52 }; @@ -454,7 +454,7 @@ public void DescriptiveAnalysisOneSampleTest() Assert.AreEqual(52, outerFence[0].Max); } - [TestMethod()] + [Test] public void DescriptiveAnalysisTwoSampleTest() { double[][] data = @@ -549,7 +549,7 @@ public void DescriptiveAnalysisTwoSampleTest() Assert.AreEqual(53, outerFence[0].Max); } - [TestMethod()] + [Test] public void DescriptiveAnalysisNSampleTest() { for (int i = 1; i < 100; i++) @@ -614,7 +614,7 @@ public void DescriptiveAnalysisNSampleTest() } - [TestMethod()] + [Test] public void DataBindTest() { double[,] data = diff --git a/Unit Tests/Accord.Tests.Statistics/Analysis/DistributionAnalysisTest.cs b/Unit Tests/Accord.Tests.Statistics/Analysis/DistributionAnalysisTest.cs index e9405578a..98259254e 100644 --- a/Unit Tests/Accord.Tests.Statistics/Analysis/DistributionAnalysisTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Analysis/DistributionAnalysisTest.cs @@ -23,13 +23,13 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Analysis; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; using Accord.Statistics.Testing; using Accord.Statistics.Distributions.Univariate; - [TestClass()] + [TestFixture] public class DistributionAnalysisTest { @@ -49,7 +49,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest() { int n = 10000; diff --git a/Unit Tests/Accord.Tests.Statistics/Analysis/GeneralConfusionMatrixTest.cs b/Unit Tests/Accord.Tests.Statistics/Analysis/GeneralConfusionMatrixTest.cs index e1fedc5a6..4c0ba4200 100644 --- a/Unit Tests/Accord.Tests.Statistics/Analysis/GeneralConfusionMatrixTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Analysis/GeneralConfusionMatrixTest.cs @@ -23,11 +23,11 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Analysis; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; using System; - [TestClass()] + [TestFixture] public class GeneralConfusionMatrixTest { @@ -47,7 +47,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void GeneralConfusionMatrixConstructorTest() { int classes = 3; @@ -73,7 +73,7 @@ public void GeneralConfusionMatrixConstructorTest() Assert.IsTrue(expectedMatrix.IsEqual(actualMatrix)); } - [TestMethod()] + [Test] public void GeneralConfusionMatrixConstructorTest2() { int[,] matrix = @@ -92,7 +92,7 @@ public void GeneralConfusionMatrixConstructorTest2() Assert.AreEqual(0, target.GeometricAgreement); } - [TestMethod()] + [Test] public void KappaTest() { int[,] matrix = @@ -112,7 +112,7 @@ public void KappaTest() Assert.AreEqual(23.367749664961245, target.GeometricAgreement); } - [TestMethod()] + [Test] public void KappaTest2() { int[,] matrix = @@ -142,7 +142,7 @@ public void KappaTest2() Assert.AreEqual(24, target.GeometricAgreement, 1e-5); } - [TestMethod()] + [Test] public void KappaTest4() { // Example from Congalton @@ -176,16 +176,16 @@ public void KappaTest4() double var0 = target.VarianceUnderNull; double varD = Accord.Statistics.Testing.KappaTest.DeltaMethodKappaVariance(target); - Assert.AreEqual(0.0007778, varD, 1e-7); - Assert.AreNotEqual(0.0007778, var, 1e-8); - Assert.AreNotEqual(0.0007778, var0, 1e-8); + Assert.AreEqual(0.0007778, varD, 1e-7); + Assert.AreEqual(0.00076995084473426684, var, 1e-10); + Assert.AreEqual(0.00074886435981842887, var0, 1e-10); Assert.IsFalse(double.IsNaN(var)); Assert.IsFalse(double.IsNaN(var0)); Assert.IsFalse(double.IsNaN(varD)); } - [TestMethod()] + [Test] public void KappaTest5() { // Example from University of York Department of Health Sciences, @@ -212,7 +212,7 @@ public void KappaTest5() } - [TestMethod()] + [Test] public void KappaVarianceTest1() { // Example from Ientilucci, Emmett (2006). "On Using and Computing the Kappa Statistic". @@ -266,11 +266,11 @@ public void KappaVarianceTest1() double varD = Accord.Statistics.Testing.KappaTest.DeltaMethodKappaVariance(a); // Variance value var_k for A (page 4) - Assert.AreEqual(0.00073735, varD, 1e-8); - - - Assert.AreNotEqual(0.00073735, var, 1e-8); - Assert.AreNotEqual(0.00073735, var0, 1e-8); + Assert.AreEqual(0.00073735, varD, 1e-8); + + + Assert.AreEqual(0.00071760415564207924, var, 1e-10); + Assert.AreEqual(0.00070251065008366978, var0, 1e-10); Assert.IsFalse(double.IsNaN(var)); Assert.IsFalse(double.IsNaN(var0)); @@ -324,11 +324,11 @@ public void KappaVarianceTest1() double varD = Accord.Statistics.Testing.KappaTest.DeltaMethodKappaVariance(b); // Variance value var_k for A (page 4) - Assert.AreEqual(0.00087457, varD, 1e-8); - - - Assert.AreNotEqual(0.00087457, var, 1e-8); - Assert.AreNotEqual(0.00087457, var0, 1e-8); + Assert.AreEqual(0.00087457, varD, 1e-8); + + + Assert.AreEqual(0.00083016849579382347, var, 1e-10); + Assert.AreEqual(0.00067037111046188824, var0, 1e-10); Assert.IsFalse(double.IsNaN(var)); Assert.IsFalse(double.IsNaN(var0)); @@ -336,7 +336,7 @@ public void KappaVarianceTest1() } } - [TestMethod()] + [Test] public void KappaVarianceTest2() { // Example from http://vassarstats.net/kappa.html @@ -372,17 +372,17 @@ public void KappaVarianceTest2() double se0 = System.Math.Sqrt(var0); double seD = System.Math.Sqrt(varD); - Assert.AreEqual(0.072, a.StandardError, 0.0005); - - Assert.AreNotEqual(0.072, seD, 0.0005); - Assert.AreNotEqual(0.072, se0, 0.0005); + Assert.AreEqual(0.072, a.StandardError, 0.0005); + + Assert.AreEqual(0.073534791185213152, seD, 1e-10); + Assert.AreEqual(0.073509316753225237, se0, 1e-10); Assert.IsFalse(double.IsNaN(se)); Assert.IsFalse(double.IsNaN(se0)); Assert.IsFalse(double.IsNaN(seD)); } - [TestMethod()] + [Test] public void KappaVarianceTest3() { // Example from J. L. Fleiss, J. Cohen, B. S. Everitt, "Large sample @@ -423,7 +423,7 @@ public void KappaVarianceTest3() Assert.IsFalse(double.IsNaN(a.VarianceUnderNull)); } - [TestMethod()] + [Test] public void TotalTest() { int[,] matrix = @@ -447,7 +447,7 @@ public void TotalTest() Assert.AreEqual(3 + 6 + 9, colTotals[2]); } - [TestMethod()] + [Test] public void GeometricAgreementTest() { int[,] matrix = @@ -464,7 +464,7 @@ public void GeometricAgreementTest() Assert.IsFalse(Double.IsNaN(actual)); } - [TestMethod()] + [Test] public void ChiSquareTest() { int[,] matrix = @@ -484,7 +484,7 @@ public void ChiSquareTest() Assert.IsFalse(Double.IsNaN(actual)); } - [TestMethod()] + [Test] public void ChiSquareTest2() { int[,] matrix = diff --git a/Unit Tests/Accord.Tests.Statistics/Analysis/IndependentComponentAnalysisTest.cs b/Unit Tests/Accord.Tests.Statistics/Analysis/IndependentComponentAnalysisTest.cs index e108e4330..bc46c6446 100644 --- a/Unit Tests/Accord.Tests.Statistics/Analysis/IndependentComponentAnalysisTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Analysis/IndependentComponentAnalysisTest.cs @@ -24,11 +24,11 @@ namespace Accord.Tests.Statistics { using Accord.Math; using Accord.Statistics.Analysis; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System.IO; using System.Runtime.Serialization.Formatters.Binary; - [TestClass()] + [TestFixture] public class IndependentComponentAnalysisTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ComputeTest() { Accord.Math.Tools.SetupGenerator(0); @@ -108,7 +108,7 @@ public void ComputeTest() Assert.IsTrue(expected.IsEqual(revertMatrix, 0.008)); } - [TestMethod()] + [Test] public void ComputeTest2() { Accord.Math.Tools.SetupGenerator(0); @@ -160,7 +160,7 @@ public void ComputeTest2() Assert.IsTrue(reverted.IsEqual(original, 0.1)); } - [TestMethod()] + [Test] public void SeparateTest() { Accord.Math.Tools.SetupGenerator(0); @@ -186,7 +186,7 @@ public void SeparateTest() Assert.IsTrue(expected.IsEqual(actual, 1e-4)); } - [TestMethod()] + [Test] public void CombineTest() { Accord.Math.Tools.SetupGenerator(0); @@ -214,7 +214,7 @@ public void CombineTest() Assert.IsTrue(expected.IsEqual(actual, 1e-4)); } - [TestMethod()] + [Test] public void CombineTest2() { Accord.Math.Tools.SetupGenerator(0); @@ -242,7 +242,7 @@ public void CombineTest2() Assert.IsTrue(expected.IsEqual(actual, 1e-4f)); } - [TestMethod()] + [Test] public void SeparateTest2() { Accord.Math.Tools.SetupGenerator(0); @@ -268,7 +268,7 @@ public void SeparateTest2() Assert.IsTrue(expected.IsEqual(actual, 1e-4f)); } - [TestMethod()] + [Test] public void SerializeTest() { Accord.Math.Tools.SetupGenerator(0); diff --git a/Unit Tests/Accord.Tests.Statistics/Analysis/KernelDiscriminantAnalysisTest.cs b/Unit Tests/Accord.Tests.Statistics/Analysis/KernelDiscriminantAnalysisTest.cs index c3a660fde..3a7d96336 100644 --- a/Unit Tests/Accord.Tests.Statistics/Analysis/KernelDiscriminantAnalysisTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Analysis/KernelDiscriminantAnalysisTest.cs @@ -23,12 +23,12 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Analysis; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics.Kernels; using Accord.Math; using System; - [TestClass()] + [TestFixture] public class KernelDiscriminantAnalysisTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ClassifyTest() { // Create some sample input data instances. This is the same @@ -113,7 +113,7 @@ public void ClassifyTest() } - [TestMethod()] + [Test] public void ClassifyTest1() { // Create some sample input data @@ -165,7 +165,7 @@ public void ClassifyTest1() } - [TestMethod()] + [Test] public void ConstructorTest1() { double[,] inputs = @@ -208,7 +208,7 @@ public void ConstructorTest1() Assert.IsNull(target.Means); } - [TestMethod()] + [Test] public void ComputeTest() { double[,] inputs = @@ -236,7 +236,7 @@ public void ComputeTest() Assert.IsTrue(Matrix.IsEqual(actual, expected)); } - [TestMethod()] + [Test] public void ComputeTest2() { // Schölkopf KPCA toy example @@ -324,7 +324,7 @@ public void ComputeTest2() return inputs; } - [TestMethod()] + [Test] public void ComputeTest3() { // Schölkopf KPCA toy example @@ -358,7 +358,7 @@ public void ComputeTest3() } - [TestMethod()] + [Test] public void ThresholdTest() { double[,] inputs = diff --git a/Unit Tests/Accord.Tests.Statistics/Analysis/KernelPrincipalComponentAnalysisTest.cs b/Unit Tests/Accord.Tests.Statistics/Analysis/KernelPrincipalComponentAnalysisTest.cs index 22a86d8f8..416e5bbd4 100644 --- a/Unit Tests/Accord.Tests.Statistics/Analysis/KernelPrincipalComponentAnalysisTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Analysis/KernelPrincipalComponentAnalysisTest.cs @@ -26,10 +26,10 @@ namespace Accord.Tests.Statistics using Accord.Math; using Accord.Statistics.Analysis; using Accord.Statistics.Kernels; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System.Data; - [TestClass()] + [TestFixture] public class KernelPrincipalComponentAnalysisTest { @@ -49,7 +49,7 @@ public class KernelPrincipalComponentAnalysisTest }; - [TestMethod()] + [Test] public void TransformTest() { // Using a linear kernel should be equivalent to standard PCA @@ -91,7 +91,7 @@ public void TransformTest() Assert.AreEqual(2, target.ComponentMatrix.GetLength(1)); } - [TestMethod()] + [Test] public void TransformTest2() { // Using a linear kernel should be equivalent to standard PCA @@ -135,7 +135,7 @@ public void TransformTest2() Assert.IsTrue(Matrix.IsEqual(result, projection, 0.000001)); } - [TestMethod()] + [Test] public void TransformTest3() { // Using a linear kernel should be equivalent to standard PCA @@ -160,7 +160,7 @@ public void TransformTest3() Assert.IsTrue(thrown); } - [TestMethod()] + [Test] public void TransformTest4() { // Tested against R's kernlab @@ -540,7 +540,7 @@ public void TransformTest4() } - [TestMethod()] + [Test] public void TransformTest5() { int element = 10; @@ -582,7 +582,7 @@ public void TransformTest5() Assert.IsTrue(result.IsEqual(expected, 1e-10)); } - [TestMethod()] + [Test] public void TransformTest_Jagged() { double[][] sourceMatrix = new double[][] @@ -639,7 +639,7 @@ public void TransformTest_Jagged() Assert.IsTrue(Matrix.IsEqual(result, projection, 0.000001)); } - [TestMethod()] + [Test] public void RevertTest() { // Using a linear kernel should be equivalent to standard PCA @@ -661,11 +661,11 @@ public void RevertTest() Assert.IsTrue(Matrix.IsEqual(data, preimage, 0.0001)); } - [TestMethod()] + [Test] public void RevertTest2() { - string path = @"..\..\..\..\Unit Tests\Accord.Tests.Statistics\Resources\examples.xls"; + string path = @"Resources\examples.xls"; // Create a new reader, opening a given path ExcelReader reader = new ExcelReader(path); @@ -698,11 +698,11 @@ public void RevertTest2() Assert.IsTrue(!reversion.HasNaN()); } - [TestMethod()] + [Test] public void RevertTest3() { - string path = @"..\..\..\..\Unit Tests\Accord.Tests.Statistics\Resources\examples.xls"; + string path = @"Resources\examples.xls"; // Create a new reader, opening a given path ExcelReader reader = new ExcelReader(path); diff --git a/Unit Tests/Accord.Tests.Statistics/Analysis/LinearDiscriminantAnalysisTest.cs b/Unit Tests/Accord.Tests.Statistics/Analysis/LinearDiscriminantAnalysisTest.cs index 93ddf33f0..add04bf7a 100644 --- a/Unit Tests/Accord.Tests.Statistics/Analysis/LinearDiscriminantAnalysisTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Analysis/LinearDiscriminantAnalysisTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Analysis; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; - [TestClass()] + [TestFixture] public class LinearDiscriminantAnalysisTest { @@ -71,7 +71,7 @@ public TestContext TestContext }; - [TestMethod()] + [Test] public void ComputeTest() { LinearDiscriminantAnalysis lda = new LinearDiscriminantAnalysis(inputs, output); @@ -110,7 +110,7 @@ public void ComputeTest() Assert.IsTrue(Matrix.IsEqual(lda.ScatterWithinClass, expectedWithin, 0.01)); } - [TestMethod()] + [Test] public void ClassifyTest1() { // Create some sample input data instances. This is the same @@ -171,7 +171,7 @@ public void ClassifyTest1() } - [TestMethod()] + [Test] public void ComputeTest2() { LinearDiscriminantAnalysis lda = new LinearDiscriminantAnalysis(inputs, output); @@ -204,7 +204,7 @@ public void ComputeTest2() Assert.AreEqual(5.6, lda.Means[1]); } - [TestMethod()] + [Test] public void ProjectionTest() { LinearDiscriminantAnalysis lda = new LinearDiscriminantAnalysis(inputs, output); @@ -243,7 +243,7 @@ public void ProjectionTest() Assert.IsFalse(Matrix.HasNaN(projection)); } - [TestMethod()] + [Test] public void ClassifyTest() { LinearDiscriminantAnalysis lda = new LinearDiscriminantAnalysis(inputs, output); diff --git a/Unit Tests/Accord.Tests.Statistics/Analysis/LogisticRegressionAnalysisTest.cs b/Unit Tests/Accord.Tests.Statistics/Analysis/LogisticRegressionAnalysisTest.cs index 43312fdc8..886948ae4 100644 --- a/Unit Tests/Accord.Tests.Statistics/Analysis/LogisticRegressionAnalysisTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Analysis/LogisticRegressionAnalysisTest.cs @@ -23,16 +23,16 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Analysis; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Math; - [TestClass()] + [TestFixture] public class LogisticRegressionAnalysisTest { - [TestMethod()] + [Test] public void ComputeTest1() { @@ -63,7 +63,7 @@ public void ComputeTest1() Assert.AreEqual(expected[i], actual[i], 1e-6); } - [TestMethod()] + [Test] public void ComputeTest2() { // Test instance 01 @@ -113,7 +113,7 @@ public void ComputeTest2() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void ComputeTest3() { double[][] inputs = training.Submatrix(null, 0, 3); @@ -127,7 +127,7 @@ public void ComputeTest3() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void ComputeTest4() { @@ -204,7 +204,7 @@ public void ComputeTest4() Assert.IsFalse(Double.IsNaN(y)); } - [TestMethod()] + [Test] public void FromSummaryTest1() { // Suppose we have a (fictitious) data set about patients who diff --git a/Unit Tests/Accord.Tests.Statistics/Analysis/MultinomialLogisticRegressionAnalysisTest.cs b/Unit Tests/Accord.Tests.Statistics/Analysis/MultinomialLogisticRegressionAnalysisTest.cs index 86c609df8..4d263fcee 100644 --- a/Unit Tests/Accord.Tests.Statistics/Analysis/MultinomialLogisticRegressionAnalysisTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Analysis/MultinomialLogisticRegressionAnalysisTest.cs @@ -26,14 +26,14 @@ namespace Accord.Tests.Statistics using Accord.Math; using Accord.Statistics.Analysis; using Accord.Statistics.Filters; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class MultinomialLogisticRegressionAnalysisTest { - [TestMethod] + [Test] public void AnalyzeExample1() { // http://www.ats.ucla.edu/stat/stata/dae/mlogit.htm @@ -113,7 +113,7 @@ public void AnalyzeExample1() } - [TestMethod] + [Test] public void ComputeTest1() { double[][] inputs; @@ -197,7 +197,7 @@ public void ComputeTest1() Assert.AreEqual(21.678124991086548, wald[1][2].Statistic, 1e-4); } - [TestMethod] + [Test] public void ComputeTest2() { double[][] inputs; @@ -263,7 +263,7 @@ public void ComputeTest2() Assert.AreEqual(1405.9414080469473, analysis.Deviance, 1e-5); } - [TestMethod] + [Test] public void CoefficientsTest1() { double[][] inputs; diff --git a/Unit Tests/Accord.Tests.Statistics/Analysis/MultipleLinearRegressionAnalysisTest.cs b/Unit Tests/Accord.Tests.Statistics/Analysis/MultipleLinearRegressionAnalysisTest.cs index 7aa338ae5..a9fc8e550 100644 --- a/Unit Tests/Accord.Tests.Statistics/Analysis/MultipleLinearRegressionAnalysisTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Analysis/MultipleLinearRegressionAnalysisTest.cs @@ -24,14 +24,14 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Analysis; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using AForge; using Accord.Statistics.Models.Regression.Linear; using Accord.Math; using Accord.Statistics.Testing; - [TestClass()] + [TestFixture] public class MultipleLinearRegressionAnalysisTest { @@ -53,7 +53,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ComputeTest() { // Example 5.1 from @@ -174,7 +174,7 @@ public void ComputeTest() Assert.AreEqual(r2a, target.RSquareAdjusted); } - [TestMethod()] + [Test] public void ComputeTest2() { // Consider the following data. An experimenter would @@ -259,7 +259,7 @@ public void ComputeTest2() Assert.AreEqual(14.219378746271506, ci.Max); } - [TestMethod()] + [Test] public void RegressTest7() { double[][] example2 = diff --git a/Unit Tests/Accord.Tests.Statistics/Analysis/PartialLeastSquaresAnalysisTest.cs b/Unit Tests/Accord.Tests.Statistics/Analysis/PartialLeastSquaresAnalysisTest.cs index 15e5651bd..3446063ec 100644 --- a/Unit Tests/Accord.Tests.Statistics/Analysis/PartialLeastSquaresAnalysisTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Analysis/PartialLeastSquaresAnalysisTest.cs @@ -23,13 +23,13 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Analysis; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; using Tools = Accord.Statistics.Tools; using System; using Accord.Statistics.Models.Regression.Linear; - [TestClass()] + [TestFixture] public class PartialLeastSquaresAnalysisTest { @@ -125,7 +125,7 @@ private static PartialLeastSquaresAnalysis CreateWineExample(out double[,] input - [TestMethod()] + [Test] public void SimplsRegressionTest() { double[,] inputs; @@ -174,7 +174,7 @@ public void SimplsRegressionTest() } - [TestMethod()] + [Test] public void SimplsComputeTest() { double[,] inputs; @@ -209,8 +209,7 @@ public void SimplsComputeTest() } - [TestMethod()] - [DeploymentItem("Accord.Statistics.dll")] + [Test] public void NipalsComputeTest() { double[,] X = @@ -285,7 +284,7 @@ public void NipalsComputeTest() } - [TestMethod()] + [Test] public void NipalsComputeTest2() { // Example data from Chiang, Y.Q., Zhuang, Y.M and Yang, J.Y, "Optimal Fisher @@ -350,10 +349,10 @@ public void NipalsComputeTest2() var idxTrain = Matrix.Indices(0, 25); var idxTest = Matrix.Indices(25, 50); - double[,] inputs = Matrix.Stack( - x1.Submatrix(idxTrain), - x2.Submatrix(idxTrain), - x3.Submatrix(idxTrain)); + double[,] a = x1.Submatrix(idxTrain); + double[,] b = x2.Submatrix(idxTrain); + double[,] c = x3.Submatrix(idxTrain); + double[,] inputs = Matrix.Stack(new double[][,] { a, b, c }); double[,] outputs = Matrix.Expand( @@ -401,35 +400,34 @@ public void NipalsComputeTest2() Assert.IsTrue(Matrix.IsEqual(outputs, uq, 0.45)); - - double[,] test = Matrix.Stack( - x1.Submatrix(idxTest), - x2.Submatrix(idxTest), - x3.Submatrix(idxTest)); + a = x1.Submatrix(idxTest); + b = x2.Submatrix(idxTest); + c = x3.Submatrix(idxTest); + double[,] test = Matrix.Stack(new double[][,] { a, b, c }); // test regression for classification var regression = target.CreateRegression(); double[][] Y = regression.Compute(test.ToArray()); - int c; - Matrix.Max(Y[0], out c); - Assert.AreEqual(0, c); + int cl; + Matrix.Max(Y[0], out cl); + Assert.AreEqual(0, cl); - Matrix.Max(Y[11], out c); - Assert.AreEqual(0, c); + Matrix.Max(Y[11], out cl); + Assert.AreEqual(0, cl); - Matrix.Max(Y[29], out c); - Assert.AreEqual(1, c); + Matrix.Max(Y[29], out cl); + Assert.AreEqual(1, cl); - Matrix.Max(Y[30], out c); - Assert.AreEqual(1, c); + Matrix.Max(Y[30], out cl); + Assert.AreEqual(1, cl); - Matrix.Max(Y[52], out c); - Assert.AreEqual(2, c); + Matrix.Max(Y[52], out cl); + Assert.AreEqual(2, cl); - Matrix.Max(Y[70], out c); - Assert.AreEqual(2, c); + Matrix.Max(Y[70], out cl); + Assert.AreEqual(2, cl); PartialLeastSquaresAnalysis target2 = new PartialLeastSquaresAnalysis(inputs, outputs, @@ -466,7 +464,7 @@ public void NipalsComputeTest2() } - [TestMethod()] + [Test] public void NipalsComputeTest3() { // Example data from P. Geladi and B.R. Kowalski, "An example of 2-block @@ -562,7 +560,7 @@ public void NipalsComputeTest3() } - [TestMethod()] + [Test] public void VariableImportanceTest() { @@ -629,7 +627,7 @@ public void VariableImportanceTest() } - [TestMethod] + [Test] public void ExceptionTest() { double[,] X = diff --git a/Unit Tests/Accord.Tests.Statistics/Analysis/PrincipalComponentAnalysisTest.cs b/Unit Tests/Accord.Tests.Statistics/Analysis/PrincipalComponentAnalysisTest.cs index cc73c37a8..31a29ad3d 100644 --- a/Unit Tests/Accord.Tests.Statistics/Analysis/PrincipalComponentAnalysisTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Analysis/PrincipalComponentAnalysisTest.cs @@ -24,11 +24,11 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Analysis; using Accord.Statistics; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; using System; - [TestClass()] + [TestFixture] public class PrincipalComponentAnalysisTest { @@ -63,7 +63,7 @@ public TestContext TestContext { 1.1, 0.9 } }; - [TestMethod()] + [Test] public void ConstructorTest() { // Reproducing Lindsay Smith's "Tutorial on Principal Component Analysis" @@ -180,7 +180,7 @@ public void ConstructorTest() Assert.IsTrue(expected.IsEqual(actual, threshold: 1e-8)); } - [TestMethod()] + [Test] public void ConstructorTest2() { // Reproducing Lindsay Smith's "Tutorial on Principal Component Analysis" @@ -290,7 +290,7 @@ public void ConstructorTest2() Assert.IsTrue(expected.IsEqual(actual, threshold: 1e-8)); } - [TestMethod()] + [Test] public void TransformTest() { PrincipalComponentAnalysis target = new PrincipalComponentAnalysis(data); @@ -324,7 +324,7 @@ public void TransformTest() Assert.IsTrue(Matrix.IsEqual(result, expected, 0.01)); } - [TestMethod()] + [Test] public void TransformTest2() { // Lindsay's tutorial data @@ -344,7 +344,7 @@ public void TransformTest2() Assert.IsTrue(Matrix.IsEqual(result, actual, 0.01)); } - [TestMethod()] + [Test] public void TransformTest3() { PrincipalComponentAnalysis target = new PrincipalComponentAnalysis(data); @@ -362,7 +362,7 @@ public void TransformTest3() Assert.IsTrue(thrown); } - [TestMethod()] + [Test] public void FromCovarianceConstructorTest() { double[] mean = Accord.Statistics.Tools.Mean(data); @@ -403,7 +403,7 @@ public void FromCovarianceConstructorTest() Assert.IsTrue(Matrix.IsEqual(reverse, data, 0.01)); } - [TestMethod()] + [Test] public void FromCorrelationConstructorTest() { double[] mean = Accord.Statistics.Tools.Mean(data); @@ -434,7 +434,7 @@ public void FromCorrelationConstructorTest() } - [TestMethod()] + [Test] public void Revert() { PrincipalComponentAnalysis target = new PrincipalComponentAnalysis(data); @@ -452,7 +452,7 @@ public void Revert() Assert.IsTrue(Matrix.IsEqual(actual, data, 0.01)); } - [TestMethod] + [Test] public void ExceptionTest() { double[,] data = @@ -480,8 +480,7 @@ public void ExceptionTest() Assert.IsTrue(thrown); } - [TestMethod()] - [DeploymentItem("Accord.Statistics.dll")] + [Test] public void adjustTest() { double[,] data = (double[,])PrincipalComponentAnalysisTest.data.Clone(); @@ -518,7 +517,7 @@ public void adjustTest() /// ///A test for Transform /// - [TestMethod()] + [Test] public void TransformTest1() { PrincipalComponentAnalysis target = new PrincipalComponentAnalysis(data); diff --git a/Unit Tests/Accord.Tests.Statistics/Analysis/ProportionalHazardsAnalysisTest.cs b/Unit Tests/Accord.Tests.Statistics/Analysis/ProportionalHazardsAnalysisTest.cs index 7c6abe84e..b9adde662 100644 --- a/Unit Tests/Accord.Tests.Statistics/Analysis/ProportionalHazardsAnalysisTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Analysis/ProportionalHazardsAnalysisTest.cs @@ -1,164 +1,147 @@ -// Accord Unit Tests -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Tests.Statistics -{ - using Accord.Statistics.Analysis; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using System; - using Accord.Math; - using Accord.Statistics.Testing; - - [TestClass()] - public class ProportionalHazardsAnalysisTest - { - - - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - - [TestMethod()] - public void ComputeTest1() - { - // Consider the following example data, adapted from John C. Pezzullo's - // example for his great Cox's proportional hazards model example in - // JavaScript (http://www.sph.emory.edu/~cdckms/CoxPH/prophaz2.html). - - // In this data, we have three columns. The first column denotes the - // input variables for the problem. The second column, the survival - // times. And the last one is the output of the experiment (if the - // subject has died [1] or has survived [0]). - - double[,] example = - { - // input time censor - { 50, 1, 0 }, - { 70, 2, 1 }, - { 45, 3, 0 }, - { 35, 5, 0 }, - { 62, 7, 1 }, - { 50, 11, 0 }, - { 45, 4, 0 }, - { 57, 6, 0 }, - { 32, 8, 0 }, - { 57, 9, 1 }, - { 60, 10, 1 }, - }; - - // First we will extract the input, times and outputs - double[,] inputs = example.GetColumns(0); - double[] times = example.GetColumn(1); - int[] output = example.GetColumn(2).ToInt32(); - - // Now we can proceed and create the analysis - var cox = new ProportionalHazardsAnalysis(inputs, times, output); - - cox.Compute(); // compute the analysis - - // Now we can show an analysis summary - // Accord.Controls.DataGridBox.Show(cox.Coefficients); - - - // We can also investigate all parameters individually. For - // example the coefficients values will be available at - - double[] coef = cox.CoefficientValues; - double[] stde = cox.StandardErrors; - - // We can also obtain the hazards ratios - double[] ratios = cox.HazardRatios; - - // And other information such as the partial - // likelihood, the deviance and also make - // hypothesis tests on the parameters - - double partial = cox.LogLikelihood; - double deviance = cox.Deviance; - - // Chi-Square for whole model - ChiSquareTest chi = cox.ChiSquare; - - // Wald tests for individual parameters - WaldTest wald = cox.Coefficients[0].Wald; - - - // Finally, we can also use the model to predict - // scores for new observations (without considering time) - - double y1 = cox.Regression.Compute(new double[] { 63 }); - double y2 = cox.Regression.Compute(new double[] { 32 }); - - // Those scores can be interpreted by comparing then - // to 1. If they are greater than one, the odds are - // the patient will not survive. If the value is less - // than one, the patient is likely to survive. - - // The first value, y1, gives approximately 86.138, - // while the second value, y2, gives about 0.00072. - - - // We can also consider instant estimates for a given time: - double p1 = cox.Regression.Compute(new double[] { 63 }, 2); - double p2 = cox.Regression.Compute(new double[] { 63 }, 10); - - // Here, p1 is the score after 2 time instants, with a - // value of 0.0656. The second value, p2, is the time - // after 10 time instants, with a value of 6.2907. - - - Assert.AreEqual(86.138421225296526, y1); - Assert.AreEqual(0.00072281400325299814, y2); - - Assert.AreEqual(0.065660458190496693, p1); - Assert.AreEqual(6.2907511049223928, p2); - - Assert.AreEqual(1, coef.Length); - Assert.AreEqual(0.37704239281490765, coef[0]); - Assert.AreEqual(0.25415746361167235, stde[0]); - Assert.AreEqual(1.4579661153488215, ratios[0]); - - Assert.AreEqual(-2.0252666205735466, partial); - Assert.AreEqual(4.0505332411470931, deviance); - - Assert.AreEqual(0.13794183001851756, wald.PValue, 1e-4); - - Assert.AreEqual(1, chi.DegreesOfFreedom); - Assert.AreEqual(7.3570, chi.Statistic, 1e-4); - Assert.AreEqual(0.0067, chi.PValue, 1e-3); - - } - - } -} +// Accord Unit Tests +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Tests.Statistics +{ + using Accord.Math; + using Accord.Statistics.Analysis; + using Accord.Statistics.Distributions.Univariate; + using Accord.Statistics.Testing; + using NUnit.Framework; + + [TestFixture] + public class ProportionalHazardsAnalysisTest + { + + [Test] + public void ComputeTest1() + { + // Consider the following example data, adapted from John C. Pezzullo's + // example for his great Cox's proportional hazards model example in + // JavaScript (http://statpages.org/prophaz2.html). + + // In this data, we have three columns. The first column denotes the + // input variables for the problem. The second column, the survival + // times. And the last one is the output of the experiment (if the + // subject has died [1] or has survived [0]). + + double[,] example = + { + // input time censor + { 50, 1, 0 }, + { 70, 2, 1 }, + { 45, 3, 0 }, + { 35, 5, 0 }, + { 62, 7, 1 }, + { 50, 11, 0 }, + { 45, 4, 0 }, + { 57, 6, 0 }, + { 32, 8, 0 }, + { 57, 9, 1 }, + { 60, 10, 1 }, + }; + + // First we will extract the input, times and outputs + double[,] inputs = example.GetColumns(0); + double[] times = example.GetColumn(1); + SurvivalOutcome[] output = example.GetColumn(2).To(); + + // Now we can proceed and create the analysis + var cox = new ProportionalHazardsAnalysis(inputs, times, output); + + cox.Compute(); // compute the analysis + + // Now we can show an analysis summary + // Accord.Controls.DataGridBox.Show(cox.Coefficients); + + + // We can also investigate all parameters individually. For + // example the coefficients values will be available at + + double[] coef = cox.CoefficientValues; + double[] stde = cox.StandardErrors; + + // We can also obtain the hazards ratios + double[] ratios = cox.HazardRatios; + + // And other information such as the partial + // likelihood, the deviance and also make + // hypothesis tests on the parameters + + double partial = cox.LogLikelihood; + double deviance = cox.Deviance; + + // Chi-Square for whole model + ChiSquareTest chi = cox.ChiSquare; + + // Wald tests for individual parameters + WaldTest wald = cox.Coefficients[0].Wald; + + + // Finally, we can also use the model to predict + // scores for new observations (without considering time) + + double y1 = cox.Regression.Compute(new double[] { 63 }); + double y2 = cox.Regression.Compute(new double[] { 32 }); + + // Those scores can be interpreted by comparing then + // to 1. If they are greater than one, the odds are + // the patient will not survive. If the value is less + // than one, the patient is likely to survive. + + // The first value, y1, gives approximately 86.138, + // while the second value, y2, gives about 0.00072. + + + // We can also consider instant estimates for a given time: + double p1 = cox.Regression.Compute(new double[] { 63 }, 2); + double p2 = cox.Regression.Compute(new double[] { 63 }, 10); + + // Here, p1 is the score after 2 time instants, with a + // value of 0.0656. The second value, p2, is the time + // after 10 time instants, with a value of 6.2907. + + + Assert.AreEqual(86.138421225296526, y1); + Assert.AreEqual(0.00072281400325299814, y2); + + Assert.AreEqual(0.17989138010770425, p1); + Assert.AreEqual(15.950244161356357, p2); + + Assert.AreEqual(1, coef.Length); + Assert.AreEqual(0.37704239281490765, coef[0]); + Assert.AreEqual(0.25415746361167235, stde[0]); + Assert.AreEqual(1.4579661153488215, ratios[0]); + + Assert.AreEqual(-2.0252666205735466, partial, 1e-6); + Assert.AreEqual(4.0505332411470931, deviance, 1e-6); + + Assert.AreEqual(0.13794183001851756, wald.PValue, 1e-4); + + Assert.AreEqual(1, chi.DegreesOfFreedom); + Assert.AreEqual(7.3570, chi.Statistic, 1e-4); + Assert.AreEqual(0.0067, chi.PValue, 1e-3); + + } + + } +} diff --git a/Unit Tests/Accord.Tests.Statistics/Analysis/ReceiverOperatingCharacteristicTest.cs b/Unit Tests/Accord.Tests.Statistics/Analysis/ReceiverOperatingCharacteristicTest.cs index 45059c00f..b011fa8a0 100644 --- a/Unit Tests/Accord.Tests.Statistics/Analysis/ReceiverOperatingCharacteristicTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Analysis/ReceiverOperatingCharacteristicTest.cs @@ -26,9 +26,9 @@ namespace Accord.Tests.Statistics using Accord.Math; using Accord.Statistics.Analysis; using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class ReceiverOperatingCharacteristicTest { @@ -36,7 +36,7 @@ public class ReceiverOperatingCharacteristicTest // Accord.Tests.MachineLearning assembly in the file // ReceiverOperatingCharacteristicSvmTest.cs - [TestMethod()] + [Test] public void ComputeTest() { // Example from @@ -157,7 +157,7 @@ public void ComputeTest() Assert.AreEqual(0.04485087617325112, error); // DeLong estimate } - [TestMethod()] + [Test] public void ReceiverOperatingCharacteristicConstructorTest2() { double[] measurement = { 0, 0, 0, 0, 0, 1, 1, 1 }; @@ -217,7 +217,7 @@ public void ReceiverOperatingCharacteristicConstructorTest2() } - [TestMethod()] + [Test] public void DeLongVarianceTest() { // Example from Sampling Variability of Nonparametric Estimates of the @@ -317,7 +317,7 @@ public void DeLongVarianceTest() Assert.IsFalse(Double.IsNaN(curve.Variance)); } - [TestMethod()] + [Test] public void DeLongComparisonTest() { // Example from Sampling Variability of Nonparametric Estimates of the diff --git a/Unit Tests/Accord.Tests.Statistics/Analysis/StepwiseLogisticRegressionAnalysisTest.cs b/Unit Tests/Accord.Tests.Statistics/Analysis/StepwiseLogisticRegressionAnalysisTest.cs index 1146c5d6e..9fff64310 100644 --- a/Unit Tests/Accord.Tests.Statistics/Analysis/StepwiseLogisticRegressionAnalysisTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Analysis/StepwiseLogisticRegressionAnalysisTest.cs @@ -21,13 +21,13 @@ // namespace Accord.Tests.Statistics -{ - using Accord.Math; - using Accord.Statistics.Analysis; - using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; - - [TestClass()] +{ + using Accord.Math; + using Accord.Statistics.Analysis; + using Accord.Statistics.Testing; + using NUnit.Framework; + + [TestFixture] public class StepwiseLogisticRegressionAnalysisTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ComputeTest() { @@ -176,7 +176,7 @@ public void ComputeTest() } - [TestMethod()] + [Test] public void DoStepTest() { diff --git a/Unit Tests/Accord.Tests.Statistics/Analysis/WeightedConfusionMatrixTest.cs b/Unit Tests/Accord.Tests.Statistics/Analysis/WeightedConfusionMatrixTest.cs index e3002f441..67d7ae138 100644 --- a/Unit Tests/Accord.Tests.Statistics/Analysis/WeightedConfusionMatrixTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Analysis/WeightedConfusionMatrixTest.cs @@ -23,11 +23,11 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Analysis; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Math; - [TestClass()] + [TestFixture] public class WeightedConfusionMatrixTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void WeightedConfusionMatrixConstructorTest() { // Sample data from Fleiss, Cohen and Everitt (1968), Large sample standard errors @@ -79,7 +79,7 @@ public void WeightedConfusionMatrixConstructorTest() Assert.AreEqual(0.004270, target.WeightedVarianceUnderNull, 1e-3); } - [TestMethod()] + [Test] public void WeightedConfusionMatrixConstructorTest2() { double[,] matrix = diff --git a/Unit Tests/Accord.Tests.Statistics/CircularTest.cs b/Unit Tests/Accord.Tests.Statistics/CircularTest.cs index 56baf9405..0dd9974f0 100644 --- a/Unit Tests/Accord.Tests.Statistics/CircularTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/CircularTest.cs @@ -26,11 +26,11 @@ namespace Accord.Tests.Statistics using Accord.Math; using Accord.Statistics; using AForge; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using System.Data; - [TestClass()] + [TestFixture] public class CircularTest { @@ -46,7 +46,7 @@ public class CircularTest // Tests performed against the Circular Statistics Toolbox (Directional Statistics) // http://fr.mathworks.com/matlabcentral/fileexchange/10676-circular-statistics-toolbox--directional-statistics- - [TestMethod()] + [Test] public void WeightedKappaTest() { DataTable table = new DataTable(); @@ -72,7 +72,7 @@ public void WeightedKappaTest() Assert.AreEqual(expectedKappa, actualKappa, 1e-6); } - [TestMethod()] + [Test] public void KappaTest1() { double expected = 3.721646; @@ -81,7 +81,7 @@ public void KappaTest1() Assert.AreEqual(expected, actual, 1e-6); } - [TestMethod()] + [Test] public void KappaTest() { double mean = Circular.Mean(angles); @@ -92,7 +92,7 @@ public void KappaTest() Assert.AreEqual(expected, actual, 1e-6); } - [TestMethod()] + [Test] public void MeanTest() { double expected = 2.0519609734450655614e-01; @@ -101,7 +101,7 @@ public void MeanTest() Assert.AreEqual(expected, actual, 1e-15); } - [TestMethod()] + [Test] public void VarianceTest() { double expected = 1.4668557528213066465e-01; @@ -110,7 +110,7 @@ public void VarianceTest() Assert.AreEqual(expected, actual, 1e-15); } - [TestMethod()] + [Test] public void CircularDeviationTest() { /* angles = [ 0.003898633 5.956808760 0.318487983 5.887227832 0.641802182, 4.640345741, 0.931996171, 0.426819547, 0.624824460, 0.247553652, 6.282827901, 0.313780766, 0.093206440, 0.392279489, 0.601228848 ] @@ -129,7 +129,7 @@ public void CircularDeviationTest() Assert.AreEqual(expected, actual, 1e-15); } - [TestMethod()] + [Test] public void StandardDeviationTest() { double expected = 5.6325338695100524156e-01; @@ -138,7 +138,7 @@ public void StandardDeviationTest() Assert.AreEqual(expected, actual, 1e-15); } - [TestMethod()] + [Test] public void DistanceTest() { double x = 0.15; @@ -150,7 +150,7 @@ public void DistanceTest() Assert.AreEqual(expected, actual, 1e-15); } - [TestMethod()] + [Test] public void SkewnessTest() { double expected = 1.4938580058598621703e-01; @@ -159,7 +159,7 @@ public void SkewnessTest() Assert.AreEqual(expected, actual, 1e-15); } - [TestMethod()] + [Test] public void KurtosisTest() { double expected = 6.4794232277921437468e-01; @@ -168,7 +168,7 @@ public void KurtosisTest() Assert.AreEqual(expected, actual, 1e-15); } - [TestMethod()] + [Test] public void MedianTest() { double expected = 3.1378076599999993324e-01; @@ -177,7 +177,7 @@ public void MedianTest() Assert.AreEqual(expected, actual, 1e-15); } - [TestMethod()] + [Test] public void MedianTest_Odd() { double expected = 3.1613437449999998163e-01; @@ -186,7 +186,7 @@ public void MedianTest_Odd() Assert.AreEqual(expected, actual, 1e-15); } - [TestMethod()] + [Test] public void QuartilesTest() { DoubleRange range; @@ -196,7 +196,7 @@ public void QuartilesTest() Assert.AreEqual(0.60122884799999998, range.Max); } - [TestMethod()] + [Test] public void StandardErrorTest() { double actual = Circular.StandardError(angles, 0.05); @@ -204,7 +204,7 @@ public void StandardErrorTest() Assert.AreEqual(3.5294262881192373094e-01, actual); } - [TestMethod()] + [Test] public void ClockTest() { double[] hours = @@ -233,7 +233,7 @@ public void ClockTest() Assert.AreEqual(2, d, 1e-15); } - [TestMethod()] + [Test] public void ClockTest2() { double[] hours = diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/DirichletDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/DirichletDistributionTest.cs index 14c82492d..7bd630d19 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/DirichletDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/DirichletDistributionTest.cs @@ -21,36 +21,16 @@ // namespace Accord.Tests.Statistics -{ - using Accord.Statistics.Distributions.Multivariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using Accord.Math; - using Accord.Statistics.Distributions.Fitting; - using Accord.Statistics; - using System.Globalization; - - [TestClass()] +{ + using Accord.Math; + using Accord.Statistics.Distributions.Multivariate; + using NUnit.Framework; + + [TestFixture] public class DirichletDistributionTest { - - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - - [TestMethod()] + [Test] public void ConstructorTest4() { // Create a Dirichlet with the following concentrations @@ -68,7 +48,7 @@ public void ConstructorTest4() // 0.0329421259789253 0.0447071709713986 0.0941203599397865 // (the above matrix representation has been transcribed to text using) - string str = cov.ToString(DefaultMatrixFormatProvider.InvariantCulture); + // string str = cov.ToString(DefaultMatrixFormatProvider.InvariantCulture); // Probability mass functions diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/InverseWishartDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/InverseWishartDistributionTest.cs index 277469fd8..f7baab24d 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/InverseWishartDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/InverseWishartDistributionTest.cs @@ -21,36 +21,16 @@ // namespace Accord.Tests.Statistics -{ - using Accord.Statistics.Distributions.Multivariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using Accord.Math; - using Accord.Statistics.Distributions.Fitting; - using Accord.Statistics; - using System.Globalization; - - [TestClass()] +{ + using Accord.Math; + using Accord.Statistics.Distributions.Multivariate; + using NUnit.Framework; + + [TestFixture] public class InverseWishartDistributionTest { - - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - - [TestMethod()] + [Test] public void ConstructorTest4() { // Create a Inverse Wishart with the parameters @@ -77,8 +57,8 @@ public void ConstructorTest4() // -4.56 -56.18 -0.2 5.3 // (the above matrix representations have been transcribed to text using) - string scov = cov.ToString(DefaultMatrixFormatProvider.InvariantCulture); - string smean = mmean.ToString(DefaultMatrixFormatProvider.InvariantCulture); + // string scov = cov.ToString(DefaultMatrixFormatProvider.InvariantCulture); + // string smean = mmean.ToString(DefaultMatrixFormatProvider.InvariantCulture); // For compatibility reasons, .Mean stores a flattened mean matrix double[] mean = invWishart.Mean; // { 1.7, -0.2, -0.2, 5.3 } diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/MultivariateContinuousDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/MultivariateContinuousDistributionTest.cs index d0e569306..28cc72c31 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/MultivariateContinuousDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/MultivariateContinuousDistributionTest.cs @@ -1,461 +1,445 @@ -// Accord Unit Tests -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Tests.Statistics -{ - using Accord.Statistics.Distributions.Multivariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using Accord.Statistics.Distributions; - using Accord.Math; - using System; - using Accord.Statistics.Distributions.Fitting; - - - [TestClass()] - public class MultivariateContinuousDistributionTest - { - - - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - - internal virtual MultivariateContinuousDistribution CreateMultivariateContinuousDistribution() - { - double[] mean = { 0.2, 4.2 }; +// Accord Unit Tests +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Tests.Statistics +{ + using Accord.Statistics.Distributions.Multivariate; + using NUnit.Framework; + using Accord.Statistics.Distributions; + using Accord.Math; + using System; + using Accord.Statistics.Distributions.Fitting; + + + [TestFixture] + public class MultivariateContinuousDistributionTest + { + + + private TestContext testContextInstance; + + public TestContext TestContext + { + get + { + return testContextInstance; + } + set + { + testContextInstance = value; + } + } + + + + internal virtual MultivariateContinuousDistribution CreateMultivariateContinuousDistribution() + { + double[] mean = { 0.2, 4.2 }; double[,] cov = { { 1.2, 0.1 }, { 0.1, 2.3 }, - }; - - return new MultivariateNormalDistribution(mean, cov); - } - - [TestMethod()] - public void VarianceTest() - { - MultivariateContinuousDistribution target = CreateMultivariateContinuousDistribution(); - double[] actual = target.Variance; - double[] expected = { 1.2, 2.3 }; - Assert.IsTrue(expected.IsEqual(actual)); - } - - [TestMethod()] - public void MeanTest() - { - MultivariateContinuousDistribution target = CreateMultivariateContinuousDistribution(); - double[] actual = target.Mean; - double[] expected = { 0.2, 4.2 }; - Assert.IsTrue(expected.IsEqual(actual)); - } - - [TestMethod()] - public void DimensionTest() - { - MultivariateContinuousDistribution target = CreateMultivariateContinuousDistribution(); - int actual = target.Dimension; - int expected = 2; - Assert.AreEqual(expected, actual); - } - - [TestMethod()] - public void CovarianceTest() - { - MultivariateContinuousDistribution target = CreateMultivariateContinuousDistribution(); - double[,] actual = target.Covariance; + }; + + return new MultivariateNormalDistribution(mean, cov); + } + + [Test] + public void VarianceTest() + { + MultivariateContinuousDistribution target = CreateMultivariateContinuousDistribution(); + double[] actual = target.Variance; + double[] expected = { 1.2, 2.3 }; + Assert.IsTrue(expected.IsEqual(actual)); + } + + [Test] + public void MeanTest() + { + MultivariateContinuousDistribution target = CreateMultivariateContinuousDistribution(); + double[] actual = target.Mean; + double[] expected = { 0.2, 4.2 }; + Assert.IsTrue(expected.IsEqual(actual)); + } + + [Test] + public void DimensionTest() + { + MultivariateContinuousDistribution target = CreateMultivariateContinuousDistribution(); + int actual = target.Dimension; + int expected = 2; + Assert.AreEqual(expected, actual); + } + + [Test] + public void CovarianceTest() + { + MultivariateContinuousDistribution target = CreateMultivariateContinuousDistribution(); + double[,] actual = target.Covariance; double[,] expected = { { 1.2, 0.1 }, { 0.1, 2.3 }, - }; - Assert.IsTrue(expected.IsEqual(actual)); - } - - [TestMethod()] - public void ProbabilityDensityFunctionTest() - { - MultivariateContinuousDistribution target = CreateMultivariateContinuousDistribution(); - double[] x = { 0.4, 2 }; - double expected = 0.032309150392899; - double actual = target.ProbabilityDensityFunction(x); - Assert.AreEqual(expected, actual, 1e-10); - } - - [TestMethod()] - public void LogProbabilityDensityFunctionTest() - { - MultivariateContinuousDistribution target = CreateMultivariateContinuousDistribution(); - double[] x = { 0.4, 2 }; - double expected = System.Math.Log(0.032309150392899); - double actual = target.LogProbabilityDensityFunction(x); - Assert.AreEqual(expected, actual, 1e-10); - } - - [TestMethod()] - public void FitTest7() - { - MultivariateContinuousDistribution target = CreateMultivariateContinuousDistribution(); - + }; + Assert.IsTrue(expected.IsEqual(actual)); + } + + [Test] + public void ProbabilityDensityFunctionTest() + { + MultivariateContinuousDistribution target = CreateMultivariateContinuousDistribution(); + double[] x = { 0.4, 2 }; + double expected = 0.032309150392899; + double actual = target.ProbabilityDensityFunction(x); + Assert.AreEqual(expected, actual, 1e-10); + } + + [Test] + public void LogProbabilityDensityFunctionTest() + { + MultivariateContinuousDistribution target = CreateMultivariateContinuousDistribution(); + double[] x = { 0.4, 2 }; + double expected = System.Math.Log(0.032309150392899); + double actual = target.LogProbabilityDensityFunction(x); + Assert.AreEqual(expected, actual, 1e-10); + } + + [Test] + public void FitTest7() + { + MultivariateContinuousDistribution target = CreateMultivariateContinuousDistribution(); + double[][] observations = { new double[] { 1, 2 }, new double[] { 3, 2 }, new double[] { 2, 3 }, new double[] { 1, 2 }, - }; - - double[] weights = { 0.125, 0.125, 0.25, 0.5 }; - - target.Fit(observations, weights); - - double[] expectedMean = { 1.5, 2.25 }; + }; + + double[] weights = { 0.125, 0.125, 0.25, 0.5 }; + + target.Fit(observations, weights); + + double[] expectedMean = { 1.5, 2.25 }; double[,] expectedCov = { { 0.76190476190476186, 0.19047619047619047 }, { 0.19047619047619047, 0.2857142857142857 }, - }; - - Assert.IsTrue(expectedMean.IsEqual(target.Mean)); - Assert.IsTrue(expectedCov.IsEqual(target.Covariance)); - - - Assert.IsTrue(Matrix.Diagonal(expectedCov).IsEqual(target.Variance)); - - double[] x = { 0.4, 2 }; - double expected = 0.168681501947055; - double actual = target.ProbabilityDensityFunction(x); - Assert.AreEqual(expected, actual, 1e-10); - } - - [TestMethod()] - public void FitTest6() - { - MultivariateContinuousDistribution target = CreateMultivariateContinuousDistribution(); // TODO: Initialize to an appropriate value + }; + + Assert.IsTrue(expectedMean.IsEqual(target.Mean)); + Assert.IsTrue(expectedCov.IsEqual(target.Covariance)); + + + Assert.IsTrue(Matrix.Diagonal(expectedCov).IsEqual(target.Variance)); + + double[] x = { 0.4, 2 }; + double expected = 0.168681501947055; + double actual = target.ProbabilityDensityFunction(x); + Assert.AreEqual(expected, actual, 1e-10); + } + + [Test] + public void FitTest6() + { + MultivariateContinuousDistribution target = CreateMultivariateContinuousDistribution(); // TODO: Initialize to an appropriate value double[][] observations = { new double[] { 1, 2 }, new double[] { 3, 2 }, new double[] { 2, 3 }, new double[] { 1, 2 }, - }; - - target.Fit(observations); - - double[] expectedMean = { 1.75, 2.25 }; + }; + + target.Fit(observations); + + double[] expectedMean = { 1.75, 2.25 }; double[,] expectedCov = { { 0.91666666666666663, 0.083333333333333329 }, { 0.083333333333333329, 0.25 }, - }; - - Assert.IsTrue(expectedMean.IsEqual(target.Mean)); - Assert.IsTrue(expectedCov.IsEqual(target.Covariance)); - - Assert.IsTrue(expectedCov.Diagonal().IsEqual(target.Variance)); - - double[] x = { 0.4, 2 }; - double expected = 0.120833904312578; - double actual = target.ProbabilityDensityFunction(x); - Assert.AreEqual(expected, actual, 1e-10); - } - - [TestMethod()] - public void FitTest5() - { - MultivariateContinuousDistribution target = CreateMultivariateContinuousDistribution(); // TODO: Initialize to an appropriate value + }; + + Assert.IsTrue(expectedMean.IsEqual(target.Mean)); + Assert.IsTrue(expectedCov.IsEqual(target.Covariance)); + + Assert.IsTrue(expectedCov.Diagonal().IsEqual(target.Variance)); + + double[] x = { 0.4, 2 }; + double expected = 0.120833904312578; + double actual = target.ProbabilityDensityFunction(x); + Assert.AreEqual(expected, actual, 1e-10); + } + + [Test] + public void FitTest5() + { + MultivariateContinuousDistribution target = CreateMultivariateContinuousDistribution(); // TODO: Initialize to an appropriate value double[][] observations = { new double[] { 1, 1 }, new double[] { 1, 1 }, - }; - - double[] weights = { 0.50, 0.50 }; - - bool thrown; - - IFittingOptions options = new NormalOptions() - { - Regularization = 0.1 - }; - - thrown = false; - try - { - target.Fit(observations, weights); - } - catch - { - thrown = true; - } - - Assert.AreEqual(true, thrown); - - - thrown = false; - try - { - target.Fit(observations, weights, options); - } - catch - { - thrown = true; - } - - Assert.AreEqual(false, thrown); - } - - [TestMethod()] - public void FitTest4() - { - MultivariateContinuousDistribution target = CreateMultivariateContinuousDistribution(); // TODO: Initialize to an appropriate value + }; + + double[] weights = { 0.50, 0.50 }; + + bool thrown; + + IFittingOptions options = new NormalOptions() + { + Regularization = 0.1 + }; + + thrown = false; + try + { + target.Fit(observations, weights); + } + catch + { + thrown = true; + } + + Assert.AreEqual(true, thrown); + + + thrown = false; + try + { + target.Fit(observations, weights, options); + } + catch + { + thrown = true; + } + + Assert.AreEqual(false, thrown); + } + + [Test] + public void FitTest4() + { + MultivariateContinuousDistribution target = CreateMultivariateContinuousDistribution(); // TODO: Initialize to an appropriate value double[][] observations = { new double[] { 1, 1 }, new double[] { 1, 1 }, - }; - - bool thrown; - - IFittingOptions options = new NormalOptions() - { - Regularization = 0.1 - }; - - thrown = false; - try - { - target.Fit(observations); - } - catch - { - thrown = true; - } - - Assert.AreEqual(true, thrown); - - - thrown = false; - try - { - target.Fit(observations, options); - } - catch - { - thrown = true; - } - - Assert.AreEqual(false, thrown); - } - - [TestMethod()] - [DeploymentItem("Accord.Statistics.dll")] - public void ProbabilityFunctionTest() - { - IDistribution target = CreateMultivariateContinuousDistribution(); - double[] x = { 0.4, 2 }; - double expected = 0.032309150392899; - double actual = target.ProbabilityFunction(x); - Assert.AreEqual(expected, actual, 1e-10); - } - - - [TestMethod()] - [DeploymentItem("Accord.Statistics.dll")] - public void LogProbabilityFunctionTest() - { - IDistribution target = CreateMultivariateContinuousDistribution(); - double[] x = { 0.4, 2 }; - double expected = System.Math.Log(0.032309150392899); - double actual = target.LogProbabilityFunction(x); - Assert.AreEqual(expected, actual, 1e-10); - } - - [TestMethod()] - [DeploymentItem("Accord.Statistics.dll")] - public void FitTest3() - { - IDistribution target = CreateMultivariateContinuousDistribution(); - + }; + + bool thrown; + + IFittingOptions options = new NormalOptions() + { + Regularization = 0.1 + }; + + thrown = false; + try + { + target.Fit(observations); + } + catch + { + thrown = true; + } + + Assert.AreEqual(true, thrown); + + + thrown = false; + try + { + target.Fit(observations, options); + } + catch + { + thrown = true; + } + + Assert.AreEqual(false, thrown); + } + + [Test] + public void ProbabilityFunctionTest() + { + IDistribution target = CreateMultivariateContinuousDistribution(); + double[] x = { 0.4, 2 }; + double expected = 0.032309150392899; + double actual = target.ProbabilityFunction(x); + Assert.AreEqual(expected, actual, 1e-10); + } + + + [Test] + public void LogProbabilityFunctionTest() + { + IDistribution target = CreateMultivariateContinuousDistribution(); + double[] x = { 0.4, 2 }; + double expected = System.Math.Log(0.032309150392899); + double actual = target.LogProbabilityFunction(x); + Assert.AreEqual(expected, actual, 1e-10); + } + + [Test] + public void FitTest3() + { + IDistribution target = CreateMultivariateContinuousDistribution(); + double[][] observations = { new double[] { 1, 2 }, new double[] { 3, 2 }, new double[] { 2, 3 }, new double[] { 1, 2 }, - }; - - target.Fit(observations); - - double[] expectedMean = Accord.Statistics.Tools.Mean(observations); - double[,] expectedCov = Accord.Statistics.Tools.Covariance(observations, expectedMean); - - MultivariateContinuousDistribution actual = target as MultivariateContinuousDistribution; - - Assert.IsTrue(expectedMean.IsEqual(actual.Mean)); - Assert.IsTrue(expectedCov.IsEqual(actual.Covariance)); - } - - /// - ///A test for Accord.Statistics.Distributions.IDistribution.Fit - /// - [TestMethod()] - [DeploymentItem("Accord.Statistics.dll")] - public void FitTest2() - { - IDistribution target = CreateMultivariateContinuousDistribution(); - + }; + + target.Fit(observations); + + double[] expectedMean = Accord.Statistics.Tools.Mean(observations); + double[,] expectedCov = Accord.Statistics.Tools.Covariance(observations, expectedMean); + + MultivariateContinuousDistribution actual = target as MultivariateContinuousDistribution; + + Assert.IsTrue(expectedMean.IsEqual(actual.Mean)); + Assert.IsTrue(expectedCov.IsEqual(actual.Covariance)); + } + + [Test] + public void FitTest2() + { + IDistribution target = CreateMultivariateContinuousDistribution(); + double[][] observations = { new double[] { 1, 2 }, new double[] { 3, 2 }, new double[] { 2, 3 }, new double[] { 1, 2 }, - }; - - target.Fit(observations); - - double[] expectedMean = Accord.Statistics.Tools.Mean(observations); - double[,] expectedCov = Accord.Statistics.Tools.Covariance(observations, expectedMean); - - MultivariateContinuousDistribution actual = target as MultivariateContinuousDistribution; - - Assert.IsTrue(expectedMean.IsEqual(actual.Mean)); - Assert.IsTrue(expectedCov.IsEqual(actual.Covariance)); - } - - /// - ///A test for Accord.Statistics.Distributions.IDistribution.Fit - /// - [TestMethod()] - [DeploymentItem("Accord.Statistics.dll")] - public void FitTest1() - { - IDistribution target = CreateMultivariateContinuousDistribution(); // TODO: Initialize to an appropriate value - + }; + + target.Fit(observations); + + double[] expectedMean = Accord.Statistics.Tools.Mean(observations); + double[,] expectedCov = Accord.Statistics.Tools.Covariance(observations, expectedMean); + + MultivariateContinuousDistribution actual = target as MultivariateContinuousDistribution; + + Assert.IsTrue(expectedMean.IsEqual(actual.Mean)); + Assert.IsTrue(expectedCov.IsEqual(actual.Covariance)); + } + + [Test] + public void FitTest1() + { + IDistribution target = CreateMultivariateContinuousDistribution(); // TODO: Initialize to an appropriate value + Array observations = new double[][] { new double[] { 1, 1 }, new double[] { 1, 1 }, - }; - - bool thrown; - - IFittingOptions options = new NormalOptions() - { - Regularization = 0.1 - }; - - thrown = false; - try - { - target.Fit(observations); - } - catch - { - thrown = true; - } - - Assert.AreEqual(true, thrown); - - - thrown = false; - try - { - target.Fit(observations, options); - } - catch - { - thrown = true; - } - - Assert.AreEqual(false, thrown); - } - - - - /// - ///A test for Accord.Statistics.Distributions.IDistribution.Fit - /// - [TestMethod()] - [DeploymentItem("Accord.Statistics.dll")] - public void FitTest() - { - IDistribution target = CreateMultivariateContinuousDistribution(); - + }; + + bool thrown; + + IFittingOptions options = new NormalOptions() + { + Regularization = 0.1 + }; + + thrown = false; + try + { + target.Fit(observations); + } + catch + { + thrown = true; + } + + Assert.AreEqual(true, thrown); + + + thrown = false; + try + { + target.Fit(observations, options); + } + catch + { + thrown = true; + } + + Assert.AreEqual(false, thrown); + } + + + [Test] + public void FitTest() + { + IDistribution target = CreateMultivariateContinuousDistribution(); + double[][] observations = { new double[] { 1, 1 }, new double[] { 1, 1 }, - }; - - double[] weights = { 0.50, 0.50 }; - - bool thrown; - - IFittingOptions options = new NormalOptions() - { - Regularization = 0.1 - }; - - thrown = false; - try - { - target.Fit(observations, weights); - } - catch - { - thrown = true; - } - - Assert.AreEqual(true, thrown); - - - thrown = false; - try - { - target.Fit(observations, weights, options); - } - catch - { - thrown = true; - } - - Assert.AreEqual(false, thrown); - } - - - - } -} + }; + + double[] weights = { 0.50, 0.50 }; + + bool thrown; + + IFittingOptions options = new NormalOptions() + { + Regularization = 0.1 + }; + + thrown = false; + try + { + target.Fit(observations, weights); + } + catch + { + thrown = true; + } + + Assert.AreEqual(true, thrown); + + + thrown = false; + try + { + target.Fit(observations, weights, options); + } + catch + { + thrown = true; + } + + Assert.AreEqual(false, thrown); + } + + + + } +} diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/MultivariateEmpiricalDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/MultivariateEmpiricalDistributionTest.cs index dc8e685df..a6fe6b1bc 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/MultivariateEmpiricalDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/MultivariateEmpiricalDistributionTest.cs @@ -1,355 +1,336 @@ -// Accord Unit Tests -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Tests.Statistics -{ - using Accord.Statistics.Distributions.Multivariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using Accord.Math; - using Accord.Statistics.Distributions.Fitting; - using Accord.Statistics; - using System.Globalization; - using Accord.Statistics.Distributions.DensityKernels; - using System; - - [TestClass()] - public class MultivariateEmpiricalDistributionTest - { - - - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - - [TestMethod()] - public void ConstructorTest4() - { - // Suppose we have the following data, and we would - // like to estimate a distribution from this data - - double[][] samples = - { - new double[] { 0, 1 }, - new double[] { 1, 2 }, - new double[] { 5, 1 }, - new double[] { 7, 1 }, - new double[] { 6, 1 }, - new double[] { 5, 7 }, - new double[] { 2, 1 }, - }; - - // Start by specifying a density kernel - IDensityKernel kernel = new EpanechnikovKernel(dimension: 2); - - // Create a multivariate Empirical distribution from the samples - var dist = new MultivariateEmpiricalDistribution(kernel, samples); - - - // Common measures - double[] mean = dist.Mean; // { 3.71, 2.00 } - double[] median = dist.Median; // { 3.71, 2.00 } - double[] var = dist.Variance; // { 7.23, 5.00 } (diagonal from cov) - double[,] cov = dist.Covariance; // { { 7.23, 0.83 }, { 0.83, 5.00 } } - - // Probability mass functions - double pdf1 = dist.ProbabilityDensityFunction(new double[] { 2, 1 }); // 0.039131176997318849 - double pdf2 = dist.ProbabilityDensityFunction(new double[] { 4, 2 }); // 0.010212109770266639 - double pdf3 = dist.ProbabilityDensityFunction(new double[] { 5, 7 }); // 0.02891906722705221 - double lpdf = dist.LogProbabilityDensityFunction(new double[] { 5, 7 }); // -3.5432541357714742 - - - Assert.AreEqual(3.7142857142857144, mean[0]); - Assert.AreEqual(2.0, mean[1]); - Assert.AreEqual(3.7142857142857144, median[0]); - Assert.AreEqual(2.0, median[1]); - Assert.AreEqual(7.2380952380952381, var[0]); - Assert.AreEqual(5.0, var[1]); - Assert.AreEqual(7.2380952380952381, cov[0, 0]); - Assert.AreEqual(0.83333333333333337, cov[0, 1]); - Assert.AreEqual(0.83333333333333337, cov[1, 0]); - Assert.AreEqual(5.0, cov[1, 1]); - Assert.AreEqual(0.039131176997318849, pdf1); - Assert.AreEqual(0.010212109770266639, pdf2); - Assert.AreEqual(0.02891906722705221, pdf3); - Assert.AreEqual(-3.5432541357714742, lpdf); - } - - - - - [TestMethod()] - public void FitTest() - { - double[][] observations = - { - new double[] { 0.1000, -0.2000 }, - new double[] { 0.4000, 0.6000 }, - new double[] { 2.0000, 0.2000 }, - new double[] { 2.0000, 0.3000 } - }; - - var target = new MultivariateEmpiricalDistribution(observations); - - double[] weigths = { 0.25, 0.25, 0.25, 0.25 }; - - bool thrown = false; - - try - { - target.Fit(observations, weigths); - } - catch (ArgumentException) - { - thrown = true; - } - - Assert.IsTrue(thrown); - } - - [TestMethod()] - public void FitTest2() - { - double[][] observations = - { - new double[] { 0.1000, -0.2000 }, - new double[] { 0.4000, 0.6000 }, - new double[] { 2.0000, 0.2000 }, - new double[] { 2.0000, 0.3000 } - }; - - double[] mean = Accord.Statistics.Tools.Mean(observations); - double[,] cov = Accord.Statistics.Tools.Covariance(observations); - - var target = new MultivariateEmpiricalDistribution(observations); - - target.Fit(observations); - - Assert.IsTrue(Matrix.IsEqual(mean, target.Mean)); - Assert.IsTrue(Matrix.IsEqual(cov, target.Covariance, 1e-10)); - } - - [TestMethod()] - public void GenerateTest1() - { - Accord.Math.Tools.SetupGenerator(0); - - double[] mean = { 2, 6 }; - - double[,] cov = - { - { 2, 1 }, - { 1, 5 } - }; - - var normal = new MultivariateNormalDistribution(mean, cov); - double[][] source = normal.Generate(10000000); - - var target = new MultivariateEmpiricalDistribution(source); - - Assert.IsTrue(mean.IsEqual(target.Mean, 0.001)); - Assert.IsTrue(cov.IsEqual(target.Covariance, 0.003)); - - double[][] samples = target.Generate(10000000); - - double[] sampleMean = samples.Mean(); - double[,] sampleCov = samples.Covariance(); - - Assert.AreEqual(2, sampleMean[0], 1e-2); - Assert.AreEqual(6, sampleMean[1], 1e-2); - Assert.AreEqual(2, sampleCov[0, 0], 1e-2); - Assert.AreEqual(1, sampleCov[0, 1], 1e-2); - Assert.AreEqual(1, sampleCov[1, 0], 1e-2); - Assert.AreEqual(5, sampleCov[1, 1], 2e-2); - } - - - [TestMethod()] - public void EpanechnikovKernelTest() - { - EpanechnikovKernel kernel = new EpanechnikovKernel(dimension: 1); - - Assert.AreEqual(3.0 / 4.0, kernel.Constant); - - double[] actual = new double[11]; - for (int i = 0; i < actual.Length; i++) - actual[i] = kernel.Function((i - 5) / 10.0); - - double[] expected = - { - 0.5625, 0.63, 0.6825, 0.72, 0.74249999999999994, - 0.75, - 0.74249999999999994, 0.72, 0.6825, 0.63, 0.5625 - }; - - for (int i = 0; i < actual.Length; i++) - Assert.AreEqual(expected[i], actual[i]); - } - - [TestMethod()] - public void WeightedEmpiricalDistributionConstructorTest() - { - double[] original = { 5, 5, 1, 4, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 4, 3, 2, 3 }; - var distribution = new MultivariateEmpiricalDistribution(original.ToArray()); - - int[] weights = { 2, 1, 1, 1, 2, 3, 1, 3, 1, 1, 1, 1 }; - double[] sources = { 5, 1, 4, 1, 2, 3, 4, 3, 4, 3, 2, 3 }; - double[][] samples = sources.ToArray(); - var target = new MultivariateEmpiricalDistribution(samples, weights); - - Assert.AreEqual(distribution.Mean[0], target.Mean[0]); - Assert.AreEqual(distribution.Median[0], target.Median[0]); - Assert.AreEqual(distribution.Mode[0], target.Mode[0]); - Assert.AreEqual(distribution.Smoothing[0, 0], target.Smoothing[0, 0]); - Assert.AreEqual(distribution.Variance[0], target.Variance[0]); - Assert.IsTrue(target.Weights.IsEqual(weights.Divide(weights.Sum()))); - Assert.AreEqual(target.Samples, samples); - - for (double x = 0; x < 6; x += 0.1) - { - double actual, expected; - expected = distribution.ComplementaryDistributionFunction(x); - actual = target.ComplementaryDistributionFunction(x); - Assert.AreEqual(expected, actual); - - expected = distribution.DistributionFunction(x); - actual = target.DistributionFunction(x); - Assert.AreEqual(expected, actual); - - expected = distribution.LogProbabilityDensityFunction(x); - actual = target.LogProbabilityDensityFunction(x); - Assert.AreEqual(expected, actual, 1e-15); - - expected = distribution.ProbabilityDensityFunction(x); - actual = target.ProbabilityDensityFunction(x); - Assert.AreEqual(expected, actual, 1e-15); - } - } - - [TestMethod()] - public void WeightedEmpiricalDistributionConstructorTest2() - { - double[] original = { 5, 5, 1, 4, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 4, 3, 2, 3 }; - var distribution = new MultivariateEmpiricalDistribution(original.ToArray()); - - double[] weights = { 2, 1, 1, 1, 2, 3, 1, 3, 1, 1, 1, 1 }; - double[] source = { 5, 1, 4, 1, 2, 3, 4, 3, 4, 3, 2, 3 }; - double[][] samples = source.ToArray(); - - weights = weights.Divide(weights.Sum()); - - var target = new MultivariateEmpiricalDistribution(samples, - weights, distribution.Smoothing); - - Assert.AreEqual(distribution.Mean[0], target.Mean[0]); - Assert.AreEqual(distribution.Median[0], target.Median[0]); - Assert.AreEqual(distribution.Mode[0], target.Mode[0]); - Assert.AreEqual(distribution.Smoothing[0, 0], target.Smoothing[0, 0]); - Assert.AreEqual(1.3655172413793104, target.Variance[0]); - Assert.AreEqual(target.Weights, weights); - Assert.AreEqual(target.Samples, samples); - - for (double x = 0; x < 6; x += 0.1) - { - double actual, expected; - expected = distribution.ComplementaryDistributionFunction(x); - actual = target.ComplementaryDistributionFunction(x); - Assert.AreEqual(expected, actual, 1e-15); - - expected = distribution.DistributionFunction(x); - actual = target.DistributionFunction(x); - Assert.AreEqual(expected, actual, 1e-15); - - expected = distribution.LogProbabilityDensityFunction(x); - actual = target.LogProbabilityDensityFunction(x); - Assert.AreEqual(expected, actual, 1e-15); - - expected = distribution.ProbabilityDensityFunction(x); - actual = target.ProbabilityDensityFunction(x); - Assert.AreEqual(expected, actual, 1e-15); - } - } - - [TestMethod()] - public void WeightedEmpiricalDistributionConstructorTest3() - { - double[] weights = { 2, 1, 1, 1, 2, 3, 1, 3, 1, 1, 1, 1 }; - double[] samples = { 5, 1, 4, 1, 2, 3, 4, 3, 4, 3, 2, 3 }; - - weights = weights.Divide(weights.Sum()); - - var target = new MultivariateEmpiricalDistribution(samples.ToArray(), weights); - - Assert.AreEqual(1.2377597081667415, target.Smoothing[0, 0]); - } - - [TestMethod()] - public void WeightedEmpiricalDistribution_DistributionFunction() - { - double[][] samples = - { - new double[] { 5, 2 }, - new double[] { 1, 5 }, - new double[] { 4, 7 }, - new double[] { 1, 6 }, - new double[] { 2, 2 }, - new double[] { 3, 4 }, - new double[] { 4, 8 }, - new double[] { 3, 2 }, - new double[] { 4, 4 }, - new double[] { 3, 7 }, - new double[] { 2, 4 }, - new double[] { 3, 1 }, - }; - - - var target = new MultivariateEmpiricalDistribution(samples); - - double[] expected = - { - 0.33333333333333331, 0.083333333333333329, 0.83333333333333337, - 0.16666666666666666, 0.083333333333333329, 0.41666666666666669, - 0.91666666666666663, 0.25, 0.5, - 0.66666666666666663, 0.16666666666666666, 0.083333333333333329 - }; - - for (int i = 0; i < samples.Length; i++) - { - double e = expected[i]; - double a = target.DistributionFunction(samples[i]); - Assert.AreEqual(e, a); - } - - } - } -} +// Accord Unit Tests +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Tests.Statistics +{ + using Accord.Math; + using Accord.Statistics; + using Accord.Statistics.Distributions.DensityKernels; + using Accord.Statistics.Distributions.Multivariate; + using NUnit.Framework; + using System; + + [TestFixture] + public class MultivariateEmpiricalDistributionTest + { + + [Test] + public void ConstructorTest4() + { + // Suppose we have the following data, and we would + // like to estimate a distribution from this data + + double[][] samples = + { + new double[] { 0, 1 }, + new double[] { 1, 2 }, + new double[] { 5, 1 }, + new double[] { 7, 1 }, + new double[] { 6, 1 }, + new double[] { 5, 7 }, + new double[] { 2, 1 }, + }; + + // Start by specifying a density kernel + IDensityKernel kernel = new EpanechnikovKernel(dimension: 2); + + // Create a multivariate Empirical distribution from the samples + var dist = new MultivariateEmpiricalDistribution(kernel, samples); + + + // Common measures + double[] mean = dist.Mean; // { 3.71, 2.00 } + double[] median = dist.Median; // { 3.71, 2.00 } + double[] var = dist.Variance; // { 7.23, 5.00 } (diagonal from cov) + double[,] cov = dist.Covariance; // { { 7.23, 0.83 }, { 0.83, 5.00 } } + + // Probability mass functions + double pdf1 = dist.ProbabilityDensityFunction(new double[] { 2, 1 }); // 0.039131176997318849 + double pdf2 = dist.ProbabilityDensityFunction(new double[] { 4, 2 }); // 0.010212109770266639 + double pdf3 = dist.ProbabilityDensityFunction(new double[] { 5, 7 }); // 0.02891906722705221 + double lpdf = dist.LogProbabilityDensityFunction(new double[] { 5, 7 }); // -3.5432541357714742 + + + Assert.AreEqual(3.7142857142857144, mean[0]); + Assert.AreEqual(2.0, mean[1]); + Assert.AreEqual(3.7142857142857144, median[0]); + Assert.AreEqual(2.0, median[1]); + Assert.AreEqual(7.2380952380952381, var[0]); + Assert.AreEqual(5.0, var[1]); + Assert.AreEqual(7.2380952380952381, cov[0, 0]); + Assert.AreEqual(0.83333333333333337, cov[0, 1]); + Assert.AreEqual(0.83333333333333337, cov[1, 0]); + Assert.AreEqual(5.0, cov[1, 1]); + Assert.AreEqual(0.039131176997318849, pdf1); + Assert.AreEqual(0.010212109770266639, pdf2); + Assert.AreEqual(0.02891906722705221, pdf3); + Assert.AreEqual(-3.5432541357714742, lpdf); + } + + + + + [Test] + public void FitTest() + { + double[][] observations = + { + new double[] { 0.1000, -0.2000 }, + new double[] { 0.4000, 0.6000 }, + new double[] { 2.0000, 0.2000 }, + new double[] { 2.0000, 0.3000 } + }; + + var target = new MultivariateEmpiricalDistribution(observations); + + double[] weigths = { 0.25, 0.25, 0.25, 0.25 }; + + bool thrown = false; + + try + { + target.Fit(observations, weigths); + } + catch (ArgumentException) + { + thrown = true; + } + + Assert.IsTrue(thrown); + } + + [Test] + public void FitTest2() + { + double[][] observations = + { + new double[] { 0.1000, -0.2000 }, + new double[] { 0.4000, 0.6000 }, + new double[] { 2.0000, 0.2000 }, + new double[] { 2.0000, 0.3000 } + }; + + double[] mean = Accord.Statistics.Tools.Mean(observations); + double[,] cov = Accord.Statistics.Tools.Covariance(observations); + + var target = new MultivariateEmpiricalDistribution(observations); + + target.Fit(observations); + + Assert.IsTrue(Matrix.IsEqual(mean, target.Mean)); + Assert.IsTrue(Matrix.IsEqual(cov, target.Covariance, 1e-10)); + } + + [Test] + public void GenerateTest1() + { + Accord.Math.Tools.SetupGenerator(0); + + double[] mean = { 2, 6 }; + + double[,] cov = + { + { 2, 1 }, + { 1, 5 } + }; + + var normal = new MultivariateNormalDistribution(mean, cov); + double[][] source = normal.Generate(10000000); + + var target = new MultivariateEmpiricalDistribution(source); + + Assert.IsTrue(mean.IsEqual(target.Mean, 0.001)); + Assert.IsTrue(cov.IsEqual(target.Covariance, 0.003)); + + double[][] samples = target.Generate(10000000); + + double[] sampleMean = samples.Mean(); + double[,] sampleCov = samples.Covariance(); + + Assert.AreEqual(2, sampleMean[0], 1e-2); + Assert.AreEqual(6, sampleMean[1], 1e-2); + Assert.AreEqual(2, sampleCov[0, 0], 1e-2); + Assert.AreEqual(1, sampleCov[0, 1], 1e-2); + Assert.AreEqual(1, sampleCov[1, 0], 1e-2); + Assert.AreEqual(5, sampleCov[1, 1], 2e-2); + } + + + [Test] + public void EpanechnikovKernelTest() + { + EpanechnikovKernel kernel = new EpanechnikovKernel(dimension: 1); + + Assert.AreEqual(3.0 / 4.0, kernel.Constant); + + double[] actual = new double[11]; + for (int i = 0; i < actual.Length; i++) + actual[i] = kernel.Function((i - 5) / 10.0); + + double[] expected = + { + 0.5625, 0.63, 0.6825, 0.72, 0.74249999999999994, + 0.75, + 0.74249999999999994, 0.72, 0.6825, 0.63, 0.5625 + }; + + for (int i = 0; i < actual.Length; i++) + Assert.AreEqual(expected[i], actual[i]); + } + + [Test] + public void WeightedEmpiricalDistributionConstructorTest() + { + double[] original = { 5, 5, 1, 4, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 4, 3, 2, 3 }; + var distribution = new MultivariateEmpiricalDistribution(original.ToArray()); + + int[] weights = { 2, 1, 1, 1, 2, 3, 1, 3, 1, 1, 1, 1 }; + double[] sources = { 5, 1, 4, 1, 2, 3, 4, 3, 4, 3, 2, 3 }; + double[][] samples = sources.ToArray(); + var target = new MultivariateEmpiricalDistribution(samples, weights); + + Assert.AreEqual(distribution.Mean[0], target.Mean[0]); + Assert.AreEqual(distribution.Median[0], target.Median[0]); + Assert.AreEqual(distribution.Mode[0], target.Mode[0]); + Assert.AreEqual(distribution.Smoothing[0, 0], target.Smoothing[0, 0]); + Assert.AreEqual(distribution.Variance[0], target.Variance[0]); + Assert.IsTrue(target.Weights.IsEqual(weights.Divide(weights.Sum()))); + Assert.AreEqual(target.Samples, samples); + + for (double x = 0; x < 6; x += 0.1) + { + double actual, expected; + expected = distribution.ComplementaryDistributionFunction(x); + actual = target.ComplementaryDistributionFunction(x); + Assert.AreEqual(expected, actual); + + expected = distribution.DistributionFunction(x); + actual = target.DistributionFunction(x); + Assert.AreEqual(expected, actual); + + expected = distribution.LogProbabilityDensityFunction(x); + actual = target.LogProbabilityDensityFunction(x); + Assert.AreEqual(expected, actual, 1e-15); + + expected = distribution.ProbabilityDensityFunction(x); + actual = target.ProbabilityDensityFunction(x); + Assert.AreEqual(expected, actual, 1e-15); + } + } + + [Test] + public void WeightedEmpiricalDistributionConstructorTest2() + { + double[] original = { 5, 5, 1, 4, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 4, 3, 2, 3 }; + var distribution = new MultivariateEmpiricalDistribution(original.ToArray()); + + double[] weights = { 2, 1, 1, 1, 2, 3, 1, 3, 1, 1, 1, 1 }; + double[] source = { 5, 1, 4, 1, 2, 3, 4, 3, 4, 3, 2, 3 }; + double[][] samples = source.ToArray(); + + weights = weights.Divide(weights.Sum()); + + var target = new MultivariateEmpiricalDistribution(samples, + weights, distribution.Smoothing); + + Assert.AreEqual(distribution.Mean[0], target.Mean[0]); + Assert.AreEqual(distribution.Median[0], target.Median[0]); + Assert.AreEqual(distribution.Mode[0], target.Mode[0]); + Assert.AreEqual(distribution.Smoothing[0, 0], target.Smoothing[0, 0]); + Assert.AreEqual(1.3655172413793104, target.Variance[0]); + Assert.AreEqual(target.Weights, weights); + Assert.AreEqual(target.Samples, samples); + + for (double x = 0; x < 6; x += 0.1) + { + double actual, expected; + expected = distribution.ComplementaryDistributionFunction(x); + actual = target.ComplementaryDistributionFunction(x); + Assert.AreEqual(expected, actual, 1e-15); + + expected = distribution.DistributionFunction(x); + actual = target.DistributionFunction(x); + Assert.AreEqual(expected, actual, 1e-15); + + expected = distribution.LogProbabilityDensityFunction(x); + actual = target.LogProbabilityDensityFunction(x); + Assert.AreEqual(expected, actual, 1e-15); + + expected = distribution.ProbabilityDensityFunction(x); + actual = target.ProbabilityDensityFunction(x); + Assert.AreEqual(expected, actual, 1e-15); + } + } + + [Test] + public void WeightedEmpiricalDistributionConstructorTest3() + { + double[] weights = { 2, 1, 1, 1, 2, 3, 1, 3, 1, 1, 1, 1 }; + double[] samples = { 5, 1, 4, 1, 2, 3, 4, 3, 4, 3, 2, 3 }; + + weights = weights.Divide(weights.Sum()); + + var target = new MultivariateEmpiricalDistribution(samples.ToArray(), weights); + + Assert.AreEqual(1.2377597081667415, target.Smoothing[0, 0]); + } + + [Test] + public void WeightedEmpiricalDistribution_DistributionFunction() + { + double[][] samples = + { + new double[] { 5, 2 }, + new double[] { 1, 5 }, + new double[] { 4, 7 }, + new double[] { 1, 6 }, + new double[] { 2, 2 }, + new double[] { 3, 4 }, + new double[] { 4, 8 }, + new double[] { 3, 2 }, + new double[] { 4, 4 }, + new double[] { 3, 7 }, + new double[] { 2, 4 }, + new double[] { 3, 1 }, + }; + + + var target = new MultivariateEmpiricalDistribution(samples); + + double[] expected = + { + 0.33333333333333331, 0.083333333333333329, 0.83333333333333337, + 0.16666666666666666, 0.083333333333333329, 0.41666666666666669, + 0.91666666666666663, 0.25, 0.5, + 0.66666666666666663, 0.16666666666666666, 0.083333333333333329 + }; + + for (int i = 0; i < samples.Length; i++) + { + double e = expected[i]; + double a = target.DistributionFunction(samples[i]); + Assert.AreEqual(e, a); + } + + } + } +} diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/MultivariateNormalDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/MultivariateNormalDistributionTest.cs index 2e45a2580..4df4a2e25 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/MultivariateNormalDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/MultivariateNormalDistributionTest.cs @@ -27,13 +27,13 @@ namespace Accord.Tests.Statistics using Accord.Statistics.Distributions.Fitting; using Accord.Statistics.Distributions.Multivariate; using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class MultivariateNormalDistributionTest { - [TestMethod()] + [Test] public void ConstructorTest1() { NormalDistribution normal = new NormalDistribution(4.2, 1.2); @@ -73,7 +73,7 @@ public void ConstructorTest1() Assert.AreEqual(1.0 - ecdf, eccdf); } - [TestMethod()] + [Test] public void ConstructorTest4() { // Create a multivariate Gaussian distribution @@ -132,7 +132,7 @@ public void ConstructorTest4() Assert.AreEqual(0.033944035782101534, cdf); } - [TestMethod()] + [Test] public void ProbabilityDensityFunctionTest() { double[] mean = { 1, -1 }; @@ -151,7 +151,7 @@ public void ProbabilityDensityFunctionTest() Assert.AreEqual(expected, actual, 0.00000001); } - [TestMethod()] + [Test] public void LogProbabilityDensityFunctionTest() { double[] mean = { 1, -1 }; @@ -170,7 +170,7 @@ public void LogProbabilityDensityFunctionTest() Assert.AreEqual(expected, actual, 0.00000001); } - [TestMethod()] + [Test] public void ProbabilityDensityFunctionTest2() { double[] mean = new double[64]; @@ -197,7 +197,7 @@ public void ProbabilityDensityFunctionTest2() Assert.AreEqual(expected, actual, 1e-10); } - [TestMethod()] + [Test] public void ProbabilityDensityFunctionTest3() { double[] mean = new double[3]; @@ -220,7 +220,7 @@ public void ProbabilityDensityFunctionTest3() Assert.IsTrue(thrown); } - [TestMethod()] + [Test] public void ProbabilityFunctionTest4() { // https://code.google.com/p/accord/issues/detail?id=98 @@ -274,7 +274,7 @@ public void ProbabilityFunctionTest4() Assert.AreEqual(expected[i], actual[i], 1e-12); } - [TestMethod()] + [Test] public void CumulativeFunctionTest1() { // Comparison against dmvnorm from the mvtnorm R package @@ -305,7 +305,7 @@ public void CumulativeFunctionTest1() Assert.AreEqual(0.27896707550525140507, ccdf, 1e-10); } - [TestMethod()] + [Test] public void CumulativeFunctionTest2() { double[] mean = { 4.2 }; @@ -339,7 +339,7 @@ public void CumulativeFunctionTest2() } } - [TestMethod()] + [Test] public void ConstructorTest() { double[] mean = { 1, -1 }; @@ -359,7 +359,7 @@ public void ConstructorTest() Assert.AreEqual(2, target.Dimension); } - [TestMethod()] + [Test] public void ConstructorTest2() { double[] mean = { 1, -1 }; @@ -373,7 +373,7 @@ public void ConstructorTest2() Assert.IsTrue(thrown); } - [TestMethod()] + [Test] public void ConstructorTest3() { double[] mean = { 0, 0 }; @@ -392,7 +392,7 @@ public void ConstructorTest3() } - [TestMethod()] + [Test] public void FitTest() { double[][] observations = @@ -429,7 +429,7 @@ public void FitTest() } } - [TestMethod()] + [Test] public void FitTest2() { double[][] observations = @@ -455,7 +455,7 @@ public void FitTest2() target.Fit(observations, options); } - [TestMethod()] + [Test] public void FitTest4() { double[][] observations = @@ -533,7 +533,7 @@ private static void checkDegenerate(MultivariateNormalDistribution target) Assert.AreEqual(1.0, ccdf2); } - [TestMethod()] + [Test] public void FitTest5() { double[][] observations = @@ -562,7 +562,7 @@ public void FitTest5() checkDegenerate(target); } - [TestMethod()] + [Test] public void FitTest3() { double[][] observations = @@ -592,7 +592,7 @@ public void FitTest3() Assert.IsFalse(psd); } - [TestMethod()] + [Test] public void GenerateTest() { Accord.Math.Tools.SetupGenerator(0); @@ -615,7 +615,7 @@ public void GenerateTest() Assert.AreEqual(5, cov[1, 1], 2e-2); } - [TestMethod()] + [Test] public void GenerateTest2() { Accord.Math.Tools.SetupGenerator(0); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/VonMisesFisherDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/VonMisesFisherDistributionTest.cs index d4643b396..147189516 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/VonMisesFisherDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/VonMisesFisherDistributionTest.cs @@ -28,14 +28,14 @@ namespace Accord.Tests.Statistics using Accord.Statistics.Distributions.Multivariate; using Accord.Statistics.Distributions.Univariate; using System; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class VonMisesFisherDistributionTest { - [TestMethod()] + [Test] public void ConstructorTest1() { // If p=2 the distribution reduces to the von Mises distribution on the circle. diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/WishartDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/WishartDistributionTest.cs index d47bdaf14..6a60a806c 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/WishartDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Continuous/WishartDistributionTest.cs @@ -21,36 +21,16 @@ // namespace Accord.Tests.Statistics -{ - using Accord.Statistics.Distributions.Multivariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using Accord.Math; - using Accord.Statistics.Distributions.Fitting; - using Accord.Statistics; - using System.Globalization; - - [TestClass()] +{ + using Accord.Math; + using Accord.Statistics.Distributions.Multivariate; + using NUnit.Framework; + + [TestFixture] public class WishartDistributionTest { - - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - - [TestMethod()] + [Test] public void ConstructorTest4() { // Create a Wishart distribution with the parameters: @@ -78,8 +58,8 @@ public void ConstructorTest4() // 175 112 504 7 14 42 // (the above matrix representations have been transcribed to text using) - string scov = cov.ToString(DefaultMatrixFormatProvider.InvariantCulture); - string smean = meanm.ToString(DefaultMatrixFormatProvider.InvariantCulture); + // string scov = cov.ToString(DefaultMatrixFormatProvider.InvariantCulture); + // string smean = meanm.ToString(DefaultMatrixFormatProvider.InvariantCulture); // For compatibility reasons, .Mean stores a flattened mean matrix double[] mean = wishart.Mean; // { 28, 7, 7, 7, 14, 14, 7, 14, 42 } diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Discrete/JointDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Discrete/JointDistributionTest.cs index f7cd4e010..b11780609 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Discrete/JointDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Discrete/JointDistributionTest.cs @@ -23,11 +23,11 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Multivariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Statistics.Distributions.Fitting; - [TestClass()] + [TestFixture] public class JointDistributionTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void JointDistributionConstructorTest() { int[] symbols = { 3, 5 }; @@ -76,7 +76,7 @@ public void JointDistributionConstructorTest() Assert.AreEqual(14, actual); } - [TestMethod()] + [Test] public void JointDistributionConstructorTest2() { int[] symbols = { 3, 5, 2 }; @@ -113,7 +113,7 @@ public void JointDistributionConstructorTest2() Assert.AreEqual(29, actual); } - [TestMethod()] + [Test] public void FitTest() { int[] symbols = { 3, 5 }; @@ -143,7 +143,7 @@ public void FitTest() Assert.AreEqual(0.25, actual); } - [TestMethod()] + [Test] public void FitTest2() { int[] symbols = { 3, 5 }; diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Discrete/MultinomialDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Discrete/MultinomialDistributionTest.cs index 0420726e7..e08223df0 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Discrete/MultinomialDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Discrete/MultinomialDistributionTest.cs @@ -23,12 +23,12 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; using Accord.Statistics.Distributions.Multivariate; using System.Globalization; - [TestClass()] + [TestFixture] public class MultinomialDistributionTest { @@ -49,7 +49,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest() { @@ -87,7 +87,7 @@ public void ConstructorTest() Assert.AreEqual("Multinomial(x; n = 5, p = { 0.25, 0.75 })", str); } - [TestMethod()] + [Test] public void ProbabilityMassFunctionTest() { MultinomialDistribution dist = new MultinomialDistribution(5, 0.25, 0.25, 0.25, 0.25); @@ -100,7 +100,7 @@ public void ProbabilityMassFunctionTest() Assert.AreEqual(expected, actual, 1e-6); } - [TestMethod()] + [Test] public void ProbabilityMassFunctionTest2() { // Example from http://onlinestatbook.com/2/probability/multinomial.html @@ -115,7 +115,7 @@ public void ProbabilityMassFunctionTest2() Assert.AreEqual(expected, actual, 1e-6); } - [TestMethod()] + [Test] public void LogProbabilityMassFunctionTest() { MultinomialDistribution dist = new MultinomialDistribution(5, 0.25, 0.25, 0.25, 0.25); @@ -128,7 +128,7 @@ public void LogProbabilityMassFunctionTest() Assert.AreEqual(expected, actual, 1e-6); } - [TestMethod()] + [Test] public void FitTest() { MultinomialDistribution dist = new MultinomialDistribution(7, new double[2]); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Discrete/MultivariateDiscreteDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Discrete/MultivariateDiscreteDistributionTest.cs index b7010fdf2..c904127de 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Discrete/MultivariateDiscreteDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/Discrete/MultivariateDiscreteDistributionTest.cs @@ -23,9 +23,9 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Multivariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class MultivariateDiscreteDistributionTest { @@ -46,7 +46,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ProbabilityMassFunctionTest() { MultivariateDiscreteDistribution target = new MultinomialDistribution(5, 0.25, 0.25, 0.25, 0.25); @@ -59,7 +59,7 @@ public void ProbabilityMassFunctionTest() Assert.AreEqual(expected, actual, 1e-6); } - [TestMethod()] + [Test] public void LogProbabilityMassFunctionTest() { MultivariateDiscreteDistribution target = new MultinomialDistribution(5, 0.25, 0.25, 0.25, 0.25); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/IndependentTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/IndependentTest.cs index bf75ead59..775eed9a0 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/IndependentTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/IndependentTest.cs @@ -1,276 +1,263 @@ -// Accord Unit Tests -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Tests.Statistics -{ - using Microsoft.VisualStudio.TestTools.UnitTesting; - using Accord.Statistics; - using Accord.Statistics.Distributions.Multivariate; - using Accord.Statistics.Distributions.Univariate; - using Accord.Statistics.Distributions.Fitting; - using System; - - [TestClass()] - public class IndependentTest - { - - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - - [TestMethod()] - public void ConstructorTest() - { - var p1 = new NormalDistribution(4.2, 1); - var p2 = new NormalDistribution(7.0, 2); - - Independent target = new Independent(p1, p2); - - Assert.AreEqual(target.Components[0], p1); - Assert.AreEqual(target.Components[1], p2); - - Assert.AreEqual(2, target.Dimension); - - Assert.AreEqual(4.2, target.Mean[0]); - Assert.AreEqual(7.0, target.Mean[1]); - - Assert.AreEqual(1, target.Variance[0]); - Assert.AreEqual(4, target.Variance[1]); - - Assert.AreEqual(1, target.Covariance[0, 0]); - Assert.AreEqual(4, target.Covariance[1, 1]); - Assert.AreEqual(0, target.Covariance[0, 1]); - Assert.AreEqual(0, target.Covariance[1, 0]); - } - - [TestMethod()] - public void ProbabilityFunctionTest() - { - var p1 = new NormalDistribution(4.2, 1); - var p2 = new NormalDistribution(7.0, 2); - - Independent target = new Independent(p1, p2); - - double[] x; - double actual, expected; - - x = new double[] { 4.2, 7.0 }; - actual = target.ProbabilityDensityFunction(x); - expected = p1.ProbabilityDensityFunction(x[0]) * p2.ProbabilityDensityFunction(x[1]); - Assert.AreEqual(expected, actual, 1e-10); - Assert.IsFalse(double.IsNaN(actual)); - - x = new double[] { 0.0, 0.0 }; - actual = target.ProbabilityDensityFunction(x); - expected = p1.ProbabilityDensityFunction(x[0]) * p2.ProbabilityDensityFunction(x[1]); - Assert.AreEqual(expected, actual, 1e-10); - Assert.IsFalse(double.IsNaN(actual)); - - x = new double[] { 7.0, 4.2 }; - actual = target.ProbabilityDensityFunction(x); - expected = p1.ProbabilityDensityFunction(x[0]) * p2.ProbabilityDensityFunction(x[1]); - Assert.AreEqual(expected, actual, 1e-10); - Assert.IsFalse(double.IsNaN(actual)); - } - - [TestMethod()] - public void CumulativeFunctionTest() - { - var p1 = new NormalDistribution(4.2, 1); - var p2 = new NormalDistribution(7.0, 2); - - Independent target = new Independent(p1, p2); - - double[] x; - double actual, expected; - - x = new double[] { 4.2, 7.0 }; - actual = target.DistributionFunction(x); - expected = p1.DistributionFunction(x[0]) * p2.DistributionFunction(x[1]); - Assert.AreEqual(expected, actual); - - x = new double[] { 0.0, 0.0 }; - actual = target.DistributionFunction(x); - expected = p1.DistributionFunction(x[0]) * p2.DistributionFunction(x[1]); - Assert.AreEqual(expected, actual); - - x = new double[] { 7.0, 4.2 }; - actual = target.DistributionFunction(x); - expected = p1.DistributionFunction(x[0]) * p2.DistributionFunction(x[1]); - Assert.AreEqual(expected, actual); - } - - [TestMethod()] - public void FitTest() - { +// Accord Unit Tests +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Tests.Statistics +{ + using Accord.Statistics.Distributions.Fitting; + using Accord.Statistics.Distributions.Multivariate; + using Accord.Statistics.Distributions.Univariate; + using NUnit.Framework; + using System; + + [TestFixture] + public class IndependentTest + { + + [Test] + public void ConstructorTest() + { + var p1 = new NormalDistribution(4.2, 1); + var p2 = new NormalDistribution(7.0, 2); + + Independent target = new Independent(p1, p2); + + Assert.AreEqual(target.Components[0], p1); + Assert.AreEqual(target.Components[1], p2); + + Assert.AreEqual(2, target.Dimension); + + Assert.AreEqual(4.2, target.Mean[0]); + Assert.AreEqual(7.0, target.Mean[1]); + + Assert.AreEqual(1, target.Variance[0]); + Assert.AreEqual(4, target.Variance[1]); + + Assert.AreEqual(1, target.Covariance[0, 0]); + Assert.AreEqual(4, target.Covariance[1, 1]); + Assert.AreEqual(0, target.Covariance[0, 1]); + Assert.AreEqual(0, target.Covariance[1, 0]); + + var text = target.ToString("N2", System.Globalization.CultureInfo.InvariantCulture); + + Assert.AreEqual("Independent(x0, x1; N(x0; μ = 4.20, σ² = 1.00) + N(x1; μ = 7.00, σ² = 4.00))", text); + } + + [Test] + public void ProbabilityFunctionTest() + { + var p1 = new NormalDistribution(4.2, 1); + var p2 = new NormalDistribution(7.0, 2); + + Independent target = new Independent(p1, p2); + + double[] x; + double actual, expected; + + x = new double[] { 4.2, 7.0 }; + actual = target.ProbabilityDensityFunction(x); + expected = p1.ProbabilityDensityFunction(x[0]) * p2.ProbabilityDensityFunction(x[1]); + Assert.AreEqual(expected, actual, 1e-10); + Assert.IsFalse(double.IsNaN(actual)); + + x = new double[] { 0.0, 0.0 }; + actual = target.ProbabilityDensityFunction(x); + expected = p1.ProbabilityDensityFunction(x[0]) * p2.ProbabilityDensityFunction(x[1]); + Assert.AreEqual(expected, actual, 1e-10); + Assert.IsFalse(double.IsNaN(actual)); + + x = new double[] { 7.0, 4.2 }; + actual = target.ProbabilityDensityFunction(x); + expected = p1.ProbabilityDensityFunction(x[0]) * p2.ProbabilityDensityFunction(x[1]); + Assert.AreEqual(expected, actual, 1e-10); + Assert.IsFalse(double.IsNaN(actual)); + } + + [Test] + public void CumulativeFunctionTest() + { + var p1 = new NormalDistribution(4.2, 1); + var p2 = new NormalDistribution(7.0, 2); + + Independent target = new Independent(p1, p2); + + double[] x; + double actual, expected; + + x = new double[] { 4.2, 7.0 }; + actual = target.DistributionFunction(x); + expected = p1.DistributionFunction(x[0]) * p2.DistributionFunction(x[1]); + Assert.AreEqual(expected, actual); + + x = new double[] { 0.0, 0.0 }; + actual = target.DistributionFunction(x); + expected = p1.DistributionFunction(x[0]) * p2.DistributionFunction(x[1]); + Assert.AreEqual(expected, actual); + + x = new double[] { 7.0, 4.2 }; + actual = target.DistributionFunction(x); + expected = p1.DistributionFunction(x[0]) * p2.DistributionFunction(x[1]); + Assert.AreEqual(expected, actual); + } + + [Test] + public void FitTest() + { double[][] data = { new double[] { 1, 8 }, new double[] { 2, 6 }, new double[] { 5, 7 }, new double[] { 3, 9 }, - }; - - - var p1 = new NormalDistribution(0, 1); - var p2 = new NormalDistribution(0, 1); - - Independent target = new Independent(p1, p2); - - target.Fit(data); - - Assert.AreEqual(2.75, target.Mean[0]); - Assert.AreEqual(7.50, target.Mean[1]); - - Assert.AreEqual(2.91666, target.Variance[0], 1e-5); - Assert.AreEqual(1.66666, target.Variance[1], 1e-5); - - Assert.AreEqual(target.Variance[0], target.Covariance[0, 0]); - Assert.AreEqual(target.Variance[1], target.Covariance[1, 1]); - Assert.AreEqual(0, target.Covariance[0, 1]); - Assert.AreEqual(0, target.Covariance[1, 0]); - } - - [TestMethod()] - public void FittingNoOptionsTest() - { + }; + + + var p1 = new NormalDistribution(0, 1); + var p2 = new NormalDistribution(0, 1); + + Independent target = new Independent(p1, p2); + + target.Fit(data); + + Assert.AreEqual(2.75, target.Mean[0]); + Assert.AreEqual(7.50, target.Mean[1]); + + Assert.AreEqual(2.91666, target.Variance[0], 1e-5); + Assert.AreEqual(1.66666, target.Variance[1], 1e-5); + + Assert.AreEqual(target.Variance[0], target.Covariance[0, 0]); + Assert.AreEqual(target.Variance[1], target.Covariance[1, 1]); + Assert.AreEqual(0, target.Covariance[0, 1]); + Assert.AreEqual(0, target.Covariance[1, 0]); + } + + [Test] + public void FittingNoOptionsTest() + { double[][] data1 = { new double[] { 0, 8 }, new double[] { 0, 6 }, new double[] { 0, 7 }, new double[] { 0, 9 }, - }; - + }; + double[][] data2 = { new double[] { 8, 0 }, new double[] { 6, 0 }, new double[] { 7, 0 }, new double[] { 9, 0 }, - }; - - - var p1 = new NormalDistribution(0, 1); - var p2 = new NormalDistribution(0, 1); - - bool thrown1 = false; - bool thrown2 = false; - - try - { - var target = new Independent(p1, p2); - target.Fit(data1); - } - catch (ArgumentException) - { - thrown1 = true; - } - - try - { - var target = new Independent(p1, p2); - target.Fit(data2); - } - catch (ArgumentException) - { - thrown2 = true; - } - - Assert.IsTrue(thrown1); - Assert.IsTrue(thrown2); - } - - [TestMethod()] - public void FittingOptionsTest() - { + }; + + + var p1 = new NormalDistribution(0, 1); + var p2 = new NormalDistribution(0, 1); + + bool thrown1 = false; + bool thrown2 = false; + + try + { + var target = new Independent(p1, p2); + target.Fit(data1); + } + catch (ArgumentException) + { + thrown1 = true; + } + + try + { + var target = new Independent(p1, p2); + target.Fit(data2); + } + catch (ArgumentException) + { + thrown2 = true; + } + + Assert.IsTrue(thrown1); + Assert.IsTrue(thrown2); + } + + [Test] + public void FittingOptionsTest() + { double[][] data1 = { new double[] { 0, 8 }, new double[] { 0, 6 }, new double[] { 0, 7 }, new double[] { 0, 9 }, - }; - + }; + double[][] data2 = { new double[] { 8, 0 }, new double[] { 6, 0 }, new double[] { 7, 0 }, new double[] { 9, 0 }, - }; - - - var p1 = new NormalDistribution(0, 1); - var p2 = new NormalDistribution(0, 1); - - { - Independent target = new Independent(p1, p2); - - target.Fit(data1, new IndependentOptions() - { - InnerOption = new NormalOptions() - { - Regularization = 1e-5 - } - }); - - Assert.AreEqual(0.00, target.Mean[0]); - Assert.AreEqual(7.50, target.Mean[1]); - - Assert.AreEqual(1e-5, target.Variance[0]); - Assert.AreEqual(1.66666, target.Variance[1], 1e-5); - } - - { - Independent target = new Independent(p1, p2); - - target.Fit(data2, new IndependentOptions() - { - InnerOption = new NormalOptions() - { - Regularization = 1e-5 - } - }); - - Assert.AreEqual(7.5, target.Mean[0]); - Assert.AreEqual(0, target.Mean[1]); - - Assert.AreEqual(1.66666, target.Variance[0], 1e-5); - Assert.AreEqual(1e-5, target.Variance[1]); - } - } - - } + }; + + + var p1 = new NormalDistribution(0, 1); + var p2 = new NormalDistribution(0, 1); + + { + Independent target = new Independent(p1, p2); + + target.Fit(data1, new IndependentOptions() + { + InnerOption = new NormalOptions() + { + Regularization = 1e-5 + } + }); + + Assert.AreEqual(0.00, target.Mean[0]); + Assert.AreEqual(7.50, target.Mean[1]); + + Assert.AreEqual(1e-5, target.Variance[0]); + Assert.AreEqual(1.66666, target.Variance[1], 1e-5); + } + + { + Independent target = new Independent(p1, p2); + + target.Fit(data2, new IndependentOptions() + { + InnerOption = new NormalOptions() + { + Regularization = 1e-5 + } + }); + + Assert.AreEqual(7.5, target.Mean[0]); + Assert.AreEqual(0, target.Mean[1]); + + Assert.AreEqual(1.66666, target.Variance[0], 1e-5); + Assert.AreEqual(1e-5, target.Variance[1]); + } + } + + } } \ No newline at end of file diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/MultivariateMixtureDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/MultivariateMixtureDistributionTest.cs index 6d9d8527a..721778f35 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/MultivariateMixtureDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Multivariate/MultivariateMixtureDistributionTest.cs @@ -21,20 +21,20 @@ // namespace Accord.Tests.Statistics -{ - using Accord.Statistics.Distributions.Multivariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using Accord.Math; - using Accord.IO; - using Accord.Tests.Statistics.Properties; +{ + using Accord.IO; + using Accord.Math; + using Accord.Statistics.Distributions.Multivariate; + using Accord.Tests.Statistics.Properties; + using NUnit.Framework; + using System.Data; using System.IO; - using System.Data; - [TestClass()] + [TestFixture] public class MultivariateMixtureDistributionTest { - [TestMethod()] + [Test] public void ConstructorTest1() { MultivariateNormalDistribution[] components = new MultivariateNormalDistribution[2]; @@ -49,7 +49,7 @@ public void ConstructorTest1() Assert.AreEqual(components, mixture.Components); } - [TestMethod()] + [Test] public void ProbabilityDensityFunctionTest() { MultivariateNormalDistribution[] components = new MultivariateNormalDistribution[2]; @@ -70,7 +70,7 @@ public void ProbabilityDensityFunctionTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void ProbabilityDensityFunctionTestPerComponent() { MultivariateNormalDistribution[] components = new MultivariateNormalDistribution[2]; @@ -91,7 +91,7 @@ public void ProbabilityDensityFunctionTestPerComponent() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void DistributionFunctionTestPerComponent() { MultivariateNormalDistribution[] components = new MultivariateNormalDistribution[2]; @@ -112,7 +112,7 @@ public void DistributionFunctionTestPerComponent() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void LogProbabilityDensityFunctionTest() { MultivariateNormalDistribution[] components = new MultivariateNormalDistribution[2]; @@ -134,7 +134,7 @@ public void LogProbabilityDensityFunctionTest() Assert.IsFalse(double.IsNaN(actual)); } - [TestMethod()] + [Test] public void LogProbabilityDensityFunctionTestPerComponent() { MultivariateNormalDistribution[] components = new MultivariateNormalDistribution[2]; @@ -156,7 +156,7 @@ public void LogProbabilityDensityFunctionTestPerComponent() Assert.IsFalse(double.IsNaN(actual)); } - [TestMethod()] + [Test] public void FitTest() { double[] coefficients = { 0.50, 0.50 }; @@ -207,7 +207,7 @@ public void FitTest() // Assert.AreEqual(expectedVar[0, 0], actualVar[0, 0], 0.0000001); } - [TestMethod()] + [Test] public void FitTest2() { double[] coefficients = { 0.50, 0.50 }; @@ -259,7 +259,7 @@ public void FitTest2() Assert.AreEqual(expectedVar[0, 0], actualVar[0, 0], 0.68); } - [TestMethod] + [Test] public void MixtureWeightsFitTest() { // Randomly initialize some mixture components @@ -287,16 +287,16 @@ public void MixtureWeightsFitTest() // Our model will be: double mean1 = mixture.Components[0].Mean[0]; // 1.41126 - double mean2 = mixture.Components[1].Mean[0]; // 6.53301 - - // With mixture coefficients - double pi1 = mixture.Coefficients[0]; // 0.51408489193241225 - double pi2 = mixture.Coefficients[1]; // 0.48591510806758775 - - Assert.AreEqual(1.4112610766836409, mean1); - Assert.AreEqual(6.5330177004151064, mean2); - - Assert.AreEqual(0.51408489193241214, pi1); + double mean2 = mixture.Components[1].Mean[0]; // 6.53301 + + // With mixture coefficients + double pi1 = mixture.Coefficients[0]; // 0.51408489193241225 + double pi2 = mixture.Coefficients[1]; // 0.48591510806758775 + + Assert.AreEqual(1.4112610766836409, mean1); + Assert.AreEqual(6.5330177004151064, mean2); + + Assert.AreEqual(0.51408489193241214, pi1); Assert.AreEqual(0.48591510806758781, pi2); /* @@ -315,7 +315,7 @@ public void MixtureWeightsFitTest() */ } - [TestMethod] + [Test] public void MixtureWeightsFitTest2() { MemoryStream stream = new MemoryStream(Resources.CircleWithWeights); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/AndersonDarlingDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/AndersonDarlingDistributionTest.cs index 8d00a20ac..e2bc5253b 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/AndersonDarlingDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/AndersonDarlingDistributionTest.cs @@ -23,11 +23,11 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using System.Globalization; - [TestClass()] + [TestFixture] public class AndersonDarlingDistributionTest { @@ -47,7 +47,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void ConstructorTest() { // Create a new Anderson Darling distribution (A²) for comparing against a Gaussian diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/BetaDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/BetaDistributionTest.cs index c1b929fc8..02bc8ba61 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/BetaDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/BetaDistributionTest.cs @@ -24,12 +24,12 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Fitting; using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Math; using Accord.Math.Differentiation; - [TestClass()] + [TestFixture] public class BetaDistributionTest { @@ -50,7 +50,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void BetaDistributionConstructorTest() { double expected, actual; @@ -84,7 +84,7 @@ public void BetaDistributionConstructorTest() } } - [TestMethod()] + [Test] public void MedianTest() { double alpha = 0.42; @@ -95,7 +95,7 @@ public void MedianTest() Assert.AreEqual(target.Median, target.InverseDistributionFunction(0.5)); } - [TestMethod()] + [Test] public void BetaMeanTest() { double alpha = 0.42; @@ -145,7 +145,7 @@ public void BetaMeanTest() Assert.AreEqual(0.89625688707910811, range3.Max); } - [TestMethod()] + [Test] public void BetaMeanTest2() { int trials = 161750; @@ -171,7 +171,7 @@ public void BetaMeanTest2() Assert.AreEqual("B(x; α = 10008, β = 151744)", str); } - [TestMethod()] + [Test] public void BetaMeanTest3() { int trials = 100; @@ -195,7 +195,7 @@ public void BetaMeanTest3() Assert.AreEqual(0.84983461640764513, p975, 1e-6); } - [TestMethod()] + [Test] public void BetaFitTest1() { double[] x = { 0.1, 0.5, 0.3, 0.8, 0.6, 0.7, 0.9, 0.9, 0.9, 0.9 }; @@ -208,7 +208,7 @@ public void BetaFitTest1() Assert.AreEqual(0.60843093922651903, target.Beta); } - [TestMethod()] + [Test] public void BetaFit_RealWeights() { double[] x = { 1.0, 0.1, 0.5, 0.3, 0.5, 0.8, 0.6, 0.7, 0.9, 0.9, 0.9 }; @@ -222,7 +222,7 @@ public void BetaFit_RealWeights() Assert.AreEqual(0.58735469613259694, target.Beta); } - [TestMethod()] + [Test] public void BetaFit_IntWeights() { double[] x = { 1.0, 0.1, 0.5, 0.3, 0.5, 0.8, 0.6, 0.7, 0.9, 0.9, 0.9 }; @@ -236,7 +236,7 @@ public void BetaFit_IntWeights() Assert.AreEqual(0.60843093922651903, target.Beta, 1e-8); } - [TestMethod()] + [Test] public void BetaMLEFitTest1() { double[] x = samples; @@ -260,7 +260,7 @@ public void BetaMLEFitTest1() } } - [TestMethod()] + [Test] public void BetaMLEFit_RealWeights() { double[] x = { 1.0, 0.1, 0.5, 0.3, 0.5, 0.8, 0.6, 0.7, 0.9, 0.9, 0.9 }; @@ -280,7 +280,7 @@ public void BetaMLEFit_RealWeights() Assert.AreEqual(0.58735469613259694, target.Beta); } - [TestMethod()] + [Test] public void BetaMLEFit_IntWeights() { double[] x = { 1.0, 0.1, 0.5, 0.3, 0.5, 0.8, 0.6, 0.7, 0.9, 0.9, 0.9 }; @@ -300,7 +300,7 @@ public void BetaMLEFit_IntWeights() Assert.AreEqual(0.60843093922651903, target.Beta, 1e-10); } - [TestMethod()] + [Test] public void LogLikelihoodTest() { var target = new BetaDistribution(3.0, 2.0); @@ -315,7 +315,7 @@ public void LogLikelihoodTest() Assert.AreEqual(expected, actual, 1e-10); } - [TestMethod()] + [Test] public void GradientTest() { for (double a = 0.1; a < 3; a += 0.1) @@ -339,7 +339,7 @@ public void GradientTest() } } - [TestMethod()] + [Test] public void BetaGenerateTest() { Accord.Math.Tools.SetupGenerator(0); @@ -357,7 +357,7 @@ public void BetaGenerateTest() Assert.AreEqual(3, actual.Beta, 1e-2); } - [TestMethod()] + [Test] public void BetaGenerateTest2() { Accord.Math.Tools.SetupGenerator(0); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/BetaPrimeDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/BetaPrimeDistributionTest.cs index f3c9328aa..b96d61682 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/BetaPrimeDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/BetaPrimeDistributionTest.cs @@ -23,29 +23,13 @@ namespace Accord.Tests.Statistics.Distributions.Univariate.Continuous { using Accord.Statistics.Distributions.Univariate; - using Accord.Statistics.Distributions.Univariate.Continuous; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System.Globalization; - [TestClass] + [TestFixture] public class BetaPrimeDistributionTest { - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - [TestMethod] + [Test] public void Confirm_BetPrimeDistribution_Relative_to_F_Distribution() { double alpha = 4.0d; @@ -69,7 +53,7 @@ public void Confirm_BetPrimeDistribution_Relative_to_F_Distribution() } - [TestMethod()] + [Test] public void Constructor_ExtensiveTestForDocumentation() { // Create a new Beta-Prime distribution with shape (4,2) diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/BirnbaumSaundersDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/BirnbaumSaundersDistributionTest.cs index 5e45de17f..cd7b62adb 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/BirnbaumSaundersDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/BirnbaumSaundersDistributionTest.cs @@ -24,12 +24,12 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; using Accord.Statistics; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Statistics.Distributions.Multivariate; using System.Globalization; - [TestClass()] + [TestFixture] public class BirnbaumSaundersDistributionTest { @@ -50,7 +50,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest1() { var bs = new BirnbaumSaundersDistribution(shape: 0.42); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/CauchyDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/CauchyDistributionTest.cs index 460e3b77e..c6e482d48 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/CauchyDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/CauchyDistributionTest.cs @@ -23,33 +23,15 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Statistics.Distributions.Fitting; - [TestClass()] + [TestFixture] public class CauchyDistributionTest { - - private TestContext testContextInstance; - - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - - [TestMethod()] + [Test] public void CauchyDistributionConstructorTest() { double location = 2; @@ -66,7 +48,7 @@ public void CauchyDistributionConstructorTest() Assert.AreEqual(Math.Log(scale) + Math.Log(4.0 * Math.PI), target.Entropy); } - [TestMethod()] + [Test] public void MedianTest() { double location = 2; @@ -76,7 +58,7 @@ public void MedianTest() Assert.AreEqual(target.Median, target.InverseDistributionFunction(0.5), 1e-10); } - [TestMethod()] + [Test] public void CauchyDistributionConstructorTest1() { CauchyDistribution target = new CauchyDistribution(); @@ -86,7 +68,7 @@ public void CauchyDistributionConstructorTest1() } - [TestMethod()] + [Test] public void DistributionFunctionTest() { double[] expected = @@ -105,7 +87,7 @@ public void DistributionFunctionTest() } } - [TestMethod()] + [Test] public void FitTest() { CauchyDistribution target = new CauchyDistribution(); @@ -118,7 +100,7 @@ public void FitTest() Assert.AreEqual(0.21, target.Scale, 0.05); } - [TestMethod()] + [Test] public void FitTest2() { double[] observations = { 0.25, 0.12, 0.72, 0.21, 0.62, 0.12, 0.62, 0.12 }; @@ -152,7 +134,7 @@ public void FitTest2() } } - [TestMethod()] + [Test] public void LogProbabilityDensityFunctionTest() { double[] expected = @@ -171,7 +153,7 @@ public void LogProbabilityDensityFunctionTest() } } - [TestMethod()] + [Test] public void ProbabilityDensityFunctionTest() { double[] expected = @@ -190,7 +172,7 @@ public void ProbabilityDensityFunctionTest() } } - [TestMethod()] + [Test] public void CauchyDistributionConstructorTest2() { double location = 0.42; diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/ChiSquareDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/ChiSquareDistributionTest.cs index 2e8faefc3..fdf528d91 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/ChiSquareDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/ChiSquareDistributionTest.cs @@ -23,11 +23,11 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; using Accord.Statistics.Testing; - [TestClass()] + [TestFixture] public class ChiSquareDistributionTest { @@ -47,7 +47,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void ConstructorTest() { var chisq = new ChiSquareDistribution(degreesOfFreedom: 7); @@ -94,7 +94,7 @@ public void ConstructorTest() Assert.AreEqual(18.475306906582361, range3.Max); } - [TestMethod()] + [Test] public void MedianTest() { var target = new ChiSquareDistribution(degreesOfFreedom: 4); @@ -102,7 +102,7 @@ public void MedianTest() Assert.AreEqual(target.Median, target.InverseDistributionFunction(0.5)); } - [TestMethod()] + [Test] public void InverseCumulativeFunctionTest() { double a; @@ -119,7 +119,7 @@ public void InverseCumulativeFunctionTest() } - [TestMethod()] + [Test] public void ProbabilityDensityFunctionTest() { int degreesOfFreedom; @@ -148,7 +148,7 @@ public void ProbabilityDensityFunctionTest() Assert.AreEqual(expected, actual, 1e-4); } - [TestMethod()] + [Test] public void LogProbabilityDensityFunctionTest() { int degreesOfFreedom; @@ -177,7 +177,7 @@ public void LogProbabilityDensityFunctionTest() Assert.AreEqual(expected, actual, 1e-10); } - [TestMethod()] + [Test] public void DistributionFunctionTest() { int degreesOfFreedom; @@ -200,7 +200,7 @@ public void DistributionFunctionTest() Assert.AreEqual(expected, actual, 1e-4); } - [TestMethod()] + [Test] public void InverseTest() { double expected = 1.8307038053275149991e+01; @@ -208,7 +208,7 @@ public void InverseTest() Assert.AreEqual(expected, actual, 1e-14); } - [TestMethod()] + [Test] public void InverseTest2() { double[] p = diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/ContinuousUniformDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/ContinuousUniformDistributionTest.cs index 7922f790c..f16680c30 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/ContinuousUniformDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/ContinuousUniformDistributionTest.cs @@ -23,12 +23,12 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Statistics.Distributions.Fitting; using System.Globalization; - [TestClass()] + [TestFixture] public class UniformDistributionTest { @@ -49,7 +49,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest() { var uniform = new UniformContinuousDistribution(a: 0.42, b: 1.1); @@ -96,7 +96,7 @@ public void ConstructorTest() Assert.AreEqual(1.0932000000000002, range3.Max); } - [TestMethod()] + [Test] public void IntervalTest() { var target = new UniformContinuousDistribution(-10, 10); @@ -114,7 +114,7 @@ public void IntervalTest() } } - [TestMethod()] + [Test] public void UniformDistributionConstructorTest() { double a = 1; @@ -124,7 +124,7 @@ public void UniformDistributionConstructorTest() Assert.AreEqual(target.Maximum, b); } - [TestMethod()] + [Test] public void UniformDistributionConstructorTest1() { double a = 6; @@ -137,7 +137,7 @@ public void UniformDistributionConstructorTest1() Assert.IsTrue(thrown); } - [TestMethod()] + [Test] public void VarianceTest() { double a = 5; @@ -148,7 +148,7 @@ public void VarianceTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void MeanTest() { double a = -1; @@ -159,7 +159,7 @@ public void MeanTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void EntropyTest() { double a = 1; @@ -170,7 +170,7 @@ public void EntropyTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void MedianTest() { double a = 1; @@ -180,7 +180,7 @@ public void MedianTest() Assert.AreEqual(target.Median, target.InverseDistributionFunction(0.5)); } - [TestMethod()] + [Test] public void ProbabilityDensityFunctionTest() { double a = -5; @@ -212,7 +212,7 @@ public void ProbabilityDensityFunctionTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void LogProbabilityDensityFunctionTest() { double a = -5; @@ -244,7 +244,7 @@ public void LogProbabilityDensityFunctionTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void FitTest() { UniformContinuousDistribution target = new UniformContinuousDistribution(); @@ -255,7 +255,7 @@ public void FitTest() Assert.AreEqual(5.0, target.Maximum); } - [TestMethod()] + [Test] public void DistributionFunctionTest() { double a = -2; @@ -280,7 +280,7 @@ public void DistributionFunctionTest() Assert.AreEqual(1, actual); } - [TestMethod()] + [Test] public void CloneTest() { double a = 12; @@ -298,7 +298,7 @@ public void CloneTest() } - [TestMethod()] + [Test] public void GenerateTest() { UniformContinuousDistribution target = new UniformContinuousDistribution(0, 2); @@ -318,7 +318,7 @@ public void GenerateTest() Assert.AreEqual(2, newTarget.Maximum, 1e-5); } - [TestMethod()] + [Test] public void GenerateTest2() { UniformContinuousDistribution target = new UniformContinuousDistribution(0, 2); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/EmpiricalDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/EmpiricalDistributionTest.cs index e4854abf1..777da68b3 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/EmpiricalDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/EmpiricalDistributionTest.cs @@ -1,457 +1,439 @@ -// Accord Unit Tests -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Tests.Statistics -{ - using System; - using Accord.Statistics.Distributions.Fitting; - using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using Accord.Math; - using Accord.Statistics; - - [TestClass()] - public class EmpiricalDistributionTest - { - - - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - - [TestMethod()] - public void EmpiricalDistributionConstructorTest1() - { - double[] samples = { 5, 5, 1, 4, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 4, 3, 2, 3 }; - double smoothing = 0.5; - - EmpiricalDistribution target = new EmpiricalDistribution(samples, smoothing); - Assert.AreEqual(samples, target.Samples); - Assert.AreEqual(smoothing, target.Smoothing); - - Assert.AreEqual(3, target.Mean); - Assert.AreEqual(1.1375929179890421, target.StandardDeviation); - Assert.AreEqual(target.Variance, target.Variance); - } - - [TestMethod()] - public void EmpiricalDistributionConstructorTest2() - { - double[] samples = { 5, 5, 1, 4, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 4, 3, 2, 3 }; - EmpiricalDistribution target = new EmpiricalDistribution(samples); - Assert.AreEqual(samples, target.Samples); - Assert.AreEqual(0.67595864392399474, target.Smoothing); - } - - [TestMethod()] - public void EmpiricalDistributionConstructorTest3() - { - double[] samples = { 5, 5, 1, 4, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 4, 3, 2, 3 }; - EmpiricalDistribution distribution = new EmpiricalDistribution(samples); - - double mean = distribution.Mean; // 3 - double median = distribution.Median; // 2.9999993064186787 - double var = distribution.Variance; // 1.2941176470588236 - double mode = distribution.Mode; // 3 - - double chf = distribution.CumulativeHazardFunction(x: 4.2); // 2.1972245773362191 - double cdf = distribution.DistributionFunction(x: 4.2); // 0.88888888888888884 - double pdf = distribution.ProbabilityDensityFunction(x: 4.2); // 0.181456280142802 - double lpdf = distribution.LogProbabilityDensityFunction(x: 4.2); // -1.7067405350495708 - double hf = distribution.HazardFunction(x: 4.2); // 1.6331065212852196 - double ccdf = distribution.ComplementaryDistributionFunction(x: 4.2); //0.11111111111111116 - double icdf = distribution.InverseDistributionFunction(p: cdf); // 4.1999999999999993 - double smoothing = distribution.Smoothing; // 0.67595864392399474 - - string str = distribution.ToString(); // Fn(x; S) - - Assert.AreEqual(samples, distribution.Samples); - Assert.AreEqual(0.67595864392399474, smoothing); - Assert.AreEqual(3.0, mode); - Assert.AreEqual(3.0, mean); - Assert.AreEqual(2.9999993064186787, median); - Assert.AreEqual(1.2941176470588236, var); - Assert.AreEqual(2.1972245773362191, chf); - Assert.AreEqual(0.88888888888888884, cdf); - Assert.AreEqual(0.18145628014280227, pdf, 1e-15); - Assert.AreEqual(-1.7067405350495708, lpdf); - Assert.AreEqual(1.6331065212852196, hf, 1e-15); - Assert.AreEqual(0.11111111111111116, ccdf); - Assert.AreEqual(4.1999999999999993, icdf); - Assert.AreEqual("Fn(x; S)", str); - - var range1 = distribution.GetRange(0.95); - var range2 = distribution.GetRange(0.99); - var range3 = distribution.GetRange(0.01); - - Assert.AreEqual(0.99999947547912593, range1.Min); - Assert.AreEqual(5.0000002464240794, range1.Max); - Assert.AreEqual(0.99999913215637204, range2.Min); - Assert.AreEqual(5.0000004605903117, range2.Max); - Assert.AreEqual(0.99999913215637204, range3.Min); - Assert.AreEqual(5.0000004605903117, range3.Max); - } - - [TestMethod()] - public void WeightedEmpiricalDistributionConstructorTest() - { - double[] original = { 5, 5, 1, 4, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 4, 3, 2, 3 }; - var distribution = new EmpiricalDistribution(original); - - int[] weights = { 2, 1, 1, 1, 2, 3, 1, 3, 1, 1, 1, 1 }; - double[] samples = { 5, 1, 4, 1, 2, 3, 4, 3, 4, 3, 2, 3 }; - var target = new EmpiricalDistribution(samples, weights); - - Assert.AreEqual(distribution.Entropy, target.Entropy, 1e-10); - Assert.AreEqual(distribution.Mean, target.Mean); - Assert.AreEqual(distribution.Median, target.Median); - Assert.AreEqual(distribution.Mode, target.Mode); - Assert.AreEqual(distribution.Quartiles.Min, target.Quartiles.Min); - Assert.AreEqual(distribution.Quartiles.Max, target.Quartiles.Max); - Assert.AreEqual(distribution.Smoothing, target.Smoothing); - Assert.AreEqual(distribution.StandardDeviation, target.StandardDeviation); - Assert.AreEqual(distribution.Support.Min, target.Support.Min); - Assert.AreEqual(distribution.Support.Max, target.Support.Max); - Assert.AreEqual(distribution.Variance, target.Variance); - Assert.IsTrue(target.Weights.IsEqual(weights.Divide(weights.Sum()))); - Assert.AreEqual(target.Samples, samples); - - for (double x = 0; x < 6; x += 0.1) - { - double actual, expected; - expected = distribution.ComplementaryDistributionFunction(x); - actual = target.ComplementaryDistributionFunction(x); - Assert.AreEqual(expected, actual); - - expected = distribution.CumulativeHazardFunction(x); - actual = target.CumulativeHazardFunction(x); - Assert.AreEqual(expected, actual); - - expected = distribution.DistributionFunction(x); - actual = target.DistributionFunction(x); - Assert.AreEqual(expected, actual); - - expected = distribution.HazardFunction(x); - actual = target.HazardFunction(x); - Assert.AreEqual(expected, actual, 1e-15); - - expected = distribution.InverseDistributionFunction(Accord.Math.Tools.Scale(0, 6, 0, 1, x)); - actual = target.InverseDistributionFunction(Accord.Math.Tools.Scale(0, 6, 0, 1, x)); - Assert.AreEqual(expected, actual); - - expected = distribution.LogProbabilityDensityFunction(x); - actual = target.LogProbabilityDensityFunction(x); - Assert.AreEqual(expected, actual, 1e-15); - - expected = distribution.ProbabilityDensityFunction(x); - actual = target.ProbabilityDensityFunction(x); - Assert.AreEqual(expected, actual, 1e-15); - - expected = distribution.QuantileDensityFunction(Accord.Math.Tools.Scale(0, 6, 0, 1, x)); - actual = target.QuantileDensityFunction(Accord.Math.Tools.Scale(0, 6, 0, 1, x)); - Assert.AreEqual(expected, actual, 1e-10); - } - } - - [TestMethod()] - public void WeightedEmpiricalDistributionConstructorTest2() - { - double[] original = { 5, 5, 1, 4, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 4, 3, 2, 3 }; - var distribution = new EmpiricalDistribution(original); - - double[] weights = { 2, 1, 1, 1, 2, 3, 1, 3, 1, 1, 1, 1 }; - double[] samples = { 5, 1, 4, 1, 2, 3, 4, 3, 4, 3, 2, 3 }; - - weights = weights.Divide(weights.Sum()); - - var target = new EmpiricalDistribution(samples, weights, distribution.Smoothing); - - Assert.AreEqual(distribution.Mean, target.Mean); - Assert.AreEqual(distribution.Median, target.Median); - Assert.AreEqual(distribution.Mode, target.Mode); - Assert.AreEqual(distribution.Quartiles.Min, target.Quartiles.Min); - Assert.AreEqual(distribution.Quartiles.Max, target.Quartiles.Max); - Assert.AreEqual(distribution.Smoothing, target.Smoothing); - Assert.AreEqual(1.1685534824642432, target.StandardDeviation); - Assert.AreEqual(distribution.Support.Min, target.Support.Min); - Assert.AreEqual(distribution.Support.Max, target.Support.Max); - Assert.AreEqual(1.3655172413793104, target.Variance); - Assert.AreEqual(target.Weights, weights); - Assert.AreEqual(target.Samples, samples); - - for (double x = 0; x < 6; x += 0.1) - { - double actual, expected; - expected = distribution.ComplementaryDistributionFunction(x); - actual = target.ComplementaryDistributionFunction(x); - Assert.AreEqual(expected, actual, 1e-15); - - expected = distribution.CumulativeHazardFunction(x); - actual = target.CumulativeHazardFunction(x); - Assert.AreEqual(expected, actual, 1e-15); - - expected = distribution.DistributionFunction(x); - actual = target.DistributionFunction(x); - Assert.AreEqual(expected, actual, 1e-15); - - expected = distribution.HazardFunction(x); - actual = target.HazardFunction(x); - Assert.AreEqual(expected, actual, 1e-14); - - expected = distribution.InverseDistributionFunction(Accord.Math.Tools.Scale(0, 6, 0, 1, x)); - actual = target.InverseDistributionFunction(Accord.Math.Tools.Scale(0, 6, 0, 1, x)); - Assert.AreEqual(expected, actual, 1e-14); - - expected = distribution.LogProbabilityDensityFunction(x); - actual = target.LogProbabilityDensityFunction(x); - Assert.AreEqual(expected, actual, 1e-15); - - expected = distribution.ProbabilityDensityFunction(x); - actual = target.ProbabilityDensityFunction(x); - Assert.AreEqual(expected, actual, 1e-15); - - expected = distribution.QuantileDensityFunction(Accord.Math.Tools.Scale(0, 6, 0, 1, x)); - actual = target.QuantileDensityFunction(Accord.Math.Tools.Scale(0, 6, 0, 1, x)); - Assert.AreEqual(expected, actual, 1e-10); - } - } - - [TestMethod()] - public void WeightedEmpiricalDistributionConstructorTest3() - { - double[] weights = { 2, 1, 1, 1, 2, 3, 1, 3, 1, 1, 1, 1 }; - double[] samples = { 5, 1, 4, 1, 2, 3, 4, 3, 4, 3, 2, 3 }; - - weights = weights.Divide(weights.Sum()); - - var target = new EmpiricalDistribution(samples, weights); - - Assert.AreEqual(1.2377597081667415, target.Smoothing); - } - - [TestMethod()] - public void EmpiricalDistributionConstructorTest4() - { - double[] samples = { 5, 5, 1, 4, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 4, 3, 2, 3 }; - EmpiricalDistribution target = new EmpiricalDistribution(samples, FaultySmoothingRule(samples)); - Assert.AreEqual(samples, target.Samples); - Assert.AreEqual(1.9144923416414432, target.Smoothing); - } - - [TestMethod()] - public void EmpiricalDistributionConstructorTest5() - { - double[] samples = { 5, 5, 1, 4, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 4, 3, 2, 3 }; - EmpiricalDistribution distribution = new EmpiricalDistribution(samples, FaultySmoothingRule(samples)); - - - double mean = distribution.Mean; // 3 - double median = distribution.Median; // 2.9999993064186787 - double var = distribution.Variance; // 1.2941176470588236 - double chf = distribution.CumulativeHazardFunction(x: 4.2); // 2.1972245773362191 - double cdf = distribution.DistributionFunction(x: 4.2); // 0.88888888888888884 - double pdf = distribution.ProbabilityDensityFunction(x: 4.2); // 0.15552784414141974 - double lpdf = distribution.LogProbabilityDensityFunction(x: 4.2); // -1.8609305013898356 - double hf = distribution.HazardFunction(x: 4.2); // 1.3997505972727771 - double ccdf = distribution.ComplementaryDistributionFunction(x: 4.2); //0.11111111111111116 - double icdf = distribution.InverseDistributionFunction(p: cdf); // 4.1999999999999993 - double smoothing = distribution.Smoothing; // 1.9144923416414432 - - string str = distribution.ToString(); // Fn(x; S) - - Assert.AreEqual(samples, distribution.Samples); - Assert.AreEqual(1.9144923416414432, smoothing, 1.0e-15); - Assert.AreEqual(3.0, mean); - Assert.AreEqual(2.9999993064186787, median); - Assert.AreEqual(1.2941176470588236, var); - Assert.AreEqual(2.1972245773362191, chf); - Assert.AreEqual(0.88888888888888884, cdf); - Assert.AreEqual(0.15552784414141974, pdf, 1e-15); - Assert.AreEqual(-1.8609305013898356, lpdf); - Assert.AreEqual(1.3997505972727771, hf, 1e-15); - Assert.AreEqual(0.11111111111111116, ccdf); - Assert.AreEqual(4.1999999999999993, icdf); - Assert.AreEqual("Fn(x; S)", str); - } - - [TestMethod()] - public void MedianTest() - { - double[] samples = { 1, 5, 2, 5, 1, 7, 1, 9 }; - EmpiricalDistribution target = new EmpiricalDistribution(samples); - - Assert.AreEqual(target.Median, target.InverseDistributionFunction(0.5)); - } - - [TestMethod()] - public void CloneTest() - { - double[] samples = { 4, 2 }; - EmpiricalDistribution target = new EmpiricalDistribution(samples); - - EmpiricalDistribution clone = (EmpiricalDistribution)target.Clone(); - - Assert.AreNotSame(target, clone); - Assert.AreEqual(target.Entropy, clone.Entropy); - Assert.AreEqual(target.Mean, clone.Mean); - Assert.AreNotSame(target.Samples, clone.Samples); - Assert.AreEqual(target.StandardDeviation, clone.StandardDeviation); - Assert.AreEqual(target.Variance, clone.Variance); - - for (int i = 0; i < clone.Samples.Length; i++) - Assert.AreEqual(target.Samples[i], clone.Samples[i]); - } - - [TestMethod()] - public void DistributionFunctionTest() - { - double[] samples = { 1, 5, 2, 5, 1, 7, 1, 9 }; - EmpiricalDistribution target = new EmpiricalDistribution(samples); - - Assert.AreEqual(0.000, target.DistributionFunction(0)); - Assert.AreEqual(0.375, target.DistributionFunction(1)); - Assert.AreEqual(0.500, target.DistributionFunction(2)); - Assert.AreEqual(0.750, target.DistributionFunction(5)); - Assert.AreEqual(0.875, target.DistributionFunction(7)); - Assert.AreEqual(1.000, target.DistributionFunction(9)); - } - - [TestMethod()] - public void FitTest1() - { - EmpiricalDistribution target = new EmpiricalDistribution(new double[] { 0 }); - - double[] observations = { 1, 5, 2, 5, 1, 7, 1, 9, 4, 2 }; - double[] weights = null; - IFittingOptions options = null; - - target.Fit(observations, weights, options); - Assert.AreEqual(1.8652004071576875, target.Smoothing); - Assert.AreNotSame(observations, target.Samples); - CollectionAssert.AreEqual(observations, target.Samples); - } - - [TestMethod()] - public void FitTest2() - { - EmpiricalDistribution target = new EmpiricalDistribution(new double[] { 0 }); - - double[] observations = { 5, 5, 1, 4, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 4, 3, 2, 3 }; - double[] weights = null; - IFittingOptions options = new EmpiricalOptions { SmoothingRule = FaultySmoothingRule }; - - target.Fit(observations, weights, options); - Assert.AreEqual(1.9144923416414432, target.Smoothing); - Assert.AreNotSame(observations, target.Samples); - CollectionAssert.AreEqual(observations, target.Samples); - } - - [TestMethod()] - public void ProbabilityDensityFunctionTest() - { - double[] samples = { 1, 5, 2, 5, 1, 7, 1, 9, 4, 2 }; - EmpiricalDistribution target = new EmpiricalDistribution(samples, 1); - - Assert.AreEqual(1.0, target.Smoothing); - - double actual; - - actual = target.ProbabilityDensityFunction(1); - Assert.AreEqual(0.16854678051819402, actual); - - actual = target.ProbabilityDensityFunction(2); - Assert.AreEqual(0.15866528844260089, actual, 1e-15); - - actual = target.ProbabilityDensityFunction(3); - Assert.AreEqual(0.0996000842425018, actual, 1e-15); - - actual = target.ProbabilityDensityFunction(4); - Assert.AreEqual(0.1008594542833362, actual); - - actual = target.ProbabilityDensityFunction(6); - Assert.AreEqual(0.078460710909263, actual, 1e-15); - - actual = target.ProbabilityDensityFunction(8); - Assert.AreEqual(0.049293898826709738, actual, 1e-15); - } - - [TestMethod()] - public void LogProbabilityDensityFunctionTest() - { - double[] samples = { 1, 5, 2, 5, 1, 7, 1, 9, 4, 2 }; - EmpiricalDistribution target = new EmpiricalDistribution(samples, 1); - - Assert.AreEqual(1.0, target.Smoothing); - - double actual; - double expected; - - actual = target.LogProbabilityDensityFunction(1); - expected = System.Math.Log(0.16854678051819402); - Assert.AreEqual(expected, actual, 1e-6); - - actual = target.LogProbabilityDensityFunction(2); - expected = System.Math.Log(0.15866528844260089); - Assert.AreEqual(expected, actual, 1e-6); - - actual = target.LogProbabilityDensityFunction(3); - expected = System.Math.Log(0.0996000842425018); - Assert.AreEqual(expected, actual, 1e-6); - - actual = target.LogProbabilityDensityFunction(4); - expected = System.Math.Log(0.1008594542833362); - Assert.AreEqual(expected, actual, 1e-6); - - actual = target.LogProbabilityDensityFunction(6); - expected = System.Math.Log(0.078460710909263); - Assert.AreEqual(expected, actual, 1e-6); - - actual = target.LogProbabilityDensityFunction(8); - expected = System.Math.Log(0.049293898826709738); - Assert.AreEqual(expected, actual, 1e-6); - } - - - private static double FaultySmoothingRule(double[] observations) - { - double sigma = Accord.Statistics.Tools.StandardDeviation(observations); - return sigma * Math.Pow(4.0 / (3.0 * observations.Length), -1 / 5.0); - } - - private static double FaultySmoothingRule(double[] observations, double[] weights, int[] repeats) - { - return FaultySmoothingRule(observations); - } - } -} +// Accord Unit Tests +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Tests.Statistics +{ + using Accord.Math; + using Accord.Statistics.Distributions.Fitting; + using Accord.Statistics.Distributions.Univariate; + using NUnit.Framework; + using System; + + [TestFixture] + public class EmpiricalDistributionTest + { + + [Test] + public void EmpiricalDistributionConstructorTest1() + { + double[] samples = { 5, 5, 1, 4, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 4, 3, 2, 3 }; + double smoothing = 0.5; + + EmpiricalDistribution target = new EmpiricalDistribution(samples, smoothing); + Assert.AreEqual(samples, target.Samples); + Assert.AreEqual(smoothing, target.Smoothing); + + Assert.AreEqual(3, target.Mean); + Assert.AreEqual(1.1375929179890421, target.StandardDeviation); + Assert.AreEqual(target.Variance, target.Variance); + } + + [Test] + public void EmpiricalDistributionConstructorTest2() + { + double[] samples = { 5, 5, 1, 4, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 4, 3, 2, 3 }; + EmpiricalDistribution target = new EmpiricalDistribution(samples); + Assert.AreEqual(samples, target.Samples); + Assert.AreEqual(0.67595864392399474, target.Smoothing); + } + + [Test] + public void EmpiricalDistributionConstructorTest3() + { + double[] samples = { 5, 5, 1, 4, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 4, 3, 2, 3 }; + EmpiricalDistribution distribution = new EmpiricalDistribution(samples); + + double mean = distribution.Mean; // 3 + double median = distribution.Median; // 2.9999993064186787 + double var = distribution.Variance; // 1.2941176470588236 + double mode = distribution.Mode; // 3 + + double chf = distribution.CumulativeHazardFunction(x: 4.2); // 2.1972245773362191 + double cdf = distribution.DistributionFunction(x: 4.2); // 0.88888888888888884 + double pdf = distribution.ProbabilityDensityFunction(x: 4.2); // 0.181456280142802 + double lpdf = distribution.LogProbabilityDensityFunction(x: 4.2); // -1.7067405350495708 + double hf = distribution.HazardFunction(x: 4.2); // 1.6331065212852196 + double ccdf = distribution.ComplementaryDistributionFunction(x: 4.2); //0.11111111111111116 + double icdf = distribution.InverseDistributionFunction(p: cdf); // 4.1999999999999993 + double smoothing = distribution.Smoothing; // 0.67595864392399474 + + string str = distribution.ToString(); // Fn(x; S) + + Assert.AreEqual(samples, distribution.Samples); + Assert.AreEqual(0.67595864392399474, smoothing); + Assert.AreEqual(3.0, mode); + Assert.AreEqual(3.0, mean); + Assert.AreEqual(2.9999993064186787, median); + Assert.AreEqual(1.2941176470588236, var); + Assert.AreEqual(2.1972245773362191, chf); + Assert.AreEqual(0.88888888888888884, cdf); + Assert.AreEqual(0.18145628014280227, pdf, 1e-15); + Assert.AreEqual(-1.7067405350495708, lpdf); + Assert.AreEqual(1.6331065212852196, hf, 1e-15); + Assert.AreEqual(0.11111111111111116, ccdf); + Assert.AreEqual(4.1999999999999993, icdf); + Assert.AreEqual("Fn(x; S)", str); + + var range1 = distribution.GetRange(0.95); + var range2 = distribution.GetRange(0.99); + var range3 = distribution.GetRange(0.01); + + Assert.AreEqual(0.99999947547912593, range1.Min); + Assert.AreEqual(5.0000002464240794, range1.Max); + Assert.AreEqual(0.99999913215637204, range2.Min); + Assert.AreEqual(5.0000004605903117, range2.Max); + Assert.AreEqual(0.99999913215637204, range3.Min); + Assert.AreEqual(5.0000004605903117, range3.Max); + } + + [Test] + public void WeightedEmpiricalDistributionConstructorTest() + { + double[] original = { 5, 5, 1, 4, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 4, 3, 2, 3 }; + var distribution = new EmpiricalDistribution(original); + + int[] weights = { 2, 1, 1, 1, 2, 3, 1, 3, 1, 1, 1, 1 }; + double[] samples = { 5, 1, 4, 1, 2, 3, 4, 3, 4, 3, 2, 3 }; + var target = new EmpiricalDistribution(samples, weights); + + Assert.AreEqual(distribution.Entropy, target.Entropy, 1e-10); + Assert.AreEqual(distribution.Mean, target.Mean); + Assert.AreEqual(distribution.Median, target.Median); + Assert.AreEqual(distribution.Mode, target.Mode); + Assert.AreEqual(distribution.Quartiles.Min, target.Quartiles.Min); + Assert.AreEqual(distribution.Quartiles.Max, target.Quartiles.Max); + Assert.AreEqual(distribution.Smoothing, target.Smoothing); + Assert.AreEqual(distribution.StandardDeviation, target.StandardDeviation); + Assert.AreEqual(distribution.Support.Min, target.Support.Min); + Assert.AreEqual(distribution.Support.Max, target.Support.Max); + Assert.AreEqual(distribution.Variance, target.Variance); + Assert.IsTrue(target.Weights.IsEqual(weights.Divide(weights.Sum()))); + Assert.AreEqual(target.Samples, samples); + + for (double x = 0; x < 6; x += 0.1) + { + double actual, expected; + expected = distribution.ComplementaryDistributionFunction(x); + actual = target.ComplementaryDistributionFunction(x); + Assert.AreEqual(expected, actual); + + expected = distribution.CumulativeHazardFunction(x); + actual = target.CumulativeHazardFunction(x); + Assert.AreEqual(expected, actual); + + expected = distribution.DistributionFunction(x); + actual = target.DistributionFunction(x); + Assert.AreEqual(expected, actual); + + expected = distribution.HazardFunction(x); + actual = target.HazardFunction(x); + Assert.AreEqual(expected, actual, 1e-15); + + expected = distribution.InverseDistributionFunction(Accord.Math.Tools.Scale(0, 6, 0, 1, x)); + actual = target.InverseDistributionFunction(Accord.Math.Tools.Scale(0, 6, 0, 1, x)); + Assert.AreEqual(expected, actual); + + expected = distribution.LogProbabilityDensityFunction(x); + actual = target.LogProbabilityDensityFunction(x); + Assert.AreEqual(expected, actual, 1e-15); + + expected = distribution.ProbabilityDensityFunction(x); + actual = target.ProbabilityDensityFunction(x); + Assert.AreEqual(expected, actual, 1e-15); + + expected = distribution.QuantileDensityFunction(Accord.Math.Tools.Scale(0, 6, 0, 1, x)); + actual = target.QuantileDensityFunction(Accord.Math.Tools.Scale(0, 6, 0, 1, x)); + Assert.AreEqual(expected, actual, 1e-10); + } + } + + [Test] + public void WeightedEmpiricalDistributionConstructorTest2() + { + double[] original = { 5, 5, 1, 4, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 4, 3, 2, 3 }; + var distribution = new EmpiricalDistribution(original); + + double[] weights = { 2, 1, 1, 1, 2, 3, 1, 3, 1, 1, 1, 1 }; + double[] samples = { 5, 1, 4, 1, 2, 3, 4, 3, 4, 3, 2, 3 }; + + weights = weights.Divide(weights.Sum()); + + var target = new EmpiricalDistribution(samples, weights, distribution.Smoothing); + + Assert.AreEqual(distribution.Mean, target.Mean); + Assert.AreEqual(distribution.Median, target.Median); + Assert.AreEqual(distribution.Mode, target.Mode); + Assert.AreEqual(distribution.Quartiles.Min, target.Quartiles.Min); + Assert.AreEqual(distribution.Quartiles.Max, target.Quartiles.Max); + Assert.AreEqual(distribution.Smoothing, target.Smoothing); + Assert.AreEqual(1.1685534824642432, target.StandardDeviation); + Assert.AreEqual(distribution.Support.Min, target.Support.Min); + Assert.AreEqual(distribution.Support.Max, target.Support.Max); + Assert.AreEqual(1.3655172413793104, target.Variance); + Assert.AreEqual(target.Weights, weights); + Assert.AreEqual(target.Samples, samples); + + for (double x = 0; x < 6; x += 0.1) + { + double actual, expected; + expected = distribution.ComplementaryDistributionFunction(x); + actual = target.ComplementaryDistributionFunction(x); + Assert.AreEqual(expected, actual, 1e-15); + + expected = distribution.CumulativeHazardFunction(x); + actual = target.CumulativeHazardFunction(x); + Assert.AreEqual(expected, actual, 1e-15); + + expected = distribution.DistributionFunction(x); + actual = target.DistributionFunction(x); + Assert.AreEqual(expected, actual, 1e-15); + + expected = distribution.HazardFunction(x); + actual = target.HazardFunction(x); + Assert.AreEqual(expected, actual, 1e-14); + + expected = distribution.InverseDistributionFunction(Accord.Math.Tools.Scale(0, 6, 0, 1, x)); + actual = target.InverseDistributionFunction(Accord.Math.Tools.Scale(0, 6, 0, 1, x)); + Assert.AreEqual(expected, actual, 1e-14); + + expected = distribution.LogProbabilityDensityFunction(x); + actual = target.LogProbabilityDensityFunction(x); + Assert.AreEqual(expected, actual, 1e-15); + + expected = distribution.ProbabilityDensityFunction(x); + actual = target.ProbabilityDensityFunction(x); + Assert.AreEqual(expected, actual, 1e-15); + + expected = distribution.QuantileDensityFunction(Accord.Math.Tools.Scale(0, 6, 0, 1, x)); + actual = target.QuantileDensityFunction(Accord.Math.Tools.Scale(0, 6, 0, 1, x)); + Assert.AreEqual(expected, actual, 1e-10); + } + } + + [Test] + public void WeightedEmpiricalDistributionConstructorTest3() + { + double[] weights = { 2, 1, 1, 1, 2, 3, 1, 3, 1, 1, 1, 1 }; + double[] samples = { 5, 1, 4, 1, 2, 3, 4, 3, 4, 3, 2, 3 }; + + weights = weights.Divide(weights.Sum()); + + var target = new EmpiricalDistribution(samples, weights); + + Assert.AreEqual(1.2377597081667415, target.Smoothing); + } + + [Test] + public void EmpiricalDistributionConstructorTest4() + { + double[] samples = { 5, 5, 1, 4, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 4, 3, 2, 3 }; + EmpiricalDistribution target = new EmpiricalDistribution(samples, FaultySmoothingRule(samples)); + Assert.AreEqual(samples, target.Samples); + Assert.AreEqual(1.9144923416414432, target.Smoothing); + } + + [Test] + public void EmpiricalDistributionConstructorTest5() + { + double[] samples = { 5, 5, 1, 4, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 4, 3, 2, 3 }; + EmpiricalDistribution distribution = new EmpiricalDistribution(samples, FaultySmoothingRule(samples)); + + + double mean = distribution.Mean; // 3 + double median = distribution.Median; // 2.9999993064186787 + double var = distribution.Variance; // 1.2941176470588236 + double chf = distribution.CumulativeHazardFunction(x: 4.2); // 2.1972245773362191 + double cdf = distribution.DistributionFunction(x: 4.2); // 0.88888888888888884 + double pdf = distribution.ProbabilityDensityFunction(x: 4.2); // 0.15552784414141974 + double lpdf = distribution.LogProbabilityDensityFunction(x: 4.2); // -1.8609305013898356 + double hf = distribution.HazardFunction(x: 4.2); // 1.3997505972727771 + double ccdf = distribution.ComplementaryDistributionFunction(x: 4.2); //0.11111111111111116 + double icdf = distribution.InverseDistributionFunction(p: cdf); // 4.1999999999999993 + double smoothing = distribution.Smoothing; // 1.9144923416414432 + + string str = distribution.ToString(); // Fn(x; S) + + Assert.AreEqual(samples, distribution.Samples); + Assert.AreEqual(1.9144923416414432, smoothing, 1.0e-15); + Assert.AreEqual(3.0, mean); + Assert.AreEqual(2.9999993064186787, median); + Assert.AreEqual(1.2941176470588236, var); + Assert.AreEqual(2.1972245773362191, chf); + Assert.AreEqual(0.88888888888888884, cdf); + Assert.AreEqual(0.15552784414141974, pdf, 1e-15); + Assert.AreEqual(-1.8609305013898356, lpdf); + Assert.AreEqual(1.3997505972727771, hf, 1e-15); + Assert.AreEqual(0.11111111111111116, ccdf); + Assert.AreEqual(4.1999999999999993, icdf); + Assert.AreEqual("Fn(x; S)", str); + } + + [Test] + public void MedianTest() + { + double[] samples = { 1, 5, 2, 5, 1, 7, 1, 9 }; + EmpiricalDistribution target = new EmpiricalDistribution(samples); + + Assert.AreEqual(target.Median, target.InverseDistributionFunction(0.5)); + } + + [Test] + public void CloneTest() + { + double[] samples = { 4, 2 }; + EmpiricalDistribution target = new EmpiricalDistribution(samples); + + EmpiricalDistribution clone = (EmpiricalDistribution)target.Clone(); + + Assert.AreNotSame(target, clone); + Assert.AreEqual(target.Entropy, clone.Entropy); + Assert.AreEqual(target.Mean, clone.Mean); + Assert.AreNotSame(target.Samples, clone.Samples); + Assert.AreEqual(target.StandardDeviation, clone.StandardDeviation); + Assert.AreEqual(target.Variance, clone.Variance); + + for (int i = 0; i < clone.Samples.Length; i++) + Assert.AreEqual(target.Samples[i], clone.Samples[i]); + } + + [Test] + public void DistributionFunctionTest() + { + double[] samples = { 1, 5, 2, 5, 1, 7, 1, 9 }; + EmpiricalDistribution target = new EmpiricalDistribution(samples); + + Assert.AreEqual(0.000, target.DistributionFunction(0)); + Assert.AreEqual(0.375, target.DistributionFunction(1)); + Assert.AreEqual(0.500, target.DistributionFunction(2)); + Assert.AreEqual(0.750, target.DistributionFunction(5)); + Assert.AreEqual(0.875, target.DistributionFunction(7)); + Assert.AreEqual(1.000, target.DistributionFunction(9)); + } + + [Test] + public void FitTest1() + { + EmpiricalDistribution target = new EmpiricalDistribution(new double[] { 0 }); + + double[] observations = { 1, 5, 2, 5, 1, 7, 1, 9, 4, 2 }; + double[] weights = null; + IFittingOptions options = null; + + target.Fit(observations, weights, options); + Assert.AreEqual(1.8652004071576875, target.Smoothing); + Assert.AreNotSame(observations, target.Samples); + CollectionAssert.AreEqual(observations, target.Samples); + } + + [Test] + public void FitTest2() + { + EmpiricalDistribution target = new EmpiricalDistribution(new double[] { 0 }); + + double[] observations = { 5, 5, 1, 4, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 4, 3, 2, 3 }; + double[] weights = null; + IFittingOptions options = new EmpiricalOptions { SmoothingRule = FaultySmoothingRule }; + + target.Fit(observations, weights, options); + Assert.AreEqual(1.9144923416414432, target.Smoothing); + Assert.AreNotSame(observations, target.Samples); + CollectionAssert.AreEqual(observations, target.Samples); + } + + [Test] + public void ProbabilityDensityFunctionTest() + { + double[] samples = { 1, 5, 2, 5, 1, 7, 1, 9, 4, 2 }; + EmpiricalDistribution target = new EmpiricalDistribution(samples, 1); + + Assert.AreEqual(1.0, target.Smoothing); + + double actual; + + actual = target.ProbabilityDensityFunction(1); + Assert.AreEqual(0.16854678051819402, actual); + + actual = target.ProbabilityDensityFunction(2); + Assert.AreEqual(0.15866528844260089, actual, 1e-15); + + actual = target.ProbabilityDensityFunction(3); + Assert.AreEqual(0.0996000842425018, actual, 1e-15); + + actual = target.ProbabilityDensityFunction(4); + Assert.AreEqual(0.1008594542833362, actual); + + actual = target.ProbabilityDensityFunction(6); + Assert.AreEqual(0.078460710909263, actual, 1e-15); + + actual = target.ProbabilityDensityFunction(8); + Assert.AreEqual(0.049293898826709738, actual, 1e-15); + } + + [Test] + public void LogProbabilityDensityFunctionTest() + { + double[] samples = { 1, 5, 2, 5, 1, 7, 1, 9, 4, 2 }; + EmpiricalDistribution target = new EmpiricalDistribution(samples, 1); + + Assert.AreEqual(1.0, target.Smoothing); + + double actual; + double expected; + + actual = target.LogProbabilityDensityFunction(1); + expected = System.Math.Log(0.16854678051819402); + Assert.AreEqual(expected, actual, 1e-6); + + actual = target.LogProbabilityDensityFunction(2); + expected = System.Math.Log(0.15866528844260089); + Assert.AreEqual(expected, actual, 1e-6); + + actual = target.LogProbabilityDensityFunction(3); + expected = System.Math.Log(0.0996000842425018); + Assert.AreEqual(expected, actual, 1e-6); + + actual = target.LogProbabilityDensityFunction(4); + expected = System.Math.Log(0.1008594542833362); + Assert.AreEqual(expected, actual, 1e-6); + + actual = target.LogProbabilityDensityFunction(6); + expected = System.Math.Log(0.078460710909263); + Assert.AreEqual(expected, actual, 1e-6); + + actual = target.LogProbabilityDensityFunction(8); + expected = System.Math.Log(0.049293898826709738); + Assert.AreEqual(expected, actual, 1e-6); + } + + + private static double FaultySmoothingRule(double[] observations) + { + double sigma = Accord.Statistics.Tools.StandardDeviation(observations); + return sigma * Math.Pow(4.0 / (3.0 * observations.Length), -1 / 5.0); + } + + private static double FaultySmoothingRule(double[] observations, double[] weights, int[] repeats) + { + return FaultySmoothingRule(observations); + } + } +} diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/EmpiricalHazardDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/EmpiricalHazardDistributionTest.cs index 57f79abff..151500d4f 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/EmpiricalHazardDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/EmpiricalHazardDistributionTest.cs @@ -1,236 +1,759 @@ -// Accord Unit Tests -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Tests.Statistics -{ - using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using System; - using Accord.Math; - - [TestClass()] - public class EmpiricalHazardDistributionTest - { - - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - [TestMethod()] - public void EmpiricalHazardConstructorTest3() - { - double[] times = { 11, 10, 9, 8, 6, 5, 4, 2 }; - double[] values = { 0.22, 0.67, 1.00, 0.18, 1.00, 1.00, 1.00, 0.55 }; - - - EmpiricalHazardDistribution distribution = new EmpiricalHazardDistribution(times, values); - - - double mean = distribution.Mean; // 0.93696461879063664 - double median = distribution.Median; // 3.9999999151458066 - double var = distribution.Variance; // 2.0441627748096289 - - try { double mode = distribution.Mode; Assert.Fail(); } - catch { } - - double chf = distribution.CumulativeHazardFunction(x: 4.2); // 1.55 - double cdf = distribution.DistributionFunction(x: 4.2); // 0.7877520261732569 - double pdf = distribution.ProbabilityDensityFunction(x: 4.2); // 0.046694554241883471 - double lpdf = distribution.LogProbabilityDensityFunction(x: 4.2); // -3.0641277326297756 - double hf = distribution.HazardFunction(x: 4.2); // 0.22 - double ccdf = distribution.ComplementaryDistributionFunction(x: 4.2); // 0.21224797382674304 - double icdf = distribution.InverseDistributionFunction(p: cdf); // 4.3483975243778978 - - string str = distribution.ToString(); // H(x; v, t) - - Assert.AreEqual(0.93696461879063664, mean); - Assert.AreEqual(3.9999999151458066, median, 1e-6); - Assert.AreEqual(2.0441627748096289, var); - Assert.AreEqual(1.55, chf); - Assert.AreEqual(0.7877520261732569, cdf); - Assert.AreEqual(0.046694554241883471, pdf); - Assert.AreEqual(-3.0641277326297756, lpdf); - Assert.AreEqual(0.22, hf); - Assert.AreEqual(0.21224797382674304, ccdf); - Assert.AreEqual(4.3483975243778978, icdf, 1e-8); - Assert.AreEqual("H(x; v, t)", str); - - var range1 = distribution.GetRange(0.95); - var range2 = distribution.GetRange(0.99); - var range3 = distribution.GetRange(0.01); - - Assert.AreEqual(1.9999999025499791, range1.Min); - Assert.AreEqual(6.0000003654595639, range1.Max); - Assert.AreEqual(1.9999997393145033, range2.Min); - Assert.AreEqual(9.0000004130107865, range2.Max); - Assert.AreEqual(1.9999997393145026, range3.Min); - Assert.AreEqual(9.0000004130107865, range3.Max); - } - - [TestMethod()] - public void DistributionFunctionTest() - { - - double[] values = - { - 1.0000000000000000, 0.8724284533876597, 0.9698946958777951, - 1.0000000000000000, 0.9840887140861863, 1.0000000000000000, - 1.0000000000000000, 1.0000000000000000, 1.0000000000000000, - 0.9979137773216293, 1.0000000000000000 - }; - - double[] times = - { - 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 - }; - - EmpiricalHazardDistribution target = EmpiricalHazardDistribution - .FromSurvivalValues(times, values); - - - // Data from: http://www.sph.emory.edu/~cdckms/CoxPH/prophaz2.html - double[] expectedBaselineSurvivalFunction = - { - 1.0000, 0.9979, 0.9979, 0.9979, - 0.9979, 0.9979, 0.9820, - 0.9820, 0.9525, 0.8310, 0.8310, - }; - - - double[] hazardFunction = new double[expectedBaselineSurvivalFunction.Length]; - double[] survivalFunction = new double[expectedBaselineSurvivalFunction.Length]; - - for (int i = 0; i < 11; i++) - hazardFunction[i] = target.CumulativeHazardFunction(i + 1); - - for (int i = 0; i < 11; i++) - survivalFunction[i] = target.ComplementaryDistributionFunction(i + 1); - - - for (int i = 0; i < expectedBaselineSurvivalFunction.Length; i++) - { - Assert.AreEqual(expectedBaselineSurvivalFunction[i], survivalFunction[i], 0.01); - - // Ho = -log(So) - Assert.AreEqual(hazardFunction[i], -Math.Log(survivalFunction[i]), 0.01); - - // So = exp(-Ho) - Assert.AreEqual(survivalFunction[i], Math.Exp(-hazardFunction[i]), 0.01); - } - } - - [TestMethod()] - public void MedianTest() - { - double[] values = - { - 0.0000000000000000, 0.0351683340828711, 0.0267358118285064, - 0.0000000000000000, 0.0103643094219679, 0.0000000000000000, - 0.0000000000000000, 0.0000000000000000, 0.0000000000000000, - 0.000762266794052363, 0.000000000000000 - }; - - double[] times = - { - 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 - }; - - - EmpiricalHazardDistribution target = - new EmpiricalHazardDistribution(times, values); - - Assert.AreEqual(target.Median, target.InverseDistributionFunction(0.5)); - } - - [TestMethod()] - public void DistributionFunctionTest2() - { - - double[] values = - { - 0.0000000000000000, 0.0351683340828711, 0.0267358118285064, - 0.0000000000000000, 0.0103643094219679, 0.0000000000000000, - 0.0000000000000000, 0.0000000000000000, 0.0000000000000000, - 0.000762266794052363, 0.000000000000000 - }; - - double[] times = - { - 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 - }; - - - EmpiricalHazardDistribution target = - new EmpiricalHazardDistribution(times, values); - - double[] expected = - { - 1.000000000000000, - 0.999238023657475, - 0.999238023657475, - 0.999238023657475, - 0.999238023657475, - 0.999238023657475, - 0.98893509519066469, - 0.98893509519066469, - 0.96284543081744489, - 0.92957227114936058, - 0.92957227114936058, - }; - - - double[] hazardFunction = new double[expected.Length]; - double[] survivalFunction = new double[expected.Length]; - double[] complementaryDistribution = new double[expected.Length]; - - for (int i = 0; i < 11; i++) - hazardFunction[i] = target.CumulativeHazardFunction(i + 1); - - for (int i = 0; i < 11; i++) - survivalFunction[i] = target.ComplementaryDistributionFunction(i + 1); - - - for (int i = 0; i < expected.Length; i++) - { - Assert.AreEqual(expected[i], survivalFunction[i], 1e-5); - - // Ho = -log(So) - Assert.AreEqual(hazardFunction[i], -Math.Log(survivalFunction[i]), 1e-5); - - // So = exp(-Ho) - Assert.AreEqual(survivalFunction[i], Math.Exp(-hazardFunction[i]), 1e-5); - } - } - - } -} +// Accord Unit Tests +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Tests.Statistics +{ + using Accord.Math; + using Accord.Statistics.Distributions.Fitting; + using Accord.Statistics.Distributions.Univariate; + using NUnit.Framework; + using System; + + [TestFixture] + public class EmpiricalHazardDistributionTest + { + + [Test] + public void DocumentationExample_Aalen() + { + // Consider the following hazard rates, occurring at the given time steps + double[] times = { 0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 17, 20, 21 }; + + double[] hazards = + { + 0, 0.111111111111111, 0.0625, 0.0714285714285714, 0.0769230769230769, + 0, 0.0909090909090909, 0, 0.111111111111111, 0.125, 0, + 0.166666666666667, 0.2, 0, 0.5, 0 + }; + + // Create a new distribution given the observations and event times + var distribution = new EmpiricalHazardDistribution(times, hazards); + + // Common measures + double mean = distribution.Mean; // 6.1658527179584119 + double median = distribution.Median; // 11.999999704601453 + double var = distribution.Variance; // 44.101147497430993 + + // Cumulative distribution functions + double cdf = distribution.DistributionFunction(x: 4); // 0.275274821017619 + double ccdf = distribution.ComplementaryDistributionFunction(x: 4); // 0.724725178982381 + double icdf = distribution.InverseDistributionFunction(p: cdf); // 4.4588994137113307 + + // Probability density functions + double pdf = distribution.ProbabilityDensityFunction(x: 4); // 0.055748090690952365 + double lpdf = distribution.LogProbabilityDensityFunction(x: 4); // -2.8869121169242962 + + // Hazard (failure rate) functions + double hf = distribution.HazardFunction(x: 4); // 0.0769230769230769 + double chf = distribution.CumulativeHazardFunction(x: 4); // 0.32196275946275932 + + string str = distribution.ToString(); // H(x; v, t) + + try { double mode = distribution.Mode; Assert.Fail(); } + catch { } + + Assert.AreEqual(SurvivalEstimator.FlemingHarrington, distribution.Estimator); + Assert.AreEqual(1, distribution.ComplementaryDistributionFunction(0)); + Assert.AreEqual(0, distribution.ComplementaryDistributionFunction(Double.PositiveInfinity)); + + Assert.AreEqual(6.1658527179584119, mean); + Assert.AreEqual(11.999999704601453, median, 1e-6); + Assert.AreEqual(44.101147497430993, var); + Assert.AreEqual(0.32196275946275932, chf); + Assert.AreEqual(0.275274821017619, cdf); + Assert.AreEqual(0.055748090690952365, pdf); + Assert.AreEqual(-2.8869121169242962, lpdf); + Assert.AreEqual(0.0769230769230769, hf); + Assert.AreEqual(0.724725178982381, ccdf); + Assert.AreEqual(4.4588994137113307, icdf, 1e-8); + Assert.AreEqual("H(x; v, t)", str); + + var range1 = distribution.GetRange(0.95); + var range2 = distribution.GetRange(0.99); + var range3 = distribution.GetRange(0.01); + + Assert.AreEqual(1, range1.Min, 1e-3); + Assert.AreEqual(20.562, range1.Max, 1e-3); + Assert.AreEqual(1, range2.Min, 1e-3); + Assert.AreEqual(20.562, range2.Max, 1e-3); + Assert.AreEqual(1, range3.Min, 1e-3); + Assert.AreEqual(20.562, range3.Max, 1e-3); + + for (int i = 0; i < hazards.Length; i++) + Assert.AreEqual(hazards[i], distribution.HazardFunction(times[i])); + } + + [Test] + public void DocumentationExample_KaplanMeier() + { + // Consider the following hazard rates, occurring at the given time steps + double[] times = { 0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 17, 20, 21 }; + + double[] hazards = + { + 0, 0.111111111111111, 0.0625, 0.0714285714285714, 0.0769230769230769, + 0, 0.0909090909090909, 0, 0.111111111111111, 0.125, 0, + 0.166666666666667, 0.2, 0, 0.5, 0 + }; + + + // Create a new distribution given the observations and event times + var distribution = new EmpiricalHazardDistribution(times, hazards, SurvivalEstimator.KaplanMeier); + + // Common measures + double mean = distribution.Mean; // 5.49198237428757 + double median = distribution.Median; // 11.999999704601453 + double var = distribution.Variance; // 39.83481657555663 + + // Cumulative distribution functions + double cdf = distribution.DistributionFunction(x: 4); // 0.275274821017619 + double ccdf = distribution.ComplementaryDistributionFunction(x: 4); // 0.018754904264376961 + double icdf = distribution.InverseDistributionFunction(p: cdf); // 4.4588994137113307 + + // Probability density functions + double pdf = distribution.ProbabilityDensityFunction(x: 4); // 0.055748090690952365 + double lpdf = distribution.LogProbabilityDensityFunction(x: 4); // -2.8869121169242962 + + // Hazard (failure rate) functions + double hf = distribution.HazardFunction(x: 4); // 0.0769230769230769 + double chf = distribution.CumulativeHazardFunction(x: 4); // 0.32196275946275932 + + string str = distribution.ToString(); // H(x; v, t) + + try { double mode = distribution.Mode; Assert.Fail(); } + catch { } + + Assert.AreEqual(SurvivalEstimator.KaplanMeier, distribution.Estimator); + Assert.AreEqual(1, distribution.ComplementaryDistributionFunction(0)); + Assert.AreEqual(0, distribution.ComplementaryDistributionFunction(Double.PositiveInfinity)); + + Assert.AreEqual(5.49198237428757, mean); + Assert.AreEqual(11.999999704601453, median, 1e-6); + Assert.AreEqual(39.83481657555663, var); + Assert.AreEqual(0.33647223662121273, chf); + Assert.AreEqual(0.28571428571428559, cdf); + Assert.AreEqual(0.054945054945054937, pdf); + Assert.AreEqual(-2.9014215940827497, lpdf); + Assert.AreEqual(0.0769230769230769, hf); + Assert.AreEqual(0.71428571428571441, ccdf); + Assert.AreEqual(5.8785425101214548, icdf, 1e-8); + Assert.AreEqual("H(x; v, t)", str); + + var range1 = distribution.GetRange(0.95); + var range2 = distribution.GetRange(0.99); + var range3 = distribution.GetRange(0.01); + + Assert.AreEqual(1, range1.Min, 1e-3); + Assert.AreEqual(20.562, range1.Max, 1e-3); + Assert.AreEqual(1, range2.Min, 1e-3); + Assert.AreEqual(20.562, range2.Max, 1e-3); + Assert.AreEqual(1, range3.Min, 1e-3); + Assert.AreEqual(20.562, range3.Max, 1e-3); + + for (int i = 0; i < hazards.Length; i++) + Assert.AreEqual(hazards[i], distribution.HazardFunction(times[i])); + } + + [Test] + public void MeasuresTest() + { + double[] values = + { + 0.0000000000000000, 0.0351683340828711, 0.0267358118285064, + 0.0000000000000000, 0.0103643094219679, 0.9000000000000000, + 0.0000000000000000, 0.0000000000000000, 0.0000000000000000, + 0.000762266794052363, 0.000000000000000 + }; + + double[] times = + { + 11, 1, 9, 8, 7, 3, 6, 5, 4, 2, 10 + }; + + var target = new EmpiricalHazardDistribution(times, values); + var general = new GeneralContinuousDistribution(target); + + //Assert.AreEqual(general.Mean, target.Mean); + //Assert.AreEqual(general.Variance, target.Variance); + Assert.AreEqual(general.Median, target.Median); + + for (int i = -10; i < 10; i++) + { + double x = i; + double expected = general.CumulativeHazardFunction(x); + double actual = target.CumulativeHazardFunction(x); + Assert.AreEqual(expected, actual, 1e-4); + } + + for (int i = -10; i < 10; i++) + { + double x = i; + double expected = general.HazardFunction(x); + double actual = target.HazardFunction(x); + Assert.AreEqual(expected, actual, 1e-5); + } + } + + [Test] + public void MedianTest() + { + double[] values = + { + 0.0000000000000000, 0.0351683340828711, 0.0267358118285064, + 0.0000000000000000, 0.0103643094219679, 0.0000000000000000, + 0.0000000000000000, 0.0000000000000000, 0.0000000000000000, + 0.000762266794052363, 0.000000000000000 + }; + + double[] times = + { + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 + }; + + + var target = new EmpiricalHazardDistribution(times, values); + + Assert.AreEqual(target.Median, target.InverseDistributionFunction(0.5)); + + Assert.AreEqual(1, target.ComplementaryDistributionFunction(0)); + Assert.AreEqual(0, target.ComplementaryDistributionFunction(Double.PositiveInfinity)); + } + + [Test] + public void DistributionFunctionTest2() + { + + double[] values = + { + 0.0000000000000000, 0.0351683340828711, 0.0267358118285064, + 0.0000000000000000, 0.0103643094219679, 0.0000000000000000, + 0.0000000000000000, 0.0000000000000000, 0.0000000000000000, + 0.000762266794052363, 0.000000000000000 + }; + + double[] times = + { + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 + }; + + + var target = new EmpiricalHazardDistribution(times, values); + + double[] expected = + { + 1.000000000000000, + 0.999238023657475, + 0.999238023657475, + 0.999238023657475, + 0.999238023657475, + 0.999238023657475, + 0.98893509519066469, + 0.98893509519066469, + 0.96284543081744489, + 0.92957227114936058, + 0.92957227114936058, + }; + + + double[] hazardFunction = new double[expected.Length]; + double[] survivalFunction = new double[expected.Length]; + + for (int i = 0; i < 11; i++) + hazardFunction[i] = target.CumulativeHazardFunction(i + 1); + + for (int i = 0; i < 11; i++) + survivalFunction[i] = target.ComplementaryDistributionFunction(i + 1); + + + for (int i = 0; i < expected.Length; i++) + { + Assert.AreEqual(expected[i], survivalFunction[i], 1e-5); + + // Ho = -log(So) + Assert.AreEqual(hazardFunction[i], -Math.Log(survivalFunction[i]), 1e-5); + + // So = exp(-Ho) + Assert.AreEqual(survivalFunction[i], Math.Exp(-hazardFunction[i]), 1e-5); + } + + Assert.AreEqual(1, target.ComplementaryDistributionFunction(0)); + Assert.AreEqual(0, target.ComplementaryDistributionFunction(Double.PositiveInfinity)); + } + + + [Test] + public void LeukemiaExample_KaplanMeier() + { + // The following are times of remission (weeks) for 21 leukemia + // patients receiving control treatment (Table 1.1 of Cox & Oakes): + // http://www-personal.umich.edu/~yili/lect2notes.pdf + + double[] t = { 1, 1, 2, 2, 3, 4, 4, 5, 5, 8, 8, 8, 8, 11, 11, 12, 12, 15, 17, 22, 23 }; + + + var distribution = new EmpiricalHazardDistribution(SurvivalEstimator.KaplanMeier); + + distribution.Fit(t, new EmpiricalHazardOptions { Estimator = HazardEstimator.KaplanMeier }); + + Assert.AreEqual(1, distribution.Survivals[0]); + Assert.AreEqual(0.905, distribution.Survivals[1], 1e-3); + Assert.AreEqual(0.809, distribution.Survivals[2], 1e-3); + Assert.AreEqual(0.762, distribution.Survivals[3], 1e-3); + + /* + http://statpages.org/prophaz2.html + 1, 1 + 1, 1 + 2, 1 + 2, 1 + 3, 1 + 4, 1 + 4, 1 + 5, 1 + 5, 1 + 8, 1 + 8, 1 + 8, 1 + 8, 1 + 11, 1 + 11, 1 + 12, 1 + 12, 1 + 15, 1 + 17, 1 + 22, 1 + 23, 1 + */ + } + + [Test] + public void LeukemiaExampleCensoring_KaplanMeier_KaplanMeier() + { + // The following are times of remission (weeks) for 21 leukemia + // patients receiving control treatment (Table 1.1 of Cox & Oakes): + + double[] t = { 6, 6, 6, 6, 7, 9, 10, 10, 11, 13, 16, 17, 19, 20, 22, 23, 25, 32, 32, 34, 35 }; + int[] c = { 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 }; + + var distribution = EmpiricalHazardDistribution.Estimate(t, c, + SurvivalEstimator.KaplanMeier, HazardEstimator.KaplanMeier); + + int[] intervals = { 6, 7, 9, 10, 11, 13, 16, 17, 19, 20, 22, 23, 25, 32, 34, 35 }; + + double[] expected = + { + 0.8571 , 0.8067, 0.8067, 0.7529, 0.7529, 0.6902, + 0.6275, 0.6275, 0.6275, 0.6275, 0.5378, 0.4482, + 0.4482, 0.4482, 0.4482, 0.4482 + }; + + for (int i = 0; i < intervals.Length; i++) + { + double x = intervals[i]; + double actual = distribution.ComplementaryDistributionFunction(x); + + double e = expected[i]; + Assert.AreEqual(e, actual, 1e-4); + } + } + + [Test] + public void LeukemiaExampleCensoring_KaplanMeier_FlemingHarrington() + { + // The following are times of remission (weeks) for 21 leukemia + // patients receiving control treatment (Table 1.1 of Cox & Oakes): + + double[] t = { 6, 6, 6, 6, 7, 9, 10, 10, 11, 13, 16, 17, 19, 20, 22, 23, 25, 32, 32, 34, 35 }; + int[] c = { 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 }; + + var distribution = new EmpiricalHazardDistribution(SurvivalEstimator.FlemingHarrington); + + distribution.Fit(t, new SurvivalOptions { Outcome = c.To() }); + + int[] intervals = { 6, 7, 9, 10, 11, 13, 16, 17, 19, 20, 22, 23, 25, 32, 34, 35 }; + + double[] expected = + { + 0.8571 , 0.8067, 0.8067, 0.7529, 0.7529, 0.6902, + 0.6275, 0.6275, 0.6275, 0.6275, 0.5378, 0.4482, + 0.4482, 0.4482, 0.4482, 0.4482 + }; + + for (int i = 0; i < intervals.Length; i++) + { + double x = intervals[i]; + double actual = distribution.ComplementaryDistributionFunction(x); + + double e = expected[i]; + Assert.AreEqual(e, actual, 0.1); + } + } + + [Test] + public void LeukemiaExampleCensoring_KaplanMeier_NelsonAalen() + { + // http://www-personal.umich.edu/~yili/lect2notes.pdf + // The following are times of remission (weeks) for 21 leukemia + // patients receiving control treatment (Table 1.1 of Cox & Oakes): + + double[] t = { 6, 6, 6, 6, 7, 9, 10, 10, 11, 13, 16, 17, 19, 20, 22, 23, 25, 32, 32, 34, 35 }; + int[] c = { 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 }; + + var distribution = EmpiricalHazardDistribution.Estimate(t, c, + SurvivalEstimator.KaplanMeier, HazardEstimator.BreslowNelsonAalen); + + int[] intervals = { 6, 7, 9, 10, 11, 13, 16, 17, 19, 20, 22, 23, 25, 32, 34, 35 }; + + double[] expected = + { + 0.8571 , 0.8067, 0.8067, 0.7529, 0.7529, 0.6902, + 0.6275, 0.6275, 0.6275, 0.6275, 0.5378, 0.4482, + 0.4482, 0.4482, 0.4482, 0.4482 + }; + + for (int i = 0; i < intervals.Length; i++) + { + double x = intervals[i]; + double actual = distribution.ComplementaryDistributionFunction(x); + + double e = expected[i]; + Assert.AreEqual(e, actual, 0.02); + } + } + + [Test] + public void LeukemiaExampleCensoring_FlemingHarrington_NelsonAalen() + { + // http://www-personal.umich.edu/~yili/lect2notes.pdf + // The following are times of remission (weeks) for 21 leukemia + // patients receiving control treatment (Table 1.1 of Cox & Oakes): + + double[] t = { 6, 6, 6, 6, 7, 9, 10, 10, 11, 13, 16, 17, 19, 20, 22, 23, 25, 32, 32, 34, 35 }; + int[] c = { 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 }; + + var distribution = EmpiricalHazardDistribution.Estimate(t, c, + SurvivalEstimator.FlemingHarrington, HazardEstimator.BreslowNelsonAalen); + + int[] intervals = { 6, 7, 9, 10, 11, 13, 16, 17, 19, 20, 22, 23, 25, 32, 34, 35 }; + + double[] expected = + { + 0.8571 , 0.8067, 0.8067, 0.7529, 0.7529, 0.6902, + 0.6275, 0.6275, 0.6275, 0.6275, 0.5378, 0.4482, + 0.4482, 0.4482, 0.4482, 0.4482 + }; + + for (int i = 0; i < intervals.Length; i++) + { + double x = intervals[i]; + double actual = distribution.ComplementaryDistributionFunction(x); + + double e = expected[i]; + Assert.AreEqual(e, actual, 0.1); + } + } + + [Test] + public void KaplanMeierTest1() + { + // Example from + // http://sas-and-r.blogspot.fr/2010/05/example-738-kaplan-meier-survival.html + + double[] times; + SurvivalOutcome[] censor; + CreateExample1(out times, out censor); + + var distribution = new EmpiricalHazardDistribution(SurvivalEstimator.KaplanMeier); + + Assert.AreEqual(SurvivalEstimator.KaplanMeier, distribution.Estimator); + + distribution.Fit(times, new EmpiricalHazardOptions(HazardEstimator.KaplanMeier, censor)); + + int[] t = { 1, 2, 3, 4, 6, 8, 9, 12, 14, 20 }; + double[] e = { 0.889, 0.833, 0.774, 0.714, 0.649, 0.577, 0.505, 0.421, 0.337, 0.168 }; + + double[] actual = t.ToDouble().Apply(distribution.ComplementaryDistributionFunction); + + for (int i = 0; i < e.Length; i++) + Assert.AreEqual(e[i], actual[i], 1e-3); + + // Assert.AreEqual(11.177, distribution.Mean); + Assert.AreEqual(12, distribution.Median, 1e-5); + } + + [Test] + public void NelsonAalenTest1() + { + // Example from + // http://sas-and-r.blogspot.fr/2010/05/example-738-kaplan-meier-survival.html + // http://sas-and-r.blogspot.fr/2010/05/example-739-nelson-aalen-estimate-of.html + + double[] times; + SurvivalOutcome[] censor; + CreateExample1(out times, out censor); + + // Test with Breslow method + + { + var distribution = EmpiricalHazardDistribution.Estimate(times, censor, HazardTiesMethod.Breslow); + + double[] expectedCHF = + { + 0.0000000, 0.1111111, 0.1111111, 0.1736111, 0.1736111, 0.2450397, 0.3219628, + 0.3219628, 0.4128719, 0.4128719, 0.5239830, 0.6489830, 0.6489830, 0.8156496, + 1.0156496, 1.0156496, 1.0156496, 1.5156496, 1.5156496 + }; + + double[] actualCHF = times.Apply(distribution.CumulativeHazardFunction); + + for (int i = 0; i < actualCHF.Length; i++) + Assert.AreEqual(expectedCHF[i], actualCHF[i], 1e-6); + + + //Assert.AreEqual(11.177, distribution.Mean); + Assert.AreEqual(12, distribution.Median, 1e-5); + } + + // Test with Effron method + { + var distribution = EmpiricalHazardDistribution.Estimate(times, censor); + + double[] expectedCHF = + { + 0.0000000, 0.1111111, 0.1111111, 0.1756496, 0.1756496, 0.2497576, 0.3298003, + 0.3298003, 0.4251104, 0.4251104, 0.5428935, 0.6764249, 0.6764249, 0.8587464, + 1.0818900, 1.0818900, 1.0818900, 1.7750372, 1.7750372 + }; + + double[] actualCHF = times.Apply(distribution.CumulativeHazardFunction); + + for (int i = 0; i < actualCHF.Length; i++) + Assert.AreEqual(expectedCHF[i], actualCHF[i], 1e-6); + + + //Assert.AreEqual(11.177, distribution.Mean); + Assert.AreEqual(12, distribution.Median, 1e-5); + } + } + + [Test] + public void ConstructorTest1() + { + double[] times; + SurvivalOutcome[] censor; + CreateExample1(out times, out censor); + + var distribution = EmpiricalHazardDistribution.Estimate(times, censor, + SurvivalEstimator.FlemingHarrington, HazardEstimator.BreslowNelsonAalen); + + double[] t = distribution.Times; + double[] s = distribution.Survivals; + double[] h = distribution.Hazards; + + double[] nt = distribution.Times.Distinct(); + double[] nh = nt.Apply(distribution.HazardFunction); + + var target = new EmpiricalHazardDistribution(nt, nh, SurvivalEstimator.FlemingHarrington); + + for (int i = 0; i < times.Length; i++) + { + double expected = distribution.HazardFunction(times[i]); + double actual = target.HazardFunction(times[i]); + Assert.AreEqual(expected, actual); + } + + for (int i = 0; i < times.Length; i++) + { + double expected = distribution.CumulativeHazardFunction(times[i]); + double actual = target.CumulativeHazardFunction(times[i]); + Assert.AreEqual(expected, actual, 1e-5); + } + + for (int i = 0; i < times.Length; i++) + { + double expected = distribution.ProbabilityDensityFunction(times[i]); + double actual = target.ProbabilityDensityFunction(times[i]); + Assert.AreEqual(expected, actual, 1e-5); + } + } + + private static void CreateExample1(out double[] times, out SurvivalOutcome[] censor) + { + // Example from http://sas-and-r.blogspot.fr/2010/05/example-738-kaplan-meier-survival.html + + object[,] data = + { + // time event + { 0.5, false }, + { 1, true }, + { 1, true }, + { 2, true }, + { 2, false }, + { 3, true }, + { 4, true }, + { 5, false }, + { 6, true }, + { 7, false }, + { 8, true }, + { 9, true }, + { 10, false }, + { 12, true }, + { 14, false }, + { 14, true }, + { 17, false }, + { 20, true }, + { 21, false }, + }; + + times = data.GetColumn(0).To(); + censor = data.GetColumn(1).To(); + } + + [Test] + public void MeasuresTest_KaplanMeier() + { + double[] values = + { + 0.0000000000000000, 0.0351683340828711, 0.0267358118285064, + 0.0000000000000000, 0.0103643094219679, 0.9000000000000000, + 0.0000000000000000, 0.0000000000000000, 0.0000000000000000, + 0.000762266794052363, 0.000000000000000 + }; + + double[] times = + { + 11, 1, 9, 8, 7, 3, 6, 5, 4, 2, 10 + }; + + var target = new EmpiricalHazardDistribution(times, values, SurvivalEstimator.KaplanMeier); + var general = new GeneralContinuousDistribution(target); + + //Assert.AreEqual(general.Mean, target.Mean); + //Assert.AreEqual(general.Variance, target.Variance); + Assert.AreEqual(general.Median, target.Median); + + for (int i = -10; i < 10; i++) + { + double x = i; + double expected = general.CumulativeHazardFunction(x); + double actual = target.CumulativeHazardFunction(x); + Assert.AreEqual(expected, actual, 1e-4); + } + + for (int i = -10; i < 10; i++) + { + double x = i; + double expected = general.HazardFunction(x); + double actual = target.HazardFunction(x); + Assert.AreEqual(expected, actual, 1e-5); + } + } + + [Test] + public void MedianTest_KaplanMeier() + { + double[] values = + { + 0.0000000000000000, 0.0351683340828711, 0.0267358118285064, + 0.0000000000000000, 0.0103643094219679, 0.0000000000000000, + 0.0000000000000000, 0.0000000000000000, 0.0000000000000000, + 0.000762266794052363, 0.000000000000000 + }; + + double[] times = + { + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 + }; + + + var target = new EmpiricalHazardDistribution(times, values, SurvivalEstimator.KaplanMeier); + + Assert.AreEqual(target.Median, target.InverseDistributionFunction(0.5)); + + + Assert.AreEqual(1, target.ComplementaryDistributionFunction(0)); + Assert.AreEqual(0, target.ComplementaryDistributionFunction(Double.PositiveInfinity)); + } + + [Test] + public void DistributionFunctionTest2_KaplanMeier() + { + + double[] values = + { + 0.0000000000000000, 0.0351683340828711, 0.0267358118285064, + 0.0000000000000000, 0.0103643094219679, 0.0000000000000000, + 0.0000000000000000, 0.0000000000000000, 0.0000000000000000, + 0.000762266794052363, 0.000000000000000 + }; + + double[] times = + { + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 + }; + + + var target = new EmpiricalHazardDistribution(times, values, SurvivalEstimator.KaplanMeier); + + double[] expected = + { + 1.000000000000000, + 0.999238023657475, + 0.999238023657475, + 0.999238023657475, + 0.999238023657475, + 0.999238023657475, + 0.98893509519066469, + 0.98893509519066469, + 0.96284543081744489, + 0.92957227114936058, + 0.92957227114936058, + }; + + + double[] hazardFunction = new double[expected.Length]; + double[] survivalFunction = new double[expected.Length]; + + for (int i = 0; i < 11; i++) + hazardFunction[i] = target.CumulativeHazardFunction(i + 1); + + for (int i = 0; i < 11; i++) + survivalFunction[i] = target.ComplementaryDistributionFunction(i + 1); + + + for (int i = 0; i < expected.Length; i++) + { + Assert.AreEqual(expected[i], survivalFunction[i], 1e-3); + + // Ho = -log(So) + Assert.AreEqual(hazardFunction[i], -Math.Log(survivalFunction[i]), 1e-5); + + // So = exp(-Ho) + Assert.AreEqual(survivalFunction[i], Math.Exp(-hazardFunction[i]), 1e-5); + } + + + Assert.AreEqual(1, target.ComplementaryDistributionFunction(0)); + Assert.AreEqual(0, target.ComplementaryDistributionFunction(Double.PositiveInfinity)); + } + } +} diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/ExponentialDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/ExponentialDistributionTest.cs index 84e9428bd..c8542de48 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/ExponentialDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/ExponentialDistributionTest.cs @@ -23,13 +23,13 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Moving; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics; using Accord.Statistics.Distributions.Univariate; using System.Globalization; using System.Threading; - [TestClass()] + [TestFixture] public class ExponentialDistributionTest { @@ -49,7 +49,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest() { ExponentialDistribution n = new ExponentialDistribution(3.42521); @@ -58,7 +58,7 @@ public void ConstructorTest() Assert.AreEqual(0.085236497078375897, n.Variance); } - [TestMethod()] + [Test] public void ConstructorTest2() { var exp = new ExponentialDistribution(rate: 0.42); @@ -105,7 +105,7 @@ public void ConstructorTest2() Assert.AreEqual(10.964690919019265, range3.Max); } - [TestMethod()] + [Test] public void ProbabilityDistributionTest() { ExponentialDistribution n = new ExponentialDistribution(3); @@ -123,7 +123,7 @@ public void ProbabilityDistributionTest() } } - [TestMethod()] + [Test] public void ProbabilityDistributionTest2() { ExponentialDistribution n = new ExponentialDistribution(0.42); @@ -142,7 +142,7 @@ public void ProbabilityDistributionTest2() } - [TestMethod()] + [Test] public void CumulativeDistributionTest() { ExponentialDistribution n = new ExponentialDistribution(3); @@ -160,7 +160,7 @@ public void CumulativeDistributionTest() } } - [TestMethod()] + [Test] public void MedianTest() { ExponentialDistribution target = new ExponentialDistribution(2.5); @@ -168,7 +168,7 @@ public void MedianTest() Assert.AreEqual(target.Median, target.InverseDistributionFunction(0.5)); } - [TestMethod()] + [Test] public void GenerateTest() { ExponentialDistribution target = new ExponentialDistribution(2.5); @@ -181,7 +181,7 @@ public void GenerateTest() Assert.AreEqual(2.5, actual.Rate, 0.01); } - [TestMethod()] + [Test] public void GenerateTest2() { ExponentialDistribution target = new ExponentialDistribution(2.5); @@ -196,7 +196,7 @@ public void GenerateTest2() Assert.AreEqual(2.5, actual.Rate, 0.01); } - [TestMethod()] + [Test] public void FitTest1() { double[] values = diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/FDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/FDistributionTest.cs index 463d0a513..67b93d776 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/FDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/FDistributionTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System.Globalization; - [TestClass()] + [TestFixture] public class FDistributionTest { @@ -46,7 +46,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest() { var F = new FDistribution(degrees1: 8, degrees2: 5); @@ -93,7 +93,7 @@ public void ConstructorTest() Assert.AreEqual(10.289311046135927, range3.Max); } - [TestMethod()] + [Test] public void MeanVarianceTest() { int[] d = { 1, 2, 3, 4, 5 }; @@ -114,7 +114,7 @@ public void MeanVarianceTest() } } - [TestMethod()] + [Test] public void DistributionFunctionTest() { FDistribution f = new FDistribution(2, 3); @@ -128,7 +128,7 @@ public void DistributionFunctionTest() Assert.AreEqual(expected, actual, 1e-6); } - [TestMethod()] + [Test] public void MedianTest() { FDistribution target = new FDistribution(2, 3); @@ -136,7 +136,7 @@ public void MedianTest() Assert.AreEqual(target.Median, target.InverseDistributionFunction(0.5)); } - [TestMethod()] + [Test] public void DistributionFunctionTest2() { double actual; @@ -162,7 +162,7 @@ public void DistributionFunctionTest2() } } - [TestMethod()] + [Test] public void ComplementaryDistributionFunctionTest() { double actual; @@ -188,7 +188,7 @@ public void ComplementaryDistributionFunctionTest() } } - [TestMethod()] + [Test] public void DistributionFunctionTest3() { @@ -211,7 +211,7 @@ public void DistributionFunctionTest3() } } - [TestMethod()] + [Test] public void ProbabilityDistributionFunctionTest() { FDistribution f = new FDistribution(2, 3); @@ -222,7 +222,7 @@ public void ProbabilityDistributionFunctionTest() Assert.AreEqual(expected, actual, 1e-6); } - [TestMethod()] + [Test] public void LogProbabilityDistributionFunctionTest() { FDistribution f = new FDistribution(2, 3); @@ -235,7 +235,7 @@ public void LogProbabilityDistributionFunctionTest() - [TestMethod()] + [Test] public void ProbabilityDistributionFunctionTest2() { FDistribution f = new FDistribution(2, 2); @@ -254,7 +254,7 @@ public void ProbabilityDistributionFunctionTest2() Assert.AreEqual(new FDistribution(10, 10).ProbabilityDensityFunction(3), 0.0487, 1e-4); } - [TestMethod()] + [Test] public void LogProbabilityDistributionFunctionTest2() { FDistribution f = new FDistribution(2, 2); @@ -280,7 +280,7 @@ public void LogProbabilityDistributionFunctionTest2() } } - [TestMethod()] + [Test] public void InverseDistributionFunctionTest() { diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/FoldedNormalDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/FoldedNormalDistributionTest.cs index 6b4fafa6c..579021354 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/FoldedNormalDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/FoldedNormalDistributionTest.cs @@ -27,9 +27,9 @@ namespace Accord.Tests.Statistics using Accord.Statistics; using Accord.Statistics.Distributions.Multivariate; using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class FoldedNormalDistributionTest { @@ -50,7 +50,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest() { var fn = new FoldedNormalDistribution(mean: 4, stdDev: 4.2); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/GammaDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/GammaDistributionTest.cs index 65b537e86..749303988 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/GammaDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/GammaDistributionTest.cs @@ -22,13 +22,12 @@ namespace Accord.Tests.Statistics { - using System; using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; + using System; using System.Globalization; - using Accord.Math; - [TestClass()] + [TestFixture] public class GammaDistributionTest { @@ -49,16 +48,16 @@ public TestContext TestContext - [TestMethod()] + [Test] public void GammaDistributionConstructorTest() { double shape = 0.4; double scale = 4.2; - double[] expected = - { - double.NegativeInfinity, 0.987114, 0.635929, 0.486871, 0.400046, - 0.341683, 0.299071, 0.266236, 0.239956, 0.218323, 0.200126 + double[] expected = + { + double.NegativeInfinity, 0.987114, 0.635929, 0.486871, 0.400046, + 0.341683, 0.299071, 0.266236, 0.239956, 0.218323, 0.200126 }; GammaDistribution target = new GammaDistribution(scale, shape); @@ -70,7 +69,7 @@ public void GammaDistributionConstructorTest() Assert.AreEqual(shape * scale * scale, target.Variance); } - [TestMethod()] + [Test] public void GammaDistributionConstructorTest2() { var gamma = new GammaDistribution(theta: 4, k: 2); @@ -119,7 +118,7 @@ public void GammaDistributionConstructorTest2() Assert.AreEqual(26.553408271975243, range3.Max); } - [TestMethod()] + [Test] public void MedianTest() { double shape = 0.4; @@ -130,16 +129,16 @@ public void MedianTest() Assert.AreEqual(target.Median, target.InverseDistributionFunction(0.5)); } - [TestMethod()] + [Test] public void DensityFunctionTest() { double shape = 0.4; double scale = 4.2; - double[] pdf = - { - double.PositiveInfinity, 0.987114, 0.635929, 0.486871, 0.400046, - 0.341683, 0.299071, 0.266236, 0.239956, 0.218323, 0.200126 + double[] pdf = + { + double.PositiveInfinity, 0.987114, 0.635929, 0.486871, 0.400046, + 0.341683, 0.299071, 0.266236, 0.239956, 0.218323, 0.200126 }; GammaDistribution target = new GammaDistribution(scale, shape); @@ -161,16 +160,16 @@ public void DensityFunctionTest() } } - [TestMethod()] + [Test] public void CumulativeFunctionTest() { double shape = 0.4; double scale = 4.2; - double[] cdf = - { - 0, 0.251017, 0.328997, 0.38435, 0.428371, 0.465289, - 0.497226, 0.525426, 0.55069, 0.573571, 0.594469 + double[] cdf = + { + 0, 0.251017, 0.328997, 0.38435, 0.428371, 0.465289, + 0.497226, 0.525426, 0.55069, 0.573571, 0.594469 }; GammaDistribution target = new GammaDistribution(scale, shape); @@ -186,7 +185,7 @@ public void CumulativeFunctionTest() } } - [TestMethod()] + [Test] public void GenerateTest2() { Accord.Math.Tools.SetupGenerator(0); @@ -202,7 +201,7 @@ public void GenerateTest2() Assert.AreEqual(2, actual.Shape, 0.01); } - [TestMethod()] + [Test] public void GenerateTest3() { Accord.Math.Tools.SetupGenerator(1); @@ -221,7 +220,7 @@ public void GenerateTest3() } - [TestMethod()] + [Test] public void NegativeValueTest() { double[] samples = NormalDistribution.Standard.Generate(100); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/GeneralContinuousDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/GeneralContinuousDistributionTest.cs index 236a49ddd..905aaeee5 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/GeneralContinuousDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/GeneralContinuousDistributionTest.cs @@ -23,29 +23,15 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; + using Accord.Math; - [TestClass()] + [TestFixture] public class GeneralContinuousDistributionTest { - - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - [TestMethod()] + [Test] public void UsageTest() { // Let's suppose we have a formula that defines a probability distribution @@ -108,7 +94,7 @@ public void UsageTest() Assert.AreEqual(14.770661223067844, range3.Max); } - [TestMethod()] + [Test] public void ConstructorTest0() { var original = new NormalDistribution(mean: 4, stdDev: 4.2); @@ -121,7 +107,7 @@ public void ConstructorTest0() testNormal(normal, 1); } - [TestMethod()] + [Test] public void ConstructorTest1() { var original = new NormalDistribution(mean: 4, stdDev: 4.2); @@ -141,7 +127,7 @@ public void ConstructorTest1() testNormal(normal, 1e3); } - [TestMethod()] + [Test] public void ConstructorTest2() { var original = new NormalDistribution(mean: 4, stdDev: 4.2); @@ -154,8 +140,8 @@ public void ConstructorTest2() double expected = original.DistributionFunction(i); double actual = normal.DistributionFunction(i); - double diff = Math.Abs(expected - actual); - Assert.AreEqual(expected, actual, 1e-6); + double diff = Math.Abs(expected - actual) / expected; + Assert.IsTrue(diff < 1e-7); } testNormal(normal, 1); @@ -191,7 +177,7 @@ private static void testNormal(GeneralContinuousDistribution normal, double prec Assert.AreEqual(1.4, icdf, 1e-7 * prec); } - [TestMethod()] + [Test] public void ConstructorTest3() { var original = new InverseGaussianDistribution(mean: 0.42, shape: 1.2); @@ -211,7 +197,7 @@ public void ConstructorTest3() testInvGaussian(invGaussian); } - [TestMethod()] + [Test] public void ConstructorTest4() { var original = new InverseGaussianDistribution(mean: 0.42, shape: 1.2); @@ -251,7 +237,7 @@ private static void testInvGaussian(GeneralContinuousDistribution invGaussian) Assert.AreEqual(0.26999999957543408, icdf, 1e-6); } - [TestMethod()] + [Test] public void ConstructorTest6() { var original = new LaplaceDistribution(location: 4, scale: 2); @@ -264,14 +250,13 @@ public void ConstructorTest6() double expected = original.ProbabilityDensityFunction(i); double actual = laplace.ProbabilityDensityFunction(i); - double diff = Math.Abs(expected - actual); - Assert.AreEqual(expected, actual, 1e-6); + Assert.IsTrue(expected.IsRelativelyEqual(actual, 1e-4)); } testLaplace(laplace); } - [TestMethod()] + [Test] public void ConstructorTest7() { var original = new LaplaceDistribution(location: 4, scale: 2); @@ -284,8 +269,7 @@ public void ConstructorTest7() double expected = original.DistributionFunction(i); double actual = laplace.DistributionFunction(i); - double diff = Math.Abs(expected - actual); - Assert.AreEqual(expected, actual, 1e-5); + Assert.IsTrue(expected.IsRelativelyEqual(actual, 1e-5)); Assert.IsFalse(Double.IsNaN(expected)); Assert.IsFalse(Double.IsNaN(actual)); } @@ -321,7 +305,7 @@ private static void testLaplace(GeneralContinuousDistribution laplace) Assert.AreEqual(0.26999999840794775, icdf, 1e-6); } - [TestMethod()] + [Test] public void MedianTest() { var laplace = new LaplaceDistribution(location: 2, scale: 0.42); @@ -339,7 +323,7 @@ public void MedianTest() Assert.AreEqual(laplace.Median, target.Median, 1e-10); } - [TestMethod()] + [Test] public void ConstructorTest8() { var original = new LognormalDistribution(location: 0.42, shape: 1.1); @@ -352,8 +336,8 @@ public void ConstructorTest8() double expected = original.DistributionFunction(i); double actual = log.DistributionFunction(i); - double diff = Math.Abs(expected - actual); - Assert.AreEqual(expected, actual, 1e-2); + Assert.IsTrue(expected.IsRelativelyEqual(actual, 1e-2)); + Assert.IsFalse(Double.IsNaN(expected)); Assert.IsFalse(Double.IsNaN(actual)); } @@ -361,7 +345,7 @@ public void ConstructorTest8() testLognormal(log); } - [TestMethod()] + [Test] public void ConstructorTest9() { var original = new LognormalDistribution(location: 0.42, shape: 1.1); @@ -374,7 +358,8 @@ public void ConstructorTest9() double expected = original.ProbabilityDensityFunction(i); double actual = log.ProbabilityDensityFunction(i); - double diff = Math.Abs(expected - actual); + Assert.IsTrue(expected.IsRelativelyEqual(actual, 1e-7)); + Assert.AreEqual(expected, actual, 1e-8); } @@ -410,7 +395,7 @@ private static void testLognormal(GeneralContinuousDistribution log) Assert.AreEqual(0.26999997937815973, icdf, 1e-5); } - [TestMethod()] + [Test] public void ConstructorTest10() { var original = new ChiSquareDistribution(degreesOfFreedom: 7); @@ -423,8 +408,7 @@ public void ConstructorTest10() double expected = original.ProbabilityDensityFunction(i); double actual = chisq.ProbabilityDensityFunction(i); - double diff = Math.Abs(expected - actual); - Assert.AreEqual(expected, actual, 1e-8); + Assert.IsTrue(expected.IsRelativelyEqual(actual, 1e-7)); Assert.IsFalse(Double.IsNaN(actual)); Assert.IsFalse(Double.IsNaN(expected)); } @@ -432,7 +416,7 @@ public void ConstructorTest10() testChiSquare(chisq); } - [TestMethod()] + [Test] public void ConstructorTest11() { var original = new ChiSquareDistribution(degreesOfFreedom: 7); @@ -445,8 +429,7 @@ public void ConstructorTest11() double expected = original.DistributionFunction(i); double actual = chisq.DistributionFunction(i); - double diff = Math.Abs(expected - actual); - Assert.AreEqual(expected, actual, 1e-6); + Assert.IsTrue(expected.IsRelativelyEqual(actual, 1e-5)); Assert.IsFalse(Double.IsNaN(actual)); Assert.IsFalse(Double.IsNaN(expected)); } @@ -482,7 +465,7 @@ private static void testChiSquare(GeneralContinuousDistribution chisq) Assert.AreEqual(6.2700000000852318, icdf, 1e-6); } - [TestMethod()] + [Test] public void ConstructorTest12() { var original = new GompertzDistribution(eta: 4.2, b: 1.1); @@ -495,8 +478,7 @@ public void ConstructorTest12() double expected = original.DistributionFunction(i); double actual = gompertz.DistributionFunction(i); - double diff = Math.Abs(expected - actual); - Assert.AreEqual(expected, actual, 1e-3); + Assert.IsTrue(expected.IsRelativelyEqual(actual, 1e-3)); Assert.IsFalse(double.IsNaN(expected)); Assert.IsFalse(double.IsNaN(actual)); } @@ -504,7 +486,7 @@ public void ConstructorTest12() testGompertz(gompertz); } - [TestMethod()] + [Test] public void ConstructorTest13() { var original = new GompertzDistribution(eta: 4.2, b: 1.1); @@ -517,8 +499,7 @@ public void ConstructorTest13() double expected = original.DistributionFunction(i); double actual = gompertz.DistributionFunction(i); - double diff = Math.Abs(expected - actual); - Assert.AreEqual(expected, actual, 1e-3); + Assert.IsTrue(expected.IsRelativelyEqual(actual, 1e-7)); Assert.IsFalse(double.IsNaN(expected)); Assert.IsFalse(double.IsNaN(actual)); } @@ -550,7 +531,7 @@ private static void testGompertz(GeneralContinuousDistribution gompertz) Assert.AreEqual(0.26999999999766749, icdf, 1e-5); } - [TestMethod()] + [Test] public void ConstructorTest14() { var original = new NakagamiDistribution(shape: 2.4, spread: 4.2); @@ -563,8 +544,7 @@ public void ConstructorTest14() double expected = original.ProbabilityDensityFunction(i); double actual = nakagami.ProbabilityDensityFunction(i); - double diff = Math.Abs(expected - actual); - Assert.AreEqual(expected, actual, 1e-3); + Assert.IsTrue(expected.IsRelativelyEqual(actual, 0.8)); Assert.IsFalse(double.IsNaN(expected)); Assert.IsFalse(double.IsNaN(actual)); } @@ -572,7 +552,7 @@ public void ConstructorTest14() testNakagami(nakagami); } - [TestMethod()] + [Test] public void ConstructorTest15() { var original = new NakagamiDistribution(shape: 2.4, spread: 4.2); @@ -585,8 +565,7 @@ public void ConstructorTest15() double expected = original.DistributionFunction(i); double actual = nakagami.DistributionFunction(i); - double diff = Math.Abs(expected - actual); - Assert.AreEqual(expected, actual, 1e-3); + Assert.IsTrue(expected.IsRelativelyEqual(actual, 1e-2)); Assert.IsFalse(double.IsNaN(expected)); Assert.IsFalse(double.IsNaN(actual)); } @@ -622,7 +601,7 @@ private static void testNakagami(GeneralContinuousDistribution nakagami) Assert.AreEqual(1.40, icdf, 1e-7); } - [TestMethod()] + [Test] public void ConstructorTest16() { var original = new VonMisesDistribution(mean: 0.42, concentration: 1.2); @@ -633,7 +612,7 @@ public void ConstructorTest16() testVonMises(vonMises, 100); } - [TestMethod()] + [Test] public void ConstructorTest17() { var original = new VonMisesDistribution(mean: 0.42, concentration: 1.2); @@ -646,8 +625,7 @@ public void ConstructorTest17() double expected = original.ProbabilityDensityFunction(i); double actual = vonMises.ProbabilityDensityFunction(i); - double diff = Math.Abs(expected - actual); - Assert.AreEqual(expected, actual, 1e-6); + Assert.IsTrue(expected.IsRelativelyEqual(actual, 1e-4)); } testVonMises(vonMises, 1); @@ -685,7 +663,7 @@ private static void testVonMises(GeneralContinuousDistribution vonMises, double Assert.AreEqual(1.39999999999, icdf, 1e-8 * prec); } - [TestMethod()] + [Test] public void InverseDistributionFunctionTest() { double[] expected = @@ -709,7 +687,7 @@ public void InverseDistributionFunctionTest() } - [TestMethod()] + [Test] public void MedianTest2() { NormalDistribution original = new NormalDistribution(0.4, 2.2); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/GeneralizedBetaDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/GeneralizedBetaDistributionTest.cs index ecb3c7cbf..26e9e0e6a 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/GeneralizedBetaDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/GeneralizedBetaDistributionTest.cs @@ -22,35 +22,18 @@ namespace Accord.Tests.Statistics { + using Accord.Math; using Accord.Statistics.Distributions.Fitting; using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; - using Accord.Math; - using Accord.Math.Differentiation; - [TestClass()] + [TestFixture] public class GeneralizedBetaDistributionTest { - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - - [TestMethod()] + [Test] public void BetaDistributionConstructorTest() { double expected, actual; @@ -84,7 +67,7 @@ public void BetaDistributionConstructorTest() } } - [TestMethod()] + [Test] public void MedianTest() { double alpha = 0.42; @@ -95,7 +78,7 @@ public void MedianTest() Assert.AreEqual(target.Median, target.InverseDistributionFunction(0.5)); } - [TestMethod()] + [Test] public void BetaMeanTest() { double alpha = 0.42; @@ -145,7 +128,7 @@ public void BetaMeanTest() Assert.AreEqual(0.89625688707910811, range3.Max); } - [TestMethod()] + [Test] public void NoncentralBetaMeanTest() { // Create a 4-parameter Beta distribution with the following parameters (α, β, a, b): @@ -197,7 +180,7 @@ public void NoncentralBetaMeanTest() Assert.AreEqual(4.0728683052205534, range3.Max); } - [TestMethod()] + [Test] public void BetaPERTTest() { // Create a Beta from a minimum, maximum and most likely value @@ -227,7 +210,7 @@ public void BetaPERTTest() Assert.AreEqual(3, beta); } - [TestMethod()] + [Test] public void BetaPERTTest2() { // Create a Beta from a minimum, maximum and most likely value @@ -253,7 +236,7 @@ public void BetaPERTTest2() Assert.AreEqual(3.9999999999999982, beta); } - [TestMethod()] + [Test] public void BetaVosePERTTest() { // Create a Beta from a minimum, maximum and most likely value @@ -279,16 +262,16 @@ public void BetaVosePERTTest() Assert.AreEqual(4.6137173333333337, beta); } - [TestMethod()] + [Test] public void BetaVosePERTTest_ModeEqualMean() { // Create a Beta from a minimum, maximum and most likely value var b = GeneralizedBetaDistribution.Vose(min: 1, max: 3, mode: 2); - double mean = b.Mean; - double median = b.Median; - double var = b.Variance; - double mode = b.Mode; + double mean = b.Mean; + double median = b.Median; + double var = b.Variance; + double mode = b.Mode; double min = b.Min; double max = b.Max; @@ -308,7 +291,7 @@ public void BetaVosePERTTest_ModeEqualMean() Assert.AreEqual(4, beta); } - [TestMethod()] + [Test] public void BetaMeanTest2() { int trials = 161750; @@ -330,7 +313,7 @@ public void BetaMeanTest2() Assert.AreEqual("B(x; α = 10008, β = 151744, min = 0, max = 1)", str); } - [TestMethod()] + [Test] public void BetaMeanTest3() { int trials = 100; @@ -354,7 +337,7 @@ public void BetaMeanTest3() Assert.AreEqual(0.84983461640764513, p975, 1e-6); } - [TestMethod()] + [Test] public void BetaFitTest1() { double[] x = { 0.1, 0.5, 0.3, 0.8, 0.6, 0.7, 0.9, 0.9, 0.9, 0.9 }; @@ -367,7 +350,7 @@ public void BetaFitTest1() Assert.AreEqual(0.60843093922651903, target.Beta, 1e-10); } - [TestMethod()] + [Test] public void BetaFit_RealWeights() { double[] x = { 1.0, 0.1, 0.5, 0.3, 0.5, 0.8, 0.6, 0.7, 0.9, 0.9, 0.9 }; @@ -381,14 +364,13 @@ public void BetaFit_RealWeights() Assert.AreEqual(0.58735469613259694, target.Beta); } - [TestMethod()] + [Test] public void BetaFit_IntWeights() { double[] x = { 1.0, 0.1, 0.5, 0.3, 0.5, 0.8, 0.6, 0.7, 0.9, 0.9, 0.9 }; int[] w = { 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 2 }; var target = new GeneralizedBetaDistribution(1, 1); - var options = new GeneralizedBetaOptions() { Method = BetaEstimationMethod.Moments }; target.Fit(x, w); @@ -396,7 +378,7 @@ public void BetaFit_IntWeights() Assert.AreEqual(0.60843093922651903, target.Beta, 1e-8); } - [TestMethod()] + [Test] public void BetaMLEFitTest1() { double[] x = samples; @@ -420,7 +402,7 @@ public void BetaMLEFitTest1() } } - [TestMethod()] + [Test] public void BetaMLEFit_RealWeights() { double[] x = { 1.0, 0.1, 0.5, 0.3, 0.5, 0.8, 0.6, 0.7, 0.9, 0.9, 0.9 }; @@ -440,7 +422,7 @@ public void BetaMLEFit_RealWeights() Assert.AreEqual(0.58735469613259694, target.Beta); } - [TestMethod()] + [Test] public void BetaMLEFit_IntWeights() { double[] x = { 1.0, 0.1, 0.5, 0.3, 0.5, 0.8, 0.6, 0.7, 0.9, 0.9, 0.9 }; @@ -460,8 +442,45 @@ public void BetaMLEFit_IntWeights() Assert.AreEqual(0.60843093922651903, target.Beta, 1e-10); } - [TestMethod()] - public void BetaGenerateTest() + [Test] + public void BetaGenerateTest1() + { + Accord.Math.Tools.SetupGenerator(0); + + int n = 100000; + + var beta = new GeneralizedBetaDistribution(alpha: 2, beta: 3, min: 0, max: 1); + double[] samples = beta.Generate(samples: n); + + Assert.AreEqual(n, samples.Length); + + var actual = GeneralizedBetaDistribution.Estimate(samples, 0, 1); + + Assert.AreEqual(2, actual.Alpha, 1e-2); + Assert.AreEqual(3, actual.Beta, 1e-2); + } + + [Test] + public void BetaGenerateTest2() + { + Accord.Math.Tools.SetupGenerator(0); + + int n = 100000; + + var beta = new GeneralizedBetaDistribution(alpha: 2, beta: 3, min: 0, max: 1); + double[] samples = new double[n]; + + for (int i = 0; i < n; i++) + samples[i] = beta.Generate(); + + var actual = GeneralizedBetaDistribution.Estimate(samples, 0, 1); + + Assert.AreEqual(2, actual.Alpha, 3e-2); + Assert.AreEqual(3, actual.Beta, 3e-2); + } + + [Test] + public void BetaRandomTest() { Accord.Math.Tools.SetupGenerator(0); @@ -478,8 +497,8 @@ public void BetaGenerateTest() Assert.AreEqual(3, actual.Beta, 1e-2); } - [TestMethod()] - public void BetaGenerateTest2() + [Test] + public void BetaRandomTest2() { Accord.Math.Tools.SetupGenerator(0); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/GeneralizedNormalDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/GeneralizedNormalDistributionTest.cs index 6045f3c6b..ce5d18ae2 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/GeneralizedNormalDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/GeneralizedNormalDistributionTest.cs @@ -1,223 +1,205 @@ -// Accord Unit Tests -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Tests.Statistics -{ - using Accord.Statistics.Distributions.Univariate; - using Accord.Statistics; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using System; - using Accord.Statistics.Distributions.Multivariate; - using System.Globalization; - using Accord.Math; - - [TestClass()] - public class GeneralizedNormalDistributionTest - { - - - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - - [TestMethod()] - public void ConstructorTest1() - { - var normal = new GeneralizedNormalDistribution(location: 1, scale: 5, shape: 0.42); - - double mean = normal.Mean; // 1 - double median = normal.Median; // 1 - double mode = normal.Mode; // 1 - double var = normal.Variance; // 19200.781700666659 - - double cdf = normal.DistributionFunction(x: 1.4); // 0.51076148867681703 - double pdf = normal.ProbabilityDensityFunction(x: 1.4); // 0.024215092283124507 - double lpdf = normal.LogProbabilityDensityFunction(x: 1.4); // -3.7207791921441378 - - double ccdf = normal.ComplementaryDistributionFunction(x: 1.4); // 0.48923851132318297 - double icdf = normal.InverseDistributionFunction(p: cdf); // 1.4000000149740108 - - double hf = normal.HazardFunction(x: 1.4); // 0.049495474543966168 - double chf = normal.CumulativeHazardFunction(x: 1.4); // 0.7149051552030572 - - string str = normal.ToString(CultureInfo.InvariantCulture); // GGD(x; μ = 1, α = 5, β = 0.42) - - Assert.AreEqual(1, mean); - Assert.AreEqual(1, median); - Assert.AreEqual(1, mode); - Assert.AreEqual(19200.781700666659, var); - Assert.AreEqual(0.7149051552030572, chf); - Assert.AreEqual(0.51076148867681703, cdf); - Assert.AreEqual(0.024215092283124507, pdf); - Assert.AreEqual(-3.7207791921441378, lpdf); - Assert.AreEqual(0.049495474543966168, hf); - Assert.AreEqual(0.48923851132318297, ccdf); - Assert.AreEqual(1.4000000149740108, icdf); - Assert.AreEqual("GGD(x; μ = 1, α = 5, β = 0.42)", str); - - var range1 = normal.GetRange(0.95); - var range2 = normal.GetRange(0.99); - var range3 = normal.GetRange(0.01); - - Assert.AreEqual(-173.60070095277663, range1.Min); - Assert.AreEqual(175.60070093821949, range1.Max); - Assert.AreEqual(-428.92857248354409, range2.Min); - Assert.AreEqual(430.92857248354375, range2.Max); - Assert.AreEqual(-428.92857248354403, range3.Min); - Assert.AreEqual(430.92857248354375, range3.Max); - } - - [TestMethod()] - public void NormalTest() - { - var target = GeneralizedNormalDistribution.Normal(mean: 0.42, stdDev: 4.2); - var normal = new NormalDistribution(mean: 0.42, stdDev: 4.2); - - test(target, normal); - } - - [TestMethod()] - public void NormalTest2() - { - var target = GeneralizedNormalDistribution.Normal(mean: 0.0, stdDev: 2 / Constants.Sqrt2); - var normal = new NormalDistribution(mean: 0.0, stdDev: 2 / Constants.Sqrt2); - - test(target, normal); - - var support = target.Support; - Assert.AreEqual(normal.Support.Min, support.Min); - Assert.AreEqual(normal.Support.Max, support.Max); - - for (double i = 0.01; i <= 1; i += 0.01) - { - var actual = normal.GetRange(i); - var expected = normal.GetRange(i); - - Assert.AreEqual(expected.Min, actual.Min); - Assert.AreEqual(expected.Max, actual.Max); - } - } - - [TestMethod()] - public void SupportTest1() - { - var target = new GeneralizedNormalDistribution(0.0, 10, 2); - - var range = target.Support; - - Assert.AreEqual(double.NegativeInfinity, range.Min); - Assert.AreEqual(double.PositiveInfinity, range.Max); - } - - [TestMethod()] - public void LaplaceTest() - { - var target = GeneralizedNormalDistribution.Laplace(location: 0.42, scale: 4.2); - var normal = new LaplaceDistribution(location: 0.42, scale: 4.2); - - test(target, normal); - - var support = target.Support; - Assert.AreEqual(normal.Support.Min, support.Min); - Assert.AreEqual(normal.Support.Max, support.Max); - - for (double i = 0.01; i <= 1.0; i += 0.01) - { - var actual = normal.GetRange(i); - var expected = normal.GetRange(i); - - Assert.AreEqual(expected.Min, actual.Min); - Assert.AreEqual(expected.Max, actual.Max); - } - } - - private static void test(GeneralizedNormalDistribution target, UnivariateContinuousDistribution normal) - { - - Assert.AreEqual(normal.Mean, target.Mean); - Assert.AreEqual(normal.Variance, target.Variance, 1e-10); - Assert.AreEqual(normal.Entropy, target.Entropy, 1e-10); - Assert.AreEqual(normal.StandardDeviation, target.StandardDeviation, 1e-10); - Assert.AreEqual(normal.Mode, target.Mode); - Assert.AreEqual(normal.Median, target.Median); - - for (double x = -10; x < 10; x += 0.0001) - { - double actual = target.ProbabilityDensityFunction(x); - double expected = normal.ProbabilityDensityFunction(x); - Assert.AreEqual(expected, actual, 1e-15); - Assert.IsFalse(Double.IsNaN(actual)); - } - - for (double x = -10; x < 10; x += 0.0001) - { - double actual = target.LogProbabilityDensityFunction(x); - double expected = normal.LogProbabilityDensityFunction(x); - Assert.AreEqual(expected, actual, 1e-10); - Assert.IsFalse(Double.IsNaN(actual)); - } - } - - [TestMethod()] - public void DistributionFunctionTest1() - { - var target = GeneralizedNormalDistribution.Normal(mean: 0.42, stdDev: 4.2); - var normal = new NormalDistribution(mean: 0.42, stdDev: 4.2); - - for (double x = -10; x < 10; x += 0.0001) - { - double actual = target.DistributionFunction(x); - double expected = normal.DistributionFunction(x); - Assert.AreEqual(expected, actual, 1e-10); - Assert.IsFalse(Double.IsNaN(actual)); - } - } - - [TestMethod()] - public void DistributionFunctionTest2() - { - var target = GeneralizedNormalDistribution.Laplace(location: 0.42, scale: 4.2); - var normal = new LaplaceDistribution(location: 0.42, scale: 4.2); - - for (double x = -10; x < 10; x += 0.0001) - { - double actual = target.DistributionFunction(x); - double expected = normal.DistributionFunction(x); - Assert.AreEqual(expected, actual, 1e-15); - Assert.IsFalse(Double.IsNaN(actual)); - } - } - - } -} +// Accord Unit Tests +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Tests.Statistics +{ + using Accord.Math; + using Accord.Statistics.Distributions.Univariate; + using NUnit.Framework; + using System; + using System.Globalization; + + [TestFixture] + public class GeneralizedNormalDistributionTest + { + + + [Test] + public void ConstructorTest1() + { + var normal = new GeneralizedNormalDistribution(location: 1, scale: 5, shape: 0.42); + + double mean = normal.Mean; // 1 + double median = normal.Median; // 1 + double mode = normal.Mode; // 1 + double var = normal.Variance; // 19200.781700666659 + + double cdf = normal.DistributionFunction(x: 1.4); // 0.51076148867681703 + double pdf = normal.ProbabilityDensityFunction(x: 1.4); // 0.024215092283124507 + double lpdf = normal.LogProbabilityDensityFunction(x: 1.4); // -3.7207791921441378 + + double ccdf = normal.ComplementaryDistributionFunction(x: 1.4); // 0.48923851132318297 + double icdf = normal.InverseDistributionFunction(p: cdf); // 1.4000000149740108 + + double hf = normal.HazardFunction(x: 1.4); // 0.049495474543966168 + double chf = normal.CumulativeHazardFunction(x: 1.4); // 0.7149051552030572 + + string str = normal.ToString(CultureInfo.InvariantCulture); // GGD(x; μ = 1, α = 5, β = 0.42) + + Assert.AreEqual(1, mean); + Assert.AreEqual(1, median); + Assert.AreEqual(1, mode); + Assert.AreEqual(19200.781700666659, var); + Assert.AreEqual(0.7149051552030572, chf); + Assert.AreEqual(0.51076148867681703, cdf); + Assert.AreEqual(0.024215092283124507, pdf); + Assert.AreEqual(-3.7207791921441378, lpdf); + Assert.AreEqual(0.049495474543966168, hf); + Assert.AreEqual(0.48923851132318297, ccdf); + Assert.AreEqual(1.4000000149740108, icdf); + Assert.AreEqual("GGD(x; μ = 1, α = 5, β = 0.42)", str); + + var range1 = normal.GetRange(0.95); + var range2 = normal.GetRange(0.99); + var range3 = normal.GetRange(0.01); + + Assert.AreEqual(-173.60070095277663, range1.Min); + Assert.AreEqual(175.60070093821949, range1.Max); + Assert.AreEqual(-428.92857248354409, range2.Min); + Assert.AreEqual(430.92857248354375, range2.Max); + Assert.AreEqual(-428.92857248354403, range3.Min); + Assert.AreEqual(430.92857248354375, range3.Max); + } + + [Test] + public void NormalTest() + { + var target = GeneralizedNormalDistribution.Normal(mean: 0.42, stdDev: 4.2); + var normal = new NormalDistribution(mean: 0.42, stdDev: 4.2); + + test(target, normal); + } + + [Test] + public void NormalTest2() + { + var target = GeneralizedNormalDistribution.Normal(mean: 0.0, stdDev: 2 / Constants.Sqrt2); + var normal = new NormalDistribution(mean: 0.0, stdDev: 2 / Constants.Sqrt2); + + test(target, normal); + + var support = target.Support; + Assert.AreEqual(normal.Support.Min, support.Min); + Assert.AreEqual(normal.Support.Max, support.Max); + + for (double i = 0.01; i <= 1; i += 0.01) + { + var actual = normal.GetRange(i); + var expected = normal.GetRange(i); + + Assert.AreEqual(expected.Min, actual.Min); + Assert.AreEqual(expected.Max, actual.Max); + } + } + + [Test] + public void SupportTest1() + { + var target = new GeneralizedNormalDistribution(0.0, 10, 2); + + var range = target.Support; + + Assert.AreEqual(double.NegativeInfinity, range.Min); + Assert.AreEqual(double.PositiveInfinity, range.Max); + } + + [Test] + public void LaplaceTest() + { + var target = GeneralizedNormalDistribution.Laplace(location: 0.42, scale: 4.2); + var normal = new LaplaceDistribution(location: 0.42, scale: 4.2); + + test(target, normal); + + var support = target.Support; + Assert.AreEqual(normal.Support.Min, support.Min); + Assert.AreEqual(normal.Support.Max, support.Max); + + for (double i = 0.01; i <= 1.0; i += 0.01) + { + var actual = normal.GetRange(i); + var expected = normal.GetRange(i); + + Assert.AreEqual(expected.Min, actual.Min); + Assert.AreEqual(expected.Max, actual.Max); + } + } + + private static void test(GeneralizedNormalDistribution target, UnivariateContinuousDistribution normal) + { + + Assert.AreEqual(normal.Mean, target.Mean); + Assert.AreEqual(normal.Variance, target.Variance, 1e-10); + Assert.AreEqual(normal.Entropy, target.Entropy, 1e-10); + Assert.AreEqual(normal.StandardDeviation, target.StandardDeviation, 1e-10); + Assert.AreEqual(normal.Mode, target.Mode); + Assert.AreEqual(normal.Median, target.Median); + + for (double x = -10; x < 10; x += 0.0001) + { + double actual = target.ProbabilityDensityFunction(x); + double expected = normal.ProbabilityDensityFunction(x); + Assert.AreEqual(expected, actual, 1e-15); + Assert.IsFalse(Double.IsNaN(actual)); + } + + for (double x = -10; x < 10; x += 0.0001) + { + double actual = target.LogProbabilityDensityFunction(x); + double expected = normal.LogProbabilityDensityFunction(x); + Assert.AreEqual(expected, actual, 1e-10); + Assert.IsFalse(Double.IsNaN(actual)); + } + } + + [Test] + public void DistributionFunctionTest1() + { + var target = GeneralizedNormalDistribution.Normal(mean: 0.42, stdDev: 4.2); + var normal = new NormalDistribution(mean: 0.42, stdDev: 4.2); + + for (double x = -10; x < 10; x += 0.0001) + { + double actual = target.DistributionFunction(x); + double expected = normal.DistributionFunction(x); + Assert.AreEqual(expected, actual, 1e-10); + Assert.IsFalse(Double.IsNaN(actual)); + } + } + + [Test] + public void DistributionFunctionTest2() + { + var target = GeneralizedNormalDistribution.Laplace(location: 0.42, scale: 4.2); + var normal = new LaplaceDistribution(location: 0.42, scale: 4.2); + + for (double x = -10; x < 10; x += 0.0001) + { + double actual = target.DistributionFunction(x); + double expected = normal.DistributionFunction(x); + Assert.AreEqual(expected, actual, 1e-15); + Assert.IsFalse(Double.IsNaN(actual)); + } + } + + } +} diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/GompertzDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/GompertzDistributionTest.cs index d8fc9f3cf..ffdb3ae22 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/GompertzDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/GompertzDistributionTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics.Testing; - [TestClass()] + [TestFixture] public class GompertzDistributionTest { @@ -46,7 +46,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void ConstructorTest() { var gompertz = new GompertzDistribution(eta: 4.2, b: 1.1); @@ -92,7 +92,7 @@ public void ConstructorTest() Assert.AreEqual(0.67295877422837591, range3.Max, 1e-6); } - [TestMethod()] + [Test] public void ConstructorTest2() { var gompertz = new GompertzDistribution(eta: 0.2, b: 1.1); @@ -127,7 +127,7 @@ public void ConstructorTest2() Assert.AreEqual("Gompertz(x; η = 0.2, b = 1.1)", str); } - [TestMethod()] + [Test] public void ConstructorTest3() { try @@ -145,7 +145,7 @@ public void ConstructorTest3() catch { } } - [TestMethod()] + [Test] public void MedianTest() { var target = new GompertzDistribution(eta: 42, b: 4.2); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/GumbelDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/GumbelDistributionTest.cs index 379c4dbfc..3d7db06d0 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/GumbelDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/GumbelDistributionTest.cs @@ -24,12 +24,12 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; using Accord.Statistics; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Statistics.Distributions.Multivariate; using System.Globalization; - [TestClass()] + [TestFixture] public class GumbelDistributionTest { @@ -50,7 +50,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest1() { var gumbel = new GumbelDistribution(location: 4.795, scale: 1 / 0.392); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/HyperbolicSecantDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/HyperbolicSecantDistributionTest.cs index 2b5816855..c63e808cf 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/HyperbolicSecantDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/HyperbolicSecantDistributionTest.cs @@ -24,9 +24,9 @@ namespace Accord.Tests.Statistics { using System.Globalization; using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class HyperbolicSecantTest { @@ -47,7 +47,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest1() { var sech = new HyperbolicSecantDistribution(); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/InverseChiSquareDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/InverseChiSquareDistributionTest.cs index 60a68c241..db25c987a 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/InverseChiSquareDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/InverseChiSquareDistributionTest.cs @@ -23,11 +23,11 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; using Accord.Statistics.Testing; - [TestClass()] + [TestFixture] public class InverseChiSquareDistributionTest { @@ -47,7 +47,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void ConstructorTest() { var invchisq = new InverseChiSquareDistribution(degreesOfFreedom: 7); @@ -94,7 +94,7 @@ public void ConstructorTest() Assert.AreEqual(18.475307115523773, range3.Max); } - [TestMethod()] + [Test] public void GetRangeTest() { var invchisq = new InverseChiSquareDistribution(degreesOfFreedom: 1); @@ -113,7 +113,7 @@ public void GetRangeTest() Assert.AreEqual(6.6348966014931854, range3.Max); } - [TestMethod()] + [Test] public void GetRangeTest2() { var invchisq = new InverseChiSquareDistribution(degreesOfFreedom: 4200); @@ -130,7 +130,7 @@ public void GetRangeTest2() Assert.AreEqual(4416.1499610177489, range3.Max); } - [TestMethod()] + [Test] public void MedianTest() { var target = new ChiSquareDistribution(degreesOfFreedom: 4); @@ -138,7 +138,7 @@ public void MedianTest() Assert.AreEqual(target.Median, target.InverseDistributionFunction(0.5)); } - [TestMethod()] + [Test] public void ProbabilityDensityFunctionTest() { int degreesOfFreedom; @@ -167,7 +167,7 @@ public void ProbabilityDensityFunctionTest() Assert.AreEqual(expected, actual, 1e-4); } - [TestMethod()] + [Test] public void LogProbabilityDensityFunctionTest() { int degreesOfFreedom; @@ -196,7 +196,7 @@ public void LogProbabilityDensityFunctionTest() Assert.AreEqual(expected, actual, 1e-10); } - [TestMethod()] + [Test] public void DistributionFunctionTest() { int degreesOfFreedom; @@ -219,7 +219,7 @@ public void DistributionFunctionTest() Assert.AreEqual(expected, actual, 1e-4); } - [TestMethod()] + [Test] public void InverseTest() { double expected = 1.8307038053275149991e+01; @@ -227,7 +227,7 @@ public void InverseTest() Assert.AreEqual(expected, actual, 1e-14); } - [TestMethod()] + [Test] public void InverseTest2() { double[] p = diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/InverseGammaDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/InverseGammaDistributionTest.cs index 5271e0717..4c1d0ea17 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/InverseGammaDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/InverseGammaDistributionTest.cs @@ -23,11 +23,11 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using System.Globalization; - [TestClass()] + [TestFixture] public class InverseGammaDistributionTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void InverseGammaDistributionConstructorTest() { double actual, expected; @@ -89,7 +89,7 @@ public void InverseGammaDistributionConstructorTest() } } - [TestMethod()] + [Test] public void InverseGammaDistributionConstructorTest2() { var invGamma = new InverseGammaDistribution(shape: 0.42, scale: 0.5); @@ -138,7 +138,7 @@ public void InverseGammaDistributionConstructorTest2() Assert.AreEqual(38513.540845383861, range3.Max); } - [TestMethod()] + [Test] public void MedianTest() { var target = new InverseGammaDistribution(shape: 4.2, scale: 7.8); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/InverseGaussianTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/InverseGaussianTest.cs index badd62cc1..48ac8e475 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/InverseGaussianTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/InverseGaussianTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System.Globalization; - [TestClass()] + [TestFixture] public class InverseGaussianTest { @@ -46,7 +46,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest2() { var invGaussian = new InverseGaussianDistribution(mean: 0.42, shape: 1.2); @@ -93,7 +93,7 @@ public void ConstructorTest2() Assert.AreEqual(1.2855706686397079, range3.Max); } - [TestMethod()] + [Test] public void ConstructorTest() { InverseGaussianDistribution g = new InverseGaussianDistribution(1.2, 4.2); @@ -104,7 +104,7 @@ public void ConstructorTest() Assert.AreEqual(0.64142698058981851, g.StandardDeviation); } - [TestMethod()] + [Test] public void ProbabilityFunctionTest() { InverseGaussianDistribution g = new InverseGaussianDistribution(1.2, 4.2); @@ -115,7 +115,7 @@ public void ProbabilityFunctionTest() Assert.AreEqual(expected, actual, 1e-6); } - [TestMethod()] + [Test] public void ProbabilityFunctionTest2() { InverseGaussianDistribution g = new InverseGaussianDistribution(4.1, 1.2); @@ -136,7 +136,7 @@ public void ProbabilityFunctionTest2() } - [TestMethod()] + [Test] public void CumulativeFunctionTest() { InverseGaussianDistribution g = new InverseGaussianDistribution(1.2, 4.2); @@ -148,7 +148,7 @@ public void CumulativeFunctionTest() Assert.IsFalse(double.IsNaN(actual)); } - [TestMethod()] + [Test] public void CumulativeFunctionTest2() { InverseGaussianDistribution g = new InverseGaussianDistribution(4.1, 1.2); @@ -168,7 +168,7 @@ public void CumulativeFunctionTest2() } } - [TestMethod()] + [Test] public void MedianTest() { InverseGaussianDistribution target = new InverseGaussianDistribution(6, 2); @@ -176,7 +176,7 @@ public void MedianTest() Assert.AreEqual(target.Median, target.InverseDistributionFunction(0.5)); } - [TestMethod()] + [Test] public void GenerateTest() { InverseGaussianDistribution target = new InverseGaussianDistribution(1, 1); @@ -190,7 +190,7 @@ public void GenerateTest() Assert.AreEqual(1, actual.Shape, 0.01); } - [TestMethod()] + [Test] public void GenerateTest2() { Accord.Math.Tools.SetupGenerator(0); @@ -206,7 +206,7 @@ public void GenerateTest2() Assert.AreEqual(2, actual.Shape, 0.01); } - [TestMethod()] + [Test] public void GenerateTest3() { InverseGaussianDistribution target = new InverseGaussianDistribution(4, 2); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/KolmogorovSmirnovDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/KolmogorovSmirnovDistributionTest.cs index ec1e4fb29..2ea2d4dc1 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/KolmogorovSmirnovDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/KolmogorovSmirnovDistributionTest.cs @@ -24,10 +24,10 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; - [TestClass()] + [TestFixture] public class KolmogorovSmirnovDistributionTest { @@ -47,7 +47,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void ConstructorTest() { var ks = new KolmogorovSmirnovDistribution(samples: 42); @@ -89,7 +89,7 @@ public void ConstructorTest() Assert.AreEqual(0.24612731591151149, range3.Max); } - [TestMethod()] + [Test] public void CumulativeFunctionTest() { for (int i = 0; i < test.Length; i++) @@ -110,7 +110,7 @@ public void CumulativeFunctionTest() } } - [TestMethod()] + [Test] public void CumulativeFunctionTest2() { int n = 7; @@ -121,7 +121,7 @@ public void CumulativeFunctionTest2() Assert.AreEqual(expected, actual, 1e-14); } - [TestMethod()] + [Test] public void SurvivalFunctionTest() { for (int i = 0; i < test.Length; i++) @@ -142,7 +142,7 @@ public void SurvivalFunctionTest() } } - [TestMethod()] + [Test] public void MedianTest() { var target = new KolmogorovSmirnovDistribution(7); @@ -150,7 +150,7 @@ public void MedianTest() Assert.AreEqual(target.Median, target.InverseDistributionFunction(0.5)); } - [TestMethod()] + [Test] public void PelzGoodTest() { double actual; @@ -178,7 +178,7 @@ public void PelzGoodTest() Assert.AreEqual(2.21229903e-15, actual, 1e-23); } - [TestMethod()] + [Test] public void DurbinTest() { double actual; @@ -206,7 +206,7 @@ public void DurbinTest() Assert.AreEqual(2.21236052547566e-15, actual, 1e-27); } - [TestMethod()] + [Test] public void DurbinTest2() { double expected; @@ -225,7 +225,7 @@ public void DurbinTest2() Assert.AreEqual(expected, actual, 1e-12); } - [TestMethod()] + [Test] public void NaN_Test() { var ks = new KolmogorovSmirnovDistribution(samples: 42); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/KumaraswamyDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/KumaraswamyDistributionTest.cs index be7044699..7d4eb4f1d 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/KumaraswamyDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/KumaraswamyDistributionTest.cs @@ -24,28 +24,13 @@ namespace Accord.Tests.Statistics.Distributions.Univariate.Continuous { using System; using System.Globalization; - using Accord.Statistics.Distributions.Univariate.Continuous; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using Accord.Statistics.Distributions.Univariate; + using NUnit.Framework; - [TestClass] + [TestFixture] public class KumaraswamyDistributionTest { - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - [TestMethod] + [Test] public void Constructor_KumaraswamyDistribution_PDF_given_0d2_AND_1d2_Parameters_Moments_matches_R_output() { var kumaraswamyDistribution = new KumaraswamyDistribution(0.2d, 1.2d); @@ -69,7 +54,7 @@ public void Constructor_KumaraswamyDistribution_PDF_given_0d2_AND_1d2_Parameters // values verified in R package = ActuDistns } - [TestMethod()] + [Test] public void Constructor_ExtensiveTestForDocumentation() { // Create a new Kumaraswamy distribution with shape (4,2) diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/LaplaceDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/LaplaceDistributionTest.cs index 60dd6eb63..82e6a083b 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/LaplaceDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/LaplaceDistributionTest.cs @@ -23,11 +23,11 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using System.Globalization; - [TestClass()] + [TestFixture] public class LaplaceDistributionTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void LaplaceDistributionConstructorTest() { { @@ -82,7 +82,7 @@ public void LaplaceDistributionConstructorTest() } } - [TestMethod()] + [Test] public void ConstructorTest2() { var laplace = new LaplaceDistribution(location: 4, scale: 2); @@ -129,7 +129,7 @@ public void ConstructorTest2() Assert.AreEqual(11.824046011144626, range3.Max); } - [TestMethod()] + [Test] public void MedianTest() { var target = new LaplaceDistribution(location: 2, scale: 0.42); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/LevyDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/LevyDistributionTest.cs index 818f34b08..73aabe8a2 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/LevyDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/LevyDistributionTest.cs @@ -27,9 +27,9 @@ namespace Accord.Tests.Statistics using Accord.Statistics; using Accord.Statistics.Distributions.Multivariate; using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class LevyDistributionTest { @@ -50,7 +50,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest() { var levy = new LevyDistribution(location: 1, scale: 4.2); @@ -110,7 +110,7 @@ public void ConstructorTest() Assert.AreEqual(26737.630417446126, range3.Max); } - [TestMethod()] + [Test] public void ConstructorTest2() { var levy = new LevyDistribution(location: 0, scale: 2.4); @@ -171,7 +171,7 @@ public void ConstructorTest2() } - [TestMethod()] + [Test] public void MedianTest1() { // plevy(5.2754624119625602, m=0, s=2.4) @@ -189,7 +189,7 @@ public void MedianTest1() Assert.IsFalse(Double.IsNaN(p)); } - [TestMethod()] + [Test] public void MedianTest2() { // plevy(7.2754624119625602, m=2, s=2.4) diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/LogLogisticDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/LogLogisticDistributionTest.cs index a78839038..e9674ccf6 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/LogLogisticDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/LogLogisticDistributionTest.cs @@ -24,9 +24,9 @@ namespace Accord.Tests.Statistics { using System.Globalization; using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class LogLogisticDistributionTest { @@ -47,7 +47,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest1() { var log = new LogLogisticDistribution(alpha: 0.42, beta: 2.2); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/LogNormalDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/LogNormalDistributionTest.cs index 9472c786a..ac30fb1fc 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/LogNormalDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/LogNormalDistributionTest.cs @@ -23,12 +23,12 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Statistics.Distributions.Fitting; using System.Globalization; - [TestClass()] + [TestFixture] public class LogNormalDistributionTest { @@ -48,7 +48,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void ConstructorTest() { var log = new LognormalDistribution(location: 0.42, shape: 1.1); @@ -96,7 +96,7 @@ public void ConstructorTest() Assert.AreEqual(19.667797655030668, range3.Max); } - [TestMethod()] + [Test] public void LogNormalDistributionConstructorTest() { double location = 9.2; @@ -106,7 +106,7 @@ public void LogNormalDistributionConstructorTest() Assert.AreEqual(shape, target.Shape); } - [TestMethod()] + [Test] public void LogNormalDistributionConstructorTest1() { double location = 4.1; @@ -114,7 +114,7 @@ public void LogNormalDistributionConstructorTest1() Assert.AreEqual(location, target.Location); } - [TestMethod()] + [Test] public void LogNormalDistributionConstructorTest2() { LognormalDistribution target = new LognormalDistribution(); @@ -122,7 +122,7 @@ public void LogNormalDistributionConstructorTest2() Assert.AreEqual(1, target.Shape); } - [TestMethod()] + [Test] public void CloneTest() { LognormalDistribution target = new LognormalDistribution(1.7, 4.2); @@ -138,7 +138,7 @@ public void CloneTest() Assert.AreEqual(target.Variance, clone.Variance); } - [TestMethod()] + [Test] public void DistributionFunctionTest() { LognormalDistribution target = new LognormalDistribution(1.7, 4.2); @@ -150,7 +150,7 @@ public void DistributionFunctionTest() Assert.AreEqual(expected, actual, 1e-15); } - [TestMethod()] + [Test] public void EstimateTest() { double[] observations = { 2, 2, 2, 2, 2 }; @@ -162,7 +162,7 @@ public void EstimateTest() Assert.AreEqual(System.Math.Sqrt(0.1), actual.Shape); } - [TestMethod()] + [Test] public void EstimateTest1() { double[] observations = @@ -181,7 +181,7 @@ public void EstimateTest1() Assert.AreEqual(expectedShape, actual.Shape, 1e-14); } - [TestMethod()] + [Test] public void EstimateTest2() { double[] observations = { 0.04, 0.12, 1.52 }; @@ -193,7 +193,7 @@ public void EstimateTest2() Assert.AreEqual(1.6893403335885702, actual.Shape); } - [TestMethod()] + [Test] public void ProbabilityDensityFunctionTest() { LognormalDistribution target = new LognormalDistribution(1.7, 4.2); @@ -205,7 +205,7 @@ public void ProbabilityDensityFunctionTest() Assert.AreEqual(expected, actual, 1e-15); } - [TestMethod()] + [Test] public void LogProbabilityDensityFunctionTest() { LognormalDistribution target = new LognormalDistribution(1.7, 4.2); @@ -217,7 +217,7 @@ public void LogProbabilityDensityFunctionTest() Assert.AreEqual(expected, actual, 1e-15); } - [TestMethod()] + [Test] public void MeanTest() { LognormalDistribution target = new LognormalDistribution(0.42, 0.56); @@ -226,7 +226,7 @@ public void MeanTest() Assert.IsFalse(Double.IsNaN(actual)); } - [TestMethod()] + [Test] public void StandardTest() { LognormalDistribution actual = LognormalDistribution.Standard; @@ -239,7 +239,7 @@ public void StandardTest() Assert.IsTrue(thrown); } - [TestMethod()] + [Test] public void VarianceTest() { LognormalDistribution target = new LognormalDistribution(0.42, 0.56); @@ -247,7 +247,7 @@ public void VarianceTest() Assert.AreEqual(1.1674914219333172, actual); } - [TestMethod()] + [Test] public void GenerateTest() { Accord.Math.Tools.SetupGenerator(0); @@ -263,7 +263,7 @@ public void GenerateTest() Assert.AreEqual(5, actual.Shape, 0.01); } - [TestMethod()] + [Test] public void GenerateTest2() { LognormalDistribution target = new LognormalDistribution(4, 2); @@ -279,7 +279,7 @@ public void GenerateTest2() Assert.AreEqual(2, actual.Shape, 0.01); } - [TestMethod()] + [Test] public void MedianTest() { LognormalDistribution target = new LognormalDistribution(7, 0.6); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/LogisticDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/LogisticDistributionTest.cs index aef440a8f..e4a6b3790 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/LogisticDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/LogisticDistributionTest.cs @@ -24,9 +24,9 @@ namespace Accord.Tests.Statistics { using System.Globalization; using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class LogisticDistributionTest { @@ -47,7 +47,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest1() { var log = new LogisticDistribution(location: 0.42, scale: 1.2); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/MannWhitneyDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/MannWhitneyDistributionTest.cs index 0e7301921..875c6c31a 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/MannWhitneyDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/MannWhitneyDistributionTest.cs @@ -23,11 +23,11 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Math; - [TestClass()] + [TestFixture] public class MannWhitneyDistributionTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest() { double[] ranks = { 1, 2, 3, 4, 5 }; @@ -97,7 +97,7 @@ public void ConstructorTest() Assert.AreEqual(6.000000194140088, range3.Max); } - [TestMethod()] + [Test] public void ProbabilityDensityFunctionTest() { double[] ranks = { 1, 2, 3, 4, 5 }; @@ -130,7 +130,7 @@ public void ProbabilityDensityFunctionTest() Assert.AreEqual(1, sum); } - [TestMethod()] + [Test] public void DistributionFunctionTest() { double[] ranks = { 1, 2, 3, 4, 5 }; @@ -161,7 +161,7 @@ public void DistributionFunctionTest() } - [TestMethod()] + [Test] public void MedianTest() { double[] ranks = { 1, 1, 2, 3, 4, 7, 5 }; diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/NakagamiDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/NakagamiDistributionTest.cs index e26db6073..36471a960 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/NakagamiDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/NakagamiDistributionTest.cs @@ -23,12 +23,12 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Moving; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics; using Accord.Statistics.Distributions.Univariate; using System.Globalization; - [TestClass()] + [TestFixture] public class NakagamiDistributionTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest() { NakagamiDistribution n = new NakagamiDistribution(0.807602, 12.5); @@ -56,7 +56,7 @@ public void ConstructorTest() Assert.AreEqual(3.1910311525611705, n.Variance); } - [TestMethod()] + [Test] public void ConstructorTest2() { var nakagami = new NakagamiDistribution(shape: 2.4, spread: 4.2); @@ -103,7 +103,7 @@ public void ConstructorTest2() Assert.AreEqual(3.5903316858157317, range3.Max); } - [TestMethod()] + [Test] public void ProbabilityDistributionTest() { NakagamiDistribution n = new NakagamiDistribution(0.807602, 12.5); @@ -121,7 +121,7 @@ public void ProbabilityDistributionTest() } } - [TestMethod()] + [Test] public void CumulativeDistributionTest() { NakagamiDistribution n = new NakagamiDistribution(0.807602, 12.5); @@ -140,7 +140,7 @@ public void CumulativeDistributionTest() } - [TestMethod()] + [Test] public void GenerateTest() { NakagamiDistribution target = new NakagamiDistribution(2, 5); @@ -154,7 +154,7 @@ public void GenerateTest() Assert.AreEqual(5, actual.Spread, 0.01); } - [TestMethod()] + [Test] public void GenerateTest2() { Accord.Math.Tools.SetupGenerator(0); @@ -172,7 +172,7 @@ public void GenerateTest2() Assert.AreEqual(2, actual.Spread, 0.01); } - [TestMethod()] + [Test] public void MedianTest() { NakagamiDistribution target = new NakagamiDistribution(5.42, 1.37); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/NoncentralTDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/NoncentralTDistributionTest.cs index 5baf1b6bb..e749e8975 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/NoncentralTDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/NoncentralTDistributionTest.cs @@ -24,11 +24,11 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using System.Globalization; - [TestClass()] + [TestFixture] public class NoncentralTDistributionTest { @@ -49,7 +49,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void ConstructorTest2() { var distribution = new NoncentralTDistribution( @@ -97,7 +97,7 @@ public void ConstructorTest2() Assert.AreEqual(10.541194525031729, range3.Max); } - [TestMethod()] + [Test] public void DistributionFunctionTest() { double[,] table = @@ -150,7 +150,7 @@ public void DistributionFunctionTest() } } - [TestMethod()] + [Test] public void ProbabilityFunctionTest() { double[,] table = @@ -189,7 +189,7 @@ public void ProbabilityFunctionTest() } - [TestMethod()] + [Test] public void MeanTest() { NoncentralTDistribution target; @@ -219,7 +219,7 @@ public void MeanTest() Assert.AreEqual(312.49612392294557, target.Variance); } - [TestMethod()] + [Test] public void MedianTest() { NoncentralTDistribution target = new NoncentralTDistribution(3.2, 4.57); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/NormalDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/NormalDistributionTest.cs index f960c68a1..308f5242e 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/NormalDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/NormalDistributionTest.cs @@ -27,13 +27,13 @@ namespace Accord.Tests.Statistics using Accord.Statistics; using Accord.Statistics.Distributions.Multivariate; using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class NormalDistributionTest { - [TestMethod()] + [Test] public void ConstructorTest5() { var normal = new NormalDistribution(mean: 4, stdDev: 4.2); @@ -84,7 +84,7 @@ public void ConstructorTest5() Assert.AreEqual(13.770661070971531, range3.Max); } - [TestMethod()] + [Test] public void FitTest() { double expectedMean = 1.125; @@ -109,7 +109,7 @@ public void FitTest() Assert.AreEqual(expectedMean, target.Mean); } - [TestMethod()] + [Test] public void FitTest2() { NormalDistribution target; @@ -124,7 +124,7 @@ public void FitTest2() Assert.IsTrue(thrown); } - [TestMethod()] + [Test] public void ConstructorTest() { double mean = 7; @@ -147,7 +147,7 @@ public void ConstructorTest() Assert.AreEqual(1, target.Variance); } - [TestMethod()] + [Test] public void ConstructorTest2() { bool thrown = false; @@ -158,7 +158,7 @@ public void ConstructorTest2() Assert.IsTrue(thrown); } - [TestMethod()] + [Test] public void ConstructorTest3() { Accord.Math.Tools.SetupGenerator(0); @@ -198,7 +198,7 @@ public void ConstructorTest3() Assert.AreEqual(3.0008, sampleDev, 1e-4); } - [TestMethod()] + [Test] public void ProbabilityDensityFunctionTest() { double x = 3; @@ -214,7 +214,7 @@ public void ProbabilityDensityFunctionTest() Assert.AreEqual(expected, actual, 1e-15); } - [TestMethod()] + [Test] public void ToMultivariateTest() { double x = 3; @@ -237,7 +237,7 @@ public void ToMultivariateTest() Assert.AreEqual(expected, actual, 1e-15); } - [TestMethod()] + [Test] public void ProbabilityDensityFunctionTest2() { double expected, actual; @@ -254,7 +254,7 @@ public void ProbabilityDensityFunctionTest2() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void LogProbabilityDensityFunctionTest() { double x = 3; @@ -270,7 +270,7 @@ public void LogProbabilityDensityFunctionTest() Assert.AreEqual(expected, actual, 1e-15); } - [TestMethod()] + [Test] public void StandardDensityFunctionTest() { for (int i = -100; i < 100; i++) @@ -284,7 +284,7 @@ public void StandardDensityFunctionTest() } } - [TestMethod()] + [Test] public void LogStandardDensityFunctionTest() { for (int i = -100; i < 100; i++) @@ -298,7 +298,7 @@ public void LogStandardDensityFunctionTest() } } - [TestMethod()] + [Test] public void DistributionFunctionTest() { double x = 3; @@ -314,7 +314,7 @@ public void DistributionFunctionTest() Assert.AreEqual(expected, actual, 1e-15); } - [TestMethod()] + [Test] public void DistributionFunctionTest3() { double expected, actual; @@ -339,7 +339,7 @@ public void DistributionFunctionTest3() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void InverseDistributionFunctionTest() { double[] expected = @@ -360,7 +360,7 @@ public void InverseDistributionFunctionTest() } } - [TestMethod()] + [Test] public void ZScoreTest() { double x = 5; @@ -375,7 +375,7 @@ public void ZScoreTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void CloneTest() { NormalDistribution target = new NormalDistribution(0.5, 4.2); @@ -390,7 +390,7 @@ public void CloneTest() } - [TestMethod()] + [Test] public void GenerateTest() { NormalDistribution target = new NormalDistribution(2, 5); @@ -403,7 +403,7 @@ public void GenerateTest() Assert.AreEqual(5, actual.StandardDeviation, 0.01); } - [TestMethod()] + [Test] public void GenerateTest2() { NormalDistribution target = new NormalDistribution(4, 2); @@ -419,7 +419,7 @@ public void GenerateTest2() Assert.AreEqual(2, actual.StandardDeviation, 0.01); } - [TestMethod()] + [Test] public void MedianTest() { NormalDistribution target = new NormalDistribution(0.4, 2.2); @@ -428,7 +428,7 @@ public void MedianTest() } - [TestMethod()] + [Test] public void EstimateTest() { double[] values = { 1 }; diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/ParetoDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/ParetoDistributionTest.cs index 7e56fe05f..351b7e9d5 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/ParetoDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/ParetoDistributionTest.cs @@ -26,9 +26,9 @@ namespace Accord.Tests.Statistics using System.Globalization; using Accord.Math; using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class ParetoDistributionTest { @@ -48,7 +48,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void ConstructorTest() { var pareto = new ParetoDistribution(scale: 0.42, shape: 3); @@ -95,7 +95,7 @@ public void ConstructorTest() Assert.AreEqual(1.9494675279346789, range3.Max, 1e-8); } - [TestMethod()] + [Test] public void ParetoDistributionConstructorTest() { double expected, actual; @@ -139,7 +139,7 @@ public void ParetoDistributionConstructorTest() } } - [TestMethod()] + [Test] public void MedianTest() { var target = new ParetoDistribution(scale: 7.12, shape: 2); @@ -147,7 +147,7 @@ public void MedianTest() Assert.AreEqual(target.Median, target.InverseDistributionFunction(0.5), 1e-6); } - [TestMethod] + [Test] public void FitTest() { var source = new ParetoDistribution(scale: 7.12, shape: 2); @@ -164,7 +164,7 @@ public void FitTest() Assert.AreEqual(2.0, target.Alpha, 1e-2); } - [TestMethod] + [Test] public void FitWeights() { var source = new ParetoDistribution(scale: 7.12, shape: 2); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/PowerLognormalDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/PowerLognormalDistributionTest.cs index c23b031fb..499341bca 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/PowerLognormalDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/PowerLognormalDistributionTest.cs @@ -24,12 +24,12 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; using Accord.Statistics; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Statistics.Distributions.Multivariate; using System.Globalization; - [TestClass()] + [TestFixture] public class PowerLognormalDistributionTest { @@ -50,7 +50,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest1() { var plog = new PowerLognormalDistribution(power: 4.2, shape: 1.2); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/PowerNormalDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/PowerNormalDistributionTest.cs index 11b971461..c975872f3 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/PowerNormalDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/PowerNormalDistributionTest.cs @@ -24,12 +24,12 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; using Accord.Statistics; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Statistics.Distributions.Multivariate; using System.Globalization; - [TestClass()] + [TestFixture] public class PowerNormalDistributionTest { @@ -50,7 +50,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest1() { var pnormal = new PowerNormalDistribution(power: 4.2); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/RayleighDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/RayleighDistributionTest.cs index be11a354a..412643905 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/RayleighDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/RayleighDistributionTest.cs @@ -23,12 +23,12 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Moving; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics; using Accord.Statistics.Distributions.Univariate; using System.Globalization; - [TestClass()] + [TestFixture] public class RayleighDistributionTest { @@ -47,7 +47,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void ConstructorTest() { RayleighDistribution n = new RayleighDistribution(0.807602); @@ -55,7 +55,7 @@ public void ConstructorTest() Assert.AreEqual(0.27993564482286737, n.Variance); } - [TestMethod()] + [Test] public void ConstructorTest2() { var rayleigh = new RayleighDistribution(sigma: 0.42); @@ -103,7 +103,7 @@ public void ConstructorTest2() Assert.AreEqual(1.2746387879926619, range3.Max); } - [TestMethod()] + [Test] public void ProbabilityDistributionTest() { RayleighDistribution n = new RayleighDistribution(0.807602); @@ -121,7 +121,7 @@ public void ProbabilityDistributionTest() } } - [TestMethod()] + [Test] public void CumulativeDistributionTest() { RayleighDistribution n = new RayleighDistribution(0.807602); @@ -140,7 +140,7 @@ public void CumulativeDistributionTest() } - [TestMethod()] + [Test] public void GenerateTest() { Accord.Math.Tools.SetupGenerator(0); @@ -154,7 +154,7 @@ public void GenerateTest() Assert.AreEqual(2.5, actual.Scale, 1e-3); } - [TestMethod()] + [Test] public void GenerateTest2() { Accord.Math.Tools.SetupGenerator(0); @@ -170,7 +170,7 @@ public void GenerateTest2() Assert.AreEqual(4.2, actual.Scale, 1e-3); } - [TestMethod()] + [Test] public void MedianTest() { RayleighDistribution target = new RayleighDistribution(0.52); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/ShapiroWilkDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/ShapiroWilkDistributionTest.cs index a4d206289..70e2011f8 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/ShapiroWilkDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/ShapiroWilkDistributionTest.cs @@ -1,91 +1,91 @@ -// Accord Unit Tests -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Tests.Statistics -{ - - using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using System.Globalization; - - [TestClass()] - public class ShapiroWilkDistributionTest - { - - - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - [TestMethod()] - public void ConstructorTest() - { - // Example from http://www.nag.com/numeric/cl/nagdoc_cl23/pdf/G01/g01ddc.pdf - - double[] a = - { - 0.11, 7.87, 4.61, 10.14, 7.95, 3.14, 0.46, 4.43, - 0.21, 4.75, 0.71, 1.52, 3.24, 0.93, 0.42, 4.97, - 9.53, 4.55, 0.47, 6.66 - }; - - var sw = new ShapiroWilkDistribution(a.Length); - - double expected = 0.0421; - double actual = sw.ComplementaryDistributionFunction(0.9005); - Assert.AreEqual(expected, actual, 1e-4); - } - - [TestMethod()] - public void ConstructorTest2() - { - // Example from http://www.nag.com/numeric/cl/nagdoc_cl23/pdf/G01/g01ddc.pdf - - double[] b = - { - 1.36, 1.14, 2.92, 2.55, 1.46, 1.06, 5.27, 1.11, 3.48, - 1.10, 0.88, 0.51, 1.46, 0.52, 6.20, 1.69, 0.08, 3.67, - 2.81, 3.49 - }; - - var sw = new ShapiroWilkDistribution(b.Length); - - double expected = 0.5246; - double actual = sw.ComplementaryDistributionFunction(0.9590); - Assert.AreEqual(expected, actual, 1e-3); +// Accord Unit Tests +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Tests.Statistics +{ + + using Accord.Statistics.Distributions.Univariate; + using NUnit.Framework; + using System.Globalization; + + [TestFixture] + public class ShapiroWilkDistributionTest + { + + + private TestContext testContextInstance; + + public TestContext TestContext + { + get + { + return testContextInstance; + } + set + { + testContextInstance = value; + } + } + + + [Test] + public void ConstructorTest() + { + // Example from http://www.nag.com/numeric/cl/nagdoc_cl23/pdf/G01/g01ddc.pdf + + double[] a = + { + 0.11, 7.87, 4.61, 10.14, 7.95, 3.14, 0.46, 4.43, + 0.21, 4.75, 0.71, 1.52, 3.24, 0.93, 0.42, 4.97, + 9.53, 4.55, 0.47, 6.66 + }; + + var sw = new ShapiroWilkDistribution(a.Length); + + double expected = 0.0421; + double actual = sw.ComplementaryDistributionFunction(0.9005); + Assert.AreEqual(expected, actual, 1e-4); } - [TestMethod()] + [Test] + public void ConstructorTest2() + { + // Example from http://www.nag.com/numeric/cl/nagdoc_cl23/pdf/G01/g01ddc.pdf + + double[] b = + { + 1.36, 1.14, 2.92, 2.55, 1.46, 1.06, 5.27, 1.11, 3.48, + 1.10, 0.88, 0.51, 1.46, 0.52, 6.20, 1.69, 0.08, 3.67, + 2.81, 3.49 + }; + + var sw = new ShapiroWilkDistribution(b.Length); + + double expected = 0.5246; + double actual = sw.ComplementaryDistributionFunction(0.9590); + Assert.AreEqual(expected, actual, 1e-3); + } + + [Test] public void ConstructorTest3() { var sw = new ShapiroWilkDistribution(samples: 12); @@ -131,7 +131,7 @@ public void ConstructorTest3() Assert.AreEqual(0.98186388183806661, range3.Max); } - [TestMethod()] + [Test] public void ConstructorTest4() { // Create a new Shapiro-Wilk's W for 5 samples @@ -176,6 +176,6 @@ public void ConstructorTest4() var range3 = sw.GetRange(0.01); Assert.AreEqual(0.70180031139628618, range3.Min); Assert.AreEqual(0.99334588234528642, range3.Max); - } - } + } + } } \ No newline at end of file diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/ShiftedLogLogisticDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/ShiftedLogLogisticDistributionTest.cs index df5d06342..c35a5aadd 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/ShiftedLogLogisticDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/ShiftedLogLogisticDistributionTest.cs @@ -24,11 +24,11 @@ namespace Accord.Tests.Statistics { using System.Globalization; using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Math; - [TestClass()] + [TestFixture] public class ShiftedLogLogisticDistributionTest { @@ -49,7 +49,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest1() { var log = new ShiftedLogLogisticDistribution(location: 0, scale: 0.42, shape: 0.1); @@ -98,7 +98,7 @@ public void ConstructorTest1() Assert.AreEqual(2.4498647072756436, range3.Max, 1e-15); } - [TestMethod()] + [Test] public void EquivalencyTest1() { // when mu = sigma / ksi, the shifted log-logistic reduces to the log-logistic distribution. @@ -150,7 +150,7 @@ public void EquivalencyTest1() } } - [TestMethod()] + [Test] public void EquivalencyTest2() { // when ksi -> 0, the shifted log-logistic reduces to the logistic distribution. @@ -202,7 +202,7 @@ public void EquivalencyTest2() } } - [TestMethod()] + [Test] public void EquivalencyTest3() { // when ksi -> 0, the shifted log-logistic reduces to the logistic distribution. diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/SkewNormalDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/SkewNormalDistributionTest.cs index d1985a2f7..d8fc0336d 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/SkewNormalDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/SkewNormalDistributionTest.cs @@ -24,12 +24,12 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; using Accord.Statistics; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Statistics.Distributions.Multivariate; using System.Globalization; - [TestClass()] + [TestFixture] public class SkewNormalDistributionTest { @@ -50,7 +50,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest1() { // Create a Skew normal distribution with location 2, scale 3 and shape 4.2 @@ -98,7 +98,7 @@ public void ConstructorTest1() Assert.AreEqual(9.7274879203457694, range3.Max); } - [TestMethod()] + [Test] public void ConstructorTest2() { var normal = SkewNormalDistribution.Normal(mean: 4, stdDev: 4.2); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/TDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/TDistributionTest.cs index bc0e84e1b..3d820181d 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/TDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/TDistributionTest.cs @@ -23,12 +23,12 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Statistics.Distributions.Fitting; using System.Globalization; - [TestClass()] + [TestFixture] public class TDistributionTest { @@ -49,7 +49,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest() { var t = new TDistribution(degreesOfFreedom: 4.2); @@ -96,7 +96,7 @@ public void ConstructorTest() Assert.AreEqual(3.6502571302187774, range3.Max); } - [TestMethod()] + [Test] public void VarianceTest() { TDistribution target = new TDistribution(3); @@ -114,7 +114,7 @@ public void VarianceTest() Assert.IsTrue(Double.IsNaN(actual)); } - [TestMethod()] + [Test] public void MeanTest() { TDistribution target; @@ -135,7 +135,7 @@ public void MeanTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void ProbabilityDensityFunctionTest() { TDistribution target = new TDistribution(1); @@ -166,7 +166,7 @@ public void ProbabilityDensityFunctionTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void InverseDistributionFunctionTest() { TDistribution target; @@ -196,7 +196,7 @@ public void InverseDistributionFunctionTest() } - [TestMethod()] + [Test] public void InverseDistributionFunctionTest2() { TDistribution target = new TDistribution(24); @@ -207,7 +207,7 @@ public void InverseDistributionFunctionTest2() Assert.AreEqual(expected, actual, 1e-06); } - [TestMethod()] + [Test] public void InverseDistributionFunctionLeftTailTest() { double[] a = { 0.1, 0.05, 0.025, 0.01, 0.005, 0.001, 0.0005 }; @@ -263,7 +263,7 @@ public void InverseDistributionFunctionLeftTailTest() } - [TestMethod()] + [Test] public void LogProbabilityDensityFunctionTest() { TDistribution target = new TDistribution(1); @@ -294,7 +294,7 @@ public void LogProbabilityDensityFunctionTest() Assert.AreEqual(expected, actual, 1e-6); } - [TestMethod()] + [Test] public void FitTest() { bool thrown = false; @@ -304,7 +304,7 @@ public void FitTest() Assert.IsTrue(thrown); } - [TestMethod()] + [Test] public void DistributionFunctionTest() { TDistribution target = new TDistribution(1); @@ -341,7 +341,7 @@ public void DistributionFunctionTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void CloneTest() { int degreesOfFreedom = 5; @@ -354,7 +354,7 @@ public void CloneTest() Assert.AreEqual(target.Variance, clone.Variance); } - [TestMethod()] + [Test] public void TDistributionConstructorTest() { int degreesOfFreedom = 4; @@ -372,7 +372,7 @@ public void TDistributionConstructorTest() Assert.IsTrue(thrown); } - [TestMethod()] + [Test] public void MedianTest() { TDistribution target = new TDistribution(7.6); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/TrapezoidalDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/TrapezoidalDistributionTest.cs index 4d3ae9527..6c7fe40b6 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/TrapezoidalDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/TrapezoidalDistributionTest.cs @@ -23,29 +23,14 @@ namespace Accord.Tests.Statistics.Distributions.Univariate.Continuous { using System; - using Accord.Statistics.Distributions.Univariate.Continuous; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using Accord.Statistics.Distributions.Univariate; + using NUnit.Framework; using System.Globalization; - [TestClass] + [TestFixture] public class TrapezoidalDistributionTest { - - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - [TestMethod] + [Test] public void TrapezoidalDistributionConstructorTest() { double x = 0.75d; @@ -72,7 +57,7 @@ public void TrapezoidalDistributionConstructorTest() //Verified using R package 'trapezoid' } - [TestMethod()] + [Test] public void DocumentationTest1() { // Create a new trapezoidal distribution with linear growth between diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/TriangularDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/TriangularDistributionTest.cs index 574287201..a5bd3607c 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/TriangularDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/TriangularDistributionTest.cs @@ -24,13 +24,13 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; using Accord.Statistics; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Math; using Accord.Statistics.Distributions.Multivariate; using System.Globalization; - [TestClass()] + [TestFixture] public class TriangularDistributionTest { @@ -51,7 +51,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest1() { var tri = new TriangularDistribution(min: 1, max: 6, mode: 3); @@ -98,7 +98,7 @@ public void ConstructorTest1() Assert.AreEqual(5.6127016687540774, range3.Max); } - [TestMethod()] + [Test] public void GenerateTest1() { Accord.Math.Tools.SetupGenerator(0); @@ -122,7 +122,7 @@ public void GenerateTest1() Assert.AreEqual(mode, target.Mode, 0.035); } - [TestMethod()] + [Test] public void GenerateTest2() { Accord.Math.Tools.SetupGenerator(0); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/TukeyLambdaDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/TukeyLambdaDistributionTest.cs index 46d925adb..11f2ff5c0 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/TukeyLambdaDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/TukeyLambdaDistributionTest.cs @@ -24,12 +24,12 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; using Accord.Statistics; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Statistics.Distributions.Multivariate; using System.Globalization; - [TestClass()] + [TestFixture] public class TukeyLambdaTest { @@ -50,7 +50,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest() { var tukey = new TukeyLambdaDistribution(lambda: 0.14); @@ -99,7 +99,7 @@ public void ConstructorTest() Assert.AreEqual(3.3841891582663117, range3.Max); } - [TestMethod()] + [Test] public void LogisticTest() { var target = new TukeyLambdaDistribution(lambda: 0); @@ -108,7 +108,7 @@ public void LogisticTest() compare(target, logistic, 1e-5); } - [TestMethod()] + [Test] public void UniformTest() { var target = new TukeyLambdaDistribution(lambda: 1); @@ -117,7 +117,7 @@ public void UniformTest() compare(target, uniform, 1e-10); } - [TestMethod()] + [Test] public void UniformTest2() { var target = new TukeyLambdaDistribution(lambda: 2); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/UQuadraticDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/UQuadraticDistributionTest.cs index 731d06245..03f3eae0c 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/UQuadraticDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/UQuadraticDistributionTest.cs @@ -23,29 +23,15 @@ namespace Accord.Tests.Statistics.Distributions.Univariate.Continuous { using System; - using Accord.Statistics.Distributions.Univariate.Continuous; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using Accord.Statistics.Distributions.Univariate; + using NUnit.Framework; using System.Globalization; - [TestClass] + [TestFixture] public class UQuadraticDistributionTest { - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - [TestMethod] + [Test] public void Constructor_UQuadratic() { double a = -2.0d; @@ -68,7 +54,7 @@ public void Constructor_UQuadratic() Assert.AreEqual(tostr, "U-Quadratic(x; a = -2, b = 2)"); } - [TestMethod()] + [Test] public void DocumentationTest1() { var u2 = new UQuadraticDistribution(a: 0.42, b: 4.2); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/UnivariateContinuousDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/UnivariateContinuousDistributionTest.cs index 850acba09..0b6d4b0c0 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/UnivariateContinuousDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/UnivariateContinuousDistributionTest.cs @@ -23,13 +23,13 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics.Distributions; using System; using Accord.Statistics.Distributions.Fitting; using Accord.Math; - [TestClass()] + [TestFixture] public class UnivariateContinuousDistributionTest { @@ -59,7 +59,7 @@ internal virtual UnivariateContinuousDistribution CreateUnivariateContinuousDist - [TestMethod()] + [Test] public void VarianceTest() { UnivariateContinuousDistribution target = CreateUnivariateContinuousDistribution(); @@ -70,7 +70,7 @@ public void VarianceTest() Assert.AreEqual(expected, actual, 1e-15); } - [TestMethod()] + [Test] public void StandardDeviationTest() { UnivariateContinuousDistribution target = CreateUnivariateContinuousDistribution(); @@ -79,7 +79,7 @@ public void StandardDeviationTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void MeanTest() { UnivariateContinuousDistribution target = CreateUnivariateContinuousDistribution(); @@ -89,7 +89,7 @@ public void MeanTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void EntropyTest() { UnivariateContinuousDistribution target = CreateUnivariateContinuousDistribution(); @@ -101,7 +101,7 @@ public void EntropyTest() - [TestMethod()] + [Test] public void ProbabilityDensityFunctionTest() { UnivariateContinuousDistribution target = CreateUnivariateContinuousDistribution(); @@ -113,7 +113,7 @@ public void ProbabilityDensityFunctionTest() Assert.AreEqual(expected, actual, 1e-10); } - [TestMethod()] + [Test] public void LogProbabilityDensityFunctionTest() { UnivariateContinuousDistribution target = CreateUnivariateContinuousDistribution(); @@ -125,8 +125,7 @@ public void LogProbabilityDensityFunctionTest() Assert.AreEqual(expected, actual, 1e-10); } - [TestMethod()] - [DeploymentItem("Accord.Statistics.dll")] + [Test] public void ProbabilityFunctionTest() { IDistribution target = CreateUnivariateContinuousDistribution(); @@ -140,7 +139,7 @@ public void ProbabilityFunctionTest() - [TestMethod()] + [Test] public void DistributionFunctionTest1() { UnivariateContinuousDistribution target = CreateUnivariateContinuousDistribution(); @@ -151,8 +150,7 @@ public void DistributionFunctionTest1() Assert.AreEqual(expected, actual); } - [TestMethod()] - [DeploymentItem("Accord.Statistics.dll")] + [Test] public void DistributionFunctionTest() { IDistribution target = CreateUnivariateContinuousDistribution(); @@ -165,7 +163,7 @@ public void DistributionFunctionTest() - [TestMethod()] + [Test] public void FitTest7() { UnivariateContinuousDistribution target = CreateUnivariateContinuousDistribution(); @@ -181,7 +179,7 @@ public void FitTest7() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void FitTest6() { UnivariateContinuousDistribution target = CreateUnivariateContinuousDistribution(); @@ -196,7 +194,7 @@ public void FitTest6() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void FitTest5() { UnivariateContinuousDistribution target = CreateUnivariateContinuousDistribution(); @@ -213,7 +211,7 @@ public void FitTest5() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void FitTest4() { UnivariateContinuousDistribution target = CreateUnivariateContinuousDistribution(); @@ -229,7 +227,7 @@ public void FitTest4() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void FitTest3() { IDistribution target = CreateUnivariateContinuousDistribution(); @@ -245,7 +243,7 @@ public void FitTest3() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void FitTest2() { IDistribution target = CreateUnivariateContinuousDistribution(); @@ -260,7 +258,7 @@ public void FitTest2() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void FitTest1() { IDistribution target = CreateUnivariateContinuousDistribution(); @@ -277,7 +275,7 @@ public void FitTest1() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void FitTest() { IDistribution target = CreateUnivariateContinuousDistribution(); @@ -294,7 +292,7 @@ public void FitTest() } - [TestMethod()] + [Test] public void GenerateTest() { UniformContinuousDistribution target = new UniformContinuousDistribution(2, 5); @@ -308,7 +306,7 @@ public void GenerateTest() Assert.AreEqual(5, actual.Maximum, 1e-4); } - [TestMethod()] + [Test] public void GenerateTest2() { UniformContinuousDistribution target = new UniformContinuousDistribution(-1, 4); @@ -324,7 +322,7 @@ public void GenerateTest2() Assert.AreEqual(4, actual.Maximum, 1e-4); } - [TestMethod()] + [Test] public void GetRangeTest() { UnivariateContinuousDistribution target = CreateUnivariateContinuousDistribution(); @@ -341,7 +339,7 @@ public void GetRangeTest() Assert.AreEqual(27.767594425958258, range3.Max); } - [TestMethod()] + [Test] public void GetRangeTest_RangeException() { UnivariateContinuousDistribution target = CreateUnivariateContinuousDistribution(); @@ -357,7 +355,7 @@ public void GetRangeTest_RangeException() Assert.IsTrue(thrown); } - [TestMethod()] + [Test] public void GetRangeTest2() { UnivariateContinuousDistribution target = CreateUnivariateContinuousDistribution(); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/VonMisesDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/VonMisesDistributionTest.cs index 92a1814cb..c595eb9f6 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/VonMisesDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/VonMisesDistributionTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System.Globalization; - [TestClass()] + [TestFixture] public class VonMisesDistributionTest { @@ -46,7 +46,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest() { var vonMises = new VonMisesDistribution(mean: 0.42, concentration: 1.2); @@ -97,7 +97,7 @@ public void ConstructorTest() } - [TestMethod()] + [Test] public void FitTest() { double[] angles = @@ -116,7 +116,7 @@ public void FitTest() Assert.AreEqual(0.2441525, distribution.Variance, 1e-3); } - [TestMethod()] + [Test] public void ProbabilityDensityFunctionTest() { VonMisesDistribution dist = new VonMisesDistribution(2.249981, 2.411822); @@ -127,7 +127,7 @@ public void ProbabilityDensityFunctionTest() Assert.AreEqual(expected, actual, 1e-10); } - [TestMethod()] + [Test] public void LogProbabilityDensityFunctionTest() { VonMisesDistribution dist = new VonMisesDistribution(2.249981, 2.411822); @@ -139,7 +139,7 @@ public void LogProbabilityDensityFunctionTest() Assert.AreEqual(expected, actual, 1e-10); } - [TestMethod()] + [Test] public void MedianTest() { VonMisesDistribution target = new VonMisesDistribution(1.621, 4.52); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/WeibullDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/WeibullDistributionTest.cs index e4f72b1d6..c35d65aba 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/WeibullDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/WeibullDistributionTest.cs @@ -23,13 +23,13 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Moving; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics; using Accord.Statistics.Distributions.Univariate; using System; using System.Globalization; - [TestClass()] + [TestFixture] public class WeibullDistributionTest { @@ -49,7 +49,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest() { WeibullDistribution n = new WeibullDistribution(0.807602, 12.5); @@ -59,7 +59,7 @@ public void ConstructorTest() Assert.IsFalse(Double.IsNaN(n.Variance)); } - [TestMethod()] + [Test] public void ConstructorTest2() { var weilbull = new WeibullDistribution(scale: 0.42, shape: 1.2); @@ -109,7 +109,7 @@ public void ConstructorTest2() Assert.AreEqual(1.4995260942223139, range3.Max); } - [TestMethod()] + [Test] public void ProbabilityDistributionTest() { WeibullDistribution n = new WeibullDistribution(0.80, 12.5); @@ -136,7 +136,7 @@ public void ProbabilityDistributionTest() } } - [TestMethod()] + [Test] public void CumulativeDistributionTest() { WeibullDistribution n = new WeibullDistribution(0.80, 12.5); @@ -163,7 +163,7 @@ public void CumulativeDistributionTest() } } - [TestMethod()] + [Test] public void MedianTest() { WeibullDistribution target = new WeibullDistribution(1.52, 0.6); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/WilcoxonDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/WilcoxonDistributionTest.cs index 77e92b77e..5b616446f 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/WilcoxonDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/WilcoxonDistributionTest.cs @@ -23,11 +23,11 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; - [TestClass()] + [TestFixture] public class WilcoxonDistributionTest { @@ -49,7 +49,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest() { double[] ranks = { 1, 2, 3, 4, 5.5, 5.5, 7, 8, 9, 10, 11, 12 }; @@ -88,7 +88,7 @@ public void ConstructorTest() Assert.AreEqual("W+(x; R)", str); } - [TestMethod()] + [Test] public void ConstructorTest2() { double[] ranks = { 1, 2, 3, 4, 5.5, 5.5, 7, 8, 9, 10, 11, 12 }; @@ -136,7 +136,7 @@ public void ConstructorTest2() Assert.AreEqual(67.99999981945885, range3.Max); } - [TestMethod()] + [Test] public void WScore() { int[] signs = { -1, -1, +1, -1, +1, +1, +1, +1, +1, +1, +1, +1 }; @@ -170,7 +170,7 @@ public void WScore() } } - [TestMethod()] + [Test] public void ProbabilityTest() { // Example from https://onlinecourses.science.psu.edu/stat414/node/319 @@ -189,7 +189,7 @@ public void ProbabilityTest() } } - [TestMethod()] + [Test] public void CumulativeTest() { // Example from https://onlinecourses.science.psu.edu/stat414/node/319 @@ -209,7 +209,7 @@ public void CumulativeTest() } } - [TestMethod()] + [Test] public void CumulativeExactTest() { // example from https://onlinecourses.science.psu.edu/stat414/node/319 @@ -236,7 +236,7 @@ public void CumulativeExactTest() Assert.AreEqual(200, inv); } - [TestMethod()] + [Test] public void MedianTest() { double[] ranks = { 1, 2, 3, 7 }; diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/WrappedCauchyDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/WrappedCauchyDistributionTest.cs index c72753746..ac369a1b5 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/WrappedCauchyDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Continuous/WrappedCauchyDistributionTest.cs @@ -23,12 +23,12 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using System.Globalization; - [TestClass()] + [TestFixture] public class WrappedCauchyDistributionTest { @@ -50,7 +50,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest() { var dist = new WrappedCauchyDistribution(mu: 0.42, gamma: 3); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/BernoulliDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/BernoulliDistributionTest.cs index e3ef6cedd..f2b895af9 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/BernoulliDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/BernoulliDistributionTest.cs @@ -23,12 +23,12 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System.Globalization; using System.Linq; - [TestClass()] + [TestFixture] public class BernoulliDistributionTest { @@ -47,7 +47,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void ConstructorTest() { var bern = new BernoulliDistribution(mean: 0.42); @@ -101,7 +101,7 @@ public void ConstructorTest() Assert.AreEqual(1.0, range3.Max); } - [TestMethod()] + [Test] public void ProbabilityMassFunctionTest() { BernoulliDistribution target = new BernoulliDistribution(0.6); @@ -112,7 +112,7 @@ public void ProbabilityMassFunctionTest() Assert.AreEqual(expected, actual, 1e-6); } - [TestMethod()] + [Test] public void LogProbabilityMassFunctionTest() { BernoulliDistribution target = new BernoulliDistribution(0.6); @@ -123,7 +123,7 @@ public void LogProbabilityMassFunctionTest() Assert.AreEqual(expected, actual, 1e-6); } - [TestMethod()] + [Test] public void DistributionFunctionTest() { BernoulliDistribution target = new BernoulliDistribution(0.6); @@ -134,7 +134,7 @@ public void DistributionFunctionTest() Assert.AreEqual(expected, actual, 1e-6); } - [TestMethod()] + [Test] public void ComplementaryDistributionFunctionTest() { BernoulliDistribution target = new BernoulliDistribution(0.42); @@ -164,7 +164,7 @@ public void ComplementaryDistributionFunctionTest() } } - [TestMethod()] + [Test] public void MedianTest() { { @@ -188,7 +188,7 @@ public void MedianTest() } } - [TestMethod()] + [Test] public void GenerationTest() { double prob = 0.5; diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/BinomialDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/BinomialDistributionTest.cs index e8e259fd5..f460dbe9c 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/BinomialDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/BinomialDistributionTest.cs @@ -26,10 +26,10 @@ namespace Accord.Tests.Statistics using Accord.Math; using Accord.Statistics.Distributions.Fitting; using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System.Globalization; - [TestClass()] + [TestFixture] public class BinomialDistributionTest { @@ -50,7 +50,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest() { var bin = new BinomialDistribution(trials: 16, probability: 0.12); @@ -109,7 +109,7 @@ public void ConstructorTest() Assert.AreEqual(5.0, range3.Max); } - [TestMethod()] + [Test] public void ProbabilityMassFunctionTest() { double[] expected = @@ -136,7 +136,7 @@ public void ProbabilityMassFunctionTest() } } - [TestMethod()] + [Test] public void FitTest() { int trials = 5; @@ -152,7 +152,7 @@ public void FitTest() Assert.AreEqual(0.066666666666666666, target.ProbabilityOfSuccess, 1e-10); } - [TestMethod()] + [Test] public void BinomialDistributionConstructorTest() { int trials = 5; @@ -165,7 +165,7 @@ public void BinomialDistributionConstructorTest() Assert.AreEqual(trials * probability * (1 - probability), target.Variance); } - [TestMethod()] + [Test] public void CloneTest() { int trials = 3; @@ -181,7 +181,7 @@ public void CloneTest() Assert.AreEqual(target.ProbabilityOfSuccess, actual.ProbabilityOfSuccess); } - [TestMethod()] + [Test] public void DistributionFunctionTest() { // http://www.stat.yale.edu/Courses/1997-98/101/binom.htm @@ -231,7 +231,7 @@ public void DistributionFunctionTest() } } - [TestMethod()] + [Test] public void DistributionFunctionTest2() { // http://www.stat.yale.edu/Courses/1997-98/101/binom.htm @@ -251,7 +251,7 @@ public void DistributionFunctionTest2() } } - [TestMethod()] + [Test] public void InverseDistributionFunctionTest() { double[] pvalues = { 0.0260838, 0.130419, 0.3287, 0.5665, 0.7687, 0.8982, 0.9629, 0.9887, 0.9972, 0.9994 }; @@ -269,7 +269,7 @@ public void InverseDistributionFunctionTest() } } - [TestMethod()] + [Test] public void DistributionFunctionTest3() { // http://www.danielsoper.com/statcalc3/calc.aspx?id=70 @@ -288,7 +288,7 @@ public void DistributionFunctionTest3() } - [TestMethod()] + [Test] public void MedianTest() { int trials = 5; @@ -319,7 +319,7 @@ public void MedianTest() } } - [TestMethod()] + [Test] public void OverflowTest() { // http://stackoverflow.com/questions/23222097/accord-net-binomial-probability-mass-function-result-differs-from-excel-result @@ -331,7 +331,7 @@ public void OverflowTest() Assert.AreEqual(expected, actual, 1e-7); } - [TestMethod()] + [Test] public void GenerateTest() { var target = new BinomialDistribution(4, 0.2); @@ -344,7 +344,7 @@ public void GenerateTest() Assert.AreEqual(0.2, target.ProbabilityOfSuccess, 1e-3); } - [TestMethod()] + [Test] public void GenerateTest2() { var target = new BinomialDistribution(4, 0.2); @@ -357,7 +357,7 @@ public void GenerateTest2() Assert.AreEqual(0.2, target.ProbabilityOfSuccess, 1e-3); } - [TestMethod()] + [Test] public void GenerateTest3() { var target = new BinomialDistribution(4); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/DegenerateDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/DegenerateDistributionTest.cs index 5a743bd97..03cbfcc1e 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/DegenerateDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/DegenerateDistributionTest.cs @@ -23,12 +23,12 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; using System.Globalization; using Accord.Statistics.Distributions; - [TestClass()] + [TestFixture] public class DegenerateDistributionTest { @@ -48,7 +48,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void ConstructorTest() { var dist = new DegenerateDistribution(value: 2); @@ -107,7 +107,7 @@ public void ConstructorTest() Assert.AreEqual(3.0, range3.Max); } - [TestMethod()] + [Test] public void ConstructorTest_DoubleIntConversionTest() { IUnivariateDistribution dist = new DegenerateDistribution(value: 2); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/GeneralDiscreteDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/GeneralDiscreteDistributionTest.cs index 5e5f5dcf5..18d04cade 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/GeneralDiscreteDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/GeneralDiscreteDistributionTest.cs @@ -23,11 +23,11 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; using System.Globalization; - [TestClass()] + [TestFixture] public class DiscreteDistributionTest { @@ -47,7 +47,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void ConstructorTest() { // Create a Categorical distribution for 3 symbols, in which @@ -110,7 +110,7 @@ public void ConstructorTest() Assert.AreEqual(2, range3.Max); } - [TestMethod()] + [Test] public void IntervalTest() { var target = GeneralDiscreteDistribution.Uniform(-10, 10); @@ -128,7 +128,7 @@ public void IntervalTest() } } - [TestMethod()] + [Test] public void ConstructorTest2() { double[] probabilities = { 0.25, 0.25, 0.50 }; @@ -144,7 +144,7 @@ public void ConstructorTest2() Assert.AreEqual(0.6875, var); } - [TestMethod()] + [Test] public void FitTest() { GeneralDiscreteDistribution target = new GeneralDiscreteDistribution(4); @@ -159,7 +159,7 @@ public void FitTest() Assert.IsTrue(Matrix.IsEqual(expected, actual)); } - [TestMethod()] + [Test] public void FitTest2() { double[] expected = { 0.50, 0.00, 0.25, 0.25 }; @@ -184,7 +184,7 @@ public void FitTest2() Assert.IsTrue(Matrix.IsEqual(expected, actual2)); } - [TestMethod()] + [Test] public void FitTest3() { GeneralDiscreteDistribution target = new GeneralDiscreteDistribution(-1, 4); @@ -199,7 +199,7 @@ public void FitTest3() Assert.IsTrue(Matrix.IsEqual(expected, actual)); } - [TestMethod()] + [Test] public void FitTest4() { double[] expected = { 0.50, 0.00, 0.25, 0.25 }; @@ -225,7 +225,7 @@ public void FitTest4() } - [TestMethod()] + [Test] public void DistributionFunctionTest() { var target = new GeneralDiscreteDistribution(0.1, 0.4, 0.5); @@ -248,7 +248,7 @@ public void DistributionFunctionTest() Assert.AreEqual(1.3999999, target.Mean, 1e-6); } - [TestMethod()] + [Test] public void MeanTest() { var target = new GeneralDiscreteDistribution(0.1, 0.4, 0.5); @@ -258,7 +258,7 @@ public void MeanTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void MeanTest2() { var target = new GeneralDiscreteDistribution(42, 0.1, 0.4, 0.5); @@ -268,7 +268,7 @@ public void MeanTest2() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void MeanTest3() { var target = new GeneralDiscreteDistribution(2, 0.5, 0.5); @@ -278,7 +278,7 @@ public void MeanTest3() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void VarianceTest() { var target = new GeneralDiscreteDistribution(42, 0.1, 0.4, 0.5); @@ -290,7 +290,7 @@ public void VarianceTest() Assert.AreEqual(expected, target.Variance); } - [TestMethod()] + [Test] public void EntropyTest() { var target = new GeneralDiscreteDistribution(42, 0.1, 0.4, 0.5); @@ -301,14 +301,14 @@ public void EntropyTest() Assert.AreEqual(expected, target.Entropy); } - [TestMethod()] + [Test] public void MedianTest() { var target = new GeneralDiscreteDistribution(0.1, 0.4, 0.5); Assert.AreEqual(target.Median, target.InverseDistributionFunction(0.5)); } - [TestMethod()] + [Test] public void UniformTest() { int a = 2; @@ -338,7 +338,7 @@ public void UniformTest() Assert.AreEqual(0, dist.ProbabilityMassFunction(7)); } - [TestMethod()] + [Test] public void ProbabilityMassFunctionTest() { GeneralDiscreteDistribution dist = GeneralDiscreteDistribution.Uniform(2, 5); @@ -353,7 +353,7 @@ public void ProbabilityMassFunctionTest() Assert.AreEqual(0, dist.ProbabilityMassFunction(7)); } - [TestMethod()] + [Test] public void LogProbabilityMassFunctionTest() { GeneralDiscreteDistribution dist = GeneralDiscreteDistribution.Uniform(2, 5); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/GeometricDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/GeometricDistributionTest.cs index 9e97c2285..832aa45aa 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/GeometricDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/GeometricDistributionTest.cs @@ -25,11 +25,11 @@ namespace Accord.Tests.Statistics using Accord.Math; using Accord.Statistics.Distributions.Fitting; using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using System.Globalization; - [TestClass()] + [TestFixture] public class GeometricDistributionTest { @@ -50,7 +50,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest() { // Create a Geometric distribution with 42% success probability @@ -108,7 +108,7 @@ public void ConstructorTest() Assert.AreEqual(8, range3.Max); } - [TestMethod()] + [Test] public void GeometricDistributionConstructorTest() { double successProbability = 0.9; @@ -118,7 +118,7 @@ public void GeometricDistributionConstructorTest() Assert.AreEqual((1 - 0.9) / (0.9 * 0.9), target.Variance); } - [TestMethod()] + [Test] public void CloneTest() { double successProbability = 1; @@ -131,7 +131,7 @@ public void CloneTest() Assert.AreEqual(target.ProbabilityOfSuccess, actual.ProbabilityOfSuccess); } - [TestMethod()] + [Test] public void DistributionFunctionTest() { double successProbability = 0.42; @@ -149,7 +149,7 @@ public void DistributionFunctionTest() } } - [TestMethod()] + [Test] public void FitTest() { double successProbability = 0; @@ -164,7 +164,7 @@ public void FitTest() Assert.AreEqual(1 / (1 - 4 / 12.0), target.ProbabilityOfSuccess); } - [TestMethod()] + [Test] public void FitTest2() { double successProbability = 0; @@ -181,7 +181,7 @@ public void FitTest2() } - [TestMethod()] + [Test] public void ProbabilityMassFunctionTest() { double successProbability = 0.42; @@ -197,7 +197,7 @@ public void ProbabilityMassFunctionTest() } } - [TestMethod()] + [Test] public void MedianTest() { { diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/HypergeometricDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/HypergeometricDistributionTest.cs index db30555e5..1f4e801d0 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/HypergeometricDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/HypergeometricDistributionTest.cs @@ -25,10 +25,10 @@ namespace Accord.Tests.Statistics using System; using Accord.Statistics.Distributions.Fitting; using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System.Globalization; - [TestClass()] + [TestFixture] public class HypergeometricDistributionTest { @@ -48,7 +48,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void ConstructorTest() { @@ -112,7 +112,7 @@ public void ConstructorTest() Assert.AreEqual(6, range3.Max); } - [TestMethod()] + [Test] public void HypergeometricDistributionConstructorTest() { bool thrown; @@ -159,7 +159,7 @@ public void HypergeometricDistributionConstructorTest() Assert.AreEqual(dn * dm * (dN - dm) * (dN - dn) / (dN * dN * (dN - 1.0)), target.Variance); } - [TestMethod()] + [Test] public void CloneTest() { int populationSize = 12; @@ -177,7 +177,7 @@ public void CloneTest() Assert.AreEqual(target.PopulationSuccess, actual.PopulationSuccess); } - [TestMethod()] + [Test] public void DistributionFunctionTest() { int populationSize = 15; @@ -191,7 +191,7 @@ public void DistributionFunctionTest() Assert.AreEqual(expected, actual, 1e-10); } - [TestMethod()] + [Test] public void MedianTest() { int populationSize = 15; @@ -202,7 +202,7 @@ public void MedianTest() Assert.AreEqual(target.Median, target.InverseDistributionFunction(0.5)); } - [TestMethod()] + [Test] public void LogProbabilityMassFunctionTest() { int populationSize = 15; @@ -217,7 +217,7 @@ public void LogProbabilityMassFunctionTest() Assert.IsFalse(Double.IsNaN(actual)); } - [TestMethod()] + [Test] public void ProbabilityMassFunctionTest() { int N = 50; @@ -231,7 +231,7 @@ public void ProbabilityMassFunctionTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void ProbabilityMassFunctionTest2() { int populationSize = 15; @@ -246,7 +246,7 @@ public void ProbabilityMassFunctionTest2() Assert.IsFalse(Double.IsNaN(actual)); } - [TestMethod()] + [Test] public void DistributionFunctionTest2() { // Verified against http://stattrek.com/online-calculator/hypergeometric.aspx @@ -299,7 +299,7 @@ public void DistributionFunctionTest2() } - [TestMethod()] + [Test] public void ConstructorTest3() { var h = new HypergeometricDistribution(9, 6, 1); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/NegativeBinomialTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/NegativeBinomialTest.cs index d4d4ab183..65072d059 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/NegativeBinomialTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/NegativeBinomialTest.cs @@ -23,11 +23,11 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using System.Globalization; - [TestClass()] + [TestFixture] public class NegativeBinomialTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest() { // Create a Negative Binomial distribution with r = 7, p = 0.42 @@ -79,10 +79,10 @@ public void ConstructorTest() double chf = dist.CumulativeHazardFunction(x: 4); // 0.64959916255036043 // String representation - string str = dist.ToString(CultureInfo.InvariantCulture); // "NegativeBinomial(x; r = 7, p = 0.42)" - - double[] probabilities = new double[10]; - for (int i = 0; i < probabilities.Length; i++) + string str = dist.ToString(CultureInfo.InvariantCulture); // "NegativeBinomial(x; r = 7, p = 0.42)" + + double[] probabilities = new double[10]; + for (int i = 0; i < probabilities.Length; i++) probabilities[i] = dist.DistributionFunction(i); Assert.AreEqual(5.068965517241379, mean); @@ -113,7 +113,7 @@ public void ConstructorTest() Assert.AreEqual(14, range3.Max); } - [TestMethod()] + [Test] public void NegativeBinomialConstructorTest() { double expected, actual; @@ -147,7 +147,7 @@ public void NegativeBinomialConstructorTest() } } - [TestMethod()] + [Test] public void MedianTest() { for (int i = 0; i < 10; i++) diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/PoissonDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/PoissonDistributionTest.cs index a1b94acb4..bc0949f30 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/PoissonDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/PoissonDistributionTest.cs @@ -23,11 +23,11 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics.Distributions; using System.Globalization; - [TestClass()] + [TestFixture] public class PoissonDistributionTest { @@ -47,7 +47,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void ConstructorTest() { // Create a new Poisson distribution with @@ -122,7 +122,7 @@ public void ConstructorTest() Assert.AreEqual(10, range3.Max); } - [TestMethod()] + [Test] public void DistributionFunctionTest() { // Create a new Poisson distribution @@ -150,7 +150,7 @@ public void DistributionFunctionTest() Assert.AreEqual(greaterThanOrEqual, 0.985004423179522, 1e-10); } - [TestMethod()] + [Test] public void ConstructorTest2() { // Create a new Poisson distribution with lambda = 0.7 @@ -211,7 +211,7 @@ public void ConstructorTest2() Assert.AreEqual(0.83666002653407556, stdDev); } - [TestMethod()] + [Test] public void FitTest() { PoissonDistribution target = new PoissonDistribution(1); @@ -223,7 +223,7 @@ public void FitTest() Assert.AreEqual(expected, target.Mean); } - [TestMethod()] + [Test] public void ProbabilityDensityFunctionTest() { PoissonDistribution target = new PoissonDistribution(25); @@ -234,7 +234,7 @@ public void ProbabilityDensityFunctionTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void LogProbabilityDensityFunctionTest() { PoissonDistribution target = new PoissonDistribution(25); @@ -246,7 +246,7 @@ public void LogProbabilityDensityFunctionTest() } - [TestMethod()] + [Test] public void MedianTest() { for (int i = 0; i < 25; i++) @@ -256,7 +256,7 @@ public void MedianTest() } } - [TestMethod()] + [Test] public void GenerateTest() { double lambda = 1.11022302462516E-16; @@ -268,7 +268,7 @@ public void GenerateTest() Assert.AreEqual(0, values[i]); } - [TestMethod()] + [Test] public void GenerateTest2() { double lambda = 1.11022302462516E-16; diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/RademacherDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/RademacherDistributionTest.cs index c3bf50b7f..01d7908c8 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/RademacherDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/RademacherDistributionTest.cs @@ -23,17 +23,17 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; using System.Globalization; using Accord.Statistics.Distributions; - [TestClass()] + [TestFixture] public class RademacherDistributionTest { - [TestMethod()] + [Test] public void ConstructorTest() { var dist = new RademacherDistribution(); @@ -74,7 +74,7 @@ public void ConstructorTest() Assert.AreEqual(+1, range3.Max); } - [TestMethod()] + [Test] public void ConstructorTest_DoubleIntConversionTest() { IUnivariateDistribution dist = new DegenerateDistribution(value: 2); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/UnivariateDiscreteDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/UnivariateDiscreteDistributionTest.cs index f611193c1..588fe2b1a 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/UnivariateDiscreteDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/Discrete/UnivariateDiscreteDistributionTest.cs @@ -23,13 +23,13 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics.Distributions; using System; using Accord.Statistics.Distributions.Fitting; using System.Globalization; - [TestClass()] + [TestFixture] public class UnivariateDiscreteDistributionTest { @@ -51,7 +51,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest() { // Create an uniform (discrete) distribution in [2, 6] @@ -112,7 +112,7 @@ public void ConstructorTest() Assert.AreEqual(6, range3.Max); } - [TestMethod()] + [Test] public void IntervalTest() { var target = new UniformDiscreteDistribution(-10, 10); @@ -136,7 +136,7 @@ internal virtual UnivariateDiscreteDistribution CreateUnivariateDiscreteDistribu return new BernoulliDistribution(mean); } - [TestMethod()] + [Test] public void VarianceTest() { UnivariateDiscreteDistribution target = CreateUnivariateDiscreteDistribution(); @@ -145,7 +145,7 @@ public void VarianceTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void StandardDeviationTest() { UnivariateDiscreteDistribution target = CreateUnivariateDiscreteDistribution(); @@ -154,7 +154,7 @@ public void StandardDeviationTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void MeanTest() { UnivariateDiscreteDistribution target = CreateUnivariateDiscreteDistribution(); @@ -163,7 +163,7 @@ public void MeanTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void EntropyTest() { UnivariateDiscreteDistribution target = CreateUnivariateDiscreteDistribution(); @@ -188,7 +188,7 @@ public void EntropyTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void ProbabilityMassFunctionTest() { UnivariateDiscreteDistribution target = CreateUnivariateDiscreteDistribution(); @@ -210,7 +210,7 @@ public void ProbabilityMassFunctionTest() Assert.AreEqual(p, target.ProbabilityMassFunction(1)); } - [TestMethod()] + [Test] public void LogProbabilityMassFunctionTest() { UnivariateDiscreteDistribution target = CreateUnivariateDiscreteDistribution(); @@ -225,7 +225,7 @@ public void LogProbabilityMassFunctionTest() Assert.AreEqual(lnp, target.LogProbabilityMassFunction(1)); } - [TestMethod()] + [Test] public void FitTest7() { UnivariateDiscreteDistribution target = CreateUnivariateDiscreteDistribution(); @@ -238,7 +238,7 @@ public void FitTest7() Assert.AreEqual(mean, target.Mean); } - [TestMethod()] + [Test] public void FitTest6() { UnivariateDiscreteDistribution target = CreateUnivariateDiscreteDistribution(); @@ -250,7 +250,7 @@ public void FitTest6() Assert.AreEqual(mean, target.Mean); } - [TestMethod()] + [Test] public void FitTest5() { UnivariateDiscreteDistribution target = CreateUnivariateDiscreteDistribution(); @@ -265,7 +265,7 @@ public void FitTest5() Assert.AreEqual(mean, target.Mean); } - [TestMethod()] + [Test] public void FitTest4() { UnivariateDiscreteDistribution target = CreateUnivariateDiscreteDistribution(); @@ -279,7 +279,7 @@ public void FitTest4() Assert.AreEqual(mean, target.Mean); } - [TestMethod()] + [Test] public void DistributionFunctionTest1() { UnivariateDiscreteDistribution target = CreateUnivariateDiscreteDistribution(); @@ -293,9 +293,7 @@ public void DistributionFunctionTest1() } - - [TestMethod()] - [DeploymentItem("Accord.Statistics.dll")] + [Test] public void ProbabilityFunctionTest() { IDistribution target = CreateUnivariateDiscreteDistribution(); @@ -318,8 +316,7 @@ public void ProbabilityFunctionTest() Assert.AreEqual(p, target.ProbabilityFunction(1)); } - [TestMethod()] - [DeploymentItem("Accord.Statistics.dll")] + [Test] public void FitTest3() { IDistribution target = CreateUnivariateDiscreteDistribution(); @@ -331,8 +328,7 @@ public void FitTest3() Assert.AreEqual(mean, (target as BernoulliDistribution).Mean); } - [TestMethod()] - [DeploymentItem("Accord.Statistics.dll")] + [Test] public void FitTest2() { IDistribution target = CreateUnivariateDiscreteDistribution(); @@ -344,8 +340,7 @@ public void FitTest2() Assert.AreEqual(mean, (target as BernoulliDistribution).Mean); } - [TestMethod()] - [DeploymentItem("Accord.Statistics.dll")] + [Test] public void FitTest1() { IDistribution target = CreateUnivariateDiscreteDistribution(); @@ -360,8 +355,7 @@ public void FitTest1() Assert.AreEqual(mean, (target as BernoulliDistribution).Mean); } - [TestMethod()] - [DeploymentItem("Accord.Statistics.dll")] + [Test] public void FitTest() { IDistribution target = CreateUnivariateDiscreteDistribution(); @@ -375,8 +369,7 @@ public void FitTest() Assert.AreEqual(mean, (target as BernoulliDistribution).Mean); } - [TestMethod()] - [DeploymentItem("Accord.Statistics.dll")] + [Test] public void DistributionFunctionTest() { IDistribution target = CreateUnivariateDiscreteDistribution(); @@ -390,7 +383,7 @@ public void DistributionFunctionTest() Assert.AreEqual(1, target.DistributionFunction(+1.1)); } - [TestMethod()] + [Test] public void GetRangeTest() { var u = new UniformDiscreteDistribution(-8, 7); diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/MixtureDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/MixtureDistributionTest.cs index 159b555ba..21d4ecb87 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/MixtureDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/MixtureDistributionTest.cs @@ -22,17 +22,17 @@ namespace Accord.Tests.Statistics { - using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; using Accord.Math; using Accord.Statistics.Distributions.Fitting; + using Accord.Statistics.Distributions.Univariate; + using NUnit.Framework; using System.Globalization; - [TestClass()] + [TestFixture] public class MixtureDistributionTest { - [TestMethod()] + [Test] public void ConstructorTest() { // Create a new mixture containing two Normal distributions @@ -84,7 +84,7 @@ public void ConstructorTest() Assert.AreEqual(1.5866611690305092, icdf1); Assert.AreEqual(3.1968506765456883, icdf2); Assert.AreEqual(5.6437596300843076, icdf3); - Assert.AreEqual("Mixture(x; 0.5*N(x; μ = 5, σ² = 1) + 0.5*N(x; μ = 5, σ² = 1))", str); + Assert.AreEqual("Mixture(x; 0.5*N(x; μ = 2, σ² = 1) + 0.5*N(x; μ = 5, σ² = 1))", str); Assert.IsFalse(double.IsNaN(icdf1)); @@ -100,7 +100,7 @@ public void ConstructorTest() Assert.AreEqual(7.0537533150666105, range3.Max); } - [TestMethod()] + [Test] public void ConstructorTest1() { NormalDistribution[] components = new NormalDistribution[2]; @@ -115,7 +115,7 @@ public void ConstructorTest1() Assert.AreEqual(components, mixture.Components); } - [TestMethod()] + [Test] public void ConstructorTest2() { // Create a new mixture containing two Normal distributions @@ -132,7 +132,7 @@ public void ConstructorTest2() Assert.AreEqual(3.25, var); } - [TestMethod()] + [Test] public void FitTest() { double[] coefficients = { 0.50, 0.50 }; @@ -171,7 +171,7 @@ public void FitTest() Assert.AreEqual(expectedVar, actualVar, 0.15); } - [TestMethod()] + [Test] public void FitTest2() { double[] coefficients = { 0.50, 0.50 }; @@ -210,7 +210,7 @@ public void FitTest2() Assert.AreEqual(expectedMean, actualMean, 1e-5); } - [TestMethod()] + [Test] public void ProbabilityDensityFunction() { NormalDistribution[] components = new NormalDistribution[2]; @@ -229,7 +229,7 @@ public void ProbabilityDensityFunction() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void ProbabilityDensityFunctionPerComponent() { NormalDistribution[] components = new NormalDistribution[2]; @@ -248,7 +248,7 @@ public void ProbabilityDensityFunctionPerComponent() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void LogProbabilityDensityFunction() { NormalDistribution[] components = new NormalDistribution[2]; @@ -268,7 +268,7 @@ public void LogProbabilityDensityFunction() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void LogProbabilityDensityFunctionPerComponent() { NormalDistribution[] components = new NormalDistribution[2]; @@ -287,7 +287,7 @@ public void LogProbabilityDensityFunctionPerComponent() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void DistributionFunctionPerComponent() { NormalDistribution[] components = new NormalDistribution[2]; @@ -306,7 +306,7 @@ public void DistributionFunctionPerComponent() Assert.AreEqual(expected, actual); } - [TestMethod] + [Test] public void MixtureWeightsFitTest() { // Randomly initialize some mixture components @@ -317,9 +317,7 @@ public void MixtureWeightsFitTest() // Create an initial mixture Mixture mixture = new Mixture(components); - // Now, suppose we have a weighted data - // set. Those will be the input points: - + // Now, suppose we have a weighted data set. Those will be the input points: double[] points = { 0, 3, 1, 7, 3, 5, 1, 2, -1, 2, 7, 6, 8, 6 }; // (14 points) // And those are their respective unnormalized weights: @@ -345,20 +343,46 @@ public void MixtureWeightsFitTest() Assert.AreEqual(0.51408489193241225, pi1); Assert.AreEqual(0.48591510806758775, pi2); - /* - // If we need the GaussianMixtureModel functionality, we can - // use the estimated mixture to initialize a new model: - GaussianMixtureModel gmm = new GaussianMixtureModel(mixture); - - Assert.AreEqual(mean1, gmm.Gaussians[0].Mean[0]); - Assert.AreEqual(mean2, gmm.Gaussians[1].Mean[0]); - - Assert.AreEqual(mean1, 1.4112610766836404, 1e-15); - Assert.AreEqual(mean2, 6.5330177004151082, 1e-14); - - Assert.AreEqual(mixture.Coefficients[0], gmm.Gaussians[0].Proportion); - Assert.AreEqual(mixture.Coefficients[1], gmm.Gaussians[1].Proportion); + /* + // If we need the GaussianMixtureModel functionality, we can + // use the estimated mixture to initialize a new model: + GaussianMixtureModel gmm = new GaussianMixtureModel(mixture); + + Assert.AreEqual(mean1, gmm.Gaussians[0].Mean[0]); + Assert.AreEqual(mean2, gmm.Gaussians[1].Mean[0]); + + Assert.AreEqual(mean1, 1.4112610766836404, 1e-15); + Assert.AreEqual(mean2, 6.5330177004151082, 1e-14); + + Assert.AreEqual(mixture.Coefficients[0], gmm.Gaussians[0].Proportion); + Assert.AreEqual(mixture.Coefficients[1], gmm.Gaussians[1].Proportion); */ } + + [Test] + public void MixtureFitTest() + { + var samples1 = new NormalDistribution(mean: -2, stdDev: 0.5).Generate(100000); + var samples2 = new NormalDistribution(mean: +4, stdDev: 0.5).Generate(100000); + + // Mix the samples from both distributions + var samples = samples1.Concatenate(samples2); + + // Create a new mixture distribution with two Normal components + var mixture = new Mixture(new[] { 0.2, 0.8 }, + new NormalDistribution(-1), + new NormalDistribution(+1)); + + // Estimate the distribution + mixture.Fit(samples, new MixtureOptions + { + Iterations = 50, + Threshold = 0 + }); + + var result = mixture.ToString("N2", System.Globalization.CultureInfo.InvariantCulture); + + Assert.AreEqual("Mixture(x; 0.50*N(x; μ = -2.00, σ² = 0.25) + 0.50*N(x; μ = 4.00, σ² = 0.25))", result); + } } } diff --git a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/UnivariateDistributionTest.cs b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/UnivariateDistributionTest.cs index 203f11173..f5855bca9 100644 --- a/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/UnivariateDistributionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Distributions/Univariate/UnivariateDistributionTest.cs @@ -23,7 +23,7 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Distributions.Univariate; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics.Distributions; using System; using Accord.Statistics.Distributions.Fitting; @@ -33,38 +33,10 @@ namespace Accord.Tests.Statistics using System.Collections.Generic; using Accord.Statistics.Distributions.Multivariate; - [TestClass()] + [TestFixture] public class UnivariateDistributionTest { - - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - [TestMethod, Ignore] - public void ListDistributions() - { - var assembly = Assembly.GetAssembly(typeof(IDistribution)); - - int nuc, nud, nmc, nmd; - - string uc = GetNames(assembly, typeof(UnivariateContinuousDistribution), out nuc); - string ud = GetNames(assembly, typeof(UnivariateDiscreteDistribution), out nud); - string mc = GetNames(assembly, typeof(MultivariateContinuousDistribution), out nmc); - string md = GetNames(assembly, typeof(MultivariateDiscreteDistribution), out nmd); - } - private static string GetNames(Assembly assembly, Type baseType, out int count) { var distributions = assembly.GetTypes().Where(p => @@ -79,7 +51,7 @@ private static string GetNames(Assembly assembly, Type baseType, out int count) return String.Join(", ", list.ToArray()); } - [TestMethod()] + [Test] public void ParameterPropertyTest() { // Dynamically enumerate all univariate distributions and make diff --git a/Unit Tests/Accord.Tests.Statistics/Filters/BranchingFilterTest.cs b/Unit Tests/Accord.Tests.Statistics/Filters/BranchingFilterTest.cs index c8266dadb..aafad3c65 100644 --- a/Unit Tests/Accord.Tests.Statistics/Filters/BranchingFilterTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Filters/BranchingFilterTest.cs @@ -26,9 +26,9 @@ namespace Accord.Tests.Statistics using Accord.Math; using Accord.Statistics.Filters; using AForge; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class BranchingFilterTest { @@ -49,7 +49,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ApplyTest() { object[,] data = diff --git a/Unit Tests/Accord.Tests.Statistics/Filters/CodificationFilterTest.cs b/Unit Tests/Accord.Tests.Statistics/Filters/CodificationFilterTest.cs index a7141e709..bb839aca9 100644 --- a/Unit Tests/Accord.Tests.Statistics/Filters/CodificationFilterTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Filters/CodificationFilterTest.cs @@ -22,14 +22,14 @@ namespace Accord.Tests.Statistics { - using System.Data; + using Accord.IO; using Accord.Math; using Accord.Statistics.Filters; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using Accord.IO; + using NUnit.Framework; using System; + using System.Data; - [TestClass()] + [TestFixture] public class CodificationFilterTest { @@ -37,7 +37,7 @@ public class CodificationFilterTest // at the Accord.Tests.MachineLearning assembly in the file // CodificationFilterSvmTest.cs - [TestMethod()] + [Test] public void ApplyTest1() { DataTable table = ProjectionFilterTest.CreateTable(); @@ -64,7 +64,7 @@ public void ApplyTest1() Assert.AreEqual(2, result.Rows[4]["Category"]); } - [TestMethod()] + [Test] public void ApplyTest() { Codification target = new Codification(); @@ -116,7 +116,7 @@ public void ApplyTest() } - [TestMethod()] + [Test] public void ApplyTest3() { string[] names = { "child", "adult", "elder" }; @@ -144,10 +144,10 @@ public void ApplyTest3() Assert.AreEqual("elder", labelc); } - [TestMethod()] + [Test] public void ApplyTest4() { - string path = @"..\..\..\..\Unit Tests\Accord.Tests.Statistics\Resources\intrusion.xls"; + string path = @"Resources\intrusion.xls"; ExcelReader db = new ExcelReader(path, false, true); @@ -170,7 +170,7 @@ public void ApplyTest4() /// This method tests, that the correct DataColumn is used /// /// - [TestMethod] + [Test] public void TranslateTest1() { string[] colNames = { "col1", "col2", "col3" }; @@ -215,7 +215,7 @@ public void TranslateTest1() /// Testing Codification.Translate(string[], string[]) /// /// - [TestMethod] + [Test] public void TranslateTest2() { string[] colNames = { "col1", "col2", "col3" }; @@ -267,7 +267,7 @@ public void TranslateTest2() /// This test assumes string input is given in correct column order - is otherwise identical to TranslateTest2 /// /// - [TestMethod] + [Test] public void TranslateTest3() { string[] colNames = { "col1", "col2", "col3" }; diff --git a/Unit Tests/Accord.Tests.Statistics/Filters/DiscretizationFilterTest.cs b/Unit Tests/Accord.Tests.Statistics/Filters/DiscretizationFilterTest.cs index d8af8928a..a52d32a1e 100644 --- a/Unit Tests/Accord.Tests.Statistics/Filters/DiscretizationFilterTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Filters/DiscretizationFilterTest.cs @@ -24,9 +24,9 @@ namespace Accord.Tests.Statistics { using System.Data; using Accord.Statistics.Filters; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class DiscretizationFilterTest { @@ -45,7 +45,7 @@ public TestContext TestContext } } - [TestMethod()] + [Test] public void ApplyTest1() { DataTable table = ProjectionFilterTest.CreateTable(); @@ -72,7 +72,7 @@ public void ApplyTest1() Assert.AreEqual("2", result.Rows[4]["Cost (M)"]); } - [TestMethod()] + [Test] public void ApplyTest() { DataTable input = new DataTable("Sample data"); diff --git a/Unit Tests/Accord.Tests.Statistics/Filters/GroupingFilterTest.cs b/Unit Tests/Accord.Tests.Statistics/Filters/GroupingFilterTest.cs index f5e5df923..d7244a657 100644 --- a/Unit Tests/Accord.Tests.Statistics/Filters/GroupingFilterTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Filters/GroupingFilterTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Filters; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System.Data; - [TestClass()] + [TestFixture] public class GroupingFilterTest { @@ -47,7 +47,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ApplyTest() { DataTable input = new DataTable("Sample data"); @@ -121,7 +121,7 @@ public void ApplyTest() } - [TestMethod()] + [Test] public void ApplyTest2() { diff --git a/Unit Tests/Accord.Tests.Statistics/Filters/LinearScalingFilterTest.cs b/Unit Tests/Accord.Tests.Statistics/Filters/LinearScalingFilterTest.cs index 788edf949..b98e57f0f 100644 --- a/Unit Tests/Accord.Tests.Statistics/Filters/LinearScalingFilterTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Filters/LinearScalingFilterTest.cs @@ -25,9 +25,9 @@ namespace Accord.Tests.Statistics using System.Data; using Accord.Statistics.Filters; using AForge; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class LinearScalingFilterTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ApplyTest() { DataTable input = new DataTable("Sample data"); diff --git a/Unit Tests/Accord.Tests.Statistics/Filters/NormalizationFilterTest.cs b/Unit Tests/Accord.Tests.Statistics/Filters/NormalizationFilterTest.cs index 4e7428dfd..3f3e6ec3b 100644 --- a/Unit Tests/Accord.Tests.Statistics/Filters/NormalizationFilterTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Filters/NormalizationFilterTest.cs @@ -24,10 +24,10 @@ namespace Accord.Tests.Statistics { using Accord.Math; using Accord.Statistics.Filters; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System.Data; - [TestClass()] + [TestFixture] public class NormalizationFilterTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ApplyTest() { DataTable input = new DataTable("Sample data"); @@ -89,7 +89,7 @@ public void ApplyTest() } } - [TestMethod()] + [Test] public void ApplyTest2() { string colName = "(test ['a'])"; @@ -129,7 +129,7 @@ public void ApplyTest2() } } - [TestMethod()] + [Test] public void ApplyTest3() { // Suppose we have a data table relating the age of diff --git a/Unit Tests/Accord.Tests.Statistics/Filters/ProjectionFilterTest.cs b/Unit Tests/Accord.Tests.Statistics/Filters/ProjectionFilterTest.cs index 187f63216..179bcef4f 100644 --- a/Unit Tests/Accord.Tests.Statistics/Filters/ProjectionFilterTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Filters/ProjectionFilterTest.cs @@ -23,12 +23,12 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Filters; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System.Data; using Accord; using Accord.Math; - [TestClass()] + [TestFixture] public class ProjectionFilterTest { @@ -62,7 +62,7 @@ public static DataTable CreateTable() } - [TestMethod()] + [Test] public void ApplyTest() { DataTable table = CreateTable(); diff --git a/Unit Tests/Accord.Tests.Statistics/Filters/SelectionFilterTest.cs b/Unit Tests/Accord.Tests.Statistics/Filters/SelectionFilterTest.cs index de53cf7db..0cdcac4de 100644 --- a/Unit Tests/Accord.Tests.Statistics/Filters/SelectionFilterTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Filters/SelectionFilterTest.cs @@ -24,10 +24,10 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Filters; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System.Data; - [TestClass()] + [TestFixture] public class SelectionFilterTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ApplyTest() { DataTable table = new DataTable("myData"); diff --git a/Unit Tests/Accord.Tests.Statistics/Filters/StratificationFilterTest.cs b/Unit Tests/Accord.Tests.Statistics/Filters/StratificationFilterTest.cs index 6ed84a121..9fb8cf5ed 100644 --- a/Unit Tests/Accord.Tests.Statistics/Filters/StratificationFilterTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Filters/StratificationFilterTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Filters; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System.Data; - [TestClass()] + [TestFixture] public class StratificationFilterTest { @@ -47,7 +47,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ApplyTest() { DataTable data = new DataTable("Sample data"); diff --git a/Unit Tests/Accord.Tests.Statistics/Kernels/AnovaTest.cs b/Unit Tests/Accord.Tests.Statistics/Kernels/AnovaTest.cs index 7b3ca7ee7..f6828106c 100644 --- a/Unit Tests/Accord.Tests.Statistics/Kernels/AnovaTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Kernels/AnovaTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Kernels; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class AnovaTest { @@ -47,7 +47,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void FunctionTest() { int s = 2; @@ -65,7 +65,7 @@ public void FunctionTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void FunctionTest2() { int s = 2; @@ -80,7 +80,7 @@ public void FunctionTest2() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void FunctionTest3() { int s = 5; diff --git a/Unit Tests/Accord.Tests.Statistics/Kernels/DynamicTimeWarpingTest.cs b/Unit Tests/Accord.Tests.Statistics/Kernels/DynamicTimeWarpingTest.cs index dbee4a876..cc8f053dc 100644 --- a/Unit Tests/Accord.Tests.Statistics/Kernels/DynamicTimeWarpingTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Kernels/DynamicTimeWarpingTest.cs @@ -23,9 +23,9 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Kernels; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class DynamicTimeWarpingTest { @@ -46,7 +46,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void FunctionTest() { var x = new double[] { 0, 4, 2, 1 }; @@ -134,7 +134,7 @@ public void FunctionTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void DistanceTest() { var x = new double[] { 0, 4, 2, 1 }; @@ -223,7 +223,7 @@ public void DistanceTest() } - [TestMethod()] + [Test] public void FunctionTest_EqualInputs() { var x = new double[] { 1, 2, 5, 1 }; diff --git a/Unit Tests/Accord.Tests.Statistics/Kernels/GaussianDtwTest.cs b/Unit Tests/Accord.Tests.Statistics/Kernels/GaussianDtwTest.cs index dadc5666d..4a4d32ed1 100644 --- a/Unit Tests/Accord.Tests.Statistics/Kernels/GaussianDtwTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Kernels/GaussianDtwTest.cs @@ -24,10 +24,10 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Kernels; using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System.Diagnostics; - [TestClass()] + [TestFixture] public class GaussianDtwTest { @@ -47,7 +47,7 @@ public TestContext TestContext } - [TestMethod] + [Test] public void GaussianFunctionTest() { var x = new double[] { 0, 4, 2, 1 }; @@ -71,7 +71,7 @@ public void GaussianFunctionTest() Assert.AreEqual(0.99065918303292089, actual); } - [TestMethod] + [Test] public void GammaSigmaTest() { var dtw = new DynamicTimeWarping(1); @@ -99,7 +99,7 @@ public void GammaSigmaTest() Assert.AreEqual(expected, actual, 1e-12); } - [TestMethod] + [Test] public void GammaSigmaSquaredTest() { var dtw = new DynamicTimeWarping(1); @@ -125,7 +125,7 @@ public void GammaSigmaSquaredTest() Assert.AreEqual(1.0 / (2 * 49), gaussian.Gamma); } - [TestMethod] + [Test] public void GaussianEstimateTest() { // Suppose we have the following data @@ -148,7 +148,7 @@ public void GaussianEstimateTest() Assert.AreEqual(sigma * sigma, sigma2); } - [TestMethod()] + [Test] public void FunctionTest_EqualInputs() { var x = new double[] { 1, 2, 5, 1 }; diff --git a/Unit Tests/Accord.Tests.Statistics/Kernels/GaussianLinearTest.cs b/Unit Tests/Accord.Tests.Statistics/Kernels/GaussianLinearTest.cs index 0b81fde39..678ff27d1 100644 --- a/Unit Tests/Accord.Tests.Statistics/Kernels/GaussianLinearTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Kernels/GaussianLinearTest.cs @@ -24,10 +24,10 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Kernels; using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System.Diagnostics; - [TestClass()] + [TestFixture] public class GaussianLinearTest { @@ -47,7 +47,7 @@ public TestContext TestContext } - [TestMethod] + [Test] public void GaussianFunctionTest() { IKernel gaussian = new Gaussian(new Linear(0), 1); @@ -73,7 +73,7 @@ public void GaussianFunctionTest() Assert.AreEqual(expected, actual, 1e-10); } - [TestMethod] + [Test] public void GaussianDistanceTest() { var gaussian = new Gaussian(new Linear(0), 1); @@ -98,7 +98,7 @@ public void GaussianDistanceTest() Assert.AreEqual(expected, actual, 1e-10); } - [TestMethod()] + [Test] public void FunctionTest() { double sigma = 0.1; @@ -118,7 +118,7 @@ public void FunctionTest() Assert.AreEqual(expected, actual); } - [TestMethod] + [Test] public void GammaSigmaTest() { var gaussian = new Gaussian(new Linear(0), 1); @@ -144,7 +144,7 @@ public void GammaSigmaTest() Assert.AreEqual(expected, actual, 1e-12); } - [TestMethod] + [Test] public void GammaSigmaSquaredTest() { var gaussian = new Gaussian(new Linear(0), 3.6); @@ -168,7 +168,7 @@ public void GammaSigmaSquaredTest() Assert.AreEqual(1.0 / (2 * 49), gaussian.Gamma); } - [TestMethod] + [Test] public void FunctionTest2() { // Tested against R's kernlab @@ -209,7 +209,7 @@ public void FunctionTest2() } - [TestMethod] + [Test] public void GaussianEstimateTest() { // Suppose we have the following data @@ -231,7 +231,7 @@ public void GaussianEstimateTest() Assert.AreEqual(sigma * sigma, sigma2); } - [TestMethod()] + [Test] public void FunctionTest_EqualInputs() { var x = new double[] { 1, 2, 5, 1 }; diff --git a/Unit Tests/Accord.Tests.Statistics/Kernels/GaussianTest.cs b/Unit Tests/Accord.Tests.Statistics/Kernels/GaussianTest.cs index cbd7c145c..1a3ac77b3 100644 --- a/Unit Tests/Accord.Tests.Statistics/Kernels/GaussianTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Kernels/GaussianTest.cs @@ -24,10 +24,10 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Kernels; using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System.Diagnostics; - [TestClass()] + [TestFixture] public class GaussianTest { @@ -47,7 +47,7 @@ public TestContext TestContext } - [TestMethod] + [Test] public void GaussianFunctionTest() { IKernel gaussian = new Gaussian(1); @@ -73,7 +73,7 @@ public void GaussianFunctionTest() Assert.AreEqual(expected, actual, 1e-10); } - [TestMethod] + [Test] public void GaussianDistanceTest() { var gaussian = new Gaussian(1); @@ -98,7 +98,7 @@ public void GaussianDistanceTest() Assert.AreEqual(expected, actual, 1e-10); } - [TestMethod()] + [Test] public void FunctionTest() { double sigma = 0.1; @@ -118,7 +118,7 @@ public void FunctionTest() Assert.AreEqual(expected, actual); } - [TestMethod] + [Test] public void GammaSigmaTest() { Gaussian gaussian = new Gaussian(1); @@ -144,7 +144,7 @@ public void GammaSigmaTest() Assert.AreEqual(expected, actual, 1e-12); } - [TestMethod] + [Test] public void GammaSigmaSquaredTest() { Gaussian gaussian = new Gaussian(3.6); @@ -168,7 +168,7 @@ public void GammaSigmaSquaredTest() Assert.AreEqual(1.0 / (2 * 49), gaussian.Gamma); } - [TestMethod] + [Test] public void FunctionTest2() { // Tested against R's kernlab @@ -209,7 +209,7 @@ public void FunctionTest2() } - [TestMethod] + [Test] public void GaussianReverseDistanceTest() { var gaussian = new Gaussian(4.2); @@ -225,7 +225,7 @@ public void GaussianReverseDistanceTest() Assert.AreEqual(expected, actual, 1e-10); } - [TestMethod] + [Test] public void GaussianEstimateTest() { // Suppose we have the following data @@ -247,7 +247,7 @@ public void GaussianEstimateTest() Assert.AreEqual(sigma * sigma, sigma2); } - [TestMethod()] + [Test] public void ExpandDistanceTest() { for (int i = 1; i <= 3; i++) @@ -274,7 +274,7 @@ public void ExpandDistanceTest() } } - [TestMethod()] + [Test] public void ExpandReverseDistanceTest() { for (int i = 1; i <= 3; i++) diff --git a/Unit Tests/Accord.Tests.Statistics/Kernels/KernelFunctionCacheTest.cs b/Unit Tests/Accord.Tests.Statistics/Kernels/KernelFunctionCacheTest.cs index f968759c5..5e61981af 100644 --- a/Unit Tests/Accord.Tests.Statistics/Kernels/KernelFunctionCacheTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Kernels/KernelFunctionCacheTest.cs @@ -3,13 +3,13 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Kernels; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using System.Collections.Generic; using Accord.Math; using System.Linq; - [TestClass()] + [TestFixture] public class KernelFunctionCacheTest { @@ -44,7 +44,7 @@ public TestContext TestContext }; - [TestMethod()] + [Test] public void KernelFunctionCacheConstructorTest() { IKernel kernel = new Linear(1); @@ -83,7 +83,7 @@ public void KernelFunctionCacheConstructorTest() } - [TestMethod()] + [Test] public void KernelFunctionCacheConstructorTest2() { IKernel kernel = new Linear(1); @@ -139,7 +139,7 @@ public void KernelFunctionCacheConstructorTest2() Assert.AreEqual(1.0, target.Usage); } - [TestMethod()] + [Test] public void KernelFunctionCacheConstructorTest6() { IKernel kernel = new Gaussian(0.6); @@ -190,7 +190,7 @@ public void KernelFunctionCacheConstructorTest6() Assert.AreEqual(1.0, target.Usage); } - [TestMethod()] + [Test] public void KernelFunctionCacheConstructorTest5() { IKernel kernel = new Linear(1); @@ -238,7 +238,7 @@ public void KernelFunctionCacheConstructorTest5() Assert.AreEqual(1.0, target.Usage); } - [TestMethod()] + [Test] public void KernelFunctionCacheConstructorTest7() { double[][] inputs = @@ -296,7 +296,7 @@ public void KernelFunctionCacheConstructorTest7() Assert.AreEqual(3, target.Hits); Assert.AreEqual(1.0, target.Usage); } - [TestMethod()] + [Test] public void KernelFunctionCacheConstructorTest3() { IKernel kernel = new Linear(1); @@ -351,7 +351,7 @@ public void KernelFunctionCacheConstructorTest3() } - [TestMethod()] + [Test] public void KernelFunctionCacheConstructorTest4() { IKernel kernel = new Linear(); diff --git a/Unit Tests/Accord.Tests.Statistics/Kernels/LaplacianTest.cs b/Unit Tests/Accord.Tests.Statistics/Kernels/LaplacianTest.cs index f42ddd633..66728bf5c 100644 --- a/Unit Tests/Accord.Tests.Statistics/Kernels/LaplacianTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Kernels/LaplacianTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Kernels; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; - [TestClass()] + [TestFixture] public class LaplacianTest { @@ -47,7 +47,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void FunctionTest() { double sigma = 2.1; @@ -64,7 +64,7 @@ public void FunctionTest() Assert.AreEqual(1.0, target.Function(x, x)); } - [TestMethod] + [Test] public void LaplacianReverseDistanceTest() { var laplacian = new Laplacian(4.2); diff --git a/Unit Tests/Accord.Tests.Statistics/Kernels/LinearTest.cs b/Unit Tests/Accord.Tests.Statistics/Kernels/LinearTest.cs index a6ad7f2ad..d4bd52549 100644 --- a/Unit Tests/Accord.Tests.Statistics/Kernels/LinearTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Kernels/LinearTest.cs @@ -24,10 +24,10 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Kernels; using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System.Diagnostics; - [TestClass()] + [TestFixture] public class LinearTest { @@ -47,7 +47,7 @@ public TestContext TestContext } - [TestMethod] + [Test] public void FunctionTest() { IKernel linear = new Linear(1); @@ -73,7 +73,7 @@ public void FunctionTest() Assert.AreEqual(expected, actual); } - [TestMethod] + [Test] public void DistanceTest() { var linear = new Linear(1); @@ -98,7 +98,7 @@ public void DistanceTest() Assert.AreEqual(expected, actual, 1e-10); } - [TestMethod] + [Test] public void ReverseDistanceTest() { var linear = new Linear(1); @@ -123,7 +123,7 @@ public void ReverseDistanceTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void FunctionTest2() { double constant = 0.1; @@ -146,7 +146,7 @@ public void FunctionTest2() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void ExpandDistanceTest() { Linear kernel = new Linear(42); @@ -163,7 +163,7 @@ public void ExpandDistanceTest() Assert.AreEqual(phi_d, d); } - [TestMethod()] + [Test] public void ExpandReverseDistanceTest() { Linear kernel = new Linear(42); diff --git a/Unit Tests/Accord.Tests.Statistics/Kernels/PolynomialTest.cs b/Unit Tests/Accord.Tests.Statistics/Kernels/PolynomialTest.cs index 0057e75ce..20e4440a2 100644 --- a/Unit Tests/Accord.Tests.Statistics/Kernels/PolynomialTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Kernels/PolynomialTest.cs @@ -24,10 +24,10 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Kernels; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; - [TestClass()] + [TestFixture] public class PolynomialTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void DistanceTest() { Polynomial target = new Polynomial(1); @@ -80,7 +80,7 @@ public void DistanceTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void FunctionTest() { Polynomial target = new Polynomial(1, 0); @@ -112,7 +112,7 @@ public void FunctionTest() Assert.AreEqual(expected, actual, 0.0001); } - [TestMethod] + [Test] public void FunctionTest2() { // Tested against R's kernlab @@ -152,7 +152,7 @@ public void FunctionTest2() Assert.AreEqual(expected[i, j], actual[i, j], 1e-2); } - [TestMethod()] + [Test] public void ExpandDistanceTest() { for (int i = 1; i <= 10; i++) @@ -177,7 +177,7 @@ public void ExpandDistanceTest() } } - [TestMethod()] + [Test] public void ExpandReverseDistanceTest() { for (int i = 1; i <= 10; i++) @@ -203,7 +203,7 @@ public void ExpandReverseDistanceTest() } } - [TestMethod()] + [Test] public void TransformTest_Linear() { double[][] data = @@ -224,7 +224,7 @@ public void TransformTest_Linear() Assert.IsTrue(expected.IsEqual(actual, 1e-10)); } - [TestMethod()] + [Test] public void TransformTest_Quadratic() { double[][] data = diff --git a/Unit Tests/Accord.Tests.Statistics/Kernels/QuadraticTest.cs b/Unit Tests/Accord.Tests.Statistics/Kernels/QuadraticTest.cs index c3eda2e47..181d4a1dc 100644 --- a/Unit Tests/Accord.Tests.Statistics/Kernels/QuadraticTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Kernels/QuadraticTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Kernels; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; - [TestClass()] + [TestFixture] public class QuadraticTest { @@ -47,7 +47,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void DistanceTest() { Quadratic target = new Quadratic(1); @@ -79,7 +79,7 @@ public void DistanceTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void FunctionTest() { Quadratic target = new Quadratic(0); @@ -111,7 +111,7 @@ public void FunctionTest() Assert.AreEqual(expected, actual, 0.0001); } - [TestMethod()] + [Test] public void ExpandDistanceTest() { Quadratic kernel = new Quadratic(0); @@ -128,7 +128,7 @@ public void ExpandDistanceTest() Assert.AreEqual(phi_d, d); } - [TestMethod()] + [Test] public void ExpandReverseDistanceTest() { Quadratic kernel = new Quadratic(0); @@ -145,7 +145,7 @@ public void ExpandReverseDistanceTest() Assert.AreEqual(phi_d, d); } - [TestMethod()] + [Test] public void ExpandDistanceWithConstantTest() { Quadratic kernel = new Quadratic(4.2); @@ -169,7 +169,7 @@ public void ExpandDistanceWithConstantTest() Assert.IsFalse(double.IsNaN(d3)); } - [TestMethod()] + [Test] public void ExpandReverseDistanceWithConstantTest() { Quadratic kernel = new Quadratic(4.2); diff --git a/Unit Tests/Accord.Tests.Statistics/Kernels/Sparse/SparseCauchyTest.cs b/Unit Tests/Accord.Tests.Statistics/Kernels/Sparse/SparseCauchyTest.cs index e8d8270df..e4fc3e47a 100644 --- a/Unit Tests/Accord.Tests.Statistics/Kernels/Sparse/SparseCauchyTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Kernels/Sparse/SparseCauchyTest.cs @@ -1,89 +1,71 @@ -// Accord Unit Tests -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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 -// - -using Accord.Statistics.Kernels.Sparse; -using Accord.Statistics.Kernels; -using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace Accord.Tests.Statistics -{ - - - /// - ///This is a test class for SparseLinearTest and is intended - ///to contain all SparseLinearTest Unit Tests - /// - [TestClass()] - public class SparseCauchyTest - { - - - private TestContext testContextInstance; - - /// - ///Gets or sets the test context which provides - ///information about and functionality for the current test run. - /// - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - [TestMethod()] - public void FunctionTest() - { - Cauchy dense = new Cauchy(3.6); - SparseCauchy target = new SparseCauchy(3.6); - - double[] sx = { 1, -0.555556, 2, +0.250000, 3, -0.864407, 4, -0.916667 }; - double[] sy = { 1, -0.666667, 2, -0.166667, 3, -0.864407, 4, -0.916667 }; - double[] sz = { 1, -0.944444, 3, -0.898305, 4, -0.916667 }; - - double[] dx = { -0.555556, +0.250000, -0.864407, -0.916667 }; - double[] dy = { -0.666667, -0.166667, -0.864407, -0.916667 }; - double[] dz = { -0.944444, +0.000000, -0.898305, -0.916667 }; - - double expected, actual; - - expected = dense.Function(dx, dy); - actual = target.Function(sx, sy); - Assert.AreEqual(expected, actual); - - expected = dense.Function(dx, dz); - actual = target.Function(sx, sz); - Assert.AreEqual(expected, actual); - - expected = dense.Function(dy, dz); - actual = target.Function(sy, sz); - Assert.AreEqual(expected, actual); - } - - - } -} +// Accord Unit Tests +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Tests.Statistics +{ + using Accord.Statistics.Kernels.Sparse; + using Accord.Statistics.Kernels; + using NUnit.Framework; + + [TestFixture] + public class SparseCauchyTest + { + + [Test] + public void FunctionTest2() + { + SparseLinearTest.SparseTest(new Cauchy(0), new SparseCauchy(0)); + SparseLinearTest.SparseTest(new Cauchy(3.6), new SparseCauchy(3.6)); + } + + [Test] + public void FunctionTest() + { + Cauchy dense = new Cauchy(3.6); + SparseCauchy target = new SparseCauchy(3.6); + + double[] sx = { 1, -0.555556, 2, +0.250000, 3, -0.864407, 4, -0.916667 }; + double[] sy = { 1, -0.666667, 2, -0.166667, 3, -0.864407, 4, -0.916667 }; + double[] sz = { 1, -0.944444, 3, -0.898305, 4, -0.916667 }; + + double[] dx = { -0.555556, +0.250000, -0.864407, -0.916667 }; + double[] dy = { -0.666667, -0.166667, -0.864407, -0.916667 }; + double[] dz = { -0.944444, +0.000000, -0.898305, -0.916667 }; + + double expected, actual; + + expected = dense.Function(dx, dy); + actual = target.Function(sx, sy); + Assert.AreEqual(expected, actual); + + expected = dense.Function(dx, dz); + actual = target.Function(sx, sz); + Assert.AreEqual(expected, actual); + + expected = dense.Function(dy, dz); + actual = target.Function(sy, sz); + Assert.AreEqual(expected, actual); + } + + + } +} diff --git a/Unit Tests/Accord.Tests.Statistics/Kernels/Sparse/SparseGaussianTest.cs b/Unit Tests/Accord.Tests.Statistics/Kernels/Sparse/SparseGaussianTest.cs index eb2516e8f..7b3f8f98c 100644 --- a/Unit Tests/Accord.Tests.Statistics/Kernels/Sparse/SparseGaussianTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Kernels/Sparse/SparseGaussianTest.cs @@ -24,31 +24,22 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Kernels.Sparse; using Accord.Statistics.Kernels; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; /// - [TestClass()] + [TestFixture] public class SparseGaussianTest - { - - - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } + { + + [Test] + public void FunctionTest2() + { + SparseLinearTest.SparseTest(new Gaussian(), new SparseGaussian()); + SparseLinearTest.SparseTest(new Gaussian(0), new SparseGaussian(0)); + SparseLinearTest.SparseTest(new Gaussian(3.6), new SparseGaussian(3.6)); } - - - [TestMethod()] + [Test] public void FunctionTest() { Gaussian dense = new Gaussian(3.6); @@ -77,7 +68,7 @@ public void FunctionTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void DistanceTest() { Gaussian dense = new Gaussian(3.6); diff --git a/Unit Tests/Accord.Tests.Statistics/Kernels/Sparse/SparseLaplacianTest.cs b/Unit Tests/Accord.Tests.Statistics/Kernels/Sparse/SparseLaplacianTest.cs index 33efcd0de..deeed59a6 100644 --- a/Unit Tests/Accord.Tests.Statistics/Kernels/Sparse/SparseLaplacianTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Kernels/Sparse/SparseLaplacianTest.cs @@ -1,117 +1,108 @@ -// Accord Unit Tests -// The Accord.NET Framework -// http://accord-framework.net -// -// Copyright © César Souza, 2009-2015 -// 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.Tests.Statistics -{ - using Accord.Statistics.Kernels.Sparse; - using Accord.Statistics.Kernels; - using Microsoft.VisualStudio.TestTools.UnitTesting; - - [TestClass()] - public class SparseLaplacianTest - { - - - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - - [TestMethod()] - public void FunctionTest() - { - Laplacian dense = new Laplacian(3.6); - SparseLaplacian target = new SparseLaplacian(3.6); - - double[] sx = { 1, -0.555556, 2, +0.250000, 3, -0.864407, 4, -0.916667 }; - double[] sy = { 1, -0.666667, 2, -0.166667, 3, -0.864407, 4, -0.916667 }; - double[] sz = { 1, -0.944444, 3, -0.898305, 4, -0.916667 }; - - double[] dx = { -0.555556, +0.250000, -0.864407, -0.916667 }; - double[] dy = { -0.666667, -0.166667, -0.864407, -0.916667 }; - double[] dz = { -0.944444, +0.000000, -0.898305, -0.916667 }; - - double expected, actual; - - expected = dense.Function(dx, dy); - actual = target.Function(sx, sy); - Assert.AreEqual(expected, actual, 1e-10); - Assert.AreEqual(0.88711080792421337, actual); - Assert.IsFalse(double.IsNaN(actual)); - - expected = dense.Function(dx, dz); - actual = target.Function(sx, sz); - Assert.AreEqual(expected, actual, 1e-10); - Assert.AreEqual(0.87918038010432886, actual, 1e-10); - Assert.IsFalse(double.IsNaN(actual)); - - expected = dense.Function(dy, dz); - actual = target.Function(sy, sz); - Assert.AreEqual(expected, actual, 1e-10); - Assert.AreEqual(0.91349716289496652, actual); - Assert.IsFalse(double.IsNaN(actual)); - } - - [TestMethod()] - public void DistanceTest() - { - Laplacian dense = new Laplacian(3.6); - SparseLaplacian target = new SparseLaplacian(3.6); - - double[] sx = { 1, -0.555556, 2, +0.250000, 3, -0.864407, 4, -0.916667 }; - double[] sy = { 1, -0.666667, 2, -0.166667, 3, -0.864407, 4, -0.916667 }; - double[] sz = { 1, -0.944444, 3, -0.898305, 4, -0.916667 }; - - double[] dx = { -0.555556, +0.250000, -0.864407, -0.916667 }; - double[] dy = { -0.666667, -0.166667, -0.864407, -0.916667 }; - double[] dz = { -0.944444, +0.000000, -0.898305, -0.916667 }; - - double expected, actual; - - expected = dense.Distance(dx, dy); - actual = target.Distance(sx, sy); - Assert.AreEqual(expected, actual, 1e-10); - Assert.IsFalse(double.IsNaN(actual)); - - expected = dense.Distance(dx, dz); - actual = target.Distance(sx, sz); - Assert.AreEqual(expected, actual, 1e-10); - Assert.IsFalse(double.IsNaN(actual)); - - expected = dense.Distance(dy, dz); - actual = target.Distance(sy, sz); - Assert.AreEqual(expected, actual, 1e-10); - Assert.IsFalse(double.IsNaN(actual)); - } - } -} +// Accord Unit Tests +// The Accord.NET Framework +// http://accord-framework.net +// +// Copyright © César Souza, 2009-2015 +// 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.Tests.Statistics +{ + using Accord.Statistics.Kernels.Sparse; + using Accord.Statistics.Kernels; + using NUnit.Framework; + + [TestFixture] + public class SparseLaplacianTest + { + + [Test] + public void FunctionTest2() + { + SparseLinearTest.SparseTest(new Laplacian(), new SparseLaplacian()); + SparseLinearTest.SparseTest(new Laplacian(0), new SparseLaplacian(0)); + SparseLinearTest.SparseTest(new Laplacian(3.6), new SparseLaplacian(3.6)); + } + + [Test] + public void FunctionTest() + { + Laplacian dense = new Laplacian(3.6); + SparseLaplacian target = new SparseLaplacian(3.6); + + double[] sx = { 1, -0.555556, 2, +0.250000, 3, -0.864407, 4, -0.916667 }; + double[] sy = { 1, -0.666667, 2, -0.166667, 3, -0.864407, 4, -0.916667 }; + double[] sz = { 1, -0.944444, 3, -0.898305, 4, -0.916667 }; + + double[] dx = { -0.555556, +0.250000, -0.864407, -0.916667 }; + double[] dy = { -0.666667, -0.166667, -0.864407, -0.916667 }; + double[] dz = { -0.944444, +0.000000, -0.898305, -0.916667 }; + + double expected, actual; + + expected = dense.Function(dx, dy); + actual = target.Function(sx, sy); + Assert.AreEqual(expected, actual, 1e-10); + Assert.AreEqual(0.88711080792421337, actual); + Assert.IsFalse(double.IsNaN(actual)); + + expected = dense.Function(dx, dz); + actual = target.Function(sx, sz); + Assert.AreEqual(expected, actual, 1e-10); + Assert.AreEqual(0.87918038010432886, actual, 1e-10); + Assert.IsFalse(double.IsNaN(actual)); + + expected = dense.Function(dy, dz); + actual = target.Function(sy, sz); + Assert.AreEqual(expected, actual, 1e-10); + Assert.AreEqual(0.91349716289496652, actual); + Assert.IsFalse(double.IsNaN(actual)); + } + + [Test] + public void DistanceTest() + { + Laplacian dense = new Laplacian(3.6); + SparseLaplacian target = new SparseLaplacian(3.6); + + double[] sx = { 1, -0.555556, 2, +0.250000, 3, -0.864407, 4, -0.916667 }; + double[] sy = { 1, -0.666667, 2, -0.166667, 3, -0.864407, 4, -0.916667 }; + double[] sz = { 1, -0.944444, 3, -0.898305, 4, -0.916667 }; + + double[] dx = { -0.555556, +0.250000, -0.864407, -0.916667 }; + double[] dy = { -0.666667, -0.166667, -0.864407, -0.916667 }; + double[] dz = { -0.944444, +0.000000, -0.898305, -0.916667 }; + + double expected, actual; + + expected = dense.Distance(dx, dy); + actual = target.Distance(sx, sy); + Assert.AreEqual(expected, actual, 1e-10); + Assert.IsFalse(double.IsNaN(actual)); + + expected = dense.Distance(dx, dz); + actual = target.Distance(sx, sz); + Assert.AreEqual(expected, actual, 1e-10); + Assert.IsFalse(double.IsNaN(actual)); + + expected = dense.Distance(dy, dz); + actual = target.Distance(sy, sz); + Assert.AreEqual(expected, actual, 1e-10); + Assert.IsFalse(double.IsNaN(actual)); + } + } +} diff --git a/Unit Tests/Accord.Tests.Statistics/Kernels/Sparse/SparseLinearTest.cs b/Unit Tests/Accord.Tests.Statistics/Kernels/Sparse/SparseLinearTest.cs index 9795ec79e..b86df714c 100644 --- a/Unit Tests/Accord.Tests.Statistics/Kernels/Sparse/SparseLinearTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Kernels/Sparse/SparseLinearTest.cs @@ -24,30 +24,13 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Kernels.Sparse; using Accord.Statistics.Kernels; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class SparseLinearTest { - - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - - [TestMethod()] + [Test] public void FunctionTest() { Linear dense = new Linear(1); @@ -76,7 +59,56 @@ public void FunctionTest() Assert.AreEqual(expected, actual, 1e-10); } - [TestMethod()] + [Test] + public void FunctionTest2() + { + SparseLinearTest.SparseTest(new Linear(), new SparseLinear()); + SparseLinearTest.SparseTest(new Linear(1), new SparseLinear(1)); + } + + public static void SparseTest(KernelBase denseKernel, KernelBase sparseKernel) + { + double[][] sparse = + { + new double[] { }, + new double[] { 2, 1 }, + new double[] { 1, 1 }, + new double[] { 1, 1, 2, 1 } + }; + + double[][] dense = + { + new double[] { 0, 0 }, + new double[] { 0, 1 }, + new double[] { 1, 0 }, + new double[] { 1, 1 }, + }; + + for (int i = 0; i < sparse.Length; i++) + { + for (int j = 0; j < sparse.Length; j++) + { + double expected = denseKernel.Function(dense[i], dense[j]); + double actual = sparseKernel.Function(sparse[i], sparse[j]); + + Assert.AreEqual(expected, actual); + } + } + + for (int i = 0; i < sparse.Length; i++) + { + for (int j = 0; j < sparse.Length; j++) + { + double expected = denseKernel.Distance(dense[i], dense[j]); + double actual = sparseKernel.Distance(sparse[i], sparse[j]); + + Assert.AreEqual(expected, actual); + } + } + } + + + [Test] public void DistanceTest() { Linear dense = new Linear(1); diff --git a/Unit Tests/Accord.Tests.Statistics/Kernels/Sparse/SparsePolynomialTest.cs b/Unit Tests/Accord.Tests.Statistics/Kernels/Sparse/SparsePolynomialTest.cs index fb9a0f8a7..0c2b4f774 100644 --- a/Unit Tests/Accord.Tests.Statistics/Kernels/Sparse/SparsePolynomialTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Kernels/Sparse/SparsePolynomialTest.cs @@ -24,30 +24,21 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Kernels; using Accord.Statistics.Kernels.Sparse; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class SparsePolynomialTest - { - - - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } + { + [Test] + public void FunctionTest2() + { + SparseLinearTest.SparseTest(new Polynomial(1), new SparsePolynomial(1)); + SparseLinearTest.SparseTest(new Polynomial(0), new SparsePolynomial(0)); + SparseLinearTest.SparseTest(new Polynomial(3), new SparsePolynomial(3)); } - - [TestMethod()] + [Test] public void FunctionTest() { Polynomial dense = new Polynomial(3); @@ -76,7 +67,7 @@ public void FunctionTest() Assert.AreEqual(expected, actual, 1e-10); } - [TestMethod()] + [Test] public void DistanceTest() { Polynomial dense = new Polynomial(3); diff --git a/Unit Tests/Accord.Tests.Statistics/Kernels/Sparse/SparseSigmoidTest.cs b/Unit Tests/Accord.Tests.Statistics/Kernels/Sparse/SparseSigmoidTest.cs index 162794636..f9f0c1ba4 100644 --- a/Unit Tests/Accord.Tests.Statistics/Kernels/Sparse/SparseSigmoidTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Kernels/Sparse/SparseSigmoidTest.cs @@ -24,30 +24,22 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Kernels.Sparse; using Accord.Statistics.Kernels; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class SparseSigmoidTest - { - - - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } + { + + [Test] + public void FunctionTest2() + { + SparseLinearTest.SparseTest(new Sigmoid(), new SparseSigmoid()); + SparseLinearTest.SparseTest(new Sigmoid(0, 0), new SparseSigmoid(0, 0)); + SparseLinearTest.SparseTest(new Sigmoid(0, 3.6), new SparseSigmoid(0, 3.6)); + SparseLinearTest.SparseTest(new Sigmoid(3.6, 0), new SparseSigmoid(3.6, 0)); } - - - [TestMethod()] + [Test] public void FunctionTest() { Sigmoid dense = new Sigmoid(3.6, 1); @@ -76,7 +68,7 @@ public void FunctionTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void DistanceTest() { Sigmoid dense = new Sigmoid(3.6, 1); diff --git a/Unit Tests/Accord.Tests.Statistics/Kernels/SplineTest.cs b/Unit Tests/Accord.Tests.Statistics/Kernels/SplineTest.cs index c80f35cad..5a1571eef 100644 --- a/Unit Tests/Accord.Tests.Statistics/Kernels/SplineTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Kernels/SplineTest.cs @@ -21,7 +21,7 @@ // using Accord.Statistics.Kernels; -using Microsoft.VisualStudio.TestTools.UnitTesting; +using NUnit.Framework; namespace Accord.Tests.Statistics { @@ -30,7 +30,7 @@ namespace Accord.Tests.Statistics ///This is a test class for SplineTest and is intended ///to contain all SplineTest Unit Tests /// - [TestClass()] + [TestFixture] public class SplineTest { @@ -54,7 +54,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void KernelTest() { Spline target = new Spline(); diff --git a/Unit Tests/Accord.Tests.Statistics/Links/CauchitLinkFunctionTest.cs b/Unit Tests/Accord.Tests.Statistics/Links/CauchitLinkFunctionTest.cs index 367a479f9..9e0d6d2a3 100644 --- a/Unit Tests/Accord.Tests.Statistics/Links/CauchitLinkFunctionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Links/CauchitLinkFunctionTest.cs @@ -24,9 +24,9 @@ namespace Accord.Tests.Statistics { using System; using Accord.Statistics.Links; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class CauchitLinkFunctionTest { @@ -46,7 +46,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void CauchitLinkFunctionConstructorTest() { CauchitLinkFunction target = new CauchitLinkFunction(); @@ -64,7 +64,7 @@ public void CauchitLinkFunctionConstructorTest() } - [TestMethod()] + [Test] public void DerivativeTest() { double[] expected = diff --git a/Unit Tests/Accord.Tests.Statistics/Links/IdentityLinkFunctionTest.cs b/Unit Tests/Accord.Tests.Statistics/Links/IdentityLinkFunctionTest.cs index 7557405fc..eec79b482 100644 --- a/Unit Tests/Accord.Tests.Statistics/Links/IdentityLinkFunctionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Links/IdentityLinkFunctionTest.cs @@ -23,9 +23,9 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Links; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class IdentityLinkFunctionTest { @@ -46,7 +46,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void IdentityLinkFunctionConstructorTest() { IdentityLinkFunction target = new IdentityLinkFunction(); @@ -62,7 +62,7 @@ public void IdentityLinkFunctionConstructorTest() } } - [TestMethod()] + [Test] public void IdentityLinkFunctionConstructorTest1() { double mean = 3.14; diff --git a/Unit Tests/Accord.Tests.Statistics/Links/InverseLinkFunctionTest.cs b/Unit Tests/Accord.Tests.Statistics/Links/InverseLinkFunctionTest.cs index 014fb00bc..0af605272 100644 --- a/Unit Tests/Accord.Tests.Statistics/Links/InverseLinkFunctionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Links/InverseLinkFunctionTest.cs @@ -24,9 +24,9 @@ namespace Accord.Tests.Statistics { using System; using Accord.Statistics.Links; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class InverseLinkFunctionTest { @@ -46,7 +46,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void InverseLinkFunctionConstructorTest() { InverseLinkFunction target = new InverseLinkFunction(); @@ -63,7 +63,7 @@ public void InverseLinkFunctionConstructorTest() } } - [TestMethod()] + [Test] public void InverseLinkFunctionConstructorTest1() { double beta = 3.14; @@ -83,7 +83,7 @@ public void InverseLinkFunctionConstructorTest1() } } - [TestMethod()] + [Test] public void DerivativeTest() { double beta = 3.14; diff --git a/Unit Tests/Accord.Tests.Statistics/Links/InverseSquaredLinkFunctionTest.cs b/Unit Tests/Accord.Tests.Statistics/Links/InverseSquaredLinkFunctionTest.cs index 8dc94f6eb..418d2f1e9 100644 --- a/Unit Tests/Accord.Tests.Statistics/Links/InverseSquaredLinkFunctionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Links/InverseSquaredLinkFunctionTest.cs @@ -24,9 +24,9 @@ namespace Accord.Tests.Statistics { using System; using Accord.Statistics.Links; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class InverseSquaredLinkFunctionTest { @@ -46,7 +46,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void InverseSquaredLinkFunctionConstructorTest() { InverseSquaredLinkFunction target = new InverseSquaredLinkFunction(); @@ -63,7 +63,7 @@ public void InverseSquaredLinkFunctionConstructorTest() } } - [TestMethod()] + [Test] public void InverseSquaredLinkFunctionConstructorTest1() { double beta = 3.14; @@ -83,7 +83,7 @@ public void InverseSquaredLinkFunctionConstructorTest1() } } - [TestMethod()] + [Test] public void DerivativeTest() { double beta = 3.14; diff --git a/Unit Tests/Accord.Tests.Statistics/Links/LogLinkFunctionTest.cs b/Unit Tests/Accord.Tests.Statistics/Links/LogLinkFunctionTest.cs index 10b840afc..e05d19043 100644 --- a/Unit Tests/Accord.Tests.Statistics/Links/LogLinkFunctionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Links/LogLinkFunctionTest.cs @@ -24,9 +24,9 @@ namespace Accord.Tests.Statistics { using System; using Accord.Statistics.Links; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class LogLinkFunctionTest { @@ -46,7 +46,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void LogLinkFunctionConstructorTest() { double beta = 0.52; @@ -66,7 +66,7 @@ public void LogLinkFunctionConstructorTest() } } - [TestMethod()] + [Test] public void LogLinkFunctionConstructorTest2() { LogLinkFunction target = new LogLinkFunction(); @@ -84,7 +84,7 @@ public void LogLinkFunctionConstructorTest2() } } - [TestMethod()] + [Test] public void DerivativeTest() { double beta = 0.52; diff --git a/Unit Tests/Accord.Tests.Statistics/Links/LogLogLinkFunctionTest.cs b/Unit Tests/Accord.Tests.Statistics/Links/LogLogLinkFunctionTest.cs index 71083dede..43ddd52e2 100644 --- a/Unit Tests/Accord.Tests.Statistics/Links/LogLogLinkFunctionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Links/LogLogLinkFunctionTest.cs @@ -24,9 +24,9 @@ namespace Accord.Tests.Statistics { using System; using Accord.Statistics.Links; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class LogLogLinkFunctionTest { @@ -45,7 +45,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void LogLogLinkFunctionConstructorTest2() { LogLogLinkFunction target = new LogLogLinkFunction(); @@ -63,7 +63,7 @@ public void LogLogLinkFunctionConstructorTest2() } } - [TestMethod()] + [Test] public void LogLogLinkFunctionConstructorTest() { double beta = 3.14; @@ -83,7 +83,7 @@ public void LogLogLinkFunctionConstructorTest() } } - [TestMethod()] + [Test] public void DerivativeTest() { LogLogLinkFunction target = new LogLogLinkFunction(); @@ -111,7 +111,7 @@ public void DerivativeTest() } - [TestMethod()] + [Test] public void DerivativeTest2() { double beta = 2; diff --git a/Unit Tests/Accord.Tests.Statistics/Links/LogitLinkFunctionTest.cs b/Unit Tests/Accord.Tests.Statistics/Links/LogitLinkFunctionTest.cs index d05235622..57c895777 100644 --- a/Unit Tests/Accord.Tests.Statistics/Links/LogitLinkFunctionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Links/LogitLinkFunctionTest.cs @@ -24,9 +24,9 @@ namespace Accord.Tests.Statistics { using System; using Accord.Statistics.Links; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class LogitLinkFunctionTest { @@ -46,7 +46,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void LogitLinkFunctionConstructorTest() { LogitLinkFunction target = new LogitLinkFunction(); @@ -63,7 +63,7 @@ public void LogitLinkFunctionConstructorTest() } } - [TestMethod()] + [Test] public void LogitLinkFunctionConstructorTest1() { double beta = 3.14; @@ -83,7 +83,7 @@ public void LogitLinkFunctionConstructorTest1() } } - [TestMethod()] + [Test] public void DerivativeTest() { double[] expected = @@ -110,7 +110,7 @@ public void DerivativeTest() } } - [TestMethod()] + [Test] public void DerivativeTest2() { double beta = 4.2; diff --git a/Unit Tests/Accord.Tests.Statistics/Links/ProbitLinkFunctionTest.cs b/Unit Tests/Accord.Tests.Statistics/Links/ProbitLinkFunctionTest.cs index ffdd2fb3a..cf088e634 100644 --- a/Unit Tests/Accord.Tests.Statistics/Links/ProbitLinkFunctionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Links/ProbitLinkFunctionTest.cs @@ -24,9 +24,9 @@ namespace Accord.Tests.Statistics { using System; using Accord.Statistics.Links; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class ProbitLinkFunctionTest { @@ -46,7 +46,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ProbitLinkFunctionConstructorTest() { ProbitLinkFunction target = new ProbitLinkFunction(); @@ -74,7 +74,7 @@ public void ProbitLinkFunctionConstructorTest() } - [TestMethod()] + [Test] public void DerivativeTest() { ProbitLinkFunction target = new ProbitLinkFunction(); diff --git a/Unit Tests/Accord.Tests.Statistics/Links/SinLinkFunctionTest.cs b/Unit Tests/Accord.Tests.Statistics/Links/SinLinkFunctionTest.cs index f28e402f4..1a4d3118a 100644 --- a/Unit Tests/Accord.Tests.Statistics/Links/SinLinkFunctionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Links/SinLinkFunctionTest.cs @@ -24,9 +24,9 @@ namespace Accord.Tests.Statistics { using System; using Accord.Statistics.Links; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class SinLinkFunctionTest { @@ -46,7 +46,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void SinLinkFunctionConstructorTest() { SinLinkFunction target = new SinLinkFunction(); @@ -64,7 +64,7 @@ public void SinLinkFunctionConstructorTest() } - [TestMethod()] + [Test] public void DerivativeTest() { double[] expected = diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Fields/ConditionalRandomFieldTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Fields/ConditionalRandomFieldTest.cs index 508149baa..6bbdddf01 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Fields/ConditionalRandomFieldTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Fields/ConditionalRandomFieldTest.cs @@ -24,7 +24,7 @@ namespace Accord.Tests.Statistics.Models.Fields { using Accord.Statistics.Models.Fields; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics.Models.Fields.Functions; using Accord.Statistics.Models.Markov; using Accord.Statistics.Models.Markov.Learning; @@ -32,7 +32,7 @@ namespace Accord.Tests.Statistics.Models.Fields using Accord.Statistics.Models.Markov.Topology; - [TestClass()] + [TestFixture] public class ConditionalRandomFieldTest { @@ -53,7 +53,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConditionalRandomFieldConstructorTest() { HiddenMarkovModel hmm = DiscreteHiddenMarkovModelFunctionTest.CreateModel1(); @@ -67,7 +67,7 @@ public void ConditionalRandomFieldConstructorTest() Assert.AreEqual(2, target.States); } - [TestMethod()] + [Test] public void ComputeTest() { @@ -98,7 +98,7 @@ public void ComputeTest() Assert.AreEqual(p1, p2, 1e-6); } - [TestMethod()] + [Test] public void LikelihoodTest() { var hmm = DiscreteHiddenMarkovModelFunctionTest.CreateModel2(); diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Features/FeatureTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Features/FeatureTest.cs index 806d848bd..2e6031b39 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Features/FeatureTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Features/FeatureTest.cs @@ -23,12 +23,12 @@ namespace Accord.Tests.Statistics.Models.Fields { using Accord.Statistics.Models.Fields.Features; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Statistics.Models.Fields.Functions; using Accord.Tests.Statistics.Models.Fields; - [TestClass()] + [TestFixture] public class InitialFeatureTest { @@ -49,7 +49,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ComputeTest() { var hmm = DiscreteHiddenMarkovClassifierPotentialFunctionTest.CreateModel1(); @@ -96,7 +96,7 @@ public void ComputeTest() } } - [TestMethod()] + [Test] public void ComputeTest2() { var hmm = MarkovContinuousFunctionTest.CreateModel1(); @@ -143,7 +143,7 @@ public void ComputeTest2() } } - [TestMethod()] + [Test] public void ComputeTest3() { var hmm = MultivariateMarkovFunctionTest.CreateModel1(); diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Fields/ForwardBackwardAlgorithmTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Fields/ForwardBackwardAlgorithmTest.cs index ca57cb6da..7e126127e 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Fields/ForwardBackwardAlgorithmTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Fields/ForwardBackwardAlgorithmTest.cs @@ -23,7 +23,7 @@ namespace Accord.Tests.Statistics.Models.Fields { using Accord.Statistics.Models.Fields; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics.Models.Fields.Functions; using Accord.Statistics.Models.Markov; using Accord.Math; @@ -34,7 +34,7 @@ namespace Accord.Tests.Statistics.Models.Fields using Accord.Statistics.Models.Markov.Learning; using Accord.Statistics.Distributions.Fitting; - [TestClass()] + [TestFixture] public class ForwardBackwardAlgorithmTest { @@ -55,7 +55,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void BackwardTest() { HiddenMarkovModel hmm = Accord.Tests.Statistics.Models.Markov. @@ -115,7 +115,7 @@ public void BackwardTest() Assert.IsFalse(double.IsNaN(p)); } - [TestMethod()] + [Test] public void BackwardTest2() { HiddenMarkovModel hmm = Accord.Tests.Statistics.Models.Markov. @@ -148,7 +148,7 @@ public void BackwardTest2() Assert.IsFalse(double.IsNaN(p)); } - [TestMethod()] + [Test] public void ForwardTest() { HiddenMarkovModel hmm = Accord.Tests.Statistics.Models.Markov. @@ -202,7 +202,7 @@ public void ForwardTest() Assert.IsFalse(double.IsNaN(p)); } - [TestMethod()] + [Test] public void ForwardTest2() { HiddenMarkovModel hmm = Accord.Tests.Statistics.Models.Markov. @@ -257,7 +257,7 @@ public void ForwardTest2() Assert.IsFalse(double.IsNaN(p)); } - [TestMethod()] + [Test] public void ForwardTest3() { HiddenMarkovModel hmm = Accord.Tests.Statistics.Models.Markov. @@ -293,7 +293,7 @@ public void ForwardTest3() Assert.IsFalse(double.IsNaN(p)); } - [TestMethod()] + [Test] public void ForwardScalingTest() { HiddenMarkovModel hmm = Accord.Tests.Statistics.Models.Markov. @@ -364,7 +364,7 @@ public void ForwardScalingTest() Assert.IsFalse(double.IsNaN(p)); } - [TestMethod()] + [Test] public void ForwardScalingTest2() { HiddenMarkovModel hmm = Accord.Tests.Statistics.Models.Markov. @@ -386,7 +386,7 @@ public void ForwardScalingTest2() Assert.IsFalse(double.IsNaN(p)); } - [TestMethod()] + [Test] public void ForwardBackwardTest() { HiddenMarkovModel hmm = Accord.Tests.Statistics.Models.Markov. @@ -412,7 +412,7 @@ public void ForwardBackwardTest() - [TestMethod()] + [Test] public void LogBackwardTest() { HiddenMarkovModel hmm = Accord.Tests.Statistics.Models.Markov. @@ -441,7 +441,7 @@ public void LogBackwardTest() Assert.IsFalse(double.IsNaN(p)); } - [TestMethod()] + [Test] public void LogBackwardTest2() { HiddenMarkovModel hmm = Accord.Tests.Statistics.Models.Markov. @@ -463,7 +463,7 @@ public void LogBackwardTest2() Assert.IsFalse(double.IsNaN(p)); } - [TestMethod()] + [Test] public void LogForwardTest() { HiddenMarkovModel hmm = Accord.Tests.Statistics.Models.Markov. @@ -491,7 +491,7 @@ public void LogForwardTest() Assert.IsFalse(double.IsNaN(p)); } - [TestMethod()] + [Test] public void LogForwardTest2() { HiddenMarkovModel hmm = Accord.Tests.Statistics.Models.Markov. @@ -519,7 +519,7 @@ public void LogForwardTest2() Assert.IsFalse(double.IsNaN(p)); } - [TestMethod()] + [Test] public void LogForwardTest3() { MultivariateNormalDistribution density = new MultivariateNormalDistribution(3); @@ -558,7 +558,7 @@ public void LogForwardTest3() Assert.IsFalse(double.IsNaN(p)); } - [TestMethod()] + [Test] public void ForwardTest4() { var hmmc = Accord.Tests.Statistics.Models.Fields. @@ -588,7 +588,7 @@ public void ForwardTest4() } - [TestMethod()] + [Test] public void LogForwardTest4() { var hmmc = Accord.Tests.Statistics.Models.Fields. @@ -624,7 +624,7 @@ public void LogForwardTest4() } } - [TestMethod()] + [Test] public void LogForwardBackwardTest() { HiddenMarkovModel hmm = Accord.Tests.Statistics.Models.Markov. diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Functions/ContinuousMarkovFunctionTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Functions/ContinuousMarkovFunctionTest.cs index 67be14bef..845c5231b 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Functions/ContinuousMarkovFunctionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Functions/ContinuousMarkovFunctionTest.cs @@ -28,10 +28,10 @@ namespace Accord.Tests.Statistics.Models.Fields using Accord.Statistics.Models.Markov; using Accord.Statistics.Models.Markov.Learning; using Accord.Statistics.Models.Markov.Topology; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics.Models.Fields.Functions.Specialized; - [TestClass()] + [TestFixture] public class MarkovContinuousFunctionTest { @@ -88,7 +88,7 @@ public static HiddenMarkovClassifier CreateModel1() } - [TestMethod()] + [Test] public void HiddenMarkovHiddenPotentialFunctionConstructorTest() { HiddenMarkovClassifier model = CreateModel1(); @@ -132,7 +132,7 @@ public void HiddenMarkovHiddenPotentialFunctionConstructorTest() } - [TestMethod()] + [Test] public void ComputeTest() { var model = CreateModel1(); @@ -174,7 +174,7 @@ public void ComputeTest() } } - [TestMethod()] + [Test] public void ComputeDeoptimizedTest() { var model = CreateModel1(); diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Functions/DiscreteHiddenMarkovClassifierFunctionTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Functions/DiscreteHiddenMarkovClassifierFunctionTest.cs index babf1d337..8cc7afb9c 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Functions/DiscreteHiddenMarkovClassifierFunctionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Functions/DiscreteHiddenMarkovClassifierFunctionTest.cs @@ -23,13 +23,13 @@ namespace Accord.Tests.Statistics.Models.Fields { using Accord.Statistics.Models.Fields.Functions; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics.Models.Markov; using Accord.Statistics.Models.Fields.Features; using Accord.Statistics.Models.Markov.Learning; using System; - [TestClass()] + [TestFixture] public class DiscreteHiddenMarkovClassifierPotentialFunctionTest { @@ -103,7 +103,7 @@ public static HiddenMarkovClassifier CreateModel1() } - [TestMethod()] + [Test] public void HiddenMarkovHiddenPotentialFunctionConstructorTest() { HiddenMarkovClassifier model = CreateModel1(); @@ -136,7 +136,7 @@ public void HiddenMarkovHiddenPotentialFunctionConstructorTest() } - [TestMethod()] + [Test] public void ComputeTest() { HiddenMarkovClassifier model = CreateModel1(); diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Functions/DiscreteHiddenMarkovModelFunctionTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Functions/DiscreteHiddenMarkovModelFunctionTest.cs index 98eb453c4..846644ccd 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Functions/DiscreteHiddenMarkovModelFunctionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Functions/DiscreteHiddenMarkovModelFunctionTest.cs @@ -23,14 +23,14 @@ namespace Accord.Tests.Statistics.Models.Fields { using Accord.Statistics.Models.Fields.Functions; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics.Models.Markov; using Accord.Statistics.Models.Fields.Features; using Accord.Statistics.Models.Markov.Topology; using Accord.Statistics.Models.Markov.Learning; using System; - [TestClass()] + [TestFixture] public class DiscreteHiddenMarkovModelFunctionTest { @@ -98,7 +98,7 @@ public static HiddenMarkovModel CreateModel2() return hmm; } - [TestMethod()] + [Test] public void HiddenMarkovModelFunctionConstructorTest() { HiddenMarkovModel model = CreateModel1(); @@ -126,7 +126,7 @@ public void HiddenMarkovModelFunctionConstructorTest() } - [TestMethod()] + [Test] public void ComputeTest() { HiddenMarkovModel model = CreateModel1(); diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Functions/IndependentMarkovFunctionTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Functions/IndependentMarkovFunctionTest.cs index 639080b73..148d0c794 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Functions/IndependentMarkovFunctionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Functions/IndependentMarkovFunctionTest.cs @@ -21,45 +21,25 @@ // namespace Accord.Tests.Statistics.Models.Fields -{ - using System; - using Accord.Math.Differentiation; - using Accord.Statistics.Distributions.Multivariate; - using Accord.Statistics.Distributions.Univariate; - using Accord.Statistics.Models.Fields; - using Accord.Statistics.Models.Fields.Functions; - using Accord.Statistics.Models.Fields.Learning; - using Accord.Statistics.Models.Markov; - using Accord.Statistics.Models.Markov.Learning; - using Accord.Statistics.Models.Markov.Topology; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using Accord.Statistics.Distributions.Fitting; - using Accord.Math; - using Accord.Statistics.Models.Fields.Functions.Specialized; - using System.Collections.Generic; - using Accord.Statistics.Models.Fields.Features; - using System.Linq; - - [TestClass()] +{ + using Accord.Math; + using Accord.Math.Differentiation; + using Accord.Statistics.Distributions.Fitting; + using Accord.Statistics.Distributions.Multivariate; + using Accord.Statistics.Distributions.Univariate; + using Accord.Statistics.Models.Fields; + using Accord.Statistics.Models.Fields.Functions; + using Accord.Statistics.Models.Fields.Learning; + using Accord.Statistics.Models.Markov; + using Accord.Statistics.Models.Markov.Learning; + using Accord.Statistics.Models.Markov.Topology; + using NUnit.Framework; + using System; + + [TestFixture] public class IndependentMarkovFunctionTest { - - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - public static HiddenMarkovClassifier CreateModel1() { // Create a Continuous density Hidden Markov Model Sequence Classifier @@ -108,8 +88,9 @@ public static HiddenMarkovClassifier CreateModel1() ); // Train the sequence classifier using the algorithm - double logLikelihood = teacher.Run(sequences, labels); - + double logLikelihood = teacher.Run(sequences, labels); + + Assert.AreEqual(-13.271981026832929d, logLikelihood); return classifier; } @@ -166,7 +147,9 @@ public static HiddenMarkovClassifier CreateModel2(out double[][][] ); // Train the sequence classifier using the algorithm - double logLikelihood = teacher.Run(sequences, labels); + double logLikelihood = teacher.Run(sequences, labels); + + Assert.AreEqual(double.NegativeInfinity, logLikelihood); // only one training sample per class return classifier; } @@ -269,7 +252,9 @@ public static HiddenMarkovClassifier CreateModel3(out double[][][] ); // Train the sequence classifier using the algorithm - double logLikelihood = teacher.Run(sequences2, labels2); + double logLikelihood = teacher.Run(sequences2, labels2); + + Assert.AreEqual(-3.0493028798326081d, logLikelihood); return classifier; } @@ -350,14 +335,16 @@ public static HiddenMarkovClassifier> CreateMode if (usePriors) teacher.Empirical = true; - double logLikelihood = teacher.Run(words, labels); + double logLikelihood = teacher.Run(words, labels); + + Assert.AreEqual(208.38345600145777d, logLikelihood); return classifier; } - [TestMethod()] + [Test] public void ComputeTest() { var model = CreateModel1(); @@ -406,7 +393,7 @@ public void ComputeTest() } } - [TestMethod()] + [Test] public void ComputeTest2() { double[][][] sequences; @@ -457,7 +444,7 @@ public void ComputeTest2() } } - [TestMethod()] + [Test] public void ComputeTest3() { double[][][] sequences2; @@ -521,7 +508,7 @@ public void ComputeTest3() } } - [TestMethod()] + [Test] public void ComputeTest4() { int[] labels; @@ -542,7 +529,7 @@ public void ComputeTest4() check4(words, model, target, hcrf); } - [TestMethod()] + [Test] public void ComputeDeoptimizeTest3() { double[][][] sequences; @@ -565,7 +552,7 @@ public void ComputeDeoptimizeTest3() check4(sequences, model, target, hcrf); } - [TestMethod()] + [Test] public void ComputeDeoptimizeTest4() { int[] labels; @@ -691,7 +678,7 @@ private static void check4(double[][][] words, HiddenMarkovClassifier model, double[] param - [TestMethod()] + [Test] public void GradientDeoptimizeTest2() { double[][][] sequences2; @@ -883,7 +870,7 @@ public void GradientDeoptimizeTest2() } } - [TestMethod()] + [Test] public void GradientDeoptimizeTest3() { double[][][] sequences2; diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Functions/MultivariateMarkovFunctionTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Functions/MultivariateMarkovFunctionTest.cs index 7dded2cd1..471e02d4a 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Functions/MultivariateMarkovFunctionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Functions/MultivariateMarkovFunctionTest.cs @@ -28,13 +28,13 @@ namespace Accord.Tests.Statistics.Models.Fields using Accord.Statistics.Models.Markov; using Accord.Statistics.Models.Markov.Learning; using Accord.Statistics.Models.Markov.Topology; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics.Distributions.Fitting; using Accord.Statistics.Models.Fields; using Accord.Statistics.Models.Fields.Functions.Specialized; using Accord.Math; - [TestClass()] + [TestFixture] public class MultivariateMarkovFunctionTest { @@ -201,7 +201,7 @@ public static HiddenMarkovClassifier CreateModel return classifier; } - [TestMethod()] + [Test] public void HiddenMarkovHiddenPotentialFunctionConstructorTest() { var model = CreateModel1(); @@ -242,7 +242,7 @@ public void HiddenMarkovHiddenPotentialFunctionConstructorTest() } - [TestMethod()] + [Test] public void HiddenMarkovHiddenPotentialFunctionConstructorTest2() { var model = CreateModel2(); @@ -284,7 +284,7 @@ public void HiddenMarkovHiddenPotentialFunctionConstructorTest2() } - [TestMethod()] + [Test] public void ComputeTest() { var model = CreateModel1(); @@ -331,7 +331,7 @@ public void ComputeTest() } - [TestMethod()] + [Test] public void ComputeTest2() { var model = CreateModel2(); @@ -376,7 +376,7 @@ public void ComputeTest2() } - [TestMethod()] + [Test] public void ComputeTest3() { var model = CreateModel3(priors: false); @@ -427,7 +427,7 @@ public void ComputeTest3() } } - [TestMethod()] + [Test] public void ComputeTest4() { var model = CreateModel3(); @@ -479,7 +479,7 @@ public void ComputeTest4() } } - [TestMethod()] + [Test] public void ComputeTest5() { HiddenMarkovClassifier model = diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Fields/HiddenConditionalRandomFieldTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Fields/HiddenConditionalRandomFieldTest.cs index 2cee46c85..803bcc6fd 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Fields/HiddenConditionalRandomFieldTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Fields/HiddenConditionalRandomFieldTest.cs @@ -32,15 +32,15 @@ namespace Accord.Tests.Statistics.Models.Fields using Accord.Statistics.Models.Markov; using Accord.Statistics.Models.Markov.Learning; using Accord.Statistics.Models.Markov.Topology; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System.IO; - [TestClass()] + [TestFixture] public class HiddenConditionalRandomFieldTest { - [TestMethod()] + [Test] public void HiddenConditionalRandomFieldConstructorTest() { HiddenMarkovClassifier hmm = DiscreteHiddenMarkovClassifierPotentialFunctionTest.CreateModel1(); @@ -52,7 +52,7 @@ public void HiddenConditionalRandomFieldConstructorTest() Assert.AreEqual(2, target.Function.Factors[0].States); } - [TestMethod()] + [Test] public void ComputeTest() { HiddenMarkovClassifier hmm = DiscreteHiddenMarkovClassifierPotentialFunctionTest.CreateModel1(); @@ -105,7 +105,7 @@ public void ComputeTest() - [TestMethod()] + [Test] public void SimpleGestureRecognitionTest() { // Let's say we would like to do a very simple mechanism for @@ -289,7 +289,7 @@ public void SimpleGestureRecognitionTest() - [TestMethod()] + [Test] public void NumberOfFeaturesTest() { Independent initial = new Independent( @@ -325,7 +325,7 @@ public void NumberOfFeaturesTest() Assert.AreEqual(4173, expected); } - [TestMethod()] + [Test] public void SaveLoadTest() { double[][] hello = diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Fields/IndependentForwardBackwardAlgorithmTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Fields/IndependentForwardBackwardAlgorithmTest.cs index 0c065fd65..50fa754ad 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Fields/IndependentForwardBackwardAlgorithmTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Fields/IndependentForwardBackwardAlgorithmTest.cs @@ -23,7 +23,7 @@ namespace Accord.Tests.Statistics.Models.Fields { using Accord.Statistics.Models.Fields; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics.Models.Fields.Functions; using Accord.Statistics.Models.Markov; using Accord.Math; @@ -31,7 +31,7 @@ namespace Accord.Tests.Statistics.Models.Fields using Accord.Statistics.Distributions.Multivariate; using Accord.Statistics.Models.Markov.Topology; - [TestClass()] + [TestFixture] public class IndependentForwardBackwardAlgorithmTest { @@ -52,7 +52,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ForwardTest() { double[][][] observations; @@ -93,7 +93,7 @@ public void ForwardTest() } } - [TestMethod()] + [Test] public void LogForwardTest() { double[][][] observations; @@ -121,7 +121,7 @@ public void LogForwardTest() } } - [TestMethod()] + [Test] public void LogBackwardTest() { double[][][] observations; @@ -151,7 +151,7 @@ public void LogBackwardTest() } - [TestMethod()] + [Test] public void ForwardTest2() { double[][][] observations; @@ -196,7 +196,7 @@ public void ForwardTest2() } } - [TestMethod()] + [Test] public void LogForwardTest2() { double[][][] observations; @@ -229,7 +229,7 @@ public void LogForwardTest2() } } - [TestMethod()] + [Test] public void LogBackwardTest2() { double[][][] observations; @@ -262,7 +262,7 @@ public void LogBackwardTest2() } } - [TestMethod()] + [Test] public void LogForwardGesturesTest() { int[] labels; @@ -296,7 +296,7 @@ public void LogForwardGesturesTest() } } - [TestMethod()] + [Test] public void LogForwardGesturesPriorsTest() { int[] labels; @@ -333,7 +333,7 @@ public void LogForwardGesturesPriorsTest() #pragma warning disable 0618 - [TestMethod()] + [Test] public void LogForwardGesturesDeoptimizedTest() { int[] labels; @@ -369,7 +369,7 @@ public void LogForwardGesturesDeoptimizedTest() } } - [TestMethod()] + [Test] public void LogForwardGesturesPriorsDeoptimizedTest() { int[] labels; diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/ConjugateGradientHiddenLearningTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/ConjugateGradientHiddenLearningTest.cs index 09f988be2..57236ccc3 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/ConjugateGradientHiddenLearningTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/ConjugateGradientHiddenLearningTest.cs @@ -27,9 +27,9 @@ namespace Accord.Tests.Statistics.Models.Fields using Accord.Statistics.Models.Fields.Functions; using Accord.Statistics.Models.Fields.Learning; using Accord.Statistics.Models.Markov; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class ConjugateGradientHiddenLearningTest { @@ -49,7 +49,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void RunTest() { var inputs = QuasiNewtonHiddenLearningTest.inputs; @@ -97,7 +97,7 @@ public void RunTest() Assert.IsTrue(ll1 > ll0); } - [TestMethod()] + [Test] public void RunTest2() { var inputs = QuasiNewtonHiddenLearningTest.inputs; diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/ForwardBackwardGradientTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/ForwardBackwardGradientTest.cs index 1026a7a4f..0bcd7b641 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/ForwardBackwardGradientTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/ForwardBackwardGradientTest.cs @@ -28,12 +28,12 @@ namespace Accord.Tests.Statistics.Models.Fields using Accord.Statistics.Models.Fields.Functions; using Accord.Statistics.Models.Fields.Learning; using Accord.Statistics.Models.Markov; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics.Distributions.Multivariate; using Accord.Statistics.Distributions.Univariate; using Accord.Statistics.Models.Markov.Topology; - [TestClass()] + [TestFixture] public class ForwardBackwardLearningTest { @@ -56,7 +56,7 @@ public TestContext TestContext #region Discrete - [TestMethod()] + [Test] public void GradientTest_DiscreteMarkov() { var function = new MarkovDiscreteFunction(2, 2, 2); @@ -82,7 +82,7 @@ public void GradientTest_DiscreteMarkov() } } - [TestMethod()] + [Test] public void GradientTest_DiscreteMarkov2() { HiddenMarkovClassifier hmm = DiscreteHiddenMarkovClassifierPotentialFunctionTest.CreateModel1(); @@ -110,7 +110,7 @@ public void GradientTest_DiscreteMarkov2() } } - [TestMethod()] + [Test] public void GradientTest_DiscreteMarkov3() { HiddenMarkovClassifier hmm = DiscreteHiddenMarkovClassifierPotentialFunctionTest.CreateModel1(); @@ -146,7 +146,7 @@ public void GradientTest_DiscreteMarkov3() #region Markov Independent - [TestMethod()] + [Test] public void GradientTest_MarkovIndependent() { double[][][] observations; @@ -180,7 +180,7 @@ public void GradientTest_MarkovIndependent() } } - [TestMethod()] + [Test] public void GradientTest_MarkovIndependentNormal_Priors() { double[][][] observations; @@ -214,7 +214,7 @@ public void GradientTest_MarkovIndependentNormal_Priors() } } - [TestMethod()] + [Test] public void GradientTest_MarkovIndependentNormal_NoPriors() { double[][][] observations; @@ -250,7 +250,7 @@ public void GradientTest_MarkovIndependentNormal_NoPriors() #endregion - [TestMethod()] + [Test] public void GradientTest_MarkovMultivariate() { // Creates a sequence classifier containing 2 hidden Markov Models @@ -291,7 +291,7 @@ public void GradientTest_MarkovMultivariate() } } - [TestMethod()] + [Test] public void GradientTest_MarkovMultivariate2() { var hmm = MultivariateMarkovFunctionTest.CreateModel1(); @@ -319,7 +319,7 @@ public void GradientTest_MarkovMultivariate2() } } - [TestMethod()] + [Test] public void GradientTest_MarkovMultivariate3() { var hmm = MultivariateMarkovFunctionTest.CreateModel1(); @@ -355,7 +355,7 @@ public void GradientTest_MarkovMultivariate3() - [TestMethod()] + [Test] public void GradientTest_MarkovNormal() { var hmm = MarkovContinuousFunctionTest.CreateModel1(); @@ -384,7 +384,7 @@ public void GradientTest_MarkovNormal() } } - [TestMethod()] + [Test] public void GradientTest_MarkovNormal_Regularization() { var hmm = MarkovContinuousFunctionTest.CreateModel1(); diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/GradientDescentHiddenLearningTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/GradientDescentHiddenLearningTest.cs index dd642497c..2e5893937 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/GradientDescentHiddenLearningTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/GradientDescentHiddenLearningTest.cs @@ -27,9 +27,9 @@ namespace Accord.Tests.Statistics.Models.Fields using Accord.Statistics.Models.Fields.Functions; using Accord.Statistics.Models.Fields.Learning; using Accord.Statistics.Models.Markov; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class GradientDescentHiddenLearningTest { @@ -49,7 +49,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void RunTest() { var inputs = QuasiNewtonHiddenLearningTest.inputs; @@ -99,7 +99,7 @@ public void RunTest() Assert.IsTrue(ll1 > ll0); } - [TestMethod()] + [Test] public void RunTest2() { var inputs = QuasiNewtonHiddenLearningTest.inputs; diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/MultivariateNormalQuasiNewtonHiddenLearningTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/MultivariateNormalQuasiNewtonHiddenLearningTest.cs index 136037473..04252256a 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/MultivariateNormalQuasiNewtonHiddenLearningTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/MultivariateNormalQuasiNewtonHiddenLearningTest.cs @@ -31,9 +31,9 @@ namespace Accord.Tests.Statistics using Accord.Statistics.Models.Markov; using Accord.Statistics.Models.Markov.Topology; using Accord.Tests.Statistics.Models.Fields; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class MultivariateNormalQuasiNewtonHiddenLearningTest { @@ -79,7 +79,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void RunTest() { var hmm = MultivariateMarkovFunctionTest.CreateModel1(); diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/NormalQuasiNewtonHiddenLearningTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/NormalQuasiNewtonHiddenLearningTest.cs index 58bb96395..7bbf041a4 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/NormalQuasiNewtonHiddenLearningTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/NormalQuasiNewtonHiddenLearningTest.cs @@ -22,14 +22,14 @@ namespace Accord.Tests.Statistics.Models.Fields -{ - using Accord.Statistics.Models.Fields; - using Accord.Statistics.Models.Fields.Functions; - using Accord.Statistics.Models.Fields.Learning; - using Microsoft.VisualStudio.TestTools.UnitTesting; +{ + using Accord.Statistics.Models.Fields; + using Accord.Statistics.Models.Fields.Functions; + using Accord.Statistics.Models.Fields.Learning; + using NUnit.Framework; using System; - [TestClass()] + [TestFixture] public class NormalQuasiNewtonHiddenLearningTest { @@ -44,7 +44,7 @@ public class NormalQuasiNewtonHiddenLearningTest - [TestMethod()] + [Test] public void RunTest() { var hmm = MarkovContinuousFunctionTest.CreateModel1(); diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/QuasiNewtonHiddenLearningTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/QuasiNewtonHiddenLearningTest.cs index f25521fc3..cf69af6c1 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/QuasiNewtonHiddenLearningTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/QuasiNewtonHiddenLearningTest.cs @@ -28,11 +28,11 @@ namespace Accord.Tests.Statistics.Models.Fields using Accord.Statistics.Models.Fields.Functions; using Accord.Statistics.Models.Fields.Learning; using Accord.Statistics.Models.Markov; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics.Distributions.Multivariate; using Accord.Statistics.Distributions.Univariate; - [TestClass()] + [TestFixture] public class QuasiNewtonHiddenLearningTest { @@ -73,7 +73,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void RunTest() { HiddenMarkovClassifier hmm = DiscreteHiddenMarkovClassifierPotentialFunctionTest.CreateModel1(); @@ -118,7 +118,7 @@ public void RunTest() Assert.IsTrue(ll1 > ll0); } - [TestMethod()] + [Test] public void RunTest2() { Accord.Math.Tools.SetupGenerator(0); diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/QuasiNewtonLearningTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/QuasiNewtonLearningTest.cs index fa4e2a670..bfa56b776 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/QuasiNewtonLearningTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/QuasiNewtonLearningTest.cs @@ -23,7 +23,7 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Models.Fields.Learning; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics.Models.Fields; using Accord.Statistics.Models.Markov; using Accord.Statistics.Models.Markov.Topology; @@ -31,7 +31,7 @@ namespace Accord.Tests.Statistics using Accord.Statistics.Models.Markov.Learning; using Accord.Math; - [TestClass()] + [TestFixture] public class QuasiNewtonLearningTest { @@ -78,7 +78,7 @@ private static HiddenMarkovModel trainHMM() return hmm; } - [TestMethod()] + [Test] public void RunTest() { int nstates = 3; diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/ResilientGradientHiddenLearningTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/ResilientGradientHiddenLearningTest.cs index 7a52e9fb7..7c4e162ba 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/ResilientGradientHiddenLearningTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Fields/Learning/ResilientGradientHiddenLearningTest.cs @@ -26,14 +26,14 @@ namespace Accord.Tests.Statistics.Models.Fields using Accord.Statistics.Models.Fields.Functions; using Accord.Statistics.Models.Fields.Learning; using Accord.Statistics.Models.Markov; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; - [TestClass()] + [TestFixture] public class ResilientGradientHiddenLearningTest { - [TestMethod()] + [Test] public void RunTest() { var inputs = QuasiNewtonHiddenLearningTest.inputs; @@ -83,7 +83,7 @@ public void RunTest() Assert.IsTrue(ll1 > ll0); } - [TestMethod()] + [Test] public void RunTest3() { var inputs = QuasiNewtonHiddenLearningTest.inputs; @@ -134,7 +134,7 @@ public void RunTest3() } - [TestMethod()] + [Test] public void RunTest2() { var inputs = QuasiNewtonHiddenLearningTest.inputs; @@ -185,7 +185,7 @@ public void RunTest2() Assert.IsTrue(ll1 > ll0); } - [TestMethod()] + [Test] public void ComputeTest2() { // Suppose we would like to learn how to classify the diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Markov/ForwardBackwardAlgorithmTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Markov/ForwardBackwardAlgorithmTest.cs index 9a4da1688..b34d70e80 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Markov/ForwardBackwardAlgorithmTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Markov/ForwardBackwardAlgorithmTest.cs @@ -22,13 +22,13 @@ namespace Accord.Tests.Statistics.Models.Markov { - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics.Models.Markov; using Accord.Math; using System; using Accord.Statistics.Distributions.Univariate; - [TestClass()] + [TestFixture] public class ForwardBackwardAlgorithmTest { @@ -147,7 +147,7 @@ public static HiddenMarkovModel CreateModel4() } - [TestMethod()] + [Test] public void BackwardTest() { HiddenMarkovModel hmm = CreateModel2(); @@ -200,7 +200,7 @@ public void BackwardTest() Assert.IsFalse(double.IsNaN(p)); } - [TestMethod()] + [Test] public void BackwardTest2() { HiddenMarkovModel hmm = CreateModel3(); @@ -232,7 +232,7 @@ public void BackwardTest2() Assert.IsFalse(double.IsNaN(p)); } - [TestMethod()] + [Test] public void ForwardTest() { HiddenMarkovModel hmm = CreateModel1(); @@ -278,7 +278,7 @@ public void ForwardTest() Assert.IsFalse(double.IsNaN(p)); } - [TestMethod()] + [Test] public void ForwardTest2() { HiddenMarkovModel hmm = CreateModel2(); @@ -328,7 +328,7 @@ public void ForwardTest2() Assert.IsFalse(double.IsNaN(p)); } - [TestMethod()] + [Test] public void ForwardTest3() { HiddenMarkovModel hmm = CreateModel3(); @@ -360,7 +360,7 @@ public void ForwardTest3() Assert.IsFalse(double.IsNaN(p)); } - [TestMethod()] + [Test] public void ForwardScalingTest() { HiddenMarkovModel hmm = CreateModel1(); @@ -423,7 +423,7 @@ public void ForwardScalingTest() Assert.IsFalse(double.IsNaN(p)); } - [TestMethod()] + [Test] public void ForwardScalingTest2() { HiddenMarkovModel hmm = CreateModel2(); @@ -441,7 +441,7 @@ public void ForwardScalingTest2() Assert.IsFalse(double.IsNaN(p)); } - [TestMethod()] + [Test] public void ForwardBackwardTest() { HiddenMarkovModel hmm = CreateModel1(); @@ -458,7 +458,7 @@ public void ForwardBackwardTest() Assert.AreEqual(fwdLogLikelihood, bwdLogLikelihood, 1e-10); // -5.5614629361549142 } - [TestMethod()] + [Test] public void ForwardBackwardGenericTest() { var discreteModel = CreateModel1(); @@ -501,7 +501,7 @@ public void ForwardBackwardGenericTest() } - [TestMethod()] + [Test] public void LogBackwardTest() { HiddenMarkovModel hmm = Accord.Tests.Statistics.Models.Markov. @@ -528,7 +528,7 @@ public void LogBackwardTest() Assert.IsFalse(double.IsNaN(p)); } - [TestMethod()] + [Test] public void LogBackwardTest2() { HiddenMarkovModel hmm = Accord.Tests.Statistics.Models.Markov. @@ -548,7 +548,7 @@ public void LogBackwardTest2() Assert.IsFalse(double.IsNaN(p)); } - [TestMethod()] + [Test] public void LogForwardTest() { HiddenMarkovModel hmm = Accord.Tests.Statistics.Models.Markov. @@ -574,7 +574,7 @@ public void LogForwardTest() Assert.IsFalse(double.IsNaN(p)); } - [TestMethod()] + [Test] public void LogForwardTest2() { HiddenMarkovModel hmm = Accord.Tests.Statistics.Models.Markov. @@ -599,7 +599,7 @@ public void LogForwardTest2() Assert.IsFalse(double.IsNaN(p)); } - [TestMethod()] + [Test] public void LogForwardBackwardGenericTest() { var discreteModel = CreateModel1(); diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Markov/HiddenMarkovClassifierTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Markov/HiddenMarkovClassifierTest.cs index 9d768fe35..d61a6885d 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Markov/HiddenMarkovClassifierTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Markov/HiddenMarkovClassifierTest.cs @@ -23,13 +23,13 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Models.Markov; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics.Models.Markov.Learning; using Accord.Math; using System; - [TestClass()] + [TestFixture] public class HiddenMarkovClassifierTest { @@ -51,7 +51,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void LearnTest() { // Declare some testing data @@ -113,7 +113,7 @@ public void LearnTest() } - [TestMethod()] + [Test] public void LearnTest2() { // Declare some testing data diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Markov/HiddenMarkovClassifier`1Test.cs b/Unit Tests/Accord.Tests.Statistics/Models/Markov/HiddenMarkovClassifier`1Test.cs index c40dad3f2..037262d8c 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Markov/HiddenMarkovClassifier`1Test.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Markov/HiddenMarkovClassifier`1Test.cs @@ -21,24 +21,24 @@ // namespace Accord.Tests.Statistics -{ - using Accord.Math; - using Accord.Statistics.Distributions.Fitting; - using Accord.Statistics.Distributions.Multivariate; - using Accord.Statistics.Distributions.Univariate; - using Accord.Statistics.Models.Markov; - using Accord.Statistics.Models.Markov.Learning; - using Accord.Statistics.Models.Markov.Topology; - using Microsoft.VisualStudio.TestTools.UnitTesting; +{ + using Accord.Math; + using Accord.Statistics.Distributions.Fitting; + using Accord.Statistics.Distributions.Multivariate; + using Accord.Statistics.Distributions.Univariate; + using Accord.Statistics.Models.Markov; + using Accord.Statistics.Models.Markov.Learning; + using Accord.Statistics.Models.Markov.Topology; + using NUnit.Framework; using System; - [TestClass()] + [TestFixture] public class GenericSequenceClassifierTest { - [TestMethod()] + [Test] public void LearnTest1() { // Create a Continuous density Hidden Markov Model Sequence Classifier @@ -94,7 +94,7 @@ public void LearnTest1() Assert.IsFalse(double.IsNaN(likelihood2)); } - [TestMethod()] + [Test] public void LearnTest2() { // Creates a new Hidden Markov Model with 10 states @@ -122,7 +122,7 @@ public void LearnTest2() } } - [TestMethod()] + [Test] public void LearnTest3() { // Create a Continuous density Hidden Markov Model Sequence Classifier @@ -195,7 +195,7 @@ public void LearnTest3() Assert.IsFalse(double.IsNaN(likelihood2)); } - [TestMethod()] + [Test] public void LearnTest4() { // Create a Continuous density Hidden Markov Model Sequence Classifier @@ -278,7 +278,7 @@ public void LearnTest4() Assert.IsFalse(double.IsNaN(likelihood2)); } - [TestMethod()] + [Test] public void LearnTest5() { // Create a Continuous density Hidden Markov Model Sequence Classifier @@ -359,7 +359,7 @@ public void LearnTest5() Assert.IsFalse(double.IsNaN(logLikelihood2)); } - [TestMethod()] + [Test] public void LearnTest6() { // Create a Continuous density Hidden Markov Model Sequence Classifier @@ -455,7 +455,7 @@ public void LearnTest6() Assert.IsFalse(double.IsNaN(response2)); } - [TestMethod()] + [Test] public void LearnTest7() { // Create a Continuous density Hidden Markov Model Sequence Classifier @@ -541,7 +541,7 @@ public void LearnTest7() Assert.IsFalse(double.IsNaN(likelihood2)); } - [TestMethod()] + [Test] public void LearnTest8() { // Declare some testing data @@ -678,7 +678,7 @@ private static double testThresholdModel(double[][] inputs, int[] outputs, Hidde - [TestMethod()] + [Test] public void LearnTest9() { double[][][] inputs = large_gestures; diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Markov/HiddenMarkovModelTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Markov/HiddenMarkovModelTest.cs index fab86c90a..3293d1ecd 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Markov/HiddenMarkovModelTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Markov/HiddenMarkovModelTest.cs @@ -27,11 +27,11 @@ namespace Accord.Tests.Statistics using Accord.Statistics.Models.Markov; using Accord.Statistics.Models.Markov.Learning; using Accord.Statistics.Models.Markov.Topology; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics.Filters; using Accord.Statistics.Distributions.Univariate; - [TestClass()] + [TestFixture] public class HiddenMarkovModelTest { @@ -52,7 +52,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest() { HiddenMarkovModel hmm; @@ -115,7 +115,7 @@ public void ConstructorTest() Assert.IsTrue(Matrix.Log(pi).IsEqual(hmm.Probabilities)); } - [TestMethod()] + [Test] public void DecodeTest() { // Example taken from http://en.wikipedia.org/wiki/Viterbi_algorithm @@ -167,7 +167,7 @@ public void DecodeTest() } - [TestMethod()] + [Test] public void LearnTest4() { @@ -205,7 +205,7 @@ public void LearnTest4() Assert.AreEqual(0.001936595918966074, p2, 1e-10); } - [TestMethod()] + [Test] public void LearnTest() { HiddenMarkovModel hmm = new HiddenMarkovModel(2, 3); @@ -282,7 +282,7 @@ public void LearnTest() Assert.IsTrue(Matrix.IsEqual(pi, hmmP)); } - [TestMethod()] + [Test] public void LearnTest3() { // We will try to create a Hidden Markov Model which @@ -343,7 +343,7 @@ public void LearnTest3() Assert.IsTrue(l2 > l3 && l2 > l4); } - [TestMethod()] + [Test] public void LearnTest6() { // We will try to create a Hidden Markov Model which @@ -404,7 +404,7 @@ public void LearnTest6() Assert.IsTrue(l2 > l3 && l2 > l4); } - [TestMethod()] + [Test] public void LearnTest_EmptySequence() { @@ -440,7 +440,7 @@ public void LearnTest_EmptySequence() Assert.IsTrue(thrown); } - [TestMethod()] + [Test] public void PredictTest() { int[][] sequences = new int[][] @@ -500,7 +500,7 @@ public void PredictTest() Assert.AreEqual(ln1, ln2, 1e-10); } - [TestMethod()] + [Test] public void PredictTest2() { // We will try to create a Hidden Markov Model which @@ -541,7 +541,7 @@ public void PredictTest2() Assert.AreEqual(prediction[0], 3); } - [TestMethod()] + [Test] public void PredictTest3() { // We will try to create a Hidden Markov Model which @@ -604,7 +604,7 @@ public void PredictTest3() } - [TestMethod()] + [Test] public void GenerateTest() { // Example taken from http://en.wikipedia.org/wiki/Viterbi_algorithm @@ -637,7 +637,7 @@ public void GenerateTest() Assert.AreEqual(expected, logLikelihood); } - [TestMethod()] + [Test] public void GenerateTest2() { Accord.Math.Tools.SetupGenerator(42); @@ -690,7 +690,7 @@ public void GenerateTest2() Assert.AreEqual("words", result[2]); } - [TestMethod()] + [Test] public void PosteriorTest1() { // Example from http://ai.stanford.edu/~serafim/CS262_2007/notes/lecture5.pdf diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Markov/HiddenMarkovModel`1Test.cs b/Unit Tests/Accord.Tests.Statistics/Models/Markov/HiddenMarkovModel`1Test.cs index aa28e7692..fd4cbcf36 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Markov/HiddenMarkovModel`1Test.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Markov/HiddenMarkovModel`1Test.cs @@ -33,9 +33,9 @@ namespace Accord.Tests.Statistics using Accord.Statistics.Models.Markov; using Accord.Statistics.Models.Markov.Learning; using Accord.Statistics.Models.Markov.Topology; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class GenericHiddenMarkovModelTest { @@ -56,7 +56,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest() { double[,] A; @@ -132,7 +132,7 @@ public void ConstructorTest() Assert.AreEqual(B, hmm.Emissions); } - [TestMethod()] + [Test] public void ConstructorTest2() { @@ -158,10 +158,10 @@ public void ConstructorTest2() Assert.AreEqual(n.Dimension, hmm.Dimension); - Assert.AreNotEqual(n.Covariance, distribution.Covariance); + Assert.AreNotSame(n.Covariance, distribution.Covariance); Assert.IsTrue(n.Covariance.IsEqual(distribution.Covariance)); - Assert.AreNotEqual(n.Mean, distribution.Mean); + Assert.AreNotSame(n.Mean, distribution.Mean); Assert.IsTrue(n.Mean.IsEqual(distribution.Mean)); } @@ -176,7 +176,7 @@ public void ConstructorTest2() Assert.IsTrue(logPi.IsEqual(hmm.Probabilities)); } - [TestMethod()] + [Test] public void ConstructorTest3() { double[,] A = new double[,] @@ -212,7 +212,7 @@ public void ConstructorTest3() Assert.IsTrue(pi.IsEqual(hmm.Probabilities)); } - [TestMethod()] + [Test] public void ConstructorTest_RandomEquals() { Accord.Math.Tools.SetupGenerator(0); @@ -233,7 +233,7 @@ public void ConstructorTest_RandomEquals() Assert.AreEqual(dhmm.Emissions[i, j], Math.Log(chmm.Emissions[i][j]), 1e-10); } - [TestMethod()] + [Test] public void DecodeTest() { @@ -282,7 +282,7 @@ public void DecodeTest() Assert.AreEqual(path[2], 0); } - [TestMethod()] + [Test] public void DecodeIntegersTest() { double[,] transitions = @@ -315,7 +315,7 @@ public void DecodeIntegersTest() Assert.AreEqual(path[2], 0); } - [TestMethod()] + [Test] public void DecodeTest2() { double[,] transitions = @@ -349,7 +349,7 @@ public void DecodeTest2() Assert.AreEqual(path[2], 0); } - [TestMethod()] + [Test] public void DecodeTest3() { double[,] transitions = @@ -386,7 +386,7 @@ public void DecodeTest3() Assert.IsTrue(thrown); } - [TestMethod()] + [Test] public void DecodeTest4() { var density = new MultivariateNormalDistribution(3); @@ -407,7 +407,7 @@ public void DecodeTest4() Assert.IsTrue(thrown); } - [TestMethod()] + [Test] public void DecodeTest5() { var density = new MultivariateNormalDistribution(3); @@ -427,7 +427,7 @@ public void DecodeTest5() - [TestMethod()] + [Test] public void LearnTest5() { @@ -498,7 +498,7 @@ public void LearnTest5() Assert.AreEqual(1, hmm.Dimension); } - [TestMethod()] + [Test] public void LearnIntegersTest5() { @@ -570,7 +570,7 @@ public void LearnIntegersTest5() } - [TestMethod()] + [Test] public void LearnTest3() { @@ -627,7 +627,7 @@ public void LearnTest3() Assert.AreEqual(1, hmm.Dimension); } - [TestMethod()] + [Test] public void LearnTest6() { // Continuous Markov Models can operate using any @@ -699,7 +699,7 @@ public void LearnTest6() Assert.IsTrue(l2 > l3 && l2 > l4); } - [TestMethod()] + [Test] public void LearnTest7() { // Create continuous sequences. In the sequences below, there @@ -787,7 +787,7 @@ public void LearnTest7() Assert.IsFalse(A.HasNaN()); } - [TestMethod()] + [Test] public void LearnTest8() { // Create continuous sequences. In the sequence below, there @@ -856,7 +856,7 @@ public void LearnTest8() Assert.AreEqual(0, A[1, 1]); } - [TestMethod()] + [Test] public void LearnTest9() { var observations = new double[][][] @@ -1012,7 +1012,7 @@ public void LearnTest9() Assert.IsFalse(Double.IsNaN(value)); } - [TestMethod()] + [Test] public void LearnTest10() { // Create sequences of vector-valued observations. In the @@ -1084,7 +1084,7 @@ public void LearnTest10() Assert.AreEqual(2.1031924118199194E-89, a3); } - [TestMethod()] + [Test] public void LearnTest10_Independent() { // Let's say we have 2 meteorological sensors gathering data @@ -1149,7 +1149,7 @@ public void LearnTest10_Independent() } - [TestMethod()] + [Test] public void LearnTest11() { @@ -1224,7 +1224,7 @@ public void LearnTest11() Assert.IsFalse(Double.IsNaN(a3)); } - [TestMethod()] + [Test] public void LearnTest12() { @@ -1300,7 +1300,7 @@ public void LearnTest12() Assert.IsFalse(Double.IsNaN(a3)); } - [TestMethod()] + [Test] public void LearnTest_EmptySequence() { double[][] sequences = @@ -1339,7 +1339,7 @@ public void LearnTest_EmptySequence() Assert.IsTrue(thrown); } - [TestMethod()] + [Test] public void LearnTest13() { var observations = new double[][][] @@ -1403,24 +1403,25 @@ public void LearnTest13() checkDegenerate(observations, 3); } - [TestMethod()] + [Test] + [Category("Intensive")] public void BigSampleLearnTest13() { Accord.Math.Tools.SetupGenerator(0); - var list = new List(); + var list = new double[1000000][][]; for (int i = 0; i < 1000000; i++) { - list.Add(new double[][] + list[i] = new double[][] { new double[] { 2, 1 }, new double[] { 5, 2 }, new double[] { 10, 3 }, - }); + }; } - - checkDegenerate(list.ToArray(), 3); + + checkDegenerate(list, 3); } @@ -1473,7 +1474,7 @@ private static void checkDegenerate(double[][][] observations, int states) } } - [TestMethod()] + [Test] public void FittingOptionsTest() { // Create a degenerate problem @@ -1543,7 +1544,7 @@ public void FittingOptionsTest() } - [TestMethod()] + [Test] public void PredictTest() { double[][] sequences = new double[][] @@ -1630,7 +1631,7 @@ public void PredictTest() } - [TestMethod()] + [Test] public void PredictTest2() { // Create continuous sequences. In the sequence below, there @@ -1689,7 +1690,7 @@ public void PredictTest2() Assert.AreEqual(0, d2.Coefficients[1]); } - [TestMethod()] + [Test] public void PredictTest3() { // We will try to create a Hidden Markov Model which @@ -1742,7 +1743,7 @@ public void PredictTest3() Assert.AreEqual(2, prediction); } - [TestMethod()] + [Test] public void GenerateTest() { double[,] A; @@ -1778,7 +1779,7 @@ public void GenerateTest() } - [TestMethod()] + [Test] public void PosteriorTest1() { // Example from http://ai.stanford.edu/~serafim/CS262_2007/notes/lecture5.pdf diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Markov/MaximumLikelihoodLearningTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Markov/MaximumLikelihoodLearningTest.cs index 5b520f4ae..eb3a6320b 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Markov/MaximumLikelihoodLearningTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Markov/MaximumLikelihoodLearningTest.cs @@ -23,13 +23,13 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Models.Markov.Learning; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Statistics.Models.Markov; using Accord.Statistics.Filters; using Accord.Math; - [TestClass()] + [TestFixture] public class MaximumLikelihoodLearningTest { @@ -50,7 +50,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void RunTest() { // Example from diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Markov/MaximumLikelihoodLearning`1Test.cs b/Unit Tests/Accord.Tests.Statistics/Models/Markov/MaximumLikelihoodLearning`1Test.cs index 39768252f..2ed718695 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Markov/MaximumLikelihoodLearning`1Test.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Markov/MaximumLikelihoodLearning`1Test.cs @@ -23,14 +23,14 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Models.Markov.Learning; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Statistics.Models.Markov; using Accord.Statistics.Filters; using Accord.Math; using Accord.Statistics.Distributions.Univariate; - [TestClass()] + [TestFixture] public class GenericMaximumLikelihoodLearningTest { @@ -51,7 +51,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void RunTest() { // Example from diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Markov/TopologyTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Markov/TopologyTest.cs index 6934c44b1..157297b2d 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Markov/TopologyTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Markov/TopologyTest.cs @@ -22,7 +22,7 @@ using Accord.Statistics.Models.Markov; using Accord.Statistics.Distributions; -using Microsoft.VisualStudio.TestTools.UnitTesting; +using NUnit.Framework; using Accord.Math; using Accord.Statistics.Distributions.Univariate; using Accord.Statistics.Models.Markov.Learning; @@ -35,7 +35,7 @@ namespace Accord.Tests.Statistics ///This is a test class for HiddenMarkovModelTest and is intended ///to contain all HiddenMarkovModelTest Unit Tests /// - [TestClass()] + [TestFixture] public class TopologyTest { @@ -59,7 +59,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void UniformTest() { // Create a new Ergodic hidden Markov model with three @@ -79,7 +79,7 @@ public void UniformTest() Assert.IsTrue(A.IsEqual(expected, 0.01)); } - [TestMethod()] + [Test] public void ForwardTest() { // Create a new Forward-only hidden Markov model with @@ -98,7 +98,7 @@ public void ForwardTest() Assert.IsTrue(actual.IsEqual(expected, 0.01)); } - [TestMethod()] + [Test] public void ForwardTest2() { var topology = new Forward(3, 2); @@ -120,7 +120,7 @@ public void ForwardTest2() Assert.AreEqual(states, 3); } - [TestMethod()] + [Test] public void ForwardTest3() { var topology = new Forward(states: 3, deepness: 2); diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Markov/ViterbiLearningTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Markov/ViterbiLearningTest.cs index 973f63991..9e910e2d2 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Markov/ViterbiLearningTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Markov/ViterbiLearningTest.cs @@ -23,14 +23,14 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Models.Markov.Learning; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Statistics.Models.Markov; using Accord.Statistics.Filters; using Accord.Math; using Accord.Statistics.Models.Markov.Topology; - [TestClass()] + [TestFixture] public class ViterbiLearningTest { @@ -49,7 +49,7 @@ public TestContext TestContext } } - [TestMethod()] + [Test] public void LearnTest2() { Accord.Math.Tools.SetupGenerator(0); @@ -103,7 +103,7 @@ public void LearnTest2() } Assert.IsTrue(ll10 > ll1); - Assert.AreNotEqual(ll1, ll10, 10); + Assert.IsTrue(Math.Abs(ll1 - ll10) > 10); // Those results must match the ones in ViterbiLearningTest`1. Assert.AreEqual(-33.834836461044411, ll1); @@ -131,7 +131,7 @@ private static bool AreEqual(HiddenMarkovModel hmm1, HiddenMarkovModel hmm10) return true; } - [TestMethod()] + [Test] public void LearnTest4() { Accord.Math.Tools.SetupGenerator(0); @@ -170,7 +170,7 @@ public void LearnTest4() Assert.AreEqual(0.008509757587448558, p2, 1e-10); } - [TestMethod()] + [Test] public void LearnTest() { Accord.Math.Tools.SetupGenerator(0); @@ -249,7 +249,7 @@ public void LearnTest() Assert.IsTrue(Matrix.IsEqual(pi, hmmP, 0.1)); } - [TestMethod()] + [Test] public void LearnTest3() { Accord.Math.Tools.SetupGenerator(0); @@ -321,7 +321,7 @@ public void LearnTest3() Assert.IsTrue(l2 > l3 && l2 > l4); } - [TestMethod()] + [Test] public void LearnTest6() { Accord.Math.Tools.SetupGenerator(0); diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Markov/ViterbiLearning`1Test.cs b/Unit Tests/Accord.Tests.Statistics/Models/Markov/ViterbiLearning`1Test.cs index 2c51bd967..31b4c1041 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Markov/ViterbiLearning`1Test.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Markov/ViterbiLearning`1Test.cs @@ -23,7 +23,7 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Models.Markov.Learning; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Statistics.Models.Markov; using Accord.Statistics.Filters; @@ -33,12 +33,12 @@ namespace Accord.Tests.Statistics using Accord.Statistics.Models.Markov.Topology; using Accord.Statistics.Distributions.Univariate; - [TestClass()] + [TestFixture] public class GenericViterbiLearningTest { - [TestMethod()] + [Test] public void LearnTest2() { Accord.Math.Tools.SetupGenerator(0); @@ -100,7 +100,7 @@ public void LearnTest2() } Assert.IsTrue(ll10 > ll1); - Assert.AreNotEqual(ll1, ll10, 10); + Assert.IsTrue(Math.Abs(ll1 - ll10) > 10); // Those results must match the ones in ViterbiLearningTest. Assert.AreEqual(-33.834836461044411, ll1); @@ -127,7 +127,7 @@ private static bool AreEqual( } - [TestMethod()] + [Test] public void LearnTest5() { double[][][] sequences = new double[][][] @@ -197,7 +197,7 @@ public void LearnTest5() Assert.AreEqual(1, hmm.Dimension); } - [TestMethod()] + [Test] public void LearnTest3() { double[][] sequences = new double[][] @@ -264,7 +264,7 @@ public void LearnTest3() Assert.AreEqual(1, hmm.Dimension); } - [TestMethod()] + [Test] public void LearnTest6() { Accord.Math.Tools.SetupGenerator(0); @@ -351,7 +351,7 @@ public void LearnTest6() Assert.IsTrue(l2 > l3 && l2 > l4); } - [TestMethod()] + [Test] public void LearnTest7() { Accord.Math.Tools.SetupGenerator(0); @@ -434,7 +434,7 @@ public void LearnTest7() Assert.IsFalse(A.HasNaN()); } - [TestMethod()] + [Test] public void LearnTest8() { Accord.Math.Tools.SetupGenerator(0); @@ -505,7 +505,7 @@ public void LearnTest8() Assert.AreEqual(0.0769230769230769, A[1, 1], 1e-6); } - [TestMethod()] + [Test] public void LearnTest9() { Accord.Math.Tools.SetupGenerator(0); diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Regression/CoxProportionalHazardsTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Regression/CoxProportionalHazardsTest.cs index 86f68acde..3b86713da 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Regression/CoxProportionalHazardsTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Regression/CoxProportionalHazardsTest.cs @@ -22,34 +22,17 @@ namespace Accord.Tests.Statistics { - using System; using Accord.Math; - using Accord.Statistics.Models.Regression; - using Microsoft.VisualStudio.TestTools.UnitTesting; using Accord.Statistics.Distributions.Univariate; + using Accord.Statistics.Models.Regression; + using NUnit.Framework; + using System; - [TestClass()] + [TestFixture] public class CoxProportionalHazardsTest { - - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - - [TestMethod()] + [Test] public void RunTest() { // Data from: http://www.sph.emory.edu/~cdckms/CoxPH/prophaz2.html @@ -76,7 +59,7 @@ public void RunTest() double[][] inputs = data.GetColumn(0).ToArray(); double[] time = data.GetColumn(1); - int[] output = data.GetColumn(2).ToInt32(); + SurvivalOutcome[] output = data.GetColumn(2).To(); { @@ -114,7 +97,7 @@ public void RunTest() } - [TestMethod()] + [Test] public void PredictTest1() { // Data from: http://www.sph.emory.edu/~cdckms/CoxPH/prophaz2.html @@ -154,7 +137,6 @@ public void PredictTest1() double[][] inputs = data.GetColumn(0).ToArray(); double[] time = data.GetColumn(1); - int[] output = data.GetColumn(2).ToInt32(); double[] expected = diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Regression/LogarithmRegressionTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Regression/LogarithmRegressionTest.cs index 02bc23560..041e88cd1 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Regression/LogarithmRegressionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Regression/LogarithmRegressionTest.cs @@ -22,33 +22,17 @@ namespace Accord.Tests.Statistics { - using Accord.Statistics.Models.Regression.Linear; using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using Accord.Statistics.Models.Regression.Linear; + using NUnit.Framework; using System.Globalization; - [TestClass()] + [TestFixture] public class LogarithmRegressionTest { - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - - [TestMethod()] + [Test] public void LogarithmRegressionRegressTest() { // This is the same data from the example available at @@ -72,8 +56,8 @@ public void LogarithmRegressionRegressTest() string result = lr.ToString("N4", CultureInfo.InvariantCulture); // Result will be "y(x) = 6.1082x + 6.0993" - + Assert.AreEqual(2.8760006026675797, error); Assert.AreEqual(6.1081800414945704, lr.Slope); Assert.AreEqual(6.0993411396126653, lr.Intercept); Assert.AreEqual("y(x) = 6.1082x + 6.0993", result); diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Regression/LogisticGradientDescentTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Regression/LogisticGradientDescentTest.cs index 2412c5013..857d9ee46 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Regression/LogisticGradientDescentTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Regression/LogisticGradientDescentTest.cs @@ -22,33 +22,17 @@ namespace Accord.Tests.Statistics { - using System; using Accord.Math.Differentiation; using Accord.Statistics.Models.Regression; using Accord.Statistics.Models.Regression.Fitting; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; + using System; - [TestClass()] + [TestFixture] public class LogisticGradientDescentTest { - - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - [TestMethod()] + [Test] public void GradientTest() { double[][] input = @@ -86,7 +70,7 @@ public void GradientTest() } } - [TestMethod()] + [Test] public void StochasticGradientTest() { double[][] input = @@ -131,16 +115,9 @@ public void StochasticGradientTest() private static double[] finiteDifferences(double[][] input, double[] output, bool stochastic) { LogisticRegression regression; - LogisticGradientDescent teacher; regression = new LogisticRegression(inputs: 2); - teacher = new LogisticGradientDescent(regression) - { - Stochastic = stochastic, - LearningRate = 1e-4, - }; - FiniteDifferences diff = new FiniteDifferences(3); diff.Function = (x) => @@ -172,7 +149,7 @@ private static double[] gradient(double[][] input, double[] output, bool stochas } - [TestMethod()] + [Test] public void RunTest() { // Suppose we have the following data about some patients. @@ -251,7 +228,7 @@ public void RunTest() Assert.IsFalse(Double.IsNaN(smokeOdds)); } - [TestMethod()] + [Test] public void RunTest1() { // Suppose we have the following data about some patients. diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Regression/LogisticRegressionTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Regression/LogisticRegressionTest.cs index 4e074ec36..3c93f17a5 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Regression/LogisticRegressionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Regression/LogisticRegressionTest.cs @@ -27,10 +27,10 @@ namespace Accord.Tests.Statistics using Accord.Statistics.Analysis; using Accord.Statistics.Models.Regression; using Accord.Statistics.Models.Regression.Fitting; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System.Collections.Generic; - [TestClass()] + [TestFixture] public class LogisticRegressionTest { @@ -50,7 +50,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ComputeTest() { // Suppose we have the following data about some patients. @@ -151,7 +151,7 @@ public void ComputeTest() Assert.AreEqual(1.7678893101571855, regression.Coefficients[2], 1e-8); } - [TestMethod()] + [Test] public void RegressTest() { @@ -257,7 +257,7 @@ public void RegressTest() Assert.IsFalse(double.IsNaN(analysis.Coefficients[1].ConfidenceUpper)); } - [TestMethod()] + [Test] public void ComputeTest3() { double[][] input = @@ -322,7 +322,7 @@ public void ComputeTest3() Assert.AreEqual(1.7678893101571855, regression.Coefficients[2], 1e-8); } - [TestMethod()] + [Test] public void LargeCoefficientsTest() { double[,] data = @@ -441,7 +441,7 @@ public void LargeCoefficientsTest() Assert.AreEqual(44.089493151268726, regression.Coefficients[3]); } - [TestMethod()] + [Test] public void RegularizationTest2() { CsvReader reader = CsvReader.FromText(Properties.Resources.regression, true); diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Regression/MultinomialLogisticRegressionTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Regression/MultinomialLogisticRegressionTest.cs index a30b6aaff..d98cb2168 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Regression/MultinomialLogisticRegressionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Regression/MultinomialLogisticRegressionTest.cs @@ -26,14 +26,14 @@ namespace Accord.Tests.Statistics using Accord.Statistics.Models.Regression; using Accord.Statistics.Models.Regression.Fitting; using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System.Linq; - [TestClass()] + [TestFixture] public class MultinomialLogisticRegressionTest { - [TestMethod] + [Test] public void RegressTest2() { double[][] inputs; @@ -161,7 +161,7 @@ public void RegressTest2() } - [TestMethod] + [Test] public void ComputeTest2() { MultinomialLogisticRegression mlr = createExample1(); @@ -195,7 +195,7 @@ public void ComputeTest2() } - [TestMethod()] + [Test] public void MultinomialLogisticRegressionConstructorTest() { int inputs = 4; @@ -213,7 +213,7 @@ public void MultinomialLogisticRegressionConstructorTest() Assert.AreEqual(5, target.StandardErrors[i].Length); } - [TestMethod()] + [Test] public void ChiSquareMethodTest() { double[][] inputs; @@ -229,10 +229,9 @@ public void ChiSquareMethodTest() } - [TestMethod()] + [Test] public void CloneTest() { - MultinomialLogisticRegression target = createExample1(); MultinomialLogisticRegression actual = (MultinomialLogisticRegression)target.Clone(); @@ -240,8 +239,8 @@ public void CloneTest() Assert.AreEqual(target.Categories, actual.Categories); Assert.AreEqual(target.Inputs, actual.Inputs); - Assert.AreNotEqual(target.Coefficients, actual.Coefficients); - Assert.AreNotEqual(target.StandardErrors, actual.StandardErrors); + Assert.AreNotSame(target.Coefficients, actual.Coefficients); + Assert.AreNotSame(target.StandardErrors, actual.StandardErrors); for (int i = 0; i < target.Coefficients.Length; i++) { @@ -254,7 +253,7 @@ public void CloneTest() } - [TestMethod()] + [Test] public void GetLogLikelihoodTest() { MultinomialLogisticRegression mlr = createExample1(); @@ -270,7 +269,7 @@ public void GetLogLikelihoodTest() } - [TestMethod()] + [Test] public void GetOddsRatioTest() { MultinomialLogisticRegression target = createExample1(); @@ -290,7 +289,7 @@ public void GetOddsRatioTest() Assert.AreEqual(System.Math.Exp(target.Coefficients[1][2]), actual); } - [TestMethod()] + [Test] public void GetWaldTestTest() { MultinomialLogisticRegression target = createExample1(); diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Regression/MultipleLinearRegressionTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Regression/MultipleLinearRegressionTest.cs index fc8dabe34..cd43372ac 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Regression/MultipleLinearRegressionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Regression/MultipleLinearRegressionTest.cs @@ -23,9 +23,9 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Models.Regression.Linear; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class MultipleLinearRegressionTest { @@ -46,7 +46,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void RegressTest() { MultipleLinearRegression target = new MultipleLinearRegression(1, true); @@ -81,7 +81,7 @@ public void RegressTest() Assert.AreEqual("y(x0) = -0,264705882352941*x0 + 50,5882352941176", str); } - [TestMethod()] + [Test] public void RegressTest2() { MultipleLinearRegression target = new MultipleLinearRegression(2, false); @@ -118,7 +118,7 @@ public void RegressTest2() Assert.AreEqual("y(x0, x1) = -0.264705882352941*x0 + 50.5882352941176*x1", str); } - [TestMethod()] + [Test] public void RegressTest3() { // We will try to model a plane as an equation in the form @@ -165,7 +165,7 @@ public void RegressTest3() } - [TestMethod()] + [Test] public void RegressTest4() { int count = 1000; @@ -201,7 +201,7 @@ public void RegressTest4() } } - [TestMethod()] + [Test] public void RegressTest5() { int count = 1000; @@ -235,7 +235,7 @@ public void RegressTest5() } } - [TestMethod()] + [Test] public void RegressTest6() { MultipleLinearRegression target = new MultipleLinearRegression(2, false); diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Regression/MultivariateLinearRegressionTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Regression/MultivariateLinearRegressionTest.cs index 396454ec8..b09bb4933 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Regression/MultivariateLinearRegressionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Regression/MultivariateLinearRegressionTest.cs @@ -21,7 +21,7 @@ // using Accord.Statistics.Models.Regression.Linear; -using Microsoft.VisualStudio.TestTools.UnitTesting; +using NUnit.Framework; namespace Accord.Tests.Statistics { @@ -30,7 +30,7 @@ namespace Accord.Tests.Statistics ///This is a test class for MultivariateLinearRegressionTest and is intended ///to contain all MultivariateLinearRegressionTest Unit Tests /// - [TestClass()] + [TestFixture] public class MultivariateLinearRegressionTest { @@ -55,7 +55,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void RegressTest() { double[][] X = @@ -110,7 +110,7 @@ public void RegressTest() } - [TestMethod()] + [Test] public void RegressTest2() { // The multivariate linear regression is a generalization of diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Regression/NewtonRaphsonCoxLearningTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Regression/NewtonRaphsonCoxLearningTest.cs index 0ed21aa8e..d3944b914 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Regression/NewtonRaphsonCoxLearningTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Regression/NewtonRaphsonCoxLearningTest.cs @@ -27,31 +27,15 @@ namespace Accord.Tests.Statistics using Accord.Statistics.Distributions.Univariate; using Accord.Statistics.Models.Regression; using Accord.Statistics.Models.Regression.Fitting; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics.Distributions.Fitting; + using Accord.Statistics; - [TestClass()] + [TestFixture] public class NewtonRaphsonCoxLearningTest { - - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - - - [TestMethod()] + [Test] public void RunTest() { // Data from: http://www.sph.emory.edu/~cdckms/CoxPH/prophaz2.html @@ -71,19 +55,19 @@ public void RunTest() { 60, 10, 1 }, }; - ProportionalHazards regression = new ProportionalHazards(1); + var regression = new ProportionalHazards(1); double[][] inputs = data.GetColumn(0).ToArray(); double[] time = data.GetColumn(1); - int[] output = data.GetColumn(2).ToInt32(); + SurvivalOutcome[] output = data.GetColumn(2).To(); - ProportionalHazardsNewtonRaphson target = new ProportionalHazardsNewtonRaphson(regression); + var target = new ProportionalHazardsNewtonRaphson(regression); double error = target.Run(inputs, time, output); double log = -2 * regression.GetPartialLogLikelihood(inputs, time, output); - + // Tested against http://www.sph.emory.edu/~cdckms/CoxPH/prophaz2.html Assert.AreEqual(0.3770, regression.Coefficients[0], 1e-4); Assert.IsFalse(Double.IsNaN(regression.Coefficients[0])); @@ -111,7 +95,7 @@ public void RunTest() } - [TestMethod()] + [Test] public void RunTest2() { // Data from: http://www.sph.emory.edu/~cdckms/CoxPH/prophaz2.html @@ -131,14 +115,14 @@ public void RunTest2() { 60, 12, 10, 1 }, }; - ProportionalHazards regression = new ProportionalHazards(2); + var regression = new ProportionalHazards(2); double[][] inputs = data.Submatrix(null, 0, 1).ToArray(); double[] time = data.GetColumn(2); - int[] output = data.GetColumn(3).ToInt32(); + SurvivalOutcome[] output = data.GetColumn(3).To(); - ProportionalHazardsNewtonRaphson target = new ProportionalHazardsNewtonRaphson(regression); + var target = new ProportionalHazardsNewtonRaphson(regression); double error = target.Run(inputs, time, output); @@ -163,7 +147,7 @@ public void RunTest2() } - [TestMethod()] + [Test] public void RunTest3() { // Data from: http://www.sph.emory.edu/~cdckms/CoxPH/prophaz2.html @@ -187,13 +171,13 @@ public void RunTest3() { 60, 10, 1 }, }; - ProportionalHazards regression = new ProportionalHazards(1); + var regression = new ProportionalHazards(1); double[][] inputs = data.GetColumn(0).ToArray(); double[] time = data.GetColumn(1); - int[] output = data.GetColumn(2).ToInt32(); + SurvivalOutcome[] output = data.GetColumn(2).To(); - ProportionalHazardsNewtonRaphson target = new ProportionalHazardsNewtonRaphson(regression); + var target = new ProportionalHazardsNewtonRaphson(regression); double error = target.Run(inputs, time, output); @@ -207,7 +191,7 @@ public void RunTest3() Assert.IsFalse(Double.IsNaN(regression.StandardErrors[0])); } - [TestMethod()] + [Test] public void RunTest4() { // Data from: http://www.sph.emory.edu/~cdckms/CoxPH/prophaz2.html @@ -231,13 +215,13 @@ public void RunTest4() { 60, 10, 1 }, }; - ProportionalHazards regression = new ProportionalHazards(1); + var regression = new ProportionalHazards(1); double[][] inputs = data.GetColumn(0).ToArray(); double[] time = data.GetColumn(1); int[] output = data.GetColumn(2).ToInt32(); - ProportionalHazardsNewtonRaphson target = new ProportionalHazardsNewtonRaphson(regression); + var target = new ProportionalHazardsNewtonRaphson(regression); double error = target.Run(inputs, time, output); @@ -251,7 +235,7 @@ public void RunTest4() Assert.IsFalse(Double.IsNaN(regression.StandardErrors[0])); } - [TestMethod()] + [Test] public void RunTest5() { double[,] inputs = @@ -272,11 +256,11 @@ public void RunTest5() int[] censor = outputs.GetRow(1).ToInt32(); - string inputStr = inputs.Transpose().ToString(Accord.Math.DefaultMatrixFormatProvider.InvariantCulture); - string outputStr = outputs.Transpose().ToString(Accord.Math.DefaultMatrixFormatProvider.InvariantCulture); + // string inputStr = inputs.Transpose().ToString(Accord.Math.DefaultMatrixFormatProvider.InvariantCulture); + // string outputStr = outputs.Transpose().ToString(Accord.Math.DefaultMatrixFormatProvider.InvariantCulture); - ProportionalHazards regression = new ProportionalHazards(2); - ProportionalHazardsNewtonRaphson target = new ProportionalHazardsNewtonRaphson(regression); + var regression = new ProportionalHazards(2); + var target = new ProportionalHazardsNewtonRaphson(regression); double error = target.Run(covariates, time, censor); @@ -294,10 +278,10 @@ public void RunTest5() } - [TestMethod()] + [Test] public void PredictTest1() { - // Data from: http://www.sph.emory.edu/~cdckms/CoxPH/prophaz2.html + // Data from: http://statpages.org/prophaz2.html double[,] data = { @@ -314,38 +298,60 @@ public void PredictTest1() { 60, 10, 1 }, }; - ProportionalHazards regression = new ProportionalHazards(1); + var regression = new ProportionalHazards(1); double[][] inputs = data.GetColumn(0).ToArray(); double[] time = data.GetColumn(1); - int[] output = data.GetColumn(2).ToInt32(); + int[] censor = data.GetColumn(2).ToInt32(); - ProportionalHazardsNewtonRaphson target = new ProportionalHazardsNewtonRaphson(regression); + var target = new ProportionalHazardsNewtonRaphson(regression); - double error = target.Run(inputs, time, output); + double error = target.Run(inputs, time, censor); + + // Tested against http://statpages.org/prophaz2.html + Assert.AreEqual(0.3770, regression.Coefficients[0], 1e-4); + Assert.AreEqual(0.2542, regression.StandardErrors[0], 1e-4); + Assert.AreEqual(51.18181818181818, regression.Offsets[0]); + double mean = regression.Offsets[0]; - double[] expected = + // Baseline survivor function at predictor means + double[] baseline = { - 0.000000000000, 0.919466527073, 0.000074105451, 0.000001707560, - 0.657371730925, 0.046771996036, 0.000074105451, 0.006836271860, - 0.000008042445, 0.339562971888, 2.029832541310 + regression.Survival(2), + regression.Survival(7), + regression.Survival(9), + regression.Survival(10), + }; + + // Tested against http://statpages.org/prophaz2.html + Assert.AreEqual(0.9979, baseline[0], 1e-4); + Assert.AreEqual(0.9820, baseline[1], 1e-4); + Assert.AreEqual(0.9525, baseline[2], 1e-4); + Assert.AreEqual(0.8310, baseline[3], 1e-4); + + double[] expected = + { + 0, 2.51908236823927, 0.000203028311170645, 4.67823782106946E-06, 1.07100164957025, + 0.118590728553659, 0.000203028311170645, 0.0187294821517496, 1.31028937819308E-05, + 0.436716853556834, 5.14665484304978 }; double[] actual = new double[inputs.Length]; for (int i = 0; i < inputs.Length; i++) - actual[i] = regression.Compute(inputs[i], time[i]); - - for (int i = 0; i < actual.Length; i++) { - Assert.AreEqual(expected[i], actual[i], 1e-6); - Assert.IsFalse(Double.IsNaN(actual[i])); + double a = actual[i] = regression.Compute(inputs[i], time[i]); + double e = expected[i]; + + Assert.AreEqual(e, a, 1e-3); } + // string exStr = actual.ToString(CSharpArrayFormatProvider.InvariantCulture); } - [TestMethod()] - public void BaselineHazardTest() + + [Test] + public void BaselineHazardTestR() { double[,] data = { @@ -369,37 +375,242 @@ public void BaselineHazardTest() { 7, 0, 38 }, }; + double[] time = data.GetColumn(0); - int[] censor = data.GetColumn(1).ToInt32(); + SurvivalOutcome[] censor = data.GetColumn(1).To(); double[][] inputs = data.GetColumn(2).ToArray(); - ProportionalHazards regression = new ProportionalHazards(1); + var regression = new ProportionalHazards(1); var target = new ProportionalHazardsNewtonRaphson(regression); - target.Normalize = false; double error = target.Run(inputs, time, censor); - double log = -2 * regression.GetPartialLogLikelihood(inputs, time, censor); - - EmpiricalHazardDistribution baseline = regression.BaselineHazard as EmpiricalHazardDistribution; - - double[] actual = new double[(int)baseline.Support.Max]; - for (int i = (int)baseline.Support.Min; i < baseline.Support.Max; i++) - actual[i] = baseline.CumulativeHazardFunction(i); - - Assert.AreEqual(14, actual.Length); + // Assert.AreEqual(-10.257417973830666, error, 1e-8); + + /* + library('survival') + options(digits=17) + time <- c(8, 4, 12, 6, 10, 8, 5, 5, 3, 14, 8, 11, 7, 7, 12, 8, 7) + x <- c(13, 56, 25, 64, 38, 80, 0, 81, 81, 38, 23, 99, 12, 36, 63, 92, 38) + c <- c(0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0) + + fit <- coxph(Surv(time, c) ~ x, ties="breslow") + + predict(fit,type="risk") + + fit$loglik + + coef exp(coef) se(coef) z p + x 0.01633097532122 1.016465054586 0.01711960930183 0.9539338797573 0.340117112635 + + Likelihood ratio test=0.94 on 1 df, p=0.332836850925 n= 17, number of events= 5 + */ + + // Tested against GNU R + Assert.AreEqual(49.352941176470587, regression.Offsets[0]); + Assert.AreEqual(0.01633097532122, regression.Coefficients[0], 1e-10); + Assert.AreEqual(0.01711960930183, regression.StandardErrors[0], 1e-10); + Assert.AreEqual(0.340117112635, regression.GetWaldTest(0).PValue, 1e-5); + Assert.AreEqual(-10.2879332934202168, regression.GetPartialLogLikelihood(time, censor)); + Assert.AreEqual(-9.8190189050165948, regression.GetPartialLogLikelihood(inputs, time, censor)); + + double[] actual = inputs.Apply(regression.Compute); + + /* + predict(r,type="risk") + [1] 0.55229166964915244 1.11466393245000361 0.67185866444081555 1.27023351821156782 0.83076808526813917 1.64953983529334769 0.44664925161695829 1.67669959872327912 + [9] 1.67669959872327912 0.83076808526813917 0.65026895029003673 2.24967304521214029 0.54334545703992021 0.80407192663266613 1.24965783376477391 2.00665280971219540 + [17] 0.83076808526813917 + */ double[] expected = { - 0,0,0, - 0.025000345517572315,0.052363663484639708,0.052363663484639708,0.052363663484639708, - 0.16317880290786446, - 0.34217461190678861,0.34217461190678861,0.34217461190678861, - 0.34217461190678861,0.34217461190678861,0.34217461190678861 + 0.55229166964915244, 1.11466393245000361, 0.67185866444081555, 1.27023351821156782, + 0.83076808526813917, 1.64953983529334769, 0.44664925161695829, 1.67669959872327912, + 1.67669959872327912, 0.83076808526813917, 0.65026895029003673, 2.24967304521214029, + 0.54334545703992021, 0.80407192663266613, 1.24965783376477391, 2.00665280971219540, + 0.83076808526813917 }; for (int i = 0; i < actual.Length; i++) Assert.AreEqual(expected[i], actual[i], 0.025); + + } + + [Test] + public void BaselineHazardTest() + { + double[,] data = + { + // t c in + { 8, 0, -1.2372626521865966 }, + { 4, 1, 0.22623087329625477 }, + { 12, 0, -0.8288458543774289 }, + { 6, 0, 0.49850873850236665 }, + { 10, 0, -0.38639432341749696 }, + { 8, 1, 1.0430644689145904 }, + { 5, 0, -1.6797141831465285 }, + { 5, 0, 1.0770992020653544 }, + { 3, 1, 1.0770992020653544 }, + { 14, 1, -0.38639432341749696 }, + { 8, 0, -0.8969153206789568 }, + { 11, 0, 1.6897243987791061 }, + { 7, 0, -1.2712973853373605 }, + { 7, 0, -0.38639432341749696 }, + { 7, 1, -0.45446378971902495 }, + { 12, 0, 0.4644740053516027 }, + { 8, 0, 1.4514812667237584 }, + }; + + double[] time = data.GetColumn(0); + SurvivalOutcome[] censor = data.GetColumn(1).To(); + double[][] inputs = data.GetColumn(2).ToArray(); + + var regression = new ProportionalHazards(1); + + var target = new ProportionalHazardsNewtonRaphson(regression); + + target.Normalize = false; + target.Lambda = 0; + regression.Coefficients[0] = 0.47983261821350764; + + double error = target.Run(inputs, time, censor); + + /* Tested against http://statpages.org/prophaz2.html + 13, 8, 0 + 56, 4, 1 + 25, 12, 0 + 64, 6, 0 + 38, 10, 0 + 80, 8, 1 + 0 , 5, 0 + 81, 5, 0 + 81, 3, 1 + 38, 14, 1 + 23, 8, 0 + 99, 11, 0 + 12, 7, 0 + 38, 7, 0 + 36, 7, 1 + 63, 12, 0 + 92, 8, 0 + */ + + double[] baseline = + { + regression.Survival(3), // 0.9465 + regression.Survival(4), // 0.8919 + regression.Survival(7), // 0.8231 + regression.Survival(8), // 0.7436 + regression.Survival(12), // 0.7436 + regression.Survival(14), // 0.0000 + }; + + Assert.AreEqual(0.9465, baseline[0], 1e-4); + Assert.AreEqual(0.8919, baseline[1], 1e-4); + Assert.AreEqual(0.8231, baseline[2], 1e-4); + Assert.AreEqual(0.7436, baseline[3], 1e-4); + Assert.AreEqual(0.7436, baseline[4], 1e-4); + Assert.AreEqual(0.0000, baseline[5], 1e-4); + + // The value of the baseline must be exact the same if it was computed + // after the Newton-Raphson or in a standalone EmpiricalHazard computation + double[] outputs = inputs.Apply(regression.Compute); + var empirical = EmpiricalHazardDistribution.Estimate(time, censor, outputs); + + baseline = new[] + { + empirical.ComplementaryDistributionFunction(3), // 0.9465 + empirical.ComplementaryDistributionFunction(4), // 0.8919 + empirical.ComplementaryDistributionFunction(7), // 0.8231 + empirical.ComplementaryDistributionFunction(8), // 0.7436 + empirical.ComplementaryDistributionFunction(12), // 0.7436 + empirical.ComplementaryDistributionFunction(14), // 0.0000 + }; + + Assert.AreEqual(0.9465, baseline[0], 1e-4); + Assert.AreEqual(0.8919, baseline[1], 1e-4); + Assert.AreEqual(0.8231, baseline[2], 1e-4); + Assert.AreEqual(0.7436, baseline[3], 1e-4); + Assert.AreEqual(0.7436, baseline[4], 1e-4); + Assert.AreEqual(0.0000, baseline[5], 1e-4); + } + + + [Test] + public void KaplanMeierTest2() + { + int[][] data = Groups.Expand( + new[] { 1, 2, 3, 4, 5, 6 }, // years + new[] { 3, 3, 3, 3, 3, 0 }, // died + new[] { 5, 10, 15, 20, 25, 10 } // censored + ); + + double[] time = data.GetColumn(0).ToDouble(); + int[] censor = data.GetColumn(1); + + ProportionalHazards kp; + ProportionalHazards km; + + double errkm, errp; + + { + km = new ProportionalHazards(inputs: 0); + + var target = new ProportionalHazardsNewtonRaphson(km) + { + Estimator = HazardEstimator.KaplanMeier + }; + + errkm = target.Run(time, censor); + Assert.AreEqual(-63.734599918211551, errkm); + } + + { + kp = new ProportionalHazards(inputs: 0); + + var target = new ProportionalHazardsNewtonRaphson(kp) + { + Estimator = HazardEstimator.BreslowNelsonAalen + }; + + errp = target.Run(time, censor); + Assert.AreEqual(errkm, errp); + } + } + + [Test] + public void KaplanMeierTest() + { + double[,] data = + { + // time censor + { 1, 0 }, // died at time 1 + { 2, 1 }, // lost at time 2 + { 3, 0 }, // died at time 3 + { 5, 0 }, // died at time 5 + { 7, 1 }, // lost at time 7 + { 11, 0 }, // ... + { 4, 0 }, + { 6, 0 }, + { 8, 0 }, + { 9, 1 }, + { 10, 1 }, + }; + + double[] time = data.GetColumn(0); + int[] censor = data.GetColumn(1).ToInt32(); + + var regression = new ProportionalHazards(inputs: 0); + + var target = new ProportionalHazardsNewtonRaphson(regression) + { + Estimator = HazardEstimator.KaplanMeier + }; + + double error = target.Run(time, censor); + + Assert.AreEqual(-5.7037824746562009, error); } } } diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Regression/NonlinearLeastSquaresTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Regression/NonlinearLeastSquaresTest.cs index c835be393..49aedf285 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Regression/NonlinearLeastSquaresTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Regression/NonlinearLeastSquaresTest.cs @@ -28,27 +28,12 @@ namespace Accord.Tests.Statistics using Accord.Math.Optimization; using Accord.Statistics.Models.Regression; using Accord.Statistics.Models.Regression.Fitting; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class NonLinearLeastSquaresTest { - - private TestContext testContextInstance; - - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - double function(double[] parameters, double[] input) { double m = parameters[0]; @@ -65,7 +50,7 @@ void gradient(double[] parameters, double[] input, double[] result) double m = parameters[0]; double s = parameters[1]; double a = parameters[2]; - double b = parameters[3]; + // double b = parameters[3]; // not needed double x = input[0]; Func exp = System.Math.Exp; @@ -84,9 +69,79 @@ void gradient(double[] parameters, double[] input, double[] result) result[3] = 1; } - [TestMethod()] + [Test] + public void ExampleTest() + { + // Suppose we would like to map the continuous values in the + // second column to the integer values in the first column. + double[,] data = + { + { -40, -21142.1111111111 }, + { -30, -21330.1111111111 }, + { -20, -12036.1111111111 }, + { -10, 7255.3888888889 }, + { 0, 32474.8888888889 }, + { 10, 32474.8888888889 }, + { 20, 9060.8888888889 }, + { 30, -11628.1111111111 }, + { 40, -15129.6111111111 }, + }; + + // Extract inputs and outputs + double[][] inputs = data.GetColumn(0).ToArray(); + double[] outputs = data.GetColumn(1); + + // Create a Nonlinear regression using + var regression = new NonlinearRegression(3, + + // Let's assume a quadratic model function: ax² + bx + c + function: (w, x) => w[0] * x[0] * x[0] + w[1] * x[0] + w[2], + + // Derivative in respect to the weights: + gradient: (w, x, r) => + { + r[0] = 2 * w[0]; // w.r.t a: 2a + r[1] = w[1]; // w.r.t b: b + r[2] = w[2]; // w.r.t c: 0 + } + ); + + // Create a non-linear least squares teacher + var nls = new NonlinearLeastSquares(regression); + + // Initialize to some random values + regression.Coefficients[0] = 4.2; + regression.Coefficients[1] = 0.3; + regression.Coefficients[2] = 1; + + // Run the function estimation algorithm + double error = Double.PositiveInfinity; + for (int i = 0; i < 100; i++) + error = nls.Run(inputs, outputs); + + // Use the function to compute the input values + double[] predict = inputs.Apply(regression.Compute); + + Assert.IsTrue(nls.Algorithm is LevenbergMarquardt); + + Assert.AreEqual(1318374605.8436923d, error); + + Assert.AreEqual(-12.025250289329851, regression.Coefficients[0], 1e-3); + Assert.AreEqual(-0.082208180694676766, regression.Coefficients[1], 1e-3); + Assert.AreEqual(-0.27402726898225627, regression.Coefficients[2], 1e-3); + + Assert.AreEqual(-19237.386162968953, predict[0]); + Assert.AreEqual(-10820.533042245008, predict[1]); + Assert.AreEqual(-4808.7299793870288, predict[2]); + Assert.AreEqual(-1203.6211380089139, predict[5]); + } + + + [Test] public void RunTest() { + // Suppose we would like to map the continuous values in the + // second column to the integer values in the first column. double[,] data = { { -40, -21142.1111111111 }, @@ -100,9 +155,11 @@ public void RunTest() { 40, -15129.6111111111 }, }; + // Extract inputs and outputs double[][] inputs = data.GetColumn(0).ToArray(); double[] outputs = data.GetColumn(1); + // Create a Nonlinear regression using NonlinearRegression regression = new NonlinearRegression(4, function, gradient); @@ -115,7 +172,7 @@ public void RunTest() regression.Coefficients[2] = 53805; // a regression.Coefficients[3] = -21330.11; //b - double error = 0; + double error = Double.PositiveInfinity; for (int i = 0; i < 100; i++) error = nls.Run(inputs, outputs); @@ -124,6 +181,8 @@ public void RunTest() double a = regression.Coefficients[2]; double b = regression.Coefficients[3]; + Assert.AreEqual(010345587.465428974, error); + Assert.AreEqual(5.316196154830604, m, 1e-3); Assert.AreEqual(12.792301798208918, s, 1e-3); Assert.AreEqual(56794.832645792514, a, 1e-3); @@ -135,7 +194,7 @@ public void RunTest() Assert.IsFalse(Double.IsNaN(b)); } - [TestMethod()] + [Test] public void RunTest1() { // Example from https://en.wikipedia.org/wiki/Gauss%E2%80%93Newton_algorithm @@ -202,6 +261,5 @@ public void RunTest1() Assert.AreEqual(6.06352, regression.StandardErrors[1], 3e-3); } - } } diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Regression/PolynomialRegressionTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Regression/PolynomialRegressionTest.cs index 2cd68ae3e..dd0e8609b 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Regression/PolynomialRegressionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Regression/PolynomialRegressionTest.cs @@ -23,9 +23,9 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Models.Regression.Linear; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class PolynomialRegressionTest { @@ -46,7 +46,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void PolynomialRegressionRegressTest() { double[] inputs = { 15.2, 229.7, 3500 }; @@ -66,7 +66,7 @@ public void PolynomialRegressionRegressTest() Assert.AreEqual(expected[2], actual[2], 000.1); } - [TestMethod()] + [Test] public void ToStringTest() { // Issue 51: diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Regression/ProbitRegressionTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Regression/ProbitRegressionTest.cs index f15ade03f..b499a54df 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Regression/ProbitRegressionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Regression/ProbitRegressionTest.cs @@ -27,9 +27,9 @@ namespace Accord.Tests.Statistics using Accord.Statistics.Links; using Accord.Statistics.Models.Regression; using Accord.Statistics.Models.Regression.Fitting; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class ProbitRegressionTest { @@ -49,7 +49,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ComputeTest() { // Example from http://bayes.bgsu.edu/bcwr/vignettes/probit_regression.pdf @@ -118,7 +118,7 @@ public void ComputeTest() Assert.AreEqual(0.016768779446085, regression.StandardErrors[1], 1e-6); } - [TestMethod()] + [Test] public void ComputeTest2() { double[][] input = diff --git a/Unit Tests/Accord.Tests.Statistics/Models/Regression/SimpleLinearRegressionTest.cs b/Unit Tests/Accord.Tests.Statistics/Models/Regression/SimpleLinearRegressionTest.cs index fe540c64a..816260d40 100644 --- a/Unit Tests/Accord.Tests.Statistics/Models/Regression/SimpleLinearRegressionTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Models/Regression/SimpleLinearRegressionTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Models.Regression.Linear; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class SimpleLinearRegressionTest { @@ -47,7 +47,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void RegressTest() { // Let's say we have some univariate, continuous sets of input data, @@ -86,7 +86,7 @@ public void RegressTest() Assert.IsFalse(double.IsNaN(y)); } - [TestMethod()] + [Test] public void ToStringTest() { // Issue 51: diff --git a/Unit Tests/Accord.Tests.Statistics/MovingNormalStatisticsTest.cs b/Unit Tests/Accord.Tests.Statistics/MovingNormalStatisticsTest.cs index 183364084..fd9439e5b 100644 --- a/Unit Tests/Accord.Tests.Statistics/MovingNormalStatisticsTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/MovingNormalStatisticsTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Moving; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics; - [TestClass()] + [TestFixture] public class MovingNormalStatisticsTest { @@ -46,7 +46,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void PushTest() { double[] values = { 0.24, 1.61, 2.22, 5.82 }; @@ -67,7 +67,7 @@ public void PushTest() Assert.AreEqual(expectedVariance, actualVariance); } - [TestMethod()] + [Test] public void PushTest2() { double[] values = { 0.24, 1.61, 2.22, 5.82 }; diff --git a/Unit Tests/Accord.Tests.Statistics/Properties/Resources.resx b/Unit Tests/Accord.Tests.Statistics/Properties/Resources.resx index 92892ce41..25f4050dd 100644 --- a/Unit Tests/Accord.Tests.Statistics/Properties/Resources.resx +++ b/Unit Tests/Accord.Tests.Statistics/Properties/Resources.resx @@ -122,10 +122,10 @@ ..\Resources\CircleWithWeights.xls;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - ..\resources\hsbdemo.csv;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + ..\Resources\hsbdemo.csv;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 - ..\resources\regression.csv;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + ..\Resources\regression.csv;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 ..\Resources\sample.xls;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 diff --git a/Unit Tests/Accord.Tests.Statistics/RunningMarkovClassifierTest.cs b/Unit Tests/Accord.Tests.Statistics/RunningMarkovClassifierTest.cs index 5aad9e29b..18f0a0bb6 100644 --- a/Unit Tests/Accord.Tests.Statistics/RunningMarkovClassifierTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/RunningMarkovClassifierTest.cs @@ -23,7 +23,7 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Running; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Statistics.Distributions; using Accord.Statistics.Models.Markov; @@ -33,7 +33,7 @@ namespace Accord.Tests.Statistics using Accord.Math; using Accord.Statistics.Models.Markov.Topology; - [TestClass()] + [TestFixture] public class GenericRunningMarkovClassifierTest { @@ -55,7 +55,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void PushTest() { int[][] sequences; @@ -83,7 +83,7 @@ public void PushTest() } } - [TestMethod()] + [Test] public void PushTest2() { int[][] sequences; diff --git a/Unit Tests/Accord.Tests.Statistics/RunningMarkovClassifierTest`1.cs b/Unit Tests/Accord.Tests.Statistics/RunningMarkovClassifierTest`1.cs index 51bf98c8b..3d9faa782 100644 --- a/Unit Tests/Accord.Tests.Statistics/RunningMarkovClassifierTest`1.cs +++ b/Unit Tests/Accord.Tests.Statistics/RunningMarkovClassifierTest`1.cs @@ -23,7 +23,7 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Running; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Statistics.Distributions; using Accord.Statistics.Models.Markov; @@ -33,7 +33,7 @@ namespace Accord.Tests.Statistics using Accord.Math; using Accord.Statistics.Models.Markov.Topology; - [TestClass()] + [TestFixture] public class RunningMarkovClassifierTest { @@ -55,7 +55,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void PushTest() { double[][] sequences; @@ -83,7 +83,7 @@ public void PushTest() } } - [TestMethod()] + [Test] public void PushTest2() { double[][] sequences; diff --git a/Unit Tests/Accord.Tests.Statistics/RunningMarkovModelTest.cs b/Unit Tests/Accord.Tests.Statistics/RunningMarkovModelTest.cs index ece58fc01..45f59e8e8 100644 --- a/Unit Tests/Accord.Tests.Statistics/RunningMarkovModelTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/RunningMarkovModelTest.cs @@ -28,14 +28,14 @@ namespace Accord.Tests.Statistics using Accord.Statistics.Models.Markov.Learning; using Accord.Statistics.Models.Markov.Topology; using Accord.Statistics.Running; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class RunningMarkovModelTest { - [TestMethod()] + [Test] public void PushTest() { var hmm = createModel(); @@ -79,7 +79,7 @@ public void PushTest() } } - [TestMethod()] + [Test] public void PeekTest() { var hmm = createModel(); diff --git a/Unit Tests/Accord.Tests.Statistics/RunningNormalStatisticsTest.cs b/Unit Tests/Accord.Tests.Statistics/RunningNormalStatisticsTest.cs index 885847ee6..05a3e8e39 100644 --- a/Unit Tests/Accord.Tests.Statistics/RunningNormalStatisticsTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/RunningNormalStatisticsTest.cs @@ -24,13 +24,13 @@ namespace Accord.Tests.Statistics { using Accord.Statistics; using Accord.Statistics.Running; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class RunningNormalStatisticsTest { - [TestMethod()] + [Test] public void ClearTest() { double[] values = { 0.5, -1.2, 0.7, 0.2, 1.1 }; @@ -52,7 +52,7 @@ public void ClearTest() Assert.AreEqual(Tools.Variance(values2), target.Variance, 1e-10); } - [TestMethod()] + [Test] public void MeanTest() { double[] values = { 0.5, -1.2, 0.7, 0.2, 1.1 }; @@ -68,7 +68,7 @@ public void MeanTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void StandardDeviationTest() { double[] values = { 0.5, -1.2, 0.7, 0.2, 1.1 }; @@ -84,7 +84,7 @@ public void StandardDeviationTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void VarianceTest() { double[] values = { 0.5, -1.2, 0.7, 0.2, 1.1 }; @@ -100,7 +100,7 @@ public void VarianceTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void RunningNormalStatisticsConstructorTest() { RunningNormalStatistics target = new RunningNormalStatistics(); diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/AndersonDarlingTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/AndersonDarlingTestTest.cs index 6a3c07a81..2c1ff7d60 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/AndersonDarlingTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/AndersonDarlingTestTest.cs @@ -25,9 +25,9 @@ namespace Accord.Tests.Statistics using System; using Accord.Statistics.Distributions.Univariate; using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class AndersonDarlingTestTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void AndersonDarlingConstructorTest() { // Test against a standard Uniform distribution @@ -106,7 +106,7 @@ public void AndersonDarlingConstructorTest() Assert.IsFalse(adtest.Significant); } - [TestMethod()] + [Test] public void AndersonDarlingConstructorTest2() { // Test against a Normal distribution diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/BartlettTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/BartlettTestTest.cs index a26783873..cdf2b6d11 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/BartlettTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/BartlettTestTest.cs @@ -23,12 +23,12 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Math; - [TestClass()] + [TestFixture] public class BartlettTestTest { @@ -50,7 +50,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void BartlettTestConstructorTest() { // Example from NIST/SEMATECH e-Handbook of Statistical Methods, diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/BinomialTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/BinomialTestTest.cs index dee36366f..dd34bfa9f 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/BinomialTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/BinomialTestTest.cs @@ -23,10 +23,10 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; - [TestClass()] + [TestFixture] public class BinomialTestTest { @@ -49,7 +49,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void BinomialTestConstructorTest1() { @@ -65,7 +65,7 @@ public void BinomialTestConstructorTest1() Assert.IsTrue(target.Significant); } - [TestMethod()] + [Test] public void BinomialTestConstructorTest4() { @@ -81,7 +81,7 @@ public void BinomialTestConstructorTest4() Assert.IsTrue(target.Significant); } - [TestMethod()] + [Test] public void BinomialTestConstructorTest2() { int successes = 5; @@ -99,7 +99,7 @@ public void BinomialTestConstructorTest2() Assert.IsTrue(target.Significant); } - [TestMethod()] + [Test] public void BinomialTestConstructorTest3() { // GNU R (0.096248626708984375) @@ -113,7 +113,7 @@ public void BinomialTestConstructorTest3() Assert.IsFalse(target.Significant); } - [TestMethod()] + [Test] public void BinomialTestConstructorTest8() { // Example from Jeffrey S. Simonoff, Analyzing Categorical Data, pg 64 @@ -138,7 +138,7 @@ public void BinomialTestConstructorTest8() Assert.IsTrue(target.Significant); } - [TestMethod()] + [Test] public void BinomialTestConstructorTest6() { double[] expected = @@ -158,7 +158,7 @@ public void BinomialTestConstructorTest6() } } - [TestMethod()] + [Test] public void BinomialTestConstructorTest7() { // Wolfram Alpha reports 0.063564300537 diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/ChiSquareTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/ChiSquareTestTest.cs index bc847eb4c..dea66d0e7 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/ChiSquareTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/ChiSquareTestTest.cs @@ -23,11 +23,11 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics.Distributions.Univariate; - [TestClass()] + [TestFixture] public class ChiSquareTestTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ConstructorTest() { double[] observed = { 639, 241 }; @@ -62,7 +62,7 @@ public void ConstructorTest() Assert.AreEqual(0.1020, chi.PValue, 1e-4); } - [TestMethod()] + [Test] public void ConstructorTest2() { double[] observed = { 6, 6, 16, 15, 4, 3 }; @@ -76,7 +76,7 @@ public void ConstructorTest2() Assert.AreEqual(false, chi.Significant); } - [TestMethod()] + [Test] public void ConstructorTest3() { // Example based on Wikipedia's article for χ²-Squared Test @@ -125,7 +125,7 @@ public void ConstructorTest3() Assert.IsFalse(significant); } - [TestMethod()] + [Test] public void ConstructorTest4() { double[] sample = @@ -143,7 +143,7 @@ public void ConstructorTest4() Assert.IsFalse(chi.Significant); } - [TestMethod()] + [Test] public void ConstructorTest5() { Accord.Math.Tools.SetupGenerator(0); @@ -183,7 +183,7 @@ public void ConstructorTest5() } } - [TestMethod()] + [Test] public void ConstructorTest_WithZero_NoNaN() { double[] observed = { 639, 0 }; diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/Contingency/BhapkarTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/Contingency/BhapkarTestTest.cs index 9b64d55ad..22f2539f1 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/Contingency/BhapkarTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/Contingency/BhapkarTestTest.cs @@ -24,9 +24,9 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Analysis; using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class BhapkarTestTest { @@ -47,7 +47,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void BhapkarTestConstructorTest() { // Bhapkar, V.P. (1966). A note on the equivalence of two test criteria diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/Contingency/BowkerTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/Contingency/BowkerTestTest.cs index 943069440..b7047665a 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/Contingency/BowkerTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/Contingency/BowkerTestTest.cs @@ -23,11 +23,11 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Statistics.Analysis; - [TestClass()] + [TestFixture] public class BowkerTestTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void BowkerTestConstructorTest() { // Example from Bortz, Lienert and Klaus. Boehnke Verteilungsfreie Methoden in Der Biostatistik, pg 166 diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/Contingency/FisherExactTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/Contingency/FisherExactTestTest.cs index e792b29e7..30b6d2744 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/Contingency/FisherExactTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/Contingency/FisherExactTestTest.cs @@ -3,11 +3,11 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Statistics.Analysis; - [TestClass()] + [TestFixture] public class FisherExactTestTest { @@ -28,7 +28,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void FisherExactTestConstructorTest1() { // Example from http://rfd.uoregon.edu/files/rfd/StatisticalResources/lec_05a.txt diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/Contingency/KappaTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/Contingency/KappaTestTest.cs index 153bcfbda..03a5078ff 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/Contingency/KappaTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/Contingency/KappaTestTest.cs @@ -24,10 +24,10 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Analysis; using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; - [TestClass()] + [TestFixture] public class KappaTestTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void KappaTestConstructorTest() { // Example from http://vassarstats.net/kappa.html @@ -94,7 +94,7 @@ public void KappaTestConstructorTest() Assert.IsFalse(double.IsNaN(target.StandardError)); } - [TestMethod()] + [Test] public void KappaTestConstructorTest2() { // Example from: M. Reichenheim (2004). Confidence intervals for the @@ -126,7 +126,7 @@ public void KappaTestConstructorTest2() Assert.AreEqual(7.0849733798130419E-27, target.PValue); } - [TestMethod()] + [Test] public void KappaTestConstructorTest4() { // Example from Statistical Methods for Rates and Proportions @@ -186,7 +186,7 @@ public void KappaTestConstructorTest4() Assert.IsFalse(target.Significant); } - [TestMethod()] + [Test] public void KappaTestConstructorTest5() { // Example from Statistical Methods for Rates and Proportions diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/Contingency/McNemarTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/Contingency/McNemarTestTest.cs index 655b709b1..c196c1316 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/Contingency/McNemarTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/Contingency/McNemarTestTest.cs @@ -24,9 +24,9 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Analysis; using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class McNemarTestTest { @@ -47,7 +47,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void McNemarTestConstructorTest() { int[,] matrix = diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/Contingency/TwoMatrixKappaTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/Contingency/TwoMatrixKappaTestTest.cs index 051f5e98c..38bf4c815 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/Contingency/TwoMatrixKappaTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/Contingency/TwoMatrixKappaTestTest.cs @@ -24,9 +24,9 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Analysis; using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class TwoMatrixKappaTestTest { @@ -47,7 +47,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void KappaTestConstructorTest1() { // Example from Ientilucci, Emmett (2006). "On Using and Computing the Kappa Statistic". @@ -115,7 +115,7 @@ public void KappaTestConstructorTest1() Assert.IsFalse(target.Significant); } - [TestMethod()] + [Test] public void KappaTestConstructorTest2() { // Example from Congalton @@ -202,7 +202,7 @@ public void KappaTestConstructorTest2() Assert.IsFalse(target.Significant); } - [TestMethod()] + [Test] public void KappaTestConstructorTest3() { double k1 = 0.95; @@ -221,7 +221,7 @@ public void KappaTestConstructorTest3() Assert.IsTrue(target.Significant); } - [TestMethod()] + [Test] public void KappaTestConstructorTest4() { { diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/FTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/FTestTest.cs index b08cece8b..b20094a73 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/FTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/FTestTest.cs @@ -3,10 +3,10 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; - [TestClass()] + [TestFixture] public class FTestTest { @@ -27,7 +27,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void FTestConstructorTest() { double var1 = 1.05766555271071; @@ -48,7 +48,7 @@ public void FTestConstructorTest() Assert.IsFalse(Double.IsNaN(twoTail.PValue)); } - [TestMethod()] + [Test] public void FTestConstructorTest2() { // The following example has been based on the page "F-Test for Equality diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/KolmogorovSmirnovTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/KolmogorovSmirnovTestTest.cs index cf0694245..f2d163bf8 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/KolmogorovSmirnovTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/KolmogorovSmirnovTestTest.cs @@ -25,10 +25,10 @@ namespace Accord.Tests.Statistics using System; using Accord.Statistics.Distributions.Univariate; using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics.Distributions; - [TestClass()] + [TestFixture] public class KolmogorovSmirnovTestTest { @@ -49,7 +49,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void KolmogorovSmirnovTestConstructorTest() { // Test against a standard Uniform distribution @@ -96,7 +96,7 @@ public void KolmogorovSmirnovTestConstructorTest() Assert.IsFalse(kstest.Significant); } - [TestMethod()] + [Test] public void KolmogorovSmirnovTestConstructorTest2() { // Test against a Normal distribution @@ -141,7 +141,7 @@ public void KolmogorovSmirnovTestConstructorTest2() Assert.IsTrue(kstest.Significant); } - [TestMethod()] + [Test] public void KolmogorovSmirnovTestConstructorTest3() { // Test if the sample's distribution is greater than a standard Normal distribution. @@ -161,7 +161,7 @@ public void KolmogorovSmirnovTestConstructorTest3() Assert.IsFalse(Double.IsNaN(target.Statistic)); } - [TestMethod()] + [Test] public void KolmogorovSmirnovTestConstructorTest4() { // Test if the sample's distribution is smaller than a standard Normal distribution @@ -181,7 +181,7 @@ public void KolmogorovSmirnovTestConstructorTest4() Assert.IsFalse(Double.IsNaN(target.Statistic)); } - [TestMethod()] + [Test] public void EmpiricalDistributionTest() { double[] sample = { 1, 5, 3, 1, 5, 2, 1 }; @@ -199,7 +199,7 @@ public void EmpiricalDistributionTest() Assert.AreEqual(sample[i], actual.Samples[i]); } - [TestMethod()] + [Test] public void TheoreticalDistributionTest() { double[] sample = { 1, 5, 3, 1, 5, 2, 1 }; diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/LeveneTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/LeveneTestTest.cs index 20f0d2797..d99cf0504 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/LeveneTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/LeveneTestTest.cs @@ -23,11 +23,11 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using System.Collections.Generic; - [TestClass()] + [TestFixture] public class LeveneTestTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void LeveneTestConstructorTest() { // Example from NIST/SEMATECH e-Handbook of Statistical Methods, @@ -63,7 +63,7 @@ public void LeveneTestConstructorTest() Assert.IsFalse(double.IsNaN(target.Statistic)); } - [TestMethod()] + [Test] public void LeveneTestConstructorTest2() { double[][] samples = @@ -81,7 +81,7 @@ public void LeveneTestConstructorTest2() Assert.AreEqual(0.58857793222910693, result.PValue); } - [TestMethod()] + [Test] public void LeveneTestConstructorTest3() { double[][] samples = diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/MannWhitneyWilcoxonTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/MannWhitneyWilcoxonTestTest.cs index 90990622c..b2bcf2503 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/MannWhitneyWilcoxonTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/MannWhitneyWilcoxonTestTest.cs @@ -4,10 +4,10 @@ namespace Accord.Tests.Statistics { using Accord.Math; using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; - [TestClass()] + [TestFixture] public class MannWhitneyWilcoxonTestTest { @@ -28,7 +28,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void MannWhitneyWilcoxonTestConstructorTest() { // The following example comes from Richard Lowry's page at @@ -85,7 +85,7 @@ public void MannWhitneyWilcoxonTestConstructorTest() Assert.IsFalse(test.Significant); } - [TestMethod()] + [Test] public void MannWhitneyWilcoxonTestConstructorTest1() { // Example from Conover, "Practical nonparametric statistics", 1999 (pg. 218) diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/MultinomialTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/MultinomialTestTest.cs index 7e88eb637..b15f906ac 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/MultinomialTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/MultinomialTestTest.cs @@ -23,11 +23,11 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; - [TestClass()] + [TestFixture] public class MultinomialTestTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void MultinomialTestConstructorTest() { // Example from http://www.stat.berkeley.edu/~stark/SticiGui/Text/chiSquare.htm @@ -70,7 +70,7 @@ public void MultinomialTestConstructorTest() Assert.AreEqual(3.55555556, target.Statistic, 1e-5); } - [TestMethod()] + [Test] public void MultinomialTestConstructorTest2() { // This example is based on the example available on About.com Statistics, diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/OneWayAnovaTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/OneWayAnovaTest.cs index f9245f44d..cd876a435 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/OneWayAnovaTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/OneWayAnovaTest.cs @@ -21,7 +21,7 @@ // using Accord.Statistics.Testing; -using Microsoft.VisualStudio.TestTools.UnitTesting; +using NUnit.Framework; using Accord.Math; using Accord.Statistics; @@ -29,7 +29,7 @@ namespace Accord.Tests.Statistics { - [TestClass()] + [TestFixture] public class OneWayAnovaTest { @@ -50,7 +50,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void OneWayAnovaConstructorTest() { // The following is the same example given in Wikipedia's page for the @@ -120,7 +120,7 @@ public void OneWayAnovaConstructorTest() } - [TestMethod()] + [Test] public void OneWayAnovaConstructorTest2() { // Test for unequal sample sizes diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/Power/TTestPowerAnalysisTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/Power/TTestPowerAnalysisTest.cs index eaf574dab..aa85c6079 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/Power/TTestPowerAnalysisTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/Power/TTestPowerAnalysisTest.cs @@ -27,9 +27,9 @@ namespace Accord.Tests.Statistics using Accord.Statistics; using Accord.Statistics.Testing; using Accord.Statistics.Testing.Power; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class TTestPowerAnalysisTest { @@ -51,7 +51,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void TTestPowerAnalysisConstructorTest4() { // Example from http://www.ats.ucla.edu/stat/stata/dae/t_test_power2.htm, @@ -101,7 +101,7 @@ public void TTestPowerAnalysisConstructorTest4() } } - [TestMethod()] + [Test] public void TTestPowerAnalysisConstructorTest() { // Let's say we have two samples, and we would like to know whether those @@ -282,7 +282,7 @@ public void TTestPowerAnalysisConstructorTest() } - [TestMethod()] + [Test] public void TTestPowerAnalysisConstructorTest2() { // Example from R's graphical manual @@ -338,7 +338,7 @@ public void TTestPowerAnalysisConstructorTest2() Assert.AreEqual(expected, actual, 1e-6); } - [TestMethod()] + [Test] public void TTestPowerAnalysisConstructorTest3() { // Examples from R's graphical manual @@ -392,7 +392,7 @@ public void TTestPowerAnalysisConstructorTest3() } } - [TestMethod()] + [Test] public void TTestPowerAnalysisConstructorTest7() { // When creating a power analysis, we have three things we can @@ -438,7 +438,7 @@ public void TTestPowerAnalysisConstructorTest7() Assert.AreEqual(0.33167864622935495, power); } - [TestMethod()] + [Test] public void TTestPowerAnalysisConstructorTest5() { var analysis = new TwoSampleTTestPowerAnalysis(TwoSampleHypothesis.ValuesAreDifferent); diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/Power/ZTestPowerAnalysisTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/Power/ZTestPowerAnalysisTest.cs index a1ccdc1a5..b2760f1c4 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/Power/ZTestPowerAnalysisTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/Power/ZTestPowerAnalysisTest.cs @@ -25,9 +25,9 @@ namespace Accord.Tests.Statistics using Accord.Statistics.Testing; using Accord.Statistics.Testing.Power; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class ZTestPowerAnalysisTest { @@ -49,7 +49,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ZTestPowerAnalysisConstructorTest1() { ZTestPowerAnalysis target; @@ -97,7 +97,7 @@ public void ZTestPowerAnalysisConstructorTest1() Assert.AreEqual(expected, actual, 1e-5); } - [TestMethod()] + [Test] public void ZTestPowerAnalysisConstructorTest2() { // When creating a power analysis, we have three things we can diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/ShapiroWilkTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/ShapiroWilkTestTest.cs index e94559995..abce8bdb4 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/ShapiroWilkTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/ShapiroWilkTestTest.cs @@ -25,9 +25,9 @@ namespace Accord.Tests.Statistics using System; using Accord.Statistics.Distributions.Univariate; using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class ShapiroWilkTestTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ShapiroWilkTest() { // Tested against R's shapiro.test(x) @@ -75,7 +75,7 @@ public void ShapiroWilkTest() Assert.AreEqual(0.04209, target.PValue, 1e-5); } - [TestMethod()] + [Test] public void ShapiroWilkTest2() { // Tested against R's shapiro.test(x) diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/SignTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/SignTestTest.cs index 41e802ae0..f416d4eb9 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/SignTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/SignTestTest.cs @@ -23,13 +23,13 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using Accord.Statistics.Distributions.Univariate; using Accord.Math; using Accord.Statistics; - [TestClass()] + [TestFixture] public class SignTestTest { @@ -51,7 +51,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void SignTestConstructorTest() { // Example from http://www.unm.edu/~marcusj/1Samplesign.pdf @@ -73,7 +73,7 @@ public void SignTestConstructorTest() } - [TestMethod()] + [Test] public void SignTestConstructorTest2() { // This example has been adapted from the Wikipedia's page about diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/StuartMaxwellTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/StuartMaxwellTestTest.cs index 167b3ff09..8572a56e6 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/StuartMaxwellTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/StuartMaxwellTestTest.cs @@ -24,11 +24,11 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Analysis; using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; - [TestClass()] + [TestFixture] public class StuartMaxwellTestTest { @@ -49,7 +49,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void StuartMaxwellTestConstructorTest() { // Example from http://www.john-uebersax.com/stat/mcnemar.htm#stuart diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/TTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/TTestTest.cs index 060e6fe3b..38541731d 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/TTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/TTestTest.cs @@ -24,11 +24,11 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics.Testing.Power; using System; - [TestClass()] + [TestFixture] public class TTestTest { @@ -49,7 +49,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void TTestConstructorTest() { @@ -108,7 +108,7 @@ public void TTestConstructorTest() Assert.IsFalse(target.Significant); // null cannot be rejected } - [TestMethod()] + [Test] public void TTestConstructorTest2() { @@ -156,7 +156,7 @@ public void TTestConstructorTest2() } - [TestMethod()] + [Test] public void StatisticToPValueTest() { double df = 2.2; @@ -212,7 +212,7 @@ public void StatisticToPValueTest() } } - [TestMethod()] + [Test] public void PValueToStatisticTest() { double df = 2.6; @@ -268,7 +268,7 @@ public void PValueToStatisticTest() } } - [TestMethod()] + [Test] public void PowerTest() { int samples = 5; diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/PairedTTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/PairedTTestTest.cs index 7373ddc3f..f438552e6 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/PairedTTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/PairedTTestTest.cs @@ -24,12 +24,12 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics.Testing.Power; using System; using Accord.Math; - [TestClass()] + [TestFixture] public class PairedTTestTest { @@ -50,7 +50,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void TTestConstructorTest() { // Suppose we would like to know the effect of a treatment (such diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/TwoProportionZTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/TwoProportionZTestTest.cs index c2bf7a3d5..566f30f9d 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/TwoProportionZTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/TwoProportionZTestTest.cs @@ -23,12 +23,12 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using AForge; using Accord.Statistics.Testing.Power; - [TestClass()] + [TestFixture] public class TwoProportionZTestTest { @@ -49,7 +49,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void TwoProportionZTestConstructorTest() { // Example from http://stattrek.com/hypothesis-test/difference-in-proportions.aspx diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/TwoSampleKolmogorovSmirnovTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/TwoSampleKolmogorovSmirnovTestTest.cs index a39eff834..dfc3d811d 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/TwoSampleKolmogorovSmirnovTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/TwoSampleKolmogorovSmirnovTestTest.cs @@ -25,10 +25,10 @@ namespace Accord.Tests.Statistics using System; using Accord.Statistics.Distributions.Univariate; using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Math; - [TestClass()] + [TestFixture] public class TwoSampleKolmogorovSmirnovTestTest { @@ -49,7 +49,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void TwoSampleKolmogorovSmirnovTestConstructorTest() { Accord.Math.Tools.SetupGenerator(0); @@ -78,7 +78,7 @@ public void TwoSampleKolmogorovSmirnovTestConstructorTest() Assert.AreEqual(0.00826, test.PValue, 1e-5); } - [TestMethod()] + [Test] public void TwoSampleKolmogorovSmirnovTestConstructorTest2() { // The following example comes from the stats page of the College @@ -128,7 +128,7 @@ public void TwoSampleKolmogorovSmirnovTestConstructorTest2() Assert.AreEqual(0.270697775095498, oneTailLesser.PValue, 1e-10); } - [TestMethod()] + [Test] public void TwoSampleKolmogorovSmirnovTestConstructorTest3() { double[] x = { 1, 2, 3, 4, 5 }; diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/TwoSampleSignTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/TwoSampleSignTestTest.cs index d8f4a5aaa..94d27a1ad 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/TwoSampleSignTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/TwoSampleSignTestTest.cs @@ -1,11 +1,11 @@ using Accord.Statistics.Testing; -using Microsoft.VisualStudio.TestTools.UnitTesting; +using NUnit.Framework; using System; namespace Accord.Tests.Statistics { - [TestClass()] + [TestFixture] public class TwoSampleSignTestTest { @@ -27,7 +27,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void SignTestConstructorTest() { // Example from http://probabilityandstats.wordpress.com/2010/02/28/the-sign-test-more-examples/ @@ -53,7 +53,7 @@ public void SignTestConstructorTest() } } - [TestMethod()] + [Test] public void SignTestConstructorTest2() { int positives = 9; diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/TwoSampleTTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/TwoSampleTTestTest.cs index b38216d43..ffe62c770 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/TwoSampleTTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/TwoSampleTTestTest.cs @@ -24,10 +24,10 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Accord.Statistics.Testing.Power; - [TestClass()] + [TestFixture] public class TwoSampleTTestTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void TTestConstructorTest() { // Example from http://en.wikipedia.org/wiki/Student%27s_t-test#Two-sample_T.C2.A02_test @@ -95,7 +95,7 @@ public void TTestConstructorTest() Assert.AreEqual(0.038, test.PValue, 0.0015); } - [TestMethod()] + [Test] public void TTestConstructorTest2() { @@ -133,7 +133,7 @@ public void TTestConstructorTest2() Assert.IsFalse(test.Significant); } - [TestMethod] + [Test] public void SampleSizeTest1() { // Example from http://udel.edu/~mcdonald/statttest.html diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/TwoSampleWilcoxonSignedRankTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/TwoSampleWilcoxonSignedRankTestTest.cs index 48e54150f..96c258664 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/TwoSampleWilcoxonSignedRankTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/TwoSampleWilcoxonSignedRankTestTest.cs @@ -23,12 +23,12 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using System.Data; using Accord.Math; - [TestClass()] + [TestFixture] public class TwoSampleWilcoxonSignedRankTestTest { @@ -49,7 +49,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void WilcoxonSignedRankTestConstructorTest() { // Example from http://en.wikipedia.org/wiki/Wilcoxon_signed-rank_test @@ -67,7 +67,7 @@ public void WilcoxonSignedRankTestConstructorTest() Assert.IsFalse(target.Significant); } - [TestMethod()] + [Test] public void WilcoxonSignedRankTestConstructorTest2() { // Example from http://vassarstats.net/textbook/ch12a.html @@ -87,7 +87,7 @@ public void WilcoxonSignedRankTestConstructorTest2() Assert.IsTrue(target.PValue > 0.01 && target.PValue < 0.05); } - [TestMethod()] + [Test] public void WilcoxonSignedRankTestConstructorTest3() { // Example from http://courses.wcupa.edu/rbove/Berenson/CD-ROM%20Topics/topice-10_5.pdf @@ -111,7 +111,7 @@ public void WilcoxonSignedRankTestConstructorTest3() Assert.IsTrue(target.Significant); } - [TestMethod()] + [Test] public void WilcoxonSignedRankTestConstructorTest4() { // Example from http://mlsc.lboro.ac.uk/resources/statistics/wsrt.pdf diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/TwoSampleZTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/TwoSampleZTestTest.cs index 3da957918..d3d9b7e50 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/TwoSampleZTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/TwoSamples/TwoSampleZTestTest.cs @@ -23,12 +23,12 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using AForge; using Accord.Statistics.Testing.Power; - [TestClass()] + [TestFixture] public class TwoSampleZTestTest { @@ -49,7 +49,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void TwoSampleZTestConstructorTest() { Accord.Math.Tools.SetupGenerator(0); @@ -84,7 +84,7 @@ public void TwoSampleZTestConstructorTest() Assert.IsTrue(actual.Significant); } - [TestMethod()] + [Test] public void TwoSampleZTestConstructorTest1() { // Example from http://www.stat.ucla.edu/~cochran/stat10/winter/lectures/lect21.html @@ -108,7 +108,7 @@ public void TwoSampleZTestConstructorTest1() Assert.IsTrue(target.Significant); } - [TestMethod()] + [Test] public void TwoSampleZTestConstructorTest2() { // Example from http://www.stat.purdue.edu/~tlzhang/stat511/chapter9_1.pdf @@ -141,7 +141,7 @@ public void TwoSampleZTestConstructorTest2() Assert.IsTrue(target.Significant); } - [TestMethod()] + [Test] public void TwoSampleZTestConstructorTest3() { // Example from Larser & Farber, Elementary Statistics: Picturing the world @@ -198,7 +198,7 @@ public void TwoSampleZTestConstructorTest3() } } - [TestMethod()] + [Test] public void PowerTest1() { // Example from http://www.statpower.net/Content/310/Print%20Version%20--%20Power%20for%20the%202-Sample%20Z-Statistic.pdf @@ -226,7 +226,7 @@ public void PowerTest1() Assert.AreEqual(expectedSamples, actualSamples); } - [TestMethod] + [Test] public void SampleSizeTest1() { // Example from http://udel.edu/~mcdonald/statttest.html diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/TwoWayAnovaTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/TwoWayAnovaTest.cs index fc265ccd1..8fbc44557 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/TwoWayAnovaTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/TwoWayAnovaTest.cs @@ -24,10 +24,10 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; - [TestClass()] + [TestFixture] public class TwoWayAnovaTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void TwoWayAnovaConstructorTest() { // Example by Aalborg Universitet @@ -81,7 +81,7 @@ public void TwoWayAnovaConstructorTest() testSources(target); } - [TestMethod()] + [Test] public void TwoWayAnovaConstructorTest2() { // Example by Aalborg Universitet diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/WilcoxonSignedRankTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/WilcoxonSignedRankTestTest.cs index 347f92227..81dafbe12 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/WilcoxonSignedRankTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/WilcoxonSignedRankTestTest.cs @@ -23,13 +23,13 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Testing; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using System; using System.Data; using Accord.Math; using Accord.Statistics; - [TestClass()] + [TestFixture] public class WilcoxonSignedRankTestTest { @@ -50,7 +50,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void WilcoxonSignedRankTestConstructorTest() { double[] sample = { 17, 50, 45, 59.8, 21.74, 16, 9, 15.43, 5.12, 40, 35, 13.35, 13.4 }; @@ -72,7 +72,7 @@ public void WilcoxonSignedRankTestConstructorTest() Assert.IsTrue(target.Significant); } - [TestMethod()] + [Test] public void WilcoxonSignedRankTestConstructorTest2() { // Example from https://onlinecourses.science.psu.edu/stat414/node/319 @@ -94,7 +94,7 @@ public void WilcoxonSignedRankTestConstructorTest2() Assert.IsFalse(target.Significant); } - [TestMethod()] + [Test] public void WilcoxonSignedRankTestConstructorTest3() { // Example from https://onlinecourses.science.psu.edu/stat414/node/319 @@ -118,7 +118,7 @@ public void WilcoxonSignedRankTestConstructorTest3() Assert.IsFalse(target.Significant); } - [TestMethod()] + [Test] public void ConstructorTest2() { // This example has been adapted from the Wikipedia's page about diff --git a/Unit Tests/Accord.Tests.Statistics/Testing/ZTestTest.cs b/Unit Tests/Accord.Tests.Statistics/Testing/ZTestTest.cs index 1819eebd9..4ae03702f 100644 --- a/Unit Tests/Accord.Tests.Statistics/Testing/ZTestTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Testing/ZTestTest.cs @@ -24,9 +24,9 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Testing; using Accord.Statistics.Testing.Power; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class ZTestTest { @@ -48,7 +48,7 @@ public TestContext TestContext - [TestMethod()] + [Test] public void ZTestConstructorTest() { // This example has been gathered from the Wikipedia's page about @@ -107,7 +107,7 @@ public void ZTestConstructorTest() } - [TestMethod()] + [Test] public void ZTestConstructorTest2() { // Example from http://science.kennesaw.edu/~jdemaio/1107/hypothesis_testing.htm @@ -130,7 +130,7 @@ public void ZTestConstructorTest2() Assert.IsTrue(target.Significant); } - [TestMethod()] + [Test] public void ZTestConstructorTest3() { // Example from http://science.kennesaw.edu/~jdemaio/1107/hypothesis_testing.htm @@ -153,7 +153,7 @@ public void ZTestConstructorTest3() Assert.IsFalse(target.Significant); } - [TestMethod()] + [Test] public void ZTestConstructorTest4() { // Example from http://science.kennesaw.edu/~jdemaio/1107/hypothesis_testing.htm @@ -176,7 +176,7 @@ public void ZTestConstructorTest4() Assert.IsFalse(target.Significant); } - [TestMethod()] + [Test] public void PowerTest1() { // Example from http://wise.cgu.edu/powermod/computing.asp @@ -199,7 +199,7 @@ public void PowerTest1() Assert.AreEqual(0.0, power.Power, 1e-3); } - [TestMethod()] + [Test] public void SampleSizeTest1() { // Example from http://wise.cgu.edu/powermod/computing.asp @@ -223,7 +223,7 @@ public void SampleSizeTest1() Assert.AreEqual(82, sampleSize, 1e-16); } - [TestMethod()] + [Test] public void PowerTest2() { // Example from http://www.cyclismo.org/tutorial/R/power.html @@ -241,7 +241,7 @@ public void PowerTest2() Assert.AreEqual(0.918362, power.Power, 1e-6); } - [TestMethod()] + [Test] public void StatisticToPValueTest() { double z = 1.96; @@ -295,7 +295,7 @@ public void StatisticToPValueTest() } } - [TestMethod()] + [Test] public void PValueToStatisticTest() { double p = 0.05; @@ -350,7 +350,7 @@ public void PValueToStatisticTest() } } - [TestMethod()] + [Test] public void EffectSizeTest1() { // Example from http://wise.cgu.edu/powermod/computing.asp @@ -371,7 +371,7 @@ public void EffectSizeTest1() Assert.AreEqual(0.50, power.Effect, 0.005); } - [TestMethod()] + [Test] public void EffectSizeTest2() { // Example from http://wise.cgu.edu/powermod/computing.asp diff --git a/Unit Tests/Accord.Tests.Statistics/ToolsTest.cs b/Unit Tests/Accord.Tests.Statistics/ToolsTest.cs index 677ecbcb7..878181fa7 100644 --- a/Unit Tests/Accord.Tests.Statistics/ToolsTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/ToolsTest.cs @@ -24,15 +24,15 @@ namespace Accord.Tests.Statistics { using System.Linq; using Accord.Math; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; using Tools = Accord.Statistics.Tools; using Accord.Statistics; - [TestClass()] + [TestFixture] public class ToolsTest { - [TestMethod()] + [Test] public void CenteringTest() { @@ -76,7 +76,7 @@ public void CenteringTest() } - [TestMethod()] + [Test] public void MahalanobisTest() { double[] x = { 1, 0 }; @@ -103,7 +103,7 @@ public void MahalanobisTest() Assert.AreEqual(expected, actual, 0.0001); } - [TestMethod()] + [Test] public void SubgroupTest1() { Accord.Math.Tools.SetupGenerator(0); @@ -140,7 +140,7 @@ public void SubgroupTest1() } } - [TestMethod()] + [Test] public void StandardDeviationTest4() { double[][] matrix = @@ -159,7 +159,7 @@ public void StandardDeviationTest4() Assert.IsTrue(stdev2.IsEqual(stdev)); } - [TestMethod()] + [Test] public void StandardDeviationTest3() { double[,] matrix = @@ -178,7 +178,7 @@ public void StandardDeviationTest3() Assert.IsTrue(stdev2.IsEqual(stdev)); } - [TestMethod()] + [Test] public void StandardDeviationTest2() { double[] values = { -5, 0.2, 2 }; @@ -187,7 +187,7 @@ public void StandardDeviationTest2() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void WeightedVarianceTest1() { double[] original = { 5, 5, 1, 4, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 4, 3, 2, 3 }; @@ -202,7 +202,7 @@ public void WeightedVarianceTest1() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void WeightedVarianceTest3() { double[] weights = { 2, 1, 1, 1, 2, 3, 1, 3, 1, 1, 1, 1 }; @@ -214,7 +214,7 @@ public void WeightedVarianceTest3() Assert.AreEqual(1.3655172413793104, actual); } - [TestMethod()] + [Test] public void WeightedVarianceTest2() { double[] original = { 5, 5, 1, 4, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 4, 3, 2, 3 }; @@ -228,7 +228,7 @@ public void WeightedVarianceTest2() } - [TestMethod()] + [Test] public void MeanTest4() { double[,] matrix = @@ -246,7 +246,7 @@ public void MeanTest4() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void MeanTest3() { double[] values = { -5, 0.2, 2 }; @@ -255,7 +255,7 @@ public void MeanTest3() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void MeanTest() { double[,] matrix = @@ -272,7 +272,7 @@ public void MeanTest() } - [TestMethod()] + [Test] public void MedianTest1() { double[] values; @@ -290,7 +290,7 @@ public void MedianTest1() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void MedianTest2() { double[][] matrix = @@ -316,7 +316,7 @@ public void MedianTest2() Assert.IsTrue(median.IsEqual(2.0000, 7.0000, 2.5000, 0.2000)); } - [TestMethod()] + [Test] public void MedianTest() { double[,] matrix = @@ -342,7 +342,7 @@ public void MedianTest() Assert.IsTrue(median.IsEqual(2.0000, 7.0000, 2.5000, 0.2000)); } - [TestMethod()] + [Test] public void QuartileTest1() { double[] values = new double[] { 3, 4, 8 }; @@ -354,7 +354,7 @@ public void QuartileTest1() Assert.AreEqual(8, q3); } - [TestMethod()] + [Test] public void QuartileTest2() { double[] values = new double[] { 1, 3, 3, 4, 5, 6, 6, 7, 8, 8 }; @@ -366,7 +366,7 @@ public void QuartileTest2() Assert.AreEqual(7, q3); } - [TestMethod()] + [Test] public void QuartileTest3() { double[] values = new double[] { 102, 104, 105, 107, 108, 109, 110, 112, 115, 116, 118 }; @@ -378,7 +378,7 @@ public void QuartileTest3() Assert.AreEqual(115, q3); } - [TestMethod()] + [Test] public void QuartileTest4() { // This is equivalent to R's type 6. This is the @@ -402,7 +402,7 @@ public void QuartileTest4() Assert.AreEqual(0.28744808199999999, q3); } - [TestMethod()] + [Test] public void ModeTest1() { double[] values = { 3, 3, 1, 4 }; @@ -411,7 +411,7 @@ public void ModeTest1() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void ModeTest() { double[,] matrix = @@ -427,7 +427,7 @@ public void ModeTest() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void ModeTest2() { double[] values = { 0, 1, 1, 2 }; @@ -437,7 +437,7 @@ public void ModeTest2() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void ModeTest3() { double[] values = { 0, 1, 2, 2 }; @@ -447,7 +447,7 @@ public void ModeTest3() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void ModeTest_NonComparable() { object a = new object(); @@ -486,7 +486,7 @@ public void ModeTest_NonComparable() Assert.AreEqual(4, count); } - [TestMethod()] + [Test] public void WeightedModeTest_NonComparable() { object a = new object(); @@ -538,7 +538,7 @@ public void WeightedModeTest_NonComparable() Assert.AreEqual(c, actual); } - [TestMethod()] + [Test] public void ModeTest_Comparable() { int a = 1; @@ -577,7 +577,7 @@ public void ModeTest_Comparable() Assert.AreEqual(4, count); } - [TestMethod()] + [Test] public void WeightedModeTest1() { double[] values = { 0, 1, 1, 2 }; @@ -588,7 +588,7 @@ public void WeightedModeTest1() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void WeightedModeTest2() { double[] values = { 0, 1, 1, 2 }; @@ -599,7 +599,7 @@ public void WeightedModeTest2() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void WeightedCountsModeTest1() { double[] values = { 0, 1, 1, 2 }; @@ -610,7 +610,7 @@ public void WeightedCountsModeTest1() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void WeightedCountsModeTest2() { double[] values = { 0, 1, 1, 2 }; @@ -622,7 +622,7 @@ public void WeightedCountsModeTest2() } - [TestMethod()] + [Test] public void CovarianceTest() { double[,] matrix = new double[,] @@ -656,7 +656,7 @@ public void CovarianceTest() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.0001)); } - [TestMethod()] + [Test] public void CovarianceTest2() { double[][] matrix = new double[,] @@ -690,7 +690,7 @@ public void CovarianceTest2() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.0001)); } - [TestMethod()] + [Test] public void CovarianceTest3() { double[][] matrix = new double[,] @@ -721,7 +721,7 @@ public void CovarianceTest3() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.0001)); } - [TestMethod()] + [Test] public void CovarianceTest5() { double[][] matrix = new double[,] @@ -754,7 +754,7 @@ public void CovarianceTest5() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.0001)); } - [TestMethod()] + [Test] public void CovarianceTest6() { double[][] matrix = new double[,] @@ -786,7 +786,7 @@ public void CovarianceTest6() } - [TestMethod()] + [Test] public void CovarianceTest4() { double[] u = { -2, 1, 5 }; @@ -799,7 +799,7 @@ public void CovarianceTest4() Assert.AreEqual(expected, actual, 0.0001); } - [TestMethod()] + [Test] public void VarianceTest7() { double[][] matrix = new double[,] @@ -826,7 +826,7 @@ public void VarianceTest7() Assert.IsTrue(Matrix.IsEqual(expected, actual, 1e-10)); } - [TestMethod()] + [Test] public void VarianceTest8() { double[,] matrix = @@ -853,7 +853,7 @@ public void VarianceTest8() Assert.IsTrue(Matrix.IsEqual(expected, actual, 1e-10)); } - [TestMethod()] + [Test] public void CorrelationTest() { // http://www.solvemymath.com/online_math_calculator/statistics/descriptive/correlation.php @@ -885,7 +885,7 @@ public void CorrelationTest() - [TestMethod()] + [Test] public void ProportionsTest() { int[,] summary = @@ -909,7 +909,7 @@ public void ProportionsTest() Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.000000001)); } - [TestMethod()] + [Test] public void GroupTest() { @@ -941,7 +941,7 @@ public void GroupTest() Assert.IsTrue(Matrix.IsEqual(expected, actual)); } - [TestMethod()] + [Test] public void ExtendTest() { int[,] summary = @@ -976,7 +976,7 @@ public void ExtendTest() Assert.IsTrue(Matrix.IsEqual(expected, actual)); } - [TestMethod()] + [Test] public void ShuffleTest() { int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; @@ -989,7 +989,7 @@ public void ShuffleTest() - [TestMethod()] + [Test] public void ExtendTest2() { int[][] data = @@ -1024,7 +1024,7 @@ public void ExtendTest2() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void KurtosisTest() { double[] values = { 3.4, 7.1, 1.5, 8.6, 4.9 }; @@ -1033,7 +1033,7 @@ public void KurtosisTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void SkewnessTest() { double[] values = { 3.4, 7.1, 1.5, 8.6, 4.9 }; @@ -1042,7 +1042,7 @@ public void SkewnessTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void KurtosisTest2() { Accord.Math.Random.Generator.Seed = 0; @@ -1051,7 +1051,7 @@ public void KurtosisTest2() Assert.AreEqual(-1.1997826610738631, actual); } - [TestMethod()] + [Test] public void SkewnessTest2() { Accord.Math.Random.Generator.Seed = 0; @@ -1061,7 +1061,7 @@ public void SkewnessTest2() } - [TestMethod()] + [Test] public void WhiteningTest() { double[,] value = @@ -1088,7 +1088,7 @@ public void WhiteningTest() } - [TestMethod()] + [Test] public void PooledVarianceTest() { double[][] samples = @@ -1105,7 +1105,7 @@ public void PooledVarianceTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void PooledStandardDeviationTest() { double[][] samples = @@ -1122,7 +1122,7 @@ public void PooledStandardDeviationTest() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void EntropyTest() { { @@ -1154,7 +1154,7 @@ public void EntropyTest() } } - [TestMethod()] + [Test] public void RankTest1() { double[] values = { 2, 3, 4, 4, 5, 6, 8, 10, 10, 14, 16, 20, 32, 40 }; @@ -1165,7 +1165,7 @@ public void RankTest1() Assert.IsTrue(expected.IsEqual(actual)); } - [TestMethod()] + [Test] public void RankTest2() { double[] values = { 7, 1, 2, 1, 7, 8, 1, 1, 2, 0, 10, 27 }; @@ -1178,7 +1178,7 @@ public void RankTest2() Assert.IsTrue(copy.IsEqual(values)); } - [TestMethod()] + [Test] public void MatrixModeTest2() { int[][] matrix = @@ -1199,7 +1199,7 @@ public void MatrixModeTest2() Assert.AreEqual(expected[2], actual[2]); } - [TestMethod()] + [Test] public void MatrixModeTest3() { double[][] matrix = @@ -1220,7 +1220,7 @@ public void MatrixModeTest3() Assert.AreEqual(expected[2], actual[2]); } - [TestMethod()] + [Test] public void ModeTest4() { int[] values = { 2, 5, 1, 6, 4, 1, 2, 6, 2, 6, 8, 2, 6, 2, 2 }; @@ -1229,7 +1229,7 @@ public void ModeTest4() Assert.AreEqual(expected, actual); } - [TestMethod()] + [Test] public void KurtosisMatrixTest1() { double[,] matrix = @@ -1258,7 +1258,7 @@ public void KurtosisMatrixTest1() } } - [TestMethod()] + [Test] public void KurtosisMatrixTest2() { double[][] matrix = @@ -1287,7 +1287,7 @@ public void KurtosisMatrixTest2() } } - [TestMethod()] + [Test] public void SkewnessMatrixTest1() { double[,] matrix = @@ -1315,7 +1315,7 @@ public void SkewnessMatrixTest1() } } - [TestMethod()] + [Test] public void SkewnessMatrixTest() { double[][] matrix = diff --git a/Unit Tests/Accord.Tests.Statistics/Visualizations/HistogramTest.cs b/Unit Tests/Accord.Tests.Statistics/Visualizations/HistogramTest.cs index f7ba11d76..7aa7e7441 100644 --- a/Unit Tests/Accord.Tests.Statistics/Visualizations/HistogramTest.cs +++ b/Unit Tests/Accord.Tests.Statistics/Visualizations/HistogramTest.cs @@ -23,9 +23,9 @@ namespace Accord.Tests.Statistics { using Accord.Statistics.Visualizations; - using Microsoft.VisualStudio.TestTools.UnitTesting; + using NUnit.Framework; - [TestClass()] + [TestFixture] public class HistogramTest { @@ -45,7 +45,7 @@ public TestContext TestContext } - [TestMethod()] + [Test] public void HistogramConstructorTest() { Histogram target = new Histogram(); @@ -54,7 +54,7 @@ public void HistogramConstructorTest() Assert.AreEqual(0, target.Bins.Count); } - [TestMethod()] + [Test] public void ComputeTest1() { Histogram target = new Histogram(); @@ -75,7 +75,7 @@ public void ComputeTest1() } - [TestMethod()] + [Test] public void ComputeTest2() { Histogram target = new Histogram(); @@ -90,7 +90,7 @@ public void ComputeTest2() - [TestMethod()] + [Test] public void ComputeTest3() { Histogram target; @@ -161,7 +161,7 @@ public void ComputeTest3() Assert.AreEqual(values.Length, sum); } - [TestMethod()] + [Test] public void ComputeTest4() { Histogram target; @@ -231,7 +231,7 @@ public void ComputeTest4() Assert.AreEqual(values.Length, sum); } - [TestMethod()] + [Test] public void ComputeTest5() { Histogram target; @@ -307,7 +307,7 @@ public void ComputeTest5() Assert.AreEqual(values.Length, sum); } - [TestMethod()] + [Test] public void ComputeTest6() { Histogram target = new Histogram(); diff --git a/Unit Tests/Accord.Tests.Vision/Accord.Tests.Vision.csproj b/Unit Tests/Accord.Tests.Vision/Accord.Tests.Vision.csproj index 1dafc9672..c9722d030 100644 --- a/Unit Tests/Accord.Tests.Vision/Accord.Tests.Vision.csproj +++ b/Unit Tests/Accord.Tests.Vision/Accord.Tests.Vision.csproj @@ -4,7 +4,6 @@ {8046613E-799A-460C-985A-444C0327B49C} Accord.Tests.Vision Accord.Tests.Vision - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} Debug AnyCPU Library @@ -32,45 +31,24 @@ true full false - bin\Debug\ + $(SolutionDir)..\Unit Tests\bin\Debug\ DEBUG;TRACE - bin\Release\net35 + $(SolutionDir)..\Unit Tests\bin\Release\net35\ TRACE;NET35 - bin\Release\net40 + $(SolutionDir)..\Unit Tests\bin\Release\net40\ TRACE;NET40 - bin\Release\net45 + $(SolutionDir)..\Unit Tests\bin\Release\net45\ TRACE;NET45 - - False - ..\..\Externals\AForge.NET\AForge.dll - - - False - ..\..\Externals\AForge.NET\AForge.Imaging.dll - - - False - ..\..\Externals\AForge.NET\AForge.Math.dll - - - False - ..\..\Externals\AForge.NET\AForge.Neuro.dll - - - False - ..\..\Externals\AForge.NET\AForge.Video.dll - - - False - ..\..\Externals\AForge.NET\AForge.Vision.dll + + ..\..\Externals\NUnit\nunit.framework.dll @@ -82,9 +60,6 @@ 3.5 - - c:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll -